/* ══════════════════════════════════════════════════════════════════════════
   FireBar Distro v4 — one stylesheet, every page.

   v3 split site.css (hand-authored homepage) from line.css (generated) so the
   two would not become co-owners of one file. v4 generates every page from one
   template set, so that split has nothing left to protect and one file is
   simply easier to keep coherent.

   The token layer is v3's and is deliberately preserved — the sand/paper/ink
   palette, the --blue action colour, capsule geometry, one spring, the --sh-*
   shadows. That system was never the problem. What changed is density: rooms
   made of photography instead of flat colour, and a grid that has to carry
   147 tiles without turning into wallpaper.
   ══════════════════════════════════════════════════════════════════════════ */

:root{
  --paper:#ffffff;
  --sand:#f3ece1;
  --sand-2:#eadfcc;
  --sand-3:#fbf7f0;
  --ink:#14151a;
  --ink-2:#45484f;      /* 8.6:1 on white */
  --ink-3:#5c6068;      /* 6.3:1 on white */
  --hair:#e7e3da;
  --hair-2:#d6d0c3;

  --blue:#2332d5;       /* the action colour. never decoration */
  --blue-deep:#1a2599;
  --teal:#108474;
  --gold:#e9b949;       /* dark ground only */
  --gold-2:#c49a2a;
  --red:#a41f2b;

  --r-xl:34px; --r-lg:22px; --r-md:14px; --r-sm:10px; --r-pill:999px;
  --shell:1260px;
  --gut:clamp(20px,5vw,56px);
  --room:clamp(72px,9vw,132px);

  --sh-1:0 1px 2px rgba(20,21,26,.05), 0 4px 14px rgba(20,21,26,.055);
  --sh-2:0 2px 4px rgba(20,21,26,.05), 0 14px 32px rgba(20,21,26,.09);
  --sh-3:0 4px 10px rgba(20,21,26,.06), 0 28px 64px rgba(20,21,26,.15);
  --sh-lift:0 2px 4px rgba(20,21,26,.10), 0 14px 30px rgba(20,21,26,.20);
  /* The hover shadow for a card that is a LINK. Warmer and tighter than
     --sh-2 so a lifted tile reads as picked up rather than floated away, and
     tinted toward the action colour so the lift and the CTA agree. */
  --sh-pick:0 2px 6px rgba(20,21,26,.07), 0 18px 40px rgba(28,36,120,.16);

  /* ── F · THE ACTION GAP ────────────────────────────────────────────────
     🚨 ONE SCALE FOR "TEXT, THEN THE BUTTON THAT ACTS ON IT".

     Owner, improvement pass 5: "the button is too close to the text (check
     this across the board)". It was true and it was worse than it looked —
     the gap between a paragraph and its CTA was hand-set in EIGHT different
     places at SEVEN different values, and in two more it was not set at all:

       .hero-cta 30 · .cta-row 30 · .mid-cta 38 · .exec-copy .btn 26 ·
       .fw-more 22 · .plan-b .btn 20 · .fg-cta 14 · .pop-note 16 ·
       .shelf-grid .btn — NONE · .counter .btn — NONE

     The two with none were the visible complaint: a solid button sitting one
     line-height under a paragraph, touching it. The fix is a token plus a
     STRUCTURAL rule below, so the next button added anywhere inherits the
     rhythm instead of needing its own number. Never nudge one of these
     individually again — change the token. */
  --cta-space:clamp(26px,3vw,38px);        /* body copy -> its action row */
  --cta-space-tight:clamp(18px,2.2vw,24px); /* the same, inside a card */

  --spring:cubic-bezier(.16,1,.3,1);
  --ease:cubic-bezier(.32,.72,0,1);
  --dur:620ms;
  --tap:300ms;

  /* §4.2 — ONE source for header height. v3 hard-coded 76/66 and 88/76 as four
     independent magic numbers that had to be hand-synced, and they drifted. */
  --hdr-h:76px;
}
@media (max-width:760px){ :root{ --hdr-h:64px; } }

*,*::before,*::after{box-sizing:border-box}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--hdr-h) + 12px);
}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI Variable Text","Segoe UI",Inter,Roboto,"Helvetica Neue",Arial,sans-serif;
  font-size:1.0625rem;line-height:1.62;letter-spacing:-.011em;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
/* ⚠️ NEVER overflow-x:hidden on html or body — it silently defeats the
   position:fixed scroll lock the drawer relies on. Contain overflow on the
   specific wide children instead. */
/* Optical tracking: the larger the setting, the tighter it wants to be. One
   value across a 2.3rem→4.4rem clamp is a compromise at both ends, so the
   display sizes take their own. Floor stays above -.04em per the craft rule. */
h1,h2,h3,h4{margin:0;font-weight:800;line-height:1.04;letter-spacing:-.034em;text-wrap:balance}
h1{font-size:clamp(2.45rem,5.6vw,4.4rem);line-height:1.01;letter-spacing:-.04em}
h2{font-size:clamp(1.85rem,3.5vw,2.95rem);line-height:1.03;letter-spacing:-.038em}
h3{font-size:1.2rem;font-weight:700;letter-spacing:-.026em;line-height:1.2}
/* `pretty` only governs the last few lines, so it fixes orphans without the
   full-paragraph rebalancing `balance` does — which is wrong for body copy. */
p{margin:0;text-wrap:pretty}
a{color:inherit}
/* 🚨 `height:auto` IS LOAD-BEARING. DO NOT DROP IT FROM THIS RULE.
   Every image element on this site ships width= and height= attributes, which is
   correct — they reserve the box and stop the page shifting as photos land.
   But those attributes are also PRESENTATIONAL HINTS, and a hint sets a real
   used value. So with only `max-width:100%` here, an image whose component
   rule says `width:100%;aspect-ratio:1` had its width shrink to the column
   and its height stay pinned at the attribute — and because aspect-ratio only
   resolves an axis that is `auto`, BOTH axes were then specified and the
   aspect-ratio was ignored outright.
   The result was 38 images across the site rendering at a FIXED pixel height
   that never responded to the viewport, with object-fit:cover then cropping
   hard into the wrong box: the counter photograph at 350×833 where it should
   have been 350×197, the Essential colour wall at 111×260 where it should
   have been 111×111 — square photographs of a duffle sliced into vertical
   slivers. That is the whole of the "pictures are not mobile responsive" and
   "clipping issues" report, and it is one declaration.
   A presentational hint loses to any author rule, so this single `height:auto`
   hands every axis back to the component. Components that genuinely want a
   fixed height (.tile-media img, .hero-media img, .shelf-shots img) state
   `height:100%` themselves and still win on specificity. */
img{display:block;max-width:100%;height:auto}
svg{display:block;max-width:100%}
picture{display:block}
[hidden]{display:none!important}
::selection{background:var(--blue);color:#fff}
:focus-visible{outline:2.5px solid var(--blue);outline-offset:3px;border-radius:8px}
.dark :focus-visible,.band-dark :focus-visible,.hero :focus-visible,.phero :focus-visible{outline-color:#fff}

.shell{width:100%;max-width:var(--shell);margin-inline:auto;padding-inline:var(--gut)}
.narrow{max-width:760px}
.narrow-col{max-width:820px;margin-inline:auto}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.skip{position:absolute;left:12px;top:-60px;z-index:200;background:var(--blue);color:#fff;
      padding:12px 20px;border-radius:var(--r-pill);font-weight:600;text-decoration:none;
      transition:top var(--tap) var(--ease)}
.skip:focus{top:12px}

/* ONE icon contract for the whole site: no fills, currentColor stroke, a
   single 1.75 weight, round caps and joins. Every glyph in the sprite is
   drawn on the same 24px grid to suit exactly this, which is what makes a
   trust tile, a flow node and a pack chip look like one family. */
.ic{width:22px;height:22px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;
    stroke-linecap:round;stroke-linejoin:round}
.ic-s{width:17px;height:17px}
.ic-xs{width:14px;height:14px;stroke-width:1.9}   /* inline with small text */

/* ══════════════════════════════════════════════════════════ MONEY ══
   §The spine. This site's whole proposition is that a buyer can read a
   number, so numbers are typeset deliberately rather than inheriting body
   text. Two rules:

   1. TABULAR FIGURES EVERYWHERE A FIGURE IS COMPARED. Proportional digits
      make $1,000 and $2,500 different lengths, so a stack of prices in a
      grid never aligns and the eye cannot scan down a column. `tnum` fixes
      the advance width; `lnum` stops any face substituting old-style digits
      that would drop the 4 and the 7 below the baseline mid-price.
   2. THE FIGURE AND ITS UNIT ARE NOT THE SAME TYPE. A price is the number;
      "MSRP" is a label about the number. They get different sizes, weights
      and colours everywhere they appear together, so neither has to be read
      to find the other. */
.stat-n,.price-n,.price-r,.tile-msrp,.mini-stats b,.vl-at,.fam-n,.chip b,
.showing b,.rail-c,.cat-h span,.gate-row b{
  font-variant-numeric:tabular-nums lining-nums;
  font-feature-settings:"tnum" 1,"lnum" 1;
}

/* ══════════════════════════════════════════════════════════ MOTION ══
   🚨 THE REVEAL NEVER TOUCHES OPACITY. Read this before "improving" it.

   v3's reveal held content at opacity:0 until a scroll event fired, so a
   full-page screenshot of /line/ came back almost entirely blank — 25 cards
   invisible because nothing had scrolled. v3 patched around it three times
   (load, resize, setTimeout(1200)) and it still failed.

   The first v4 attempt reproduced the identical bug for the identical reason:
   an `opacity:0` resting state armed by JS. A full-page capture showed the
   hero and then seven blank bands. Any fix built on "light it up after N ms"
   or "light what is in view at arm time" is timing-dependent and fails a
   screenshot, a print, a bot, and a slow connection.

   So the reveal is TRANSFORM-ONLY. An element that has not been observed yet
   sits 18px low; that is the entire hidden state. Content is legible at every
   instant, in every render mode, with JS on or off — and the motion still
   reads, because motion is what the eye notices, not the fade. This is the one
   rule that makes the whole thing safe: if it cannot make content invisible,
   it cannot strand content invisible. */
.js-reveal [data-reveal]{transform:translate3d(0,18px,0)}
.js-reveal [data-reveal].lit{
  transform:none;
  transition:transform var(--dur) var(--spring) var(--d,0ms);
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .js-reveal [data-reveal]{transform:none!important}
  *{animation-duration:.001ms!important;transition-duration:.001ms!important}
}

/* ══════════════════════════════════════════════════════════ BUTTONS ══ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:13px 24px;border-radius:var(--r-pill);border:1.5px solid transparent;
  font-weight:650;font-size:.9688rem;letter-spacing:-.012em;text-decoration:none;
  cursor:pointer;white-space:nowrap;
  transition:background var(--tap) var(--ease),color var(--tap) var(--ease),
             border-color var(--tap) var(--ease),transform var(--tap) var(--spring),
             box-shadow var(--tap) var(--ease);
}
.btn:hover{transform:translateY(-1.5px)}
.btn:active{transform:translateY(0)}

/* 🚨 THE STRUCTURAL ACTION GAP — see --cta-space above.
   Any action row that DIRECTLY FOLLOWS a block of text gets the same gap,
   whatever section it is in and whether or not anyone remembered to style it.
   Stated as a sibling rule rather than per-component so it cannot be missed
   on the next section someone adds; the per-component values below are now
   only for the cases that genuinely differ (a tight card, a centred end-cap). */
:is(p,ul,ol,dl,h1,h2,h3,h4,figure,table,.band-p,.ticks,.flow,.bfam,.fg-feats,
   .abt-cats,.abt-why,.pop-list,.ctr-picks,.grid,.colour-wall,.flavor-wall)
  + :is(.btn,.cta-row,.hero-cta,.mid-cta,.fg-cta,.btn-row){margin-top:var(--cta-space)}
/* A card is a smaller room; it gets the tighter step. */
:is(.plan-b,.pil,.ctr-p-b,.fg-offer-a,.mk-prod) :is(p,ul,h3)
  + :is(.btn,.cta-row,.fg-cta){margin-top:var(--cta-space-tight)}
.btn-lg{padding:16px 30px;font-size:1.03rem}
.btn-sm{padding:8px 15px;font-size:.8125rem}
.btn-wide{width:100%}
.btn-solid{background:var(--blue);color:#fff;box-shadow:var(--sh-1)}
.btn-solid:hover{background:var(--blue-deep);box-shadow:var(--sh-2)}
.btn-gold{background:var(--gold);color:#1a1508}
.btn-gold:hover{background:#f2c65e}
.btn-ghost{background:rgba(255,255,255,.14);color:#fff;border-color:rgba(255,255,255,.34)}
.btn-ghost:hover{background:rgba(255,255,255,.24)}
.btn-ghost-ink{background:transparent;color:var(--ink);border-color:var(--hair-2)}
.btn-ghost-ink:hover{background:var(--sand);border-color:var(--ink-3)}
/* ⚠️ No backdrop-filter here. v3 nested blur(12px) on .btn-glass inside a
   blur(18px) header — a known compositing-artifact source. */
.btn-glass{background:rgba(255,255,255,.16);color:#fff;border-color:rgba(255,255,255,.4)}
.btn-glass:hover{background:rgba(255,255,255,.28)}

/* ═══════════════════════════════════════════════ SECTION MARKER ══
   These labels are authored copy and stay. What changes is that they stop
   floating as a disembodied eyebrow above the heading and become a structural
   marker for the section: a short accent rule, then the label, sitting on the
   same optical line. It reads as "you are entering this part of the page"
   rather than as a caption nobody asked for, and it gives the eye a repeating
   anchor to scan the long homepage by — which is the job the SVG glyph
   language does everywhere else. */
.kicker{display:flex;align-items:center;gap:10px;
        font-size:.75rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
        color:var(--ink-3);margin-bottom:16px}
.kicker::before{content:"";width:22px;height:2px;border-radius:2px;flex:none;
                background:var(--blue);opacity:.9}
.kicker.light{color:rgba(255,255,255,.86)}
.kicker.light::before{background:#fff;opacity:.55}
.kicker.gold{color:var(--gold)}
.kicker.gold::before{background:var(--gold)}
/* Centred blocks centre their marker with them. */
.endcta .kicker{justify-content:center}

/* ══════════════════════════════════════════════════════════ HEADER ══
   §4.2. One partial, identical on every page. The failure modes it fixes:
     · differing nav item counts between page types (items vanished, row re-flowed)
     · a scroll-position class toggle with no hysteresis (flicker)
     · transparent white-on-white on any light-topped page
     · display:none nav at ≤760px with no replacement (no mobile nav at all) */
.hdr{
  position:fixed;inset:0 0 auto;z-index:70;
  transition:background var(--tap) var(--ease),
             box-shadow var(--tap) var(--ease),
             color var(--tap) var(--ease);   /* colour eases WITH background */
  color:#fff;
}
/* Permanent top-down scrim so white text is legible over ANY hero, light or
   dark. This removes the white-on-white class of bug for good rather than
   relying on every page happening to open on a dark band. */
.hdr::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,.55),rgba(0,0,0,.16) 62%,transparent);
  transition:opacity var(--tap) var(--ease);
}
/* Fully opaque, not .94/.96. The spec asked for an "opaque rgba(255,255,255,.94)"
   to avoid needing a backdrop-filter — but 4-6% translucency over a scrolling
   grid is enough to read product names through the bar, which looks like a
   rendering fault. Solid white costs nothing and there is no blur to replace. */
.hdr.stuck{background:#fff;color:var(--ink);box-shadow:var(--sh-1)}
.hdr.stuck::before{opacity:0}
.hdr-in{
  display:flex;align-items:center;gap:clamp(12px,2.4vw,34px);height:var(--hdr-h);
  max-width:var(--shell);margin-inline:auto;padding-inline:var(--gut);position:relative;
}
.brand{display:flex;align-items:center;gap:11px;text-decoration:none;
       font-weight:800;letter-spacing:-.03em;font-size:1.0625rem;white-space:nowrap;color:inherit}
/* 🚨 THE REAL MARK, NOT A DRAWN GLYPH ON A PLATE.
   This was a 36px blue rounded square containing an invented `i-flame` icon.
   It is now the actual FireBar Labs mark — the flame over a cloud with a bolt
   through it — with no plate behind it, because the artwork is the brand and a
   coloured tile around it is a second, competing shape.

   ⚠️ ONE FILE SERVES BOTH GROUNDS. The artwork is a pure black silhouette on
   transparency, so invert(1) maps every ink pixel to white and leaves alpha
   untouched, antialiased edges included. The header is white-on-photograph
   until it sticks and ink-on-white after, so the filter follows exactly that
   switch and eases on the same curve as the rest of the bar. Shipping a second
   white PNG would be a second file to keep in sync, and it would be the one
   that rots. */
.brand .mark{width:auto;height:34px;flex:none;display:grid;place-items:center}
.brand .mark img{display:block;height:34px;width:auto}
.hdr:not(.stuck) .brand .mark img{filter:invert(1)}
.brand .mark img{transition:filter var(--tap) var(--ease)}

/* The full horizontal lockup, wherever there is room to read a two-line
   wordmark: the drawer, the footer, the print mastheads, /about/ and the
   media kit. NEVER in the header — see the note at MARK() in build-site.mjs. */
.lockup{display:block;height:auto;max-width:100%}
.drawer-brand{display:inline-flex;align-items:center;text-decoration:none;
              border-radius:var(--r-sm)}
.ftr-logo{display:inline-block;text-decoration:none}
.ftr-loc{display:inline-flex;align-items:center;gap:8px;margin-top:10px;
         font-size:.9063rem;font-weight:600;color:var(--ink-2)}
.ftr-loc .ic{color:var(--ink-3);flex:none}
.brand-tx{display:flex;flex-direction:column;line-height:1.05}
.brand em{font-style:normal;font-weight:500;font-size:.7rem;letter-spacing:.1em;
          text-transform:uppercase;opacity:.62}

.nav{margin-left:auto}
.nav ul{display:flex;gap:clamp(14px,2vw,28px);list-style:none;margin:0;padding:0;
        font-size:.9375rem;font-weight:550}
.nav-i{position:relative}
.nav-i>a{text-decoration:none;color:inherit;opacity:.86;display:block;padding:10px 2px;
         transition:opacity var(--tap) var(--ease)}
.nav-i>a::after{content:"";position:absolute;left:2px;right:2px;bottom:4px;height:1.75px;
                background:currentColor;transform:scaleX(0);transform-origin:left;border-radius:2px;
                transition:transform var(--tap) var(--ease)}
.nav-i>a:hover,.nav-i>a[aria-current]{opacity:1}
.nav-i>a:hover::after,.nav-i>a[aria-current]::after{transform:scaleX(1)}

.hdr-act{display:flex;align-items:center;gap:9px;margin-left:6px}
.hdr .btn{padding:10px 18px;font-size:.9063rem}
.hdr.stuck .btn-ghost{background:transparent;color:var(--ink);border-color:var(--hair-2)}
.hdr.stuck .btn-ghost:hover{background:var(--sand)}
.burger{display:none;width:44px;height:44px;align-items:center;justify-content:center;
        background:rgba(255,255,255,.14);border:1.5px solid rgba(255,255,255,.34);
        border-radius:12px;color:inherit;cursor:pointer;
        transition:background var(--tap) var(--ease),border-color var(--tap) var(--ease)}
.hdr.stuck .burger{background:transparent;border-color:var(--hair-2)}

/* mega menu — desktop nav only, which is now ≥1041px (see DRAWER) */
.mega{
  position:absolute;top:calc(100% + 12px);left:50%;translate:-50% 0;
  min-width:min(760px,86vw);background:#fff;color:var(--ink);
  border:1px solid var(--hair);border-radius:var(--r-lg);box-shadow:var(--sh-3);
  padding:18px;opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity 180ms var(--ease),transform 180ms var(--ease),visibility 180ms;
  z-index:5;
}
.mega::before{content:"";position:absolute;top:-14px;left:0;right:0;height:14px}
.nav-i.has-mega:hover .mega,.nav-i.open .mega{opacity:1;visibility:visible;transform:none}
.mega-in{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.mega-f{display:block;padding:11px 13px;border-radius:var(--r-md);text-decoration:none;
        transition:background var(--tap) var(--ease)}
.mega-f:hover{background:var(--sand-3)}
.mega-t{display:block;font-weight:700;font-size:.9375rem}
.mega-d{display:block;font-size:.8125rem;color:var(--ink-3);line-height:1.42;margin-top:2px}
.mega-all{grid-column:1/-1;margin-top:6px;padding:11px 13px;border-top:1px solid var(--hair);
          font-weight:650;color:var(--blue);text-decoration:none;font-size:.9375rem}

/* ══════════════════════════════════════════════════════════ DRAWER ══
   §4.3 — a REAL mobile nav. v3 had `.nav{display:none}` at ≤760px with no
   hamburger and no replacement: zero ways to navigate the site on a phone. */
.drawer-scrim{position:fixed;inset:0;background:rgba(20,21,26,.5);z-index:88;opacity:0;
              transition:opacity 240ms var(--ease)}
.drawer{
  position:fixed;top:0;right:0;bottom:0;width:min(360px,88vw);z-index:90;
  background:#fff;box-shadow:var(--sh-3);display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform 260ms var(--ease);
  overflow-y:auto;overscroll-behavior:contain;
}
.drawer-open .drawer{transform:none}
.drawer-open .drawer-scrim{opacity:1}
.drawer-top{display:flex;align-items:center;justify-content:space-between;
            padding:18px 20px;border-bottom:1px solid var(--hair)}
.drawer-ttl{font-weight:800;letter-spacing:-.02em}
.drawer-x{width:44px;height:44px;display:grid;place-items:center;background:transparent;
          border:1px solid var(--hair);border-radius:12px;cursor:pointer;color:var(--ink)}
.drawer-nav{display:flex;flex-direction:column;padding:10px 12px;gap:2px}
.drawer-nav>a{display:block;padding:14px 12px;border-radius:var(--r-md);text-decoration:none;
              font-size:1.0625rem;font-weight:650;min-height:44px}
.drawer-nav>a:hover{background:var(--sand-3)}
.drawer-sub{display:flex;flex-direction:column;padding:0 0 8px 12px;margin-left:10px;
            border-left:1px solid var(--hair-2)}
.drawer-sub a{padding:11px 12px;text-decoration:none;font-size:.9688rem;color:var(--ink-2);
              border-radius:var(--r-sm);min-height:44px;display:flex;align-items:center}
.drawer-sub a:hover{background:var(--sand-3);color:var(--ink)}
.drawer-act{margin-top:auto;padding:18px 20px 26px;border-top:1px solid var(--hair);
            display:flex;flex-direction:column;gap:10px}
.drawer-tel{display:flex;align-items:center;justify-content:center;gap:8px;padding:12px;
            text-decoration:none;font-weight:650;color:var(--ink-2)}

/* 🚨 1040, NOT 980 — raised in improvement pass 5 when /about/ made the nav
   SEVEN items. Six fitted at 980; seven wrap or shrink past legibility. The
   drawer lists all seven at full size, so the only thing this costs is 60px of
   viewport width where the row was already cramped. Keep this value, the mega
   -menu comment above and the thumb-bar breakpoint below in step — they are
   three statements of one boundary. */
@media (max-width:1040px){
  .nav{display:none}
  .burger{display:flex}
  .hdr-apply{display:none}     /* lives in the persistent thumb bar instead */
}
@media (min-width:1041px){
  .drawer,.drawer-scrim{display:none!important}
}
@media (max-width:520px){
  .hdr-signin span{display:none}
  .hdr-signin{padding:10px 12px}
  .brand em{display:none}
}

/* ════════════════════════════════════════════════════════════ HERO ══ */
.hero{position:relative;min-height:min(88vh,760px);display:flex;align-items:flex-end;
      padding-top:var(--hdr-h);isolation:isolate;overflow:hidden}
.hero-media{position:absolute;inset:0;z-index:-2}
.hero-media img{width:100%;height:100%;object-fit:cover}
.hero-veil{position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(12,13,17,.52) 0%,rgba(12,13,17,.30) 38%,rgba(12,13,17,.86) 100%)}
.hero-in{padding-block:clamp(48px,8vw,96px);color:#fff;max-width:840px}
.hero h1{color:#fff;max-width:14ch}
.hero-sub{margin-top:20px;font-size:clamp(1.03rem,1.6vw,1.2rem);line-height:1.55;
          color:rgba(255,255,255,.9);max-width:60ch}
.hero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:var(--cta-space)}
.hero-quiet{display:inline-flex;align-items:center;gap:7px;margin-top:16px;
            color:rgba(255,255,255,.86);text-decoration:none;font-weight:600;font-size:.9375rem;
            border-bottom:1.5px solid rgba(255,255,255,.32);padding:8px 0 4px}
.hero-quiet:hover{color:#fff;border-color:#fff}
/* The arrow leans into the direction it points on hover — the one moving
   part in the hero, and it moves only when the pointer is already there. */
.hero-quiet .ic{transition:transform var(--tap) var(--spring)}
.hero-quiet:hover .ic{transform:translateX(3px)}

/* interior page hero */
.phero{position:relative;min-height:clamp(320px,42vw,460px);display:flex;align-items:flex-end;
       padding-top:var(--hdr-h);isolation:isolate;overflow:hidden}
.phero-m{position:absolute;inset:0;z-index:-2}
.phero-m img{width:100%;height:100%;object-fit:cover}
.phero-veil{position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(12,13,17,.56),rgba(12,13,17,.82))}
.phero-in{padding-block:clamp(30px,4.5vw,56px);color:#fff;max-width:820px}
.phero h1{color:#fff;font-size:clamp(2rem,4.4vw,3.4rem)}
.phero-sub{margin-top:14px;color:rgba(255,255,255,.9);font-size:1.03rem;max-width:62ch}
.crumb{display:flex;flex-wrap:wrap;gap:8px;align-items:center;font-size:.8438rem;
       margin-bottom:16px;color:rgba(255,255,255,.78)}
.crumb a{text-decoration:none;opacity:.9;display:inline-flex;align-items:center;min-height:32px}
.crumb a:hover{text-decoration:underline}
.crumb b{font-weight:650}
.crumb.dark{color:var(--ink-3);padding-top:calc(var(--hdr-h) + 22px)}
.crumb.dark a{color:var(--ink-2)}

/* ═══════════════════════════════════════════════════ STAT / TRUST ══ */
.stats{background:var(--ink);color:#fff;padding-block:clamp(38px,4.8vw,62px)}
.stats-in{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(16px,3vw,40px)}
.stat{display:flex;flex-direction:column;gap:7px;position:relative}
/* A hairline BETWEEN the columns rather than a box around each. Four boxed
   tiles would be the same icon-heading-text card the rest of this page is
   built to avoid; a divider does the separating for one pixel and keeps the
   numerals the loudest thing in the band. */
.stat+.stat{padding-left:clamp(16px,3vw,40px)}
.stat+.stat::before{content:"";position:absolute;left:0;top:3px;bottom:3px;width:1px;
                    background:rgba(255,255,255,.14)}
.stat-ic{color:var(--gold);opacity:.92}
.stat-n{font-size:clamp(2.15rem,4.3vw,3.3rem);font-weight:800;letter-spacing:-.052em;line-height:1}
.stat-l{font-size:.875rem;color:rgba(255,255,255,.68);line-height:1.35;max-width:22ch}
@media (max-width:760px){
  .stats-in{grid-template-columns:repeat(2,1fr);gap:26px 18px}
  /* At two columns every odd child starts a row, so its divider would hang
     off the left edge of the band. */
  .stat:nth-child(odd){padding-left:0}
  .stat:nth-child(odd)::before{display:none}
}

/* §5.3 — four EQUAL tiles. No tile larger or louder than another, and the
   compliance one is not first and is not a link. */
.trust{background:var(--sand-3);border-bottom:1px solid var(--hair);padding-block:clamp(26px,3.2vw,38px)}
.trust-in{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(14px,2.4vw,28px)}
.tr{display:flex;gap:13px;align-items:flex-start;font-size:.9063rem;line-height:1.42;
    position:relative}
/* Same divider logic as the stats band above, so the two strips read as one
   idea seen twice — once on ink, once on sand. */
.tr+.tr{padding-left:clamp(14px,2.4vw,28px)}
.tr+.tr::before{content:"";position:absolute;left:0;top:2px;bottom:2px;width:1px;
                background:var(--hair-2)}
.tr .ic{color:var(--ink-2);margin-top:1px}
.tr b{display:block;font-weight:700;letter-spacing:-.015em}
.tr span,.tr a{color:var(--ink-3);font-size:.8438rem}
.tr a{font-weight:600;color:var(--blue);display:inline-flex;align-items:center;min-height:32px}
@media (max-width:900px){
  .trust-in{grid-template-columns:repeat(2,1fr);gap:20px}
  .tr:nth-child(odd){padding-left:0}
  .tr:nth-child(odd)::before{display:none}
}
@media (max-width:520px){
  .trust-in{grid-template-columns:1fr;gap:16px}
  .tr{padding-left:0!important}
  .tr::before{display:none!important}
}

/* ═══════════════════════════════════════════════════════════ BANDS ══ */
.band{padding-block:var(--room)}
.band-sand{background:var(--sand)}
.band-dark{background:var(--ink);color:#fff}
.band-dark h2,.band-dark h3{color:#fff}
.band-dark .band-p{color:rgba(255,255,255,.76)}
.band-head{max-width:820px}
.band-head.narrow{max-width:700px}
.band-p{margin-top:16px;color:var(--ink-2);font-size:1.03rem;line-height:1.62;max-width:64ch}
.mid-cta{margin-top:var(--cta-space);text-align:center}

/* The data pack is the full brand catalog; current wholesale availability is
   decided in the portal order form. Keep that distinction adjacent to every
   catalog CTA instead of implying that every showcased item is orderable. */
.catalog-availability{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;
  margin-top:18px;color:var(--ink-3);font-size:.875rem;line-height:1.5}
.catalog-availability p{margin:0}
.catalog-availability-link{display:inline-flex;align-items:center;min-block-size:40px;
  font-weight:750;color:var(--blue);text-decoration:underline;text-underline-offset:3px}
.catalog-availability-link:hover{color:var(--ink)}
.catalog-availability-dark{justify-content:center;margin-top:24px;padding-top:16px;
  border-top:1px solid rgba(255,255,255,.14);color:rgba(255,255,255,.68)}
.catalog-availability-dark .catalog-availability-link{color:var(--gold)}
.catalog-availability-dark .catalog-availability-link:hover{color:#fff}
.catalog-availability-hero{max-width:62ch;color:rgba(255,255,255,.78)}
.catalog-availability-hero .catalog-availability-link{color:#fff}
.catalog-availability-pdp{display:block;margin-top:14px}
.catalog-availability-footer{display:block;margin-top:12px}
.catalog-availability-sheet{display:block;margin-top:6px;font-size:.75rem;line-height:1.35}
.catalog-availability-sheet .catalog-availability-link{min-block-size:0}

/* 15G ────────────────────────────────────────────────────────────── */

/* ── THE FEATURE SET ───────────────────────────────────────────────────
   §5.4b — what replaced the ascent chart on the home page. The chart drew
   one variable beautifully; a buyer deciding whether to open the line needs
   eight, and seven of them are numbers. Each tile leads with the fact and
   explains underneath, so the band can be READ AT TWO SPEEDS — scan the bold
   leads for the spec, or read the second line for why it matters on a shelf.

   The rule that keeps this from becoming a wall: the icon is 1.75-weight like
   every other glyph on the site, the lead is the only bold thing in the tile,
   and nothing here gets a fill or a border of its own. Separation comes from
   a hairline and space, because eight bordered boxes on a dark ground read as
   a table of contents, not a product. */
.fg-feats{list-style:none;display:grid;grid-template-columns:repeat(4,1fr);
  gap:1px;margin:44px 0 0;padding:1px 0 0}
.fg-f{padding:24px 22px 26px;display:flex;
  flex-direction:column;align-items:flex-start;gap:9px}
.fg-ic{flex:none}
.fg-f b{font-size:1.09rem;font-weight:780;letter-spacing:-.028em;line-height:1.15;
  text-wrap:balance}
.fg-f span{font-size:.8125rem;line-height:1.5;max-width:30ch}

/* Dark ground — inside band-dark on the home page. */
.fg-f-dark{background:rgba(255,255,255,.13)}
.fg-f-dark .fg-f{background:var(--ink)}
.fg-f-dark .fg-ic{color:var(--gold);opacity:.95}
.fg-f-dark .fg-f b{color:#fff}
.fg-f-dark .fg-f span{color:rgba(255,255,255,.63)}

/* Light ground — the 15G product page. The hairline grid is the same idea in
   the opposite polarity: cells sit on paper, the seam is the border colour. */
.fg-f-light{background:var(--hair);border:1px solid var(--hair);
  border-radius:var(--r-lg);overflow:hidden;margin-top:8px}
.fg-f-light .fg-f{background:#fff}
.fg-f-light .fg-ic{color:var(--blue)}
.fg-f-light .fg-f b{color:var(--ink)}
.fg-f-light .fg-f span{color:var(--ink-3)}
.pdp-15g{grid-column:1/-1;margin-top:30px}
@media (max-width:1080px){.fg-feats{grid-template-columns:repeat(2,1fr)}}
@media (max-width:520px){
  .fg-feats{grid-template-columns:1fr;margin-top:34px}
  .fg-f{padding:19px 18px 20px;gap:7px}
  .fg-f b{font-size:1.03rem}
}

/* The quiet route to the product page. The wall's photos are already links,
   so this is for the buyer who wants detail rather than a flavor. */
.fw-more{display:inline-flex;align-items:center;gap:8px;margin-top:22px;
  font-size:.875rem;font-weight:650;color:var(--gold);text-decoration:none}
.fw-more:hover{text-decoration:underline;text-underline-offset:4px}

/* ── THE OPENER ────────────────────────────────────────────────────────
   🚨 The price is gated. This block carries the SHAPE of the offer and a
   lock; the number is behind the account and never renders here. */
.fg-offer{margin-top:52px;border-radius:var(--r-lg);padding:clamp(26px,4vw,44px);
  display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(24px,4vw,52px);
  align-items:center}
.fg-dark{background:linear-gradient(140deg,rgba(255,255,255,.085),rgba(255,255,255,.03));
  border:1px solid rgba(255,255,255,.16)}
.fg-light{background:var(--sand-3);border:1px solid var(--hair)}
.fg-offer h3{font-size:clamp(1.5rem,2.9vw,2.15rem);font-weight:800;
  letter-spacing:-.042em;line-height:1.08;margin:9px 0 0}
.fg-dark h3{color:#fff}
.fg-offer-p{margin-top:13px;font-size:.9375rem;line-height:1.6;max-width:46ch}
.fg-dark .fg-offer-p{color:rgba(255,255,255,.74)}
.fg-light .fg-offer-p{color:var(--ink-3)}
.fg-offer-b{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.fg-offer-b li{display:flex;align-items:flex-start;gap:10px;font-size:.9375rem;
  font-weight:600;line-height:1.35}
.fg-dark .fg-offer-b li{color:#fff}
.fg-offer-b .ic{flex:none;margin-top:2px;color:var(--gold)}
.fg-light .fg-offer-b .ic{color:var(--blue)}
.fg-gate{display:flex;align-items:center;gap:8px;margin-top:18px;
  font-size:.8125rem;font-weight:700;letter-spacing:.01em}
.fg-dark .fg-gate{color:rgba(255,255,255,.62)}
.fg-light .fg-gate{color:var(--ink-3)}
.fg-cta{display:flex;flex-wrap:wrap;gap:10px;margin-top:var(--cta-space-tight)}
@media (max-width:860px){
  .fg-offer{grid-template-columns:1fr;gap:26px;margin-top:38px}
}

.peak{margin-top:34px;max-width:560px}
/* The CTA under the ladder needs its own air — it was sitting on the labels. */
.peak+.btn{margin-top:32px}
.peak-t{display:block;font-weight:800;color:var(--gold);letter-spacing:-.02em;
        font-size:1.03rem;margin-bottom:16px}
/* Standalone in the band head (the ascent no longer follows it there). */
.band-head>.peak-t{margin:26px 0 0}

/* ── THE ASCENT ────────────────────────────────────────────────────────
   The five fixed states, drawn as the climb they describe. The five equal
   bars this replaced encoded intensity as OPACITY, which is the one channel
   that cannot show a progression — five bars of one height read as five of a
   thing, not as a ladder. Height reads as more, instantly and without a key.

   The graphic encodes exactly ONE variable, because intensity is the only
   thing the ladder is permitted to say. No step gets a description, a colour
   of its own, or an area label.

   `vector-effect:non-scaling-stroke` is what makes it survive being scaled:
   the SVG stretches from ~330px on a phone to 560px on a desktop, and without
   it every stroke would thicken and thin with the viewport while the icons
   beside it stayed at 1.75. */
.ascent{color:var(--gold);--asc-bg:var(--ink)}
.ascent-g{width:100%;height:auto;overflow:visible}
.ascent-line{fill:none;stroke:currentColor;stroke-width:2.6;
             stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.ascent-tick{stroke:currentColor;stroke-width:1;opacity:.24;fill:none;
             stroke-dasharray:3 5;vector-effect:non-scaling-stroke}
.ascent-n{fill:var(--asc-bg);stroke:currentColor;stroke-width:2.4;
          vector-effect:non-scaling-stroke}
.ascent-n.is-top{fill:currentColor}
.ascent-l{display:grid;grid-template-columns:repeat(5,1fr);margin-top:11px;
          font-size:.6875rem;font-weight:750;letter-spacing:.07em;text-transform:uppercase;
          color:rgba(255,255,255,.6);text-align:center}
/* The labels are centred in five equal columns and the nodes sit at 10/30/50/
   70/90% of the viewBox, so the two line up at every width with no query. */
.ascent-l span:last-child{color:var(--gold)}
@media (max-width:420px){
  .ascent-l{font-size:.625rem;letter-spacing:.04em}
}

/* The same component on a light ground, on the 15G product page. Gold at full
   brightness fails contrast on white, so the light variant steps down to the
   deeper gold and repaints the node centres. */
.pdp-ascent{grid-column:1/-1;margin-top:8px;padding:24px clamp(18px,3vw,30px);
            border:1px solid var(--hair);border-radius:var(--r-lg);background:var(--sand-3)}
.pdp-ascent .peak-t{color:var(--gold-2)}
/* Capped, or the climb flattens: across the full body width the same five
   nodes describe a shallow diagonal instead of an ascent, and height is the
   only thing this graphic is allowed to say. */
.pdp-ascent .ascent{color:var(--gold-2);--asc-bg:var(--sand-3);max-width:660px}
.pdp-ascent .ascent-l{color:var(--ink-3)}
.pdp-ascent .ascent-l span:last-child{color:var(--gold-2)}
.flavor-wall{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-top:52px}
.fw{text-decoration:none;color:#fff;display:block;border-radius:var(--r-md);overflow:hidden;
    background:rgba(255,255,255,.05);transition:transform var(--tap) var(--spring)}
/* ⚠️ HOVER IS NOT ONE GESTURE REPEATED. Three different objects get three
   different responses, chosen by what the object IS:
     · a CARD that is a link (.tile, .pil, .rail-i) is picked up — it lifts.
     · a PHOTOGRAPH in a wall (.fw, .cw) is looked at more closely — the photo
       moves inside its frame and the card underneath stays put.
     · a CONTROL (.btn, .sw-b) responds in place.
   Before this everything on the site was translateY(-4px), which makes a
   40-photo colour wall behave like a row of buttons and reads as a template
   rather than as a designed surface. */
.fw:hover img{transform:scale(1.07)}
.fw img{width:100%;aspect-ratio:1;object-fit:cover;
        transition:transform 620ms var(--spring)}
.fw span{display:block;padding:10px 12px 13px;font-size:.8125rem;font-weight:600;
         color:rgba(255,255,255,.86);line-height:1.3}
@media (max-width:900px){.flavor-wall{grid-template-columns:repeat(3,1fr)}}
@media (max-width:520px){.flavor-wall{grid-template-columns:repeat(2,1fr);gap:9px}}

/* Executive Tech ─────────────────────────────────────────────────── */
.exec-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(30px,5vw,72px);align-items:center}
.exec-detail{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.exec-detail picture{border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-2)}
.exec-detail img{width:100%;height:100%;object-fit:cover;aspect-ratio:4/5}
/* 🚨 BLOCK, NOT INLINE-FLEX. As an inline element the partner endorsement
   sat on the SAME BASELINE as the section's CTA, so a claim chip and an
   action button read as a two-button row and the endorsement looked
   clickable. width:fit-content keeps the pill hugging its text while
   making it block-level, which lets the button take the action gap below
   it. Part of the same CTA-rhythm pass as --cta-space. */
.partner{display:flex;width:fit-content;max-width:100%;align-items:center;gap:8px;margin-top:22px;padding:9px 16px;
         background:var(--sand);border-radius:var(--r-pill);font-weight:650;font-size:.9063rem}
.exec-copy .btn{margin-top:var(--cta-space)}
/* 🚨 NOT A SCROLLER ANY MORE. Nine colourways of one backpack is a SET, not
   a sequence — there is no reason the ninth should be harder to reach than
   the first, and on a 1280px desktop all nine fit with room to spare. It is a
   wrapping grid from 620px up and keeps native swipe below that, where a row
   of nine genuinely cannot fit. Same markup, no arrows needed, nothing to
   hijack the wheel. */
.sw-strip{display:grid;gap:10px;align-items:start;margin-top:clamp(36px,5vw,64px);
          grid-template-columns:auto repeat(9,minmax(0,1fr))}
@media (max-width:900px){.sw-strip{grid-template-columns:auto repeat(5,minmax(0,1fr))}}
@media (max-width:620px){
  .sw-strip{display:flex;overflow-x:auto;padding-bottom:10px;
            scroll-snap-type:x proximity;scrollbar-width:none;
            -webkit-overflow-scrolling:touch}
  .sw-strip::-webkit-scrollbar{display:none}
  .sw-strip>*{scroll-snap-align:start}
  /* No track to fill down here, so the item states its own size again. */
  .sw-i{flex:none;width:118px}
  .sw-lab{flex:none}
}
.sw-lab{flex:none;align-self:center;font-size:.75rem;font-weight:800;letter-spacing:.14em;
        text-transform:uppercase;color:var(--ink-3);writing-mode:horizontal-tb;padding-right:6px}
/* 🚨 FLUID IN GRID MODE. These carried flex:none and a hard 118px from the
   days when the strip was a horizontal scroller, and the fixed width survived
   the change to a grid — so each of the nine items ignored its 1fr track and
   the last one hung 16px past the right edge of the shell. A fixed width
   inside a fractional track is always going to win and always going to
   overflow. The 118px is now scoped to the mobile flex mode below, where it is
   the correct value because there is no track to fill. */
.sw-i{min-width:0;text-decoration:none;color:var(--ink-2)}
.sw-i img{width:100%;height:auto;aspect-ratio:1;object-fit:cover;
  border-radius:var(--r-md);background:var(--sand)}
.sw-i span{display:block;margin-top:7px;font-size:.75rem;line-height:1.3;font-weight:600}
.sw-i:hover{color:var(--ink)}
@media (max-width:900px){.exec-grid{grid-template-columns:1fr}}

/* compare ────────────────────────────────────────────────────────── */
.cmp-wrap{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,5vw,64px);align-items:center}
.cmp-copy{align-self:center}
.cmp{position:relative;border-radius:var(--r-xl);overflow:hidden;box-shadow:var(--sh-3);
     aspect-ratio:1;background:var(--sand-2)}
.cmp img{width:100%;height:100%;object-fit:cover;display:block}
.cmp-b,.cmp-a{position:absolute;inset:0}
.cmp-a{clip-path:inset(0 calc(100% - var(--wipe)) 0 0)}
.cmp-tag{position:absolute;bottom:14px;padding:7px 14px;border-radius:var(--r-pill);
         background:rgba(20,21,26,.76);color:#fff;font-size:.75rem;font-weight:650;letter-spacing:.02em}
.cmp-tag.left{left:14px}
.cmp-tag.right{right:14px}
.cmp input[type=range]{
  position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:ew-resize;z-index:3}
.cmp-handle{position:absolute;top:0;bottom:0;left:var(--wipe);width:3px;background:#fff;
            box-shadow:0 0 0 1px rgba(0,0,0,.18);z-index:2;pointer-events:none}
.cmp-handle::after{content:"";position:absolute;top:50%;left:50%;translate:-50% -50%;
  width:46px;height:46px;border-radius:50%;background:#fff;box-shadow:var(--sh-2)}
.cmp input[type=range]:focus-visible ~ .cmp-handle{outline:3px solid var(--blue);outline-offset:2px}
.cmp-note{grid-column:1/-1;margin-top:16px;font-size:.8438rem;color:var(--ink-3);text-align:center}
@media (max-width:900px){.cmp-wrap{grid-template-columns:1fr}}

/* The Essential colour wall — fourteen photographs of one shape, all
   different. The most direct answer on the page to "no variety of the
   photos", and it makes the range legible without a single word. */
.colour-wall{display:grid;grid-template-columns:repeat(7,1fr);gap:10px;
             margin-top:clamp(30px,4vw,52px)}
.cw{text-decoration:none;color:var(--ink-2);display:block}
.cw:hover{color:var(--ink)}
/* The photograph lifts off its label rather than the whole cell moving —
   fourteen colourways all sliding at once looked like the grid had come
   loose. */
.cw img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:var(--r-md);
        background:var(--sand-3);
        transition:transform var(--tap) var(--spring),box-shadow var(--tap) var(--ease)}
.cw:hover img,.cw:focus-visible img{transform:translateY(-5px) scale(1.02);box-shadow:var(--sh-2)}
.cw span{display:block;margin-top:7px;font-size:.6875rem;font-weight:650;line-height:1.28}
@media (max-width:900px){.colour-wall{grid-template-columns:repeat(5,1fr)}}
@media (max-width:560px){.colour-wall{grid-template-columns:repeat(3,1fr);gap:8px}}

/* pillars ────────────────────────────────────────────────────────── */
.pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(18px,2.6vw,30px);margin-top:46px}
.pil{background:#fff;border:1px solid var(--hair);border-radius:var(--r-xl);overflow:hidden;
     display:flex;flex-direction:column;box-shadow:var(--sh-1);
     transition:transform var(--tap) var(--spring),box-shadow var(--tap) var(--ease)}
.pil:hover,.pil:focus-within{transform:translateY(-4px);box-shadow:var(--sh-pick)}
.pil-m img{width:100%;aspect-ratio:4/3;object-fit:cover;
           transition:transform 700ms var(--spring)}
.pil:hover .pil-m img{transform:scale(1.035)}
.pil h3{margin:22px 24px 0}
.pil p{margin:10px 24px 0;color:var(--ink-2);font-size:.9688rem;line-height:1.55}
.pil-tag{margin:16px 24px 24px;font-size:.8125rem;font-weight:700;color:var(--blue);
         letter-spacing:-.01em}
@media (max-width:900px){.pillars{grid-template-columns:1fr}}

/* shelf ──────────────────────────────────────────────────────────── */
.shelf-grid{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(28px,5vw,68px);align-items:center}
.shelf-shots{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.shelf-shots picture:first-child{grid-column:1/-1}
.shelf-shots picture{border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-2)}
.shelf-shots img{width:100%;height:100%;object-fit:cover}
.shelf-shots picture:first-child img{aspect-ratio:4/3}
.shelf-shots picture:not(:first-child) img{aspect-ratio:1}
@media (max-width:900px){.shelf-grid{grid-template-columns:1fr}}

/* counter ────────────────────────────────────────────────────────── */
.counter-in{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(28px,5vw,68px);align-items:center}
.counter-m picture{border-radius:var(--r-xl);overflow:hidden;box-shadow:var(--sh-3)}
.counter-m img{width:100%;aspect-ratio:16/9;object-fit:cover}
@media (max-width:900px){.counter-in{grid-template-columns:1fr}}

/* 🚨 THE FAMILY RAIL IS GONE. It was a horizontal scroller of twelve 130px
   thumbnails on the homepage, and it is now the .bfam brand-family GRID at
   the bottom of this file — same photographs, same links, same counts, plus
   the grouping the section was arguing for, and nothing to scroll.
   Owner: "the horizontal scroll bars in all section is also awkward to scroll
   on desktop." This was the first of them and the easiest to delete, because
   the content was never sequential — twelve peers do not need an axis.
   The .rail-* rules below are retained ONLY as the swatch fallback's sizing
   host; if that changes, delete them. */
.rail{display:none}
.rail-i{flex:none;width:130px;text-decoration:none;scroll-snap-align:start;
        transition:transform var(--tap) var(--spring)}
.rail-i:hover{transform:translateY(-3px)}
.rail-m{display:block;border-radius:var(--r-lg);overflow:hidden;background:var(--sand)}
.rail-m img,.rail-m .swatch{width:130px;height:130px;object-fit:cover}
.rail-t{display:block;margin-top:9px;font-weight:700;font-size:.8438rem;line-height:1.25}
.rail-c{display:block;font-size:.75rem;color:var(--ink-3)}

/* ═══════════════════════════════════════════════════════════ TILES ══ */
.grid{display:grid;gap:clamp(12px,1.6vw,20px);margin-top:22px}
.grid[data-cols="3"]{grid-template-columns:repeat(auto-fill,minmax(290px,1fr))}
.grid[data-cols="4"]{grid-template-columns:repeat(auto-fill,minmax(228px,1fr))}
.grid[data-cols="6"]{grid-template-columns:repeat(auto-fill,minmax(164px,1fr))}
.grid-preview{grid-template-columns:repeat(auto-fill,minmax(228px,1fr));margin-top:34px}

/* §8 — 2-up on a phone, NEVER 1-up. A 228px minmax leaves room for exactly one
   column inside a 390px viewport, which turns the lineup into an endless
   single file and makes a 147-tile catalog feel smaller than a 25-tile one.
   The auto-fill tracks above are correct from 561px up; below that the column
   count is stated outright rather than negotiated. */
@media (max-width:560px){
  .grid,.grid[data-cols],.grid-preview{grid-template-columns:repeat(2,1fr)!important;gap:10px}
  .tile-name{font-size:.9375rem}
  .tile-fam,.tile-sub{font-size:.6875rem}
  .tile-msrp{font-size:.875rem}
}

.tile{background:#fff;border:1px solid var(--hair);border-radius:var(--r-lg);overflow:hidden;
      transition:transform var(--tap) var(--spring),box-shadow var(--tap) var(--ease),
                 border-color var(--tap) var(--ease)}
/* The lift is 3px and the shadow is tinted toward the action colour, so a
   picked-up tile and the button it leads to agree with each other. Keyboard
   focus gets the same treatment as hover — a tile that only responds to a
   mouse is a tile half the people using it never see respond. */
.tile:hover,.tile:focus-within{transform:translateY(-3px);box-shadow:var(--sh-pick);
                               border-color:#c3c7e6}
/* position:relative because .flags is a SIBLING of .tile-media now and hangs
   off this box instead — see tileHtml(). Screen output is identical; print
   gains the ability to drop the chips out of the photograph. */
.tile-a{position:relative;display:flex;flex-direction:column;height:100%;
        text-decoration:none;color:inherit}
.tile-media{position:relative;display:block;background:var(--sand-3);aspect-ratio:1;overflow:hidden}
.tile-media img{width:100%;height:100%;object-fit:cover;
                transition:transform 700ms var(--spring)}
.tile:hover .tile-media img{transform:scale(1.045)}
.tile-fam{padding:13px 15px 0;font-size:.6875rem;font-weight:800;letter-spacing:.11em;
          text-transform:uppercase;color:var(--ink-3)}
/* §6.2 — the VARIANT is the headline, the product name is secondary. v3 had
   this inverted: eight Essentials cards read as eight near-identical raw
   Shopify titles with the differentiating word buried mid-sentence. */
.tile-name{padding:5px 15px 0;font-size:1.0625rem;font-weight:750;letter-spacing:-.025em;
           line-height:1.2}
.tile-sub{padding:3px 15px 0;font-size:.8125rem;color:var(--ink-3);line-height:1.35}
/* THE MONEY ROW — the spine of the tile, and of the site.
   A hairline separates it from the name block so that a column of tiles gives
   the eye a single continuous line to drop down and read prices along. The
   figure and its unit are deliberately different objects: the price is large,
   heavy and tabular; "MSRP" is a small chip that never has to be read twice.
   Before this they were one 15.5px row in the same weight, so finding a price
   meant reading a sentence. */
.tile-msrp{margin:auto 15px 0;padding:12px 0 0;border-top:1px solid var(--hair);
           font-size:1.0625rem;font-weight:800;letter-spacing:-.03em;
           display:flex;align-items:baseline;gap:7px}
.tile-msrp em{font-style:normal;font-size:.625rem;font-weight:800;letter-spacing:.11em;
              text-transform:uppercase;color:var(--ink-3);position:relative;top:-1px;
              padding:2px 5px;border-radius:4px;background:var(--sand)}
.tile-pack{display:flex;align-items:center;gap:6px;
           padding:8px 15px 0;font-size:.75rem;font-weight:650;color:var(--teal)}
.tile-pack .ic{opacity:.85}
/* THE LOCKED COST ROW — the gated twin of .tile-msrp above.
   It deliberately mirrors that row's geometry: same 15px gutters, same
   baseline-aligned flex, so the two read as one money block with the bottom
   half gated. The visual token is intentionally NONNUMERIC, not a blurred
   estimate; the honest sentence is in the .sr span beside it. */
.cost{display:flex;align-items:center;gap:7px;margin:0 15px;padding:9px 0 14px;
      font-size:.75rem;font-weight:700;color:var(--ink-3);letter-spacing:-.01em}
.cost-l{white-space:nowrap}
.cens{position:relative;display:inline-flex;align-items:center;
      padding:2px 9px;border-radius:6px;overflow:hidden;
      background:linear-gradient(180deg,rgba(20,21,26,.085),rgba(20,21,26,.055));
      box-shadow:inset 0 0 0 1px rgba(20,21,26,.07);
      transition:background var(--tap) var(--ease),box-shadow var(--tap) var(--ease)}
/* The hatch is what separates "redacted on purpose" from "the page is
   broken" — blur alone reads as a rendering fault. */
.cens::after{content:"";position:absolute;inset:0;pointer-events:none;
   background:repeating-linear-gradient(-52deg,rgba(20,21,26,.055) 0 2px,transparent 2px 6px)}
.cens-n{font-size:1.04rem;font-weight:800;letter-spacing:.18em;color:var(--ink-2);
        -webkit-user-select:none;user-select:none;opacity:.78}
.cost-lock{color:var(--ink-3);flex:none;
           transition:color var(--tap) var(--ease),transform var(--tap) var(--spring)}
/* The chip is held at zero width so it costs the row no space until it is
   wanted, then slides out from behind the lock. */
.cost-chip{display:inline-flex;align-items:center;white-space:nowrap;
   max-width:0;opacity:0;transform:translateX(-5px);overflow:hidden;
   color:var(--blue);font-weight:750;
   transition:max-width 260ms var(--spring),opacity var(--tap) var(--ease),
              transform var(--tap) var(--spring)}
.tile:hover .cost-chip,.tile:focus-within .cost-chip{max-width:140px;opacity:1;transform:none}
.tile:hover .cens-n,.tile:focus-within .cens-n{opacity:1}
.tile:hover .cens,.tile:focus-within .cens{
   background:linear-gradient(180deg,rgba(58,74,214,.13),rgba(58,74,214,.07));
   box-shadow:inset 0 0 0 1px rgba(58,74,214,.2)}
.tile:hover .cost-lock,.tile:focus-within .cost-lock{color:var(--blue);transform:translateY(-1px)}
@media (prefers-reduced-motion:reduce){
  .cens-n,.cens,.cost-chip,.cost-lock{transition:none}
  .cost-chip{transform:none}
}
/* 🚨 NO [data-oos] RULE. A saturate(.35) filter used to grey the photograph
   of any out-of-stock variant. See THE SOLD-OUT RULE in data/content.mjs — the
   public site does not signal availability at all, and the IMAGE was carrying
   the signal as loudly as the chip was. The attribute is no longer emitted;
   this selector is left documented rather than silently deleted so nobody
   re-adds it as "just a small visual cue". */

.flags{position:absolute;top:10px;left:10px;z-index:1;display:flex;flex-direction:column;
       gap:5px;align-items:flex-start;pointer-events:none}
.flag{padding:4px 9px;border-radius:var(--r-pill);font-size:.6875rem;font-weight:750;letter-spacing:.02em}
.flag-out{background:rgba(20,21,26,.82);color:#fff}
.flag-ltd{background:var(--gold);color:#1a1508}

/* §6.3 — the honest fallback. A flat swatch of the colorway's ACTUAL hex with
   its name on it. Never another colorway's photograph. */
.swatch{position:relative;display:flex;flex-direction:column;justify-content:flex-end;
        gap:3px;padding:14px;width:100%;height:100%;aspect-ratio:1;background:var(--sw,#d6d0c3)}
.swatch-n{font-weight:750;font-size:.9375rem;color:#fff;letter-spacing:-.02em;line-height:1.2}
.swatch-m{font-size:.6875rem;font-weight:650;letter-spacing:.06em;text-transform:uppercase;
          color:rgba(255,255,255,.72)}
.swatch-n.on-light{color:var(--ink)}
.swatch-m.on-light{color:var(--ink-3)}

/* ══════════════════════════════════════════════════════════ LINEUP ══ */
/* Solid, for the same reason as the stuck header — it sits directly beneath it
   and two translucent bars stacked over a scrolling grid let product names
   read through both. */
.linebar{position:sticky;top:var(--hdr-h);z-index:40;background:#fff;
         border-bottom:1px solid var(--hair)}
.linebar-in{display:flex;align-items:center;gap:18px;padding-block:12px;flex-wrap:wrap}
.chips{display:flex;gap:8px;flex-wrap:wrap}
.chip{padding:8px 15px;border-radius:var(--r-pill);border:1.5px solid var(--hair-2);
      background:#fff;font-size:.875rem;font-weight:600;cursor:pointer;min-height:38px;
      transition:background var(--tap) var(--ease),border-color var(--tap) var(--ease),
                 color var(--tap) var(--ease)}
.chip b{font-weight:800;opacity:.55;margin-left:3px}
.chip:hover{border-color:var(--ink-3)}
.chip[aria-pressed=true]{background:var(--ink);border-color:var(--ink);color:#fff}
.chip[aria-pressed=true] b{opacity:.6}
.linebar-r{display:flex;align-items:center;gap:14px;margin-left:auto;flex-wrap:wrap}
.showing{font-size:.8125rem;color:var(--ink-3)}
.showing b{color:var(--ink);font-weight:800}
.dens{display:flex;border:1.5px solid var(--hair-2);border-radius:var(--r-pill);overflow:hidden}
.dens button{padding:7px 13px;background:#fff;border:0;font-size:.8125rem;font-weight:600;
             cursor:pointer;min-height:36px}
.dens button[aria-pressed=true]{background:var(--ink);color:#fff}
.jump-print{display:inline-flex;align-items:center;min-height:36px;
            font-size:.8125rem;font-weight:650;color:var(--blue);text-decoration:none}
@media (max-width:760px){
  .dens{display:none}
  .linebar-in{gap:10px}
  /* Mobile-only scroller. Native swipe is the right interaction here — but
     the cut edge needs to LOOK cut, or the last visible chip reads as the
     last chip. A mask fades it instead of a scrollbar. */
  .chips{overflow-x:auto;flex-wrap:nowrap;padding-bottom:2px;scrollbar-width:none;
         -webkit-overflow-scrolling:touch;
         -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 30px),transparent);
         mask-image:linear-gradient(90deg,#000 calc(100% - 30px),transparent)}
  .chips::-webkit-scrollbar{display:none}
}

.jump{background:var(--sand-3);border-bottom:1px solid var(--hair)}
/* 🚨 WRAPS, does not scroll. Twelve family shortcuts are a table of
   contents; hiding half of them behind a sideways drag on a 1260px page was
   the worst of the site's scrollers because the hidden items were NAVIGATION.
   Native swipe is kept below 760px, where twelve chips genuinely cannot sit
   on one line. */
.jump-in{display:flex;flex-wrap:wrap;gap:8px;padding-block:11px}
@media (max-width:760px){
  .jump-in{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
           -webkit-overflow-scrolling:touch;
           -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 34px),transparent);
           mask-image:linear-gradient(90deg,#000 calc(100% - 34px),transparent)}
  .jump-in::-webkit-scrollbar{display:none}
}
.jump-in a{flex:none;font-size:.8125rem;font-weight:600;color:var(--ink-3);text-decoration:none;
           padding:6px 12px;border-radius:var(--r-pill);white-space:nowrap}
.jump-in a:hover{background:#fff;color:var(--ink)}

.cat-block{padding-top:clamp(38px,5vw,64px);scroll-margin-top:calc(var(--hdr-h) + 64px)}
.cat-h{font-size:clamp(1.5rem,2.6vw,2.1rem);display:flex;align-items:baseline;gap:12px;
       padding-bottom:10px;border-bottom:2px solid var(--ink)}
.cat-h span{font-size:.9375rem;font-weight:700;color:var(--ink-3)}
.fam{padding-top:clamp(30px,4vw,52px);scroll-margin-top:calc(var(--hdr-h) + 64px)}
.fam-head{max-width:720px}
.fam-head h3{font-size:clamp(1.2rem,2vw,1.5rem);display:flex;align-items:baseline;gap:10px}
.fam-n{font-size:.8125rem;font-weight:700;color:#fff;background:var(--ink);
       padding:2px 9px;border-radius:var(--r-pill)}
.fam-head p{margin-top:8px;color:var(--ink-3);font-size:.9375rem;line-height:1.5}

/* ═════════════════════════════════════════════════════════════ PDP ══ */
.pdp-top{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,4.5vw,64px);
         padding-block:clamp(22px,3vw,40px)}
/* 🚨 min-width:0 ON THE GRID ITEM, not just on the scroller inside it.
   A grid item's automatic minimum size is its content size, exactly like a
   flex item's. With 64 thumbnails in the rail this column refused to be
   narrower than 5179px, so the rail had nothing to scroll within, the arrows
   hid themselves as "not scrollable", and the whole document went 5574px wide
   — a PDP that scrolled sideways off the screen. Fixing .thumbs alone did
   nothing; the constraint has to start at the track. */
.pdp-media{min-width:0}
.gal{min-width:0}
/* ── THE GALLERY ───────────────────────────────────────────────────────
   Stage, rail, lightbox.

   What was here before was a static CSS grid of up to eight thumbnails that
   nothing could click. It looked like a gallery and behaved like a contact
   sheet. The rail below is a real horizontal scroller because the products
   carry up to sixty-seven photographs — a wrapping grid of those is four
   hundred pixels of thumbnails pushing the price off the first screen.

   The stage keeps its 1:1 box so switching images never reflows the page. */
.gal{position:relative}
.pdp-hero{position:relative;margin:0;border-radius:var(--r-xl);overflow:hidden;
          background:var(--sand-3);box-shadow:var(--sh-2)}
.pdp-hero img{display:block;width:100%;aspect-ratio:1;object-fit:cover}

/* Stage controls stay out of the way until the pointer is on the photograph;
   on touch there is no hover, so they are simply always there. */
.gal-nav,.gal-zoom{position:absolute;z-index:2;display:grid;place-items:center;
  border:0;border-radius:50%;cursor:pointer;color:var(--ink);
  background:rgba(255,255,255,.9);box-shadow:0 2px 10px rgba(20,21,26,.16);
  opacity:0;transition:opacity var(--tap) var(--ease),transform var(--tap) var(--spring),
             background var(--tap) var(--ease)}
.gal-nav{top:50%;width:40px;height:40px;margin-top:-20px}
.gal-prev{left:12px}
.gal-next{right:12px}
.gal-prev .ic{transform:rotate(180deg)}
.gal-zoom{top:12px;right:12px;width:36px;height:36px}
.pdp-hero:hover .gal-nav,.pdp-hero:hover .gal-zoom,
.gal-nav:focus-visible,.gal-zoom:focus-visible{opacity:1}
.gal-nav:hover,.gal-zoom:hover{background:#fff;transform:scale(1.06)}
.gal-prev:hover{transform:scale(1.06) translateX(-2px)}
.gal-next:hover{transform:scale(1.06) translateX(2px)}
@media (hover:none){.gal-nav,.gal-zoom{opacity:1}}
.gal-count{position:absolute;left:12px;bottom:12px;z-index:2;
  padding:4px 10px;border-radius:var(--r-pill);
  background:rgba(20,21,26,.62);color:#fff;
  font-size:.6875rem;font-weight:750;letter-spacing:.04em;
  font-variant-numeric:tabular-nums}

.gal-rail{position:relative;display:flex;align-items:center;gap:6px;margin-top:12px}
.gal-arrow{flex:none;width:30px;height:64px;display:grid;place-items:center;
  border:1px solid var(--hair);border-radius:var(--r-md);background:#fff;
  color:var(--ink-3);cursor:pointer;
  transition:color var(--tap) var(--ease),border-color var(--tap) var(--ease),
             opacity var(--tap) var(--ease)}
.gal-arrow:hover:not([disabled]){color:var(--ink);border-color:var(--hair-2)}
/* Disabled, not removed — the rail must not change width as you scroll it. */
.gal-arrow[disabled]{opacity:.3;cursor:default}
/* A rail with nothing to scroll gets no controls at all. */
.gal-rail[data-scrollable="0"] .gal-arrow{display:none}
.gal-arrow-l .ic{transform:rotate(180deg)}
/* The rail scrolls natively. scroll-snap keeps a thumb from parking half cut
   off, and the scrollbar is hidden because the arrows and the fade already
   say "there is more this way". */
/* 🚨 flex:1 AND min-width:0. Without min-width:0 a flex item's automatic
   minimum size is its CONTENT size, so a rail of 64 thumbnails simply grew to
   1400px instead of scrolling: overflow-x had nothing to overflow, the arrows
   correctly reported "nothing to scroll" and hid themselves, and the strip
   pushed the page sideways. The overflow property is not the scroller — the
   constrained width is. */
/* 🚨 NO scroll-snap ON THIS RAIL. It was here (x proximity + snap-align:start
   on every thumb) and it silently disabled the arrow buttons: a programmatic
   rail.scrollBy(400) inside a snap container is re-snapped straight back to
   the current snap target, so the measured movement was 2.4px -> 2px. Zero.
   The buttons looked fine, fired their handler, and did nothing.
   Snapping bought nothing here — these are 72px thumbnails, not full-width
   slides — so it is gone rather than worked around. */
/* 🚨 THE ONE GENUINE SCROLLER LEFT ON THE SITE, and it earns it: a product
   can carry sixty-seven photographs, which is not a grid, it is a filmstrip.
   Everything else that used to scroll sideways is now a grid — see the notes
   on .rail, .sw-strip and .jump-in.
   It already had overlay arrows, roving tabindex and keyboard control. What it
   was missing is the two things that tell a mouse user it CAN be dragged:
   an edge fade where the content is cut, and a grab cursor.
   The mask is applied per side by data-edge, which the gallery module already
   maintains for the arrow disabled states — so no new bookkeeping, and a rail
   scrolled to the end does not keep pretending there is more. */
.thumbs{flex:1;min-width:0;display:flex;gap:9px;overflow-x:auto;overflow-y:hidden;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;
  padding:2px;margin:-2px;cursor:grab;
  -webkit-mask-image:var(--edge,none);mask-image:var(--edge,none)}
.thumbs::-webkit-scrollbar{display:none}
.thumbs[data-drag="1"]{cursor:grabbing;scroll-behavior:auto;user-select:none}
.thumbs[data-drag="1"] .thumb{pointer-events:none}
.gal-rail[data-edge="both"] .thumbs{--edge:linear-gradient(90deg,transparent,#000 26px,#000 calc(100% - 26px),transparent)}
.gal-rail[data-edge="end"]  .thumbs{--edge:linear-gradient(90deg,#000 calc(100% - 26px),transparent)}
.gal-rail[data-edge="start"] .thumbs{--edge:linear-gradient(90deg,transparent,#000 26px)}
.thumb{flex:none;width:72px;padding:0;margin:0;cursor:pointer;
  border-radius:var(--r-md);overflow:hidden;background:var(--sand-3);
  border:1px solid var(--hair);
  transition:border-color var(--tap) var(--ease),box-shadow var(--tap) var(--ease),
             transform var(--tap) var(--spring)}
.thumb img{display:block;width:100%;aspect-ratio:1;object-fit:cover;
  transition:opacity var(--tap) var(--ease)}
.thumb:hover{border-color:var(--hair-2);transform:translateY(-2px)}
.thumb img{opacity:.82}
.thumb:hover img{opacity:1}
/* The selected thumbnail is stated twice — a ring and full opacity — because
   a single 1px border change is not a state a buyer notices at 72px. */
.thumb[aria-pressed="true"]{border-color:var(--blue);box-shadow:0 0 0 2px var(--blue) inset;
  transform:none}
.thumb[aria-pressed="true"] img{opacity:1}

/* ── lightbox ── */
.lb{position:fixed;inset:0;z-index:300;display:grid;place-items:center;
  padding:clamp(16px,4vw,54px);background:rgba(12,13,17,.93)}
.lb img{max-width:100%;max-height:100%;width:auto;height:auto;
  border-radius:var(--r-md);box-shadow:0 24px 70px rgba(0,0,0,.5)}
.lb-x,.lb-nav{position:absolute;z-index:2;display:grid;place-items:center;
  border:1px solid rgba(255,255,255,.26);border-radius:50%;cursor:pointer;
  background:rgba(255,255,255,.1);color:#fff;
  transition:background var(--tap) var(--ease),transform var(--tap) var(--spring)}
.lb-x{top:16px;right:16px;width:42px;height:42px}
.lb-nav{top:50%;width:46px;height:46px;margin-top:-23px}
.lb-prev{left:14px}
.lb-next{right:14px}
.lb-prev .ic{transform:rotate(180deg)}
.lb-x:hover,.lb-nav:hover{background:rgba(255,255,255,.22);transform:scale(1.07)}
.lb-count{position:absolute;bottom:18px;left:50%;transform:translateX(-50%);
  color:rgba(255,255,255,.8);font-size:.8125rem;font-weight:700;
  font-variant-numeric:tabular-nums}
@media (max-width:560px){.lb-nav{width:38px;height:38px;margin-top:-19px}.lb-prev{left:6px}.lb-next{right:6px}}

@media (prefers-reduced-motion:reduce){
  .gal-nav,.gal-zoom,.thumb,.lb-x,.lb-nav{transition:none}
  .gal-nav:hover,.gal-zoom:hover,.thumb:hover,.lb-x:hover,.lb-nav:hover{transform:none}
  .thumbs{scroll-behavior:auto}
}
.pdp-fam a{display:inline-flex;align-items:center;min-height:32px;
           font-size:.75rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
           color:var(--ink-3);text-decoration:none}
.pdp-fam a:hover{color:var(--ink)}
.pdp-buy h1{font-size:clamp(1.6rem,2.9vw,2.35rem);margin-top:12px;letter-spacing:-.032em}
.badges{display:flex;flex-wrap:wrap;gap:7px;margin-top:16px}
.badge{padding:5px 12px;border-radius:var(--r-pill);background:var(--sand);
       font-size:.75rem;font-weight:700;letter-spacing:-.005em}
.price{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-top:22px}
.price-n{font-size:clamp(1.9rem,3.2vw,2.6rem);font-weight:800;letter-spacing:-.048em;line-height:1}
.price-r{font-size:1.3rem;font-weight:700;color:var(--ink-3);letter-spacing:-.03em}
.price-l{width:100%;font-size:.75rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
         color:var(--ink-3);margin-top:6px}
/* The .stock line is gone from the markup — see THE SOLD-OUT RULE. */
.pack{display:flex;align-items:center;gap:7px;
      margin-top:7px;font-size:.875rem;font-weight:650;color:var(--teal)}

.vsel{margin-top:26px;padding-top:22px;border-top:1px solid var(--hair)}
.vsel-h{display:flex;align-items:baseline;gap:9px;margin-bottom:12px}
.vsel-lab{font-size:.6875rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.vsel-cur{font-weight:700;font-size:.9375rem}
.vsel-row{display:flex;flex-wrap:wrap;gap:9px}
.sw-b{width:44px;height:44px;border-radius:50%;border:2px solid var(--hair-2);cursor:pointer;
      background:var(--sw);position:relative;padding:0;
      transition:transform var(--tap) var(--spring),box-shadow var(--tap) var(--ease)}
.sw-b:hover{transform:scale(1.08)}
.sw-b[aria-pressed=true]{box-shadow:0 0 0 2px #fff,0 0 0 4.5px var(--ink)}
/* .sw-b.oos / .chip-b.oos are gone with the stock signal. Kept as a note so
   the strike-through does not get reinvented. */
.sw-b-oos-retired::after{content:"";position:absolute;inset:-2px;border-radius:50%;
  background:linear-gradient(45deg,transparent 46%,rgba(255,255,255,.9) 47%,rgba(255,255,255,.9) 53%,transparent 54%)}
.chip-b{padding:10px 16px;border-radius:var(--r-pill);border:1.5px solid var(--hair-2);
        background:#fff;font-size:.875rem;font-weight:600;cursor:pointer;min-height:44px}
.chip-b[aria-pressed=true]{background:var(--ink);border-color:var(--ink);color:#fff}


/* §7.4 — the gate. Deliberately conspicuous: the asymmetry between public MSRP
   and private cost IS the conversion engine, not a limitation of the page. */
.gate{margin-top:26px;padding:20px 22px 22px;border:2px solid var(--blue);
      border-radius:var(--r-lg);
      background:linear-gradient(180deg,rgba(35,50,213,.055),rgba(35,50,213,.015))}
.gate-h{display:flex;align-items:center;gap:8px;margin-bottom:12px;
        font-size:.6875rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
        color:var(--blue)}
.gate-row{display:flex;justify-content:space-between;align-items:center;padding-block:9px;
          font-size:.9688rem}
.gate-row+.gate-row{border-top:1px dashed rgba(35,50,213,.22)}
.gate-row span{font-weight:600;color:var(--ink-2)}
.dots{letter-spacing:.22em;color:var(--blue);opacity:.5;font-size:.8125rem}
.gate .btn{margin-top:16px}
/* min-height on both of these: they were 23px and 27px tall, which is a
   text link pretending to be a control on a page that is mostly used on a
   phone behind a counter. */
.gate-alt{display:inline-flex;align-items:center;justify-content:center;gap:6px;
          margin-top:10px;width:100%;min-height:40px;
          font-size:.875rem;font-weight:650;color:var(--blue);text-decoration:none}
.gate-alt:hover{text-decoration:underline}
.callus{display:inline-flex;align-items:center;gap:8px;margin-top:14px;min-height:40px;
        font-size:.875rem;font-weight:650;color:var(--ink-3);text-decoration:none}
.callus:hover{color:var(--ink)}

.pdp-body{display:grid;grid-template-columns:1.25fr .75fr;gap:clamp(28px,4.5vw,64px);
          padding-block:clamp(34px,5vw,64px);align-items:start}
.pdp-copy p{margin-top:16px;font-size:1.0625rem;line-height:1.66;color:var(--ink-2);max-width:62ch}
.pdp-copy p:first-child{margin-top:0;font-size:1.15rem;color:var(--ink);line-height:1.55}
/* A flagged lede paragraph. The 3px gold border-left this replaced is the
   single most recognisable tell of a generated interface, and it was also
   the only place on the site using that device — so it read as imported
   rather than designed. The marker is now the same short accent rule the
   section kickers use, which makes the callout part of the site's own
   vocabulary instead of a stray convention. */
.lede-flag{background:var(--sand-3);border:1px solid var(--hair);
           border-radius:var(--r-md);padding:16px 18px}
.lede-flag::before{content:"";display:block;width:26px;height:2px;border-radius:2px;
                   background:var(--gold-2);margin-bottom:12px}
.sells{grid-column:1/-1;margin-top:14px}
.sells h2,.feats h2,.specs h2,.faq h2{font-size:1.25rem;margin-bottom:16px}
.sells-g{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
.sell{padding:20px;border:1px solid var(--hair);border-radius:var(--r-lg);background:var(--sand-3)}
.sell .ic{color:var(--ink-3);margin-bottom:10px}
.sell b{display:block;font-size:.9688rem;font-weight:700}
.sell span{display:block;margin-top:5px;font-size:.875rem;color:var(--ink-3);line-height:1.5}
.feats ul{margin:0;padding-left:20px;color:var(--ink-2);font-size:.9375rem;line-height:1.6}
.specs dl{display:grid;grid-template-columns:auto 1fr;gap:0;border-top:1px solid var(--hair);
          margin:0;font-size:.9063rem}
.specs dt{padding:11px 20px 11px 0;font-weight:700;border-bottom:1px solid var(--hair);white-space:nowrap}
.specs dd{padding:11px 0;margin:0;color:var(--ink-2);border-bottom:1px solid var(--hair)}
.faq{grid-column:1/-1;max-width:820px}
.faq details{border-bottom:1px solid var(--hair)}
.faq summary{padding:16px 34px 16px 0;font-weight:650;cursor:pointer;position:relative;
             list-style:none;min-height:44px;display:flex;align-items:center}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";position:absolute;right:8px;top:50%;width:9px;height:9px;
  border-right:2px solid var(--ink-3);border-bottom:2px solid var(--ink-3);
  translate:0 -60%;rotate:45deg;transition:rotate var(--tap) var(--ease)}
.faq details[open] summary::after{rotate:225deg;translate:0 -30%}
.faq details p{padding:0 0 18px;color:var(--ink-2);font-size:.9688rem;line-height:1.62;max-width:68ch}
.rel-h{font-size:clamp(1.3rem,2.2vw,1.75rem)}
.rel-p{margin-top:8px;color:var(--ink-3);font-size:.9375rem;max-width:60ch}
@media (max-width:900px){
  .pdp-top,.pdp-body{grid-template-columns:1fr}
  .specs dl{grid-template-columns:1fr}
  .specs dt{padding-bottom:2px;border-bottom:0}
  .specs dd{padding-top:0}
}

/* ═══════════════════════════════════════════════════ INTERIOR BITS ══ */
/* §5.9 — /displays/. The three-plan stack (.plans / .plan-space / .plan-mix)
   that lived here was deleted 2026-08-10 with the fixtures it described: the
   page claimed a counter tray, a four-foot carry wall and a locked glass case
   that FireBar does not have, each sized in a dimension nobody measured. One
   floor display exists, for the bag line, and it is the only thing that needs
   this treatment — hence .plan-solo rather than a list. Do not reintroduce a
   multi-plan layout without real fixtures to put in it. */
.plan-solo{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(22px,3.6vw,48px);
      align-items:center;background:#fff;border:1px solid var(--hair);
      border-radius:var(--r-xl);overflow:hidden;box-shadow:var(--sh-1);
      scroll-margin-top:calc(var(--hdr-h) + 24px)}
.plan-m img{width:100%;height:100%;object-fit:cover;aspect-ratio:4/3}
.plan-b{padding:clamp(22px,3vw,40px) clamp(22px,3vw,40px) clamp(22px,3vw,40px) 0}
.plan-b h2{margin-top:8px;font-size:clamp(1.3rem,2.2vw,1.8rem)}
.plan-b p{margin-top:12px;color:var(--ink-2);line-height:1.6;font-size:.9688rem}
.plan-b .btn{margin-top:var(--cta-space-tight)}
@media (max-width:820px){
  .plan-solo{grid-template-columns:1fr}
  .plan-b{padding:0 24px 28px}
}

/* ── POP DISPLAYS ──────────────────────────────────────────────────────
   Every count in this list is a live Shopify increment read at build time.
   The number is the loudest thing in the row because the number is what the
   buyer came for; the family name is the label, not the headline. */
.pop-head{max-width:760px}
.pop-list{list-style:none;margin:34px 0 0;padding:0;
  border:1px solid var(--hair);border-radius:var(--r-lg);overflow:hidden;background:#fff}
.pop-r{display:flex;align-items:center;gap:14px;padding:15px 20px}
.pop-r+.pop-r{border-top:1px solid var(--hair)}
.pop-ic{color:var(--ink-3);flex:none}
.pop-n{font-weight:700;letter-spacing:-.02em;font-size:.9688rem;flex:1;min-width:0}
.pop-c{display:flex;align-items:baseline;gap:7px;font-size:1.25rem;font-weight:800;
  letter-spacing:-.04em;flex:none}
.pop-c em{font-style:normal;font-size:.6875rem;font-weight:800;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-3)}
.pop-note{display:flex;align-items:center;gap:9px;margin-top:16px;
  font-size:.875rem;color:var(--ink-3)}
.pop-note .ic{flex:none}
@media (max-width:520px){
  .pop-r{gap:11px;padding:13px 15px}
  .pop-n{font-size:.9062rem}
  /* Stack rather than hide. Dropping "to a display" saved a few pixels and
     left a bare "5" against a product name — the one thing on this page a
     buyer is here to read, stripped of its unit. */
  .pop-c{font-size:1.09rem;flex-direction:column;align-items:flex-end;gap:1px}
  .pop-c em{font-size:.5625rem;letter-spacing:.06em}
}

.note{display:flex;gap:14px;align-items:flex-start;margin-top:34px;padding:22px;
      background:var(--sand-3);border:1px solid var(--hair);border-radius:var(--r-lg)}
.note .ic{color:var(--ink-3);flex:none}
.note p{color:var(--ink-2);font-size:.9375rem;line-height:1.6}

/* ── THE ORDERING FLOW ─────────────────────────────────────────────────
   One component, two callers: the homepage's five steps and the four
   AUTHORED steps on /retailers/. It replaces a row of equal bordered cards,
   which stated the steps but not the fact that they are a SEQUENCE — the one
   thing a buyer reads this block to work out.

   `grid-auto-flow:column` + `grid-auto-columns:1fr` means the component takes
   its column count from however many steps it is handed. Four and five both
   lay out correctly with no per-caller media query, and a sixth would too. */
.flow{list-style:none;margin:0;padding:0;
      --mark:54px;--fgap:clamp(14px,2vw,26px);
      display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:var(--fgap)}
.flow-s{position:relative}

/* The connector. A negative `right` lets the rule run past its own cell and
   across the grid gap, stopping 8px short of the next node — so the line
   belongs to the space BETWEEN two steps rather than to either one. Dashed,
   because a dashed run reads as travel without needing an arrowhead. */
.flow-s::after{content:"";position:absolute;top:calc(var(--mark) / 2);
               left:calc(var(--mark) + 10px);right:calc(8px - var(--fgap));
               height:0;border-top:1.5px dashed var(--hair-2)}
.flow-s:last-child::after{display:none}

.flow-mark{width:var(--mark);height:var(--mark);display:grid;place-items:center;
           border-radius:17px;background:#fff;border:1px solid var(--hair-2);
           color:var(--blue);box-shadow:var(--sh-1);position:relative}
.flow-ic{width:24px;height:24px}
.flow-num .flow-n{position:absolute;top:-8px;right:-8px;min-width:23px;height:23px;
                  padding:0 6px;border-radius:var(--r-pill);background:var(--ink);color:#fff;
                  font-size:.625rem;font-weight:800;letter-spacing:.04em;
                  display:grid;place-items:center;box-sizing:border-box}
.flow-t{margin-top:17px;font-size:1.03rem;font-weight:750;letter-spacing:-.024em;line-height:1.25}
.flow-d{display:block;margin-top:7px;color:var(--ink-3);font-size:.875rem;line-height:1.5}

/* Below 820 the run turns vertical and the connector becomes a rail down the
   left, threaded through the centre of each node. Five columns squeezed into
   a phone would give each caption about 60px of measure. */
@media (max-width:820px){
  .flow{grid-auto-flow:row;grid-auto-columns:auto;gap:0;--mark:48px}
  .flow-s{display:grid;grid-template-columns:auto 1fr;column-gap:17px;padding-bottom:26px}
  .flow-mark{grid-row:1/3}
  .flow-s::after{top:calc(var(--mark) + 9px);bottom:9px;height:auto;
                 left:calc(var(--mark) / 2 - 1px);right:auto;width:0;
                 border-top:0;border-left:1.5px dashed var(--hair-2)}
  .flow-t{margin-top:0;align-self:center}
  .flow-s:has(.flow-d) .flow-t{align-self:end}
  .flow-d{align-self:start}
}
/* On the sand band the white nodes need a touch more separation from the
   ground than the 1px hairline gives them. */
.flowband .flow-mark{box-shadow:var(--sh-1),0 0 0 4px rgba(255,255,255,.5)}
/* The band heading and the first node were colliding — the descender of
   "ordering" was landing on the ring. .band-head carries no bottom margin of
   its own because most bands follow it with a grid that brings its own. */
.flowband .band-head{margin-bottom:clamp(30px,4vw,46px)}

.two-up{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,5vw,68px)}
@media (max-width:820px){.two-up{grid-template-columns:1fr}}
.mini-stats{display:flex;gap:30px;margin-top:22px}
.mini-stats b{display:block;font-size:2rem;font-weight:800;letter-spacing:-.04em;line-height:1}
.mini-stats span{display:block;font-size:.8125rem;color:var(--ink-3);margin-top:4px;max-width:16ch}

.ticks{list-style:none;margin:24px 0 0;padding:0;display:flex;flex-direction:column;gap:13px}
.ticks li{display:flex;gap:11px;align-items:flex-start;font-size:1rem;line-height:1.5}
.ticks .ic{color:var(--teal);margin-top:4px;flex:none}
.cta-row{display:flex;flex-wrap:wrap;gap:12px;margin-top:var(--cta-space)}
.signup-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,68px);align-items:center}
.signup-m picture{border-radius:var(--r-xl);overflow:hidden;box-shadow:var(--sh-3)}
.signup-m img{width:100%;aspect-ratio:4/3;object-fit:cover}
@media (max-width:900px){.signup-grid{grid-template-columns:1fr}}
.endcta{max-width:720px;margin-inline:auto;text-align:center}
.endcta p{margin-top:14px;color:var(--ink-2);font-size:1.03rem;line-height:1.6}
.endcta .cta-row{justify-content:center}
.endcta.light p{color:rgba(255,255,255,.78)}

/* ladder ─────────────────────────────────────────────────────────── */
.ladder{background:var(--ink);color:#fff;padding-block:clamp(44px,6vw,80px)}
.ladder-head h2{display:flex;align-items:center;gap:12px;font-size:clamp(1.5rem,2.5vw,2.1rem)}
.ladder-ic{color:var(--gold);flex:none}
.ladder-head p{margin-top:10px;color:rgba(255,255,255,.64);font-size:.9375rem}

/* ── THE DISCOUNT LADDER, DRAWN AS A LADDER ────────────────────────────
   This band renders on all 36 pages, which makes it the most repeated object
   on the site and the one most worth drawing properly. Four identical cards
   said "here are four numbers". A rising stair says "the more of the order
   goes on one invoice, the more comes back" — which is the actual proposition
   and the reason the band exists at all.

   🚨 ONE DISTINCTION CARRIES THE GRAPHIC: $300 is OUTLINED, the other three
   are FILLED. $300 is a floor you have to clear; the rest is money returned.
   Drawing all four the same states the opening minimum as if it were a fourth
   discount, which is the single misreading that costs a buyer money.

   The bars are at full height at rest and never animate up from zero — same
   rule as the reveal, for the same reason. */
.vladder{
  list-style:none;margin:36px 0 0;padding:0;position:relative;
  display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(7px,1.1vw,13px);
  --stage:clamp(118px,16vw,200px);
}
/* A tight gap and a small top radius are what make four bars read as one
   staircase rather than as a bar chart. Widen either and the risers separate
   into columns, and the ascent stops being a single object. */
/* One continuous baseline under all four risers, drawn on the container so it
   does not break across the column gaps the way four cell borders would. */
.vladder::before{content:"";position:absolute;left:0;right:0;top:var(--stage);height:1px;
                 background:rgba(255,255,255,.2)}
.vl{display:grid;grid-template-rows:var(--stage) auto auto}
.vl-bar{
  align-self:end;width:100%;
  height:calc(var(--stage) * (.34 + .22 * var(--i)));
  border-radius:9px 9px 2px 2px;
  background:linear-gradient(180deg,var(--gold),var(--gold-2));
  box-shadow:0 1px 0 rgba(255,255,255,.32) inset;
}
.vl-floor .vl-bar{background:none;box-shadow:none;
                  border:1.5px dashed rgba(255,255,255,.32)}
.vl-at{padding-top:15px;font-size:clamp(1.3rem,2.1vw,1.75rem);font-weight:800;
       letter-spacing:-.045em;color:var(--gold);line-height:1}
.vl-floor .vl-at{color:#fff}
.vl-d{margin-top:8px;font-size:.875rem;color:rgba(255,255,255,.74);line-height:1.45}

/* Below 620 the stair rotates: the bar becomes a rule under each row and
   WIDTH carries the climb instead of height. Four 70px-wide columns would
   have made the numbers unreadable to keep a shape that no longer fits. */
@media (max-width:620px){
  .vladder{grid-template-columns:1fr;gap:0;margin-top:26px}
  .vladder::before{display:none}
  .vl{display:flex;flex-direction:column;align-items:stretch;
      padding:16px 0;border-bottom:1px solid rgba(255,255,255,.13)}
  .vl:first-child{padding-top:0}
  .vl:last-child{border-bottom:0;padding-bottom:0}
  /* ⚠️ align-self MUST be reset here. The desktop rule sets `align-self:end`
     to sit each riser on the baseline; in this column-direction flex the
     cross axis is HORIZONTAL, so `end` right-aligns the bars and the ladder
     reads as a descent from the right edge — the exact opposite of what the
     graphic says. */
  .vl-bar{order:3;align-self:flex-start;height:8px;border-radius:var(--r-pill);
          margin-top:13px;width:calc(28% + 24% * var(--i))}
  .vl-at{order:1;padding-top:0}
  .vl-d{order:2;margin-top:6px}
}

/* ══════════════════════════════════════════════════════════ FOOTER ══ */
.ftr{background:var(--sand-3);border-top:1px solid var(--hair);padding-block:clamp(46px,6vw,76px) 0}
.ftr-in{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:clamp(24px,3.4vw,44px)}
.brand-ink{color:var(--ink)}
.ftr-note{margin-top:16px;color:var(--ink-3);font-size:.9063rem;line-height:1.6;max-width:40ch}
.ftr-tel{display:inline-flex;align-items:center;gap:8px;margin-top:14px;min-height:40px;
         font-weight:700;text-decoration:none;color:var(--ink)}
.ftr-col h3{font-size:.75rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
            color:var(--ink-3)}
/* gap → min-height. The links were 20px tall in a 9px-gapped stack, which is
   a 20px target; the same visual rhythm made of 36px rows is a real one. */
.ftr-col ul{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:0}
.ftr-col a{display:inline-flex;align-items:center;min-height:36px;
           text-decoration:none;font-size:.9375rem;color:var(--ink-2)}
.ftr-col a:hover{color:var(--ink);text-decoration:underline}
.ftr-legal{display:flex;flex-wrap:wrap;gap:14px;align-items:center;margin-top:clamp(34px,4vw,56px);
           padding-block:20px;border-top:1px solid var(--hair);font-size:.8125rem;color:var(--ink-3)}
.pill-21{padding:3px 11px;border-radius:var(--r-pill);background:var(--ink);color:#fff;
         font-weight:750;font-size:.75rem}
.ftr-c{margin-left:auto}
@media (max-width:900px){.ftr-in{grid-template-columns:1fr 1fr}}
@media (max-width:520px){.ftr-in{grid-template-columns:1fr}.ftr-c{margin-left:0}}

/* ═════════════════════════════════════════════════════ THUMB BAR ══ */
.thumbbar{
  position:fixed;left:0;right:0;bottom:0;z-index:60;display:none;gap:10px;align-items:center;
  padding:11px calc(var(--gut) / 2) calc(11px + env(safe-area-inset-bottom));
  background:rgba(255,255,255,.97);border-top:1px solid var(--hair);
  transform:translateY(110%);transition:transform 320ms var(--ease);
}
.thumbbar.up{transform:none}
.thumb-tel{width:48px;height:48px;flex:none;display:grid;place-items:center;border-radius:14px;
           border:1.5px solid var(--hair-2);color:var(--ink);text-decoration:none}
/* The thumb bar carries the apply CTA wherever .hdr-apply is hidden, so this
   breakpoint must match the DRAWER one exactly. */
@media (max-width:1040px){.thumbbar{display:flex}}

/* ═══════════════════════════════════════════ LINE SHEET + PRINT ══
   §6.6 — /line/?print=1 is a line sheet a rep can hand over.

   🚨 Two rules this section exists to enforce, both learned the hard way on
   2026-08-10:

   (a) SHEET MODE IS VISIBLE ON SCREEN. `?print=1` was a dead parameter — no
       JS read it and no rule reacted to it, so the "Line sheet" link served
       the ordinary page and the buyer had to guess Ctrl+P. `.is-sheet` now
       renders the sheet on screen, so the preview and the paper agree.

   (b) NEVER PAINT SHEET TEXT WHITE ON A BACKGROUND. Browsers drop background
       colours from print by default, so every white-on-ink badge on this page
       (.fam-n counts, .flag-out) printed as white text on white paper —
       invisible, not merely ugly. Sheet styling is ink-on-paper only: dark
       text, hairline borders, no filled chips. Do not "fix" this with
       print-color-adjust; a line sheet that demands a colour cartridge to be
       readable is not a line sheet. */

/* The masthead and the running footer only exist for the handout — the page
   has a header of its own. */
.sheet-head{display:none}
.sheet-bar{display:none}
.sheet-run{display:none}

.is-sheet .sheet-bar{display:block;position:sticky;top:0;z-index:60;
  background:var(--ink);color:#fff;padding:10px 0}
.sheet-bar-in{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.sheet-bar-t{display:inline-flex;align-items:center;gap:7px;
  font-size:.8125rem;font-weight:750;letter-spacing:-.01em;white-space:nowrap}
.sheet-bar-d{font-size:.8125rem;color:rgba(255,255,255,.72);flex:1;min-width:180px}
.sheet-bar-a{display:flex;gap:8px;margin-left:auto}
.sheet-bar .btn-ghost-ink{color:#fff;border-color:rgba(255,255,255,.42)}
.sheet-bar .btn-ghost-ink:hover{background:rgba(255,255,255,.12)}
@media (max-width:640px){.sheet-bar-d{display:none}}

/* On-screen sheet: strip the page to what prints, in paper proportions. */
.is-sheet .hdr,.is-sheet .thumbbar,.is-sheet .jump,.is-sheet .ladder,
.is-sheet .ftr,.is-sheet .phero,.is-sheet .endcta,.is-sheet .cost,
.is-sheet .linebar{display:none!important}
.is-sheet body,.is-sheet{background:var(--sand-3)}
.is-sheet .sheet-head{display:flex;align-items:flex-end;justify-content:space-between;
  gap:18px;flex-wrap:wrap;max-width:1120px;margin:22px auto 0;padding:0 22px 13px;
  border-bottom:2px solid var(--ink)}
.is-sheet #grid{background:transparent}
.sheet-head-l b{display:block;font-size:1.25rem;font-weight:800;letter-spacing:-.03em}
.sheet-head-l span,.sheet-head-r span{display:block;font-size:.75rem;color:var(--ink-3)}
.sheet-head-r{text-align:right}

/* Sheet + print share the tile treatment, so the preview is honest — which
   includes the cell padding fixed in the print block below. A preview that
   does not show the MSRP gutter is a preview of a different document. */
.is-sheet .tile,.is-sheet .fam-n,.is-sheet .flag{box-shadow:none}
.is-sheet .tile{padding-bottom:9px}
.is-sheet .tile-fam,.is-sheet .tile-name,.is-sheet .tile-sub{padding-inline:12px}
.is-sheet .tile-msrp{margin-inline:12px;padding-top:7px}
.is-sheet .tile-pack{padding:4px 12px 0}
.is-sheet .fam-n,.is-sheet .flag-out{background:transparent;color:var(--ink);
  border:1px solid var(--hair-2)}

/* ── SHEET MODE SWITCHING ──────────────────────────────────────────────
   One page, two artefacts. Both label sets exist in the markup and the mode
   class picks one, so there is no flash of the wrong sheet's chrome. */
.sheet-bar [data-only],.sheet-run [data-only]{display:none}
.is-line .sheet-bar [data-only="line"],
.is-order .sheet-bar [data-only="order"]{display:inline-flex;align-items:center;gap:7px}
/* The running footer names the document it is printed on — see the note in
   renderLine(). Without this the order form's every page called itself a
   line sheet. */
.is-line .sheet-run [data-only="line"],
.is-order .sheet-run [data-only="order"]{display:inline}
.is-line .sheet-bar .sheet-bar-d[data-only="line"],
.is-order .sheet-bar .sheet-bar-d[data-only="order"]{flex:1;min-width:180px}
@media (max-width:640px){.is-sheet .sheet-bar .sheet-bar-d{display:none}}

/* ══════════════════════════════════════════════════ ORDER SHEET ══
   (§6.7) The printable order form. Ink-only by the same rule the line sheet
   obeys — browsers drop backgrounds from print, so anything that depends on a
   fill to be legible arrives blank. Hairlines, black text, and one empty
   bordered cell per row for the pen.

   🔴 There is no cost column and there is no discount ladder on this form.
   See orderSheet() in tools/build-site.mjs. */
.ordersheet{display:none}
.is-order .ordersheet{display:block;margin:18px 0 30px}
.ordersheet[hidden]{display:none!important}
.is-order #grid,.is-order .ladder,.is-order .sheet-head{display:none!important}
.is-order .endcta{display:none!important}

.os-head{display:flex;align-items:flex-start;justify-content:space-between;gap:22px;
  flex-wrap:wrap;padding-bottom:11px;border-bottom:2px solid var(--ink)}
.os-head-l b{display:block;font-size:1.25rem;font-weight:800;letter-spacing:-.03em}
.os-head-l span{display:block;font-size:.75rem;color:var(--ink-3)}
.os-head-r{display:grid;grid-template-columns:1fr 1fr;gap:8px 16px;min-width:min(100%,340px)}
/* A labelled rule, not an input: this is printed and written on. */
.os-f{display:flex;align-items:baseline;gap:7px}
.os-f-w{grid-column:span 2}
.os-f b{font-size:.6875rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);white-space:nowrap}
.os-f i{flex:1;border-bottom:1px solid var(--ink-3);height:1.05em}

.os-terms{display:flex;flex-wrap:wrap;gap:6px 20px;margin:11px 0 14px;
  font-size:.8125rem;color:var(--ink-2)}
.os-terms b{font-weight:800;color:var(--ink)}

.os-t{width:100%;border-collapse:collapse;font-size:.8125rem}
.os-t th,.os-t td{text-align:left;padding:6px 8px;border-bottom:1px solid var(--hair)}
.os-t thead th{font-size:.6875rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);border-bottom:1.5px solid var(--ink)}
.os-t .os-fam th{padding-top:15px;font-size:.875rem;font-weight:800;letter-spacing:-.02em;
  color:var(--ink);border-bottom:1px solid var(--ink-3)}
.os-t .os-fam th span{margin-left:8px;font-size:.6875rem;font-weight:700;color:var(--ink-3)}
.os-n{width:auto}
/* nowrap: a SKU that wraps to two lines doubles the row height and is harder
   to copy onto a purchase order than one that is simply narrow. */
.os-sku{width:128px;white-space:nowrap;font-variant-numeric:tabular-nums;
        font-size:.75rem;color:var(--ink-2)}
.os-sku em{font-style:normal;font-weight:750;color:var(--ink-3)}
.os-sku em::before{content:"×"}
.os-n em{white-space:nowrap}
.os-p{width:74px;text-align:right!important;font-variant-numeric:tabular-nums;font-weight:750}
.os-d{width:78px;text-align:center!important;color:var(--ink-3)}
.os-q{width:70px}
.os-t tbody td.os-q{border:1px solid var(--ink-3);height:26px;background:transparent}
.os-n em{font-style:normal;font-size:.6875rem;font-weight:750;color:var(--ink-3)}
.os-oos .os-n,.os-oos .os-sku,.os-oos .os-p{color:var(--ink-3)}

.os-foot{display:flex;align-items:flex-end;justify-content:space-between;gap:22px;
  flex-wrap:wrap;margin-top:20px;padding-top:12px;border-top:1.5px solid var(--ink)}
.os-foot-l{display:grid;gap:12px;min-width:min(100%,330px);flex:1}
.os-foot p{font-size:.75rem;color:var(--ink-3)}
@media (max-width:640px){
  .os-head-r{grid-template-columns:1fr}
  .os-f-w{grid-column:auto}
  .os-sku{display:none}
  .os-t th.os-sku,.os-t td.os-sku{display:none}
}

/* ══════════════════════════════════════════════════════ HEADER DENSITY ══
   §9 — the nav carries SEVEN items since /about/ landed in improvement pass 5.
   At 1280px that row still has slack; at the bottom of the desktop band it
   does not. Trimming the gap and the button padding buys ~110px and keeps the
   header exactly one line tall everywhere it is shown. Do not solve this by
   dropping a nav item on some pages — a nav that differs per page is the v3
   bug verify.mjs check 1 exists to catch.

   🚨 TWO THINGS HOLD THE ROW TO ONE LINE, AND BOTH ARE LOAD-BEARING.

   1. white-space:nowrap ON THE LINK. Without it the seventh item does not
      overflow — it WRAPS INSIDE ITSELF, and a screenshot at exactly 981px
      showed "Media / kit" stacked in the middle of the bar with the row
      silently 20px taller. An item that breaks its own label is worse than
      one that overflows, because nothing reports it.
   2. THE DRAWER TAKES OVER AT 1040, NOT 980. Six items fitted at 980; seven
      do not, at any legible size. Raising the burger breakpoint is the honest
      fix — squeezing the gap to 8px and the font to 13px would have "fitted"
      by making the nav unreadable. The drawer lists all seven at full size,
      so nothing is lost below 1040. This value MUST stay in step with the
      .hdr-signin / .hdr-apply / .burger rules below; they are one decision. */
@media (max-width:1160px){
  .nav ul{gap:13px;font-size:.875rem}
  .hdr .btn{padding:10px 14px;font-size:.875rem}
  .brand{font-size:1rem}
}
.nav-i>a{white-space:nowrap}

/* ═════════════════════════════════════════════════════════ MEDIA KIT ══
   §9 /media-kit/ — an asset library, not a sales page.

   The mode is OPERATE: a retailer arrives knowing what they want and the
   design's whole job is to get out of the way of finding it. So the
   money-legibility rule that governs /line/ is applied here to ORGANISATION
   instead — the counts, the labels and the image dimensions are typeset
   deliberately, and everything decorative is turned down until the
   photographs are the only loud thing on the page.

   Two rules worth keeping:
   · ACTIONS ARE NEVER HOVER-ONLY. Every Save/Copy control is visible at rest.
     A hover-reveal action row is invisible on every touch device, which is
     most of the traffic that will ever use this page, and undiscoverable by
     keyboard without a focus-within hack that then fights the grid.
   · THE PREVIEW IS `contain`, NOT `cover`. Everywhere else on this site a
     product photo is cropped to fill its tile, which is right for
     merchandising. It is wrong here: this tile is a preview OF A FILE, and a
     crop misrepresents the asset the button hands over. */

.mk-hero{position:relative;overflow:hidden;background:var(--ink);color:#fff;
  padding-block:clamp(46px,6vw,84px) clamp(34px,4.4vw,56px)}
/* ⚠️ NO DECORATIVE GRID HERE, AND IT IS NOT COMING BACK.
   This shipped as a faint 56px square grid, defended as "a contact sheet —
   the page's own subject drawn in the ground". The design detector flagged it
   as a generated-UI slop signature and was right: a hairline gradient grid on
   a fixed pixel cell means something only on a canvas, map or measurement
   surface, and a metaphor is not a reason to put ornament behind a headline.
   The ground is now flat ink with one directional light, which is what the
   rest of the site's dark bands do. */
.mk-hero::after{content:"";position:absolute;pointer-events:none;
  width:min(760px,80vw);aspect-ratio:1;right:-16%;top:-42%;
  background:radial-gradient(circle,rgba(35,50,213,.44),transparent 62%)}
.mk-hero-in{position:relative;z-index:1}
.mk-hero .crumb a{color:rgba(255,255,255,.72)}
.mk-hero h1{max-width:16ch}
.mk-lede{margin-top:16px;max-width:56ch;font-size:clamp(1.02rem,1.5vw,1.19rem);
  color:rgba(255,255,255,.82);line-height:1.55}

.mk-stats{display:flex;flex-wrap:wrap;gap:10px 40px;margin:26px 0 0}
.mk-stats div{display:flex;flex-direction:column-reverse}
.mk-stats dt{font-size:.72rem;font-weight:650;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.55)}
.mk-stats dd{margin:0;font-size:clamp(1.5rem,2.6vw,2.05rem);font-weight:800;
  letter-spacing:-.035em;font-variant-numeric:tabular-nums;line-height:1.05}
.mk-hero .hero-cta{margin-top:28px}

/* ── the toolbar ─────────────────────────────────────────────────── */
/* One sticky group holding the filter bar AND the family nav. The children
   are static inside it, so the second bar needs no knowledge of the first
   one's height — see the note in the template. */
.mk-stick{position:sticky;top:var(--hdr-h);z-index:40}
.mk-stick .linebar{position:static;top:auto;z-index:auto}
.mk-bar .linebar-in{gap:14px}
.mk-find{position:relative;display:flex;align-items:center;flex:1 1 250px;max-width:340px}
.mk-find-i{position:absolute;left:13px;color:var(--ink-3);pointer-events:none}
.mk-find input{width:100%;min-height:40px;padding:8px 14px 8px 40px;
  border:1.5px solid var(--hair-2);border-radius:var(--r-pill);background:#fff;
  font:inherit;font-size:.9rem;color:var(--ink);
  transition:border-color var(--tap) var(--ease),box-shadow var(--tap) var(--ease)}
.mk-find input::placeholder{color:var(--ink-3)}
.mk-find input:focus{outline:none;border-color:var(--blue);
  box-shadow:0 0 0 3.5px rgba(35,50,213,.15)}
.mk-find input::-webkit-search-cancel-button{cursor:pointer}

/* ── body ────────────────────────────────────────────────────────── */
.mk-body{padding-bottom:clamp(40px,6vw,80px)}
.mk-fam{padding-top:clamp(34px,4.6vw,60px);scroll-margin-top:calc(var(--hdr-h) + 118px)}
.mk-fam-head{max-width:760px;padding-bottom:6px;border-bottom:2px solid var(--ink)}
.mk-fam-head h2{font-size:clamp(1.45rem,2.5vw,2.05rem)}
.mk-fam-b{margin-top:8px;color:var(--ink-3);font-size:.9375rem;line-height:1.5}
.mk-fam-n{margin-top:10px;padding-bottom:8px;font-size:.8125rem;color:var(--ink-3);
  font-variant-numeric:tabular-nums}
.mk-fam-n b{color:var(--ink);font-weight:800}

.mk-prod{padding-top:clamp(24px,3vw,38px)}
.mk-prod-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.mk-prod-head h3{font-size:1.0625rem}
.mk-prod-n{font-size:.75rem;font-weight:700;color:#fff;background:var(--ink);
  padding:3px 10px;border-radius:var(--r-pill);font-variant-numeric:tabular-nums}
.mk-prod-a{display:flex;gap:8px;margin-left:auto;flex-wrap:wrap}

.mk-shots{display:grid;gap:14px;
  grid-template-columns:repeat(auto-fill,minmax(186px,1fr))}

.mk-shot{margin:0;display:flex;flex-direction:column;background:#fff;
  border:1px solid var(--hair);border-radius:var(--r-md);overflow:hidden;
  transition:border-color var(--tap) var(--ease),box-shadow var(--tap) var(--ease)}
.mk-shot:hover{border-color:var(--hair-2);box-shadow:var(--sh-1)}
.mk-shot-m{position:relative;display:block;aspect-ratio:1;background:var(--sand-3);
  border-bottom:1px solid var(--hair)}
/* 🚨 ABSOLUTELY POSITIONED, SO THE PHOTOGRAPH CAN NEVER SIZE ITS OWN BOX.
   The preview must be a uniform square whatever shape the source is —
   otherwise one non-square photo stretches its entire grid row and the shelf
   goes ragged (it did: a 500×523 image made a 227px box in a 218px grid).
   Taking the image out of flow makes that structurally impossible rather than
   merely unlikely, which is the only kind of fix worth making here. */
.mk-shot-m img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;padding:8px;
  transition:transform var(--dur) var(--spring)}
.mk-shot:hover .mk-shot-m img{transform:scale(1.035)}
/* The expand affordance is an enhancement on a link that already works, so it
   may hide at rest — unlike the Save and Copy controls beneath it. */
/* The glyph is a CSS mask rather than an inline <svg><use>, because at 535
   tiles an inline icon is 34 KB of repeated markup for one decorative arrow.
   It is the same i-expand path the sprite carries. */
.mk-shot-x{position:absolute;right:9px;top:9px;width:30px;height:30px;
  border-radius:9px;background:rgba(20,21,26,.72);
  opacity:0;transform:translateY(-3px);
  transition:opacity var(--tap) var(--ease),transform var(--tap) var(--ease)}
.mk-shot-x::after{content:"";position:absolute;inset:7px;background:#fff;
  -webkit-mask:var(--mk-expand) center/contain no-repeat;
  mask:var(--mk-expand) center/contain no-repeat}
:root{--mk-expand:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.5 4.5h5v5'/%3E%3Cpath d='M19.5 4.5 13.7 10.3'/%3E%3Cpath d='M9.5 19.5h-5v-5'/%3E%3Cpath d='M4.5 19.5l5.8-5.8'/%3E%3C/svg%3E")}
.mk-shot-m:hover .mk-shot-x,.mk-shot-m:focus-visible .mk-shot-x{opacity:1;transform:none}

/* min-height holds two label lines whether or not the label needs both, so
   every tile in a row is the same height. Without it a one-line colourway
   makes a 339px tile beside a 348px one and the grid row goes ragged. */
.mk-shot-c{display:flex;flex-direction:column;gap:3px;padding:10px 12px 8px;min-height:74px}
.mk-shot-l{font-size:.8125rem;font-weight:600;line-height:1.35;color:var(--ink);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.mk-shot-d{font-size:.6875rem;color:var(--ink-3);font-variant-numeric:tabular-nums;
  letter-spacing:.01em}

.mk-acts{display:flex;gap:6px;padding:0 10px 10px;margin-top:auto}

/* ── the one button ──────────────────────────────────────────────── */
.mk-b{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:44px;padding:7px 11px;border-radius:var(--r-pill);
  border:1.5px solid var(--hair-2);background:#fff;color:var(--ink);
  font:inherit;font-size:.78rem;font-weight:650;line-height:1;cursor:pointer;
  text-decoration:none;white-space:nowrap;
  transition:background var(--tap) var(--ease),border-color var(--tap) var(--ease),
             color var(--tap) var(--ease)}
.mk-b:hover{border-color:var(--ink-3)}
.mk-b .ic{flex:none}
.mk-acts .mk-b{flex:1;min-width:0}
.mk-acts .mk-b span{overflow:hidden;text-overflow:ellipsis}
.mk-b-save{background:var(--ink);border-color:var(--ink);color:#fff}
.mk-b-save:hover{background:#000;border-color:#000}
/* Teal is the palette's confirmation colour — see MEDIA_KIT.palette roles. */
.mk-b.is-copied{background:var(--teal);border-color:var(--teal);color:#fff}
.mk-b.is-working{opacity:.72}

.mk-more{display:inline-flex;align-items:center;gap:9px;margin-top:14px;min-height:44px;
  padding:9px 18px;border-radius:var(--r-pill);border:1.5px dashed var(--hair-2);
  background:transparent;color:var(--ink-2);font:inherit;font-size:.8125rem;
  font-weight:650;cursor:pointer;
  transition:border-color var(--tap) var(--ease),color var(--tap) var(--ease),
             background var(--tap) var(--ease)}
.mk-more:hover{border-style:solid;border-color:var(--ink);color:var(--ink);background:var(--sand-3)}
.mk-more-n{font-size:.72rem;font-weight:800;color:#fff;background:var(--ink-3);
  padding:2px 8px;border-radius:var(--r-pill);font-variant-numeric:tabular-nums}

.mk-empty{padding:56px 0 20px;text-align:center;color:var(--ink-3);font-size:1rem}
.mk-empty .mk-b{margin-left:10px}

/* ── brand assets ────────────────────────────────────────────────── */
.mk-brand-head{max-width:640px;margin-bottom:clamp(26px,3.4vw,42px)}
.mk-brand-head p{margin-top:10px;color:rgba(255,255,255,.7);font-size:1rem}
.mk-logos{display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(258px,1fr))}
.mk-logo{margin:0;display:flex;flex-direction:column;gap:12px;padding:16px;
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.13);
  border-radius:var(--r-lg)}
.mk-logo-m{display:grid;place-items:center;min-height:104px;padding:20px;
  border-radius:var(--r-md)}
/* A white mark previewed on white is the classic broken-looking download. */
.mk-logo-light .mk-logo-m{background:#fff}
.mk-logo-dark .mk-logo-m{background:#0b0c10;border:1px solid rgba(255,255,255,.1)}
.mk-logo-m img{max-height:62px;width:auto;max-width:100%}
.mk-logo figcaption{display:flex;flex-direction:column;gap:3px}
.mk-logo-t{font-size:.9375rem;font-weight:700}
.mk-logo-d{font-size:.8125rem;color:rgba(255,255,255,.62)}
.mk-logo .mk-b{align-self:flex-start;background:#fff;border-color:#fff;color:var(--ink)}
.mk-logo .mk-b:hover{background:var(--sand);border-color:var(--sand)}
.mk-logo .mk-b.is-copied{background:var(--teal);border-color:var(--teal);color:#fff}

.mk-swatches{margin-top:clamp(34px,4.4vw,56px)}
.mk-swatches h3,.mk-boiler h3{font-size:1.0625rem;letter-spacing:-.02em}
.mk-chips{display:grid;gap:12px;margin-top:16px;
  grid-template-columns:repeat(auto-fill,minmax(212px,1fr))}
.mk-sw{display:flex;align-items:center;gap:12px;padding:11px 13px;text-align:left;
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.13);
  border-radius:var(--r-md);color:#fff;font:inherit;cursor:pointer;
  transition:background var(--tap) var(--ease),border-color var(--tap) var(--ease)}
.mk-sw:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.3)}
.mk-sw-c{width:38px;height:38px;flex:none;border-radius:10px;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.22)}
.mk-sw-t{display:flex;flex-direction:column;gap:1px;min-width:0}
.mk-sw-t b{font-size:.875rem;font-weight:700}
.mk-sw-h{font-size:.78rem;color:rgba(255,255,255,.8);font-variant-numeric:tabular-nums;
  letter-spacing:.02em;text-transform:uppercase}
.mk-sw-r{font-size:.72rem;color:rgba(255,255,255,.5);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.mk-sw.is-copied{background:var(--teal);border-color:var(--teal)}

.mk-boiler{margin-top:clamp(34px,4.4vw,56px);max-width:820px}
.mk-boiler-h{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.mk-boiler-h .mk-b{background:#fff;border-color:#fff;color:var(--ink)}
.mk-boiler-h .mk-b.is-copied{background:var(--teal);border-color:var(--teal);color:#fff}
.mk-boiler-t{margin-top:14px;padding:20px 22px;border-radius:var(--r-lg);
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.13);
  display:grid;gap:13px}
.mk-boiler-t p{font-size:.9375rem;line-height:1.62;color:rgba(255,255,255,.86)}

/* ── usage strip ─────────────────────────────────────────────────── */
.mk-usage{background:var(--sand);border-top:1px solid var(--hair)}
.mk-usage-in{display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  padding-block:clamp(20px,2.6vw,30px)}
.mk-usage .ic{flex:none;color:var(--ink-2)}
.mk-usage p{flex:1 1 320px;font-size:.9375rem;color:var(--ink-2);line-height:1.55}
.mk-usage-a{display:flex;gap:16px;flex-wrap:wrap}
.mk-usage-a a{font-size:.875rem;font-weight:650;color:var(--blue);text-decoration:none}
.mk-usage-a a:hover{text-decoration:underline}

/* ── the /retailers/ cross-link ──────────────────────────────────── */
.mk-xlink{display:flex;align-items:center;gap:clamp(20px,4vw,48px);flex-wrap:wrap}
.mk-xlink>div{flex:1 1 420px}
.mk-xlink h2{font-size:clamp(1.5rem,2.6vw,2.1rem)}
.mk-xlink p{margin-top:12px;color:var(--ink-2);font-size:1rem;line-height:1.6;max-width:60ch}

/* ── toast ───────────────────────────────────────────────────────── */
.mk-toast{position:fixed;left:50%;bottom:26px;z-index:120;
  transform:translate(-50%,14px);opacity:0;pointer-events:none;
  max-width:min(560px,calc(100vw - 32px));
  padding:11px 20px;border-radius:var(--r-pill);background:var(--ink);color:#fff;
  font-size:.85rem;font-weight:600;box-shadow:var(--sh-3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  transition:opacity var(--tap) var(--ease),transform var(--tap) var(--ease)}
.mk-toast.on{opacity:1;transform:translate(-50%,0)}
@media (max-width:1040px){ .mk-toast{bottom:calc(72px + env(safe-area-inset-bottom,0px))} }

/* ── narrow ──────────────────────────────────────────────────────── */
@media (max-width:760px){
  .mk-bar .linebar-in{gap:10px}
  .mk-find{max-width:none;flex:1 1 100%;order:-1}
  .mk-prod-a{margin-left:0;width:100%}
  .mk-prod-a .mk-b{flex:1}

  /* 🚨 ONLY THE SEARCH AND CHIPS STAY PINNED ON A PHONE.
     The desktop stack is header + toolbar + family nav, and on a 390×844
     screen that measured 310px — 37% of the viewport permanently spent on
     chrome, on a page whose entire content is photographs. The family nav is
     the part that gives: it is still at the top of the page, and every family
     is also listed in the drawer, so nothing becomes unreachable. The toolbar
     stays because filtering a 535-image library from the bottom of it is the
     one thing you cannot do by scrolling back up.

     ⚠️ display:contents, NOT position:static. A sticky element only sticks
     while its CONTAINING BLOCK is on screen, and .mk-stick is a ~200px box —
     so merely un-sticking the wrapper left the toolbar sticking to a parent
     that scrolls away at 200px, and it vanished with it (measured: top
     -2405px). display:contents removes the wrapper's box altogether, which
     makes <main> the toolbar's containing block and lets it stick for the
     whole page. The wrapper carries no background or border, so it has
     nothing to lose by dissolving. */
  .mk-stick{display:contents}
  .mk-stick .linebar{position:sticky;top:var(--hdr-h);z-index:40}
  /* The toolbar's "Brand assets" shortcut is the third copy of that link on a
     phone — the hero CTA and the family nav both carry it — and every row it
     costs is a row of photographs. */
  .mk-bar .jump-print{display:none}
  .mk-bar .linebar-in{padding-block:9px}
}
@media (max-width:560px){
  /* §8, applied to this page's grid by name: 2-up at 390px, never 1-up. A
     single column makes a 500-image library feel like a short list. */
  .mk-shots{grid-template-columns:repeat(2,1fr)!important;gap:10px}
  .mk-shot-c{padding:8px 9px 6px}
  .mk-acts{padding:0 8px 8px;gap:5px}
  /* Taller on a phone than on a pointer device: these two are the whole point
     of the page and they are being hit with a thumb. */
  .mk-acts .mk-b{min-height:40px}
  .mk-b{padding:7px 8px;font-size:.72rem}
  /* At two-up the icon eats the label's room and both go illegible. The
     label is the word that matters; the glyph is the one that goes. */
  .mk-acts .mk-b .ic{display:none}
  .mk-stats{gap:10px 26px}
  .mk-logos{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  .mk-shot-m img,.mk-shot-x,.mk-toast{transition:none}
  .mk-shot:hover .mk-shot-m img{transform:none}
}

@media print{
  .hdr,.drawer,.drawer-scrim,.thumbbar,.linebar,.jump,.ladder,.ftr,.phero,
  .cost,.skip,.hero-cta,.endcta,.sheet-bar,.crumb{display:none!important}
  html,body{background:#fff!important}
  body{font-size:9.5pt;color:#000}
  @page{margin:11mm}

  /* The masthead is the only thing identifying the paper once it leaves. */
  .sheet-head{display:flex!important;align-items:flex-end;
    justify-content:space-between;gap:14px;padding:0 0 7px;margin:0 0 10px;
    border-bottom:1.5pt solid #000}
  .sheet-head-l b{font-size:13pt;font-weight:800}
  .sheet-head-l span,.sheet-head-r span{display:block;font-size:7.5pt;color:#333}
  .sheet-head-r{text-align:right}

  /* 🚨 break-inside:avoid belongs ONLY on things smaller than a page. It sat
     on .cat-block and .fam until 2026-08-10, and a category block holding 52
     tiles cannot fit on a sheet of Letter — so the engine pushed the whole
     block to a fresh page, overflowed it anyway, and left page one holding
     nothing but the masthead. Tiles are the only unit here that must not be
     split; the headings use break-after to avoid being orphaned. */
  .band,.cat-block,.fam{padding-block:0}
  .shell{max-width:none;padding:0}
  /* FIVE across, not four. At four the sheet ran two rows to a page behind
     the masthead and headings and wasted a third of every sheet; the line is
     147 items and a rep should not be handed nine pages of it. Five keeps the
     photograph big enough to tell two colourways apart, which is the only
     thing this grid has to do. */
  .grid,.grid[data-cols]{grid-template-columns:repeat(5,1fr)!important;gap:6px}
  /* 🚨 THE CELL NEEDS A FLOOR. Owner, improvement pass 5: "the line sheet the
     msrp is too close to the border of the box."
     Two faults, and the second was the real one. The gutters were 6px, about
     4.5pt, which is tight against a .75pt rule — but .tile-msrp also had NO
     BOTTOM MARGIN, and it is the last element in every tile that carries no
     display-pack chip. On those the price was sitting directly ON the bottom
     border of the cell. Its own border-top ran to within 4.5pt of the side
     rules as well, so the money row read as a box inside a box.
     The tile now carries the padding and the rows inherit it, which is also
     why they no longer each state their own: one number, one place. */
  .tile{border:.75pt solid #999;box-shadow:none;break-inside:avoid;background:#fff;
    padding-bottom:7pt}
  .tile-media{aspect-ratio:1;background:#fff}
  .tile-fam{font-size:5.5pt;padding:5px 9pt 0;color:#444;letter-spacing:.07em}
  .tile-name{font-size:8pt;padding:2px 9pt 0;line-height:1.16}
  .tile-sub{font-size:6.5pt;padding:1px 9pt 0;color:#333;line-height:1.25}
  .tile-msrp{margin:auto 9pt 0;padding:5pt 0 0;font-size:9pt;font-weight:800;
    border-top:.5pt solid #bbb}
  .tile-msrp em{font-size:5.5pt;color:#444;padding:1px 3px}
  /* When the pack chip IS present it becomes the floor, so the tile's own
     bottom padding would double up. Pull it back by the same amount. */
  .tile-pack{padding:3pt 9pt 0;font-size:6pt;color:#333}

  /* 🚨 The state chips come OFF the photograph on paper. Print drops their
     fill, so an outlined "Limited edition" was being drawn straight over a
     bag — see the note in tileHtml(). In flow they cost one short line and
     are legible every time. */
  .flags{position:static;flex-direction:row;flex-wrap:wrap;gap:3px;
    padding:5px 6px 0;pointer-events:auto}
  .flag{padding:1px 5px;font-size:5.5pt;font-weight:750}

  /* Filled chips print as white-on-white. Outline them instead. */
  .fam-n,.flag,.flag-out,.flag-ltd,.pill-21{background:transparent!important;
    color:#000!important;border:.5pt solid #666!important}

  /* The running footer — one per printed page. */
  .sheet-run{display:flex!important;justify-content:space-between;gap:12px;
    position:fixed;left:0;right:0;bottom:0;
    padding-top:3px;border-top:.5pt solid #ccc;
    font-size:6pt;color:#555;background:#fff}
  body{padding-bottom:16pt}
  .fam-head h3{font-size:11pt}
  .cat-h,.fam-head h3{break-after:avoid}
  /* The heading alone was kept with the next block, but the family blurb sits
     between it and the grid — so "FireBar DUO / Five paired-strain
     configurations…" printed at the foot of a page with its five tiles
     overleaf. Keep the whole head with what it introduces. */
  .fam-head{break-inside:avoid;break-after:avoid}
  .cat-h{font-size:12pt;margin-top:9px}
  .tile[data-oos] .tile-media img{filter:none}

  /* The no-photograph fallback on paper. Its colour field is dropped by the
     print pipeline, so the colourway name was left floating at 15px directly
     above the SAME name set in bold as the tile title — it read as a broken
     tile rather than an honest one. Small, muted and centred inside the box,
     it reads as what it is: this item has no photograph yet. */
  .swatch{border:none;align-items:center;justify-content:center;text-align:center;
    padding:8px;background:#fff!important}
  .swatch-n,.swatch-n.on-light{font-size:6.5pt;font-weight:650;color:#777!important;
    line-height:1.25}
  .swatch-m,.swatch-m.on-light{font-size:5.5pt;color:#999!important}
  a[href]::after{content:""}
  a{color:#000;text-decoration:none}

  /* ── the order sheet on paper ──────────────────────────────────────
     thead is a table-header-group, so the column headings reprint at the top
     of every page for free — which is the whole reason this is one table
     rather than one table per family. Rows must not split; a family heading
     must not be the last thing on a page. */
  .is-order .ordersheet{display:block!important;margin:0}
  .os-head{padding-bottom:6px;border-bottom:1.5pt solid #000}
  .os-head-l b{font-size:13pt}
  .os-head-l span{font-size:7.5pt;color:#333}
  .os-f b{font-size:6.5pt;color:#333}
  .os-f i{border-bottom:.75pt solid #666}
  .os-terms{margin:7px 0 9px;font-size:8pt;gap:4px 16px}
  .os-t{font-size:8pt}
  .os-t th,.os-t td{padding:3.2px 6px;border-bottom:.5pt solid #bbb}
  .os-t thead th{font-size:6.5pt;color:#333;border-bottom:1pt solid #000}
  .os-t thead{display:table-header-group}
  .os-t tr{break-inside:avoid}
  .os-t .os-fam th{padding-top:9px;font-size:9.5pt;border-bottom:.75pt solid #666;
    break-after:avoid;break-inside:avoid}
  .os-t .os-fam th span{font-size:6.5pt;color:#333}
  .os-t tbody td.os-q{border:.75pt solid #555;height:15pt}
  .os-sku{width:116px;font-size:7pt;color:#333;white-space:nowrap}
  .os-n em{font-size:6.5pt;color:#444}
  .os-oos .os-n,.os-oos .os-sku,.os-oos .os-p{color:#555}
  .os-foot{margin-top:12px;padding-top:8px;border-top:1pt solid #000;break-inside:avoid}
  .os-foot p{font-size:7pt;color:#333}
}

/* ═════════════════════════════════ IMPROVEMENT PASS 5 · COMPONENTS ══
   Everything below was added in one pass and each block names the owner note
   it answers. Appended rather than interleaved so the diff stays readable;
   nothing here overrides a rule above it by specificity accident — every
   selector is a new class. */

/* ── D · THE 15G NAME, SET AS DISPLAY TYPE ────────────────────────────
   "for the 15G hero section, we need to write the name 15G by Chocolate
   Tripz somewhere as a title type of look."
   The numeral carries the weight; the attribution sits under it on a rule, so
   the two read as one lockup rather than as a heading with a subtitle. The
   gold is the band's existing accent — no new colour enters the system for
   this. Tabular figures because 15G is a measurement, not a word. */
.fg-name{margin:18px 0 6px;display:flex;flex-direction:column;gap:2px;line-height:1}
.fg-name-n{font-size:clamp(3.4rem,8.5vw,6.2rem);font-weight:800;letter-spacing:-.055em;
  color:var(--gold);font-variant-numeric:tabular-nums;line-height:.86}
.fg-name-by{font-size:clamp(.8125rem,1.5vw,1rem);font-weight:700;letter-spacing:.17em;
  text-transform:uppercase;color:rgba(255,255,255,.72);padding-top:12px;
  border-top:1px solid rgba(233,185,73,.34);align-self:flex-start}
.band-head>.fg-name+h2{margin-top:20px}

/* ── D · the opener photograph ────────────────────────────────────────
   "THE OPENER (anywhere this is, make sure they know its for 15G and add a
   picture please)."

   🚨 IT IS A COLUMN, NOT A BANNER. The first attempt spanned the photo across
   the top of the block (grid-column:1/-1) and a screenshot of /displays/
   showed why that is wrong: at 1100px the offer card is full-shell width, so
   the picture rendered 1058×595 — bigger than the hero of most pages, above
   three lines of copy, on a card that is not the page's subject. It also
   upscaled, because the source is 941px tall.
   As a third column it is the size of an illustration: it fills the card's own
   height, states what the offer is, and leaves the copy and the buttons the
   room they had. Below 1024 it goes back across the top, capped, where a third
   column would squeeze the bullets to two words a line. */
/* 🚨 THE PHOTOGRAPH IS 16:9 AND IT STAYS 16:9. Stretching it to the card's
   height cropped the sides — and it cropped two BARS off a shot whose only job
   is showing all ten of them, on a block headlined "every 15G flavor". The
   column is sized so the natural ratio fills it, and the image is centred
   rather than stretched, so no future card height can crop it again. */
.fg-offer-ph{grid-template-columns:minmax(0,1.05fr) minmax(0,1.12fr) minmax(0,.86fr);
  align-items:center}
.fg-offer-m{border-radius:var(--r-md);overflow:hidden;
  background:rgba(255,255,255,.05);line-height:0;align-self:center}
.fg-light .fg-offer-m{background:var(--sand)}
.fg-offer-m img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover}
@media (max-width:1024px){
  .fg-offer-ph{grid-template-columns:1.15fr .85fr}
  .fg-offer-m{grid-column:1/-1}
  .fg-offer-m img{height:auto;aspect-ratio:21/9;max-height:260px}
}
@media (max-width:820px){
  .fg-offer-ph{grid-template-columns:1fr}
  .fg-offer-m img{aspect-ratio:16/9;max-height:none}
}

/* ── E · THE COUNTER ──────────────────────────────────────────────────
   "for the counter section, go hard on Candy Coated Chocolate Gems and
   Diamonds." Two products, each with its own photograph, its own reason and
   its own points. Deliberately NOT the .tile treatment: these are arguments,
   not inventory, so the photograph is wide and the copy has room to make one. */
.ctr-picks{display:grid;grid-template-columns:1fr 1fr;gap:clamp(20px,3vw,34px);
  margin-top:clamp(34px,4.4vw,54px)}
.ctr-p{display:flex;flex-direction:column;border-radius:var(--r-lg);overflow:hidden;
  background:linear-gradient(150deg,rgba(255,255,255,.085),rgba(255,255,255,.028));
  border:1px solid rgba(255,255,255,.15)}
.ctr-p-m{display:block;line-height:0;background:rgba(255,255,255,.05);overflow:hidden}
.ctr-p-m img{display:block;width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;
  transition:transform 700ms var(--spring)}
.ctr-p:hover .ctr-p-m img{transform:scale(1.035)}
.ctr-p-b{padding:clamp(20px,2.6vw,30px)}
.ctr-p-k{display:inline-flex;align-items:center;gap:8px;font-size:.6875rem;font-weight:800;
  letter-spacing:.13em;text-transform:uppercase;color:var(--gold)}
.ctr-p-b h3{margin:11px 0 0;font-size:clamp(1.14rem,1.9vw,1.42rem);font-weight:800;
  letter-spacing:-.032em;line-height:1.16}
.ctr-p-b h3 a{color:#fff;text-decoration:none}
.ctr-p-b h3 a:hover{text-decoration:underline;text-underline-offset:4px}
.ctr-p-b>p{margin:11px 0 0;color:rgba(255,255,255,.74);font-size:.9375rem;line-height:1.58}
.ctr-p-l{list-style:none;margin:16px 0 0;padding:0;display:flex;flex-direction:column;gap:8px}
.ctr-p-l li{display:flex;align-items:flex-start;gap:9px;font-size:.875rem;font-weight:600;
  color:rgba(255,255,255,.9);line-height:1.35}
.ctr-p-l .ic{flex:none;margin-top:3px;color:var(--gold)}
.ctr-pop{display:flex;align-items:flex-start;gap:10px;margin-top:clamp(24px,3vw,34px);
  font-size:.9375rem;color:rgba(255,255,255,.76);max-width:62ch}
.ctr-pop .ic{flex:none;margin-top:3px;color:var(--gold)}
@media (max-width:860px){.ctr-picks{grid-template-columns:1fr}}

/* ── C/H · THE BRAND-FAMILY MAP ───────────────────────────────────────
   "for the line section in the section is to highlight the brand family."
   This REPLACED the homepage horizontal family rail (see the note on .rail),
   so it carries the photographs the rail carried and adds the structure the
   section was arguing for: one parent, two groups, twelve labelled nodes.
   It wraps as a grid at every width — the thing it replaced was the site's
   most-used sideways scroller. */
.bfam{margin-top:clamp(30px,4vw,46px)}
.bf-root{display:inline-flex;align-items:center;gap:10px;margin:0;
  padding:9px 17px 9px 13px;border-radius:var(--r-pill);
  background:var(--ink);color:#fff;font-weight:800;letter-spacing:-.02em;font-size:.9375rem}
.bf-root-ic{color:var(--gold)}
.band-dark .bf-root{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2)}
/* The spine: one rule down from the parent chip, then a rule across each
   group heading. Drawn with borders rather than an SVG because it has to
   survive every wrap point, and a border always knows where its box ended. */
/* 🚨 THE GROUPS ARE SIZED BY HOW MANY NODES THEY HOLD, not 50/50.
   With two equal columns the four-node group wrapped 3 + 1 and the seven-node
   group wrapped 3 + 3 + 1 — two orphans, side by side, on a graphic whose
   whole job is looking orderly. `--n` is written by the template from the
   group's own length, so the widths stay proportional if a family is ever
   added or retired and nobody has to remember this rule. */
.bf-g{display:flex;flex-wrap:wrap;gap:clamp(24px,3vw,36px);
  margin-top:20px;padding-top:22px;position:relative}
.bf-grp{flex:var(--n,1) 1 0;min-width:264px}
/* basis 0 so the ratio, not the content, decides the width; min-width is
   what makes them wrap onto separate rows on a narrow window. */
.bf-g::before{content:"";position:absolute;left:34px;top:0;width:1.5px;height:22px;
  background:var(--hair-2);border-radius:2px}
.band-dark .bf-g::before{background:rgba(255,255,255,.24)}
.bf-h{margin:0 0 14px;font-size:.6875rem;font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);display:flex;align-items:center;gap:12px}
.bf-h::after{content:"";flex:1;height:1px;background:var(--hair)}
.band-dark .bf-h{color:rgba(255,255,255,.6)}
.band-dark .bf-h::after{background:rgba(255,255,255,.16)}
.bf-ns{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(158px,1fr))}
.bf-n{display:flex;flex-direction:column;text-decoration:none;color:inherit;
  border-radius:var(--r-md);overflow:hidden;background:var(--paper);
  border:1px solid var(--hair);
  transition:transform var(--tap) var(--spring),box-shadow var(--tap) var(--ease),
             border-color var(--tap) var(--ease)}
.bf-n:hover{transform:translateY(-3px);box-shadow:var(--sh-pick);border-color:var(--hair-2)}
.band-dark .bf-n{background:rgba(255,255,255,.055);border-color:rgba(255,255,255,.14)}
.band-dark .bf-n:hover{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.28)}
.bf-m{display:block;line-height:0;background:var(--sand);overflow:hidden}
.bf-m img,.bf-m .swatch{display:block;width:100%;height:auto;aspect-ratio:1;object-fit:cover}
.bf-b{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;
  gap:1px 9px;padding:11px 13px 13px;align-items:center}
.bf-ic{grid-row:1/3;align-self:center;color:var(--ink-3);flex:none}
.band-dark .bf-ic{color:var(--gold)}
.bf-t{font-weight:700;font-size:.875rem;letter-spacing:-.02em;line-height:1.2}
.bf-c{font-size:.75rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.band-dark .bf-c{color:rgba(255,255,255,.6)}
@media (min-width:900px){.bf-g{gap:clamp(28px,3.4vw,48px)}}
@media (max-width:540px){.bf-ns{grid-template-columns:repeat(2,1fr);gap:10px}}

/* ── H · /about/ ──────────────────────────────────────────────────────
   "make an about page". Three list shapes, all grids, so nothing on this page
   scrolls sideways either. */
.abt-cats{list-style:none;margin:clamp(30px,4vw,48px) 0 0;padding:0;display:grid;
  gap:clamp(16px,2.4vw,26px);grid-template-columns:repeat(auto-fit,minmax(238px,1fr))}
.abt-cat{padding:clamp(22px,2.6vw,30px);border-radius:var(--r-lg);
  background:var(--sand-3);border:1px solid var(--hair)}
.abt-cat-i{display:grid;place-items:center;width:46px;height:46px;border-radius:var(--r-md);
  background:var(--paper);border:1px solid var(--hair);color:var(--blue)}
.abt-cat h3{margin:16px 0 0;font-size:1.0625rem;font-weight:800;letter-spacing:-.028em;line-height:1.2}
.abt-cat p{margin:9px 0 0;font-size:.9375rem;line-height:1.58;color:var(--ink-2)}
.abt-why{list-style:none;margin:clamp(30px,4vw,48px) 0 0;padding:0;display:grid;
  gap:clamp(18px,2.6vw,30px);grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.abt-w{display:flex;gap:15px;align-items:flex-start}
.abt-w-i{flex:none;margin-top:3px;color:var(--blue)}
.abt-w h3{margin:0;font-size:1.0313rem;font-weight:800;letter-spacing:-.026em;line-height:1.24}
.abt-w p{margin:8px 0 0;font-size:.9375rem;line-height:1.58;color:var(--ink-2)}
.abt-reach{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,68px);align-items:center}
.abt-reach-m{border-radius:var(--r-lg);overflow:hidden;line-height:0}
.abt-reach-m img{display:block;width:100%;height:auto}
.abt-fig{list-style:none;margin:clamp(24px,3vw,34px) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:14px}
.abt-fig li{display:flex;align-items:center;gap:10px;padding:12px 18px;border-radius:var(--r-md);
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.15)}
.abt-fig .ic{color:var(--gold);flex:none}
.abt-fig b{font-size:1.375rem;font-weight:800;letter-spacing:-.04em;font-variant-numeric:tabular-nums}
.abt-fig span{font-size:.8125rem;color:rgba(255,255,255,.7);max-width:16ch;line-height:1.3}
@media (max-width:900px){.abt-reach{grid-template-columns:1fr}}

/* ── A · the lockup in the drawer, footer and print masthead ─────────── */
.drawer-brand .lockup{width:132px}
.ftr-logo .lockup{width:188px}
.sheet-head-l .lockup{width:150px;margin-bottom:6px}
/* The media kit previews its own marks. The reversed one needs the dark
   swatch or a white logo is previewed on white, which reads as a broken file. */
.mk-logo-m img{max-height:88px;width:auto;margin-inline:auto}

@media (prefers-reduced-motion:reduce){
  .ctr-p-m img,.bf-n{transition:none}
  .ctr-p:hover .ctr-p-m img,.bf-n:hover{transform:none}
}

@media print{
  /* The map and the counter picks are screen furniture. The sheet is a price
     list and neither belongs on it. */
  .bfam,.ctr-picks,.ctr-pop,.fg-offer-m{display:none!important}
  .sheet-head-l .lockup{width:132px}
}

/* ── coarse-pointer target floor ───────────────────────────────────────
   The dense desktop chrome earns its density with a fine pointer. On a touch
   primary device, every compact action that is not already a card-sized link
   gets a 44 CSS-pixel hit box. This deliberately lives after the narrow rules:
   the line and gallery rails keep their native inner scrolling, while their
   controls become reliably tappable without changing any fine-pointer layout. */
@media (pointer:coarse){
  :is(.brand,.nav-i>a,.mega-f,.mega-all,.drawer-brand,.drawer-tel,.btn,
      .hero-quiet,.fw-more,.tr a,.crumb a,.chip,.dens button,.jump-print,
      .jump-in a,.sheet-bar .btn-sm,.pdp-fam a,.gate-alt,.callus,.ftr-logo,
      .ftr-tel,.ftr-col a,.catalog-availability-link,.mk-find input,
      .mk-acts .mk-b,.mk-more,.mk-sw,
      .gal-arrow,.lb-nav,.ctr-p-b h3 a){
    min-inline-size:44px;
    min-block-size:44px;
  }

  /* Product-title links are inline in the desktop typography. Make their
     coarse-pointer hit box real without changing the fine-pointer line box. */
  .ctr-p-b h3 a{display:inline-flex;align-items:center}

  /* These controls are visually circular; set their real boxes instead of
     relying on a pseudo-element that can overlap adjacent gallery controls. */
  .gal-nav,.gal-zoom,.lb-x{inline-size:44px;block-size:44px}
  .gal-nav{margin-top:-22px}
}

/* The narrow lightbox rule intentionally compacts its arrows to 38px. Restore
   the touch floor and its visual centering only when a coarse primary pointer
   is also at that narrow viewport. */
@media (pointer:coarse) and (max-width:560px){
  .lb-nav{inline-size:44px;block-size:44px;margin-top:-22px}
}

/* The screen-only sheet has three actions in line mode and four in order mode.
   At phone width they are a compact action grid, not an unbreakable desktop row. */
@media (pointer:coarse) and (max-width:640px){
  .sheet-bar-a{flex:1 1 100%;min-width:0;flex-wrap:wrap;margin-left:0}
  .sheet-bar-a .btn{flex:1 1 calc(50% - 4px);min-inline-size:44px;white-space:normal}
}
