/* ==========================================================================
   STRATA — Blueprint & Solar Dawn
   Art direction: DESIGN-BRIEF.md. Quality floor: INTERFACE-GUIDELINES.md.

   The palette is inherited verbatim from the PM Dashboard so the two products
   read as one house: deep navy ink, warm cream paper, one amber accent meaning
   *interactive or hot*, blueprint-blue hairlines for structure only.

   The organising idea is an encyclopedia you page into. Each step of the funnel
   is one measurable step lighter — the tonal ladder below — and ornament is
   removed as the pages lighten. Pages select a rung with <body data-tone="n">;
   nothing is hand-tuned per page.
   ========================================================================== */

@import url("/assets/fonts/fonts.css");

:root {
  /* ---- palette (DESIGN-BRIEF token table, verbatim) -------------------- */
  --ink:        #0C1B2A;   /* deep navy — the cover, the viewport, dark bands */
  --ink-2:      #13283E;
  --paper:      #F7F4EE;   /* warm cream — the clean page */
  --paper-2:    #EFEAE0;
  --amber:      #F5A524;   /* the accent. A hot nozzle is amber; so is dawn. */
  --amber-deep: #C77800;
  --line:       rgba(122, 158, 196, .25);   /* blueprint blue rules */
  --ok:         #1F9D55;
  --warn:       #D97706;
  --danger:     #D64545;

  /* derived, kept to a minimum. No new hues — only value steps.
     --amber-ink is --amber darkened until it clears 4.5:1 as *text* on the
     dimmest rung of the ladder (#E8E2D6). Same hue, not a second accent. */
  --amber-ink:   #8A5200;
  --amber-wash:  rgba(245, 165, 36, 0.13);
  --amber-edge:  rgba(245, 165, 36, 0.45);
  --ok-ink:      #116434;   /* --ok darkened until it carries text at AA */
  --ok-wash:     rgba(31, 157, 85, 0.12);
  --warn-ink:    #8A4C14;
  --danger-ink:  #A32020;
  --warn-wash:   rgba(217, 119, 6, 0.12);
  --danger-wash: rgba(214, 69, 69, 0.10);

  /* ---- type ------------------------------------------------------------
     Display — Bricolage Grotesque, variable 300–800, tight negative tracking.
     Mono    — IBM Plex Mono: every price, dimension, layer height, order
               number and eyebrow label, always tabular.
     Both self-hosted as woff2 (see assets/fonts/fonts.css) — never the Google
     Fonts CDN, which would transmit the visitor IP without consent. */
  --font-display: 'Bricolage Grotesque', system-ui, sans-serif;
  --font-body:    'Bricolage Grotesque', system-ui, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, monospace;

  --t-micro: 0.6875rem;                          /* 11 — mono labels only */
  --t-xs:    0.75rem;                            /* 12 */
  --t-sm:    0.8125rem;                          /* 13 */
  --t-base:  0.9375rem;                          /* 15 */
  --t-md:    1.0625rem;                          /* 17 */
  --t-lg:    clamp(1.25rem, 1.05rem + 0.9vw, 1.5rem);
  --t-xl:    clamp(1.5rem, 1.2rem + 1.5vw, 2.125rem);
  --t-2xl:   clamp(1.875rem, 1.35rem + 2.6vw, 3rem);
  --t-3xl:   clamp(2.25rem, 1.3rem + 4.4vw, 4.25rem);

  --lh-tight: 1.04;
  --lh-snug:  1.3;
  --lh-body:  1.62;

  --track-display: -0.035em;
  --track-label:    0.12em;

  /* ---- space (4px base) ------------------------------------------------ */
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;     --s-7: 3rem;     --s-8: 4.5rem;
  --s-9: 6.5rem;

  /* ---- shape ----------------------------------------------------------- */
  --r-sm: 3px;
  --r-md: 6px;
  --r-lg: 10px;
  --r-pill: 999px;

  /* --ring is declared on <body> instead, because its halo takes --page and a
     var() inside a custom property resolves on the element that declares it. */
  --ring-dark: 0 0 0 2px var(--ink), 0 0 0 4px var(--amber);

  --wrap: 1200px;
  --header-h: 60px;

  --ease: cubic-bezier(0.2, 0.6, 0.3, 1);
  --dur: 160ms;                                  /* ≤200ms, per the guidelines */
  --turn: 240ms;                                 /* the page turn, under 260ms */
  --turn-ease: cubic-bezier(0.32, 0.08, 0.24, 1);
}

/* ==========================================================================
   THE TONAL LADDER — paging deeper into the encyclopedia.

   One token set; the page picks a rung with <body data-tone="n">. Every role
   colour below is derived from the rung, so a component written once works on
   the dark cover and on the quiet checkout page without a second rule.

     0  /            #0C1B2A  the bound cover
     1  /shop /quote #DCD3C0  the book opens
     2  /product     #E7E0D0  a plate page
     3  /cart        #F0EADE  nearly clean
     4  /checkout /order #F7F4EE  the quiet page

   (The rung values above were once written as #E8E2D6 / #F0EBE1 / #F4F0E7.
   They were lowered when the ramp was made to start darker; the comment was
   not. Read the declarations, and keep this table matching them.)

   Contrast floors against --text-2, the weakest body colour, on the bare rung
   with no wash: #4A5B6E on #F7F4EE = 6.35:1 (rungs 2–4 sit between). Rung 1 is
   the exception — it carries the diagonal wash, so its floor is measured on
   the composite, not on the flat ground; see body[data-tone="1"] below.
   ========================================================================== */
body {
  --page:        #F7F4EE;
  --surface:     #FFFDF8;   /* cards lifted off the ground */
  --sunk:        #EFEAE0;   /* inset wells, inputs */
  --text:        #0C1B2A;
  --text-2:      #4A5B6E;   /* muted body copy, mono labels */
  --rule:        var(--line);
  --accent-text: var(--amber-ink);   /* amber where it has to carry text */
  /* Semantic colours as *text*: darkened on cream, lightened on the cover.
     Same three hues either way — the rung decides the value, not the meaning. */
  --ok-text:     var(--ok-ink);
  --warn-text:   var(--warn-ink);
  --danger-text: var(--danger-ink);

  /* box-shadow focus ring — respects border-radius, unlike outline. The halo
     takes the page ground so the ring reads on every rung; it has to live here
     rather than on :root because --page is a body-level token. */
  --ring: 0 0 0 2px var(--page), 0 0 0 4px var(--amber);
}

body[data-tone="0"] {
  --page:        #0C1B2A;
  --surface:     #13283E;
  --sunk:        #08131E;
  --text:        #F7F4EE;
  --text-2:      #93A7BC;            /* 7.05:1 on the cover */
  --rule:        rgba(122, 158, 196, .30);
  --accent-text: var(--amber);       /* 8.53:1 on the cover */
  --ok-text:     #5FD98F;            /* 7.2:1 on the cover */
  --warn-text:   var(--amber);
  --danger-text: #F79191;            /* 7.0:1 on the cover */
}
/* The rungs are deliberately dimmer than plain paper at the top of the ladder.
   Landing (L≈0.010) straight into #F7F4EE (L≈0.90) is a ~90x luminance jump and
   it genuinely hurts; the ramp now starts much lower and opens gradually, so the
   page only reaches full paper at the checkout — which is also where the reader
   most needs a clean, quiet surface. */
/* Rung 1 also darkens its text: on a dimmer ground the paper-rung greys lose
   their margin, and the diagonal wash below eats the rest of it. */
body[data-tone="1"] {
  --page: #DCD3C0; --surface: #E6DECD; --sunk: #CEC4AD;
  /* Darker than the paper rungs use, and deliberately so: it is what pays for
     the diagonal wash, which stays at .42 — see body[data-tone="1"]::before.

     History, because the number keeps looking arbitrary: #3E4C5C capped the
     wash at .26; #33404F was chosen to buy the .42 corner and was recorded as
     "4.96:1". That figure was measured at the 72% gradient stop (alpha ≈ .185)
     and the sweep behind it stopped there — it never reached the 72%→100%
     segment where the footer and the lower product cards actually sit
     (effective alpha ≈ .40). Re-measured there, #33404F was 2.89–3.09:1 against
     the darkest ground text occupies: eight elements on /shop and one on
     /quote below the 4.5:1 floor for normal text.

     Read the number that matters before touching this: at the darkest ground
     any text on this rung actually sits on — rgb(130,134,133), the copyright
     line where the wash and the bp-spool drawing overlap — **--text itself
     only reaches 4.73:1**. That is the ceiling for every colour on this rung.
     It is a property of .42 plus the drawings, not of this token, and it
     leaves 0.23 of headroom above the 4.5 floor for the *whole* palette.

     So there is no room on rung 1 for a second, lighter body tone at AA, and
     pretending otherwise is what produced #33404F. #141C25 measures 4.66:1 at
     that pixel and 4.95:1 under the footer blurb — a real margin, at the price
     of being indistinguishable from --text (L* 9.9 against 9.2).

     Read this as: **rung 1 has no muted tone.** It is kept as its own token
     rather than `var(--text)` so the value stays measurable, and so the rung
     can get its hierarchy back the day the wash or the drawing positions
     change — not because the two are meant to look different today. On this
     rung hierarchy is carried by size, weight and mono tracking.

     --text-2 may only ever move *darker* from here. */
  --text-2:      #141C25;
  --accent-text: #6E4100;
  --ok-text:     #0C5028;
  --danger-text: #8E1F1F;
}
body[data-tone="2"] { --page: #E7E0D0; --surface: #F0EADC; --sunk: #D9D0BB; }
body[data-tone="3"] { --page: #F0EADE; --surface: #F7F3EA; --sunk: #E2DACA; }
body[data-tone="4"] { --page: #F7F4EE; --surface: #FFFDF8; --sunk: #EFEAE0; }

/* The ground layer needs a positioned ancestor to span the document rather than
   the viewport; see body[data-tone="1"]::before. */
body { position: relative; }

/* --- ornament is removed as the pages lighten ---------------------------
   Cover: embossed book cloth. Catalogue: the blueprint grid over paper
   grain. Product: hairlines only — nothing here. Cart and checkout: nothing.
   Do not add decoration back to make the checkout "match". */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: none;
}

/* --- eye adaptation ------------------------------------------------------
   The jump from the cover to a light rung is roughly a twelvefold increase in
   luminance, and a heavier diagonal wash can't absorb it without eating the
   text contrast (measured: .16 alpha already fails 11 elements). So the page
   opens from the cover's own ink instead — the reader's eye rides the ramp
   down rather than being handed the lit page at once.

   Only set when the referrer is the cover, by an inline script in <head> so
   the class lands before the first frame. Nothing depends on it: without JS
   the page simply renders lit. */
@keyframes strata-exposure {
  from { opacity: 1; }
  60%  { opacity: .34; }
  to   { opacity: 0; }
}
html.is-adapting body::after {
  content: "";
  position: fixed; inset: 0; z-index: 90; pointer-events: none;
  background: var(--ink);
  animation: strata-exposure 760ms cubic-bezier(.33, 0, .2, 1) forwards;
}
@media (prefers-reduced-motion: reduce) {
  html.is-adapting body::after { display: none; }
}
body[data-tone="0"]::before {
  background:
    radial-gradient(120% 78% at 50% -12%, rgba(245, 165, 36, .09), transparent 62%),
    url("/assets/cover-emboss.webp") center / cover no-repeat;
  /* Measured, not eyeballed: the emboss has bright highlights, and a contrast
     audit that only composites background *colours* misses them entirely. At
     .5 the lede (#93A7BC) fell to 1.90:1 over the brightest pixels. .18 is the
     AA threshold; .14 keeps headroom at 5.15:1 while the cloth still reads. */
  opacity: .14;
}
/* Rung 1 — the workshop ground.
   `position: absolute` (not the inherited `fixed`) is the whole point: the layer
   then spans the *document*, so the diagonal wash reads as "the second half of
   the page", not "the bottom-right of the window". Anchored to the window the
   content scrolls through the dark end and every measurement has to assume the
   worst case everywhere; anchored to the document each element has one fixed
   position on the ramp, which is what buys the extra darkness.

   Layer opacity is 1 and every layer carries its own alpha. A blanket opacity
   would dilute the wash along with the ornament, and the old paper-grain layer
   is gone because it is an opaque image — at full strength it simply repainted
   the rung back to cream. */
body[data-tone="1"]::before {
  position: absolute;
  inset: 0;
  min-height: 100vh;
  opacity: 1;
  background:
    /* topmost: the wash shades everything below it, ornament included */
    /* Peak .42 at the bottom-right corner.

       CORRECTION — the figure that used to stand here ("worst 4.96:1") was
       wrong, and wrong in a way worth naming so it is not repeated. It came
       from a sweep that walked the ramp and stopped at the 72% stop, i.e.
       alpha ≈ .185. Everything past that stop — the whole 72%→100% segment,
       effective alpha ≈ .40, which is exactly where the footer and the lower
       product cards sit — was never evaluated. At .42 with --text-2 at
       #33404F the real worst was 2.89:1, not 4.96:1.

       Re-measured properly (glyphs painted transparent, the composite sampled
       under every text rect, every pixel, /shop and /quote at 375 and 1280, DE
       and EN), with --text-2 at #141C25: worst 4.66:1 under text.

       The ceiling is the real news. Where this wash overlaps bp-spool.webp
       behind the footer, the ground reaches rgb(130,134,133) — and *--text
       itself* only measures 4.73:1 there. .42 plus the drawings leaves the
       entire palette 0.23 above the AA floor. That is why --text-2 had to
       collapse into --text on this rung (see body[data-tone="1"]).

       There is nothing left to trade. Raising .42 does not cost a token any
       more; it costs the page its AA compliance outright, because the darkest
       colour available already sits 0.23 from the floor. If this rung ever
       needs a muted tone back, the lever is the drawing positions or .42 —
       not another darker grey, because there isn't one. */
    linear-gradient(135deg,
      rgba(12, 27, 42, 0)   45%,
      rgba(12, 27, 42, .19) 72%,
      rgba(12, 27, 42, .42) 100%),

    /* the machine, drawn as plate figures. Alpha and blueprint tint are baked
       into the assets so they stay faint without a layer-wide opacity. */
    url("/assets/bp-hotend.webp") no-repeat 93% 9%  / clamp(150px, 19vw, 280px) auto,
    url("/assets/bp-gantry.webp") no-repeat 4%  46% / clamp(170px, 24vw, 360px) auto,
    url("/assets/bp-spool.webp")  no-repeat 86% 84% / clamp(140px, 17vw, 250px) auto,

    /* drafting grid — was var(--line) under a .5 layer, so half that here */
    repeating-linear-gradient(to right,  rgba(122, 158, 196, .13) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(to bottom, rgba(122, 158, 196, .13) 0 1px, transparent 1px 64px);
}

/* ==========================================================================
   CROSS-DOCUMENT PAGE TURNS
   The outgoing page lifts and dims; the incoming page rises from beneath.
   The masthead and wordmark are pulled out of the root snapshot so they hold
   still while the body changes underneath — that stillness is the effect.
   Browsers without support simply navigate. No polyfill.
   ========================================================================== */
@view-transition { navigation: auto; }

::view-transition-group(root) { animation-duration: var(--turn); }

/* The old page has to paint *over* the new one for a lift to read, and the
   default pair is isolated with the new snapshot on top. Opting out of the
   isolation lets z-index and plain alpha do the work. */
::view-transition-image-pair(root) { isolation: auto; }
::view-transition-old(root),
::view-transition-new(root) { mix-blend-mode: normal; }

::view-transition-old(root) {
  z-index: 1;
  animation: page-lift 200ms var(--turn-ease) both;
}
::view-transition-new(root) {
  z-index: 0;
  animation: page-rise var(--turn) var(--turn-ease) both;
}
@keyframes page-lift {
  to { opacity: 0; transform: translateY(-1.1%) scale(1.012); }
}
@keyframes page-rise {
  from { opacity: 0; transform: translateY(1.4%); }
}

/* ==========================================================================
   reset
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
  margin: 0;
  background: var(--page);
  color: var(--text);
  font: var(--t-base)/var(--lh-body) var(--font-body);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
}
p { margin: 0; }
img, svg, canvas { display: block; max-width: 100%; }

/* A class-level `display` beats the `hidden` attribute, and this sheet sets
   display on dropzones, grids and canvases that JS toggles with `hidden`. */
[hidden] { display: none !important; }
button, input, select, textarea { font: inherit; color: inherit; font-variant-numeric: tabular-nums; }

a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }

ul, ol { margin: 0; padding: 0; }
li { list-style: none; }
table { border-collapse: collapse; width: 100%; }

:focus { outline: none; }
:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-sm); }

::selection { background: var(--amber); color: var(--ink); }

/* Interactive chrome should not be text-selectable. */
button, .btn, .badge, .segmented label, .swatch, .pager__page, .lang-switch__btn {
  -webkit-user-select: none; user-select: none;
}

/* ==========================================================================
   layout primitives
   ========================================================================== */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--s-5); }
main { flex: 1 0 auto; }

.stack > * + * { margin-top: var(--s-4); }
.stack-sm > * + * { margin-top: var(--s-2); }
.stack-lg > * + * { margin-top: var(--s-5); }

.row { display: flex; align-items: center; gap: var(--s-3); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.row-wrap { flex-wrap: wrap; }
.grow { flex: 1; }

.skip-link {
  position: absolute; left: var(--s-4); top: -60px; z-index: 100;
  background: var(--amber); color: var(--ink);
  padding: var(--s-2) var(--s-4); border-radius: var(--r-md); font-weight: 600;
}
.skip-link:focus { top: var(--s-3); text-decoration: none; }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   STRATA — the structural unit. A section is a layer: hairline rule on top,
   the eyebrow label sitting on the rule carrying a real measurement.
   ========================================================================== */
.stratum {
  position: relative;
  border-top: 1px solid var(--rule);
  padding-block: var(--s-7) var(--s-8);
}
.stratum:last-of-type { padding-bottom: var(--s-8); }

.stratum__label {
  position: absolute; top: 0; left: 0;
  transform: translateY(-50%);
  background: var(--page);
  padding-right: var(--s-4);
  display: inline-flex; align-items: center; gap: var(--s-3);
}

/* Mono micro-label: uppercase, wide tracking, muted. Carries real data —
   a measurement, never a sequence number outside the "how it works" run. */
.spec-label {
  font: 500 var(--t-micro)/1 var(--font-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-2);
  white-space: nowrap;
}
.spec-label--accent { color: var(--accent-text); }
.spec-label--seq { color: var(--text); }

.stratum__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-5); flex-wrap: wrap; margin-bottom: var(--s-6);
}

/* Page head: the top stratum of an inner page. */
.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-5); flex-wrap: wrap;
  padding-block: var(--s-7) var(--s-6);
}
.page-head h1 { margin-top: var(--s-3); }
.page-head .lede { margin-top: var(--s-3); }
.page-body { padding-bottom: var(--s-8); }

/* ==========================================================================
   typography helpers
   ========================================================================== */
.h-display { font-size: var(--t-3xl); letter-spacing: -0.04em; }
.h-xl  { font-size: var(--t-xl); }
.h-lg  { font-size: var(--t-lg); }
.h-md  { font-size: var(--t-md); }
.h-sm  { font-size: var(--t-base); font-weight: 600; letter-spacing: -0.015em; }

.lede { font-size: var(--t-md); color: var(--text-2); max-width: 62ch; line-height: 1.5; }
.muted { color: var(--text-2); }
.small { font-size: var(--t-sm); }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }

/* ==========================================================================
   header / footer
   ========================================================================== */
/* The masthead is pulled out of the root view-transition snapshot, so it holds
   still while the body turns underneath. `view-transition-name` must be unique
   per document — hence the descendant selector; the footer wordmark is left
   unnamed on purpose. */
.site-header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--page) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule);
  view-transition-name: masthead;
}
@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .site-header { background: var(--page); }
}
.site-header__inner { display: flex; align-items: center; gap: var(--s-4); height: var(--header-h); }
.site-header .brand { view-transition-name: wordmark; }

/* The wordmark: display face, uppercase, tight negative tracking. The only
   permitted graphic mark is the strata — a stack of rules of varying weight. */
.brand {
  display: inline-flex; align-items: center; gap: var(--s-3);
  color: var(--text); font-family: var(--font-display);
  font-weight: 700; letter-spacing: -0.02em; font-size: var(--t-md);
  text-transform: uppercase;
}
.brand:hover { text-decoration: none; color: var(--text); }
.brand svg { width: 22px; height: 22px; flex: none; }

/* strata mark — rules of varying weight, the top one amber (the hot layer) */
.strata-mark {
  display: inline-flex; flex-direction: column; gap: 2px;
  width: 17px; flex: none;
}
.strata-mark i { display: block; height: 2px; background: currentColor; border-radius: 1px; }
.strata-mark i:nth-child(1) { height: 3px; background: var(--amber); }
.strata-mark i:nth-child(2) { opacity: .85; }
.strata-mark i:nth-child(3) { opacity: .55; width: 78%; }
.strata-mark i:nth-child(4) { opacity: .32; width: 56%; }

.nav { display: flex; align-items: center; gap: var(--s-1); margin-left: var(--s-5); }
.nav a {
  color: var(--text-2); padding: var(--s-2) var(--s-3); min-height: 36px;
  display: inline-flex; align-items: center;
  border-radius: var(--r-md); font-size: var(--t-sm); font-weight: 500;
  transition: color var(--dur) var(--ease);
}
@media (hover: hover) { .nav a:hover { color: var(--text); text-decoration: none; } }
.nav a[aria-current="page"] { color: var(--text); font-weight: 600; }

.header-actions { margin-left: auto; display: flex; align-items: center; gap: var(--s-3); }

.cart-link {
  position: relative; display: inline-flex; align-items: center; gap: var(--s-2);
  min-height: 36px; padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md); border: 1px solid var(--rule);
  color: var(--text); font-size: var(--t-sm); font-weight: 500; background: var(--surface);
  transition: border-color var(--dur) var(--ease);
}
@media (hover: hover) { .cart-link:hover { text-decoration: none; border-color: var(--text-2); } }
.cart-link svg { width: 16px; height: 16px; }
.cart-count {
  min-width: 18px; height: 18px; padding-inline: 5px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--amber); color: var(--ink);
  border-radius: var(--r-pill); font: 600 10px/1 var(--font-mono);
}
.cart-count[hidden] { display: none; }

.nav-toggle { display: none; }

.lang-switch { display: inline-flex; gap: var(--s-1); align-items: center; }
.lang-switch__btn {
  padding: var(--s-2); min-width: 34px; min-height: 36px;
  background: none; border: 0; border-radius: var(--r-md); cursor: pointer;
  font: 500 var(--t-micro)/1 var(--font-mono); letter-spacing: var(--track-label);
  color: var(--text-2);
  transition: color var(--dur) var(--ease);
}
@media (hover: hover) { .lang-switch__btn:hover { color: var(--text); } }
.lang-switch__btn[aria-current="true"] { color: var(--accent-text); }

.site-footer {
  border-top: 1px solid var(--rule);
  padding-block: var(--s-7) var(--s-5);
  margin-top: var(--s-8);
  font-size: var(--t-sm);
  color: var(--text-2);
}
.footer-grid { display: grid; grid-template-columns: 1.7fr repeat(2, 1fr); gap: var(--s-6); }
.footer-grid h3 {
  font: 500 var(--t-micro)/1 var(--font-mono); letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--text-2); margin-bottom: var(--s-4);
}
.footer-grid a { color: var(--text); }
@media (hover: hover) { .footer-grid a:hover { color: var(--accent-text); } }
.footer-grid li + li { margin-top: var(--s-2); }
.footer-blurb { margin-top: var(--s-4); max-width: 38ch; color: var(--text-2); }
.footer-bottom {
  margin-top: var(--s-7); padding-top: var(--s-4); border-top: 1px solid var(--rule);
  display: flex; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap;
  font-family: var(--font-mono); font-size: var(--t-micro); color: var(--text-2);
}

/* ==========================================================================
   buttons — 44px minimum touch target
   ========================================================================== */
.btn {
  --btn-bg: var(--surface);
  --btn-fg: var(--text);
  --btn-bd: var(--rule);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  padding: var(--s-3) var(--s-5); min-height: 44px;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--btn-bd); border-radius: var(--r-md);
  font-family: var(--font-body); font-size: var(--t-sm); font-weight: 600;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
@media (hover: hover) { .btn:hover { text-decoration: none; border-color: var(--text-2); } }
.btn:active { transform: scale(0.98); }
.btn[disabled], .btn[aria-disabled="true"], .btn.is-disabled {
  opacity: 0.4; cursor: not-allowed; transform: none; pointer-events: none;
}
.btn svg { width: 16px; height: 16px; flex: none; }

.btn--primary { --btn-bg: var(--amber); --btn-fg: var(--ink); --btn-bd: var(--amber); }
@media (hover: hover) {
  .btn--primary:hover { background: var(--amber-deep); border-color: var(--amber-deep); }
}
.btn--ghost { --btn-bg: transparent; --btn-bd: transparent; --btn-fg: var(--text-2); }
@media (hover: hover) { .btn--ghost:hover { color: var(--text); border-color: var(--rule); } }

.btn--danger { --btn-bg: transparent; --btn-fg: var(--danger-text); --btn-bd: var(--rule); }
@media (hover: hover) { .btn--danger:hover { background: var(--danger-wash); border-color: var(--danger); } }

.btn--lg { padding: var(--s-4) var(--s-6); min-height: 52px; font-size: var(--t-base); }
.btn--sm { padding: var(--s-2) var(--s-3); min-height: 36px; font-size: var(--t-xs); }
.btn--block { display: flex; width: 100%; }

.btn.is-busy { position: relative; color: transparent !important; pointer-events: none; }
.btn.is-busy::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid var(--btn-fg); border-top-color: transparent;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Inline success on the trigger itself, not a toast (INTERFACE-GUIDELINES). */
.btn.is-done { --btn-bg: var(--ok-ink); --btn-bd: var(--ok-ink); --btn-fg: #fff; }

.link-btn {
  background: none; border: 0; padding: var(--s-1) 0; color: var(--text-2);
  font-size: var(--t-sm); cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
@media (hover: hover) { .link-btn:hover { color: var(--danger-text); } }

/* ==========================================================================
   surfaces — hairlines and space, never stacked shadows
   ========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: var(--s-5);
}
.card--flush { padding: 0; overflow: hidden; }
.card__body { padding: var(--s-5); }

.badge {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: 3px var(--s-2); border-radius: var(--r-sm);
  background: var(--sunk); color: var(--text-2);
  font: 500 var(--t-micro)/1.5 var(--font-mono);
  letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap;
}
.badge--accent { background: var(--amber-wash); color: var(--accent-text); }
.badge--hot  { background: var(--warn-wash); color: var(--warn-text); }   /* functional: in production */
.badge--ok   { background: var(--ok-wash); color: var(--ok-text); }
.badge--err  { background: var(--danger-wash); color: var(--danger-text); }

/* ==========================================================================
   forms
   ========================================================================== */
.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field > label, .label, .fieldset__legend {
  font-size: var(--t-sm); font-weight: 600; color: var(--text);
}
.label-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
.req { color: var(--accent-text); }
.optional { color: var(--text-2); font-weight: 400; }

/* 16px on inputs prevents iOS zoom-on-focus. */
.input, .select, .textarea {
  width: 100%;
  padding: var(--s-3);
  min-height: 46px;
  font-size: 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  color: var(--text);
  transition: border-color var(--dur) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--text-2); opacity: 0.7; }
@media (hover: hover) {
  .input:hover, .select:hover, .textarea:hover { border-color: var(--text-2); }
}
.input:focus-visible, .select:focus-visible, .textarea:focus-visible {
  box-shadow: var(--ring); border-color: var(--amber);
}
.textarea { min-height: 96px; resize: vertical; line-height: var(--lh-snug); }

.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5' fill='none' stroke='%234A5B6E' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s-3) center;
  background-size: 12px;
  padding-right: var(--s-6);
}

.field-error { font-size: var(--t-sm); color: var(--danger-text); display: none; }
.field.has-error .input, .field.has-error .select, .field.has-error .textarea {
  border-color: var(--danger); background: var(--danger-wash);
}
.field.has-error .field-error { display: block; }

.hint { font-size: var(--t-sm); color: var(--text-2); }
.hint.center { text-align: center; }

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }
.form-grid .span-2 { grid-column: 1 / -1; }

/* fieldsets used for real radio groups (variant/colour/quality pickers) */
.fieldset { border: 0; padding: 0; margin: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--s-2); }
.fieldset__legend { padding: 0; }

/* range slider */
input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 44px; background: transparent; cursor: pointer; margin: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 3px; border-radius: var(--r-pill);
  background: linear-gradient(to right, var(--amber) var(--fill, 20%), var(--rule) var(--fill, 20%));
}
input[type="range"]::-moz-range-track { height: 3px; border-radius: var(--r-pill); background: var(--rule); }
input[type="range"]::-moz-range-progress { height: 3px; border-radius: var(--r-pill); background: var(--amber); }
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; margin-top: -7.5px;
  border-radius: 50%; background: var(--amber); border: 3px solid var(--surface);
  box-shadow: 0 0 0 1px var(--amber);
}
input[type="range"]::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--amber); border: 3px solid var(--surface); box-shadow: 0 0 0 1px var(--amber);
}
input[type="range"]:focus-visible { box-shadow: var(--ring); border-radius: var(--r-pill); }

/* segmented control (radio group) */
.segmented { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.segmented input { position: absolute; opacity: 0; pointer-events: none; }
.segmented label {
  flex: 1 1 0; min-width: 86px; min-height: 56px;
  display: flex; flex-direction: column; gap: 2px; align-items: center; justify-content: center;
  padding: var(--s-3) var(--s-2);
  border: 1px solid var(--rule); border-radius: var(--r-md);
  background: var(--surface); cursor: pointer; text-align: center;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.segmented label span.seg-t { font: 600 var(--t-sm)/1.3 var(--font-body); color: var(--text); }
.segmented label span.seg-m { font: 500 var(--t-micro)/1.3 var(--font-mono); color: var(--text-2); letter-spacing: 0.04em; }
@media (hover: hover) { .segmented label:hover { border-color: var(--text-2); } }
.segmented input:checked + label { border-color: var(--amber); background: var(--amber-wash); }
.segmented input:checked + label span.seg-t { color: var(--accent-text); }
.segmented input:checked + label span.seg-m { color: var(--accent-text); }
.segmented input:focus-visible + label { box-shadow: var(--ring); }

/* colour swatches — real radios in a fieldset, visually restyled */
.swatches { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.swatches input { position: absolute; opacity: 0; pointer-events: none; }
.swatch {
  display: inline-flex; align-items: center; gap: var(--s-2);
  min-height: 44px; padding: var(--s-2) var(--s-4) var(--s-2) var(--s-2);
  border: 1px solid var(--rule); border-radius: var(--r-pill);
  background: var(--surface); cursor: pointer;
  font-size: var(--t-xs); font-weight: 500; color: var(--text-2);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.swatch i {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.16);
}
@media (hover: hover) { .swatch:hover { border-color: var(--text-2); color: var(--text); } }
.swatches input:checked + .swatch { border-color: var(--amber); color: var(--text); background: var(--amber-wash); }
.swatches input:focus-visible + .swatch { box-shadow: var(--ring); }
.swatches input:disabled + .swatch { opacity: 0.4; cursor: not-allowed; }

/* quantity stepper */
.qty {
  display: inline-flex; align-items: center;
  border: 1px solid var(--rule); border-radius: var(--r-md);
  background: var(--surface); overflow: hidden;
}
.qty button {
  width: 44px; height: 44px; background: none; border: 0; color: var(--text-2);
  cursor: pointer; font-size: var(--t-md); line-height: 1;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
@media (hover: hover) { .qty button:hover:not([disabled]) { background: var(--sunk); color: var(--text); } }
.qty button[disabled] { opacity: 0.3; cursor: not-allowed; }
.qty input {
  width: 48px; height: 44px; text-align: center; border: 0; background: none;
  font-family: var(--font-mono); font-size: 16px; -moz-appearance: textfield;
}
.qty input::-webkit-outer-spin-button, .qty input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ==========================================================================
   alerts
   ========================================================================== */
.alert {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-3) var(--s-4); border-radius: var(--r-md);
  border: 1px solid var(--rule); background: var(--surface);
  font-size: var(--t-sm); line-height: var(--lh-snug);
}
.alert svg { width: 17px; height: 17px; flex: none; margin-top: 1px; }
.alert--err  { border-color: var(--danger); background: var(--danger-wash); color: var(--danger-text); }
.alert--ok   { border-color: var(--ok); background: var(--ok-wash); color: var(--ok-text); }
.alert--warn { border-color: var(--warn); background: var(--warn-wash); color: var(--warn-text); }
.alert--info { border-color: var(--amber-edge); background: var(--amber-wash); color: var(--accent-text); }

.toasts {
  position: fixed; right: var(--s-5); bottom: var(--s-5); z-index: 90;
  display: flex; flex-direction: column; gap: var(--s-2);
  max-width: min(360px, calc(100vw - 2rem));
}
.toast {
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-md); padding: var(--s-3) var(--s-4);
  font-size: var(--t-sm);
  animation: toast-in 160ms var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }
.toast.is-leaving { opacity: 0; transition: opacity 160ms var(--ease); }

/* ==========================================================================
   loading / empty states
   ========================================================================== */
.skeleton {
  background: var(--sunk);
  border-radius: var(--r-sm);
  color: transparent !important;
  position: relative; overflow: hidden;
}
.skeleton::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 20%, rgba(247,244,238,0.55) 50%, transparent 80%);
  animation: shimmer 1.3s linear infinite;
}
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.sk-line { height: 0.8em; border-radius: var(--r-sm); }
.sk-line + .sk-line { margin-top: var(--s-2); }
.sk-w-40 { width: 40%; } .sk-w-60 { width: 60%; } .sk-w-80 { width: 80%; }

.empty {
  text-align: center; padding: var(--s-8) var(--s-4);
  border: 1px solid var(--rule); border-radius: var(--r-lg);
  background: var(--surface);
}
.empty svg { width: 40px; height: 40px; margin: 0 auto var(--s-4); color: var(--rule); }
.empty h3 { font-size: var(--t-md); margin-bottom: var(--s-2); }
.empty p { color: var(--text-2); font-size: var(--t-sm); max-width: 44ch; margin: 0 auto var(--s-5); }
.empty__actions { justify-content: center; }
.empty--inline { padding: var(--s-6) var(--s-3); }
.empty--inline svg { width: 32px; height: 32px; margin-bottom: var(--s-3); }
.empty--inline h3 { font-size: var(--t-sm); }
.empty--inline p { font-size: var(--t-xs); margin-bottom: 0; }

/* ==========================================================================
   product card — the object is the hero, separated by hairline and space
   ========================================================================== */
.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(236px, 1fr));
  gap: var(--s-5) var(--s-4);
}

.product-card {
  display: flex; flex-direction: column; color: var(--text);
  border-radius: var(--r-lg);
}
a.product-card:hover { text-decoration: none; }
a.product-card:focus-visible { box-shadow: var(--ring); }
@media (hover: hover) {
  a.product-card:hover .thumb { border-color: var(--text-2); }
  a.product-card:hover .product-card__name { color: var(--accent-text); }
}

.thumb {
  position: relative; aspect-ratio: 4 / 3;
  background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--r-md);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease);
}
.thumb img { width: 100%; height: 100%; object-fit: cover; }
.thumb__badges { position: absolute; top: var(--s-2); left: var(--s-2); display: flex; gap: var(--s-1); flex-wrap: wrap; }

/* placeholder artwork: a part drawn in strata, on the paper ground */
.thumb--ph { display: grid; place-items: center; }
.thumb--ph::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(to bottom, rgba(12,27,42,0.05) 0 1px, transparent 1px 5px);
}
.thumb--ph svg { width: 46%; height: auto; color: var(--text-2); opacity: .45; }
.thumb--ph svg[data-tilt="-4"] { transform: rotate(-4deg); }
.thumb--ph svg[data-tilt="-3"] { transform: rotate(-3deg); }
.thumb--ph svg[data-tilt="-2"] { transform: rotate(-2deg); }
.thumb--ph svg[data-tilt="-1"] { transform: rotate(-1deg); }
.thumb--ph svg[data-tilt="1"]  { transform: rotate(1deg); }
.thumb--ph svg[data-tilt="2"]  { transform: rotate(2deg); }
.thumb--ph svg[data-tilt="3"]  { transform: rotate(3deg); }
.thumb--ph svg[data-tilt="4"]  { transform: rotate(4deg); }

.product-card__body { padding-top: var(--s-3); display: flex; flex-direction: column; gap: var(--s-1); flex: 1; }
.product-card__name {
  font-family: var(--font-display); font-size: var(--t-md); font-weight: 600;
  letter-spacing: -0.025em; line-height: var(--lh-snug);
  transition: color var(--dur) var(--ease);
}
.product-card__desc {
  font-size: var(--t-sm); color: var(--text-2); line-height: var(--lh-snug);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.product-card__foot {
  margin-top: auto; padding-top: var(--s-3);
  display: flex; align-items: baseline; gap: var(--s-2);
}

/* Every price is mono with tabular figures. */
.price {
  font: 600 var(--t-md)/1 var(--font-mono);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.price--big { font-size: var(--t-xl); letter-spacing: -0.035em; }
.price--strike { font: 400 var(--t-sm)/1 var(--font-mono); color: var(--text-2); text-decoration: line-through; }
.price-from { font: 500 var(--t-micro)/1 var(--font-mono); color: var(--text-2); text-transform: uppercase; letter-spacing: var(--track-label); }

/* ==========================================================================
   pagination
   ========================================================================== */
.pager { display: flex; align-items: center; justify-content: center; gap: var(--s-1); margin-top: var(--s-7); flex-wrap: wrap; }
.pager__page {
  min-width: 44px; height: 44px; padding-inline: var(--s-2);
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: var(--r-md);
  color: var(--text-2); font: 500 var(--t-sm)/1 var(--font-mono);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
@media (hover: hover) { .pager__page:hover { color: var(--text); border-color: var(--rule); text-decoration: none; } }
.pager__page[aria-current="page"] { border-color: var(--amber); color: var(--accent-text); }
.pager__page[aria-disabled="true"] { opacity: 0.3; cursor: not-allowed; pointer-events: none; }
.pager__gap { color: var(--text-2); padding-inline: var(--s-1); }

/* ==========================================================================
   spec lists / metrics — the measurement type
   ========================================================================== */
.spec-list { display: grid; gap: var(--s-2); margin: 0; }
.spec { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); font-size: var(--t-sm); }
.spec dt, .spec__k { color: var(--text-2); }
.spec dd, .spec__v { margin: 0; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.spec--total {
  border-top: 1px solid var(--rule); margin-top: var(--s-3); padding-top: var(--s-3);
}
.spec--total dt { color: var(--text); font-weight: 600; }
.spec--total dd { font-size: var(--t-md); font-weight: 600; }

.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 1px; background: var(--rule); border: 1px solid var(--rule); border-radius: var(--r-md); overflow: hidden; }
.metric { background: var(--surface); padding: var(--s-3) var(--s-4); }
.metric__k { font: 500 var(--t-micro)/1.4 var(--font-mono); text-transform: uppercase; letter-spacing: var(--track-label); color: var(--text-2); }
.metric__v { font: 600 var(--t-md)/1.35 var(--font-mono); font-variant-numeric: tabular-nums; margin-top: 2px; letter-spacing: -0.02em; }
.metric__v small { font-size: var(--t-xs); color: var(--text-2); font-weight: 400; margin-left: 2px; }

/* ==========================================================================
   tables
   ========================================================================== */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table { font-size: var(--t-sm); min-width: 560px; font-variant-numeric: tabular-nums; }
.table th {
  text-align: left; font: 500 var(--t-micro)/1 var(--font-mono);
  text-transform: uppercase; letter-spacing: var(--track-label); color: var(--text-2);
  padding: var(--s-3); border-bottom: 1px solid var(--rule); white-space: nowrap;
  position: sticky; top: 0; background: var(--page); z-index: 1;
}
.table td { padding: var(--s-3); border-bottom: 1px solid var(--rule); vertical-align: middle; }
@media (hover: hover) { .table tbody tr:hover { background: var(--sunk); } }
.table .right { text-align: right; }
.table tbody tr:focus-visible { box-shadow: var(--ring); }

/* ==========================================================================
   timeline
   ========================================================================== */
.timeline { position: relative; padding-left: var(--s-6); }
.timeline::before {
  content: ""; position: absolute; left: 6px; top: 8px; bottom: 8px; width: 1px;
  background: var(--rule);
}
.tl-item { position: relative; padding-bottom: var(--s-5); }
.tl-item:last-child { padding-bottom: 0; }
.tl-item::before {
  content: ""; position: absolute; left: calc(-1 * var(--s-6) + 1px); top: 5px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--page); border: 1px solid var(--rule);
}
.tl-item.is-done::before { background: var(--text-2); border-color: var(--text-2); }
.tl-item.is-current::before { background: var(--amber); border-color: var(--amber); box-shadow: 0 0 0 3px var(--amber-wash); }
.tl-item__t { font-weight: 600; font-size: var(--t-sm); }
.tl-item__m { font: 400 var(--t-micro)/1.5 var(--font-mono); color: var(--text-2); }
.tl-item__n { font-size: var(--t-sm); color: var(--text-2); margin-top: 2px; }

/* ==========================================================================
   page: home — the bound cover (tone 0)

   The hero is the thesis: the engraved encyclopedia plate, the wordmark, one
   sentence. Below it, strata separated by blueprint rules with the eyebrow
   label sitting on the rule. Eyebrows carry measurements, never sequence
   numbers — the 01–04 run in "how it works" is the one earned exception.
   ========================================================================== */
.cover { padding-block: var(--s-7) var(--s-8); }
.cover__inner {
  display: grid; grid-template-columns: 0.92fr 1.08fr;
  gap: var(--s-8); align-items: center;
}

/* The wordmark, set as a display line rather than a logo image so it stays
   selectable, searchable and crisp at any size. */
.wordmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(3.25rem, 1.4rem + 8.4vw, 7.5rem);
  line-height: 0.88;
  letter-spacing: -0.055em;
  text-transform: uppercase;
  margin-block: var(--s-4) var(--s-5);
}
.wordmark b { font-weight: 800; color: var(--amber); }

.cover__rules { display: flex; flex-direction: column; gap: 3px; max-width: 168px; }
.cover__rules i { display: block; height: 2px; background: var(--text); opacity: .22; }
.cover__rules i:nth-child(1) { height: 4px; background: var(--amber); opacity: 1; }
.cover__rules i:nth-child(2) { height: 3px; opacity: .5; }
.cover__rules i:nth-child(3) { width: 74%; }
.cover__rules i:nth-child(4) { width: 48%; }

.cover__lede { font-size: var(--t-md); color: var(--text-2); max-width: 46ch; line-height: 1.55; }
.cover__cta { display: flex; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-6); }

/* The plate is tipped in: a cream leaf on the dark cover, with a ruled
   caption underneath the way a real plate is captioned. */
.plate { margin: 0; }
.plate__leaf {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: var(--s-3);
  box-shadow: 0 18px 40px -26px rgba(0, 0, 0, .8);
}
.plate__leaf img { width: 100%; height: auto; border-radius: 1px; }
.plate__cap {
  margin-top: var(--s-3); padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
  display: flex; gap: var(--s-5) var(--s-6); flex-wrap: wrap;
}
.plate__cap div { display: flex; flex-direction: column; gap: 3px; }
.plate__cap b {
  font: 600 var(--t-base)/1 var(--font-mono);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}

/* --- section 1: what it is ---------------------------------------------- */
.offer { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-7); align-items: start; }
.offer__col > h3 { font-size: var(--t-lg); margin-block: var(--s-3) var(--s-3); }
.offer__col > p { color: var(--text-2); font-size: var(--t-sm); line-height: var(--lh-body); max-width: 46ch; }
.offer__more { margin-top: var(--s-4); display: inline-flex; align-items: center; gap: var(--s-2); font-weight: 600; font-size: var(--t-sm); }
.offer__more svg { width: 15px; height: 15px; }
.offer__strip { margin-top: var(--s-7); border-top: 1px solid var(--rule); padding-top: var(--s-5); }
.offer__strip > .spec-label { display: block; margin-bottom: var(--s-4); }
.offer__strip .product-grid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: var(--s-5) var(--s-4); }
.offer__strip .product-card__desc { display: none; }
.offer__strip .product-card__name { font-size: var(--t-sm); }

/* --- section 2: the specimen plate --------------------------------------- */
.specimen { display: grid; grid-template-columns: 0.86fr 1.14fr; gap: var(--s-7); align-items: start; }
.specimen__fig { margin: 0; }
.specimen__fig img { width: 100%; height: auto; border: 1px solid var(--rule); border-radius: 2px; }
.specimen__fig figcaption { margin-top: var(--s-3); font: 400 var(--t-micro)/1.6 var(--font-mono); color: var(--text-2); }

.mat-rows { border-top: 1px solid var(--rule); }
.mat-row {
  display: grid; grid-template-columns: 7.5rem 1fr;
  gap: var(--s-3) var(--s-5);
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--rule);
}
.mat-row__name { font-family: var(--font-display); font-weight: 700; font-size: var(--t-md); letter-spacing: -0.03em; }
.mat-row__fig { font: 500 var(--t-micro)/1.7 var(--font-mono); font-variant-numeric: tabular-nums; color: var(--text-2); letter-spacing: 0.04em; margin-top: 2px; }
.mat-row__fig b { color: var(--text); font-weight: 600; }
.mat-row__use { font-size: var(--t-sm); color: var(--text-2); line-height: var(--lh-snug); }

/* --- section 3: how it works (the one place 01–04 is earned) ------------- */
.step .spec-label { display: block; margin-bottom: var(--s-1); }
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 1px; background: var(--rule); border-top: 1px solid var(--rule); }
.step { background: var(--page); padding: var(--s-5) var(--s-5) var(--s-6); }
.step h3 { font-size: var(--t-md); margin-block: var(--s-4) var(--s-2); }
.step p { font-size: var(--t-sm); color: var(--text-2); line-height: var(--lh-snug); }
.spec-label--seq { font-size: var(--t-sm); font-weight: 600; letter-spacing: 0.06em; }

/* --- section 4: the machine ---------------------------------------------- */
.machine { display: grid; grid-template-columns: 1.25fr 0.75fr; gap: var(--s-7); align-items: center; }
.machine__fig { margin: 0; position: relative; }
.machine__fig img { width: 100%; height: auto; border-radius: 2px; border: 1px solid var(--rule); }
.machine__fig figcaption {
  margin-top: var(--s-3); font: 400 var(--t-micro)/1.6 var(--font-mono);
  color: var(--text-2); letter-spacing: 0.04em;
}
.machine__body h2 { font-size: var(--t-xl); margin-bottom: var(--s-4); }
.machine__body p { color: var(--text-2); font-size: var(--t-sm); line-height: var(--lh-body); }
.machine__facts { margin-top: var(--s-5); border-top: 1px solid var(--rule); }
.machine__facts div { display: flex; justify-content: space-between; gap: var(--s-4); padding-block: var(--s-3); border-bottom: 1px solid var(--rule); font-size: var(--t-sm); }
.machine__facts dt { color: var(--text-2); }
.machine__facts dd { margin: 0; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* --- section 5: close ----------------------------------------------------- */
.close-band { display: grid; gap: var(--s-5); max-width: 54ch; }
.close-band h2 { font-size: var(--t-2xl); }
.close-band p { color: var(--text-2); }
.close-band .btn { justify-self: start; }

.hero { padding-block: var(--s-8) var(--s-7); }
.hero__inner { display: grid; grid-template-columns: 1.02fr 0.98fr; gap: var(--s-8); align-items: center; }
.hero h1 { font-size: var(--t-3xl); margin-block: var(--s-5) var(--s-5); max-width: 15ch; }
.hero h1 em { font-style: normal; color: var(--accent-text); }
.hero__cta { display: flex; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-6); }
.hero--quote { padding-block: var(--s-7) var(--s-6); max-width: 62ch; }
.hero--quote h1 { margin-block: var(--s-4) var(--s-4); }

.trust { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--s-5); }
.trust__item b { display: block; font-size: var(--t-sm); margin-bottom: var(--s-1); }
.trust__item span { font-size: var(--t-sm); color: var(--text-2); line-height: var(--lh-snug); }
.trust--compact { grid-template-columns: 1fr; gap: var(--s-3); }
.trust--compact b, .trust--compact span { font-size: var(--t-xs); }

.cta-band {
  border: 1px solid var(--rule); border-radius: var(--r-lg);
  background: var(--surface);
  padding: var(--s-7) var(--s-6);
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-5); flex-wrap: wrap;
}

/* ==========================================================================
   page: shop
   ========================================================================== */
.shop-layout { display: grid; grid-template-columns: 200px 1fr; gap: var(--s-7); align-items: start; }
.filter-rail { position: sticky; top: calc(var(--header-h) + var(--s-5)); }
.filter-group + .filter-group { margin-top: var(--s-6); }
.filter-group h3 {
  font: 500 var(--t-micro)/1 var(--font-mono); text-transform: uppercase;
  letter-spacing: var(--track-label); color: var(--text-2); margin-bottom: var(--s-3);
}
.cat-list a {
  display: block; padding: var(--s-2) 0; min-height: 36px;
  color: var(--text-2); font-size: var(--t-sm);
  border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease);
}
@media (hover: hover) { .cat-list a:hover { color: var(--text); text-decoration: none; } }
.cat-list a[aria-current="true"] { color: var(--accent-text); font-weight: 600; }

/* Input decoration sits on top of the field, not beside it. */
.searchbar { position: relative; }
.searchbar svg {
  position: absolute; left: var(--s-3); top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: var(--text-2); pointer-events: none;
}
.searchbar .input { padding-left: calc(var(--s-3) * 2 + 16px); }

.results-bar { min-height: 32px; margin-bottom: var(--s-4); }
.result-count { font: 500 var(--t-micro)/1 var(--font-mono); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-2); }

/* ==========================================================================
   page: product
   ========================================================================== */
.product-layout { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: var(--s-8); align-items: start; }
.breadcrumb { display: flex; gap: var(--s-2); align-items: center; flex-wrap: wrap; font-size: var(--t-sm); color: var(--text-2); margin-bottom: var(--s-5); min-height: 20px; }
.breadcrumb a { color: var(--text-2); }
@media (hover: hover) { .breadcrumb a:hover { color: var(--accent-text); } }
.breadcrumb span[aria-current] { color: var(--text); }
/* The separator is structural, not decoration, so it clears AA like the
   links either side of it rather than sitting at hairline weight. */
.breadcrumb .sep { color: var(--text-2); }
.breadcrumb--top { padding-top: var(--s-6); }

.gallery__main {
  aspect-ratio: 1; background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--r-lg);
  overflow: hidden; position: relative;
}
.gallery__main img { width: 100%; height: 100%; object-fit: cover; }
.gallery__thumbs { display: flex; gap: var(--s-2); margin-top: var(--s-3); flex-wrap: wrap; }
.gallery__thumb {
  width: 64px; height: 64px; border-radius: var(--r-md); overflow: hidden;
  border: 1px solid var(--rule); background: var(--surface); padding: 0; cursor: pointer;
}
.gallery__thumb img { width: 100%; height: 100%; object-fit: cover; }
.gallery__thumb[aria-current="true"] { border-color: var(--amber); }

.buybox { position: sticky; top: calc(var(--header-h) + var(--s-5)); }
.prose { font-size: var(--t-sm); color: var(--text-2); line-height: var(--lh-body); white-space: pre-line; max-width: 68ch; }
.product-desc { margin-top: var(--s-6); border-top: 1px solid var(--rule); padding-top: var(--s-5); }
.product-facts { border-top: 1px solid var(--rule); padding-top: var(--s-4); }

/* ==========================================================================
   page: quote — the one dark surface, and the signature layer-scan
   ========================================================================== */
.quote-layout { display: grid; grid-template-columns: 1.12fr 0.88fr; gap: var(--s-6); align-items: start; }

.dropzone {
  position: relative;
  display: grid; place-items: center; text-align: center;
  padding: var(--s-8) var(--s-5);
  border: 1px dashed var(--rule); border-radius: var(--r-lg);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
@media (hover: hover) { .dropzone:hover { border-color: var(--text-2); } }
.dropzone.is-over { border-color: var(--amber); border-style: solid; background: var(--amber-wash); }
.dropzone.is-rejected { border-color: var(--danger); border-style: solid; background: var(--danger-wash); }
.dropzone:focus-visible { box-shadow: var(--ring); }
.dropzone svg.dz-icon { width: 34px; height: 34px; color: var(--accent-text); margin: 0 auto var(--s-4); }
.dropzone h3 { font-size: var(--t-md); margin-bottom: var(--s-2); }
.dropzone p { font-size: var(--t-sm); color: var(--text-2); }
.dropzone input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }

.progress { height: 3px; border-radius: var(--r-pill); background: var(--rule); overflow: hidden; }
.progress__bar { height: 100%; width: 0%; background: var(--amber); border-radius: var(--r-pill); transition: width 120ms linear; }

/* --- the viewport: the single justified dark moment ---------------------- */
.viewport {
  background: var(--ink);
  border-radius: var(--r-lg);
  overflow: hidden;
  color: var(--paper);
}
.viewer {
  position: relative; aspect-ratio: 4 / 3; min-height: 260px;
  background: radial-gradient(72% 62% at 50% 34%, var(--ink-2), var(--ink) 76%);
}
.viewer canvas { width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
.viewer canvas:active { cursor: grabbing; }
.viewer canvas:focus-visible { box-shadow: var(--ring-dark); }
.viewer__hint {
  position: absolute; left: var(--s-4); bottom: var(--s-4); pointer-events: none;
  font: 400 var(--t-micro)/1 var(--font-mono); letter-spacing: 0.04em;
  color: rgba(247, 244, 238, 0.52);
}
.viewer__badge { position: absolute; right: var(--s-4); top: var(--s-4); background: rgba(247,244,238,0.10); color: rgba(247,244,238,0.78); }
.viewer__fallback { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; padding: var(--s-5); }
.viewer__fallback svg { width: 44px; height: 44px; color: rgba(247,244,238,0.22); margin: 0 auto var(--s-3); }
.viewer__fallback p { color: rgba(247, 244, 238, 0.62); max-width: 40ch; }

/* --- Z-scrub: the layer readout under the viewport ----------------------- */
.zscrub {
  border-top: 1px solid rgba(247, 244, 238, 0.10);
  padding: var(--s-3) var(--s-4) var(--s-4);
}
.zscrub__read {
  display: flex; gap: var(--s-5); flex-wrap: wrap; margin-bottom: var(--s-1);
}
.zscrub__cell { display: flex; flex-direction: column; gap: 1px; min-width: 74px; }
.zscrub__k {
  font: 500 var(--t-micro)/1.4 var(--font-mono);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: rgba(247, 244, 238, 0.52);
}
.zscrub__v {
  font: 500 var(--t-sm)/1.4 var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--paper);
}
.zscrub__v em { font-style: normal; color: rgba(247, 244, 238, 0.52); }
.zscrub input[type="range"]::-webkit-slider-runnable-track {
  background: linear-gradient(to right, var(--amber) var(--fill, 100%), rgba(247,244,238,0.18) var(--fill, 100%));
}
.zscrub input[type="range"]::-moz-range-track { background: rgba(247,244,238,0.18); }
.zscrub input[type="range"]::-webkit-slider-thumb { border-color: var(--ink); }
.zscrub input[type="range"]::-moz-range-thumb { border-color: var(--ink); }
.zscrub input[type="range"]:focus-visible { box-shadow: var(--ring-dark); }

.file-chip {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--t-sm); max-width: 100%; min-width: 0;
}
.file-chip svg { width: 15px; height: 15px; color: var(--accent-text); flex: none; }
.file-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); }
.model-head { border-bottom: 1px solid var(--rule); padding-bottom: var(--s-4); }
.upload-progress { margin-top: var(--s-4); }

.price-card { position: sticky; top: calc(var(--header-h) + var(--s-5)); }
.price-hero { border-bottom: 1px solid var(--rule); padding-bottom: var(--s-5); }
.price-hero__k { font: 500 var(--t-micro)/1 var(--font-mono); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-2); margin-bottom: var(--s-3); }
.price-hero__v { font: 600 var(--t-2xl)/1 var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.045em; }
.price-hero__u { font: 400 var(--t-sm)/1 var(--font-mono); color: var(--text-2); margin-top: var(--s-2); min-height: 1em; }

/* Recalculating keeps the old number legible — never collapses to a spinner. */
.is-stale { opacity: 0.38; transition: opacity var(--dur) var(--ease); }

.price-details { margin-top: var(--s-5); }
.est-list { border-top: 1px solid var(--rule); margin-top: var(--s-4); padding-top: var(--s-3); }
.est-list dt, .est-list dd { color: var(--text-2); font-size: var(--t-xs); }
#price-error:empty { display: none; }
#price-error { margin-top: var(--s-4); }
#price-body > .btn { margin-top: var(--s-5); }

/* ==========================================================================
   page: cart / checkout
   ========================================================================== */
.cart-layout { display: grid; grid-template-columns: 1fr 330px; gap: var(--s-7); align-items: start; }
.summary { position: sticky; top: calc(var(--header-h) + var(--s-5)); }

.line-item { display: grid; grid-template-columns: 76px 1fr auto; gap: var(--s-4); padding: var(--s-5) 0; border-bottom: 1px solid var(--rule); align-items: start; }
.line-items > .line-item:first-child { padding-top: 0; }
.line-item:last-child { border-bottom: 0; padding-bottom: 0; }
.line-item__thumb { width: 76px; height: 76px; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--rule); background: var(--surface); display: grid; place-items: center; }
.line-item__thumb img { width: 100%; height: 100%; object-fit: cover; }
.line-item__thumb svg { width: 30px; height: 30px; color: var(--rule); }
.line-item__name { font-family: var(--font-display); font-weight: 600; font-size: var(--t-md); letter-spacing: -0.025em; }
.line-item__meta { font: 400 var(--t-xs)/1.5 var(--font-mono); color: var(--text-2); margin-top: 2px; }
.line-item__ctrl { display: flex; align-items: center; gap: var(--s-4); margin-top: var(--s-3); flex-wrap: wrap; }
.line-item__right { text-align: right; display: flex; flex-direction: column; gap: var(--s-1); align-items: flex-end; }

.ship-hint { display: flex; flex-direction: column; gap: var(--s-2); font-size: var(--t-sm); color: var(--text-2); }
.ship-hint__bar { height: 3px; border-radius: var(--r-pill); background: var(--rule); overflow: hidden; }
.ship-hint__fill { display: block; height: 100%; background: var(--amber); border-radius: var(--r-pill); transition: width var(--dur) var(--ease); }
.ok-text { color: var(--ok-text); }
.ok-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); flex: none; }

.steps-bar { font: 500 var(--t-micro)/1 var(--font-mono); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-2); }
.steps-bar b { color: var(--accent-text); font-weight: 500; }

.mini-lines { border-bottom: 1px solid var(--rule); padding-bottom: var(--s-3); margin-bottom: var(--s-1); }
.mini-line { display: flex; justify-content: space-between; gap: var(--s-3); padding: var(--s-2) 0; align-items: baseline; }
.mini-line__n { font-size: var(--t-sm); font-weight: 500; }
.mini-line__m { font: 400 var(--t-micro)/1.5 var(--font-mono); color: var(--text-2); }
.mini-line__p { font-size: var(--t-sm); white-space: nowrap; }
.mini-line__p .faint { color: var(--text-2); }

/* ==========================================================================
   page: order
   ========================================================================== */
.order-hero { padding-block: var(--s-6) var(--s-7); border-bottom: 1px solid var(--rule); }
.order-hero__icon { width: 34px; height: 34px; color: var(--ok-text); margin-bottom: var(--s-4); }
.order-number { font: 600 var(--t-xl)/1 var(--font-mono); letter-spacing: -0.03em; }
.order-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--s-7); align-items: start; margin-top: var(--s-7); }
.address-block { font-size: var(--t-sm); color: var(--text-2); line-height: 1.7; }

/* ==========================================================================
   responsive
   ========================================================================== */
@media (max-width: 1000px) {
  .hero__inner { grid-template-columns: 1fr; gap: var(--s-6); }
  .cover__inner, .offer, .specimen, .machine { grid-template-columns: 1fr; gap: var(--s-6); }
  .cover { padding-block: var(--s-6) var(--s-7); }
  .product-layout, .quote-layout, .cart-layout, .order-grid { grid-template-columns: 1fr; }
  .buybox, .summary, .price-card, .filter-rail { position: static; }
  .shop-layout { grid-template-columns: 1fr; gap: var(--s-6); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 720px) {
  .wrap { padding-inline: var(--s-4); }
  .stratum { padding-block: var(--s-6) var(--s-7); }
  .hero { padding-block: var(--s-6) var(--s-6); }
  .nav {
    display: none; position: absolute; top: var(--header-h); left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0; margin: 0;
    background: var(--page); border-bottom: 1px solid var(--rule);
    padding: var(--s-2) var(--s-4) var(--s-4);
  }
  .nav.is-open { display: flex; }
  .nav a { padding: var(--s-3) 0; font-size: var(--t-md); border-bottom: 1px solid var(--rule); }
  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin-left: auto;
    background: none; border: 1px solid var(--rule);
    border-radius: var(--r-md); cursor: pointer; color: var(--text);
  }
  .nav-toggle svg { width: 18px; height: 18px; }
  .header-actions { margin-left: var(--s-2); gap: var(--s-2); }
  .product-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--s-5) var(--s-3); }
  .form-grid { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; gap: var(--s-5); }
  .cta-band { padding: var(--s-5) var(--s-4); }
  .line-item { grid-template-columns: 62px 1fr; }
  .line-item__thumb { width: 62px; height: 62px; }
  .line-item__right { grid-column: 2; flex-direction: row; justify-content: space-between; align-items: baseline; width: 100%; }
  .card { padding: var(--s-4); }
  .card__body { padding: var(--s-4); }
  .toasts { left: var(--s-4); right: var(--s-4); bottom: var(--s-4); max-width: none; }
  .zscrub__read { gap: var(--s-4); }
}

@media (max-width: 720px) {
  .mat-row { grid-template-columns: 1fr; gap: var(--s-2); }
  .plate__leaf { padding: var(--s-2); }
  .offer__strip .product-grid { grid-template-columns: repeat(auto-fill, minmax(116px, 1fr)); }
}

@media (max-width: 380px) {
  .product-grid { grid-template-columns: 1fr; }
  .offer__strip .product-grid { grid-template-columns: 1fr 1fr; }
  .segmented label { min-width: 0; flex-basis: 30%; }
  .zscrub__cell { min-width: 62px; }
  .plate__cap { gap: var(--s-4); }
}

/* ==========================================================================
   reduced motion — the layer-scan build is skipped in JS; here we flatten
   everything else.
   ========================================================================== */
/* Compact controls keep their visual size but grow to the 44px touch floor
   where the pointer is a finger. */
@media (pointer: coarse) {
  .btn--sm, .lang-switch__btn, .nav a, .cart-link, .link-btn { min-height: 44px; }
  .lang-switch__btn { min-width: 44px; }
  /* Footer and brand links sit at text height (15px / 28px) on a fine pointer,
     well under the touch floor. inline-flex so the grown box is hit-testable;
     the existing list gap is dropped because the links now supply the rhythm. */
  .footer-grid a, .footer-bottom a, .brand, .offer__more {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .footer-grid li + li { margin-top: 0; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .skeleton::after { display: none; }

  /* The page turn is disabled outright, not merely shortened: the navigation
     simply happens, which is what the preference asks for. */
  @view-transition { navigation: none; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; }
}

/* ==========================================================================
   page: order — details
   ========================================================================== */
.order-hero__meta { margin-top: var(--s-4); }
.order-thanks { margin-top: var(--s-4); }
.order-thanks-text { margin-top: var(--s-2); max-width: 62ch; }
.order-section-head { padding-bottom: var(--s-3); border-bottom: 1px solid var(--rule); margin-bottom: var(--s-2); }
.order-totals { border-top: 1px solid var(--rule); margin-top: var(--s-4); padding-top: var(--s-4); }
.line-item--order { grid-template-columns: 1fr auto; }
.lookup-card { max-width: 420px; }

/* The order number carries the whole relationship now — there is no
   confirmation e-mail behind it — so it is set large and sits next to its own
   copy control rather than being something to transcribe by hand. */
.order-number-row {
  display: flex; align-items: center; gap: var(--s-4);
  flex-wrap: wrap; margin-top: var(--s-1);
}
.order-copy { flex: none; }
.order-copy svg { width: 15px; height: 15px; }

.order-keep {
  display: flex; align-items: flex-start; gap: var(--s-2);
  margin-top: var(--s-4); max-width: 62ch;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--rule); border-radius: var(--r-md);
  background: var(--surface);
}
.order-keep svg { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--accent-text); }

.plain-list { list-style: none; margin: var(--s-3) 0 0; padding: 0; }
.plain-list li + li { margin-top: var(--s-2); }
.order-contact { font-size: var(--t-sm); }

/* checkbox line — used across the admin forms */
.checkline { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-sm); color: var(--text); min-height: 44px; cursor: pointer; }
.checkline input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--amber); flex: none; }
.pager__page[disabled] { opacity: 0.3; cursor: not-allowed; }

/* ==========================================================================
   page: facts — the article (tone 2)

   The one page where the encyclopedia metaphor is literal: an entry with a
   plate, a chronology, marginal notes and hairline rules carrying mono
   eyebrows. Rung 2 ornament only — hairlines and figures, no atmosphere
   layers, no scroll theatre. The running measure is held at 60–75ch; the
   margin column carries notes and the faint blueprint figures.
   ========================================================================== */
.article { display: block; }

/* --- the opening plate ---------------------------------------------------- */
.fx-open {
  display: grid; grid-template-columns: 1.02fr 0.98fr;
  gap: var(--s-8); align-items: center;
  padding-block: var(--s-7) var(--s-8);
}
.fx-title {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: var(--lh-tight);
  margin-block: var(--s-4) var(--s-5);
  max-width: 16ch;
}
.fx-standfirst {
  font-size: var(--t-md); line-height: 1.55; max-width: 52ch;
  margin-top: var(--s-5);
}
.fx-plate .plate__leaf { box-shadow: 0 16px 34px -28px rgba(12, 27, 42, .55); }

/* Plate and figure captions: mono, the way a real plate is captioned. */
.fx-figcap {
  margin-top: var(--s-3); padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
  font: 400 var(--t-micro)/1.6 var(--font-mono);
  color: var(--text-2);
}

/* --- contents ------------------------------------------------------------- */
.fx-toc { margin-top: var(--s-6); border-top: 1px solid var(--rule); padding-top: var(--s-3); }
.fx-toc ol { margin-top: var(--s-2); }
.fx-toc li + li { border-top: 1px solid var(--rule); }
.fx-toc a {
  display: block; padding-block: var(--s-2);
  font-size: var(--t-sm); font-weight: 500; color: var(--text);
}
@media (hover: hover) { .fx-toc a:hover { color: var(--accent-text); } }

/* --- the two-column article grid ------------------------------------------
   A reading measure on the left, marginalia on the right. The margin column
   is never load-bearing: it collapses under the body copy on narrow screens. */
.fx-cols {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 15.5rem);
  gap: var(--s-7) var(--s-8); align-items: start;
}
/* The running measure: 76ch at the body size leaves the prose inside it —
   which sets its own 62ch cap at 17px — between 62 and 66 characters. */
.fx-body { max-width: 76ch; }
.fx-body > * + * { margin-top: var(--s-5); }
.fx-lede { font-size: var(--t-md); color: var(--text-2); line-height: 1.55; max-width: 66ch; }

.fx-margin { display: grid; gap: var(--s-6); }

/* Marginal note — it has to carry something the running text does not. */
.fx-note {
  border-left: 2px solid var(--amber-edge);
  padding-left: var(--s-4);
  font-size: var(--t-sm); line-height: var(--lh-body); color: var(--text-2);
}
.fx-note .spec-label { display: block; margin-bottom: var(--s-2); }
.fx-note__link {
  display: inline-block; margin-top: var(--s-3);
  font-size: var(--t-sm); font-weight: 600;
}

/* The blueprint line art, used as faint plate figures. Alpha and tint are
   baked into the asset — no layer-wide opacity here. */
.fx-bp { margin: 0; max-width: 220px; }
.fx-bp img { width: 100%; height: auto; }

/* --- chronology -----------------------------------------------------------
   Genuinely a sequence, so the labels are the dates themselves. */
.chron { border-top: 1px solid var(--rule); }
.chron__item {
  display: grid; grid-template-columns: 4.75rem minmax(0, 1fr);
  gap: var(--s-4); align-items: baseline;
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--rule);
}
.chron__y {
  font: 600 var(--t-sm)/1.5 var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  color: var(--text);
}
.chron__d { font-size: var(--t-md); line-height: var(--lh-body); max-width: 62ch; }

/* --- materials: editorial prose, live figures ----------------------------- */
.fx-fig { margin: 0; }
.fx-fig img { width: 100%; height: auto; border: 1px solid var(--rule); border-radius: 2px; }

.fx-mats { border-top: 1px solid var(--rule); }
.fx-mat { padding-block: var(--s-5); border-bottom: 1px solid var(--rule); }
.fx-mat__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-4) var(--s-5); flex-wrap: wrap;
}
.fx-mat__name {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--t-md); letter-spacing: -0.03em;
}
/* Two mono lines, reserved so the figures landing from the API shift nothing. */
.fx-mat__fig {
  display: flex; flex-direction: column; gap: 2px;
  min-height: calc(2 * 1.7em);
  font: 500 var(--t-micro)/1.7 var(--font-mono);
  font-variant-numeric: tabular-nums; letter-spacing: 0.04em;
  color: var(--text-2);
  text-align: right;
}
.fx-mat__row { display: inline-flex; align-items: baseline; gap: var(--s-2); justify-content: flex-end; }
.fx-mat__k { text-transform: uppercase; }
.fx-mat__fig b { color: var(--text); font-weight: 600; }
.fx-mat__fig .sk-line { width: 130px; }
.fx-mat__d { margin-top: var(--s-3); font-size: var(--t-md); line-height: var(--lh-body); max-width: 62ch; }

/* --- labelled points: why / limits ---------------------------------------- */
.fx-points { border-top: 1px solid var(--rule); margin: 0; }
.fx-point { padding-block: var(--s-4); border-bottom: 1px solid var(--rule); }
.fx-point dt { margin-bottom: var(--s-2); }
.fx-point dd { margin: 0; font-size: var(--t-md); line-height: var(--lh-body); max-width: 62ch; }

@media (max-width: 1000px) {
  .fx-open { grid-template-columns: 1fr; gap: var(--s-6); padding-block: var(--s-6) var(--s-7); }
  .fx-cols { grid-template-columns: 1fr; gap: var(--s-6); }
  .fx-margin { grid-auto-flow: row; }
  .fx-title { max-width: none; }
}

@media (max-width: 560px) {
  .chron__item { grid-template-columns: 1fr; gap: var(--s-1); }
  .fx-mat__fig { text-align: left; }
  .fx-mat__row { justify-content: flex-start; }
  .fx-bp { max-width: 180px; }
}

/* The touch floor applies to the article's own links too. */
@media (pointer: coarse) {
  .fx-toc a, .fx-note__link { display: flex; align-items: center; min-height: 44px; }
}

/* ==========================================================================
   FILM — generated motion, used twice and gated hard.

   Both elements are decorative: nothing the page has to say lives only in a
   video. The posters are real files, so each figure is complete before any
   video arrives and identical if none ever does — no JS, preload="none",
   reduced motion, or a codec the browser refuses. Neither autoplays from
   markup; film.js is the only thing that starts them.
   ========================================================================== */

/* The cover film sits exactly where the emboss sits and plays the same role:
   weather behind the type, never the subject.

   Opacity .20 is measured, not chosen. The ungraded clip blows its nozzle glow
   to pure white (luminance 1.00), which caps the safe opacity at .034 — a layer
   nobody can see. The shipped file is graded to a 0.162 peak, lifting the
   ceiling for the cover lede (#93A7BC) to .224. Regrade before raising this. */
.cover-film {
  position: fixed;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .20;
  pointer-events: none;
  display: none;              /* film.js opts in, once the file is seekable */
}
.cover-film[data-film="on"] { display: block; }

/* Replaces a still of the same frame, so the figure must not move when it
   swaps in: same box, same ratio, ink behind it while it decodes. */
.machine__film {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  /* No film at all: the cover keeps its embossed cloth, and the machine figure
     keeps its poster — which is the still it replaced. */
  .cover-film { display: none !important; }
}

/* --- the printed wordmark ------------------------------------------------
   The canvas replaces the type only once logo-print.js has decoded the image.
   Until then — and forever, without JS — the <h1> renders as type, so the cover
   never depends on the mark loading. The canvas keeps the type's own box, so
   swapping one for the other shifts nothing. */
.wordmark { position: relative; }
.wordmark__print { display: none; }

.wordmark[data-print="on"] .wordmark__type {
  visibility: hidden;                  /* keeps the box, releases the pixels */
}
.wordmark[data-print="on"] .wordmark__print {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

@media (prefers-reduced-motion: reduce) {
  /* No build, no canvas: the heading is the heading. */
  .wordmark__print { display: none !important; }
  .wordmark[data-print="on"] .wordmark__type { visibility: visible; }
}

/* The workshop behind the reference section (/facts, rung 0).

   Opacity .30 is measured the same way the cover film was: the clip is graded
   to a 0.0988 luminance peak, which puts the ceiling for --text-2 (#93A7BC) at
   .385 against 4.5:1. .30 keeps headroom. Regrade the file before raising it. */
.page-film {
  position: fixed;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .30;
  pointer-events: none;
  display: none;                /* film.js opts in when motion is allowed */
}
.page-film[data-film="on"] { display: block; }

@media (prefers-reduced-motion: reduce) {
  .page-film { display: none !important; }
}
