/* dials — axis two.
 *
 * ⚠⚠ LOAD ORDER MATTERS: this file must be linked BEFORE framings.css.
 * Class selectors all carry the same specificity, so on a token both a ground
 * and a framing set, whichever is defined LAST wins. Framing is the structural
 * decision and has to win — otherwise a ground paints a mat onto a full-bleed
 * plate. Each token has exactly one owner: geometry and the mat belong to
 * framing, colour belongs to ground. Any of these may be worn by any framing, and any layout
 * family. Plain classes for the same reason framings.css uses them: they must
 * compose on an element, not fight over :root.
 *
 * ground · motion · type here. `label` is built too (works.js renders it);
 * it is a class and a manifest value rather than tokens, so it has no block.
 *
 * ⚠ 2026-09-02 — the ground axis grew by two (cloth, bench) and the type axis
 * by four register pairings plus one alternate face, all from grounds.html.
 * The study's token values are TAKEN, not re-derived; where the engine needs a
 * token the study did not carry (a scrim colour, a thumb border) it is the
 * study's ink at the alpha the neighbouring ground uses.
 */

/* ─── ground ──────────────────────────────────────────────────────────────
 * Taken wholesale from the neutral family, and the reasoning travels with
 * it because the principle is not taste: a gallery wall, a neutral mid-grey
 * and a darkroom are the three surrounds people actually judge images against.
 * Mid-grey is the standard BECAUSE a neutral surround does not bias colour
 * perception. `paper` is loupe's own fourth, for work that wants warmth.
 * ⚠ The dark grounds want .f-bleed. Matting on near-black reads as
 * letterboxing — the finding in ARCHITECTURE.md §2.5.
 */
.g-wall {
  /* ⚠⚠ THE PLATE BARELY STEPS BACK ON A LIGHT GROUND, and it cannot. --rest
     expresses "the room rather than the subject" by fading the plate toward the
     ground — which works on near-black, where fading means receding, and
     destroys the picture on museum white, where fading means washing out. At
     base's 0.26 this ground composites a dark photograph to about 185/255:
     not a room behind the row, a milky veil over the whole page.
     ⚠ The consequence, stated plainly: on these grounds the step-back is
     essentially retired. If the GESTURE is wanted back it needs a different
     expression — saturation or scale, the way the enlargement's stage already
     uses --stage-lit-saturate — not a smaller number here.
     ⚠⚠ 1, NOT 0.92. Anything below 1 is a veil over EVERY PIXEL of the
     photograph, not a local effect — at 0.92 the whole image was lifted 8%
     toward the paper white, which reads as a page-wide wash no amount of
     tuning the corner lobes can remove. The only things allowed to touch this
     photograph's opacity are the two scrims, and only where they sit.
     Owner's call 2026-08-31. Dark and grey grounds keep base's 0.26, so
     boardwalk and the showcase are untouched. */
  --rest: 1;
  /* ⚠ NO RAIL LOBE. On a light ground the scrim is LIGHT — it lifts rather
     than darkens, because the ink here is dark — so the lobe under the rail
     reads as a bright blob on the photograph instead of disappearing into it
     the way a dark scrim does on a dark ground. It was supplying nothing the
     thumbnails' own borders do not already supply. The credit's lobe stays:
     that one is what makes the title readable, which is the whole purpose.
     Owner's call 2026-08-31, seen on riso. */
  --scrim-rail: 0;
  --chrome-halo: 0 1px 14px rgba(243, 243, 241, 0.92);                                    /* museum white and hairlines */
  --ground: #f3f3f1; --ink: #191a1b; --ink-dim: #54575b; --ink-faint: #7c7f83;
  --accent: #3e4a56; --accent-glow: rgba(62, 74, 86, 0.18);
  --scrim-rgb: 25 26 27; --scrim: 0.74;
  --lit-ground: #edede9; --mount-bg: #fbfbf9; --thumb-bg: #ffffff;
  --thumb-border: 1px solid rgba(25, 26, 27, 0.22);
  --edge-color: rgba(25, 26, 27, 0.4);
  --n-ink: rgba(25, 26, 27, 0.8); --duo-dark: #191a1b; --duo-light: #fbfbf9;
}
.g-grey {
  --chrome-halo: 0 1px 14px rgba(30, 30, 30, 0.9);                     /* ⚠ #666666 exactly — see base.css, load-bearing */
  --ground: #666666; --ink: #f4f4f3; --ink-dim: #e6e6e4; --ink-faint: #c2c2c0;
  --accent: #f0d9a8; --accent-glow: rgba(240, 217, 168, 0.22);
  --scrim-rgb: 30 30 30; --scrim: 0.72;
  --lit-ground: #5e5e5e; --mount-bg: #5c5c5c; --thumb-bg: #5c5c5c;
  --thumb-border: 1px solid rgba(244, 244, 243, 0.28);
  --edge-color: rgba(244, 244, 243, 0.5);
  --n-ink: rgba(244, 244, 243, 0.85); --duo-dark: #1e1e1e; --duo-light: #f4f4f3;
}
.g-dark {
  --chrome-halo: 0 1px 14px rgba(0, 0, 0, 0.9);                    /* neutral charcoal, never blue-black, one amber */
  --ground: #171717; --ink: #ececea; --ink-dim: #a9a9a6; --ink-faint: #6e6e6c;
  --accent: #c6a36a; --accent-glow: rgba(198, 163, 106, 0.28);
  --scrim-rgb: 10 10 10; --scrim: 0.7;
  --lit-ground: #121212; --mount-bg: #1c1c1c; --thumb-bg: #1c1c1c;
  --thumb-border: 1px solid rgba(236, 236, 234, 0.18);
  --edge-color: rgba(236, 236, 234, 0.35);
  --n-ink: rgba(236, 236, 234, 0.85); --duo-dark: #0f0f0f; --duo-light: #ececea;
}
.g-paper {
  /* ⚠⚠ THE PLATE BARELY STEPS BACK ON A LIGHT GROUND, and it cannot. --rest
     expresses "the room rather than the subject" by fading the plate toward the
     ground — which works on near-black, where fading means receding, and
     destroys the picture on museum white, where fading means washing out. At
     base's 0.26 this ground composites a dark photograph to about 185/255:
     not a room behind the row, a milky veil over the whole page.
     ⚠ The consequence, stated plainly: on these grounds the step-back is
     essentially retired. If the GESTURE is wanted back it needs a different
     expression — saturation or scale, the way the enlargement's stage already
     uses --stage-lit-saturate — not a smaller number here.
     ⚠⚠ 1, NOT 0.92. Anything below 1 is a veil over EVERY PIXEL of the
     photograph, not a local effect — at 0.92 the whole image was lifted 8%
     toward the paper white, which reads as a page-wide wash no amount of
     tuning the corner lobes can remove. The only things allowed to touch this
     photograph's opacity are the two scrims, and only where they sit.
     Owner's call 2026-08-31. Dark and grey grounds keep base's 0.26, so
     boardwalk and the showcase are untouched. */
  --rest: 1;
  /* ⚠ NO RAIL LOBE. On a light ground the scrim is LIGHT — it lifts rather
     than darkens, because the ink here is dark — so the lobe under the rail
     reads as a bright blob on the photograph instead of disappearing into it
     the way a dark scrim does on a dark ground. It was supplying nothing the
     thumbnails' own borders do not already supply. The credit's lobe stays:
     that one is what makes the title readable, which is the whole purpose.
     Owner's call 2026-08-31, seen on riso. */
  --scrim-rail: 0;
  --chrome-halo: 0 1px 14px rgba(239, 236, 228, 0.92);                                 /* warm stock, ink rather than light */
  --ground: #efece4; --ink: #1b1917; --ink-dim: #4a4640; --ink-faint: #7d776e;
  --accent: #7c5434; --accent-glow: rgba(124, 84, 52, 0.2);
  /* ⚠ A SMALLER, SOFTER CREDIT LOBE than base's 40% 52% at 0.7. This is the
     only light ground worn by a BLEED preset (riso), so it is the only one
     whose lobe lies across the photograph rather than on a mat — and a light
     scrim there lifts the picture wherever it reaches. Shrinking the ellipse
     and easing the alpha keeps it doing its one job, making the title
     readable, without bleaching a corner of the frame to do it.
     Owner's call 2026-08-31, on riso.
     ⚠⚠ ANCHORED AT THE BOTTOM-LEFT CORNER, and sized in vw/vh so it means what
     it says. `at 0% 100%` is the corner of #shade, whose bottom and left edges
     ARE the viewport's — so the lobe is a quarter ellipse growing out of the
     corner the credit sits in, 31vw across and 30vh up. Drawn to an outline the
     owner marked on a screenshot, 2026-08-31.
     ⚠ Percentages for the SIZE would have been a trap: #shade is 46vh tall, so
     base's `52%` is 24vh, and its `at 4% 94%` puts the centre at 97% of the
     VIEWPORT — below the credit text at 90.5%-96%, lighting the strip beneath
     it rather than the text. That mismatch is why tuning this by percentage
     kept producing shapes nobody predicted. vh and vw resolve against the
     viewport; percentages resolve against the box.
     ⚠⚠ A FAST FALLOFF WAS TRIED HERE AND REVERTED. --scrim-falloff at 0.22
     concentrated the lift beautifully at the lobe's centre and dropped the
     contrast at the credit's RIGHT-HAND end to 1.5:1 — dark ink on a dark
     photograph, effectively unreadable. The radial is centred on the corner and
     the text runs away from it, so any faster decay starves the end of the line
     first. Keep it linear; shorten the ellipse instead.
     ⚠⚠ MEASURE AT THE TEXT, NOT AT THE LOBE'S CENTRE. The centre reads about
     5.6:1 and that number is meaningless, because nothing is drawn there. What
     matters is the far end of the credit line, where the ink runs out of lift.
     Measured at the actual #plate-text box: 5.1:1 at the title's left, 2.7:1 at
     its right, 2.7:1 at the sub-line's right.
     ⚠⚠ SO THE RIGHT-HAND END OF THE CREDIT IS UNDER 4.5:1 AND ALWAYS HAS BEEN —
     it measured about 3.0:1 before any of this session's changes. This shape is
     not the cause and cannot be the cure: a radial centred on the corner starves
     the end of a horizontal line of text no matter how it is tuned. Fixing it
     properly means a different SHAPE — a linear gradient up from the bottom
     edge, or a scrim that follows the text box — not another number here.
     ⚠ ledgerlines and salon share this ground and are MATTED, so their lobe
     sits on the mat, where it was never load-bearing anyway. */
  --scrim-size: 31vw 30vh;
  --scrim-at:   0% 100%;
  --scrim-rgb: 243 241 235; --scrim: 0.64;
  --lit-ground: #e9e6de; --mount-bg: #fbfaf6; --thumb-bg: #f6f4ee;
  --thumb-border: 1px solid rgba(27, 25, 23, 0.24);
  --edge-color: rgba(27, 25, 23, 0.4);
  --n-ink: rgba(27, 25, 23, 0.78); --duo-dark: #2b2721; --duo-light: #f3f0e8;
}

/* ⚠ THE TWO GROUNDS FROM THE STUDY — grounds.html, 2026-09-02. The study's
 * `wall` and `paper` are near enough the two light grounds above that they
 * refine them per preset (presets.css → .p-wall, .p-paper) rather than
 * becoming a fifth and sixth light ground; `cloth` and `bench` are grounds
 * the engine did not have. Values are the study's `[data-reg]` blocks:
 * --g → --ground, --g-ink → --ink, --g-soft → --ink-faint, --mat → the mount,
 * the register's spot colour → --accent. */

/* cloth — undyed linen. Warm, and disciplined: the trap is faux-rustic, and
 * the restraint is what lets the object's own warmth read. A LIGHT ground, so
 * it takes the light grounds' two rules — the plate does not step back, and
 * there is no rail lobe — for the reasons written on .g-wall above. */
.g-cloth {
  --rest: 1;
  --scrim-rail: 0;
  --chrome-halo: 0 1px 14px rgba(232, 224, 208, 0.92);
  --ground: #e8e0d0; --ink: #2a241b; --ink-dim: #55493b; --ink-faint: #7a6f5f;
  --accent: #9c4a38; --accent-glow: rgba(156, 74, 56, 0.2);       /* madder */
  --scrim-size: 31vw 30vh;
  --scrim-at:   0% 100%;
  --scrim-rgb: 236 229 216; --scrim: 0.64;
  --lit-ground: #e1d8c6; --mount-bg: #f1ebdf; --thumb-bg: #efe8da;
  --thumb-border: 1px solid rgba(42, 36, 27, 0.22);
  --edge-color: rgba(42, 36, 27, 0.4);
  --n-ink: rgba(42, 36, 27, 0.8); --duo-dark: #2a241b; --duo-light: #f1ebdf;
}

/* kraft — brown paper. Owner's call 2026-09-10, for works on paper: the ground
 * a print is wrapped in and posted in, rather than the cream it is pulled on.
 * `paper` is already cream laid stock, so this is the browner, coarser end of
 * the same shelf and not a second version of it.
 * ⚠ #c8ab84 is MUCH darker than cloth's #e8e0d0, and that is what makes it its
 * own ground rather than a tint: cloth's ink-dim measures 4.00 here and its
 * ink-faint 2.25, which fails outright. Every step below was measured against
 * this ground rather than carried over — see check-contrast.js.
 *   --ink       #241d14   7.63   passes small text
 *   --ink-dim   #453b2d   5.02   passes small text
 *   --ink-faint #5a4e3e   3.71   passes large / UI, which is all it carries
 *   --accent    #7a2f20   4.26   a deeper madder; cloth's #9c4a38 is 2.79 here
 * ⚠ A LIGHT ground, so it keeps cloth's posture — `--rest: 1`, no rail lobe —
 * rather than .g-dark's. */
.g-kraft {
  --rest: 1;
  --scrim-rail: 0;
  --chrome-halo: 0 1px 14px rgba(200, 171, 132, 0.92);
  --ground: #c8ab84; --ink: #241d14; --ink-dim: #453b2d; --ink-faint: #5a4e3e;
  --accent: #7a2f20; --accent-glow: rgba(122, 47, 32, 0.22);       /* deep madder */
  --scrim-size: 31vw 30vh;
  --scrim-at:   0% 100%;
  --scrim-rgb: 206 180 144; --scrim: 0.62;
  --lit-ground: #bfa079; --mount-bg: #d7bd99; --thumb-bg: #d2b590;
  --thumb-border: 1px solid rgba(36, 29, 20, 0.26);
  --edge-color: rgba(36, 29, 20, 0.42);
  --n-ink: rgba(36, 29, 20, 0.8); --duo-dark: #241d14; --duo-light: #e3cead;
}

/* bench — walnut-dark. Weight, and site: built work wants structure, not
 * air. A DARK ground, so it keeps base's --rest and the rail lobe, like
 * .g-dark; the cells sit in the study's #1d1a17. Captions in oxide. */
.g-bench {
  --chrome-halo: 0 1px 14px rgba(20, 17, 14, 0.9);
  --ground: #2b2723; --ink: #e9e1d3; --ink-dim: #c4b8a8; --ink-faint: #a1958a;
  --accent: #c2694a; --accent-glow: rgba(194, 105, 74, 0.28);      /* oxide */
  --scrim-rgb: 20 17 14; --scrim: 0.7;
  --lit-ground: #221e1b; --mount-bg: #1d1a17; --thumb-bg: #1d1a17;
  --thumb-border: 1px solid rgba(233, 225, 211, 0.16);
  --edge-color: rgba(233, 225, 211, 0.35);
  --n-ink: rgba(233, 225, 211, 0.85); --duo-dark: #1d1a17; --duo-light: #e9e1d3;
}

/* ─── motion ──────────────────────────────────────────────────────────────
 * ⚠⚠ MEASURED CORRECTION TO TEMPLATES.md. That document says "13 --settle
 * values collapse to three". They do not. Sorted by --settle the fifteen do
 * not cluster at all: gesso (1700ms) sits beside cyanotype (800ms), and riso
 * (600ms) beside boardwalk (1250ms).
 *
 * What DOES cluster, cleanly and monotonically, is how far things travel and
 * how much they rotate — --scatter-radius with --thumb-tilt and the start
 * scales:
 *     12–47px, 0deg   still       cyanotype graphite gesso blueprint
 *                                 plaster daguerre autochrome obsidian
 *     58–77px, 8–15deg restrained slate safelight newsprint
 *     88–114px, 18–34deg generous midway boardwalk duplex riso
 *
 * ⚠ So motion is TRAVEL, and duration is a second, near-independent axis —
 * tempo. riso is fast AND generous; gesso is slow and still. Each position
 * below sets a tempo that suits its travel, but the two are separable and a
 * preset may override tempo alone. Worth a fourth dial if anyone asks for one.
 */
.m-still {
  --scatter-radius: 24px; --scatter-spread: 56deg; --thumb-tilt: 0deg;
  --thumb-start-scale: 0.9; --plate-start-scale: 0.86; --plate-exit-scale: 1.04;
  --settle: 900ms; --settle-ease: cubic-bezier(0.3, 0.75, 0.28, 1);
  --grow: 1200ms; --grow-ease: cubic-bezier(0.3, 0.7, 0.25, 1);
  --burst: 2000ms; --stagger: 80ms; --fade: 700ms; --grid-stagger: 45ms;
}
.m-restrained {
  --scatter-radius: 64px; --scatter-spread: 100deg; --thumb-tilt: 10deg;
  --thumb-start-scale: 0.68; --plate-start-scale: 0.4; --plate-exit-scale: 1.08;
  --settle: 1300ms; --settle-ease: cubic-bezier(0.2, 0.85, 0.25, 1);
  --grow: 1600ms; --grow-ease: cubic-bezier(0.22, 0.72, 0.22, 1);
  --burst: 2400ms; --stagger: 130ms; --fade: 900ms; --grid-stagger: 70ms;
}
.m-generous {
  /* ⚠⚠ These are boardwalk's own values, not round numbers. Owner's call
     2026-08-30: boardwalk is the showcase gallery, so it DEFINES this position
     rather than approximating it. Changing them changes the showcase. */
  --scatter-radius: 96px; --scatter-spread: 136deg; --thumb-tilt: 23deg;
  --thumb-start-scale: 0.42; --plate-start-scale: 0.13; --plate-exit-scale: 1.16;
  --settle: 1250ms; --settle-ease: cubic-bezier(0.16, 0.9, 0.22, 1);
  --grow: 1500ms; --grow-ease: cubic-bezier(0.14, 0.76, 0.18, 1);
  --burst: 2000ms; --stagger: 130ms; --fade: 700ms;
  /* boardwalk declares no --grid-stagger; its effective value is loupe.js`s
     tok() default of 60, so that is what this position inherits. */
  --grid-stagger: 60ms;
  --drift: 54s;
}

/* ─── type ────────────────────────────────────────────────────────────────
 * Three pairings, not ten. ⚠ the neutral family's three themes share ONE pairing
 * on purpose — same catalogue typography, different wall — and a grotesque is
 * what museum labelling uses. Keep this axis small; it is the one most likely
 * to be grown for no reason. Fonts are declared here but @import belongs on
 * the page, so a gallery fetches only the face it uses.
 */
.ty-grotesque {
  --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;
}
.ty-serif {
  --font-display: 'EB Garamond', Garamond, Georgia, serif;
  --font-label:   'EB Garamond', Garamond, Georgia, serif;
  --title-size: 22px; --title-tracking: 0.1em;  --title-case: none;
  --label-size: 13px; --label-tracking: 0.08em; --label-case: none;
  --sub-size: 12px;
}
.ty-mono {
  --font-display: 'IBM Plex Mono', ui-monospace, monospace;
  --font-label:   'IBM Plex Mono', ui-monospace, monospace;
  --title-size: 12px; --title-tracking: 0.34em; --title-case: lowercase;
  --label-size: 11px; --label-tracking: 0.2em;  --label-case: lowercase;
  --sub-size: 10px;
}

/* ⚠ FOUR MORE, NAMED AFTER THE REGISTERS — grounds.html, 2026-09-02. The
 * note above says keep this axis small, and it still holds: a register is a
 * pairing PLUS a ground PLUS a framing, and naming a position after one keeps
 * the axis meaningful rather than merely larger. Each is the free pairing the
 * study shipped; the display face carries the title and the label face the
 * small lines, which is the study's --fd / --fl. Sizes are the study's
 * gallery-title sizes brought down to the credit line's scale. The engine's
 * tokens carry no weight, so a face that needs one (Big Shoulders at 700)
 * asks for it in LOUPE_FONTS and gets it as the face's only weight loaded. */

/* the wall — a light grotesque for the chrome, a book serif for the lines. */
.ty-wall {
  --font-display: 'Hanken Grotesk', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-label:   'Crimson Pro', Georgia, serif;
  --title-size: 18px; --title-tracking: 0;      --title-case: none;
  --label-size: 12px; --label-tracking: 0.02em; --label-case: none;
  --sub-size: 12px;
}
/* the cloth — a Venetian serif with a real italic, a humanist sans below. */
.ty-cloth {
  --font-display: 'Fraunces', Georgia, serif;
  --font-label:   'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --title-size: 22px; --title-tracking: 0;      --title-case: none;
  --label-size: 11px; --label-tracking: 0.01em; --label-case: none;
  --sub-size: 11px;
}
/* the bench — wood type, set condensed and in caps like a stamped plate. */
.ty-bench {
  --font-display: 'Big Shoulders Display', 'Arial Narrow', Impact, sans-serif;
  --font-label:   'Barlow Condensed', 'Arial Narrow', Arial, sans-serif;
  --title-size: 26px; --title-tracking: 0.01em; --title-case: uppercase;
  --label-size: 11px; --label-tracking: 0.08em; --label-case: uppercase;
  --sub-size: 11px;
}
/* ⚠ the bench's ONE alternate — the same pairing with Anton for the display
 * face. Owner's call 2026-09-02: Big Shoulders ships, Anton stays reachable
 * on the dial; Ultra and Bricolage are out. Not a register, so it is the one
 * position here not named for one. */
.ty-anton {
  --font-display: 'Anton', 'Arial Narrow', Impact, sans-serif;
  --font-label:   'Barlow Condensed', 'Arial Narrow', Arial, sans-serif;
  --title-size: 24px; --title-tracking: 0.03em; --title-case: uppercase;
  --label-size: 11px; --label-tracking: 0.08em; --label-case: uppercase;
  --sub-size: 11px;
}
/* the paper — a Didone for the plate, a geometric sans for the small lines. */
.ty-paper {
  --font-display: 'Bodoni Moda', 'Didot', 'Bodoni 72', Georgia, serif;
  --font-label:   'Jost', 'Century Gothic', sans-serif;
  --title-size: 22px; --title-tracking: 0.02em; --title-case: none;
  --label-size: 11px; --label-tracking: 0.14em; --label-case: uppercase;
  --sub-size: 11px;
}
