/* base — the neutral ground every framing and dial is written over.
 *
 * ⚠⚠ THIS FILE EXISTS BECAUSE THE OLD DEFAULT LAYER WAS BOARDWALK.
 * Every one of loupe.css's 135 `var()` fallbacks, and all five of loupe.js's
 * tok() defaults, carry boardwalk's values — --ground #07060a, --drift 54s,
 * settle 1250ms. That was invisible while each of the fifteen themes declared
 * every token it needed. It stops being invisible the moment treatments
 * compose: a dial that omits a value silently resolves to dark carnival, in
 * the middle of a gallery wall, and it reads as a rendering bug rather than a
 * missing default.
 *
 * ⚠⚠ AND IT MUST DECLARE EVERY TOKEN, not just the ones a dial might forget.
 * The dual `:root, .t-<name>` selector composes correctly only for tokens
 * EVERY theme declares. Tokens only *some* declare leak from :root to whoever
 * does not — measured 2026-08-30 on themes.html, where :root carries duplex's
 * --edge-color #ff2f6d and --edge-width 14px 0 0 0, and all fifteen previews
 * inherit them. It is latent today only because the picker renders no #edge.
 * Framing makes some files declare edge tokens and others not, which is
 * exactly the shape that turns that latent bug into a live one.
 *
 * The posture: proof grey, matted, still, grotesque — the neutral family,
 * whose whole design job is to SUBTRACT personality so the only colour on the
 * page is the work. A default that asserts nothing is the right default for a
 * product that shows other people's art.
 *
 * ⚠ --ground #666666 is exact and load-bearing upstream, not approximate:
 * it is recorded as the ground its hand-set lettering was drawn on in 2004,
 * baked into the pixels, so artwork composites on it with no halo. Mid-grey is
 * also the standard surround BECAUSE a neutral ground does not bias colour
 * perception — which is why photo software defaults to it. Do not tidy it.
 */

:root {
  /* ground and ink — proof grey */
  --ground:      #666666;
  --ink:         #f4f4f3;
  --ink-dim:     #e6e6e4;
  --ink-faint:   #c2c2c0;
  --scrim-rgb:   30 30 30;
  --scrim:       0.72;
  /* ⚠ The bottom scrim has TWO lobes and they do different jobs. The left one
     sits under the credit and exists so the title reads over whatever
     photograph is standing behind it. The right one sits under the RAIL — and
     a row of thumbnails already carries its own borders, backgrounds and
     shadow, so it is earning much less. This multiplier is how a ground turns
     the right lobe down; see the light grounds in dials.css. */
  --scrim-rail:  1;
  /* the credit lobe's ellipse. Big enough to carry the title across a
     photograph on a bleed; a ground that does not need that much may shrink
     it — see .g-paper in dials.css. */
  --scrim-size:  40% 52%;
  /* ⚠⚠ THESE PERCENTAGES RESOLVE AGAINST #shade, WHICH IS 46vh TALL — not
     against the viewport. So `52%` is 52% of 46vh (about 24vh), and `94%` puts
     the centre at 97% of the VIEWPORT height, below the credit rather than on
     it. That mismatch made every attempt to tune this behave unpredictably.
     A ground that wants predictable geometry should override both of these in
     vw/vh, which resolve against the viewport and mean what they say — see
     .g-paper in dials.css. */
  --scrim-at:    4% 94%;
  /* ⚠ The MARK's own scrim, top right. #shade is anchored to the bottom and is
     46vh tall, so it cannot reach the corner the mark sits in — this one
     belongs to #home itself and travels with it.
     ⚠ ON EVERYWHERE, dark grounds included — owner's call 2026-08-31. It was
     briefly off by default to keep boardwalk untouched; that is no longer the
     intent. ⚠⚠ SO THIS DOES CHANGE THE SHOWCASE: boardwalk carries no ground
     class and therefore takes its value from here.
     ⚠ It scales with --scrim, so each ground gets a lobe in its own direction —
     darkening under the word on a dark ground, lifting it on a light one. */
  --scrim-mark:  1;
  /* ⚠ How fast the credit lobe dies away, as its alpha at the HALFWAY point.
     0.5 is exactly what a plain two-stop ramp does, so this default changes
     nothing — a gradient from A to transparent is already A/2 at 50%, and the
     stop is written as a plain multiple of A so that identity holds. Lower it
     to concentrate the lift near the text instead of spreading it. That matters
     because a two-stop lobe is still lifting at half strength halfway out,
     which is what makes a small ellipse wash a large area. */
  --scrim-falloff: 0.5;
  --chrome-shadow: none;          /* matted: chrome sits on the ground, no halo */
  --chrome-halo:   0 1px 14px rgba(0, 0, 0, 0.9);
  /* ⚠ --chrome-halo is the halo a ground WOULD need; --chrome-shadow is whether
     it gets one. Framing decides (bleed puts chrome on the photograph), the
     ground supplies a halo that suits its ink. Found by comparison: composed
     bleed had --chrome-shadow: none and its credit line dissolved into the
     bright half of the picture. */

  /* type — grotesque. One pairing, deliberately: the sibling product' three Advanced
     themes share one on purpose — same catalogue typography, different wall —
     and a grotesque is what museum labelling actually uses. */
  --font-display:   'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-label:     'IBM Plex Mono', ui-monospace, monospace;
  --title-size:     13px;
  --title-tracking: 0.2em;
  --title-case:     uppercase;
  --label-size:     10px;
  --label-tracking: 0.12em;
  --label-case:     none;
  --sub-size:       10px;

  /* framing — matted. --plate-inset is unitless, in vmin, so a miniature
     reproduces the mat without knowing the viewport. */
  --plate-base:  100vmin;
  --plate-inset: 8;
  --plate-fit:   contain;

  /* the edge — declared at nothing, so no framing can inherit another's.
     This is the leak fix; do not delete these three for being empty. */
  --edge-color: transparent;
  --edge-width: 0;
  --edge-inset: 0;

  /* duotone the rail — off, but declared, so the axis can be compared */
  --rail-duotone: 0;
  --duo-dark:     #1e1e1e;
  --duo-light:    #f4f4f3;
  --duo-contrast: 1.1;

  /* the rail */
  --thumb-size:    72px;
  --thumb-size-sm: 52px;
  --thumb-gap:     12px;
  --thumb-gap-sm:  9px;
  --thumb-radius:  0px;
  --thumb-border:  1px solid rgba(244, 244, 243, 0.28);
  --thumb-bg:      #5c5c5c;
  --thumb-shadow:  none;
  --thumb-shadow-hover: none;
  --thumb-filter:       saturate(0.92);
  --thumb-filter-hover: saturate(1);
  --thumb-hover-scale:  1.02;
  --accent:      #f0d9a8;
  --accent-glow: rgba(240, 217, 168, 0.22);
  --n-ink:       rgba(244, 244, 243, 0.85);

  /* ⚠ --accent measures 4.15:1 on this ground — under the 4.5 floor, so it is
     for LARGE text only, never body copy. Measured upstream, not assumed. */

  /* environment */
  --grain:       0;
  --grain-blend: multiply;

  /* the enlargement — matted, because the ground is a considered colour.
     ⚠ Matting only pays when it is. On near-black it reads as letterboxing,
     which is why the dark grounds below bleed instead. */
  --lit-ground:     #5e5e5e;
  --mount-pad:      22px;
  --mount-bg:       #5c5c5c;
  --mount-border:   1px solid rgba(244, 244, 243, 0.3);
  --enlarge-shadow: none;
  --enlarge-max-w:  82vw;
  --enlarge-max-h:  82vh;
  /* how far the plate left standing steps back once the row is released —
     the room rather than the subject */
  --rest: 0.26;
  --stage-lit-opacity:  0.08;
  --stage-lit-saturate: 0.6;

  /* motion — still. Not zero: the page still assembles, it just does not
     perform. Every value here is overridden wholesale by a motion dial. */
  --burst:       900ms;
  --grow:        600ms;
  --grow-ease:   cubic-bezier(0.3, 0.7, 0.3, 1);
  --settle:      500ms;
  --settle-ease: cubic-bezier(0.3, 0.7, 0.3, 1);
  --stagger:     40ms;
  --fade:        400ms;
  --plate-start-scale: 0.96;
  --plate-exit-scale:  1.01;
  --thumb-start-scale: 0.96;
  --scatter-radius: 0px;
  --scatter-spread: 0deg;
  --thumb-tilt:     0deg;
  --drift:       120s;
  --drift-scale: 1;

  /* the contact sheet and section grids */
  --cell-size:     152px;
  --cell-gap:      14px;
  --grid-stagger:  40ms;
  --backdrop:      0.15;

  /* chrome insets */
  --rail-inset-x:   max(5vw, 44px);
  --rail-inset-y:   max(5vh, 36px);
  --credit-inset-x: max(5vw, 44px);
  --credit-inset-y: max(5vh, 38px);
}
