/* ============================================================
   KAPEX — base layer
   Light, geometric, Ondo-adjacent surface. Serif is reserved for
   the hero line only; everything else is the grotesque.
   ============================================================ */

/* Fonts are self-hosted, on this origin and this connection. Linking them
   from a third party put a DNS lookup, a TLS handshake and a round trip in
   front of first paint, for files that were already sitting in fonts/. */
@font-face{
  font-family:'Outfit';
  font-style:normal;
  font-weight:200 700;
  font-display:swap;
  src:url(fonts/outfit-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Newsreader';
  font-style:italic;
  font-weight:300 400;
  font-display:swap;
  src:url(fonts/newsreader-italic-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'JetBrains Mono';
  font-style:normal;
  font-weight:400 500;
  font-display:swap;
  src:url(fonts/jetbrains-mono-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root{
  /* ink & paper */
  --paper:#ffffff;
  --paper-2:#f4f4f2;
  --paper-3:#ebebe8;
  --white:#ffffff;
  --ink:#0a0a0a;
  --ink-2:#3d3d3d;
  --ink-3:#6b6b6b;
  --line:rgba(10,10,10,.12);
  --line-soft:rgba(10,10,10,.07);

  /* night surfaces */
  --night:#000000;
  --night-2:#111112;
  --night-3:#1c1c1e;
  --night-line:rgba(255,255,255,.14);

  /* product accents */
  --a1:#7c4dff;
  --a1-soft:#efe9ff;
  --a2:#3b6fe0;
  --a2-soft:#e7eeff;
  --a3:#12996b;
  --a3-soft:#e2f4ec;
  --acc:var(--a1);

  /* the accents again, darkened, for when the accent carries TEXT. The
     bright values are tuned as fills and rules; as ink on their own soft
     tint they measure 3.2:1 to 4.1:1, and small type needs 4.5:1. */
  --a1-ink:#6a3ad9;
  --a2-ink:#2f57b8;
  --a3-ink:#0b6e4c;

  /* type */
  --sans:'Outfit',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --serif:'Newsreader',Georgia,'Times New Roman',serif;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  /* metrics */
  --shell:1440px;
  --gut:clamp(20px,4.4vw,64px);
  --band:clamp(72px,8vw,120px);

  /* Two padded bands in a row read as one huge void. Every section pays a
     full band on top and a half band underneath, so the seam between any
     two of them is 1.5 bands, not 2. The night band pays less on both
     counts, deliberately: it is the only full-bleed black on the page and
     a dark ground supplies its own containment, so it does not need the
     separation a white section needs from the one above it. Four numbers,
     and every section spends one of them — no section carries a literal. */
  --band-t:var(--band);
  --band-b:calc(var(--band) * .55);
  --band-t-dark:calc(var(--band) * .76);
  --band-b-dark:calc(var(--band) * .52);

  --nav-h:58px;
  --r:12px;
  --r-card:20px;
  --r-pill:999px;
  --sq:52px;

  /* motion */
  --e-out:cubic-bezier(.16,1,.3,1);
  --e-io:cubic-bezier(.65,0,.35,1);
}

*,*::before,*::after{box-sizing:border-box}

html{-webkit-text-size-adjust:100%;scroll-behavior:auto}

body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--sans);
  font-size:17px;
  line-height:1.5;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
  overflow-x:clip;
}

img,svg,video,canvas{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
ul,ol{margin:0;padding:0;list-style:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
h1,h2,h3,h4{margin:0;font-weight:500;letter-spacing:-.025em;line-height:1.05}
p{margin:0}
::selection{background:var(--ink);color:var(--paper)}

/* ── shell ───────────────────────────────────────────────── */

.shell{width:100%;max-width:var(--shell);margin-inline:auto;padding-inline:var(--gut)}
.shell--wide{max-width:1680px}

/* ── type scale ───────────────────────────────────────────
   Grotesque throughout. The hero is the one place a serif is
   allowed, and it opts in explicitly with .t-serif.          */

.t-display{font-size:clamp(46px,7.6vw,104px);font-weight:500;letter-spacing:-.03em;line-height:1.02}
.t-h1{font-size:clamp(36px,4.1vw,56px);font-weight:500;letter-spacing:-.03em;line-height:1.05}
.t-h2{font-size:clamp(28px,2.9vw,40px);font-weight:500;letter-spacing:-.02em;line-height:1.05}
.t-h3{font-size:clamp(21px,2vw,28px);font-weight:500;letter-spacing:-.02em;line-height:1.1}
.t-lead{font-size:20px;line-height:1.35;color:var(--ink-2);font-weight:400;letter-spacing:-.01em}
.t-body{font-size:17px;line-height:1.45;color:var(--ink-2);font-weight:400}
.t-meta{font-size:18px;font-weight:400;letter-spacing:-.01em;color:var(--ink-3)}
.t-num{font-family:var(--mono);font-variant-numeric:tabular-nums}
.t-tone{color:var(--ink-3)}
.t-dim{color:var(--ink-3)}

/* the serif, opted into — hero only */
.t-serif{font-family:var(--serif);font-weight:300;letter-spacing:-.025em}
.t-em{font-style:italic}

/* ── rules and section marks ─────────────────────────────── */

.rule{height:1px;background:var(--line);border:0;margin:0}

/* ── buttons ─────────────────────────────────────────────── */

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:48px;padding:0 24px;border-radius:var(--r-pill);
  font-size:16px;font-weight:500;letter-spacing:-.01em;white-space:nowrap;
  border:1px solid transparent;
  transition:background .28s var(--e-out),color .28s var(--e-out),
             border-color .28s var(--e-out),transform .28s var(--e-out);
}
.btn--dark{background:var(--ink);color:var(--paper)}
.btn--dark:hover{background:#232323;transform:translateY(-1px)}
.btn--light{background:var(--paper-2);color:var(--ink)}
.btn--light:hover{background:var(--paper-3)}
.btn--ghost{border-color:var(--line);color:var(--ink)}
.btn--ghost:hover{border-color:var(--ink)}
.btn--onnight{background:rgba(255,255,255,.94);color:var(--night)}
.btn--onnight:hover{background:#fff}
.btn--accent{background:var(--acc);color:#fff}
.btn--accent:hover{filter:brightness(1.08)}

.link{
  display:inline-flex;align-items:center;gap:8px;
  font-size:15px;font-weight:500;
  border-bottom:1px solid var(--line);padding-bottom:2px;
  transition:border-color .25s var(--e-out),color .25s var(--e-out);
}
.link span{transition:transform .25s var(--e-out)}
.link:hover{border-color:var(--acc);color:var(--acc)}
.link:hover span{transform:translateX(3px)}

/* ── spec rows (used inside cards, not as the page's look) ── */

.spec{display:grid;gap:0;border-top:1px solid var(--line-soft)}
.spec__row{
  display:grid;grid-template-columns:minmax(0,.42fr) minmax(0,1fr);
  gap:18px;padding:12px 0;border-bottom:1px solid var(--line-soft);
}
.spec__k{
  font-size:16px;color:var(--ink-3);padding-top:2px;
}
.spec__v{font-size:17px;color:var(--ink)}

/* ── placeholder skins ───────────────────────────────────── */
/* Everything that will be photography renders as an explicit,
   labelled placeholder frame with a photo mark in the corner.  */

.ph{
  position:relative;overflow:hidden;
  background:linear-gradient(135deg,var(--paper-2) 0%,var(--paper-3) 100%);
}
.ph--night{background:linear-gradient(135deg,#17171a 0%,#0b0b0d 100%)}

/* the corner label */
.ph::after{
  content:attr(data-ph);
  position:absolute;inset:auto 14px 12px auto;
  font-size:13px;letter-spacing:.01em;color:rgba(10,10,10,.5);
}
.ph--night::after{color:rgba(255,255,255,.62)}

/* a photo frame mark, so an empty block reads as "image goes here" */
.ph--photo::before{
  content:"";position:absolute;left:50%;top:50%;
  width:clamp(26px,7%,44px);aspect-ratio:4/3;
  transform:translate(-50%,-50%);
  border:1px solid rgba(10,10,10,.22);border-radius:3px;
  background:
    linear-gradient(135deg,transparent 54%,rgba(10,10,10,.16) 54% 62%,transparent 62%),
    radial-gradient(circle at 30% 32%,rgba(10,10,10,.22) 0 2.2px,transparent 2.3px);
}
.ph--night.ph--photo::before{
  border-color:rgba(255,255,255,.3);
  background:
    linear-gradient(135deg,transparent 54%,rgba(255,255,255,.22) 54% 62%,transparent 62%),
    radial-gradient(circle at 30% 32%,rgba(255,255,255,.3) 0 2.2px,transparent 2.3px);
}

/* ── scroll-scene primitives ─────────────────────────────── */

.scene{position:relative}
.scene__stage{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden}

.js .rv{opacity:0;transform:translateY(22px);
  transition:opacity .8s var(--e-out),transform .8s var(--e-out)}
.js .rv.in{opacity:1;transform:none}

/* ── numeric roller ──────────────────────────────────────── */

.roll{display:inline-flex;overflow:hidden;line-height:1;vertical-align:baseline}
.roll__col{overflow:hidden;height:1em}
.roll__strip{display:flex;flex-direction:column;transition:transform 1.6s var(--e-out)}
.roll__strip span{height:1em;display:block}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important}
  .js .rv{opacity:1;transform:none}
}


/* ── focus ─────────────────────────────────────────────────
   One authored indicator for every interactive element; the
   accent ring reads on paper and on the navy bands alike.    */
:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--acc);
  outline-offset:3px;
  border-radius:3px;
}
.ph--night :focus-visible,
[class*="--night"] :focus-visible{outline-color:#fff}

/* the skip link moves focus to main, which is programmatic, so it never
   matches :focus-visible and must not draw a ring around the whole page */
main:focus{outline:none}

/* anchors land below the fixed chrome */
:where(main) > [id]{scroll-margin-top:calc(var(--ann-h,52px) + var(--nav-h) + 16px)}

/* and so does anything tabbed to inside them: the rule above only covers
   the section boxes, so Shift+Tab was parking controls under the pill */
:where(main) :where(a,button,input,select,textarea,[tabindex]){
  scroll-margin-top:calc(var(--nav-h) + 24px);
  scroll-margin-bottom:24px;
}

/* skip link */
.skip{
  position:fixed;top:8px;left:8px;z-index:80;
  transform:translateY(-160%);
  background:var(--ink);color:var(--paper);
  padding:12px 18px;border-radius:var(--r);
  font-size:15px;font-weight:500;
  transition:transform .25s var(--e-out);
}
.skip:focus{transform:none}


/* stand-in photography: a real image fills the slot, the corner label still
   names what belongs there so nobody mistakes it for final art */
.ph[data-img]{background:#e8e8e6}
.ph[data-img]::before{display:none}
.ph__img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block;
}
.ph[data-img]::after{
  background:rgba(10,10,10,.55);color:rgba(255,255,255,.9);
  padding:4px 9px;border-radius:4px;
}
/* the hero tiles and the case shots carry no data-ph, but a padded, filled
   chip with empty content still paints an 18x8 blob in the photo's corner */
.ph:not([data-ph])::after{content:none}




/* ============================================================
   Chrome: announcement rail + header that collapses into a pill
   ============================================================ */


/* ── header ──────────────────────────────────────────────── */


/* The header rides from under the announcement rail up to the top edge.
   That is a pure translation, so it is one transform — no layout. */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:50;
  transition:transform .5s var(--e-out);
  pointer-events:none;
}
.nav > *{pointer-events:auto}

.nav__pill{
  display:flex;align-items:center;gap:24px;
  width:100%;max-width:none;margin-inline:auto;
  height:var(--nav-h);padding-inline:var(--gut);
  border-radius:0;
  background:transparent;
  color:#fff;
  /* max-width and padding-inline ARE the collapse — the pill is narrower
     and tighter than the full-bleed bar, and no transform expresses that
     without distorting the type. They run once per threshold crossing on a
     fixed, out-of-flow element, not per frame. Height is deliberately not
     animated: it stays constant so the bar never jumps vertically. */
  transition:max-width .55s var(--e-out),padding-inline .55s var(--e-out),
             background .45s var(--e-out),border-radius .55s var(--e-out),
             color .45s var(--e-out),box-shadow .5s var(--e-out);
}

.nav__brand{display:inline-flex;align-items:center;gap:10px;color:inherit;flex:none}
.nav__mark{width:24px;height:24px}
.nav__word{font-size:20px;font-weight:600;letter-spacing:-.01em}

.nav__links{display:flex;gap:30px;margin-inline:auto}
.nav__links a{font-size:16px;font-weight:500;color:inherit;opacity:.9;transition:opacity .25s var(--e-out)}
.nav__links a:hover{opacity:1}

.nav__cta{flex:none}

/* collapsed state: a floating black pill, centred */
.nav.is-pill{transform:translateY(10px)}
.nav.is-pill .nav__pill{
  max-width:min(1080px,calc(100% - 2*var(--gut)));
  padding-inline:10px 10px;
  padding-left:22px;
  border-radius:12px;
  background:var(--night);
  box-shadow:0 20px 46px -30px rgba(13,27,42,.7);
}

/* over light sections before collapsing (e.g. deep-linked) */
.nav.is-dark:not(.is-pill) .nav__pill{color:var(--ink)}
.nav.is-dark:not(.is-pill) .nav__cta{background:var(--ink);color:#fff}

.nav__burger{display:none;width:44px;height:44px;flex-direction:column;
  justify-content:center;gap:6px;padding:0;flex:none}
.nav__burger span{display:block;width:20px;height:1.6px;background:currentColor;margin-inline:auto;
  transition:transform .32s var(--e-out)}
.nav__burger.is-open span:nth-child(1){transform:translateY(3.8px) rotate(45deg)}
.nav__burger.is-open span:nth-child(2){transform:translateY(-3.8px) rotate(-45deg)}

.nav__sheet{
  display:none;flex-direction:column;
  max-height:calc(100vh - var(--nav-h) - 24px);overflow-y:auto;
  margin:10px var(--gut) 0;padding:10px 18px 18px;
  background:var(--night);color:var(--paper);border-radius:var(--r-card);
}
.nav__sheet.is-open{display:flex}
.nav__sheet a{padding:15px 0;font-size:17px;border-bottom:1px solid rgba(255,255,255,.12)}
.nav__sheet-cta{
  margin-top:16px;border:0!important;background:var(--paper);color:var(--night);
  text-align:center;border-radius:var(--r);padding:15px 0!important;font-weight:500;
}

/* placeholder for a section that has not been built yet */
.pending{
  padding:120px 0;background:repeating-linear-gradient(45deg,#fafafa 0 12px,#f2f2f0 12px 24px);
  color:var(--ink-3);font-size:14px;letter-spacing:.08em;text-transform:uppercase;
}

.nav__scrim{
  position:fixed;inset:0;z-index:45;
  background:rgba(10,10,10,.45);
  backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
}
.nav__scrim[hidden]{display:none}

@media (max-width:1040px){
  .nav__links,.nav__cta{display:none}
  .nav__burger{display:flex;margin-left:auto}
  .nav.is-pill .nav__pill{max-width:calc(100% - 2*var(--gut));padding-inline:20px}
}


/* the header CTA is the reference's size, not the page button size — but
   the hero's own buttons do not appear until the collapse is three
   quarters done, so for the first thousand pixels of the page this is the
   only call to action on screen and it cannot be the smallest type on it */
.nav__cta{height:38px;padding:0 18px;border-radius:8px;font-size:16px}


/* ── hero ── */
/* ============================================================
   hero — sticky 220vh scene
   Three full-bleed material tiles collapse into a leaning stack
   while the serif headline parts in two halves and a warm-paper
   veil rises behind them. The ink flips navy-white → graphite.
   ============================================================ */

.hero{
  height:190vh;
  background:var(--night);
}

/* --tile is the *end-state* size of one tile. The outer tiles reach
   0.9 x --tile either side of centre (hero.js REACH), so the cluster
   is 1.8 x --tile wide — and the headline has to live outside that,
   inside the same content width. Sizing the two together is the whole
   game: see hero.js measure(). */
.hero__stage{
  background:var(--night);
  --tile:clamp(170px,17vw,286px);
}

/* ── paper veil (under the tiles, over the stage ground) ──── */

.hero__veil{
  position:absolute;inset:0;z-index:1;
  background:var(--paper);
  opacity:0;
  will-change:opacity;
}

/* measuring stick for the end-state tile size (--tile is a clamp()) */
.hero__probe{
  position:absolute;top:0;left:0;height:0;
  width:var(--tile);pointer-events:none;visibility:hidden;
}

/* ── material stack ──────────────────────────────────────── */

.hero__media{
  position:absolute;inset:0;z-index:2;
  display:grid;
  place-items:center;
}

/* --rad and --inv are written once per frame on the stage, not as a
   border-radius string on each tile: three full-bleed elements are
   the most expensive things on the page to re-style. */
/* A grid cell pins an over-sized item to its start edge instead of
   centring it, so the full-bleed tiles are positioned by hand. */
.hero__tile{
  position:absolute;left:50%;top:50%;
  width:var(--tfull,100vmax);height:var(--tfull,100vmax);
  overflow:hidden;
  border-radius:var(--rad,var(--sq));
  transform-origin:50% 50%;
  will-change:transform,opacity;
  backface-visibility:hidden;
}

/* one hairline of the commodity's own accent, so the three blocks
   read as three materials rather than three copies of one crop */
.hero__ph{
  width:100%;height:100%;
  border-radius:inherit;            /* the ring has to follow the corner */
  box-shadow:inset 0 0 0 1px var(--tint,var(--night-line));
}
.hero__tile--a .hero__ph{--tint:rgba(176,131,52,.7)}    /* brass  — gold       */
.hero__tile--b .hero__ph{--tint:rgba(47,107,79,.7)}     /* green  — fertilizer */
.hero__tile--c .hero__ph{--tint:rgba(69,96,122,.75)}    /* steel  — freight    */

/* The material label keeps its real size while the tile scales — and
   sits far enough in from the corner to clear the rounded arc. A point
   inset d from the corner of a radius-R round rect is inside the shape
   once d >= R * (1 - 1/sqrt2) ≈ 0.3R; at R = 44px that is ~13px, so
   base.css's 12/10 gets clipped and 20/18 does not.
   Each label also takes the one corner the next tile does not cover:
   the stack leans down-right, so a → top-left, b → bottom-left,
   c → bottom-right. */
.hero__tile .ph::after{
  color:rgba(245,242,236,.72);
  transform:scale(var(--inv,1));
}
.hero__tile--a .ph::after{inset:18px auto auto 20px;transform-origin:0 0}
.hero__tile--b .ph::after{inset:auto auto 18px 20px;transform-origin:0 100%}
.hero__tile--c .ph::after{inset:auto 20px 18px auto;transform-origin:100% 100%}

.hero__scrim{
  position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    linear-gradient(180deg,
      rgba(6,10,14,.78) 0%,
      rgba(6,10,14,.42) 30%,
      rgba(6,10,14,.34) 52%,
      rgba(6,10,14,.72) 100%),
    radial-gradient(72% 52% at 50% 48%, rgba(6,10,14,.46) 0%, rgba(6,10,14,0) 78%);
  will-change:opacity;
}

/* ── headline ────────────────────────────────────────────── */

.hero__copy{
  position:absolute;inset:0;z-index:3;
  display:flex;align-items:center;justify-content:center;
  padding-inline:var(--gut);
  pointer-events:none;
}

/* The halves are hung off the exact centre line, so one shared
   translation reads as a symmetrical split. The line is sized to fit
   *beside* the cluster, not to fill the viewport: at 1440 the halves
   and the cluster share one content width. --fit is the last-resort
   step-down hero.js applies when a half still would not clear the
   cluster (longer copy, an odd viewport, a fallback face). */
.hero__line{
  position:relative;
  width:100%;height:1em;
  font-size:calc(clamp(30px,3.5vw,56px) * var(--fit,1));
  letter-spacing:-.018em;
  white-space:nowrap;
  color:var(--paper);
}

.hero__half{
  position:absolute;top:0;
  display:block;
  will-change:transform;
}
.hero__half--l{right:50%;padding-right:.11em}
.hero__half--r{left:50%;padding-left:.11em}

/* ── sub copy + actions ──────────────────────────────────── */

.hero__sub{
  position:absolute;z-index:3;
  left:50%;top:var(--subY,64%);bottom:auto;
  width:min(58ch,calc(100% - 2*var(--gut)));
  transform:translate(-50%,40px);
  opacity:0;
  text-align:center;
  will-change:transform,opacity;
}

.hero__actions{
  /* above the rail and the cue, both of which are decoration pinned to
     the same floor; the script also reserves the rail's height so they
     do not share the strip in the first place */
  position:absolute;z-index:5;
  left:50%;top:var(--actY,76%);bottom:auto;
  transform:translate(-50%,40px);
  opacity:0;
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  justify-content:center;
  pointer-events:none;
  will-change:transform,opacity;
}
.hero__btn{min-width:186px}

/* ── scroll cue ──────────────────────────────────────────── */

.hero__cue{
  position:absolute;z-index:4;
  left:50%;bottom:118px;
  /* decorative and aria-hidden, so it must never be in front of a
     control: it is a wide box and it sits in the same strip the
     buttons land in on a short window */
  pointer-events:none;
  transform:translateX(-50%);
  display:flex;align-items:center;gap:12px;
  font-family:var(--mono);
  font-size:14px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(245,242,236,.62);
  white-space:nowrap;
}

/* The ring stays put and only the glyph moves, so the arrow always
   points down. The bob never fades out entirely: the cue has to be
   readable in a still. */
.hero__cue-arrow{
  display:grid;place-items:center;
  width:26px;height:26px;
  border:1px solid rgba(245,242,236,.3);
  border-radius:50%;
  font-size:14px;line-height:1;
}

.hero__cue-glyph{
  display:block;
  animation:hero__nudge 2.4s ease-in-out infinite;
}

@keyframes hero__nudge{
  0%,100%{transform:translateY(-3px);opacity:.55}
  50%    {transform:translateY(3px);opacity:1}
}

@media (prefers-reduced-motion:reduce){
  .hero__cue-glyph{animation:none;opacity:1}
}

/* ── port rail ───────────────────────────────────────────── */

.hero__rail{
  position:absolute;z-index:4;
  left:0;right:0;bottom:0;
  padding:0 0 32px;
  /* This was eating every click on the two hero buttons. The rail is a
     full-width box pinned to the floor of the stage, it is aria-hidden
     and decorative, and it comes after the actions in the DOM at the
     same z-index, so it won the hit test over both buttons at every
     viewport tested. Decoration does not take pointer events. */
  pointer-events:none;
  overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent);
}

/* even item count + a uniform pitch (margin, not gap) keeps the
   marquee's half-track wrap landing exactly on an item boundary */
.hero__rail-track{
  display:flex;align-items:center;
  width:max-content;
  will-change:transform;
}
.hero__rail-track > *{flex:none;margin-right:44px}

.hero__port{
  display:inline-flex;align-items:baseline;gap:9px;
  font-family:var(--mono);font-size:14px;letter-spacing:.1em;
  white-space:nowrap;
}
.hero__port b{
  font-weight:500;
  color:rgba(245,242,236,.76);
}
.hero__port i{
  font-style:normal;font-size:14px;letter-spacing:.06em;
  color:rgba(245,242,236,.4);
}

/* ── collapsed variant: narrow viewports and reduced motion ─ */

@media (max-width:1040px),(prefers-reduced-motion:reduce){

  .hero{height:auto;background:var(--paper)}

  .hero__stage{
    position:static;height:auto;overflow:visible;
    background:var(--paper);
    display:flex;flex-direction:column;align-items:center;gap:30px;
    /* clears both the fixed announcement rail and the header */
    padding:calc(var(--ann-h,44px) + var(--nav-h) + 30px) var(--gut) 44px;
  }

  .hero__veil,
  .hero__scrim{display:none}

  .hero__media{
    position:static;
    display:grid;grid-template-columns:repeat(3,1fr);
    gap:10px;width:100%;max-width:760px;
    place-items:stretch;
    order:4;
  }

  .hero__tile{
    position:static;                 /* the scene positions them by hand */
    grid-area:auto;
    width:auto;height:auto;aspect-ratio:1;
    border-radius:clamp(14px,4vw,var(--sq))!important;
    transform:none!important;
    opacity:1!important;
  }
  .hero__tile .ph::after{transform:none;inset:auto 10px 9px auto!important}

  .hero__copy{position:static;padding:0;order:1;display:block}

  .hero__line{
    position:static;width:auto;height:auto;
    white-space:normal;
    font-size:clamp(34px,8.4vw,60px);
    color:var(--ink)!important;
    text-align:center;
  }
  .hero__half{position:static;display:block;transform:none!important}
  .hero__half--l{padding-right:0}
  .hero__half--r{padding-left:0}

  .hero__sub{
    position:static;order:2;
    width:100%;max-width:52ch;
    transform:none!important;opacity:1!important;
  }

  .hero__actions{
    position:static;order:3;
    transform:none!important;opacity:1!important;
    pointer-events:auto!important;
    width:100%;
  }
  .hero__btn{min-width:0;flex:1 1 200px;max-width:280px}

  .hero__cue{display:none}

  .hero__rail{
    position:static;order:5;
    width:100%;padding:0;
    opacity:1!important;
  }
  .hero__port b{color:var(--ink-2)}
  .hero__port i{color:var(--ink-3)}
}

@media (max-width:520px){
  .hero__rail-track > *{margin-right:30px}
  .hero__btn{flex:1 1 100%;max-width:none}
}


/* ── conflict ── */
/* ============================================================
   2. conflict — the deadlock, the answer, the refusals.
   Three beats on three surfaces: tinted cards on paper (one accent
   each, two facing positions inside), the claim on a night panel
   with its consequence set beside it, then the stop-list as a
   ruled ledger on a soft band.
   ============================================================ */

.conflict{
  position:relative;
  background:var(--paper);
  padding-top:var(--band-t);
}

/* ── head ─────────────────────────────────────────────────── */

.conflict__head{padding-bottom:clamp(34px,4vw,58px)}

/* two authored lines. Each half is its own block so the break can
   never depend on collapsing whitespace between them. */
.conflict__title{max-width:none;text-wrap:pretty}
.conflict__title-a,
.conflict__title-b{display:block}

/* ── the three deadlocks ──────────────────────────────────── */

.conflict__cards{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(12px,1.5vw,20px);
  align-items:stretch;
}

.conflict__card{
  --acc:var(--a1);
  --acc-soft:var(--a1-soft);
  --acc-ink:var(--a1-ink);
  display:flex;
  flex-direction:column;
  min-width:0;
  padding:clamp(20px,2.1vw,28px);
  border-radius:var(--r-card);
  background:var(--acc-soft);
}
.conflict__card--a2{--acc:var(--a2);--acc-soft:var(--a2-soft);--acc-ink:var(--a2-ink)}
.conflict__card--a3{--acc:var(--a3);--acc-soft:var(--a3-soft);--acc-ink:var(--a3-ink)}

/* --acc is the card's fill and its pip; --acc-ink is the same accent
   where it has to be READ. On these tints the bright values measure
   4.07 / 3.98 / 3.17:1, and 16px type needs 4.5. */
.conflict__idx{
  display:flex;align-items:center;gap:10px;
  font-size:16px;font-weight:500;letter-spacing:-.01em;
  color:var(--acc-ink);
  font-variant-numeric:tabular-nums;
}
.conflict__pip{
  width:7px;height:7px;flex:none;border-radius:50%;
  background:var(--acc);
}

.conflict__ct{
  margin-top:clamp(14px,1.6vw,20px);
  margin-bottom:clamp(16px,1.8vw,22px);
  color:var(--ink);
}

/* the two positions, on a white sheet laid into the tint */
.conflict__face{
  display:flex;
  flex-direction:column;
  padding:clamp(16px,1.7vw,22px);
  border-radius:var(--r);
  background:var(--white);
}

.conflict__who{
  display:flex;align-items:center;gap:9px;
  font-size:16px;font-weight:500;letter-spacing:-.01em;
  color:var(--ink-3);
  margin-bottom:6px;
}
.conflict__who::before{
  content:"";
  width:9px;height:9px;flex:none;border-radius:50%;
}
/* filled = the side holding the goods, hollow = the side holding the money */
.conflict__who--p::before{background:var(--acc)}
.conflict__who--b::before{border:1.5px solid var(--ink-3)}

.conflict__say{
  font-size:17px;line-height:1.45;
  color:var(--ink-2);
}

/* the hairline between the two positions — drawn on scroll */
.conflict__split{
  display:block;height:1px;
  margin:clamp(14px,1.5vw,18px) 0;
  background:var(--line);
  transform:scaleX(var(--draw,1));
  transform-origin:left center;
  will-change:transform;
}
.js .conflict__card{--draw:0}

/* only one card carries a closing line; it sits on the floor of the
   sheet so all three sheets still end level */
.conflict__close{
  margin-top:clamp(14px,1.5vw,18px);
  padding-top:clamp(14px,1.5vw,18px);
  border-top:1px solid var(--line-soft);
  font-size:17px;line-height:1.45;font-weight:500;
  color:var(--ink);
}

/* the axis of the disagreement, as two opposed chips */
.conflict__axis{
  display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  margin-top:auto;
  padding-top:clamp(16px,1.8vw,22px);
}
.conflict__axis-a,
.conflict__axis-b{
  display:inline-flex;align-items:center;
  height:32px;padding:0 14px;border-radius:var(--r-pill);
  font-size:15px;font-weight:500;letter-spacing:-.01em;
  white-space:nowrap;
}
/* white on the bright green measured 3.62:1; the three chips take the
   ink value together so the row still reads as one device across cards */
.conflict__axis-a{background:var(--acc-ink);color:#fff}
.conflict__axis-b{
  background:var(--white);color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--line);
}
.conflict__axis-vs{font-size:15px;color:var(--ink-3)}

/* ── the punch: claim on night, consequence beside it ─────── */

.conflict__punch{
  margin-top:clamp(44px,5vw,80px);
  margin-bottom:clamp(44px,5vw,80px);
  border-radius:clamp(20px,2vw,28px);
  background:var(--night);
  color:var(--paper);
  padding:clamp(30px,4vw,64px);
  overflow:hidden;
}

.conflict__punch-in{
  display:grid;
  grid-template-columns:minmax(0,1.28fr) minmax(0,.72fr);
  align-items:stretch;
}

.conflict__claim{
  color:var(--paper);
  padding-right:clamp(24px,3vw,52px);
  text-wrap:pretty;
}
.conflict__claim-a{display:block;text-wrap:balance}
.conflict__claim-b{display:block;color:rgba(255,255,255,.62)}

.conflict__result{
  position:relative;
  display:flex;
  flex-direction:column;
  justify-content:center;
  padding-left:clamp(24px,3vw,52px);
}

/* the rule that joins the claim to what follows from it */
.conflict__stroke{
  position:absolute;left:0;top:0;bottom:0;width:1px;
  background:var(--night-line);
  transform:scaleY(var(--draw2,1));
  transform-origin:top center;
  will-change:transform;
}
.js .conflict__punch{--draw2:0}

/* three pips — one per deadlock above, all resolved by the line below */
.conflict__trio{display:flex;gap:6px;margin-bottom:clamp(16px,1.8vw,22px)}
.conflict__trio i{width:9px;height:9px;border-radius:50%;display:block}
.conflict__trio i:nth-child(1){background:var(--a1)}
.conflict__trio i:nth-child(2){background:var(--a2)}
.conflict__trio i:nth-child(3){background:var(--a3)}

.conflict__result-line{color:var(--paper);text-wrap:pretty}

/* ── the refusals ─────────────────────────────────────────── */





/* the struck square: a refusal, drawn as one */
.conflict__x{
  position:relative;
  width:38px;height:38px;flex:none;
  border:1px solid var(--line);
  border-radius:9px;
  margin-top:2px;
  overflow:hidden;
}
/* the strike runs corner to corner: bottom-left is its pivot, so it
   draws upward across the square as the row arrives */
.conflict__x i{
  position:absolute;left:0;bottom:0;width:142%;height:1px;
  background:var(--ink);
  transform:rotate(-45deg) scaleX(0);
  transform-origin:0 100%;
}


/* ── reduced motion: the end state, no drawing ────────────── */

@media (prefers-reduced-motion:reduce){
  .js .conflict__card{--draw:1}
  .js .conflict__punch{--draw2:1}
  .conflict__x i{transform:rotate(-45deg) scaleX(1)}
}

/* ── narrow ───────────────────────────────────────────────── */

/* One rail. The card keeps both positions, but now they sit beside
   each other and the hairline between them stands up — the same
   opposition, read across instead of down. */
@media (max-width:1040px){
  .conflict__cards{grid-template-columns:minmax(0,1fr);gap:clamp(12px,1.6vw,18px)}

  .conflict__face{flex-direction:row;flex-wrap:wrap;align-items:stretch}
  .conflict__pos{flex:1 1 0;min-width:0}
  .conflict__split{
    flex:0 0 1px;width:1px;height:auto;align-self:stretch;
    margin:0 clamp(18px,2.8vw,30px);
    transform:scaleY(var(--draw,1));
    transform-origin:top center;
  }
  .conflict__close{flex:1 0 100%}

  .conflict__punch-in{grid-template-columns:minmax(0,1fr);row-gap:clamp(26px,3.4vw,40px)}
  .conflict__claim{padding-right:0}
  .conflict__result{padding-left:0;padding-top:clamp(24px,3vw,34px)}
  .conflict__stroke{
    left:0;right:0;top:0;bottom:auto;width:auto;height:1px;
    transform:scaleX(var(--draw2,1));transform-origin:left center;
  }

    }

/* below this the two positions no longer take a column each */
@media (max-width:620px){
  .conflict__face{flex-direction:column;flex-wrap:nowrap;padding:18px}
  .conflict__pos{flex:0 0 auto}
  .conflict__close{flex:0 0 auto}
  .conflict__split{
    flex:none;width:auto;height:1px;align-self:auto;
    margin:clamp(14px,1.5vw,18px) 0;
    transform:scaleX(var(--draw,1));
    transform-origin:left center;
  }
}

@media (max-width:560px){
  .conflict__punch{
    margin-inline:0;
    padding:26px 22px 30px;
    border-radius:18px;
  }
    .conflict__x{width:32px;height:32px;border-radius:8px}
    .conflict__axis{gap:6px}
  .conflict__axis-a,
  .conflict__axis-b{height:30px;padding:0 12px}
}


/* ── commodities ── */
/* ============================================================
   4. commodities — sticky scene, 280vh, three stops
   Left rail accordion (38%) + right parameter panel (62%).
   The accent swaps with the active direction (--a1 → --a2 → --a3)
   and carries the panel: tray tint, badge, dots, tiles, bars.
   ============================================================ */

.commodities{
  height:280vh;
  background:var(--paper);
}

.commodities__stage{
  --acc:var(--a1);
  --acc-soft:var(--a1-soft);
  --acc-ink:var(--a1-ink);
  display:flex;
  background:var(--paper);
}
.commodities__stage[data-acc="2"]{--acc:var(--a2);--acc-soft:var(--a2-soft);--acc-ink:var(--a2-ink)}
.commodities__stage[data-acc="3"]{--acc:var(--a3);--acc-soft:var(--a3-soft);--acc-ink:var(--a3-ink)}

.commodities__shell{
  display:flex;
  flex-direction:column;
  width:100%;
  min-height:0;
  padding-top:calc(var(--nav-h) + 18px);
  padding-bottom:18px;
}

/* ── head ─────────────────────────────────────────────────── */

.commodities__label{
  display:flex;align-items:center;gap:10px;
  margin-bottom:10px;
}
.commodities__label::before{
  content:"";width:7px;height:7px;border-radius:50%;
  background:var(--acc);
  transition:background-color .5s var(--e-out);
}

.commodities__headrow{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,24em);
  align-items:end;
  gap:32px;
  padding-bottom:16px;
  border-bottom:1px solid var(--line-soft);
}
.commodities__lead{max-width:32ch;padding-bottom:5px}

/* ── columns: rail 38% / panel 62%, 20px gutter ───────────── */

.commodities__cols{
  display:grid;
  grid-template-columns:38% minmax(0,1fr);
  gap:20px;
  flex:1 1 auto;
  min-height:0;
  padding-block:16px;
}

/* ── left rail ────────────────────────────────────────────── */

.commodities__rail{
  display:flex;
  flex-direction:column;
  gap:10px;
  min-height:0;
}

.commodities__item{
  display:flex;flex-direction:column;
  flex:0 1 auto;
  border:1px solid var(--line);
  border-radius:var(--r-card);
  background:var(--paper);
  padding:16px 20px 0;
  transition:border-color .5s var(--e-out),background-color .5s var(--e-out),
             box-shadow .5s var(--e-out),flex-grow .7s var(--e-out);
}
.commodities__item.is-active{
  flex-grow:1;
  border-color:transparent;
  background:var(--acc-soft);
  box-shadow:0 20px 44px -34px rgba(10,10,10,.45);
}

.commodities__item:not(.is-active){flex-grow:.5}
.commodities__item:not(.is-active) .commodities__item-title{margin-block:auto}

.commodities__item-title{margin:0;font-weight:inherit;letter-spacing:inherit;line-height:inherit}

.commodities__tab{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  width:100%;min-height:48px;padding:0 0 14px;text-align:left;
}
.commodities__tab:focus-visible{outline:2px solid var(--acc);outline-offset:4px;border-radius:8px}

.commodities__name{
  font-size:clamp(22px,2.2vw,32px);
  transition:color .5s var(--e-out);
}
.commodities__item.is-active .commodities__name{color:var(--ink)}
.commodities__item:not(.is-active) .commodities__name{color:var(--ink-2)}

.commodities__mark{
  flex:none;width:13px;height:13px;border-radius:50%;
  background:rgba(10,10,10,.14);
  transition:background-color .5s var(--e-out),transform .5s var(--e-out);
}
.commodities__item.is-active .commodities__mark{background:var(--acc);transform:scale(1.25)}

/* accordion body: grid-rows 0fr → 1fr, no height animation */
.commodities__body{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows .7s var(--e-out);
}
.commodities__item.is-active .commodities__body{grid-template-rows:1fr;flex:1 1 auto;min-height:0}

.commodities__body-in{
  display:flex;flex-direction:column;
  overflow:hidden;
  min-height:0;
  opacity:0;
  transform:translateY(10px);
  transition:opacity .45s var(--e-out),transform .55s var(--e-out);
}
.commodities__item.is-active .commodities__body-in{opacity:1;transform:none;transition-delay:.12s}

.commodities__copy{max-width:44ch;color:var(--ink-2)}
.commodities__cta{align-self:flex-start;margin-top:auto;margin-bottom:20px}

/* photo slot inside the expanded direction */
.commodities__shot{
  width:100%;aspect-ratio:16/5;max-height:132px;border-radius:var(--r);
  margin:4px 0 2px;
}

/* ── right panel ──────────────────────────────────────────── */
/* One wide card over two equal cards, on a tinted tray that
   carries the active accent. */

.commodities__dash{
  display:grid;
  grid-template-columns:1fr 1fr;
  grid-template-rows:minmax(0,1.5fr) minmax(0,1fr);
  gap:12px;
  min-height:0;
  padding:12px;
  border-radius:30px;
  background:var(--acc-soft);
  transition:background-color .5s var(--e-out);
}

.commodities__card{
  display:flex;flex-direction:column;
  min-height:0;
  padding:24px 28px 20px;
  border-radius:var(--r-card);
  background:var(--paper);
}
.commodities__card--wide{grid-column:1 / -1}

.commodities__card-top{display:flex;align-items:center;justify-content:space-between;gap:14px}
.commodities__card-label{letter-spacing:-.01em;white-space:nowrap}

/* the per-stop qualifier that keeps every figure reading as an example */
.commodities__note{
  font-size:16px;line-height:1.25;color:var(--ink-3);text-align:right;
  min-width:0;
}

/* the accent as ink on its own tint: the bright value measures 4.07:1
   here, which is a fill's contrast, not text's */
.commodities__badge{
  display:inline-flex;align-items:center;height:30px;padding:0 14px;
  border-radius:var(--r-pill);
  background:var(--acc-soft);color:var(--acc-ink);
  font-size:15px;font-weight:500;letter-spacing:-.01em;white-space:nowrap;
  transition:background-color .5s var(--e-out),color .5s var(--e-out);
}

.commodities__value{
  margin-top:4px;
  font-size:clamp(30px,2.6vw,36px);
  font-weight:500;letter-spacing:-.03em;line-height:1.05;
  font-variant-numeric:tabular-nums;
}

/* the caption rail at the foot of every card */
.commodities__foot{
  display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  margin-top:12px;padding-top:10px;
  border-top:1px solid var(--line-soft);
  font-size:16px;line-height:1.3;color:var(--ink-3);
}
.commodities__foot span:last-child{text-align:right;color:var(--ink-2)}

/* ── dot field (wide card) ────────────────────────────────── */
/* The svg is drawn 1:1 to the measured box in JS, so the field
   runs the full width of the card at any height. */

.commodities__chart{flex:1 1 auto;min-height:104px;margin-top:12px}
.commodities__dots{width:100%;height:100%;display:block}
.commodities__dot{
  fill:var(--acc);
  opacity:0;
  transform:translateY(26px);
  transition:transform .8s var(--e-out),opacity .45s linear,fill .5s var(--e-out);
  transition-delay:calc(var(--i) * 26ms);
}
.commodities__dash.is-on .commodities__dot{opacity:1;transform:none}
/* dots above the curve are the empty part of the scale */
.commodities__dash.is-on .commodities__dot.is-dim{opacity:.16}

/* ── tile grid (grades & forms) ───────────────────────────── */

.commodities__grid{
  display:grid;
  grid-template-columns:repeat(7,minmax(0,1fr));
  grid-template-rows:repeat(3,minmax(0,1fr));
  gap:8px;
  flex:1 1 auto;
  min-height:56px;
  margin-top:12px;
}
.commodities__grid li{display:flex;min-height:0}
.commodities__cell{
  flex:1 1 auto;
  border-radius:6px;
  background:var(--acc);
  opacity:0;transform:scale(.4);
  transition:opacity .4s var(--e-out),transform .5s var(--e-out),
             background-color .5s var(--e-out);
  transition-delay:calc(var(--i) * 34ms);
}
.commodities__dash.is-on .commodities__cell{opacity:1;transform:none}
/* tiles past the example count read as open slots */
.commodities__dash.is-on .commodities__cell.is-dim{opacity:.16}

/* ── bars (lead time) ─────────────────────────────────────── */

.commodities__bars{
  display:flex;align-items:flex-end;gap:10px;
  flex:1 1 auto;min-height:44px;margin-top:12px;
}
.commodities__bar{
  flex:1 1 0;
  height:calc(var(--h) * 100%);
  min-height:12px;                       /* the shortest step still reads as a bar */
  border-radius:8px 8px 3px 3px;
  background:var(--acc);
  transform:scaleY(0);
  transform-origin:bottom;
  transition:transform .8s var(--e-out),background-color .5s var(--e-out);
  transition-delay:calc(var(--i) * 40ms);
}
.commodities__dash.is-on .commodities__bar{transform:scaleY(1)}

.commodities__ticks{
  display:flex;gap:10px;margin-top:9px;
  font-size:14px;line-height:1.2;color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}
.commodities__ticks li{flex:1 1 0;text-align:center}

/* ── stop indicator ───────────────────────────────────────── */

.commodities__stops{display:flex;gap:7px;flex:none}
.commodities__stop{
  width:26px;height:3px;border-radius:2px;
  background:rgba(10,10,10,.12);
  transition:background-color .5s var(--e-out),transform .5s var(--e-out);
}
.commodities__stop.is-on{background:var(--acc);transform:scaleX(1.25);transform-origin:left}

/* ── reduced motion: end state, no stagger ────────────────── */

@media (prefers-reduced-motion:reduce){
  .commodities__dot{opacity:1;transform:none}
  .commodities__cell{opacity:1;transform:none}
  .commodities__bar{transform:scaleY(1)}
  .commodities__body-in{opacity:1;transform:none}
}

@media (min-width:1041px) and (max-width:1300px){
  .commodities__card{padding:22px 22px 18px}
  .commodities__headrow{gap:24px;grid-template-columns:minmax(0,1fr) minmax(0,21em)}
}

/* ── the pinned stage is one viewport tall ────────────────────
   Short viewports tighten the panel first, then drop the photo. */

@media (min-width:1041px) and (max-height:900px){
  .commodities__shot{aspect-ratio:21/9}
  .commodities__card{padding:20px 24px 18px}
  .commodities__chart,.commodities__grid,.commodities__bars{margin-top:10px}
  .commodities__foot{margin-top:10px;padding-top:9px}
}
@media (min-width:1041px) and (max-height:860px){
  .commodities__name{font-size:clamp(24px,2.4vw,32px)}
  .commodities__copy{font-size:16px}   /* the floor, not a step below it */
  .commodities__chart{min-height:96px}
}
@media (min-width:1041px) and (max-height:820px){
  .commodities__shot{display:none}
  .commodities__copy{margin-bottom:10px}
  .commodities__foot{margin-top:8px;padding-top:8px}
}
/* under ~800px of viewport the qualifiers fold away: the lede already
   states that every figure is an example, so the cards keep the data */
@media (min-width:1041px) and (max-height:800px){
  .commodities__foot,.commodities__note{display:none}
  .commodities__title{font-size:clamp(36px,3.4vw,46px)}
  .commodities__label{margin-bottom:6px}
  .commodities__headrow{padding-bottom:12px}
  .commodities__cols{padding-block:12px}
  .commodities__card{padding:16px 20px 14px}
  .commodities__card-label{font-size:16px}
  .commodities__value{font-size:30px}
  .commodities__chart{min-height:64px;margin-top:8px}
  .commodities__grid{min-height:40px;margin-top:8px;gap:6px}
  .commodities__bars{min-height:32px;margin-top:8px}
  .commodities__ticks{margin-top:6px}
  .commodities__item{padding-block:14px}
}
@media (min-width:1041px) and (max-height:700px){
  .commodities__ticks{display:none}
  .commodities__chart{min-height:52px}
  .commodities__grid{min-height:32px;gap:5px}
  .commodities__bars{min-height:26px}
}

/* The open direction is stretched to match the panel beside it, but the
   photo is capped and the action is pinned to the card's floor, so on a
   tall viewport the slack collected as an empty tinted band between them
   — 150px at 1920x1080, 330px at 2560x1440. Above 1000px the photo takes
   the slack instead. The signed-off 1440x900 composition is below the
   gate and is untouched. */
@media (min-width:1041px) and (min-height:1000px){
  .commodities__shot{max-height:none;flex:1 1 auto;min-height:132px;margin-bottom:14px}
}

/* ── below 1040px: the scene collapses into a stacked block ── */

@media (max-width:1040px){
  .commodities{height:auto}
  .commodities__stage{position:static;height:auto;overflow:visible;display:block}
  .commodities__shell{padding-top:76px;padding-bottom:64px}
  .commodities__headrow{grid-template-columns:minmax(0,1fr);align-items:start;gap:16px}
  .commodities__lead{padding-bottom:0;max-width:52ch}
  .commodities__cols{grid-template-columns:minmax(0,1fr);gap:16px;padding-block:24px}
  .commodities__dash{grid-template-rows:auto auto;padding:10px;border-radius:26px}
  .commodities__chart{flex:0 0 auto;height:180px;min-height:0}
  .commodities__grid{min-height:120px}
  .commodities__bars{min-height:104px}
}

@media (max-width:640px){
  .commodities__dash{grid-template-columns:minmax(0,1fr);grid-template-rows:auto}
  .commodities__card--wide{grid-column:auto}
  .commodities__card{padding:22px 20px 18px}
  .commodities__item{padding-inline:16px}
  .commodities__chart{height:150px}
  .commodities__grid{grid-template-columns:repeat(7,minmax(0,1fr));min-height:104px}
  .commodities__value{font-size:32px}
}


/* ── parameters ── */
/* ============================================================
   5. parameters — the foundation band.
   Heading holds the left rail; the right rail is a stack of four
   rows, each one an enormous numeral with its label set beside it
   and a quiet third column saying what the numeral counts.
   Full-width hairlines, big vertical padding. A register, not a
   dashboard — and no card ever appears here.
   ============================================================ */

.parameters{
  background:var(--paper);
  padding:var(--band-t) 0 var(--band-b);

  --par-num:clamp(96px,10.2vw,150px);   /* the hero of every row */
  --par-col:.6em;                       /* one digit column       */
}

/* ── the two rails ───────────────────────────────────────── */

.parameters__grid{
  display:grid;
  grid-template-columns:minmax(0,.56fr) minmax(0,1fr);
  column-gap:clamp(40px,5vw,80px);
  align-items:start;
}

/* ── head ────────────────────────────────────────────────── */

.parameters__head{
  position:sticky;
  top:calc(var(--nav-h) + 56px);
}

.parameters__mark{margin-bottom:clamp(22px,2.6vw,40px)}

.parameters__title{max-width:15ch;text-wrap:pretty}

.parameters__note{
  margin-top:clamp(32px,3.6vw,52px);
  padding-top:clamp(20px,2vw,26px);
  border-top:1px solid var(--line);
  display:grid;
  grid-template-columns:minmax(0,4.6em) minmax(0,1fr);
  column-gap:clamp(16px,1.6vw,24px);
  row-gap:8px;
  max-width:40ch;
}
.parameters__note-k{
  font-size:16px;
  font-weight:500;
  letter-spacing:-.01em;
  color:var(--ink);
}
.parameters__note-v{
  font-size:16px;
  line-height:1.45;
  color:var(--ink-3);
}

/* ── the stack ───────────────────────────────────────────── */

.parameters__list{
  margin:0;
  border-top:1px solid var(--line);
}

.parameters__row{
  display:grid;
  grid-template-columns:max-content minmax(0,.86fr) minmax(0,1.06fr);
  align-items:center;
  column-gap:clamp(22px,2.4vw,34px);
  row-gap:10px;
  padding-block:clamp(28px,3.2vw,46px);
  border-bottom:1px solid var(--line);
}

/* the numeral — the row is built around it */
.parameters__fig{
  margin:0;
  grid-column:1;
  font-size:var(--par-num);
  font-weight:500;
  line-height:1;
  letter-spacing:0;
  color:var(--ink);
  font-variant-numeric:tabular-nums;
}

.parameters__body{
  margin:0;
  grid-column:2 / span 2;
  display:grid;
  grid-template-columns:subgrid;
  align-items:center;
  column-gap:inherit;
  row-gap:10px;
}

.parameters__label{
  grid-column:1;
  margin:0;
  font-size:clamp(21px,1.8vw,25px);
  font-weight:500;
  line-height:1.14;
  letter-spacing:-.02em;
  color:var(--ink);
  text-wrap:balance;
}

.parameters__expand{
  grid-column:2;
  margin:0;
  font-size:17px;
  line-height:1.45;
  color:var(--ink-3);
}

/* the closing figure is the point of the block, so it carries the accent */
.parameters__row--key .parameters__fig{color:var(--a1)}

/* ── the roller ──────────────────────────────────────────── */
/* one fixed-width column per digit so the strips stay aligned
   while they slide; the numeral itself is the grotesque, not mono */

.parameters__num{
  display:inline-flex;
  align-items:flex-start;
  line-height:1;
}
.parameters .roll__lit{display:block;height:1em;line-height:1}
.parameters .roll__col{width:var(--par-col);text-align:center;height:1.02em}
/* the strips slide once, when the row arrives, and never move again.
   The hint is held only until they land: promoting eight 88x1469 layers
   for the life of the page buys nothing after the first 1.8 seconds. */
.parameters .roll:not(.is-rolled) .roll__col > .roll__strip{will-change:transform}
.parameters .roll__strip span{text-align:center;height:1em;line-height:1}

/* ── responsive ──────────────────────────────────────────── */

/* one rail: the heading sits over the stack, the rows keep three columns */
@media (max-width:1080px){
  .parameters{--par-num:clamp(104px,13vw,150px)}
  .parameters__grid{
    grid-template-columns:minmax(0,1fr);
    row-gap:clamp(40px,5vw,64px);
  }
  .parameters__head{position:static}
  .parameters__title{max-width:20ch}
  .parameters__note{max-width:62ch;grid-template-columns:minmax(0,4.6em) minmax(0,1fr)}
}

/* the third column folds under the label */
@media (max-width:860px){
  .parameters{--par-num:clamp(88px,13vw,112px)}
  .parameters__row{
    grid-template-columns:max-content minmax(0,1fr);
    align-items:center;
    padding-block:clamp(30px,4.6vw,42px);
  }
  .parameters__body{
    grid-column:2;
    display:block;
  }
  .parameters__expand{margin-top:10px;max-width:46ch}
}

/* the numeral takes its own line and the label follows underneath */
@media (max-width:600px){
  .parameters{--par-num:clamp(80px,25vw,108px)}
  .parameters__row{
    grid-template-columns:minmax(0,1fr);
    row-gap:14px;
    padding-block:clamp(28px,8vw,38px);
  }
  .parameters__body{grid-column:1}
  .parameters__label{font-size:22px}
  .parameters__expand{margin-top:8px;max-width:none}
  .parameters__note{
    grid-template-columns:minmax(0,1fr);
    row-gap:6px;
    max-width:none;
  }
}


/* ── routes ── */
/* ── routes ── "We move …" dot-globe scene carrying trade lanes ──
   Wrapper is 300vh; the stage is pinned and everything inside is driven
   by transform/opacity from routes.js. The globe is a canvas; the hub
   codes are DOM labels laid over it so they stay real monospaced type. */

.routes{
  height:230vh;
  --routes-fs:clamp(32px,5vw,72px);
  --routes-orb:min(52vh,560px);
  --rt-acc:var(--a1);           /* JS overwrites with an rgb() tint */
}

.routes__stage{
  position:sticky;              /* inherited from .scene__stage, kept explicit */
  display:flex;align-items:center;
  background:var(--paper);
}

/* ── running head ────────────────────────────────────────── */

.routes__top{
  position:absolute;top:calc(var(--ann-h,52px) + var(--nav-h) + 54px);left:0;right:0;
  pointer-events:none;
}
.routes__top-in{
  display:flex;align-items:baseline;justify-content:space-between;gap:20px;
}
.routes__strap{
  font-family:var(--sans);font-style:normal;
  /* the minimum is the house floor: the old 15px held from 1153px down,
     so this line was under it on every tablet and every phone */
  font-size:clamp(16px,1.3vw,19px);line-height:1.2;
  color:var(--ink-3);
}

/* ── the line ────────────────────────────────────────────── */

.routes__shell{width:100%}

/* Three columns, not a flex row: the globe owns the middle track, so it
   sits on the page's centre line whatever the two texts weigh. */
.routes__line{
  display:grid;
  grid-template-columns:1fr var(--routes-orb) 1fr;
  align-items:center;
  gap:clamp(14px,2.1vw,30px);
  font-family:var(--sans);font-weight:400;
  font-size:var(--routes-fs);
  letter-spacing:-.02em;line-height:1;
  margin:0;
}
.routes__static{white-space:nowrap;justify-self:start}

/* ── globe ───────────────────────────────────────────────── */

.routes__orb{
  position:relative;
  width:100%;min-width:0;
  height:auto;aspect-ratio:1;
}
.routes__orb::before{
  content:"";position:absolute;inset:-6%;border-radius:50%;
  background:radial-gradient(circle at 50% 50%,var(--rt-acc) 0%,rgba(255,255,255,0) 68%);
  opacity:.10;
}
.routes__canvas{
  display:block;position:relative;
  width:100%;height:100%;
}

/* hub codes: zero-size anchors moved by transform, label hung beside */
.routes__hubs{position:absolute;inset:0;display:block;pointer-events:none}
.routes__hub{
  position:absolute;left:0;top:0;width:0;height:0;
  opacity:0;
}
.routes__hub-t{
  position:absolute;left:11px;top:calc(-8px + var(--oy,0px));
  white-space:nowrap;
  font-family:var(--mono);font-size:14px;font-weight:500;
  letter-spacing:.1em;color:var(--ink-2);
  background:rgba(245,242,236,.74);
  padding:1px 3px;border-radius:2px;
}
.routes__hub.is-left .routes__hub-t{left:auto;right:11px}

/* ── swapping paragraph ──────────────────────────────────── */

/* the three phrases share one grid cell, so the block is as wide as the
   longest of them and they can crossfade in place */
.routes__phrases{display:grid;min-width:0;justify-self:center;justify-items:center}
.routes__phrase{
  grid-area:1/1;
  white-space:nowrap;font-style:normal;
  opacity:0;
  transition:opacity .45s var(--e-out),transform .45s var(--e-out);
}
.routes__phrase[data-ri="0"]{color:var(--a1)}
.routes__phrase[data-ri="1"]{color:var(--a2)}
.routes__phrase[data-ri="2"]{color:var(--a3)}
/* no-JS / pre-boot fallback: first state visible */
.routes__phrase[data-ri="0"]{opacity:1}

/* The paragraph belongs to the left half of the line, so it stops where
   the globe's column begins — and it is pulled back up out of the grid
   row the globe made tall, so it reads as the second line of "We move"
   rather than as a caption stranded under the sphere. */
.routes__paras{
  display:grid;
  max-width:min(44ch,calc((100% - var(--routes-orb)) / 2 - clamp(14px,2.1vw,30px)));
  margin-top:calc(var(--routes-fs) * .5 + 30px - var(--routes-orb) / 2);
}
.routes__para{
  grid-area:1/1;
  opacity:0;
  transition:opacity .45s var(--e-out),transform .45s var(--e-out);
}
.routes__para[data-ri="0"]{opacity:1}

/* while the scroll scene is scrubbing, JS owns opacity/transform frame by
   frame — CSS transitions would fight it */
.routes.is-scrub .routes__phrase,
.routes.is-scrub .routes__para{transition:none}

/* ── the qualifier under the scene ───────────────────────── */

.routes__bottom{
  position:absolute;left:0;right:0;bottom:clamp(28px,4vh,48px);
}
.routes__bottom-in{
  display:flex;align-items:flex-end;justify-content:space-between;gap:24px;
  padding-top:13px;border-top:1px solid var(--line);
}

/* ── collapsed layout: ordinary stacked section ────────────
   Deliberately NOT also the reduced-motion layout, unlike hero.css.
   The three phrases and the three paragraphs share one grid cell each
   and are revealed by scroll position, so collapsing the wrapper leaves
   only the first of each visible: measured at 390px, the paragraph
   opacities are 1,0,0 and stay there. Folding the preference in here
   would take two thirds of this section's copy away from the reader it
   was meant to help. Nothing in the section animates under the
   preference anyway — the globe's loop is gated in routes.js and both
   crossfades are cut to none below — so what is left is a tall section
   whose copy changes on scroll, which is what a reduced-motion user is
   supposed to get in place of a transition. */

@media (max-width:1040px){
  .routes{
    height:auto;
    --routes-fs:clamp(30px,8.4vw,50px);
    --routes-orb:min(64vw,340px);
  }
  .routes__stage{
    position:static;height:auto;overflow:visible;
    display:block;
    padding:clamp(72px,14vw,110px) 0 clamp(48px,10vw,72px);
  }
  .routes__top{position:static;margin-bottom:clamp(26px,6vw,40px)}
  .routes__top-in{flex-direction:column;align-items:flex-start;gap:9px}
  .routes__line{
    grid-template-columns:1fr;
    justify-items:start;
    gap:clamp(16px,4vw,26px);
  }
  .routes__orb{width:var(--routes-orb);justify-self:center}
  .routes__phrases{justify-self:start;justify-items:start}
  .routes__paras{max-width:38ch;margin-top:clamp(18px,4vw,26px)}
  .routes__bottom{position:static;margin-top:clamp(30px,7vw,44px)}
  .routes__bottom-in{flex-direction:column;align-items:flex-start;gap:18px}
}

/* below this the globe is too small to carry twelve codes legibly */
@media (max-width:759px){
  .routes__hubs{display:none}
}

@media (prefers-reduced-motion:reduce){
  .routes__phrase,.routes__para{transition:none}
}


/* ── flow ── */
/* ============================================================
   flow, "From inquiry to handover, checked at every step."
   Process and compliance, joined, on the night band.

   Composition (the one the old compliance section used, which is
   itself the Ondo "Institutional Grade" band):

     · a full-bleed black band with a night terminal behind it,
       dimmed under a two-axis scrim so the photograph is present
       but never competes with the copy;
     · the heading and the lead top-left, over the darkest part of
       the frame;
     · along the bottom a rail of seven steps. The step you are on
       carries everything it has to say; the other six are narrow
       dark slabs with a number and a name. The rail translates so
       the open card stays in view and the strip always ends flush
       with the right edge, with a real peek of the next slab
       whenever there is more to come.

   The open card belongs to the band. It is the night ground lifted
   by a few per cent of white and closed with a hairline, not a sheet
   of paper laid on top of it, and everything inside it is opened by
   a rule and paid for in space rather than fenced into a box.

   Nothing on this band is paper-white. The document the step issues
   is drawn in line, ruled and stamped, on its stack, in the same pen
   as the ticks and the arrows, and it is held below the value of the
   copy it illustrates.

   Nothing here is driven by scroll. The state changes only on a
   click or a key. Below 1040px the rail becomes a plain list with
   every step expanded and the controls gone.
   ============================================================ */

.flow{
  position:relative;
  /* clipped for the same reason the rail is: with the rail clipped, the
     next scroll container up would be this one, and the browser would
     scroll the whole band sideways to reveal a slab tabbed to past the
     edge. `hidden` stays first as the fallback. */
  overflow:hidden;
  overflow:clip;
  background:var(--night);
  color:var(--paper);
  /* the night band's own pair of the four spacing tokens; see base.css
     for why a dark ground is allowed to pay less air than a paper one */
  padding:var(--band-t-dark) 0 var(--band-b-dark);

  /* ── ink on the night ground ─────────────────────────────── */
  --n-1:rgba(255,255,255,.92);
  --n-2:rgba(255,255,255,.62);
  /* the quietest ink on the band still has to be read. At .44 the only
     run that carries it, the note under the rail, composites to
     rgb(112,112,112) over the black floor of the frame: 4.25:1, the one
     text run in the section under AA. .52 measures 5.6:1 on that same
     ground at every width and still sits a clear step under --n-2. */
  --n-3:rgba(255,255,255,.52);
  --n-line:rgba(255,255,255,.13);
  --n-fill:rgba(255,255,255,.035);

  /* ── ink on the open card ────────────────────────────────────
     The open card is the band lifted, not a sheet of paper laid on
     top of it, so every value below is measured against that lifted
     dark surface, which samples #242423 along its head and #121212
     at its foot. Sampled off the rendered band at 1440, worst
     ground each of them ever sits on:
       --c-1  14.1:1   names, values, the sentence a check opens on
       --c-2   9.5:1   17px body copy
       --c-3   6.5:1   the 15 and 16px captions                    */
  --c-1:rgba(255,255,255,.95);
  --c-2:rgba(255,255,255,.76);
  --c-3:rgba(255,255,255,.60);

  /* the guarantee, in the one green that carries on the night: the
     mint is 11.9:1 on black and 8.8:1 on the brightest part of the
     lifted card. The deep green the paper card used is 4.3:1 there
     and went out with the paper. */
  --ok-night:#3ddc9a;

  /* the flow's own accent, which has to survive the move to dark.
     #3b6fe0 is 3.4:1 on this ground, display sizes and rules only,
     so it is spent on the ring and the wash behind the open step's
     numeral; the numeral itself takes the lightened blue, 5.6:1 on
     that wash, which clears AA at 16px. */
  --a2-night:#7ba4f5;

  /* ── rail geometry ───────────────────────────────────────────
     The three lengths below are the no-JS fallback. With JS the
     script solves the two widths from the measured rail so that a
     fixed share of one slab always sits past the right edge: the
     peek is designed, not whatever happened to fit. */
  --flow-cw:206px;         /* a closed slab */
  --flow-cwa:826px;        /* the open card */
  --flow-gap:12px;
  --flow-h:520px;          /* rail height, solved from the tallest card */
  --flow-shift:0px;
  --flow-fade-l:0px;
  --flow-fade-r:0px;
}

/* ── the photograph, and the scrim that keeps it behind ────── */

.flow__bg{position:absolute;inset:0;z-index:0;background:#000}
.flow__img{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  /* the one lit thing in the frame is a lamp on the quay: pushed
     right, it sits beside the lead instead of under the heading */
  object-position:70% 44%;
  opacity:.62;
  filter:grayscale(.3) brightness(.86) contrast(.94);
}
.flow__scrim{
  position:absolute;inset:0;
  background:
    linear-gradient(180deg,rgba(0,0,0,.58) 0%,rgba(0,0,0,.12) 32%,
                    rgba(0,0,0,.42) 60%,rgba(0,0,0,.88) 100%),
    linear-gradient(96deg,#000 0%,rgba(0,0,0,.88) 24%,
                    rgba(0,0,0,.52) 56%,rgba(0,0,0,.26) 100%);
}
/* hairlines top and bottom, so the band is a band and not a hole */
.flow::before,
.flow::after{
  content:"";position:absolute;left:0;right:0;height:1px;z-index:2;
  background:var(--n-line);pointer-events:none;
}
.flow::before{top:0}
.flow::after{bottom:0}

.flow__shell{position:relative;z-index:1}

/* ── head ─────────────────────────────────────────────────── */

.flow__title{color:var(--paper);max-width:18ch}
.flow__title-b{display:block}
/* .t-tone is grey on paper; on the night ground it becomes the
   quieter white, so the second clause still reads as an aside */
.flow .t-tone{color:rgba(255,255,255,.42)}

.flow__lead{
  margin-top:clamp(14px,1.4vw,20px);
  max-width:56ch;
  color:var(--n-2);
}

/* ── the rail ─────────────────────────────────────────────── */

.flow__rail{
  position:relative;
  margin-top:clamp(28px,3.1vw,44px);
  /* clipped, not hidden. `overflow:hidden` makes the rail a scroll
     container, and the browser scrolls a scroll container sideways to
     reveal a control that is tabbed to while it sits past the edge:
     five Tab presses and the rail is 820px out of step with the strip.
     Nothing here models scrollLeft, so that offset is never noticed and
     never undone, and the open card stays off screen while the counter
     still says it is open. A clipped box is not a scroll container at
     all, so there is nothing to put out of step. `hidden` stays first
     as the fallback for engines that do not know `clip`. */
  overflow:hidden;
  overflow:clip;
  /* the strip bleeds through the right gutter, so it reads as
     continuing past the page rather than stopping in a margin */
  margin-right:calc(-1 * var(--gut));
  padding-right:var(--gut);
  /* an edge only fades where something is really behind it */
  -webkit-mask-image:linear-gradient(90deg,
    transparent 0, #000 var(--flow-fade-l),
    #000 calc(100% - var(--flow-fade-r)), transparent 100%);
  mask-image:linear-gradient(90deg,
    transparent 0, #000 var(--flow-fade-l),
    #000 calc(100% - var(--flow-fade-r)), transparent 100%);
}

.flow__track{
  display:flex;
  align-items:stretch;
  gap:var(--flow-gap);
  width:max-content;
  transform:translate3d(calc(-1 * var(--flow-shift)),0,0);
  /* the one clock on this band. Paging is a single geometric event and
     the travel is its longest component; the card's width and the body's
     grid row below carry this same duration and this same ease to the
     millisecond, because they are the other two axes of that one event. */
  transition:transform .52s var(--e-out);
}
/* The rail moves on a click and on nothing else, so the hint is worth
   holding only once the pointer or the focus is on the band. A permanent
   one keeps a 2134x456 layer alive for the whole page, thousands of
   pixels after anybody could still reach the controls. */
.flow:hover .flow__track,
.flow:focus-within .flow__track{will-change:transform}

/* ── one step ─────────────────────────────────────────────── */

.flow__card{
  position:relative;
  display:flex;
  flex-direction:column;
  flex:0 0 var(--flow-cw);
  width:var(--flow-cw);
  height:var(--flow-h);
  padding:clamp(18px,1.45vw,21px);
  border-radius:var(--r-card);
  background:var(--n-fill);
  box-shadow:inset 0 0 0 1px var(--n-line);
  overflow:hidden;
  /* width and flex-basis are the same event as the track's travel above,
     so they take the same clock. box-shadow is gone: it never changed
     value between the two states and was animating nothing. What is left
     of background-color is the hover below, which is a pointer answer and
     gets a pointer's clock, not a paging one. */
  transition:width .52s var(--e-out),flex-basis .52s var(--e-out),
             background-color .2s var(--e-out);
}
.flow__card:hover{background:rgba(255,255,255,.075)}

/* The open card is the band lifted, not a hole cut in it: a few per
   cent of white laid over the night ground, brightest along the head
   where the light would fall, and a hairline a shade brighter than
   the one the closed slabs carry. It does not fade in. Which card is
   open is a fact, not a movement: the surface is simply there on the
   frame the click lands, so the only thing travelling is the rail. */
.flow__card::before{
  content:"";position:absolute;inset:0;z-index:0;
  border-radius:inherit;pointer-events:none;
  /* the black under the white is not a second colour, it is the quay
     lamp being held down: the closed slabs let the photograph
     through, the open card has copy on it and cannot */
  background:
    linear-gradient(180deg,
      rgba(255,255,255,.125) 0%,
      rgba(255,255,255,.068) 44%,
      rgba(255,255,255,.05) 100%),
    rgba(0,0,0,.58);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.175),
             inset 0 1px 0 rgba(255,255,255,.11);
  opacity:0;
}
.flow__card.is-active::before{opacity:1}

.flow__card.is-active{
  flex-basis:var(--flow-cwa);
  width:var(--flow-cwa);
}
/* the open card is not a target any more, so hover stops answering */
.flow__card.is-active:hover{background:var(--n-fill)}

/* the whole slab is the control */
.flow__pick{
  position:absolute;inset:0;z-index:3;
  width:100%;height:100%;border-radius:inherit;
}
.flow__pick:focus-visible{outline:2px solid #fff;outline-offset:-5px}
.flow__card.is-active .flow__pick{cursor:default}

/* the index: a stamp in a hairline square, not a pill */
.flow__stamp{
  position:relative;z-index:2;
  display:flex;align-items:center;justify-content:center;
  width:40px;height:40px;flex:none;
  border-radius:6px;
  border:1px solid rgba(255,255,255,.28);
  font-size:16px;
  letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;
  color:rgba(255,255,255,.78);
}
/* the open step is the one place the flow's blue appears: a wash and
   a ring in --a2, the numeral in the lightened blue that clears AA */
.flow__card.is-active .flow__stamp{
  border-color:rgba(59,111,224,.62);
  background:rgba(59,111,224,.16);
  color:var(--a2-night);
}

/* this step carries a check we put in writing */
.flow__flag{
  /* top and left are the card's own padding, hand-copied; the left is
     then the stamp's width plus the 12px gap beside it. If the padding
     or the stamp is ever retuned, these three numbers move with it. */
  position:absolute;top:clamp(18px,1.45vw,21px);
  left:calc(clamp(18px,1.45vw,21px) + 52px);
  z-index:2;
  display:flex;align-items:center;justify-content:center;
  width:40px;height:40px;
  border-radius:50%;
  color:var(--ok-night);
  box-shadow:inset 0 0 0 1px rgba(61,220,154,.4);
}
.flow__flag svg{width:19px;height:19px}

/* ── the name, and everything the open card adds under it ─── */

/* the name and everything under it sit on the floor of the card; the
   padding is the least air the stamp is ever given above them */
.flow__inner{
  margin-top:auto;position:relative;z-index:2;
  padding-top:clamp(14px,1.35vw,20px);
}

.flow__name{
  font-size:clamp(21px,1.8vw,26px);
  font-weight:500;
  line-height:1.1;
  letter-spacing:-.02em;
  color:var(--paper);
  text-wrap:balance;
}
.flow__card.is-active .flow__name{text-wrap:pretty}

/* the rail is as tall as its tallest step, so the shorter steps carry
   slack. On a closed slab the name stays on the floor; on the open card
   the slack is split above and below the block, otherwise all of it
   piles up under the stamp and the card reads half-empty. This is the
   treatment for the single-column band at 1041-1300, where the file
   sits under the copy and nothing in the column can absorb slack; the
   wide layout overrides it below. */
.flow__card.is-active .flow__inner{margin-bottom:auto}

/* On the wide layout the split is not the right treatment, because the
   rail is as tall as step 04 and the other six then float their whole
   contents in the middle of a card with a void at each end. Instead the
   head keeps the designed minimum air under the stamp on every step and
   the body grows to the floor, so both columns really do run the full
   height the comment above claims for them. */
@media (min-width:1301px){
  .flow__card.is-active .flow__inner{
    margin-top:0;margin-bottom:0;
    flex:1 1 auto;min-height:0;
    display:flex;flex-direction:column;
  }
  .flow__card.is-active .flow__body{flex:1 1 auto;min-height:0}

  /* The rail is as tall as step 04, so the six shorter steps hand their
     left column 100 to 180px it has no copy for. The file column beside
     it already ends flush with the floor, so leaving the slack under the
     copy empties the bottom-left quadrant and the card reads lopsided.
     The ruled block takes the floor instead: copy at the head, the rule
     and what it opens on the floor, and the air lands in the middle
     where it reads as space rather than as a gap at the end. */
  .flow__card.is-active .flow__said > :last-child{margin-top:auto}
}

/* the body opens on a grid row rather than on a height, so nothing
   has to be measured for the transition to be smooth */
.flow__body{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows .52s var(--e-out);
}
.flow__card.is-active .flow__body{grid-template-rows:1fr}

/* on the open card: what happens on the left, what it puts in your
   file on the right. Both columns run to the floor of the card, so
   the ruled edge between them runs the full height of the body.

   There are no boxes here. Every region on this card is opened by a
   hairline and paid for in space: the facts and the checks by a rule
   above them, the file by a rule down its left side. */
.flow__bodyin{
  min-height:0;
  overflow:hidden;
  opacity:0;
  /* opacity and a 0fr row hide the six closed steps from the eye but not
     from a screen reader: without this the whole section is read end to
     end, all seven steps, while every closed pick reports aria-expanded
     false. visibility takes them out of the tree, and it flips only once
     the fade has finished so nothing blinks out from under the copy */
  visibility:hidden;
  /* the copy is not a fourth event. This fade exists for one reason: while
     the card is still narrow the copy lays out to that narrow width, so it
     wraps wrong and the grid row is still cropping it. The fade covers that,
     which is why it is short and why it is over well before the rail lands.
     Closing carries no delay, so the old card's copy clears instead of
     smearing across the band behind the new one. */
  transition:opacity .2s var(--e-out),visibility 0s linear .2s;
  display:grid;
  grid-template-columns:minmax(0,1.62fr) minmax(0,.86fr);
  column-gap:clamp(22px,2.2vw,30px);
  align-items:stretch;
  padding-top:clamp(13px,1.15vw,17px);
}
.flow__card.is-active .flow__bodyin{
  opacity:1;visibility:visible;
  transition:opacity .2s var(--e-out) .1s,visibility 0s linear 0s;
}

.flow__said{
  min-width:0;
  display:flex;
  flex-direction:column;
}

.flow__copy{
  font-size:17px;
  line-height:1.4;
  letter-spacing:-.01em;
  color:var(--c-2);
  max-width:62ch;
  margin-bottom:clamp(13px,1.15vw,17px);
}

/* ── steps with no separate check still say who signs ─────── */

.flow__facts{
  padding-top:clamp(12px,1.05vw,15px);
  border-top:1px solid var(--n-line);
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:clamp(20px,2.4vw,34px);
  row-gap:10px;
}
.flow__fact{min-width:0}
.flow__fact-k{font-size:16px;letter-spacing:-.01em;color:var(--c-3);margin-bottom:3px}
.flow__fact-v{
  margin:0;font-size:17px;line-height:1.3;font-weight:500;
  letter-spacing:-.01em;color:var(--c-1);
}

/* ── the check: a guarantee, ruled off rather than boxed ───
   Same idiom as the facts above, which sit in the same slot on the
   steps that carry no check: a hairline, then air, then the copy.
   The heading takes the mint, which is the guarantee's colour and
   reads 10.4:1 where it sits on the card. */

.flow__checks{
  padding-top:clamp(12px,1.05vw,15px);
  border-top:1px solid var(--n-line);
}
.flow__checks-k{
  font-size:16px;
  letter-spacing:-.01em;
  font-weight:500;
  color:var(--ok-night);
  margin-bottom:clamp(8px,.8vw,11px);
}

.flow__check-list{display:grid;row-gap:12px}

.flow__check{
  display:grid;
  grid-template-columns:24px minmax(0,1fr);
  column-gap:12px;
  align-items:start;
  min-width:0;
}
/* the tick matches the flag on the closed slabs: a hairline ring,
   not a filled disc. Nothing on this card is a solid shape at all,
   the document included. */
.flow__tick{
  display:flex;align-items:center;justify-content:center;
  width:24px;height:24px;flex:none;margin-top:1px;
  border-radius:50%;
  color:var(--ok-night);
  box-shadow:inset 0 0 0 1px rgba(61,220,154,.45);
}
.flow__tick svg{width:14px;height:14px}

.flow__check-in{display:block;min-width:0}
.flow__check-t{
  display:block;font-size:17px;line-height:1.28;font-weight:500;
  letter-spacing:-.01em;color:var(--c-1);
}
.flow__check-c{
  display:block;margin-top:4px;
  font-size:16px;line-height:1.36;color:var(--c-2);
}

/* ── the file column ─────────────────────────────────────────
   What the step puts in your hands, ruled off from what it does.
   The panel that used to carry it is gone: the column is opened by a
   hairline down its left edge, the same rule that opens the checks,
   turned on its side. */

.flow__file{
  display:flex;
  flex-direction:column;
  min-width:0;
  padding-left:clamp(22px,2.2vw,30px);
  border-left:1px solid var(--n-line);
}
.flow__file-k{font-size:16px;letter-spacing:-.01em;color:var(--c-3)}

/* ── the document, drawn ────────────────────────────────────
   The solid paper-white sheet is gone. It was the one object on this
   band lit brighter than the sentence explaining it, and on a night
   ground a white rectangle is a hole, not a document.

   What stands there now is a drawing of the same thing, in the pen
   the rest of the section is drawn with: one viewBox, 1.5px, round
   caps and joins, held at that weight through every breakpoint by
   the non-scaling stroke rather than by being redrawn per size.

   The sheets already in the file are not rectangles stacked behind
   the front one. Each is only the contour it keeps past the sheet in
   front of it, so seven sheets are seven clean strokes and never a
   hatch, and they step back in tone as they step back in space. The
   file visibly thickens from step 01 to step 07.

   The whole ladder sits under the type it serves. The brightest
   value in the object is the front sheet's outline, one hairline at
   66% of white, which measures below the body copy beside it: the
   drawing is the illustration of the sentence, not its rival.

   The mark at the foot is a stamp, two concentric rings, and it is
   deliberately NOT the section's tick. A tick here would read as a
   check, and steps 01, 03 and 07 carry no check; the ring says
   issued and signed, which is true of all seven. */

.flow__pile{
  position:relative;
  flex:1 1 auto;
  min-height:126px;
  margin:clamp(10px,1.05vw,14px) 0 clamp(12px,1.2vw,16px);
}
/* The artefact fills its box and stands on the floor of it, directly
   over the name of the document it draws. It takes the whole box on
   purpose: on the wide layout the file column runs the full height of
   the card, and a small drawing pinned to the floor of a tall column
   leaves "Comes back to you" stranded a hundred pixels above the thing
   it labels. Growing costs nothing, because "meet" can only ever scale
   the drawing down to fit and the stroke does not scale at all.

   The 8px held back on the right is the stack's own margin. By step 07
   the drawing is six sheets wider than the sheet in front, and on the
   wide layout it grows until the column's width is what stops it, so
   without this the last sheet in the file ends a hairline short of the
   copy's edge. It costs nothing where height is the binding dimension,
   which is every breakpoint below 1301. */
.fp{
  position:absolute;left:0;bottom:0;
  /* an svg is a replaced element, so the margin has to be taken out of
     the width: left + right on it would simply be ignored */
  width:calc(100% - 8px);height:100%;
  overflow:visible;
}
/* one weight for the whole object */
.fp path,.fp circle{
  fill:none;
  stroke-width:1.5;
  stroke-linecap:round;
  stroke-linejoin:round;
  vector-effect:non-scaling-stroke;
}

/* the sheets already in the file, nearest first */
.fp__stack path{stroke:rgba(255,255,255,.34)}
.fp__stack path:nth-of-type(2){stroke:rgba(255,255,255,.29)}
.fp__stack path:nth-of-type(3){stroke:rgba(255,255,255,.25)}
.fp__stack path:nth-of-type(4){stroke:rgba(255,255,255,.21)}
.fp__stack path:nth-of-type(5){stroke:rgba(255,255,255,.18)}
.fp__stack path:nth-of-type(6){stroke:rgba(255,255,255,.15)}

/* the sheet this step issues */
.fp__edge{stroke:rgba(255,255,255,.66)}
.fp__fold{stroke:rgba(255,255,255,.38)}
.fp__line{stroke:rgba(255,255,255,.24)}
.fp__line--h{stroke:rgba(255,255,255,.44)}
/* signed off, in the one green this band carries */
.fp__seal{stroke:var(--ok-night,#3ddc9a)}
.fp__seal--in{stroke:rgba(61,220,154,.55)}

.flow__file-v{
  margin-top:auto;
  font-size:clamp(18px,1.5vw,21px);
  font-weight:500;line-height:1.15;letter-spacing:-.02em;
  color:var(--c-1);
}
.flow__file-c{
  margin-top:5px;font-size:15px;letter-spacing:-.01em;
  color:var(--c-3);font-variant-numeric:tabular-nums;
}

/* ── paging ───────────────────────────────────────────────── */

.flow__bar{
  position:relative;z-index:1;
  display:flex;align-items:center;justify-content:space-between;
  gap:24px;flex-wrap:wrap;
  margin-top:clamp(18px,1.8vw,26px);
  padding-top:clamp(13px,1.25vw,18px);
  border-top:1px solid var(--n-line);
}

.flow__nav{display:flex;align-items:center;gap:10px}

/* The script writes `arrow.disabled` on whatever carries the id, and
   disabling a button that has the focus on it blurs it: the keyboard
   user who pages to the last step is put on <body> and the next Tab
   restarts the document. So the id sits on this slot instead, where
   `disabled` is an inert property, and the button under it is never
   disabled while somebody is standing on it. The slot generates no box,
   so the nav lays out exactly as it did when the buttons carried the
   ids themselves. */
.flow__arrow-slot{display:contents}

.flow__arrow{
  display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;flex:none;
  border-radius:var(--r-pill);
  border:1px solid rgba(255,255,255,.24);
  color:var(--paper);
  /* opacity is out of this list because nothing fades the arrow any
     more: the end of the rail is now told in the two colours below,
     which is what opacity .3 was resolving to anyway, and which leaves
     the focus ring at full strength on a control that can still be
     tabbed to. Same clock, same three-property answer to the pointer. */
  transition:background-color .3s var(--e-out),border-color .3s var(--e-out),
             color .3s var(--e-out);
}
.flow__arrow svg{width:19px;height:19px}
.flow__arrow:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.5)}
/* base.css rings a focused control in the paper accent, and its night
   override keys off an ancestor class this section does not carry, so
   without this the arrows would be the only purple on the band while the
   seven picks beside them ring in white */
.flow__arrow:focus-visible{outline:2px solid #fff;outline-offset:3px}

/* An arrow with nowhere to go, read off the rail rather than off the
   button's own state: first step open, the back arrow is spent; last
   step open, the forward one is. The values are the ones opacity .3
   used to composite to, so the band looks exactly as it did. It stops
   answering the pointer, and pressing it on the keyboard is the no-op
   the script already clamps it to. #flowTrack keeps this off the
   off-screen probe, where every twin card is open at once. */
.flow:has(#flowTrack > .flow__card:first-child.is-active) .flow__arrow--prev,
.flow:has(#flowTrack > .flow__card:last-child.is-active) .flow__arrow--next{
  color:rgba(255,255,255,.3);
  border-color:rgba(255,255,255,.072);
  pointer-events:none;
  cursor:default;
}

.flow__count{
  margin-left:12px;font-size:17px;letter-spacing:-.01em;
  color:var(--n-2);font-variant-numeric:tabular-nums;
}
.flow__count span{color:var(--paper)}

.flow__note{font-size:16px;letter-spacing:-.01em;color:var(--n-3);text-align:right}

/* the off-screen twin the script measures the rail height with */
.flow__probe{
  position:absolute;left:-99999px;top:0;height:0;
  visibility:hidden;pointer-events:none;overflow:hidden;
}
.flow__probe .flow__card{
  position:relative;flex:none;width:100%;height:auto;
  transition:none;
}
.flow__probe .flow__bodyin{opacity:1;visibility:visible;transition:none}

/* ── the middle band: the file panel drops under the copy ─── */

@media (min-width:1041px) and (max-width:1300px){
  .flow__bodyin{
    grid-template-columns:minmax(0,1fr);
    row-gap:clamp(14px,1.6vw,18px);
  }
  /* the file sits under the copy now, so the rule that opens it turns
     with it: a hairline above instead of a hairline down the side */
  .flow__file{
    display:grid;
    grid-template-columns:auto minmax(0,1fr);
    column-gap:20px;
    align-items:center;
    align-content:center;
    border-left:0;padding-left:0;
    border-top:1px solid var(--n-line);
    padding-top:clamp(15px,1.6vw,19px);
  }
  .flow__file-k{grid-column:2;order:1}
  /* the stack steps out to seven sheets by the last step: the pile has
     to be wide enough for it, or the drawing walks over the copy */
  .flow__pile{
    grid-row:1 / span 3;grid-column:1;
    flex:none;width:152px;min-height:0;height:116px;margin:0;
  }
  .flow__file-v{grid-column:2;order:2;margin-top:2px}
  .flow__file-c{grid-column:2;order:3}
}

/* ── below 1040px: no rail, seven steps read down the page ── */

@media (max-width:1040px){
  .flow{padding-bottom:clamp(46px,7vw,64px)}
  .flow__title{max-width:none}
  .flow__lead{max-width:60ch}

  /* stacked, the band is metres tall: a photograph stretched over all
     of it would be a smear, so it keeps to the head and dissolves */
  .flow__bg{inset:0 0 auto 0;height:clamp(360px,58vh,560px)}
  .flow__img{object-position:22% 46%;opacity:.5}
  .flow__scrim{
    background:linear-gradient(180deg,rgba(0,0,0,.7) 0%,rgba(0,0,0,.34) 32%,
                               rgba(0,0,0,.8) 76%,#000 100%);
  }

  .flow__rail{
    margin-top:clamp(30px,5vw,44px);
    margin-right:0;padding-right:0;overflow:visible;
    -webkit-mask-image:none;mask-image:none;
  }
  .flow__track{
    flex-direction:column;width:auto;gap:0;
    transform:none;transition:none;
    border-top:1px solid var(--n-line);
  }

  /* every step is open, so "active" stops meaning anything: the
     slabs become rows on the night ground, ruled apart */
  .flow__card,
  .flow__card.is-active{
    flex:0 0 auto;width:100%;height:auto;
    background:none;box-shadow:none;border-radius:0;
    border-bottom:1px solid var(--n-line);
    padding:clamp(22px,4vw,30px) 0;
    overflow:visible;
    transition:none;
  }
  .flow__card:hover,
  .flow__card.is-active:hover{background:none}
  /* nothing is "open" here, so nothing is lifted */
  .flow__card::before,
  .flow__card.is-active::before{display:none}
  .flow__pick{display:none}

  .flow__stamp,
  .flow__card.is-active .flow__stamp{
    background:none;border-color:rgba(255,255,255,.28);
    color:rgba(255,255,255,.78);
    width:40px;height:40px;font-size:16px;
  }
  .flow__flag,
  .flow__card.is-active .flow__flag{
    top:clamp(22px,4vw,30px);left:52px;
    width:40px;height:40px;
  }

  .flow__inner{margin-top:clamp(14px,2vw,18px);padding-top:0}
  .flow__name,
  .flow__card.is-active .flow__name{color:var(--paper);font-size:clamp(23px,3.4vw,28px)}

  .flow__body,
  .flow__card.is-active .flow__body{grid-template-rows:1fr;transition:none}
  .flow__bodyin,
  .flow__card.is-active .flow__bodyin{
    /* every step is open here, so every body is on the page and in the
       accessibility tree; nothing is collapsed to hide */
    opacity:1;visibility:visible;transition:none;overflow:visible;
    grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
    column-gap:clamp(20px,3vw,32px);
    padding-top:clamp(12px,1.8vw,16px);
  }

  /* the copy sits straight on the black here rather than on a lifted
     card, but it is the same ink and the same ruled idiom, so nothing
     needs restating beyond the copy width */
  .flow__copy{max-width:60ch}

  .flow__file{
    align-self:start;
    border-left:1px solid var(--n-line);
    padding-left:clamp(20px,3vw,28px);
  }
  .flow__file-v{margin-top:0}
  .flow__pile{flex:none;min-height:0;height:118px;margin:14px 0 16px}

  /* nothing left to page through */
  .flow__nav{display:none}
  .flow__bar{border-top:0;padding-top:0;margin-top:clamp(20px,3vw,28px);justify-content:flex-start}
  .flow__note{text-align:left}
}

@media (max-width:760px){
  .flow__bodyin,
  .flow__card.is-active .flow__bodyin{
    grid-template-columns:minmax(0,1fr);
    row-gap:16px;
  }
  /* one column: the rule turns with the file, as it does at 1300 */
  .flow__file{
    align-self:stretch;
    border-left:0;padding-left:0;
    border-top:1px solid var(--n-line);
    padding-top:clamp(15px,3vw,19px);
  }
  .flow__facts{grid-template-columns:minmax(0,1fr);row-gap:10px}
}

@media (max-width:560px){
  .flow__file{
    display:grid;grid-template-columns:auto minmax(0,1fr);
    column-gap:18px;align-items:center;align-content:center;
  }
  .flow__file-k{grid-column:2;order:1}
  .flow__pile{grid-row:1 / span 3;grid-column:1;width:128px;height:104px;margin:0}
  .flow__file-v{grid-column:2;order:2;margin-top:2px}
  .flow__file-c{grid-column:2;order:3}
}

/* ── reduced motion: the state changes, nothing travels ───── */

@media (prefers-reduced-motion:reduce){
  /* five things transition now, and this is all five of them: the three
     axes of the one geometric event, the copy fade, and the arrows'
     answer to the pointer */
  .flow__track,.flow__card,.flow__body,.flow__bodyin,.flow__arrow{transition:none}
}


/* ── stoplist ── */
/* ── what we do not do: its own band, after the flow ─────── */

/* One band, one rhythm. The section used to pay --band AND a second
   clamp() on the inner wrapper, so it opened on ~196px of nothing and
   closed on ~150px. The wrapper is a leftover from when this list lived
   inside `conflict`; it carries the ground now and nothing else.
   It spends the tinted-band pair, the same one the flow spends, rather
   than a third set of multipliers of its own. */
.stoplist{
  background:var(--paper-2);
  padding:var(--band-t-dark) 0 var(--band-b-dark);
}
.stoplist__inner{width:100%}

.stoplist__title{
  max-width:none;
  margin-bottom:clamp(22px,2.4vw,34px);
}

.stoplist__list{border-top:1px solid var(--line)}

/* Three columns: the mark, the thing we do not do, and the one line
   that says why. Side by side, because the label and its line are one
   statement, and because stacking them leaves half the page empty. */
.stoplist__item{
  display:grid;
  grid-template-columns:38px minmax(0,.92fr) minmax(0,1.08fr);
  align-items:start;
  column-gap:clamp(20px,2.4vw,34px);
  row-gap:8px;
  padding-block:clamp(18px,1.9vw,26px);
  border-bottom:1px solid var(--line);
}

.js .stoplist__item.in .conflict__x i{
  transform:rotate(-45deg) scaleX(1);
  transition:transform .85s var(--e-out) .18s;
}

.stoplist__label{
  margin:0;
  font-size:clamp(20px,1.65vw,24px);
  font-weight:500;line-height:1.14;letter-spacing:-.02em;
  color:var(--ink);
  text-wrap:pretty;
}
.stoplist__line{
  font-size:clamp(17px,1.35vw,20px);line-height:1.4;
  color:var(--ink-2);
  padding-top:1px;
}

/* under 900 the two texts stop fitting side by side and the line drops
   under its label, in the mark's column-gap rather than under the mark */
@media (max-width:900px){
  .stoplist__item{grid-template-columns:38px minmax(0,1fr)}
  .stoplist__line{grid-column:2;padding-top:0}
}

@media (max-width:560px){
  .stoplist__item{
    grid-template-columns:32px minmax(0,1fr);
    column-gap:16px;
    row-gap:6px;
  }
  .stoplist__label{font-size:20px}
}


/* ── cases ── */
/* ============================================================
   8. cases — anonymised deal files in a peeking-neighbour rail.
   One wide card per slide, split photo-left / copy-right, with
   the neighbouring cards showing ~40px at each edge.
   ============================================================ */

.cases{
  --cases-gap:max(12px,calc(var(--gut) - 40px));
  --cases-card:calc(min(100vw,var(--shell)) - 2 * var(--gut));
  --cases-acc:var(--a3);
  --cases-tint:var(--a3-soft);
  position:relative;
  padding:var(--band-t) 0 var(--band-b);
  background:var(--paper);
  overflow:hidden;              /* peeking neighbours never widen the page */
}

/* ── heading ─────────────────────────────────────────────── */

.cases__head{margin-bottom:clamp(34px,4vw,58px)}
.cases__mark{margin-bottom:20px}
.cases__title{max-width:17ch}
.cases__title-b{display:block;color:var(--ink-3)}
.cases__lede{max-width:56ch;margin-top:22px}

/* ── rail ────────────────────────────────────────────────── */

.cases__stage{width:100%}

.cases__viewport{
  touch-action:pan-y;
  --cases-fade:clamp(18px,3.4vw,52px);
  width:100%;
  overflow:hidden;
  outline:none;
  cursor:grab;
  padding-block:4px;
  -webkit-mask-image:linear-gradient(90deg,
    transparent 0,#000 var(--cases-fade),
    #000 calc(100% - var(--cases-fade)),transparent 100%);
          mask-image:linear-gradient(90deg,
    transparent 0,#000 var(--cases-fade),
    #000 calc(100% - var(--cases-fade)),transparent 100%);
  -webkit-mask-repeat:no-repeat;
          mask-repeat:no-repeat;
  -webkit-mask-size:100% 100%;
          mask-size:100% 100%;
}
.cases__viewport:focus-visible{
  outline:2px solid var(--ink);
  outline-offset:-3px;
  border-radius:var(--r-card);
}
.cases__viewport.is-drag{cursor:grabbing}

.cases__track{
  display:flex;
  align-items:stretch;
  gap:var(--cases-gap);
  padding-inline:calc((100% - min(100%,var(--shell))) / 2 + var(--gut));
  transition:transform .72s var(--e-out);
}
/* promoted while the reader is on the rail, not for the life of the page:
   the track is idle until a click, a key or a drag asks it to move */
.cases:hover .cases__track,
.cases:focus-within .cases__track,
.cases__track.is-drag{will-change:transform}
.cases__track.is-drag{transition:none}

/* ── the card: photo left (46%), copy right (54%) ────────── */

.cases__card{
  position:relative;
  flex:0 0 var(--cases-card);
  width:var(--cases-card);
  display:grid;
  grid-template-columns:46% minmax(0,1fr);
  /* the row height is set here, not by the photo's ratio: a stretched
     grid item with aspect-ratio derives its WIDTH from the row and
     spills over the copy column the moment the copy is the taller side */
  min-height:clamp(340px,29vw,432px);
  overflow:hidden;
  border:1px solid var(--line);
  border-radius:var(--r-card);
  background:var(--white);
  opacity:.42;
  transition:opacity .6s var(--e-out),border-color .6s var(--e-out),
             box-shadow .6s var(--e-out);
}
.cases__card.is-active{
  opacity:1;
  border-color:rgba(10,10,10,.16);
  box-shadow:0 1px 0 rgba(10,10,10,.05);
}
.cases__card--brass{--cases-acc:var(--a1);--cases-tint:var(--a1-soft)}
.cases__card--green{--cases-acc:var(--a2);--cases-tint:var(--a2-soft)}
.cases__card--steel{--cases-acc:var(--a3);--cases-tint:var(--a3-soft)}

/* ── left: the photograph, edge to edge ──────────────────── */

.cases__shot{
  position:relative;
  width:100%;height:100%;
  border-right:1px solid var(--line-soft);
  background:var(--paper-2);
}

/* ── right: kicker, route, structure, data, action ───────── */

.cases__body{
  display:flex;flex-direction:column;align-items:flex-start;
  padding:clamp(24px,2.4vw,34px) clamp(22px,2.6vw,38px);
}
.cases__kicker{
  display:inline-flex;align-items:center;gap:9px;
  font-size:16px;font-weight:500;letter-spacing:-.01em;
  color:var(--ink-3);
}
.cases__kicker::before{
  content:"";
  width:9px;height:9px;flex:none;
  border-radius:2px;
  background:var(--cases-acc);
}
.cases__route{
  margin-top:clamp(12px,1.4vw,18px);
  color:var(--ink);
}
.cases__sep{color:var(--ink-3);margin:0 1px}
.cases__arrow-g{color:var(--cases-acc);padding:0 2px}
.cases__copy{
  margin-top:clamp(12px,1.3vw,16px);
  font-size:17px;line-height:1.45;
  color:var(--ink-2);
  max-width:44ch;
}

/* the ledger, folded into one compact row */
.cases__meta{
  margin:clamp(18px,2vw,26px) 0 0;
  padding-top:14px;
  width:100%;
  display:flex;flex-wrap:wrap;gap:8px 26px;
  border-top:1px solid var(--line-soft);
}
.cases__pair{display:flex;align-items:baseline;gap:8px;min-width:0}
.cases__pair dt{font-size:16px;color:var(--ink-3)}
.cases__pair dd{margin:0;font-size:16px;font-weight:500;color:var(--ink)}

/* the action sits on the floor of the card, never closer than this */
.cases__cta{margin-top:auto}
.cases__meta{margin-bottom:clamp(20px,2.4vw,32px)}

/* slide position, exposed to assistive tech only */
.cases__sr{
  position:absolute;width:1px;height:1px;
  margin:-1px;padding:0;border:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;
}

/* ── controls ────────────────────────────────────────────── */

.cases__foot{
  margin-top:clamp(24px,3vw,40px);
  display:flex;align-items:center;justify-content:space-between;gap:24px;
}
.cases__nav{display:flex;align-items:center;gap:10px}
.cases__arrow{
  width:48px;height:48px;flex:none;
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:var(--r);
  color:var(--ink);
  transition:border-color .3s var(--e-out),background .3s var(--e-out),
             opacity .3s var(--e-out);
}
.cases__arrow svg{width:19px;height:19px}
.cases__arrow:hover{border-color:var(--ink);background:var(--paper-2)}
.cases__arrow:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.cases__arrow[disabled]{opacity:.32;cursor:default}
.cases__arrow[disabled]:hover{border-color:var(--line);background:none}
.cases__count{
  margin-left:8px;
  font-size:14px;letter-spacing:.1em;color:var(--ink-3);
}

/* dots read 8px; the hit box is the 40px square around them
   (padding + background-clip:content-box), so touch never aims at paint */
.cases__dots{
  display:flex;align-items:center;gap:2px;
  margin-inline-end:-16px;
}
.cases__dots > li{display:flex}
.cases__dot{
  display:block;
  width:40px;height:40px;flex:none;
  padding:16px;
  border-radius:var(--r-pill);
  background-color:rgba(10,10,10,.2);
  background-clip:content-box;
  transition:background-color .3s var(--e-out),transform .3s var(--e-out);
}
.cases__dot:hover{background-color:rgba(10,10,10,.42)}
.cases__dot.is-on{background-color:var(--ink);transform:scale(1.25)}
.cases__dot:focus-visible{outline:2px solid var(--ink);outline-offset:-12px}

/* ── the NDA line under the rail ─────────────────────────── */

.cases__ndaline{margin-top:clamp(30px,4vw,52px)}
.cases__nda{
  padding-top:16px;
  font-size:16px;color:var(--ink-3);
}

/* ── responsive ──────────────────────────────────────────── */

@media (max-width:1100px){
  .cases__card{grid-template-columns:42% minmax(0,1fr)}
  .cases__copy{max-width:none}
  .cases__title{max-width:none}
}

@media (max-width:820px){
  .cases__card{grid-template-columns:1fr;min-height:0}
  .cases__shot{
    height:auto;aspect-ratio:16/9;
    border-right:0;border-bottom:1px solid var(--line-soft);
  }
  .cases__meta{gap:6px 20px}
}

@media (max-width:640px){
  .cases{--cases-gap:12px}
  .cases__foot{gap:12px}
  .cases__arrow{width:44px;height:44px}
  .cases__count{display:none}
  .cases__body{padding:22px 20px 24px}
  .cases__cta{width:100%}
}


/* ── inquiry ── */
/* ── 9. inquiry — request sheet + footer ──────────────────────
   Modelled on the reference's closing band: a dark full-bleed
   block, one centred heading, a short lead, then the sheet in the
   middle of the measure. Fields are 46px tall with an 8px radius
   on a translucent ground and a light submit beside them; the
   footer runs on the same dark ground.
   ──────────────────────────────────────────────────────────── */

.inquiry{
  position:relative;
  background:var(--night);
  color:var(--paper);
}

/* padding-block only — the shell owns the gutters */
.inquiry__shell{
  padding-block:var(--band-t) var(--band-b);
}

/* ── head: centred, like the reference's closing headline ─── */

.inquiry__head{
  max-width:760px;margin-inline:auto;text-align:center;
  margin-bottom:clamp(30px,3.4vw,46px);
}
.inquiry__mark{color:rgba(245,242,236,.62);margin-bottom:14px}
.inquiry__title{color:var(--paper)}
.inquiry__title-b{display:block;color:rgba(245,242,236,.5)}
.inquiry__lede{
  margin-top:16px;color:rgba(245,242,236,.66);
  max-width:56ch;margin-inline:auto;
}

/* ── body: the sheet centred, the promises quiet underneath ── */

/* column, not column-reverse. The sheet is written first in inquiry.html
   now, so nothing has to be flipped back into place, and Tab no longer
   leaves the aside's email link to land 774px back up the page in the
   first form field. Reversing here again would restore that failure. */
.inquiry__body{
  max-width:900px;margin-inline:auto;
  display:flex;flex-direction:column;           /* sheet first, promises after */
  gap:clamp(24px,2.6vw,34px);
}

.inquiry__sheet{
  border:1px solid rgba(245,242,236,.13);
  border-radius:var(--r-card);
  background:rgba(245,242,236,.035);
  padding:clamp(22px,2.4vw,32px);
}

.inquiry__cap{
  display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding-bottom:16px;margin-bottom:20px;
  border-bottom:1px solid rgba(245,242,236,.12);
}
.inquiry__cap-l{font-size:16px;font-weight:500;color:var(--paper)}
.inquiry__cap-r{font-size:14px;color:rgba(245,242,236,.5)}

/* ── form ──────────────────────────────────────────────────── */

.inquiry__form{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:16px 18px;
}
.inquiry__field{display:flex;flex-direction:column;gap:7px;min-width:0}
.inquiry__field--full{grid-column:1 / -1}

.inquiry__label{
  font-size:16px;font-weight:400;
  color:rgba(245,242,236,.66);
}

.inquiry__input{
  width:100%;height:46px;
  padding:0 14px;
  font-family:var(--sans);font-size:16px;
  color:var(--paper);
  background:rgba(245,242,236,.06);
  border:1px solid rgba(245,242,236,.14);
  border-radius:8px;
  transition:border-color .2s var(--e-out),background .2s var(--e-out);
  appearance:none;
}
/* the six examples are the fastest way to understand what the form wants,
   and at .36 they were the hardest text on the page to read. The ground
   under them is not the black band: the sheet lays .035 over it and the
   field another .06, so it composites to rgb(22,22,22), and against that
   the old value measured 3.1:1. Sampled off rendered pixels, .48 comes
   out at 4.52:1 and .50 at 4.87:1, so this takes the one with a margin. */
.inquiry__input::placeholder{color:rgba(245,242,236,.5)}
.inquiry__input:hover{border-color:rgba(245,242,236,.24)}
/* no outline:none here. It used to sit at (0,2,0) and beat base.css's
   :where() focus ring, so the page's only conversion path was the one
   place a keyboard user got no ring at all — just a 1px border tint. */
.inquiry__input:focus{
  border-color:rgba(245,242,236,.55);
  background:rgba(245,242,236,.09);
}
/* the script sets aria-invalid on the field it stopped on; without a
   paint the only signal is a status line at the foot of the sheet, which
   for the commodity field is most of a screen away from the problem */
.inquiry__input[aria-invalid="true"]{
  border-color:#ffb3a7;
  background:rgba(255,179,167,.08);
}
.inquiry__area{height:auto;min-height:96px;padding:12px 14px;line-height:1.45;resize:vertical}

.inquiry__select-wrap{position:relative}
.inquiry__select{padding-right:38px;cursor:pointer}
.inquiry__select option{color:var(--ink)}
.inquiry__caret{
  position:absolute;right:14px;top:50%;transform:translateY(-50%);
  pointer-events:none;font-size:14px;color:rgba(245,242,236,.5);
}

/* ── submit row ────────────────────────────────────────────── */

.inquiry__submit-row{
  grid-column:1 / -1;
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  padding-top:4px;
}
.inquiry__submit{
  height:46px;border-radius:8px;
  background:var(--paper);color:var(--night);
  font-size:16px;font-weight:500;
  padding:0 26px;
}
.inquiry__submit:hover{background:#fff;transform:none}
.inquiry__submit[aria-busy="true"]{opacity:.62;pointer-events:none}

.inquiry__status{font-size:16px;line-height:1.4;color:rgba(245,242,236,.7)}
.inquiry__status[data-state="error"]{color:#ffb3a7}
.inquiry__status[data-state="ok"]{color:#7ee2b8}
.inquiry__status a{color:inherit;text-decoration:underline;text-underline-offset:3px}

/* the honeypot. Off screen rather than display:none, which the
   better bots skip: they fill what they can reach, and reaching it
   is the whole point. Never a tab stop, never announced. */
.inquiry__pot{
  position:absolute;left:-9999px;top:auto;
  width:1px;height:1px;overflow:hidden;
}

/* the run with the most legal weight on the page was the least readable
   thing on it: 14px at 3.73:1 and 91 characters to the line. 16px at .58
   measures 6.28:1, and 72ch is a measure rather than a paragraph width. */
.inquiry__legal{
  margin-top:18px;
  max-width:72ch;
  font-size:16px;line-height:1.5;
  color:rgba(245,242,236,.58);
}

/* ── the three promises, one quiet row under the sheet ─────── */

.inquiry__aside{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:20px 28px;
}
.inquiry__points{display:contents}
.inquiry__point{
  display:flex;gap:12px;align-items:flex-start;
  padding-top:16px;border-top:1px solid rgba(245,242,236,.14);
}
.inquiry__point-n{font-size:14px;color:rgba(245,242,236,.55);padding-top:2px}
.inquiry__point-t{font-size:16px;line-height:1.4;color:rgba(245,242,236,.74)}

.inquiry__direct{
  grid-column:1 / -1;
  display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  padding-top:16px;border-top:1px solid rgba(245,242,236,.14);
}
.inquiry__direct-k{font-size:16px;color:rgba(245,242,236,.6)}
.inquiry__direct-v{
  font-size:17px;color:var(--paper);
  border-bottom:1px solid rgba(245,242,236,.3);padding-bottom:2px;
}
.inquiry__direct-v:hover{border-color:var(--paper)}
.inquiry__direct-note{font-size:16px;color:rgba(245,242,236,.58)}

/* ── footer, same ground ───────────────────────────────────── */

.inquiry__footer{
  border-top:1px solid rgba(245,242,236,.14);
  padding-top:clamp(44px,4.6vw,64px);
}
.inquiry__footer-in{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);
  gap:clamp(30px,4vw,64px);
  padding-bottom:clamp(36px,4vw,56px);
}
.inquiry__brand-row{display:flex;align-items:center;gap:11px}
.inquiry__mark-svg{width:26px;height:26px;color:var(--paper)}
.inquiry__wordmark{font-size:18px;font-weight:600;letter-spacing:.18em}
.inquiry__brand-note{
  margin-top:16px;max-width:42ch;
  font-size:16px;line-height:1.5;color:rgba(245,242,236,.56);
}

/* the contact column carries a three-line postal address and the other
   two carry one word per row, so three equal columns starved the only
   one with a measure: the address broke into 4 to 6 ragged lines from
   901px up, orphaning "floor," and "Sheba,". It takes a double track. */
.inquiry__cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,2fr);gap:24px}
.inquiry__col-title{
  font-size:16px;font-weight:500;color:rgba(245,242,236,.6);
  margin-bottom:14px;
}
.inquiry__list li a,
.inquiry__list li span{
  display:block;padding-block:9px;
  font-size:16px;color:rgba(245,242,236,.86);
  transition:color .2s var(--e-out);
}
.inquiry__list li a:hover{color:var(--paper)}
.inquiry__static{color:rgba(245,242,236,.56)!important}

.inquiry__bottom{
  border-top:1px solid rgba(245,242,236,.14);
  padding-block:22px clamp(26px,3vw,38px);
}
.inquiry__copy{
  font-size:16px;line-height:1.55;color:rgba(245,242,236,.58);
  max-width:72ch;
}

/* ── responsive ────────────────────────────────────────────── */

/* The brand block and the link columns stack at the site's own 1040
   breakpoint, exactly as the header does, so the four-column footer
   never runs on a shell that has already given up its wide gutters:
   between 901 and 1040 the address had 130 to 152px to hold a line
   that wants 218. */
@media (max-width:1040px){
  .inquiry__footer-in{grid-template-columns:minmax(0,1fr)}
}

@media (max-width:900px){
  .inquiry__form{grid-template-columns:minmax(0,1fr)}
  .inquiry__aside{grid-template-columns:minmax(0,1fr)}
  .inquiry__cols{grid-template-columns:repeat(2,minmax(0,1fr))}
}

@media (max-width:560px){
  .inquiry__cap{flex-direction:column;gap:6px}
  .inquiry__submit{width:100%}
  .inquiry__cols{grid-template-columns:minmax(0,1fr)}
}
