/* ==========================================================================
   LH BARBERSHOP — THE FRAME
   One fixed layer that darkens the four edges of the window so the gutters,
   the header bar and the footer recede and the centre column reads as the
   thing being looked at.

   Loaded after system.css and menu.css. It introduces no colour, no spacing
   step and no duration the design system does not already define: the ink is
   --ink, the reach is expressed in the same clamp() idiom every other
   viewport-scaled value uses, and it animates nothing.

   THREE RULES, and the whole file is their consequences.

   1. IT IS FELT, NOT SEEN. Peak alpha sits under 16% at the very edge and
      every band falls off on an ease, so there is no line anywhere at which
      it begins. The moment you can point at where it starts it has stopped
      being a vignette and become a border.

   2. IT IS A CHILD OF .viewport, NOT OF <body>. The menu does not rise over
      the page; the page scales into the bottom-right corner to reveal it
      (menu.css § 1). A body-level frame would stay window-sized while the
      page shrank to half, and would tint the menu panel besides. As a direct
      child it is fixed to the window while the menu is shut and contained by
      .viewport's transform the moment it is frozen — so it recedes WITH the
      page, exactly as the grid rules and the book pill already do.

   3. IT IS ABOVE EVERY GROUND, BELOW THE CHROME. z-index 50 inside
      .viewport: above the last opaque section surface, below the header
      (z 60, a sibling of .viewport) and the menu trigger, which stay on top
      of the frame rather than under it.
   ========================================================================== */

.frame{
  /* HOW FAR EACH BAND REACHES IN. The foot is deepest, the sides shallowest.
     A page is read down its centre: crowding the long edges is felt much
     sooner than crowding the short ones, and the sides already have the
     gutter doing this job in hairlines. */
  --vig-side:clamp(40px,10vw,190px);
  --vig-top:clamp(56px,11vh,190px);
  --vig-bottom:clamp(72px,16vh,260px);

  /* PEAK ALPHA AT THE OUTERMOST PIXEL of each band. The sides carry least:
     they overlap nothing, so pushing them to parity with the top and foot
     resolves into a rectangle drawn around the content. */
  --vig-ink:var(--ink);
  --vig-a-side:11%;
  --vig-a-top:13%;
  --vig-a-bottom:16%;

  position:fixed;inset:0;z-index:50;
  pointer-events:none;user-select:none;
}

/* --- 1. The four bands ---------------------------------------------------
   FOUR LINEAR GRADIENTS, NOT ONE RADIAL. A radial vignette pinches the
   corners of a wide window and leaves the middle of the long edges untouched,
   which is backwards for a page that is tall and narrow. Four edge-anchored
   bands darken every edge evenly and cross-fade into deeper corners for free.

   EACH BAND DECAYS OVER SIX STOPS approximating an ease-out: fast for the
   first fifth, then a long tail that spends its last 30% under 3% alpha. The
   tail is the whole trick. A three-stop gradient terminates on a straight
   line, and at this depth the eye reads that termination as a faint rectangle
   — rule 1 broken. Stretching the last stops past the point of visibility is
   what keeps the inner edge from ever resolving.
   -------------------------------------------------------------------------- */
.frame::before{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(to bottom,
      color-mix(in srgb,var(--vig-ink) var(--vig-a-top),transparent) 0,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-top) * .56),transparent) 20%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-top) * .28),transparent) 42%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-top) * .11),transparent) 64%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-top) * .03),transparent) 84%,
      transparent 100%),
    linear-gradient(to top,
      color-mix(in srgb,var(--vig-ink) var(--vig-a-bottom),transparent) 0,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-bottom) * .56),transparent) 20%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-bottom) * .28),transparent) 42%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-bottom) * .11),transparent) 64%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-bottom) * .03),transparent) 84%,
      transparent 100%),
    linear-gradient(to right,
      color-mix(in srgb,var(--vig-ink) var(--vig-a-side),transparent) 0,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .56),transparent) 20%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .28),transparent) 42%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .11),transparent) 64%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .03),transparent) 84%,
      transparent 100%),
    linear-gradient(to left,
      color-mix(in srgb,var(--vig-ink) var(--vig-a-side),transparent) 0,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .56),transparent) 20%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .28),transparent) 42%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .11),transparent) 64%,
      color-mix(in srgb,var(--vig-ink) calc(var(--vig-a-side) * .03),transparent) 84%,
      transparent 100%);
  background-repeat:no-repeat;
  background-size:
    100% var(--vig-top),
    100% var(--vig-bottom),
    var(--vig-side) 100%,
    var(--vig-side) 100%;
  background-position:top left,bottom left,left top,right top;
}

/* --- 2. The grain --------------------------------------------------------
   WHAT KEEPS IT FROM BANDING. An 8-bit gradient spread across a 190px falloff
   posterises into visible stripes on a wide screen — paper is the worst case,
   because the steps land in the region the eye resolves best. A 160px fractal
   noise tile at low amplitude dithers them away.

   It is masked to the same four bands as the gradient, so the centre of the
   page stays completely clean: this site paints photographs at full
   resolution and a global grain would sit on them as dirt.

   NO BLEND MODE. The obvious move is mix-blend-mode:overlay, which lets the
   noise lift as well as darken within the band and reads more like film. It
   also promotes this layer into a blend group over the whole window, and the
   window is where the cuts rail pins and the process scroll scrubs. The
   texture is not worth a composite on every frame of those. Plain alpha at
   low opacity breaks the banding, which is the job it was brought in to do.
   -------------------------------------------------------------------------- */
.frame::after{
  content:"";position:absolute;inset:0;
  opacity:.22;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
  /* Mask layers composite additively, so the four bands union into a single
     region open on all four edges with the centre fully masked out. */
  -webkit-mask-image:
    linear-gradient(to bottom,#000 0,transparent 100%),
    linear-gradient(to top,#000 0,transparent 100%),
    linear-gradient(to right,#000 0,transparent 100%),
    linear-gradient(to left,#000 0,transparent 100%);
  mask-image:
    linear-gradient(to bottom,#000 0,transparent 100%),
    linear-gradient(to top,#000 0,transparent 100%),
    linear-gradient(to right,#000 0,transparent 100%),
    linear-gradient(to left,#000 0,transparent 100%);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-size:
    100% var(--vig-top),
    100% var(--vig-bottom),
    var(--vig-side) 100%,
    var(--vig-side) 100%;
  mask-size:
    100% var(--vig-top),
    100% var(--vig-bottom),
    var(--vig-side) 100%,
    var(--vig-side) 100%;
  -webkit-mask-position:top left,bottom left,left top,right top;
  mask-position:top left,bottom left,left top,right top;
}

/* --- 3. The hand -----------------------------------------------------------
   A phone has no gutter to speak of and a much shorter measure: at 10vw the
   side bands reach into the text column itself. They close down to a hairline
   of shade and the vertical bands carry the whole effect. This is the same
   breakpoint the grid drops to two columns on (system.css § 3). */
@media (max-width:900px){
  .frame{
    --vig-side:22px;
    --vig-a-side:7%;
    --vig-top:clamp(44px,8vh,110px);
    --vig-bottom:clamp(56px,11vh,150px);
  }
}

/* --- 4. Forced colours -----------------------------------------------------
   A decorative tint is noise at best and a legibility hazard at worst when
   the reader has asked the OS for a specific palette. */
@media (forced-colors:active){
  .frame{display:none}
}
