/* ==========================================================================
   Kilo Peptides — wholesale supply site
   Visual system: minimalist, editorial, architectural.

   Warm cream ground, charcoal type, one rust accent, gray hairlines. Stark
   contrast, heavy negative space, asymmetric composition. No glass, no
   photographic ground, no three-column feature cards.

   THE PALETTE IS MANDATED AND UNIVERSAL. These four values, and only these:

       #FAF9F5  cream      the ground, everywhere
       #141413  charcoal   type, and the dark structural blocks
       #D97757  rust       interactive accent and fills
       #B0AEA5  gray       hairlines and borders

   HOW THEY MAY BE COMBINED IS NOT A STYLE CHOICE, IT IS MEASURED:

       charcoal on cream    17.5:1   body copy, headings, anything
       cream on charcoal    17.5:1   dark inverted sections
       rust on charcoal      5.9:1   accent type inside dark blocks
       charcoal on rust      5.9:1   type sitting ON a rust button
       rust on cream         2.96:1  FILL ONLY -- never type
       cream on rust         2.96:1  NEVER. A rust button takes charcoal
                                     type, not white. This is the one that
                                     gets built wrong by reflex.
       gray on cream         2.11:1  hairlines only, never type

   Rust at 2.96:1 against cream also sits a hair under the 3:1 a UI control
   needs to be identifiable by its boundary, so interactive rust fills carry
   a charcoal edge rather than floating on the cream unbordered.

   MOTION is spring, not linear. --ease-spring overshoots slightly and settles;
   linear fades are what make a page feel like a template. Everything is
   inside a prefers-reduced-motion guard.
   ========================================================================== */

:root{
  /* --- the four --------------------------------------------------------- */
  --cream:#FAF9F5;
  --charcoal:#141413;
  --rust:#D97757;
  --gray:#B0AEA5;

  /* Derived tints, all from the four above. Kept few on purpose: a long ramp
     of near-identical greys is how a stark palette turns muddy. */
  --cream-2:#F2F0E9;          /* a barely-there band, for alternating sections */
  --charcoal-70:#5C5B58;      /* secondary type -- 6.45:1 cream, 5.96 raised  */
  /* Tertiary type. #767470 was here, documented as 4.54:1 -- it actually
     measures 4.43 on cream and 4.09 on the raised band, so it failed AA for
     normal text in all 31 places it was used: SKUs, spec-table keys, form
     hints, footer headings, table headers, tab subtitles. #6D6D61 is the same
     warm neutral hue at 4.97 on cream and 4.59 raised, passing on both. */
  --charcoal-50:#6D6D61;      /* tertiary type  -- 4.97:1 cream, 4.59 raised  */
  --rust-deep:#C25E3F;        /* hover only; never a text colour on cream     */
  /* #B0AEA5 is the mandated border colour and this is where it belongs:
     decorative separators between blocks. It measures 2.11:1 on cream, which
     is right for a hairline and NOT enough for anything a user has to find
     and click -- so control boundaries use --hair-strong below. */
  --hair:var(--gray);
  /* Control boundaries: inputs, selects, the things a 3:1 identifiability
     requirement actually applies to. */
  --hair-strong:rgba(20,20,19,.34);

  /* --- semantic aliases --------------------------------------------------
     The 1,400 lines of component CSS below were written against these names. */
  --paper:var(--cream);
  --paper-2:var(--cream);
  --paper-3:var(--cream-2);
  --ink:var(--charcoal);
  --ink-2:var(--charcoal-70);
  --ink-3:var(--charcoal-50);
  --line:var(--hair);
  --line-2:var(--hair-strong);

  --accent:var(--rust);
  --accent-text:var(--charcoal);   /* rust cannot be type on cream */
  --accent-soft:rgba(217,119,87,.10);
  --accent-on:var(--charcoal);     /* type ON a rust fill */
  --accent-hover:var(--rust-deep);
  --focus:var(--charcoal);

  --scrim:rgba(20,20,19,.42);
  --blue:#5C5B58; --blue-text:var(--charcoal-70); --blue-soft:var(--cream-2);
  --green:#4F6B52; --green-text:#3D5540; --green-soft:rgba(79,107,82,.10);
  --clay:#A8452A;                  /* warnings: 5.8:1 on cream */

  --promo-bg:var(--charcoal);
  --promo-ink:var(--cream);

  /* Editorial pages do not float. Elevation is a hairline and a lot of
     space, not a drop shadow. */
  --shadow:none;
  --shadow-lift:0 10px 30px rgba(20,20,19,.09);

  --radius:4px;
  --radius-lg:6px;
  --maxw:1240px;

  /* --- type -------------------------------------------------------------
     Space Grotesk for headings (quirky geometric grotesque — closer to the
     Styrene-like Anthropic/Geist register than Poppins). Source Serif 4 for
     reading (editorial text serif, Tiempos-adjacent free stand-in). Fluid
     throughout: every size below is a clamp() so the scale compresses on a
     phone instead of stepping at a breakpoint. --type-scale is the editor's
     size control. */
  --type-scale:1;
  --serif:"Source Serif 4", Georgia, "Times New Roman", serif;
  --display:"Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --body:"Source Serif 4", Georgia, "Times New Roman", serif;
  --data:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --step--1:clamp(.92rem, .88rem + .18vw, 1.00rem);
  --step-0 :clamp(1.06rem, 1.00rem + .28vw, 1.18rem);
  --step-1 :clamp(1.28rem, 1.16rem + .55vw, 1.55rem);
  --step-2 :clamp(1.60rem, 1.35rem + 1.10vw, 2.25rem);
  --step-3 :clamp(2.05rem, 1.60rem + 2.10vw, 3.30rem);
  --step-4 :clamp(2.60rem, 1.80rem + 4.00vw, 5.20rem);
  --step-5 :clamp(3.20rem, 1.70rem + 7.00vw, 7.50rem);

  /* --- motion ------------------------------------------------------------
     Spring, not linear. The overshoot is small on purpose: enough to feel
     physical, not enough to look bouncy on a wholesale supply site. */
  --dur:.34s;
  --dur-slow:.62s;
  --ease:cubic-bezier(.2,.8,.2,1);
  --ease-spring:cubic-bezier(.34,1.56,.5,1);
  --lift:-3px;
}

html{background:var(--cream)}

/* ==========================================================================
   THE GROUND
   ==========================================================================
   A flat expanse of #FAF9F5 across a whole viewport is harsh -- it glares,
   and it makes the page feel like an unstyled document. So the Flatirons
   photograph stays, but inverted from how it was used before: instead of a
   dark scrim holding a bright photo down, a CREAM scrim holds it up.

   The scrim used to sit at ~.80–.88 cream, which buried the Flatirons into
   anonymous paper tone. It was then lightened to .58–.70 so mountains read
   through mid-page panels — and charcoal body copy on that composite failed
   on a phone: Published Pricing sat on bare photograph and the SKU rows were
   unreadable. Desktop keeps a lighter mid-stop so the rock still shows;
   phones and the price list get an opaque cream band of their own. */
body::before{
  content:"";
  position:fixed;
  inset:0;
  z-index:-2;
  pointer-events:none;
  background:
    linear-gradient(180deg,
      rgba(250,249,245,.82) 0%,
      rgba(250,249,245,.74) 42%,
      rgba(250,249,245,.80) 100%),
    var(--ground-photo, none) center center / cover no-repeat,
    var(--cream);
}
body[data-ground="flatirons"]{--ground-photo:url("/img/ground-flatirons-2560.jpg")}
body[data-ground="hanginglake"]{--ground-photo:url("/img/ground-hanginglake-2560.jpg")}
body[data-ground="tetons"]{--ground-photo:url("/img/ground-tetons-2560.jpg")}
body[data-ground="none"]{--ground-photo:none}
/* The console gets a plain ground. A photograph behind a two-hundred-row
   order table is texture competing with the only thing on the page anyone is
   trying to read -- the storefront can afford atmosphere, a data view
   cannot. */
body.is-admin{--ground-photo:none}
body.is-admin::before{background:var(--cream)}
@media (max-width:900px){
  body[data-ground="flatirons"]{--ground-photo:url("/img/ground-flatirons-1400.jpg")}
  body[data-ground="hanginglake"]{--ground-photo:url("/img/ground-hanginglake-1400.jpg")}
  /* Phones crop the photograph into high-contrast forest texture under the
     mid-page. Raise the cream until charcoal type clears, even if the rock
     reads only as warmth. */
  body::before{
    background:
      linear-gradient(180deg,
        rgba(250,249,245,.94) 0%,
        rgba(250,249,245,.90) 45%,
        rgba(250,249,245,.93) 100%),
      var(--ground-photo, none) center center / cover no-repeat,
      var(--cream);
  }
}

/* The one place the photograph is a photograph. A charcoal block bled to the
   full width with the image behind it, cream type on top -- the stark
   cream/charcoal contrast the brief asks for, with the picture supplying the
   texture rather than a flat black rectangle. */
.block-dark{
  position:relative;
  background:var(--charcoal);
  color:var(--cream);
  isolation:isolate;
}
.block-dark::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  pointer-events:none;
  background:
    linear-gradient(100deg, rgba(20,20,19,.90) 0%, rgba(20,20,19,.66) 55%, rgba(20,20,19,.52) 100%),
    var(--ground-photo, none) center 38% / cover no-repeat,
    var(--charcoal);
}
.block-dark h1,.block-dark h2,.block-dark h3,.block-dark h4{color:var(--cream)}
.block-dark p{color:rgba(250,249,245,.82)}
/* Rust is 5.9:1 on charcoal, so inside a dark block it CAN be type -- the one
   place in the design where that is true. */
.block-dark .label,.block-dark .accent{color:var(--rust)}


*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none !important}
html{
  -webkit-text-size-adjust:100%;
  overflow-x:clip;
}
body{
  margin:0;
  overflow-x:clip;
  /* Transparent on purpose: the ground photograph and its cream scrim are
     painted by the fixed body::before above, and any background here would
     bury them. */
  background:transparent;
  color:var(--ink);
  font-family:var(--body);
  font-size:18px;
  line-height:1.65;
  min-height:100vh;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
}
img{max-width:100%;display:block}
a{color:var(--accent-text)}
button,input,select,textarea{font-family:var(--display);color:inherit}

.wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px}
.wrap-narrow{max-width:800px;margin:0 auto;padding:0 24px}

/* ---------- type ----------
   Space Grotesk for every heading, Source Serif 4 for reading. Quirky
   grotesque over a news serif is the Anthropic/Geist-adjacent register —
   technical and a little human — without shipping proprietary faces.

   Every size is a clamp() rather than a breakpoint step, so the scale
   compresses continuously from desktop to phone. --type-scale multiplies the
   lot, which is what the editor's text-size control moves. */
h1,h2,h3,h4{
  font-family:var(--display);
  margin:0 0 .45em;
  font-weight:600;
  letter-spacing:-.028em;
  line-height:1.04;
  text-wrap:balance;
  color:var(--charcoal);
}
h1{font-size:calc(var(--step-4) * var(--type-scale));letter-spacing:-.038em;font-weight:500}
h2{font-size:calc(var(--step-3) * var(--type-scale));letter-spacing:-.032em;font-weight:500}
h3{font-size:calc(var(--step-1) * var(--type-scale));letter-spacing:-.016em;line-height:1.2;font-weight:600}
h4{font-size:calc(var(--step-0) * var(--type-scale));letter-spacing:-.01em}

p{margin:0 0 1.15em}

/* The oversized editorial opener. Used once per page at most -- its whole
   value is that it is bigger than anything else on the screen. */
.h-display{
  font-family:var(--display);font-weight:600;
  font-size:calc(var(--step-5) * var(--type-scale));
  line-height:.94;letter-spacing:-.042em;text-wrap:balance;margin:0 0 .3em;
}

.data{font-family:var(--data);font-variant-numeric:tabular-nums;letter-spacing:.01em}
p{margin:0 0 1em}
.lede{font-size:clamp(1.12rem,1.8vw,1.28rem);color:var(--ink-2);line-height:1.6;max-width:62ch}
.label{
  font-family:var(--display);font-size:.7rem;font-weight:500;letter-spacing:.15em;
  text-transform:uppercase;color:var(--accent-text);display:block;margin:0 0 14px;
}
.label-muted{color:var(--ink-3)}
.card-key.label-muted{color:var(--ink-3)}
.ui{font-family:var(--display)}
.num{font-variant-numeric:tabular-nums}
.small{font-size:.92rem}
.muted{color:var(--ink-3)}
.nowrap{white-space:nowrap}

/* ---------- announcement bar ---------- */
.promo{
  background:var(--promo-bg);color:var(--promo-ink);font-family:var(--display);
  font-size:.82rem;text-align:center;padding:10px 20px;line-height:1.4;
}
.promo strong{font-weight:600}
.promo a{color:var(--promo-ink);text-decoration:underline;text-underline-offset:2px}

/* ---------- header ---------- */
.site-head{
  position:sticky;top:0;z-index:60;background:var(--paper);
  border-bottom:1px solid var(--line);
}
.head-row{display:flex;align-items:center;gap:28px;height:70px}
.brand{display:flex;align-items:center;gap:11px;text-decoration:none;color:inherit;flex:0 0 auto}
.brand-mark{
  width:32px;height:32px;border-radius:7px;background:var(--accent);color:var(--accent-on);
  display:grid;place-items:center;font-family:var(--display);font-weight:600;font-size:.8rem;
  letter-spacing:-.02em;flex:0 0 auto;
}
.brand-name{font-family:var(--display);font-weight:600;letter-spacing:-.03em;font-size:1.08rem;display:block}
.brand-sub{font-family:var(--display);font-size:.6rem;font-weight:500;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);display:block;margin-top:-2px}
.nav{display:flex;gap:2px;margin-left:auto;align-items:center;font-family:var(--display)}
.nav a{
  text-decoration:none;font-size:.9rem;color:var(--ink-2);padding:9px 13px;border-radius:var(--radius);
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease);
}
.nav a:hover{background:var(--paper-3);color:var(--ink)}
.nav a.is-active{color:var(--ink);font-weight:500}
.nav a.nav-cta{margin-left:10px;color:var(--accent-on)}
.nav a.nav-cta:hover{color:var(--accent-on);background:var(--accent-hover)}
.burger{display:none;margin-left:auto;background:none;border:1px solid var(--line-2);border-radius:var(--radius);padding:9px 11px;cursor:pointer}
.burger span{display:block;width:18px;height:1.5px;background:var(--ink);margin:3.5px 0}

html.nav-open{overflow:hidden}
@media (max-width:940px){
  .nav{
    position:fixed;inset:70px 0 auto 0;flex-direction:column;align-items:stretch;gap:0;
    background:var(--paper);border-bottom:1px solid var(--line);padding:8px 16px 18px;
    display:flex;
    visibility:hidden;opacity:0;pointer-events:none;
    transform:translate3d(0,-10px,0);
    transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),visibility 0s linear var(--dur);
    box-shadow:var(--shadow);

    /* The drawer must scroll on its own.

       On a phone the two mega panels are forced open and stacked inside this
       drawer (see the max-width:940px block further down), so it holds seven
       nav links, six product groups, eleven service links and the account row.
       That is taller than any phone. Without a height cap it simply ran off
       the bottom of the screen: the drawer is positioned, so the page behind
       it scrolls instead, and the links past the fold could not be reached at
       all.

       dvh, not vh: on iOS Safari 100vh is the height of the viewport WITHOUT
       the address bar, so a vh-based cap is taller than the visible screen and
       reintroduces the same unreachable strip. dvh tracks the bar as it hides
       and shows. The vh line above it is the fallback for browsers that do not
       know dvh -- slightly too tall there, but scrollable, which is the point.

       overscroll-behavior stops a flick at the end of the list from chaining
       into the page underneath and closing the drawer out from under a thumb. */
    max-height:calc(100vh - 88px);
    max-height:calc(100dvh - 88px);
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    overscroll-behavior:contain;
  }
  .nav.is-open{
    visibility:visible;opacity:1;pointer-events:auto;transform:none;
    transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),visibility 0s;
  }
  .nav a{padding:14px 8px;border-bottom:1px solid var(--line)}
  .nav-cta{margin:12px 0 0}
  .burger{display:block}
}

/* ---------- buttons ---------- */
/* Soft rectangles, not stadium pills. A 6px corner matches the rest of the
   token radius and reads closer to a research brand than a consumer SaaS
   template. The 2px border is not decoration: primary and ghost are told
   apart by weight, and a 2px edge survives a glance where a hairline does not. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  font-family:var(--display);padding:12px 24px;border-radius:6px;
  border:2px solid transparent;font-size:.92rem;font-weight:600;text-decoration:none;cursor:pointer;
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease),color var(--dur) var(--ease),transform 220ms var(--ease);
  white-space:nowrap;
}
.btn:active{transform:translateY(1px)}
.btn[disabled]:active{transform:none}
.btn-primary{background:var(--accent);color:var(--accent-on);border-color:var(--accent)}
.btn-primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn-ghost:hover{background:var(--paper-3)}
.btn-dark{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.btn-dark:hover{opacity:.88}
.btn-sm{padding:8px 14px;font-size:.83rem}
.btn-block{width:100%}
.btn[disabled]{opacity:.42;cursor:not-allowed}

/* ---------- gate ---------- */
.gate{
  position:fixed;inset:0;z-index:200;background:var(--paper);
  display:flex;justify-content:center;padding:28px 24px;overflow-y:auto;
}
.gate-card{max-width:580px;width:100%;text-align:left;margin:auto}
.gate-card .brand-mark{width:46px;height:46px;font-size:1.05rem;border-radius:10px;margin-bottom:22px}
.gate h1{font-size:clamp(1.6rem,3.8vw,2.15rem);margin-bottom:16px}
.gate-terms{border:1px solid var(--line);border-radius:var(--radius-lg);padding:20px 22px;background:var(--paper-2);margin:24px 0}
.gate-terms li{margin-bottom:12px}
.gate-terms li:last-child{margin-bottom:0}
.gate-actions{display:flex;gap:12px;flex-wrap:wrap}

/* ---------- sections ---------- */
.section{padding:86px 0}
.section + .section{border-top:1px solid var(--line)}
.section-band{background:var(--paper-3);border-radius:var(--radius-lg);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.section-band + .section{border-top:0}
.section-tight{padding:56px 0}
.hero{padding:88px 0 78px}
@media (max-width:700px){.section{padding:56px 0}.hero{padding:52px 0 48px}}

.section-head{max-width:64ch;margin-bottom:46px}
@media (max-width:960px){.hero-grid{grid-template-columns:1fr;gap:40px}}
.hero-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:30px}

/* ---------- feature blocks (4-up) ---------- */
@media (max-width:900px){.features{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.features{grid-template-columns:1fr}}

/* ---------- cards / grids ---------- */
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.grid-2{display:grid;grid-template-columns:repeat(2,1fr);gap:24px}
@media (max-width:900px){.grid-3{grid-template-columns:repeat(2,1fr)}}
@media (max-width:620px){.grid-3,.grid-2{grid-template-columns:1fr}}

.card{background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius-lg);padding:26px 24px}
.card h3{margin-bottom:10px}
.card p:last-child{margin-bottom:0}
.card-key{
  font-family:var(--display);font-size:.68rem;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent-text);display:block;margin-bottom:14px;
}

.steps{counter-reset:step;display:grid;gap:1px;background:var(--line);border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden}
.step{background:var(--paper-2);padding:26px 24px;display:grid;grid-template-columns:44px 1fr;gap:18px;align-items:start}
.step-n{
  font-family:var(--display);font-size:.8rem;font-weight:600;color:var(--accent-on);background:var(--accent);
  border-radius:50%;width:30px;height:30px;display:grid;place-items:center;
}
.step h3{margin-bottom:5px}
.step p{margin:0;color:var(--ink-2);font-size:.94rem}
@media (max-width:620px){.step{grid-template-columns:1fr;gap:12px}}

/* ---------- price / tier showcase ---------- */
.tier-showcase{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
@media (max-width:820px){.tier-showcase{grid-template-columns:1fr}}
.tier-card{
  background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:26px 24px;display:flex;flex-direction:column;gap:10px;
}
.tier-card.is-only{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.tier-card.is-off{opacity:.62}
.tier-price{font-family:var(--display);font-size:2rem;font-weight:600;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.tier-strike{text-decoration:line-through;color:var(--ink-3)}

/* ---------- catalog ---------- */
.catalog-bar{
  display:grid;grid-template-columns:1fr auto auto auto;gap:12px;align-items:center;
  padding:18px 0;position:sticky;top:70px;z-index:40;background:var(--paper);
  border-bottom:1px solid var(--line);
}
@media (max-width:820px){.catalog-bar{grid-template-columns:1fr 1fr;position:static}}
.field{
  display:flex;align-items:center;gap:8px;background:var(--paper-2);
  border:1px solid var(--line-2);border-radius:var(--radius);padding:0 13px;height:44px;
}
.field:focus-within{border-color:var(--focus);box-shadow:0 0 0 3px var(--focus)}
.field input,.field select{border:0;background:transparent;outline:none;width:100%;height:100%;font-size:.92rem}
.field select{cursor:pointer;-webkit-appearance:none;appearance:none;padding-right:14px}
.field svg{flex:0 0 auto;opacity:.5}

.catalog-results{min-height:min(46vh,32rem)}
.catalog-results .empty{margin-top:0}
.prod-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:24px}
@media (max-width:1240px){.prod-grid{grid-template-columns:repeat(3,1fr)}}
@media (max-width:1000px){.prod-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:640px){.prod-grid{grid-template-columns:1fr}}

.prod{
  background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius);padding:14px;
  display:flex;flex-direction:column;gap:9px;cursor:pointer;
  content-visibility:auto;contain-intrinsic-size:auto 22rem;
}
.prod-img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--radius);background:var(--paper-3);margin-bottom:2px}
.prod-top{display:flex;justify-content:space-between;gap:8px;align-items:flex-start}
.prod-name{font-family:var(--display);font-size:1.05rem;font-weight:600;letter-spacing:-.02em;margin:0;line-height:1.3}
.prod-name-sub{font-size:.82em;font-weight:500;color:var(--ink-2);letter-spacing:0}
.prod-sku{font-family:var(--display);font-size:.8rem;color:var(--ink-2);letter-spacing:.05em;margin-top:2px}
.tag{
  font-family:var(--display);font-size:.64rem;font-weight:500;letter-spacing:.11em;text-transform:uppercase;
  padding:4px 9px;border-radius:20px;background:var(--paper-3);color:var(--ink-2);white-space:nowrap;
}
.tag-ok{background:var(--green-soft);color:var(--green-text)}
.tag-gated{background:var(--accent-soft);color:var(--accent-text)}
.tag-warn{background:var(--accent-soft);color:var(--accent-text)}
.tag-info{background:var(--blue-soft);color:var(--blue-text)}
.tag-accent{background:var(--accent-soft);color:var(--accent-text)}

.spec{display:grid;grid-template-columns:auto 1fr;gap:3px 10px;font-size:.79rem;margin:0;font-family:var(--display);line-height:1.35}
.spec dt{color:var(--ink-2);font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;padding-top:2px;font-weight:500}
.spec dd{margin:0;color:var(--ink)}

.tiers{width:100%;border-collapse:collapse;font-size:.9rem;font-family:var(--display);font-variant-numeric:tabular-nums}
.tiers th{
  text-align:left;font-size:.72rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-3);font-weight:500;padding:0 0 7px;border-bottom:1px solid var(--line);
}
.tiers td{padding:5px 0;border-bottom:1px solid var(--line)}
.tiers td:last-child,.tiers th:last-child{text-align:right}
.tiers tr:last-child td{border-bottom:0}

.price-locked{
  display:flex;align-items:center;gap:7px;font-family:var(--display);font-size:.78rem;color:var(--ink-2);
  background:var(--paper-3);border-radius:var(--radius);padding:8px 10px;
}
.prod-foot{margin-top:auto;display:flex;gap:7px;align-items:center;padding-top:2px}

.ruo{
  font-family:var(--display);font-size:.68rem;line-height:1.5;color:var(--ink-2);
  margin:18px 0 0;padding-top:14px;border-top:1px solid var(--line);max-width:none;
}
.ruo strong{font-weight:600}
.ruo a{color:var(--accent-text)}

.empty{text-align:center;padding:70px 20px;border:1px dashed var(--line-2);border-radius:var(--radius-lg);color:var(--ink-3);margin-top:30px}

.notice{
  display:flex;gap:12px;align-items:flex-start;border:1px solid var(--line);
  border-left:3px solid var(--accent);background:var(--accent-soft);
  padding:15px 17px;border-radius:var(--radius);font-size:.92rem;color:var(--ink-2);margin:24px 0;
}
.notice strong{color:var(--ink)}
.notice-info{border-left-color:var(--blue);background:var(--blue-soft)}
.notice-ok{border-left-color:var(--green);background:var(--green-soft)}

.qty-in{width:96px;border:1px solid var(--line-2);border-radius:var(--radius);padding:8px 9px;background:var(--paper-2);font-size:.86rem;font-variant-numeric:tabular-nums}

/* ---------- forms ---------- */
.form-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
@media (max-width:700px){.form-grid{grid-template-columns:1fr}}
.form-row{display:flex;flex-direction:column;gap:7px}
.form-row.full{grid-column:1/-1}
label{font-family:var(--display);font-size:.84rem;font-weight:500;color:var(--ink-2)}
label .req{color:var(--accent-text)}
input[type=text],input[type=email],input[type=tel],input[type=url],input[type=number],select,textarea{
  width:100%;background:var(--paper-2);border:2px solid var(--line-2);border-radius:var(--radius);
  padding:12px 13px;font-size:.93rem;outline:none;transition:border-color .12s,box-shadow .12s;
}
textarea{min-height:110px;resize:vertical;font-family:var(--body)}
input:focus,select:focus,textarea:focus{border-color:var(--focus);box-shadow:0 0 0 3px var(--focus)}
.check{display:flex;gap:11px;align-items:flex-start;font-family:var(--display);font-size:.88rem;color:var(--ink-2);line-height:1.5}
.check input{margin-top:3px;flex:0 0 auto;width:17px;height:17px;accent-color:var(--accent)}
.form-hint{font-family:var(--display);font-size:.86rem;color:var(--ink-2)}
fieldset{border:1px solid var(--line);border-radius:var(--radius-lg);padding:26px;margin:0 0 24px;background:var(--paper-2)}
legend{font-family:var(--display);font-size:.68rem;font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text);padding:0 8px}

/* ---------- tables ---------- */
.table-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--paper-2)}
table.data{width:100%;border-collapse:collapse;font-size:.92rem;min-width:600px}
table.data th{
  text-align:left;font-family:var(--display);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-3);font-weight:500;padding:15px 18px;border-bottom:1px solid var(--line);background:var(--paper-3);
}
table.data td{padding:15px 18px;border-bottom:1px solid var(--line);vertical-align:top;color:var(--ink-2)}
table.data td strong{color:var(--ink);font-family:var(--display);font-weight:600;font-size:.92rem}
table.data tr:last-child td{border-bottom:0}

/* ---------- prose ---------- */
.prose h2{margin-top:2.2em}
.prose h2:first-child{margin-top:0}
.prose h3{margin-top:1.8em}
.prose ul,.prose ol{padding-left:1.2em;margin:0 0 1.1em;color:var(--ink-2)}
.prose li{margin-bottom:.5em}
.prose p{color:var(--ink-2)}
.prose strong{color:var(--ink);font-weight:600}

/* ---------- footer ---------- */
.site-foot{border-top:1px solid var(--line);background:var(--paper-2);padding:58px 0 32px}
.foot-grid{display:grid;grid-template-columns:1.5fr repeat(3,1fr);gap:36px}
@media (max-width:820px){.foot-grid{grid-template-columns:1fr 1fr;gap:28px}}
.foot-col h4{font-family:var(--display);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);font-weight:500;margin-bottom:14px}
.foot-col a{display:block;text-decoration:none;color:var(--ink-2);font-family:var(--display);font-size:.89rem;padding:5px 0}
.foot-col a:hover{color:var(--accent-text)}
.foot-bottom{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-top:18px;font-family:var(--display);font-size:.79rem;color:var(--ink-3)}
.foot-meta{display:inline-flex;align-items:center;gap:14px;flex-wrap:wrap}
.foot-admin{
  color:var(--ink-3);text-decoration:none;letter-spacing:.04em;
  opacity:.55;transition:opacity .15s,color .15s;
}
.foot-admin:hover{opacity:1;color:var(--charcoal);text-decoration:underline;text-underline-offset:3px}

.skip{position:absolute;left:-9999px}
.skip:focus{left:16px;top:12px;z-index:300;background:var(--ink);color:var(--paper);padding:9px 14px;border-radius:var(--radius)}
:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
/* Reduced motion must not nuke discrete overlay/visibility, or drawers and
   dialogs pop with no closed state at all. Instant settling, not display:none. */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  .mega,.nav,.sheet-dialog,.sheet-dialog::backdrop,.btn,.nav a,.mega-trigger .caret,
  .mega-cta,.head-search,.head-cart,.card,.prod,.feat-row a{
    transition:none!important;animation:none!important;transform:none!important;
    clip-path:none!important;
  }
}


/* ==========================================================================
   Admin console — dense operations layer
   Appended section, plus the token block above: --accent-hover and --scrim
   were added there (and two raw hex values / one raw rgba() above this
   comment were pointed at them) to get the whole file to zero raw colors —
   same computed values, so storefront output is unaffected. No other
   storefront rule above this comment was touched.
   Same token system as the storefront. --display (Poppins) is used for
   every rule below — no serif anywhere in the admin.
   ========================================================================== */

/* ---------- console shell ---------- */
/* ---------- admin console: the same palette, pitched down ----------------
   The storefront ground is a vivid cornflower because it has ten seconds to
   convince someone. The console is where the day is spent — reading tables,
   comparing numbers, scanning for the row that needs attention — and a
   saturated ground fights that: it wins every contrast comparison against
   the data sitting on it, so nothing on the page can look more urgent than
   the background does.

   So the console takes the same family one step darker. Indigo night is the
   ground, indigo the panels, and cornflower is demoted from ground to
   ACCENT — it now marks the current nav item, which is the one place the
   brand colour earns its loudness. Yellow stays what it has always been:
   the thing that means act here, spent only on counts and focus rings.
   Same palette, different register. Nothing here is a new colour. */
/* The admin console keeps the storefront's palette and changes only the
   DENSITY. Surfaces are opaque rather than translucent because a two-hundred-
   row order table is the one place translucency costs more than it returns.
   Ink and accent tokens are inherited, not restated. */
body.is-admin{
  --paper:var(--cream);
  --paper-2:var(--cream);
  --paper-3:var(--cream-2);   /* side rail, one step off the ground */
  /* Hairlines, NOT --cream-2. That value is 1.08:1 against the ground, so
     pointing --line at it erased every border in the console at once --
     table rows, the side rail, the KPI tiles, the editor panels. */
  --line:var(--hair);
  --line-2:var(--hair-strong);
  --shadow:0 1px 0 rgba(0,0,0,.35);
}

/* Current page. Sage rather than rust: rust is reserved for "something needs
   you", and where you already are is not that. The count pills below stay rust
   and stay louder, because they are the thing that needs you. */
body.is-admin .adm-navi a.on{
  background:rgba(79,107,82,.12);color:var(--ink);font-weight:600;
  box-shadow:inset 3px 0 0 var(--charcoal-50);
}
body.is-admin .adm-navi a:hover{background:var(--cream-2)}
/* Counts ARE "something needs you" — this is the loud element on the page. */
/* Rust fill, charcoal type: 5.9:1. This used to be --focus on --accent-on,
   which was fine when those were yellow-on-indigo and became charcoal on
   charcoal -- a 1:1 black blob -- the moment the palette went light. These
   are the pending-account and awaiting-payment counters, so an invisible
   one is a missed order. */
body.is-admin .adm-navi .pill{background:var(--rust);color:var(--charcoal)}
/* Same rule for the tiles. .kpi.act marks the two that are a queue of work —
   pending accounts, orders awaiting payment — so their edge is the yellow
   that means act here, not the neutral white the other tiles carry. Without
   this the console says "yellow = attention" in the nav and something else
   entirely eight pixels away. */
body.is-admin .kpi.act::before{background:var(--focus)}

/* .adm-top is a direct grid child (sibling of .adm-side and .adm-main) via
   named grid areas, rather than nested inside .adm-main, so the responsive
   rule below can place the mobile nav strip between the page title row and
   the page content without having to reach inside another grid item. */
.adm{
  display:grid;grid-template-columns:186px 1fr;
  grid-template-areas:"side top" "side main";
  min-height:70vh;font-family:var(--display);
}
@media (max-width:860px){
  /* Below 860px there is no room for a persistent side rail. Hiding it
     outright (the old rule) left every admin page but the dashboard with no
     way to reach Accounts, Catalog, Settings, Messages, etc. Instead the
     rail becomes a horizontal, keyboard-reachable strip under the page
     title rather than disappearing. */
  .adm{grid-template-columns:1fr;grid-template-areas:"top" "side" "main"}
  .adm-side{
    flex-direction:row;align-items:center;overflow-x:auto;-webkit-overflow-scrolling:touch;
    border-right:0;border-bottom:1px solid var(--line);
  }
  .adm-brand,.adm-user{display:none}
  .adm-navi{flex-direction:row;gap:4px;padding:8px 12px}
  .adm-navi a{white-space:nowrap}
}

/* ---------- console chrome (header / footer) ---------- */
/* Deliberately not .nav: that class hides itself behind a .burger below
   940px with no admin burger to reopen it, which would make "View
   storefront" and "Log out" unreachable on a phone. This is its own,
   always-visible, always-reachable strip. */
.adm-head .head-row{flex-wrap:wrap}
.adm-head-nav{display:flex;align-items:center;gap:6px;margin-left:auto;font-family:var(--display)}
.adm-head-nav a{
  text-decoration:none;font-size:.86rem;color:var(--ink-2);padding:9px 13px;border-radius:var(--radius);
  transition:background .12s,color .12s;
}
.adm-head-nav a:hover{background:var(--paper-3);color:var(--ink)}
.adm-head-nav form{margin:0}
@media (max-width:480px){.adm-head .head-row{height:auto;padding:10px 0;row-gap:6px}}

footer.adm-foot{padding:20px 0}
.adm-foot-row{
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  font-family:var(--display);font-size:.79rem;color:var(--ink-3);
}

.adm-side{grid-area:side;background:var(--paper-3);border-right:1px solid var(--line);display:flex;flex-direction:column}
.adm-brand{padding:18px 16px;border-bottom:1px solid var(--line)}

.adm-navi{display:flex;flex-direction:column;gap:2px;padding:12px 10px}
.adm-navi a{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  font-family:var(--display);font-size:.75rem;color:var(--ink-2);text-decoration:none;
  padding:9px 12px;border-radius:99px;transition:background .12s,color .12s;
}
.adm-navi a:hover{background:var(--paper-2)}
.adm-navi a.on{background:var(--paper-2);color:var(--ink);font-weight:500;box-shadow:var(--shadow)}
.adm-navi .pill{
  font-family:var(--display);font-size:.66rem;font-weight:600;line-height:1;
  background:var(--accent);color:var(--accent-on);border-radius:99px;padding:2px 7px;
  font-variant-numeric:tabular-nums;
}

.adm-user{margin-top:auto;border-top:1px solid var(--line);padding:14px 16px;font-family:var(--display);font-size:.72rem;color:var(--ink-3)}

.adm-main{grid-area:main;padding:0 32px 28px;min-width:0}

.adm-top{grid-area:top;padding:28px 32px 0;display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:24px;min-width:0}
.adm-h1{font-family:var(--display);font-size:1.25rem;font-weight:600;letter-spacing:-.02em;margin:0}
.adm-sec{font-family:var(--display);font-size:.8125rem;font-weight:600;display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}

/* ---------- KPI tiles ---------- */
.kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
@media (max-width:860px){.kpis{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* KPI tiles double as an <a>, since several are actionable links straight
   into a filtered list — these rules are harmless no-ops on the plain <div>
   tiles that aren't (Payments, Emails). */
.kpi{position:relative;display:block;background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px 14px 18px;overflow:hidden;text-decoration:none;color:inherit;transition:border-color .12s}
a.kpi:hover{border-color:var(--line-2)}
.kpi::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--line-2)}
.kpi.act::before{background:var(--accent)}
.kpi.good::before{background:var(--green)}
.kpi.inf::before{background:var(--blue)}

.adm-health{
  display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px;
  margin-bottom:22px;
}
@media (max-width:1100px){.adm-health{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:640px){.adm-health{grid-template-columns:repeat(2,minmax(0,1fr))}}
.adm-health-item{
  border:1px solid var(--line);border-radius:var(--radius);
  background:var(--paper-2);padding:12px 14px;
}
.adm-health-item.is-ok{border-color:rgba(46,125,50,.28)}
.adm-health-item.is-warn{border-color:rgba(183,110,42,.35);background:rgba(183,110,42,.06)}
.adm-health-k{
  display:block;font-family:var(--display);font-size:.68rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-bottom:4px;
}
.adm-health-v{font-family:var(--display);font-size:.9rem;font-weight:500;color:var(--ink)}
.adm-split{display:grid;grid-template-columns:1.4fr 1fr;gap:28px}
@media (max-width:900px){.adm-split{grid-template-columns:1fr}}
.adm-bars{list-style:none;margin:0;padding:0}
.adm-bars li{display:grid;grid-template-columns:42px 1fr 40px;gap:10px;align-items:center;margin-bottom:6px}
.adm-bars-d,.adm-bars-n{font-family:var(--data);font-size:.75rem;color:var(--ink-3)}
.adm-bars-n{text-align:right}
.adm-bars-track{height:8px;background:var(--paper-3);border-radius:99px;overflow:hidden}
.adm-bars-fill{display:block;height:100%;background:var(--accent);border-radius:99px}
.adm-status-list{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.adm-status-list li a{
  display:flex;justify-content:space-between;gap:12px;padding:12px 0;
  border-bottom:1px solid var(--line);text-decoration:none;color:inherit;
  font-family:var(--display);font-size:.9rem;
}
.adm-status-list li a:hover{color:var(--accent)}
.adm-passkey-list{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.adm-passkey-list li{
  display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:12px 0;border-bottom:1px solid var(--line);
}
.adm-passkey-list .small{display:block;margin-top:2px}

.kpi-n{font-family:var(--display);font-size:1.44rem;font-weight:600;line-height:1.2;font-variant-numeric:tabular-nums}
.kpi-l{font-family:var(--display);font-size:.72rem;color:var(--ink-3);margin-top:2px}
.kpi-d{font-family:var(--display);font-size:.7rem;color:var(--ink-3);margin-top:6px;font-variant-numeric:tabular-nums}

/* ---------- data tables ---------- */
.dtable{width:100%;min-width:600px;border-collapse:collapse;background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius);font-family:var(--display);font-size:.75rem}
.dtable th{
  text-align:left;text-transform:uppercase;font-size:.66rem;letter-spacing:.08em;font-weight:500;
  color:var(--ink-3);background:var(--paper-3);padding:9px 12px;border-bottom:1px solid var(--line);
  white-space:nowrap;
}
.dtable td{padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:top}
.dtable tbody tr:last-child td{border-bottom:0}
.dtable tbody tr:hover{background:var(--paper-3)}
.dtable .r{text-align:right;font-variant-numeric:tabular-nums}
.dtable .mono{font-weight:500;font-variant-numeric:tabular-nums slashed-zero}
.dtable .sub{display:block;font-size:.68rem;color:var(--ink-3);margin-top:2px}

/* ---------- editor form ---------- */
.ed{display:grid;grid-template-columns:1fr 268px;gap:20px}
@media (max-width:860px){.ed{grid-template-columns:1fr}}

.ed-panel{background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius);padding:18px}
.ed-panel + .ed-panel{margin-top:20px}
.ed-legend{display:block;font-family:var(--display);font-size:.688rem;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-bottom:12px}

.ed-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
@media (max-width:640px){.ed-grid{grid-template-columns:1fr}}

.ed-f{display:flex;flex-direction:column;gap:4px}
.ed-f.full{grid-column:1/-1}
.ed-f label{font-family:var(--display);font-size:.688rem;color:var(--ink-3);font-weight:500}

/* Scoped to .adm rather than raised to !important: the storefront's
   input[type=text] etc. rule is (0,1,1) and beats a bare .ed-in (0,1,0)
   outright regardless of source order, so text/email/tel/url/number inputs
   were silently rendering at storefront size while the bare-element select
   and textarea rules (0,0,1) lost to .ed-in and rendered dense — a visible
   height mismatch in the same panel. .adm .ed-in is (0,2,0), which beats
   every one of those unconditionally. */
.adm .ed-in{
  width:100%;font-family:var(--display);font-size:.719rem;color:var(--ink);background:var(--paper);
  border:1px solid var(--line-2);border-radius:var(--radius);padding:8px 10px;
  outline:none;transition:border-color .12s,box-shadow .12s;
}
.adm .ed-in:focus{border-color:var(--focus);box-shadow:0 0 0 3px var(--focus);outline:none}

.tier-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) 26px;gap:8px;align-items:center}

.trash{
  width:26px;height:26px;display:grid;place-items:center;background:transparent;
  border:1px solid var(--line-2);border-radius:var(--radius);color:var(--ink-3);cursor:pointer;
  transition:border-color .12s,color .12s;
}
.trash:hover{border-color:var(--accent);color:var(--accent)}

/* Scoped to label.toggle (0,1,1), not bare .toggle (0,1,0), so it can never
   land on a plain <button class="btn ... toggle">: at equal (0,1,0)
   specificity that bare rule, appended after .btn/.btn-ghost/.btn-sm in
   source, was winning the tie and turning the button into a full-width
   block with muted text. The only two callers are the product-editor
   active/gated/protected switches, which are genuinely <label> elements. */
label.toggle{display:flex;align-items:center;gap:9px;font-family:var(--display);font-size:.719rem;color:var(--ink-2)}
.tog{
  position:relative;display:inline-block;width:31px;height:18px;border-radius:99px;flex:0 0 auto;
  background:var(--green);cursor:pointer;transition:background .15s;
}
.tog::after{
  content:"";position:absolute;top:2px;right:2px;width:14px;height:14px;border-radius:50%;
  background:var(--paper-2);transition:right .15s,left .15s;
}
.tog.off{background:var(--line-2)}
.tog.off::after{right:auto;left:2px}
@media (prefers-reduced-motion: reduce){
  .tog,.tog::after{transition:none}
}

.ed-actions{display:flex;gap:8px;border-top:1px solid var(--line);padding-top:16px;margin-top:16px}

/* ---------- status chips ---------- */
.chip{
  display:inline-flex;align-items:center;font-family:var(--display);font-size:.66rem;font-weight:500;
  letter-spacing:.04em;padding:3px 9px;border-radius:99px;
  background:var(--paper-3);color:var(--ink-2);border:1px solid var(--line-2);
}
.chip.ok{background:var(--green-soft);color:var(--green-text);border-color:var(--green)}
.chip.warn{background:var(--accent-soft);color:var(--accent-text);border-color:var(--accent)}
.chip.info{background:var(--blue-soft);color:var(--blue-text);border-color:var(--blue)}

/* The storefront sets serif on form controls for its editorial voice. The
   console is Poppins throughout, so re-assert it here rather than patching
   every admin textarea inline. */
.adm input,
.adm select,
.adm textarea,
.adm button{font-family:var(--display)}
.adm textarea{line-height:1.5}

/* A real fixed-width face, because the two places this class is used — order
   numbers and Bitcoin receiving addresses — are both read character by
   character against something else. The stack leads with faces that
   disambiguate 0/O and 1/l/I; getting that wrong on an address costs money. */
.mono{
  font-family:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  font-variant-numeric:tabular-nums slashed-zero;
  font-size:.94em;
  letter-spacing:.01em;
}
.mono-block{
  display:block; word-break:break-all; line-height:1.7;
  background:var(--paper-3); border:1px solid var(--line-2);
  border-radius:var(--radius); padding:12px 14px;
  font-family:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  font-variant-numeric:tabular-nums slashed-zero;
  letter-spacing:.02em;
}

/* ==========================================================================
   Home page
   Four sections, not six, and almost no card chrome. The old page argued its
   whole case in stacked card grids of equal weight, which is what made it read
   as busy and as generic — every block shouted at the same volume, and each
   one repeated a sub-page that says it better. Here the hero leads, the spec
   strip informs, two statements argue, and one line closes. Space does the
   work that borders were doing.
   ========================================================================== */

/* Legacy home rules below are superseded by the page-grid block further down.
   Kept only where no later rule exists — do not re-add padding or h1 sizing here. */
.hm-hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(32px,5vw,72px);align-items:center}
@media (max-width:900px){.hm-hero-grid{grid-template-columns:1fr;gap:40px}}

/* ---- the box figure ---- */
.hm-fig{margin:0}
.hm-fig svg{width:100%;height:auto;display:block}
.hm-fig figcaption{
  font-family:var(--display);font-size:.72rem;font-weight:500;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-2);margin-top:16px;text-align:center;
}
/* The carton is a charcoal block with ten vials of pale crystalline cake and
   rust crimp caps. The fill is deliberately NOT liquid — what ships in these
   vials is lyophilized powder, and drawing it as a solution would misdescribe
   the product on the first screen of the site. The rust cap is the one place
   the accent appears as an object rather than as a fill. */
/* With a photograph behind the page, a 62%-opaque carton let pine trees show
   through the vials, which read as a rendering fault rather than as glass. */
.v-glass{fill:var(--cream-2)}

/* ---- spec strip ---- */
.hm-specs{padding:clamp(36px,5vw,56px) 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.hm-spec-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:28px 40px;margin:0}
@media (max-width:820px){.hm-spec-grid{grid-template-columns:repeat(2,1fr);gap:24px 28px}}
@media (max-width:520px){.hm-spec-grid{grid-template-columns:1fr}}
.hm-spec-grid dt{
  font-family:var(--display);font-size:.66rem;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase;color:var(--accent-text);margin-bottom:6px;
}
.hm-spec-grid dd{margin:0;font-size:.95rem;line-height:1.5;color:var(--ink)}

/* ---- two statements ---- */
.hm-points{padding:clamp(56px,8vw,96px) 0}
.hm-points .wrap{display:grid;grid-template-columns:1fr 1fr;gap:clamp(36px,6vw,88px)}
@media (max-width:820px){.hm-points .wrap{grid-template-columns:1fr;gap:48px}}
.hm-point{display:flex;flex-direction:column;align-items:flex-start}
.hm-point h2{font-size:clamp(1.5rem,2.6vw,2rem);letter-spacing:-.03em;margin:0 0 16px;max-width:16ch}
.hm-point p{color:var(--ink-2);margin:0 0 18px;max-width:46ch}
.hm-more{
  font-family:var(--display);font-size:.86rem;font-weight:600;text-decoration:none;
  border-bottom:2px solid currentColor;padding-bottom:2px;margin-top:auto;
}
.hm-more:hover{color:var(--ink)}

/* Boxed inline links — serif body voice, bold, bordered so they read as
   deliberate calls to deep pages rather than footnote underlines. */
.box-links{
  display:flex;flex-wrap:wrap;gap:12px;margin:0 0 28px;max-width:62ch;
}
.box-link{
  display:inline-flex;align-items:center;
  font-family:var(--body);font-weight:600;
  font-size:calc(var(--step-0) * var(--type-scale));line-height:1.35;
  color:var(--ink);text-decoration:none;
  border:2px solid var(--charcoal);border-radius:6px;
  padding:10px 16px;
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease),color var(--dur) var(--ease);
}
.box-link:hover{
  background:var(--cream-2);border-color:var(--rust);color:var(--ink);
}
.hm-point .box-links{margin-bottom:20px;max-width:none}

/* ---- close ---- */
.hm-close{padding:clamp(56px,7vw,88px) 0 clamp(72px,9vw,112px);border-top:1px solid var(--line);text-align:center}
.hm-close h2{margin:0 0 12px}
.hm-close p{color:var(--ink-2);max-width:48ch;margin:0 auto 26px}
.hm-close .hero-actions{justify-content:center}

/* ==========================================================================
   MOTION + SURFACE OVERRIDES
   Appended last on purpose. Every rule here upgrades a component that is
   already defined above rather than replacing it, so the specificity
   workarounds documented earlier in this file (.adm .ed-in beating
   input[type=text]; label.toggle not catching button.toggle) are left
   exactly as they were.
   ========================================================================== */

/* ---------- sticky chrome ----------
   Header and catalog bar are the two surfaces content scrolls under, so they
   carry a near-opaque cream and a hairline rather than a shadow. */
.catalog-bar{
  padding:18px 20px;
  margin:0 -20px;
  border-radius:0 0 var(--radius) var(--radius);
}
.promo{
  /* Charcoal bar, cream type. The one loud element per screen — the role is
     unchanged from the old announcement bar, only the palette moved. */
  font-weight:500;letter-spacing:.005em;
}

/* ---------- panels ---------- */
.card,.prod,.tier-card,.news-card,.offer-card{transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease)}
.section-band{
  background:var(--cream);
  border-top:1px solid var(--hair);
  border-bottom:1px solid var(--hair);
}
.site-foot{
  background:var(--cream);
  border-top:1px solid var(--hair);
}
.step{background:var(--cream)}
.steps{background:var(--hair);border:0;box-shadow:var(--shadow)}

/* Hover lift, per the brief: translateY(-4px) and a deeper shadow. */
.card:hover,.prod:hover,.tier-card:hover{
  transform:translateY(var(--lift));
  box-shadow:var(--shadow-lift);
}
/* .notice and .empty are status surfaces, not objects. They stay put —
   a warning that jumps when the pointer crosses it reads as a bug. */

/* ---------- controls ---------- */
.btn{
  transition:background var(--dur) var(--ease), border-color var(--dur) var(--ease),
             color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
             transform var(--dur) var(--ease);
  letter-spacing:.005em;
}
.btn-primary:hover{transform:translateY(-2px)}
.btn-ghost{
  background:var(--cream);
  border-color:var(--hair);
}
.btn-ghost:hover{background:var(--cream);border-color:var(--hair-strong);transform:translateY(-2px)}
.btn:active{transform:translateY(1px)}

input,select,textarea,.field{
  background:var(--cream);
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* Focus: charcoal, 2px, offset so it never sits on the glyphs. Charcoal is
   17.5:1 on cream and stays above 16:1 over the ground photograph, so the
   ring is visible on every surface in the design. */
:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:2px}

/* ---------- data surfaces ----------
   Tables are the one surface where a fill fights the data, so they carry a
   hairline and nothing else. */
table.data,.dtable{
  background:var(--cream);
  border:1px solid var(--hair);
  border-radius:var(--radius);
  overflow:hidden;
}
table.data th,.dtable th{background:var(--cream-2)}
.dtable tbody tr{transition:background var(--dur) var(--ease)}
.dtable tbody tr:hover{background:var(--cream-2)}

/* SKU codes, strengths and prices move to the instrument voice. */
/* Mono is the instrument voice, so it goes on the things that are read off
   a label — codes, strengths, prices. It is deliberately NOT on .spec dd:
   half those values are prose ("Reconstitution water for peptides that need
   acidic solution"), and prose set in mono reads as a terminal dump. */
.prod-sku,.tier-price,.tiers td{font-family:var(--data);font-variant-numeric:tabular-nums}
/* Strength is the number a buyer scans the grid for, so it gets the
   instrument voice and the accent colour. It was the one inline style in
   the codebase that fought the stylesheet rather than cooperating with it:
   every other inline rule here sets a token, which is why the whole palette
   swap carried through them untouched. */
.prod-strength{
  font-family:var(--data);font-variant-numeric:tabular-nums;
  font-weight:600;font-size:.86rem;color:var(--accent-text);margin-top:2px;
  letter-spacing:.02em;
}
.prod-sku{letter-spacing:.06em;text-transform:uppercase}

/* ---------- reduced motion ----------
   Everything the brief asks to animate, switched off in one place. */
@media (prefers-reduced-motion:reduce){
  .card,.prod,.tier-card,.btn,.dtable tbody tr,input,select,textarea,.field{transition:none}
  .card:hover,.prod:hover,.tier-card:hover,
  .btn-primary:hover,.btn-ghost:hover,.btn:active{transform:none}
}

/* ==========================================================================
   HEADER: two tiers, wide search, mega-menu
   ==========================================================================
   The header height is a token because two other things depend on it: the
   catalog bar sticks directly beneath it, and the mobile drawer opens from
   its bottom edge. Hardcoding 70px in three places is how those drift apart.
   ========================================================================== */
:root{--head-h:118px}

.site-head{position:sticky;top:0;z-index:60}
.head-top{border-bottom:1px solid var(--hair)}
.head-top .head-row{gap:24px;height:72px}
/* Child combinator, not a descendant selector. The mega panel reuses the
   .wrap utility for its own inner container, and that container lives inside
   .head-bar -- so `.head-bar .wrap` (0-2-0) silently beat `.mega-grid`
   (0-1-0) and laid the panel out as a flex row instead of a grid, which is
   why its CTA ignored its own max track width. Style the row you own. */
.head-bar > .wrap{display:flex;align-items:center;min-height:46px}

/* ---------- the wide search ----------
   Wide is the point, so it takes the free space rather than a fixed width,
   with a ceiling so it does not sprawl on a 27-inch display. */
.head-search{
  flex:1 1 auto;max-width:620px;min-width:0;
  display:flex;align-items:center;gap:10px;
  background:var(--cream);
  border:1px solid var(--hair);border-radius:999px;
  padding:5px 6px 5px 16px;
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.head-search:focus-within{border-color:var(--rust);box-shadow:0 0 0 3px rgba(20,20,19,.18)}
.head-search svg{color:var(--charcoal-50);flex:0 0 auto}
.head-search input{
  flex:1 1 auto;min-width:0;background:none;border:0;padding:8px 0;
  font-family:var(--body);font-size:.92rem;color:var(--ink);
}
.head-search input::placeholder{color:var(--charcoal-50);opacity:.85}
.head-search input:focus{outline:none}
.head-search .btn{flex:0 0 auto}

.head-actions{display:flex;align-items:center;gap:14px;flex:0 0 auto;margin-left:auto}
.head-cart{
  font-family:var(--display);font-size:.88rem;color:var(--ink-2);text-decoration:none;
  transition:color var(--dur) var(--ease);white-space:nowrap;
}
.head-cart:hover{color:var(--ink)}

/* ---------- the nav bar ---------- */
.head-bar .nav{margin-left:0;gap:2px}
.nav a:hover{background:var(--cream-2)}
.nav a.is-active{color:var(--rust)}
.nav-only-mobile{display:none}

/* ---------- mega-menu ----------
   Opens on :hover and :focus-within. No JavaScript is required to open,
   close, or read it — site.js only adds Escape, click-outside, and the
   aria-expanded state on top. */
.has-mega{position:static}
.mega-trigger{display:inline-flex;align-items:center;gap:6px}
.mega-trigger .caret{transition:transform var(--dur) var(--ease);opacity:.7}
.has-mega:hover .caret,.has-mega:focus-within .caret{transform:rotate(180deg);opacity:1}

.mega{
  position:absolute;left:0;right:0;top:100%;z-index:70;
  /* Opaque, not translucent: a dropdown is the one surface with arbitrary
     page content directly behind it, and any bleed-through reads as two
     texts on top of each other.
     Closed with clip-path inset from the header seam (a curtain, not a
     fade-and-slide) so the panel reveals as an extension of the bar. */
  background:var(--cream);
  border-top:1px solid var(--hair);
  opacity:0;visibility:hidden;
  clip-path:inset(0 0 100% 0);
  transition:opacity var(--dur) var(--ease),clip-path var(--dur) var(--ease),visibility 0s linear var(--dur);
}
.has-mega:hover > .mega,
.has-mega:focus-within > .mega,
.has-mega.is-open > .mega{
  opacity:1;visibility:visible;clip-path:inset(0 0 0 0);
  transition:opacity var(--dur) var(--ease),clip-path var(--dur) var(--ease),visibility 0s;
}
/* Closed panels must not be reachable by Tab, or a keyboard user walks into
   twenty invisible links. visibility:hidden already does this; the explicit
   rule is here so it survives someone swapping the transition for opacity. */
.mega[hidden]{display:none}

/* One flat four-column grid: three link columns and the CTA. An earlier
   version nested the three inside a wrapper so the CTA could take a fixed
   track, but a nested grid cannot align its rows with its siblings, and the
   wrapper's min-content width let the CTA claim far more than its minmax
   allowed. Flat is both simpler and correct.

   minmax(0,1fr) rather than 1fr: a plain 1fr floors at min-content, so one
   long unbreakable link would push the other columns narrow. */
.mega-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr)) minmax(220px,280px);
  gap:36px;padding:32px 24px 36px;align-items:start;
}
/* Every column header occupies the same height whether its label runs to one
   line or two, so the rules underneath them line up across the panel.
   "Ordering & accounts" wraps where "Legal" does not, and without this the
   three lists start at three different heights. */
.mega-head{
  display:block;font-family:var(--display);font-size:.68rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--charcoal-50);line-height:1.4;
  min-height:2.8em;margin-bottom:14px;padding-bottom:10px;
  border-bottom:1px solid var(--hair);
}
.mega-list{list-style:none;margin:0;padding:0;display:grid;gap:2px}
.mega-list a{
  display:block;text-decoration:none;color:var(--ink);padding:9px 10px;
  border-radius:var(--radius);transition:background var(--dur) var(--ease);
}
.mega-list a:hover{background:var(--cream-2)}
.mega-label{display:block;font-family:var(--display);font-size:.92rem;font-weight:500}
.mega-count{color:var(--charcoal-50);font-size:.78rem;margin-left:4px}
.mega-blurb{display:block;font-size:.8rem;color:var(--ink-3);margin-top:2px;line-height:1.4}
.mega-list-plain a{font-family:var(--display);font-size:.9rem;color:var(--ink-2)}
.mega-list-plain a:hover{color:var(--ink)}

/* The CTA box the brief asks for on the far right. It is the one rust fill
   in the panel, which is what makes it read as the way out rather than as a
   seventh link. */
.mega-cta{
  display:flex;flex-direction:column;gap:8px;text-decoration:none;
  padding:22px 22px 20px;border-radius:var(--radius-lg);
  transition:border-color var(--dur) var(--ease),transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.mega-cta:hover{border-color:var(--rust);transform:translateY(var(--lift));box-shadow:var(--shadow-lift)}
.mega-cta-kicker{
  font-family:var(--display);font-size:.7rem;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--rust);
}
.mega-cta-body{font-size:.86rem;color:var(--ink-2);line-height:1.5}
.mega-cta-go{font-family:var(--display);font-size:.86rem;font-weight:600;color:var(--ink);margin-top:auto}

/* ---------- catalog bar sits under the header ---------- */
.catalog-bar{top:var(--head-h)}
.filter-note{
  font-size:.88rem;color:var(--ink-2);margin:16px 0 0;
}
.filter-note a{margin-left:8px}
/* When scripting is on, typing filters live and the submit button is noise.
   It is removed by site.js rather than hidden here, so the no-JS path keeps
   a working button. */
.wrap-pad-top{padding-top:16px}
.notice-flush{margin:0}

/* ---------- responsive ---------- */
@media (max-width:1080px){
  .head-search{max-width:none}
  .mega-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:28px}
}
@media (max-width:940px){
  :root{--head-h:132px}   /* logo row + full-width search; 72px was stale */
  /* The nav bar collapses to nothing rather than to display:none — the
     drawer's <nav> lives inside it, so hiding the bar would hide the drawer
     with it. Zero height keeps the element in the tree and lets the header
     measure 72px, which is what --head-h above now says it is. */
  .head-bar{border:0}
  .head-bar > .wrap{min-height:0;display:block;padding:0}
  .head-search{order:3;flex-basis:100%;max-width:none}
  .head-top .head-row{flex-wrap:wrap;height:auto;padding-top:14px;padding-bottom:14px;gap:14px}
  /* Account controls are repeated in .nav-only-mobile. Leaving them in the
     top row next to the burger made Log in / Open an account overlap the
     menu button under ~520px (both carried margin-left:auto on one flex
     line). Hide the row copy; the drawer is the mobile account path. */
  .head-actions{display:none}
  .burger{margin-left:auto}
  /* The drawer replaces the whole nav bar on mobile, so the account links
     that live in the top row on desktop reappear inside it. */
  .nav-only-mobile{display:flex;flex-direction:column}
  /* Repositioned under the header bar. The height cap has to be restated for
     this variant: it is measured from the drawer's own top edge, which has
     moved, and the rule above was written against the fixed 70px version. */
  .nav{inset:auto 0 auto 0;top:100%;position:absolute;
       max-height:calc(100vh - 116px);
       max-height:calc(100dvh - 116px);
       overflow-y:auto;overscroll-behavior:contain}
  .has-mega{position:relative}
  .mega{position:static;opacity:1;visibility:visible;transform:none;clip-path:none;box-shadow:none;
        background:none;border-top:0;transition:none}
  .mega-grid{padding:0 0 12px;gap:16px;grid-template-columns:1fr}
  .mega-cta{display:none}
  .mega-trigger .caret{display:none}
}
@media (prefers-reduced-motion:reduce){
  .mega,.mega-trigger .caret,.mega-cta,.head-search,.head-cart{transition:none}
  .mega-cta:hover{transform:none}
}

/* Small layout utilities, replacing the two inline styles that were in the
   catalog's empty state. */
.mb-0{margin:0}
.mt-8{margin:8px 0 0}

/* ==========================================================================
   The research-use-only block
   ==========================================================================
   The one statement on this site with legal weight, so it is given a surface
   of its own rather than a smaller type size at the bottom of the page. Clay
   is the palette's warning colour and it is used here and nowhere else, so
   the block reads as a different KIND of thing from the navigation above it
   without shouting.

   Clay is 5.8:1 on cream, so it can carry the mark type directly; the block
   is set off by its own hairline and clay left rule rather than by a fill. */
.ruo-block{
  display:block;margin:40px 0 0;padding:20px 22px;
  background:var(--cream);
  border:1px solid rgba(168,69,42,.28);
  border-left:3px solid var(--clay);
  border-radius:var(--radius);
}
.ruo-mark{
  display:block;font-family:var(--display);font-size:.66rem;font-weight:700;
  letter-spacing:.18em;text-transform:uppercase;color:var(--clay);margin-bottom:8px;
}
.ruo{margin:0;font-size:.83rem;line-height:1.62;color:var(--ink-2);border:0;padding:0;font-family:var(--body)}
.ruo strong{color:var(--ink);font-weight:600}
.ruo a{color:var(--accent-text)}

/* footer + gate odds and ends, replacing inline styles */
.foot-brand{margin-bottom:14px}
.foot-blurb{max-width:36ch}
.gate-row{margin-bottom:16px}
.gate-row-last{margin-bottom:18px}
.gate-checks{list-style:none;padding:0;margin:0}
.gate-selfcert{margin-top:22px;max-width:58ch}
.gate-card .ruo-block{margin-top:24px}

/* ---------- attestation gate ---------- */
.gate-card{
  background:var(--cream);
  border-radius:var(--radius-lg);
  padding:34px 34px 30px;
  box-shadow:var(--shadow-lift);
  position:relative;
}

.gate-terms{background:var(--cream-2);border-color:var(--hair)}
@media (max-width:560px){.gate-card{padding:24px 20px}}

/* ==========================================================================
   HOME: vertical tabs, featured lines, logistics, news
   ========================================================================== */

/* Visually hidden but still focusable and still announced. Used for the tab
   and stream radios, whose LABELS are the visible control. */
.vis-hidden{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ---------- the four-tab block ---------- */
.hm-tabs{padding:64px 0}
.tabset{display:grid;grid-template-columns:minmax(220px,264px) minmax(0,1fr);gap:28px;align-items:start}
.tab-rail{display:flex;flex-direction:column;gap:10px}

.tab{
  display:block;cursor:pointer;padding:16px 18px;border-radius:var(--radius);
  background:var(--cream);
  border:1px solid var(--hair);border-left:3px solid transparent;
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease),
             transform var(--dur) var(--ease);
}
.tab:hover{background:var(--cream);border-left-color:var(--charcoal-50);transform:translateX(3px)}
.tab-name{display:block;font-family:var(--display);font-weight:600;font-size:1rem;color:var(--ink)}
.tab-sub{display:block;font-size:.78rem;color:var(--ink-3);margin-top:2px}

/* Active state. The rust left edge is the same device the RUO block uses for
   clay: a 3px rule that says "this one", without changing the type. */
#ht-about:checked    ~ .tab-rail .tab[for="ht-about"],
#ht-offer:checked    ~ .tab-rail .tab[for="ht-offer"],
#ht-featured:checked ~ .tab-rail .tab[for="ht-featured"],
#ht-contact:checked  ~ .tab-rail .tab[for="ht-contact"]{
  background:var(--cream);border-left-color:var(--rust);border-color:var(--hair);
  border-left-color:var(--rust);
}
#ht-about:checked    ~ .tab-rail .tab[for="ht-about"] .tab-name,
#ht-offer:checked    ~ .tab-rail .tab[for="ht-offer"] .tab-name,
#ht-featured:checked ~ .tab-rail .tab[for="ht-featured"] .tab-name,
#ht-contact:checked  ~ .tab-rail .tab[for="ht-contact"] .tab-name{color:var(--charcoal)}

/* The radio is off-screen, so its focus ring has to be drawn on the label. */
#ht-about:focus-visible    ~ .tab-rail .tab[for="ht-about"],
#ht-offer:focus-visible    ~ .tab-rail .tab[for="ht-offer"],
#ht-featured:focus-visible ~ .tab-rail .tab[for="ht-featured"],
#ht-contact:focus-visible  ~ .tab-rail .tab[for="ht-contact"]{
  outline:2px solid var(--focus);outline-offset:2px;
}

.tab-panes{
  background:var(--cream);
  border-radius:var(--radius-lg);padding:32px 34px;position:relative;
  box-shadow:var(--shadow);min-height:320px;
}

.tab-pane{display:none}
#ht-about:checked    ~ .tab-panes .tp-about,
#ht-offer:checked    ~ .tab-panes .tp-offer,
#ht-featured:checked ~ .tab-panes .tp-featured,
#ht-contact:checked  ~ .tab-panes .tp-contact{display:block}

.tab-lead{
  font-family:var(--serif);font-size:clamp(1.25rem,2.1vw,1.6rem);line-height:1.34;
  color:var(--ink);max-width:44ch;margin:0 0 18px;
}
.tab-pane p{color:var(--ink-2);max-width:64ch}

/* Our offering: three cards */
/* Asymmetric, not three equal columns -- the brief rules those out by name.
   The first card carries the weight and the other two stack beside it. */
.offer-grid{display:grid;grid-template-columns:1.35fr 1fr;gap:18px;align-items:start}
.offer-grid > :first-child{grid-row:span 2}
.offer-card{
  background:var(--cream);border:1px solid var(--hair);border-radius:var(--radius);
  padding:20px 20px 18px;transition:transform var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.offer-card:hover{transform:translateY(var(--lift));border-color:var(--hair)}
.offer-card h3{margin-bottom:8px;font-size:1rem}
.offer-card p{font-size:.9rem;margin-bottom:12px}

/* Featured: a price list, so it is set as one. Four columns of tabular data,
   not nine cards -- a buyer comparing lines reads down a column. */
.feat-list{list-style:none;margin:0;padding:0;border-top:1px solid var(--hair)}
.feat-row{border-bottom:1px solid var(--hair)}
.feat-row a{
  display:grid;grid-template-columns:74px minmax(0,1fr) auto auto;gap:16px;align-items:baseline;
  padding:12px 8px;text-decoration:none;border-radius:var(--radius);
  transition:background var(--dur) var(--ease);
}
.feat-row a:hover{background:var(--cream-2)}
.feat-sku{color:var(--charcoal-70);font-size:.92rem;letter-spacing:.06em}
.feat-name{color:var(--ink);font-family:var(--display);font-weight:500;font-size:1.05rem}
.feat-strength{color:var(--ink-2);font-size:.92rem;white-space:nowrap}
.feat-price{color:var(--charcoal);font-weight:600;font-size:1.05rem;white-space:nowrap;text-align:right}
.feat-note{font-size:.85rem;margin:16px 0 0}

.contact-cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:28px;margin-bottom:24px}
.contact-cols .mega-list a{padding-left:0}

/* ---------- logistics ---------- */
.hm-logistics{padding:8px 0 64px}
.logi-panel{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.9fr);gap:44px;padding:38px 40px;align-items:center}
.logi-copy h2{margin-bottom:14px}
.logi-copy p{color:var(--ink-2);max-width:52ch}
.logi-note{
  margin:18px 0 0;padding:12px 14px;border-radius:var(--radius);
  background:var(--cream-2);border-left:3px solid var(--charcoal-50);font-size:.88rem;
}
.logi-note strong{color:var(--ink)}

.usmap{margin:0}
.usmap-svg{width:100%;height:auto;display:block;overflow:visible}

/* Landmass: a filled silhouette rather than an outline, so the country reads
   as one mass at a glance and the highlighted state has something to sit in. */
/* Night lights. The landmass is a solid charcoal silhouette so the city
   glow is the only thing emitting; see the editorial layer for the live fill. */
.usmap-land{
  stroke:var(--cream-2);
  stroke-width:1.1;
  stroke-linejoin:round;
}
.usmap-borders{fill:none;stroke:var(--cream-2);stroke-width:.6;stroke-linejoin:round}
.usmap-home{fill:rgba(20,20,19,.10);stroke:rgba(20,20,19,.55);stroke-width:1.3;stroke-linejoin:round}

/* Three passes of the same thousand points. Warm rust rather than NASA's
   sodium-white, so the map belongs to this palette instead of quoting a
   photograph everyone recognises. */

.usmap-glow{pointer-events:none}
.usmap-ring{fill:none;stroke:var(--rust);stroke-width:1.6;opacity:.85}

.usmap-caption{
  display:flex;align-items:center;gap:9px;margin-top:14px;
  font-family:var(--display);font-size:.82rem;color:var(--ink-2);
}

.usmap-dot{width:9px;height:9px;border-radius:50%;background:var(--rust);flex:0 0 auto;
  box-shadow:0 0 0 4px rgba(20,20,19,.22)}

/* ---------- blog / news ---------- */
.news-sec{padding:8px 0 64px}
.news-head{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;margin-bottom:20px;flex-wrap:wrap}
.news-h2{margin:0}
.news-toggle{
  display:inline-flex;gap:2px;padding:4px;border-radius:999px;
  background:var(--cream);border:1px solid var(--hair);
}
.news-tab{
  cursor:pointer;padding:9px 20px;border-radius:999px;
  font-family:var(--display);font-size:.86rem;font-weight:500;color:var(--ink-3);
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease);
}
.news-tab:hover{color:var(--ink)}
#stream-blog:checked ~ .news-tab[for="stream-blog"],
#stream-news:checked ~ .news-tab[for="stream-news"]{background:var(--rust);color:var(--accent-on)}
#stream-blog:focus-visible ~ .news-tab[for="stream-blog"],
#stream-news:focus-visible ~ .news-tab[for="stream-news"]{outline:2px solid var(--focus);outline-offset:2px}

.news-pane{display:none}
.news-sec:has(#stream-blog:checked) .news-pane-blog{display:block}
.news-sec:has(#stream-news:checked) .news-pane-news{display:block}
/* :has() is the clean way to reach a pane that is not a sibling of the
   radio. Where it is unsupported both panes would stay hidden, so the blog
   pane is shown unconditionally first and the rule above only ever adds. */
@supports not selector(:has(*)){
  .news-pane-blog{display:block}
}

.news-sample{
  margin:0 0 20px;padding:12px 16px;border-radius:var(--radius);
  background:var(--cream-2);border-left:3px solid var(--charcoal-50);
  font-size:.86rem;color:var(--ink-2);
}
.news-sample strong{color:var(--ink)}
.news-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}
.news-card{
  display:flex;flex-direction:column;gap:10px;padding:22px 22px 20px;
  background:var(--cream);border:1px solid var(--hair);border-radius:var(--radius-lg);
  transition:transform var(--dur) var(--ease),border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.news-card:hover{transform:translateY(var(--lift));border-color:var(--hair);box-shadow:var(--shadow-lift)}
.news-meta{display:flex;align-items:center;gap:10px;font-size:.74rem}
.news-meta time{color:var(--ink-3);letter-spacing:.04em}
.news-kicker{
  font-family:var(--display);font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--charcoal-50);font-size:.64rem;
}
.news-title{margin:0;font-size:1.02rem;line-height:1.3}
.news-summary{margin:0;font-size:.88rem;color:var(--ink-2);line-height:1.55;flex:1}
.news-go{font-family:var(--display);font-size:.84rem;font-weight:600;color:var(--accent-text);text-decoration:none}
.news-go.is-inert{color:var(--ink-3);font-weight:500;font-style:italic}
.news-empty{font-size:.9rem;color:var(--ink-2);max-width:56ch;margin:0}

/* ---------- responsive ---------- */
@media (max-width:1000px){
  .offer-grid,.news-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .logi-panel{grid-template-columns:1fr;gap:32px;padding:30px 26px}
}
@media (max-width:860px){
  .tabset{grid-template-columns:1fr;gap:16px}
  .tab-rail{flex-direction:row;overflow-x:auto;gap:8px;padding-bottom:4px}
  .tab{flex:1 0 auto;border-left:0;border-bottom:3px solid transparent;padding:12px 14px}
  .tab:hover{transform:none}
  #ht-about:checked    ~ .tab-rail .tab[for="ht-about"],
  #ht-offer:checked    ~ .tab-rail .tab[for="ht-offer"],
  #ht-featured:checked ~ .tab-rail .tab[for="ht-featured"],
  #ht-contact:checked  ~ .tab-rail .tab[for="ht-contact"]{border-bottom-color:var(--rust)}
  .tab-panes{padding:24px 20px}
  /* Scoped to the old tabbed feature list — an unscoped .feat-row rule here
     was rewriting the Published Pricing grid at 760–860px and made the
     strength/price columns land on the wrong rows when the window resized. */
  .hm-tabs .feat-row a{grid-template-columns:64px minmax(0,1fr) auto;row-gap:2px}
  .hm-tabs .feat-strength{grid-column:2/3}
  .hm-tabs .feat-price{grid-column:3/4;grid-row:1/3}
}
@media (max-width:700px){
  .offer-grid,.news-grid,.contact-cols{grid-template-columns:1fr}
  .hm-tabs{padding:44px 0}
}
@media (prefers-reduced-motion:reduce){
  .tab,.offer-card,.news-card,.feat-row a{transition:none}
  .tab:hover,.offer-card:hover,.news-card:hover{transform:none}
}

/* Anchor targets must clear the sticky header. The footer deep-links into
   /terms#shipping, #use and #privacy, and the Terms page has nineteen
   anchored sections -- without this every one of them lands underneath the
   header and the reader sees the middle of the previous clause. */
[id]{scroll-margin-top:calc(var(--head-h) + 18px)}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

.ship-box{min-height:110px}

/* ---------- tracking + COA in the buyer portal ---------- */
.r{text-align:right}
.track-row{margin-top:16px}
.track-link{
  display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;text-decoration:none;
  padding:10px 12px;margin-top:6px;border-radius:var(--radius);
  background:var(--cream-2);border:1px solid var(--hair);
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease);
}
.track-link:hover{border-color:var(--hair);background:var(--cream-2)}
.track-carrier{font-family:var(--display);font-weight:600;color:var(--ink)}
.track-num{font-size:.84rem;color:var(--ink-2);word-break:break-all}
.track-go{margin-left:auto;font-family:var(--display);font-size:.84rem;font-weight:600;color:var(--accent-text)}
.track-plain{margin:6px 0 0;font-size:.86rem;color:var(--ink-2);word-break:break-all}

.coa-card{margin-bottom:24px}
.coa-list{list-style:none;margin:0;padding:0}
.coa-row{
  display:grid;grid-template-columns:72px minmax(0,1fr) auto;gap:12px;align-items:baseline;
  padding:10px 0;border-bottom:1px solid var(--hair);
}
.coa-row:last-child{border-bottom:0}
.coa-sku{font-size:.8rem;color:var(--charcoal-50);letter-spacing:.06em}
.coa-name{font-size:.92rem;color:var(--ink)}
.coa-go{font-family:var(--display);font-size:.84rem;font-weight:600;white-space:nowrap}
.coa-pending{font-size:.82rem;color:var(--ink-3);white-space:nowrap}
.coa-note{margin:14px 0 0}
@media (max-width:560px){
  .coa-row{grid-template-columns:1fr auto}
  .coa-sku{grid-column:1/3}
}
.mt-10{margin-top:10px}

/* ---------- attestation checkpoints ----------
   The error state on the gate has to live in the page itself: gate.ejs
   includes only partials/head, so the site-wide flash mechanism in the
   header partial is unreachable from it. Clay is the palette's warning
   colour, used here and on the research-use-only block and nowhere else. */
.notice-error{
  border-left:3px solid var(--clay);
  background:rgba(168,69,42,.10);
}
.notice-error strong{color:var(--clay)}
.gate-error{margin:0 0 22px}
.gate-fixed{
  margin:0;padding:11px 14px;border-radius:var(--radius);
  background:var(--cream-2);border:1px solid var(--hair);
  font-family:var(--display);font-weight:600;color:var(--ink);
}

/* The announcement bar's rotating holiday tag. */
.promo{display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap}
.promo-tag{
  font-family:var(--display);font-size:.66rem;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;padding:3px 9px;border-radius:999px;
  background:var(--cream);color:var(--promo-ink);white-space:nowrap;
}
.promo-text{font-weight:500}

/* ==========================================================================
   INLINE EDITING
   ==========================================================================
   Locked, this is one small button in the corner. Unlocked, it becomes a
   toolbar pinned to the bottom of the window and every editable string on
   the page gains a dashed outline.

   The outline only ever appears in edit mode: a visitor must never see a hint
   that the page is editable, and a dotted border round every heading would
   be exactly that hint. */
.edbar{
  position:fixed;right:18px;bottom:18px;z-index:300;
  display:flex;align-items:center;gap:8px;
}
.edbar-toggle{
  font-family:var(--display);font-size:.78rem;font-weight:600;
  padding:9px 15px;border-radius:999px;cursor:pointer;
  background:var(--cream);color:var(--ink-2);
  border:1px solid var(--hair);
  transition:color var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.edbar-toggle:hover{color:var(--ink);border-color:var(--hair-strong)}
.edbar-unlock{
  display:flex;align-items:center;gap:8px;padding:8px;border-radius:999px;
  background:var(--cream);border:1px solid var(--hair);
}
.edbar-unlock input[type=password]{
  width:190px;padding:8px 12px;border-radius:999px;font-size:.86rem;
  background:var(--cream-2);border:1px solid var(--hair);
}

/* Unlocked: a full-width bar, because the look controls do not fit in a pill
   and a toolbar that overlaps the content you are editing is useless. */
.edbar.is-on{
  left:0;right:0;bottom:0;padding:0;
  background:var(--cream);
  border-top:1px solid var(--hair);
  box-shadow:0 -14px 40px rgba(0,0,0,.5);
}
.edbar-row{
  max-width:var(--maxw);margin:0 auto;padding:12px 24px;
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;
}
.edbar-brand{
  font-family:var(--display);font-size:.66rem;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--accent-on);background:var(--rust);
  padding:4px 10px;border-radius:999px;flex:0 0 auto;
}
.edbar-status{font-size:.82rem;color:var(--ink-3);min-width:16ch}
.edbar-status.is-ok{color:var(--green-text)}
.edbar-status.is-err{color:var(--clay)}
.edbar-group{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-left:auto}
.edbar-field{display:flex;flex-direction:column;gap:3px}
.edbar-field > span{
  font-size:.62rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--charcoal-50);
}
.edbar-field select,.edbar-field input{
  font-size:.8rem;padding:6px 9px;border-radius:var(--radius);
  background:var(--cream-2);border:1px solid var(--hair);color:var(--ink);
  max-width:230px;
}
.edbar-field-narrow input{width:78px}
.edbar-actions{display:flex;gap:8px;align-items:center}
.edbar-inline{display:inline}

/* Editable blocks, marked only while editing. */
.is-editing [data-edit]{
  outline:1px dashed rgba(20,20,19,.45);
  outline-offset:3px;border-radius:2px;
  transition:outline-color var(--dur) var(--ease),background var(--dur) var(--ease);
  cursor:text;
}
.is-editing [data-edit]:hover{outline-color:var(--rust);background:rgba(20,20,19,.06)}
.is-editing [data-edit]:focus{
  outline:2px solid var(--rust);outline-offset:3px;
  background:rgba(20,20,19,.09);
}
/* The bar is fixed, so the page needs room to scroll past it. */
.is-editing body,body.is-editing{padding-bottom:96px}

@media (max-width:820px){
  .edbar-group{margin-left:0;width:100%}
  .edbar-field select,.edbar-field input{max-width:none;width:100%}
}
@media (prefers-reduced-motion:reduce){
  .edbar-toggle,.is-editing [data-edit]{transition:none}
}

/* ==========================================================================
   EDITORIAL LAYER
   ==========================================================================
   Appended last, so it wins over the component rules written for the old
   dark system without having to hunt every one of them down.

   The character here is architectural: hairlines instead of borders, flat
   fills instead of elevation, and a great deal of space. Nothing floats.
   ========================================================================== */

body{
  background:transparent;
  color:var(--charcoal);
  font-family:var(--body);
  font-size:calc(var(--step-0) * var(--type-scale));
  line-height:1.62;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
.lede{
  font-size:calc(var(--step-1) * var(--type-scale));
  line-height:1.5;color:var(--charcoal-70);max-width:36ch;
}

/* Labels are the one place the sans gets small and wide. */
.label,.card-key,.mega-head,.eyebrow{
  font-family:var(--display);font-weight:600;
  font-size:calc(var(--step--1) * var(--type-scale) * .82);
  letter-spacing:.15em;text-transform:uppercase;color:var(--charcoal-50);
}

/* ---------- surfaces ----------
   A card is a hairline and padding. No shadow, no fill, no radius to speak
   of -- on a cream ground a filled card just makes a slightly different
   cream rectangle, which is noise. */
.card,.prod,.tier-card,.notice,.empty,.gate-terms,.tab-panes,.news-card,
.offer-card,.logi-panel,.ruo-block,.step{
  background:transparent;
  border:1px solid var(--hair);
  border-radius:var(--radius);
  box-shadow:none;
}
.card,.prod,.tier-card,.news-card,.offer-card{padding:26px 24px}
.section-band{background:var(--cream-2);border-top:1px solid var(--hair);border-bottom:1px solid var(--hair)}
.site-foot{background:transparent;border-top:1px solid var(--hair-strong)}
.steps{background:transparent;border:1px solid var(--hair);gap:0}
.step{border:0;border-bottom:1px solid var(--hair)}
.step:last-child{border-bottom:0}

/* ---------- controls ----------
   Rust is a FILL. The type on it is charcoal, never cream -- cream on rust
   measures 2.96:1. The charcoal edge exists because rust against cream is
   also 2.96:1, just under the 3:1 a control needs to be identifiable by its
   boundary alone. */
.btn{
  font-family:var(--display);font-weight:600;
  border-radius:6px;border:1.5px solid transparent;
  padding:13px 26px;
  font-size:calc(var(--step--1) * var(--type-scale));
  transition:background var(--dur) var(--ease-spring),
             border-color var(--dur) var(--ease-spring),
             color var(--dur) var(--ease),
             transform var(--dur) var(--ease-spring);
}
.btn-primary{background:var(--rust);color:var(--charcoal);border-color:var(--charcoal);box-shadow:none}
.btn-primary:hover{background:var(--rust-deep);transform:translateY(var(--lift))}
.btn-ghost{background:transparent;color:var(--charcoal);border-color:var(--charcoal)}
.btn-ghost:hover{background:var(--charcoal);color:var(--cream);transform:translateY(var(--lift))}
.block-dark .btn-ghost{color:var(--cream);border-color:var(--cream)}
.block-dark .btn-ghost:hover{background:var(--cream);color:var(--charcoal)}

input,select,textarea,.field,.head-search{
  background:var(--cream);border:1px solid var(--hair-strong);
  border-radius:var(--radius);color:var(--charcoal);
}
.head-search{border-radius:6px}
.head-search input{background:transparent;border:0}
:focus-visible{outline:2px solid var(--charcoal);outline-offset:2px}

/* ---------- chrome ---------- */
.site-head{background:rgba(250,249,245,.92);border-bottom:1px solid var(--hair);box-shadow:none}
/* Home: after the shared translucent chrome rule so specificity+order win.
   Opaque enough that large hero caps cannot read through the sticky bar. */
.is-home .site-head{
  background:rgba(250,249,245,.97);
  backdrop-filter:saturate(1.1) blur(8px);
  -webkit-backdrop-filter:saturate(1.1) blur(8px);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .is-home .site-head{background:var(--cream)}
}
.head-top{border-bottom:1px solid var(--hair)}
.promo{background:var(--charcoal);color:var(--cream)}
.promo-tag{background:var(--rust);color:var(--charcoal)}
.nav a{color:var(--charcoal-70);font-family:var(--display);font-weight:500}
.nav a:hover{background:transparent;color:var(--charcoal)}
.nav a.is-active{color:var(--charcoal)}
.mega{background:var(--cream);border-top:1px solid var(--hair);box-shadow:0 18px 40px rgba(20,20,19,.08)}
.mega-cta{background:var(--rust);border:1px solid var(--charcoal)}
.mega-cta-kicker,.mega-cta-go{color:var(--charcoal)}
.mega-cta-body{color:rgba(20,20,19,.78)}
.catalog-bar{background:rgba(250,249,245,.94);border-bottom:1px solid var(--hair);box-shadow:none}

table.data,.dtable{background:transparent;border:1px solid var(--hair)}
table.data th,.dtable th{background:var(--cream-2);color:var(--charcoal-50)}

/* ---------- the drawn carton, in the new palette ---------- */
.carton{fill:var(--charcoal);stroke:none}
.v-glass{fill:rgba(250,249,245,.16)}
.v-fill{fill:var(--cream)}
.v-cap{fill:var(--rust)}
.v-edge{fill:none;stroke:rgba(250,249,245,.30);stroke-width:2}
.hm-photo{
  width:100%;height:auto;display:block;
  border:1px solid var(--hair);border-radius:var(--radius);
}

/* ---------- the map, relit for cream ---------- */
.usmap-land{fill:var(--charcoal);stroke:none}
.usmap-borders{stroke:rgba(250,249,245,.16);stroke-width:.6}
.usmap-home{fill:var(--rust);stroke:var(--rust);stroke-width:1.2}
.usmap-haze circle{fill:#D97757;opacity:.20}
.usmap-bloom circle{fill:#E8A87F;opacity:.38}
.usmap-core circle{fill:#FFF3E8;opacity:.90}
.usmap-ring{stroke:var(--cream)}
.usmap-pin-core{fill:var(--cream)}
.usmap-dot{background:var(--rust)}
.usmap-caption{color:var(--charcoal-70)}

/* ---------- motion ----------
   Spring on interaction, and a staggered entrance on scroll. The stagger is
   applied by site.js setting --i on each child; the delay is a multiple of
   it rather than a hand-written nth-child list.

   THIS BLOCK HID THE SITE'S CONTENT AND MUST STAY CHEAP.

   The first version ran 620ms with a 420ms stagger and a 6px blur on every
   one of twenty-seven blocks. Three consequences, all of them reported as
   "the page comes up unfinished":

     - blur() promotes each block to its own compositing layer, so a phone
       was compositing twenty-seven blurred layers over a 190KB document;
     - 620ms + 420ms is over a second before a paragraph is legible, which
       is longer than a flick-scroll takes to pass it;
     - anything the observer had not reached yet was not merely un-animated,
       it was INVISIBLE, because opacity:0 is the resting state.

   So: no blur, no spring on entrance, 260ms, and a stagger small enough that
   the last child of a group is not a third of a second behind the first.
   Motion here is decoration. The failsafe in site.js guarantees the content
   arrives whether or not any of it runs. */
[data-reveal]{
  opacity:0;
  transform:translateY(10px);
  transition:opacity 260ms var(--ease), transform 260ms var(--ease);
  transition-delay:calc(var(--i, 0) * 45ms);
  will-change:opacity, transform;
}
[data-reveal].is-in{opacity:1;transform:none;will-change:auto}

@media (prefers-reduced-motion:reduce){
  [data-reveal]{opacity:1;transform:none;filter:none;transition:none}
  .btn:hover,.card:hover,.prod:hover,.news-card:hover,.offer-card:hover{transform:none}
  *{scroll-behavior:auto}
}

/* The build stamp. Deliberately quiet -- it is a diagnostic, not information
   a buyer needs. --ink-3 on the footer ground, one step down in size. */
.foot-build{color:var(--ink-3);font-family:var(--data);font-size:.72rem;letter-spacing:0;margin-left:10px;white-space:nowrap}


/* ==========================================================================
   HOMEPAGE LAYOUT — the page grid, and the sections placed on it.

   Everything here is scoped to `.is-home` or to a class that only the
   homepage renders. /catalog, /cart and /checkout are transactional surfaces
   and keep the centred 1240px .wrap they have always had.

   WHY THIS EXISTS. Measured on the previous homepage: all twelve .wrap
   elements computed to an identical 1240px box at x=100. The two grids whose
   comments claimed asymmetry were 1.05fr/.95fr and 1fr/.9fr -- a 4.7% offset
   nobody perceives. Median inked-row span was 1174px of 1440. Nothing on the
   page ever left the centreline, which is why a correct palette and correct
   type still read as a template.
   ========================================================================== */

:root{
  /* The page gutter and column gap. Consumed by .bleed, .is-home .promo,
     .is-home .site-head .wrap, .is-home .head-bar .wrap and the footer.
     Change either and check all of them. */
  --gut:clamp(16px,3.2vw,56px);   /* 16 @390  ·  46.08 @1440 */
  --gap:clamp(12px,1.7vw,24px);   /* 12 @390  ·  24.00 @1440 */

  --s1:4px;   --s2:8px;   --s3:12px;  --s4:16px;  --s5:24px;
  --s6:32px;  --s7:48px;  --s8:64px;  --s9:96px;  --s10:128px;
  --s11:168px; --s12:208px;

  --pad-tight:clamp(48px,6vw,96px);
  --pad-open:clamp(96px,11vw,168px);
  --pad-vast:clamp(128px,14vw,208px);

  /* One deliberate jump at the top of the scale, no drift in the middle.
     Capped at 6.25rem — 8.50rem at laptop widths forced four-line headlines
     and collided with the floating plate beside the type. */
  --step-d:clamp(2.75rem, .35rem + 7.8vw, 6.25rem);   /*  44 @390 · 100 @1440 */
}

/* THE PAGE GRID.

   All thirteen line names are written out on purpose. The abbreviated form
   `[c1] repeat(12, minmax(0,1fr)) [c13]` defines only c1 and c13; every
   reference to c2-c12 then resolves to an IMPLICIT line and the browser
   appends a phantom track past the frame. Measured with the short form, an
   item at c5/edge-end rendered x=1346 width=94 instead of x=511 width=929 --
   no error, no warning, just a page that is quietly wrong. Do not abbreviate. */
.bleed{
  display:grid;
  column-gap:var(--gap);
  max-width:1800px;
  margin-inline:auto;
  grid-template-columns:
    [edge] var(--gut)
    [c1]  minmax(0,1fr) [c2]  minmax(0,1fr) [c3]  minmax(0,1fr)
    [c4]  minmax(0,1fr) [c5]  minmax(0,1fr) [c6]  minmax(0,1fr)
    [c7]  minmax(0,1fr) [c8]  minmax(0,1fr) [c9]  minmax(0,1fr)
    [c10] minmax(0,1fr) [c11] minmax(0,1fr) [c12] minmax(0,1fr)
    [c13] var(--gut) [edge-end];
}

/* ---------- hero: charcoal band, display type beside the floating carton ---
   Layering contract across breakpoints:
   1. Sticky header stays above everything (z-index 60).
   2. Hero type stays above the product plate where their columns meet.
   3. line-height on the display H1 never drops low enough to clip ascenders
      (0.86 did — the tops of Research / Wholesale sat under the sticky bar
      and looked like a z-index bug).
   4. Below ~1280px the plate leaves absolute hang and stacks under the CTAs
      so laptop-width overlap cannot bury the headline. */
.hm-hero{
  background:var(--charcoal);color:var(--cream);
  padding-block:clamp(64px, 7.5vw, 104px) clamp(48px, 5vw, 64px);
  position:relative;isolation:isolate;z-index:1;
  overflow:visible;
}

/* THE PHOTOGRAPH, FINALLY DOING WORK. The 100deg gradient is darkest where
   the type is and opens toward the right, behind the product plate, where
   nothing is set. The 52% stop is a CONTRAST device, not a taste one:
   softening it drops the rust eyebrow below 4.5:1 with no visual warning.
   Measured over ground-flatirons-2560.jpg at 1440x801 -- worst pixel in the
   left half #1d1c1b (cream 16.15:1, rust 5.45:1); worst under the display
   #343234 (cream 12.07:1); worst in the plate zone #5b5b5d (cream 6.43:1). */
.hm-hero::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    linear-gradient(100deg,
      rgba(20,20,19,.985) 0%,
      rgba(20,20,19,.955) 52%,
      rgba(20,20,19,.780) 78%,
      rgba(20,20,19,.620) 100%),
    var(--ground-photo,none) center 34% / cover no-repeat,
    var(--charcoal);
}
.hm-hero > .bleed{align-items:start;overflow:visible}

.hm-hero .label{
  grid-column:c1/c7;grid-row:1;display:block;margin:0 0 var(--s5);
  color:var(--rust);            /* MARK -- rust on charcoal, 5.45:1 worst measured */
  font-family:var(--display);font-weight:600;font-size:var(--step--1);
  letter-spacing:.15em;text-transform:uppercase;
  position:relative;z-index:2;
}
.hm-h1{
  /* Stop at c7 on wide layouts — c8 let the display line run under the plate
     column at 1200–1400px where the gutter dropped under ~20px. */
  grid-column:c1/c7;grid-row:2;
  margin:0 0 var(--s6);
  margin-left:0;
  padding-top:.08em;
  font-family:var(--display);font-weight:500;
  font-size:calc(var(--step-d) * var(--type-scale));
  line-height:1.04;letter-spacing:-.048em;color:var(--cream);
  overflow:visible;
  position:relative;z-index:2;
  text-wrap:pretty;
  overflow-wrap:normal;
}
.hm-lede{
  grid-column:c1/c7;grid-row:3;
  font-size:calc(var(--step-1) * var(--type-scale));line-height:1.5;
  color:rgba(250,249,245,.86);  /* 13.05:1 on charcoal, 12.1:1 on the composite */
  max-width:48ch;margin:0 0 var(--s5);
  position:relative;z-index:2;
}
.hm-hero .hero-actions{
  grid-column:c1/c7;grid-row:4;display:flex;gap:var(--s4);flex-wrap:wrap;margin:0;
  position:relative;z-index:2;
}

/* ---- the box, inside the charcoal band ----
   The cutout floats beside the lede/actions. height:0 keeps the figure from
   stretching the band; z-index stays below the type so a mid-width overlap
   never buries the headline. */
.hm-fig{
  grid-column:c8/edge-end;grid-row:3 / 6;
  align-self:start;margin:0;padding-top:var(--s6);height:0;position:relative;z-index:1;
}
.hm-shot-frame{
  position:absolute;top:0;left:0;width:100%;
  overflow:visible;aspect-ratio:1073/873;min-height:160px;background:transparent;
  transform:none;
}
.hm-photo{
  position:absolute;inset:0;width:100%;height:100%;
  max-width:none;border:0;border-radius:0;
  object-fit:contain;object-position:center center;
  filter:drop-shadow(0 18px 28px rgba(0,0,0,.45));
}
.hm-fig svg{position:absolute;top:0;left:0;width:100%;height:auto;display:block}
.hm-fig figcaption{
  position:absolute;bottom:100%;left:0;margin:0 0 var(--s3);
  font-family:var(--display);font-weight:500;font-size:var(--step--1);
  letter-spacing:.12em;text-transform:uppercase;text-align:left;
  color:var(--cream);
  white-space:nowrap;
}

/* Wide viewports: cap the plate width and pin it to the right gutter so the
   hang clears the three pillar columns. padding-top on .hm-pillars used to be
   220–340px for this; it was cut to ~96px and the box started sitting on
   "Domestic shipping" at laptop zoom. clamp() tracks zoom and resolution
   without a fixed void. */
@media (min-width:1281px){
  .hm-shot-frame{
    width:min(100%,clamp(240px,20vw,360px));
    left:auto;right:0;
  }
  .hm-hero{
    padding-top:clamp(80px, 8vw, 112px);
    padding-bottom:clamp(56px, 6vw, 96px);
  }
  .hm-fig{padding-top:clamp(32px, 4vw, 56px)}
  .hm-pillars{padding-top:clamp(96px, 11vw, 168px)}
}

/* Laptop and below: stack the plate under the copy so absolute hang cannot
   collide with the headline or CTAs. 1280px is the measured point where the
   h1–frame gutter dropped under ~20px while the frame still hung into the
   CTA row — including browser zoom on a 1440px screen. Production shipped
   1100px and left a dead zone up to ~1400px with a 136px headline. */
@media (max-width:1280px){
  .hm-hero{padding-block:clamp(40px,6vw,56px) clamp(40px,6vw,56px)}
  .hm-hero .label,
  .hm-lede,
  .hm-hero .hero-actions{grid-column:c1/c13}
  .hm-h1{
    grid-column:edge/edge-end;
    font-size:clamp(2.35rem,7.5vw,4.25rem);
    line-height:1.05;
    letter-spacing:-.04em;
    padding-top:.04em;
  }
  .hm-fig{
    grid-column:c1/c13;grid-row:5;
    height:auto;align-self:stretch;
    margin:var(--s5) 0 0;
    z-index:1;
  }
  .hm-shot-frame{
    position:relative;top:auto;left:auto;
    width:min(100%,26rem);margin:0 auto;
    transform:none;min-height:0;
  }
  /* The plate carries its own empty margin above the carton, which stacked
     under the caption as a band of bare charcoal. Cropping to a shorter
     frame biased toward the carton removes the source's padding instead of
     adding CSS gaps back on top of it. */
  .hm-photo{
    position:relative;inset:auto;width:100%;height:auto;
    aspect-ratio:1073/740;display:block;
    object-fit:cover;object-position:center 72%;
  }
  .hm-fig figcaption{
    position:static;bottom:auto;
    margin:0 0 var(--s2);
    text-align:center;white-space:normal;
  }
  .hm-fig svg{position:relative;width:min(100%,26rem);margin:0 auto;display:block}
  .hm-hero .hero-actions{gap:var(--s3)}
}

/* Narrow / mobile: stack every homepage band in DOM order instead of the
   13-column grid. display:block on .bleed (below) drops grid formatting;
   these rules run first so typography and spacing stay intentional. */
@media (max-width:960px){
  .hm-prices > .bleed{
    display:flex;flex-direction:column;gap:var(--s6);
  }
  .hm-prices-h,
  .hm-prices-note,
  .feat-list{
    grid-column:unset;grid-row:unset;width:100%;max-width:none;
  }
  .hm-prices-note{max-width:42ch}
  .reg-head,.feat-row a{padding-right:0}
}

@media (max-width:640px){
  .hm-hero{padding-block:clamp(28px,5vw,44px) clamp(32px,5vw,48px)}
  .hm-hero > .bleed{
    display:flex;flex-direction:column;gap:var(--s4);
  }
  .hm-hero .label,
  .hm-h1,
  .hm-lede,
  .hm-hero .hero-actions,
  .hm-fig{
    grid-column:unset;grid-row:unset;width:100%;max-width:none;
  }
  .hm-h1{
    font-size:clamp(1.85rem,9vw,2.65rem);
    line-height:1.08;letter-spacing:-.035em;
  }
  .hm-lede{font-size:var(--step-0);line-height:1.55;max-width:none}
  .hm-hero .hero-actions{
    flex-direction:column;align-items:stretch;gap:var(--s3);
  }
  .hm-hero .hero-actions .btn{width:100%;white-space:normal;text-align:center}
  .hm-fig{margin:var(--s2) 0 0}
  .hm-shot-frame{width:min(100%,20rem)}
}

/* ---------- the price list ------------------------------------------------
   Nine real SKUs, out from behind the Featured tab. The heading takes a
   narrow left block and the list runs wide right: 306.96 against 928.64 at
   1440, a 33/67 split. The hairlines run to the viewport edge while the
   numbers stop dead on c13, which rhymes with the photograph bleeding off
   that same edge above.

   Top padding clears the hero photograph's overhang on wide layouts — see the
   min-width:1201px rule on .hm-pillars. Stacked layouts (≤1200px) need none. */
/* ---------- live undercut strip (copy only; no competitor scrape) -------- */
.hm-undercut{
  padding-block:clamp(28px,4vw,48px);
  background:transparent;
  position:relative;z-index:1;
}
.hm-undercut-panel{
  grid-column:c1/c13;
  display:grid;
  grid-template-columns:auto minmax(0,1fr) auto;
  grid-template-areas:
    "live head btn"
    "live body btn";
  column-gap:clamp(20px,3vw,36px);
  row-gap:var(--s3);
  align-items:center;
  padding:clamp(20px,2.5vw,28px) clamp(22px,3vw,36px);
  background:rgba(250,249,245,.88);
  border:1px solid var(--hair);
  box-shadow:0 18px 40px rgba(20,20,19,.08);
}
.hm-undercut-live{
  grid-area:live;align-self:start;
  display:inline-flex;align-items:center;gap:8px;
  margin-top:4px;
  font-family:var(--display);font-weight:600;font-size:var(--step--1);
  letter-spacing:.14em;text-transform:uppercase;color:var(--charcoal);
  white-space:nowrap;
}
/* Live indicator. Three level bars stepping like a meter — the owner turned
   down two dot treatments (expanding ring, breathing glow), so this drops the
   dot entirely. The element is the middle bar; the pseudo-elements are the
   outer two, offset a third of a cycle each so the wave never freezes. Bars
   scale from the bottom like a real meter, and reduced-motion users get a
   static mid-read instead of nothing. */
.hm-undercut-dot{
  position:relative;
  width:3px;height:12px;border-radius:1px;
  margin:0 6px 0 1px;
  background:var(--rust);
  transform-origin:bottom;
  animation:hm-live-bar 1.2s ease-in-out infinite;
  animation-delay:-.4s;
}
.hm-undercut-dot::before,
.hm-undercut-dot::after{
  content:"";
  position:absolute;bottom:0;width:3px;height:100%;border-radius:1px;
  background:var(--rust);
  transform-origin:bottom;
  animation:hm-live-bar 1.2s ease-in-out infinite;
}
.hm-undercut-dot::before{left:-6px;animation-delay:-.8s}
.hm-undercut-dot::after{left:6px;animation-delay:0s}
@keyframes hm-live-bar{
  0%,100%{transform:scaleY(.3)}
  50%{transform:scaleY(1)}
}
@media (prefers-reduced-motion:reduce){
  .hm-undercut-dot,.hm-undercut-dot::before,.hm-undercut-dot::after{animation:none}
  .hm-undercut-dot{transform:scaleY(.85)}
  .hm-undercut-dot::before{transform:scaleY(.55)}
  .hm-undercut-dot::after{transform:scaleY(.7)}
}
.hm-undercut-h{
  grid-area:head;margin:0;
  font-family:var(--display);font-weight:500;
  font-size:calc(var(--step-2) * var(--type-scale));
  line-height:1.15;letter-spacing:-.02em;color:var(--charcoal);
  text-wrap:balance;
}
.hm-undercut-p{
  grid-area:body;margin:0;max-width:62ch;
  font-size:calc(var(--step-0) * var(--type-scale));line-height:1.5;
  color:var(--charcoal-70);
}
.hm-undercut-p strong{color:var(--charcoal);font-weight:600}
.hm-undercut-panel > .btn{grid-area:btn;justify-self:end;align-self:center;white-space:nowrap}
@media (max-width:820px){
  .hm-undercut-panel{
    grid-template-columns:1fr;
    grid-template-areas:"live" "head" "body" "btn";
  }
  .hm-undercut-panel > .btn{justify-self:start}
}

.hm-prices{
  padding-block:var(--s8) var(--s8);
  /* Cream band, not transparent: the Fixed Flatirons ground used to show
     through this list on phones and made every SKU row fight the forest. */
  background:rgba(250,249,245,.96);
  position:relative;z-index:0;
  border-block:1px solid var(--hair);
}

.hm-prices-h{
  grid-column:c1/c4;grid-row:1;align-self:start;margin:0;
  font-size:calc(var(--step-2) * var(--type-scale));
  text-wrap:initial;
  color:var(--charcoal);
}
/* The note used to share the heading's grid row and get pushed clear of it
   with a margin computed from the heading's font size — which broke the
   moment the heading wrapped to two lines and left the note jammed against
   the descenders. Two rows, no arithmetic. Sans, not serif: a serif caption
   under a grotesk heading at this size read as a typo, not a pairing. */
.hm-prices-note{
  grid-column:c1/c4;grid-row:2;align-self:start;
  margin:var(--s3) 0 0;
  font-family:var(--display);
  font-size:var(--step-0);
  line-height:1.5;
  color:var(--charcoal-70);max-width:26ch;
}

.feat-list{
  grid-column:c5/edge-end;grid-row:1 / 3;
  list-style:none;margin:0;padding:0;border-top:1px solid var(--charcoal);
}
.reg-head,.feat-row a{
  display:grid;align-items:baseline;
  grid-template-columns:40px 84px minmax(0,1fr) minmax(128px,168px) minmax(96px,112px);
  column-gap:clamp(var(--s4),1.6vw,var(--s6));
  padding-right:calc(var(--gut) + var(--gap));
}
.reg-head{
  padding-block:var(--s3);border-bottom:1px solid var(--hair);
  font-family:var(--display);font-size:var(--step--1);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--charcoal-50);  /* 4.97:1 */
}
.reg-head span{white-space:nowrap}
.reg-head span:nth-child(1){grid-column:2}
.reg-head span:nth-child(2){grid-column:3}
.reg-head span:nth-child(3){grid-column:4}
.reg-head span:nth-child(4){grid-column:5;text-align:right}

.feat-row{
  border-bottom:1px solid var(--hair);
  content-visibility:auto;contain-intrinsic-size:auto 4.75rem;
}
.feat-row a{
  text-decoration:none;padding-block:clamp(var(--s4),1.7vw,var(--s5));
  transition:transform 180ms var(--ease-spring),background 180ms var(--ease);
}
.feat-row a:hover{transform:translateX(6px);background:rgba(20,20,19,.045)}
.reg-i{
  font-family:var(--data);font-size:var(--step--1);color:var(--charcoal-50);
  padding:2px 6px;transition:background 180ms var(--ease),color 180ms var(--ease);
}
.feat-row a:hover .reg-i{background:var(--rust);color:var(--charcoal)}   /* FILL — 5.90:1 */
.feat-sku{font-family:var(--data);font-size:var(--step-0);color:var(--charcoal-70);letter-spacing:.06em}
.feat-name{font-family:var(--display);font-weight:500;font-size:calc(var(--step-1) * var(--type-scale));color:var(--charcoal);line-height:1.28}
.feat-strength{font-family:var(--data);font-size:var(--step--1);color:var(--charcoal-70);line-height:1.35;white-space:normal}
.feat-price{
  font-family:var(--display);font-weight:600;
  font-size:calc(var(--step-1) * var(--type-scale));
  text-align:right;color:var(--charcoal);white-space:nowrap;
}
.feat-price.is-quote{font-family:var(--data);font-weight:400;font-size:var(--step-0);color:var(--charcoal-70)}
.feat-empty{padding:var(--s5) 0;border-bottom:1px solid var(--hair)}
.feat-empty-msg{
  display:block;max-width:52ch;color:var(--charcoal-70);
  font-size:calc(var(--step-0) * var(--type-scale));line-height:1.5;
}
.feat-empty-msg code{font-family:var(--data);font-size:.92em}
/* Not optional. Nine right-aligned prices that do not align digit-for-digit
   undercut the one section whose whole job is to look transparent. */
.feat-price,.feat-sku,.reg-i{font-variant-numeric:tabular-nums slashed-zero}

@media (max-width:760px){
  .reg-head,.reg-i{display:none}
  .feat-row a{grid-template-columns:minmax(0,1fr) auto;row-gap:6px;padding-block:14px;padding-right:0;min-height:68px}
  .feat-sku{grid-column:1;grid-row:2}
  .feat-name{grid-column:1;grid-row:1}
  .feat-strength{grid-column:2;grid-row:2;text-align:right}
  .feat-price{grid-column:2;grid-row:1}
}

/* The mobile collapse. Switching .bleed to a vertical flex stack keeps DOM
   order, drops grid-column assignments cleanly, and reflows live as the
   window is resized — display:block left grid-row numbers inert but gave
   sections no gap and made mid-width pricing rows fight old tab CSS. */
@media (max-width:760px){
  .is-home .bleed{
    display:flex;flex-direction:column;gap:var(--s5);
    padding-inline:var(--gut);
  }
  .is-home .bleed > *{
    grid-column:unset !important;grid-row:unset !important;
    width:100%;max-width:none;
  }
}

/* The ghost button on a dark band. .btn-ghost is charcoal type inside a
   charcoal border, which is correct on cream and measures 1.00:1 on the hero
   -- the "Open an account" call to action was rendering fully invisible at
   x=281, 180px wide, on the first screen. Cream on charcoal is 17.50:1.
   Scoped to the dark band only; the cream sections keep the charcoal ghost. */
.hm-hero .btn-ghost{color:var(--cream);border-color:rgba(250,249,245,.55);background:transparent}
.hm-hero .btn-ghost:hover{border-color:var(--cream);background:rgba(250,249,245,.08)}

/* ---------- pillars + mission: translucent so the Flatirons read through --
   Solid cream here would paint over body::before and undo the lighter scrim.
   rgba cream keeps type legible while the rock shows as atmosphere, not a
   postcard behind the copy. No cards, no icon pills — just three columns
   and a serif mission line, matching the mockup the owner preferred.

   Top padding used to be ~220–340px to clear a hanging JPEG plate that
   spilled deep into this band. The floating PNG cutout sits mostly inside
   the charcoal hero now, so that clearance is handled on wide viewports by
   the min-width:1281px padding-top rule — modest on stacked layouts. */
.hm-pillars{
  padding-block:clamp(40px,5vw,64px) clamp(40px,5vw,64px);
  padding-top:clamp(48px,6vw,72px);
  background:rgba(250,249,245,.42);
  border-bottom:1px solid var(--hair);
  position:relative;z-index:0;
}
.hm-pillar-list{
  list-style:none;margin:0;padding:0;
  grid-column:c1/c13;
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(28px,4vw,48px);
}
.hm-pillar{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0}
.hm-pillar-ico{color:var(--rust);flex:0 0 auto;display:block}
.hm-pillar h2{
  margin:0;font-family:var(--display);font-weight:600;
  font-size:var(--step-0);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink);line-height:1.25;
}
.hm-pillar p{
  margin:0;max-width:36ch;color:var(--ink-2);
  font-size:calc(var(--step-0) * var(--type-scale));line-height:1.5;
}
@media (max-width:820px){
  .hm-pillar-list{grid-template-columns:1fr;gap:28px}
}

.hm-mission{
  padding-block:clamp(48px,7vw,88px);
  background:rgba(250,249,245,.88);
  position:relative;z-index:0;
}
.hm-mission > .bleed{align-items:start}
.hm-mission .label{
  grid-column:c1/c5;grid-row:1;display:block;margin:0 0 var(--s5);
  color:var(--rust);font-family:var(--display);font-weight:600;
  font-size:var(--step--1);letter-spacing:.15em;text-transform:uppercase;
}
.hm-mission .label::after{
  content:"";display:inline-block;width:2.2em;height:1px;
  margin-left:.65em;vertical-align:middle;background:var(--rust);opacity:.7;
}
.hm-mission h2{
  grid-column:c1/c8;grid-row:2;margin:0;
  font-family:var(--body);font-weight:500;
  font-size:clamp(1.85rem,3.6vw,2.85rem);line-height:1.12;
  letter-spacing:-.025em;color:var(--ink);max-width:16ch;
  text-wrap:balance;
}
.hm-mission p{
  grid-column:c8/c13;grid-row:2;margin:0;align-self:end;
  max-width:42ch;color:var(--ink-2);
  font-size:calc(var(--step-1) * var(--type-scale));line-height:1.55;
}
@media (max-width:900px){
  .hm-mission h2{grid-column:c1/c13;grid-row:2;max-width:18ch;margin-bottom:var(--s5)}
  .hm-mission p{grid-column:c1/c13;grid-row:3;align-self:start}
}
@media (min-width:901px) and (max-width:1200px){
  /* Mid-width / zoomed: mission copy stacks under the headline instead of
     sitting at the far grid edge with a dead zone between. */
  .hm-mission h2{grid-column:c1/c10}
  .hm-mission p{grid-column:c1/c11;grid-row:3;margin-top:var(--s5);align-self:start}
}

/* ---------- the manifest --------------------------------------------------
   Replaces a 3x2 grid of six identical 370.66px cells whose values rendered
   at 15.2px -- smaller than the 18px body copy introducing them. Seven rows,
   because an odd count cannot read as a matrix. */
.hm-manifest{padding-block:var(--pad-open)}
.hm-manifest-h{
  grid-column:c1/c5;grid-row:1;align-self:start;
  position:sticky;top:calc(118px + var(--s6));
  font-size:calc(var(--step-3) * var(--type-scale));
  line-height:1.02;letter-spacing:-.028em;margin:0;
  text-wrap:initial;
}
.manifest{grid-column:c5/c13;grid-row:1;margin:0;border-top:1px solid var(--hair)}
.mf-row{
  display:grid;grid-template-columns:minmax(0,3.1fr) minmax(0,8.9fr);
  column-gap:var(--gap);align-items:baseline;
  padding-block:clamp(var(--s5),2vw,var(--s6));
  border-bottom:1px solid var(--hair);
}
.mf-row dt{
  font-family:var(--display);font-weight:600;font-size:var(--step--1);
  letter-spacing:.15em;text-transform:uppercase;color:var(--charcoal-50);  /* 4.97:1 */
}
.mf-row dd{
  margin:0;font-family:var(--display);font-weight:500;
  font-size:calc(var(--step-2) * var(--type-scale));
  line-height:1.16;letter-spacing:-.02em;color:var(--charcoal);            /* 17.50:1 */
  max-width:46ch;
}
/* The sentence a procurement manager buys on. The only value at heading
   scale, and the widest line in the section. */
.mf-coa dd{
  font-size:calc(var(--step-2) * var(--type-scale));
  font-weight:500;line-height:1.2;letter-spacing:-.02em;max-width:36ch;
}
.mf-coa a{color:var(--rust);text-decoration:underline;text-underline-offset:3px}
.mf-coa a:hover{color:var(--charcoal)}
@media (max-width:760px){
  .hm-manifest-h{position:static;top:auto;margin-bottom:var(--s7)}
  .mf-row{grid-template-columns:minmax(0,1fr);row-gap:var(--s2)}
  .mf-row dd,.mf-coa dd{max-width:none}
}

/* ---------- COA teaser on home (deep copy → /analytical-reality) --------- */
.hm-coa{
  padding-block:var(--pad-open);
  background:rgba(250,249,245,.92);
  border-top:1px solid var(--hair);
  border-bottom:1px solid var(--hair);
  position:relative;z-index:0;
}
.hm-coa > .bleed{align-items:start}
.hm-coa .label{
  grid-column:c1/c5;grid-row:1;display:block;margin:0 0 var(--s5);
  color:var(--rust);font-family:var(--display);font-weight:600;
  font-size:var(--step--1);letter-spacing:.15em;text-transform:uppercase;
}
.hm-coa h2{
  grid-column:c1/c10;grid-row:2;margin:0 0 var(--s5);
  font-size:calc(var(--step-4) * var(--type-scale));
  line-height:1.02;letter-spacing:-.035em;max-width:22ch;text-wrap:balance;
}
.hm-coa-lede{
  grid-column:c1/c9;grid-row:auto;margin:0 0 var(--s5);
  max-width:56ch;color:var(--ink-2);
  font-size:calc(var(--step-1) * var(--type-scale));line-height:1.5;
}
.hm-coa .hm-more{
  grid-column:c1/c9;grid-row:auto;margin-top:var(--s3);
}
@media (max-width:900px){
  .hm-coa h2,.hm-coa-lede,.hm-coa .hm-more{grid-column:c1/c13;max-width:none}
}

/* ---------- the closing band ----------------------------------------------
   Was text-align:center with a centred paragraph and centred buttons -- the
   most generic closing band available. The headline now pulls left past the
   frame like the hero h1, and the buttons pin to the opposite corner. */
.hm-close{
  padding-block:var(--pad-vast);
  border-top:0;                 /* the band above is the rule */
  text-align:left;background:transparent;
}
.hm-close h2{
  grid-column:edge/c9;grid-row:1;
  margin:0 0 var(--s6);margin-left:-.035em;
  font-size:calc(var(--step-4) * var(--type-scale));
  line-height:.94;letter-spacing:-.042em;text-wrap:initial;
}
.hm-close p{
  grid-column:c1/c6;grid-row:2;margin:0;
  font-size:calc(var(--step-1) * var(--type-scale));
  color:var(--charcoal-70);max-width:36ch;   /* 6.45:1 */
}
.hm-close .hero-actions{
  grid-column:c9/c13;grid-row:1/3;
  align-self:end;justify-self:end;
  display:flex;gap:var(--s4);flex-wrap:wrap;justify-content:flex-end;margin:0;
}
@media (max-width:760px){
  .hm-close h2{margin-left:-.02em}
  .hm-close .hero-actions{justify-self:stretch;justify-content:flex-start;margin-top:var(--s7);flex-direction:column;align-items:stretch}
  .hm-close .btn{text-align:center;min-height:48px;display:flex;align-items:center;justify-content:center}
}

/* The step-4 token the closing headline needs. */

/* ---------- logistics: full-bleed charcoal --------------------------------
   The best element on the page was a 1px-hairline card in a 561/505 near-even
   split. Border, radius, padding and the fake asymmetry are gone.

   The ::before does two jobs. The first gradient masks the photograph off the
   map's columns with opaque charcoal from 43% rightward -- the map starts at
   c6 = 43.17%, so the mask is flat under every pixel of it. THIS IS A
   CONTRAST DEVICE: the landmass reads 1.70:1 against flat charcoal, but where
   the photograph shows through the composite lifts and it drops to 1.51:1.
   Do not move the 43% stop right. Measured from a real render at 1440x830 --
   type zone worst pixel #251f1b (cream 15.45:1, rust 5.21:1); map zone flat
   #141413 (cream 17.50:1). */
.hm-logistics{
  background:var(--charcoal);color:var(--cream);
  padding-block:var(--pad-open);
  position:relative;isolation:isolate;
}
.hm-logistics::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    linear-gradient(90deg, rgba(20,20,19,0) 0 40%, var(--charcoal) 43% 100%),
    linear-gradient(100deg,
      rgba(20,20,19,.985) 0%,
      rgba(20,20,19,.945) 42%,
      rgba(20,20,19,.900) 46%,
      rgba(20,20,19,.900) 100%),
    var(--ground-photo,none) center 55% / cover no-repeat,
    var(--charcoal);
}
.hm-logistics > .bleed{align-items:start}
.hm-logistics .label{grid-column:c1/c5;grid-row:1;color:var(--rust);margin:0 0 var(--s5)}  /* MARK — 5.21:1 */
.hm-logistics h2{
  grid-column:c1/c6;grid-row:2;
  font-size:calc(var(--step-4) * var(--type-scale));
  line-height:.98;letter-spacing:-.04em;color:var(--cream);margin:0 0 var(--s6);
  max-width:12ch;text-wrap:initial;
}
.hm-logistics p{
  grid-column:c1/c5;
  font-size:calc(var(--step-0) * var(--type-scale));
  color:rgba(250,249,245,.86);max-width:42ch;margin:0 0 var(--s5);   /* 13.05:1 */
}
.hm-logistics p:nth-of-type(1){grid-row:3}
.hm-logistics p:nth-of-type(2){grid-row:4}
.hm-logistics .logi-note{
  grid-column:c1/c5;grid-row:5;margin:var(--s5) 0 0;
  padding:var(--s3) var(--s4);border-radius:0;border:0;
  background:rgba(250,249,245,.07);
  border-left:3px solid var(--rust);                  /* MARK — 5.21:1 */
  color:rgba(250,249,245,.86);
}
.hm-logistics .logi-note strong{color:var(--cream)}
/* On the charcoal logistics band the land used to fill with --charcoal on a
   charcoal ground, so the silhouette vanished, and state seams at 16% cream
   were invisible from a normal viewing distance — the owner reported "you
   can't see it… there's no borders." A later pass at .55 still read as a
   soft blob under the city lights, so seams are near-cream and the land is
   lifted another step so the outline and interior borders both read. Scoped
   to .hm-logistics so a cream-ground use of the same partial is untouched. */
.hm-logistics .usmap-land{
  fill:#3c3b38;stroke:rgba(250,249,245,.45);stroke-width:1.4;stroke-linejoin:round;
}
.hm-logistics .usmap-borders{
  fill:none;stroke:rgba(250,249,245,.82);stroke-width:1.35;stroke-linejoin:round;
}
.hm-logistics .usmap-home{
  fill:var(--rust);stroke:rgba(250,249,245,.95);stroke-width:1.6;stroke-linejoin:round;
}
.hm-logistics .usmap-haze circle{opacity:.18}
.hm-logistics .usmap-bloom circle{opacity:.36}
.hm-logistics .usmap-core circle{opacity:.95}
.hm-logistics .usmap-caption{color:rgba(250,249,245,.72)}

.logi-map{grid-column:c6/edge-end;grid-row:1/6;align-self:center;margin:0}
.logi-map svg{width:100%;height:auto;display:block}
@media (max-width:760px){
  .logi-map{margin-top:var(--s7)}
  .hm-logistics h2,.hm-logistics p,.hm-logistics .logi-note{max-width:none}
}

/* The operational shipping facts on /terms. A label/value list rather than
   prose, because this is what the footer's "Shipping & returns" link is
   opened to find and nobody reads a paragraph for a cutoff time. */
.ship-facts{margin:0 0 28px;border-top:1px solid var(--hair)}
.ship-facts > div{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,3fr);
  gap:8px 24px;align-items:baseline;
  padding:14px 0;border-bottom:1px solid var(--hair);
}
.ship-facts dt{
  font-family:var(--display);font-weight:600;font-size:var(--step--1);
  letter-spacing:.14em;text-transform:uppercase;color:var(--charcoal-50);  /* 4.97:1 */
}
.ship-facts dd{margin:0;color:var(--charcoal)}                             /* 17.50:1 */
.ret-lede{font-weight:500}
@media (max-width:640px){
  .ship-facts > div{grid-template-columns:minmax(0,1fr);gap:4px}
}

/* ---------- shipping, on the landing page ---------------------------------
   Same five facts as /terms section 8 and 9. They live here because this is
   the page a buyer is on when they ask them. Narrow sticky heading, wide
   rows -- the same 33/67 relationship as the price list and the manifest, so
   the page has one structural idea rather than three. */
.hm-ship{padding-block:var(--pad-open)}
.hm-ship-h{
  grid-column:c1/c4;grid-row:1;align-self:start;margin:0;
  position:sticky;top:calc(118px + var(--s6));
  font-size:calc(var(--step-3) * var(--type-scale));
  line-height:1.02;letter-spacing:-.028em;text-wrap:initial;
}
.ship-rows{grid-column:c5/c13;grid-row:1;margin:0;border-top:1px solid var(--charcoal)}
.ship-rows > div{
  display:grid;grid-template-columns:minmax(0,3.1fr) minmax(0,8.9fr);
  column-gap:var(--gap);align-items:baseline;
  padding-block:clamp(var(--s4),1.6vw,var(--s5));
  border-bottom:1px solid var(--hair);
}
.ship-rows dt{
  font-family:var(--display);font-weight:600;font-size:var(--step--1);
  letter-spacing:.15em;text-transform:uppercase;color:var(--charcoal-50);   /* 4.97:1 */
}
.ship-rows dd{
  margin:0;font-size:calc(var(--step-0) * var(--type-scale));
  line-height:1.5;color:var(--charcoal);max-width:52ch;                     /* 17.50:1 */
}
.ship-rows dd strong{font-weight:600}
@media (max-width:760px){
  .hm-ship-h{position:static;top:auto;margin-bottom:var(--s6)}
  .ship-rows > div{grid-template-columns:minmax(0,1fr);row-gap:var(--s1)}
  .ship-rows dd{max-width:none}
}

/* ---------- the product clips ---------------------------------------------
   Two portrait phone videos of real stock. Asymmetric spans and a vertical
   offset on the second, so two tall rectangles do not read as a pair of
   cards. preload="none": the files are 21MB together and nobody should pay
   that before choosing to watch. */
.hm-clips{padding-block:var(--pad-open) var(--pad-tight);background:var(--cream-2)}
.hm-clips .label{grid-column:c1/c5;grid-row:1;display:block;margin:0 0 var(--s4);color:var(--charcoal-50)}
.hm-clips-h{
  grid-column:c1/c7;grid-row:2;margin:0 0 var(--s4);
  font-size:calc(var(--step-3) * var(--type-scale));
  line-height:1.02;letter-spacing:-.028em;text-wrap:initial;
}
.hm-clips-note{
  grid-column:c1/c6;grid-row:3;margin:0 0 var(--s8);
  font-size:var(--step-0);color:var(--charcoal-70);max-width:44ch;          /* 6.45:1 */
}
.clip{margin:0}
.clip-a{grid-column:c1/c6;grid-row:4}
.clip-b{grid-column:c7/c12;grid-row:4;margin-top:var(--s9)}   /* the offset that stops it being a pair */
.clip-v{
  width:100%;height:auto;display:block;background:var(--charcoal);
  border:1px solid var(--hair);
}
.clip figcaption{
  margin-top:var(--s3);font-family:var(--display);font-weight:500;
  font-size:var(--step--1);letter-spacing:.1em;text-transform:uppercase;
  color:var(--charcoal-50);                                                 /* 4.97:1 */
}
@media (max-width:760px){
  .clip-b{margin-top:var(--s7)}
  .hm-clips-note{margin-bottom:var(--s6)}
}

/* ---- shipping address suggestions -----------------------------------------
   The list is positioned against .addr-field rather than the textarea so it
   still lands correctly when the textarea is resized by the browser's own
   grip. It is hidden by the `hidden` attribute, not a class, so the field
   degrades to a plain textarea when JavaScript is off. */
.addr-field { position:relative; }

.addr-suggestions {
  position:absolute; z-index:40; left:0; right:0; top:calc(100% - 4px);
  margin:0; padding:4px; list-style:none;
  background:var(--paper); border:1px solid var(--line-2); border-radius:8px;
  box-shadow:0 10px 28px rgba(0,0,0,.14);
  max-height:15rem; overflow-y:auto;
}
.addr-suggestions[hidden] { display:none; }

.addr-suggestion {
  padding:9px 11px; border-radius:6px; cursor:pointer;
  font-size:15px; line-height:1.35; color:var(--ink);
}
/* Hover and keyboard selection must look identical -- the arrow keys are the
   accessible path through this list and should not feel like a lesser one. */
.addr-suggestion:hover,
.addr-suggestion.is-active { background:var(--accent-soft); color:var(--accent-text); }

@media (prefers-reduced-motion:no-preference) {
  .addr-suggestion { transition:background .12s ease; }
}

/* ---------- /testing — fill the empty Flatirons under the worth columns --
   The owner screenshot showed half a viewport of unused ground after "What a
   supplier COA is worth." That space is now the skepticism band: why COAs
   fall short, the analyses they omit, and why people skip them (cost).
   Translucent cream so the Flatirons still read; denser list so it does not
   look like another empty band with a thin bullet list floating in it. */
.pg-testing .tst-hero{padding-bottom:48px}
.pg-testing .tst-hero h1{max-width:21ch}
.pg-testing .tst-split{padding-top:48px;padding-bottom:56px}
.pg-testing .tst-grid{gap:48px;align-items:start}
.pg-testing .tst-gaps{
  padding-block:clamp(56px,7vw,96px);
  background:rgba(250,249,245,.48);
  border-top:1px solid var(--hair);
  border-bottom:1px solid var(--hair);
}
.pg-testing .tst-gaps .section-head{margin-bottom:36px}
.pg-testing .tst-gap-list{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0;border-top:1px solid var(--hair);
}
.pg-testing .tst-gap-list li{
  display:grid;gap:6px;
  padding:20px 22px 20px 0;
  border-bottom:1px solid var(--hair);
}
.pg-testing .tst-gap-list li:nth-child(odd){padding-right:28px}
.pg-testing .tst-gap-list li:nth-child(even){padding-left:28px;border-left:1px solid var(--hair)}
.pg-testing .tst-gap-list strong{
  font-family:var(--display);font-weight:600;
  font-size:var(--step-0);letter-spacing:.02em;color:var(--ink);
}
.pg-testing .tst-gap-list span{
  color:var(--ink-2);font-size:calc(var(--step-0) * var(--type-scale));line-height:1.45;
  max-width:42ch;
}
.pg-testing .tst-gap-why{
  margin:28px 0 0;max-width:62ch;
  color:var(--ink);font-size:calc(var(--step-1) * var(--type-scale));line-height:1.5;
}
.pg-testing .tst-program{padding-block:clamp(56px,7vw,88px)}
.pg-testing .tst-close{padding-top:48px;padding-bottom:72px}
@media (max-width:760px){
  .pg-testing .tst-gap-list{grid-template-columns:1fr}
  .pg-testing .tst-gap-list li:nth-child(odd),
  .pg-testing .tst-gap-list li:nth-child(even){
    padding-left:0;padding-right:0;border-left:0;
  }
}

/* ---------- /unlabeled — cream Why band, no photo-fighting cards -------- */
.pg-supply .supply-hero{padding-bottom:48px}
.pg-supply .supply-why{
  padding-block:clamp(48px,6vw,80px);
  background:rgba(250,249,245,.96);
  border-top:1px solid var(--hair);
  border-bottom:1px solid var(--hair);
}
.pg-supply .supply-why h2{
  margin:0 0 16px;max-width:22ch;
  font-size:calc(var(--step-3) * var(--type-scale));
  line-height:1.12;letter-spacing:-.03em;
}
.pg-supply .supply-why .lede{max-width:58ch;margin:0 0 28px}
.pg-supply .supply-why .label{
  display:block;margin:0 0 14px;color:var(--rust);
  font-family:var(--display);font-weight:600;
  font-size:var(--step--1);letter-spacing:.15em;text-transform:uppercase;
}
.pg-supply .supply-facts{
  margin:8px 0 0;padding:0;border-top:1px solid var(--hair);
  display:grid;grid-template-columns:1fr 1fr;gap:0;
}
.pg-supply .supply-facts > div{
  display:grid;grid-template-columns:minmax(7rem,9rem) minmax(0,1fr);
  gap:12px 18px;align-items:baseline;
  padding:16px 20px 16px 0;border-bottom:1px solid var(--hair);
}
.pg-supply .supply-facts > div:nth-child(even){padding-left:24px;border-left:1px solid var(--hair)}
.pg-supply .supply-facts dt{
  margin:0;font-family:var(--display);font-weight:600;
  font-size:var(--step--1);letter-spacing:.12em;text-transform:uppercase;color:var(--charcoal-50);
}
.pg-supply .supply-facts dd{
  margin:0;color:var(--ink-2);
  font-size:calc(var(--step-0) * var(--type-scale));line-height:1.45;
}
@media (max-width:700px){
  .pg-supply .supply-facts{grid-template-columns:1fr}
  .pg-supply .supply-facts > div:nth-child(even){padding-left:0;border-left:0}
}

/* ---------- /analytical-reality ------------------------------------------ */
.pg-analytical .ar-hero{padding-bottom:48px}
.pg-analytical .ar-hero h1{max-width:22ch}
.pg-analytical .ar-hero .lede + .lede{margin-top:14px}
.pg-analytical .ar-split{gap:40px;align-items:start}
.pg-analytical .ar-split h3{
  margin:0 0 12px;font-family:var(--display);font-weight:600;
  font-size:var(--step-0);letter-spacing:.04em;text-transform:uppercase;
}
.pg-analytical .ar-omit{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0;border-top:1px solid var(--hair);
}
.pg-analytical .ar-omit li{
  padding:18px 22px 18px 0;border-bottom:1px solid var(--hair);
  color:var(--ink-2);font-size:calc(var(--step-0) * var(--type-scale));line-height:1.45;
}
.pg-analytical .ar-omit li:nth-child(odd){padding-right:28px}
.pg-analytical .ar-omit li:nth-child(even){padding-left:28px;border-left:1px solid var(--hair)}
.pg-analytical .ar-omit strong{color:var(--ink);font-weight:600}
.pg-analytical .ar-evidence{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:28px 40px;
}
.pg-analytical .ar-evidence article{margin:0}
.pg-analytical .ar-evidence h3{
  margin:0 0 8px;font-family:var(--display);font-weight:600;
  font-size:var(--step-0);letter-spacing:.02em;color:var(--ink);
}
.pg-analytical .ar-evidence p{
  margin:0;max-width:48ch;color:var(--ink-2);
  font-size:calc(var(--step-0) * var(--type-scale));line-height:1.5;
}
.pg-analytical .ar-close{padding-block:clamp(48px,6vw,80px);text-align:left}
.pg-analytical .ar-close h2{max-width:22ch;margin:0 0 14px}
.pg-analytical .ar-close .lede{max-width:58ch}
/* ---------- /pricing ----------------------------------------------------- */
.pg-pricing .pricing-hero{padding-bottom:48px}
.pg-pricing .pricing-hero h1{max-width:20ch}
.pg-pricing .pricing-facts{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0;margin:0;border-top:1px solid var(--hair);
}
.pg-pricing .pricing-facts > div{
  padding:22px 28px 22px 0;border-bottom:1px solid var(--hair);
}
.pg-pricing .pricing-facts > div:nth-child(even){
  padding-left:28px;padding-right:0;border-left:1px solid var(--hair);
}
.pg-pricing .pricing-facts dt{
  font-family:var(--display);font-weight:600;font-size:var(--step--1);
  letter-spacing:.14em;text-transform:uppercase;color:var(--charcoal-50);margin:0 0 8px;
}
.pg-pricing .pricing-facts dd{
  margin:0;max-width:42ch;color:var(--ink-2);
  font-size:calc(var(--step-0) * var(--type-scale));line-height:1.5;
}
@media (max-width:760px){
  .pg-pricing .pricing-facts{grid-template-columns:1fr}
  .pg-pricing .pricing-facts > div,
  .pg-pricing .pricing-facts > div:nth-child(even){
    padding-left:0;padding-right:0;border-left:0;
  }
}

@media (max-width:760px){
  .pg-analytical .ar-omit,
  .pg-analytical .ar-evidence{grid-template-columns:1fr}
  .pg-analytical .ar-omit li:nth-child(odd),
  .pg-analytical .ar-omit li:nth-child(even){
    padding-left:0;padding-right:0;border-left:0;
  }
}

/* ==========================================================================
   Product sheet — dialog + dedicated page
   Native <dialog>, so Escape, focus trap and backdrop are free. The homepage
   spreadsheet and catalog names open this from a <template> already in the
   page; without JS the same href goes to /p/:sku.
   ========================================================================== */
.prod-sheet-link{color:inherit;text-decoration:none}
.prod-sheet-link:hover{text-decoration:underline;text-underline-offset:3px}

.psheet-page{padding-block:clamp(32px,5vw,64px) 80px}
.psheet-page-wrap{max-width:46rem}
.psheet-back{margin:0 0 18px;font-family:var(--display);font-size:.88rem}
.psheet-back a{color:var(--charcoal-70);text-decoration:none}
.psheet-back a:hover{color:var(--charcoal)}

/* Masthead — lab document, not a marketing card. */
.psheet-mast{
  display:flex;justify-content:space-between;align-items:flex-start;gap:16px;
  margin:0 0 22px;padding-bottom:14px;border-bottom:1px solid var(--charcoal);
}
.psheet-doc{
  margin:0;font-family:var(--display);font-weight:600;font-size:.72rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--charcoal);
}
.psheet-brand{margin:4px 0 0;font-size:.82rem;color:var(--charcoal-70)}
.psheet-ruo-flag{
  margin:0;font-family:var(--display);font-size:.64rem;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--rust);
  white-space:nowrap;
}

.psheet-titleblock{margin:0 0 28px}
.psheet-kicker{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 14px;
  margin:0 0 10px;font-family:var(--display);
}
.psheet-sku{
  font-size:var(--step--1);letter-spacing:.12em;text-transform:uppercase;
  color:var(--rust);
}
.psheet-cat,.psheet-grade{
  font-size:var(--step--1);letter-spacing:.08em;text-transform:uppercase;
  color:var(--charcoal-50);
}
.psheet-name{
  font-family:var(--display);font-weight:500;letter-spacing:-.04em;
  font-size:clamp(1.9rem,4.2vw,2.75rem);line-height:1.06;margin:0 0 8px;
  text-wrap:pretty;color:var(--charcoal);
}
.psheet-name-sub{font-weight:500;color:var(--charcoal-50);font-size:.58em;letter-spacing:0}
.psheet-strength{
  margin:0;font-size:var(--step-0);color:var(--charcoal-70);
}

/* Numbered sections — InvivoChem-style sections, KP type. */
.psheet-sec{margin:0 0 26px}
.psheet-sec-last{margin-bottom:18px}
.psheet-sec-h{
  display:flex;align-items:baseline;gap:12px;
  margin:0 0 10px;padding-bottom:8px;border-bottom:1px solid var(--hair);
  font-family:var(--display);font-weight:600;font-size:.78rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--charcoal);
}
.psheet-n{
  color:var(--rust);font-weight:600;letter-spacing:.06em;min-width:1.6em;
}
.psheet-sec-lede{
  margin:0 0 12px;font-size:.88rem;line-height:1.5;color:var(--charcoal-70);max-width:52ch;
}
.psheet-sec-lede a{color:var(--charcoal);text-underline-offset:2px}

/* Property table — Property | Value, full width, hairlines. */
.psheet-table{
  width:100%;border-collapse:collapse;
  font-size:.92rem;color:var(--charcoal);
}
.psheet-table th,.psheet-table td{
  padding:9px 0;border-bottom:1px solid var(--hair);
  vertical-align:top;text-align:left;
}
.psheet-table tr:last-child th,.psheet-table tr:last-child td{border-bottom:0}
.psheet-table th{
  width:38%;max-width:12rem;padding-right:18px;
  font-family:var(--display);font-size:.68rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--charcoal-50);
}
.psheet-table td{line-height:1.45}
.psheet-table a{color:var(--charcoal);text-underline-offset:2px}
.psheet-recon-body{
  margin:12px 0 0;font-size:.9rem;line-height:1.55;color:var(--charcoal);max-width:54ch;
}
.psheet-ruo{
  margin:0;font-size:.82rem;line-height:1.55;color:var(--charcoal-70);max-width:58ch;
}

.psheet-actions{
  display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;
  margin-top:8px;padding-top:18px;border-top:1px solid var(--charcoal);
}
.psheet-add{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap}
.psheet-qty{
  display:flex;flex-direction:column;gap:4px;
  font-family:var(--display);font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--charcoal-50);
}

.sheet-dialog{
  width:min(calc(100% - 28px), 44rem);
  max-height:min(94dvh, 56rem);
  padding:0;
  border:1px solid var(--hair-strong, var(--hair));
  border-radius:12px;
  background:var(--cream);
  color:var(--charcoal);
  box-shadow:0 28px 80px rgba(20,20,19,.32);
  opacity:0;
  transform:translate3d(0,14px,0);
  transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),
             overlay var(--dur) allow-discrete,display var(--dur) allow-discrete;
}
.sheet-dialog[open]{opacity:1;transform:none}
@starting-style{
  .sheet-dialog[open]{opacity:0;transform:translate3d(0,14px,0)}
}
.sheet-dialog::backdrop{
  background:rgba(20,20,19,.55);
  backdrop-filter:saturate(1.05) blur(8px);
  -webkit-backdrop-filter:saturate(1.05) blur(8px);
  opacity:0;
  transition:opacity var(--dur) var(--ease),overlay var(--dur) allow-discrete,display var(--dur) allow-discrete;
}
.sheet-dialog[open]::backdrop{opacity:1}
@starting-style{
  .sheet-dialog[open]::backdrop{opacity:0}
}
.sheet-chrome{
  display:flex;justify-content:flex-end;
  padding:10px 12px 0;
}
.sheet-close{
  appearance:none;border:1px solid var(--hair);background:transparent;
  width:36px;height:36px;border-radius:8px;cursor:pointer;
  font-size:1.35rem;line-height:1;color:var(--charcoal);
}
.sheet-close:hover{background:var(--cream-2, rgba(20,20,19,.06))}
.sheet-body{padding:4px 32px 32px;overflow:auto}

@media (max-width:640px){
  .sheet-dialog{
    width:100%;max-height:96dvh;margin:auto 0 0;
    border-radius:16px 16px 0 0;border-bottom:0;
    transform:translate3d(0,18px,0);
  }
  .sheet-dialog[open]{transform:none}
  @starting-style{
    .sheet-dialog[open]{opacity:0;transform:translate3d(0,18px,0)}
  }
  .sheet-body{padding:4px 18px 24px}
  .psheet-mast{flex-direction:column;gap:8px}
  .psheet-table th{width:42%;font-size:.62rem}
  .psheet-table th,.psheet-table td{padding:8px 0}
}

@media (prefers-reduced-motion:reduce){
  .sheet-dialog, .sheet-dialog::backdrop{transition:none}
}

/* Checkout — blocked wire/card rail fault dialog */
.rail-error-dialog .sheet-body{padding-top:0}
.rail-error-ref{
  margin:0 0 12px;font-size:.78rem;color:var(--accent-text, #b45309);
  word-break:break-word;
}
.rail-error-pre{
  margin:0;padding:14px 16px;
  font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size:.72rem;line-height:1.55;white-space:pre-wrap;
  background:var(--cream-2, rgba(20,20,19,.04));
  border:1px solid var(--hair);border-radius:8px;
  color:var(--charcoal);
  max-height:min(42vh, 18rem);overflow:auto;
}
.rail-error-actions{
  display:flex;flex-wrap:wrap;gap:10px;margin-top:22px;
}


