/* Self-hosted variable faces -- every page also preloads them, because an
   @font-face can't start downloading until the CSS is parsed. fonts/NOTICE.md */
@font-face{
  font-family:'Inter';
  src:url('../fonts/inter-var.woff2?v=1') format('woff2');
  font-weight:400 700;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Space Grotesk';
  src:url('../fonts/space-grotesk-var.woff2?v=1') format('woff2');
  font-weight:500 700;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'JetBrains Mono';
  src:url('../fonts/jetbrains-mono-var.woff2?v=1') format('woff2');
  font-weight:400 600;font-style:normal;font-display:swap;
}

:root{
  /* brand primitives + channel triplets for alpha derivatives -- see DESIGN.md */
  --ink:#0C1116;      --ink-rgb:12 17 22;
  --cyan-500:#16C0D9; --cyan-rgb:22 192 217;
  --slate:#808F9E;    --slate-rgb:124 138 153;   /* hairlines keep the original slate */
  --amber:#F2A63B;    --amber-rgb:242 166 59;
  --paper:#FBFBFC;    --paper-rgb:251 251 252;
  --ink2:#10161D;--graphite:#1B2632;--steel:#2C3B4A;
  --cyan-100:#D3F5FA;--cyan-300:#7CE0EE;--cyan-700:#0E8A9C;
  --mist:#DFE4E9;--fog:#AEB9C4;
  --line:rgb(var(--slate-rgb)/.22);--line-dark:rgb(var(--slate-rgb)/.16);
  /* fallbacks render during the swap window -- nearest per platform, not bare sans */
  --display:'Space Grotesk',system-ui,-apple-system,'Segoe UI',sans-serif;
  --body:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;

  /* Type scale -- only steps that repeat across sheets. DESIGN.md sec.6
     In rem, not px, so a reader who raises their browser's default font size
     gets larger text: page zoom always worked, but that setting did nothing
     while these were px. 1rem = 16px, so 0.8125rem is the 13px it replaced and
     nothing moves at the default.
     The display headings are the one exception and keep a px MINIMUM in their
     clamp() -- see .h-xl below. */
  --t-kicker:0.65625rem;   /* tracked uppercase label above a heading */
  --t-meta:0.71875rem;     /* mono meta: part numbers, table heads, tray chips */
  --t-fine:0.78125rem;     /* dense secondary: spec values, notes, captions */
  --t-small:0.8125rem;      /* rows, footer links, controls */
  --t-copy:0.90625rem;     /* card body copy */
  --track-kicker:.16em;

  /* surfaces, named by role */
  --surface:#fff;              /* elevated card face */
  --text-hi:#fff;              /* emphasis text ON a dark surface; --paper is body text there */
  --surface-sunk:#EDF0F2;      /* filter bar, segmented control track */
  --surface-quote:#EDF6F8;     /* article callout */
  --danger:#F27171;            /* form validation only */
  --accent-off:#0E7A8A;        /* primary action, unavailable */
  --accent-off-ink:#E8F6F8;    /* its label, 4.55:1 on --accent-off */

  /* elevation */
  --shadow-rest:0 1px 2px rgb(var(--ink-rgb)/.04),0 8px 28px rgb(var(--ink-rgb)/.05);
  --shadow-lift:0 2px 4px rgb(var(--ink-rgb)/.05),0 24px 48px rgb(var(--ink-rgb)/.10);
  --shadow-tray:0 12px 40px rgb(var(--ink-rgb)/.45);
  --shadow-seg:0 2px 8px rgb(var(--ink-rgb)/.18);

  /* motion */
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-inout:cubic-bezier(.65,0,.35,1);

  /* radii, named by what wears them */
  --r-pill:999px;--r-card:24px;--r-panel:28px;--r-tray:18px;
  --r-seg:20px;--r-input:12px;--r-chip:10px;

  /* Surface-dependent roles. The primitives above are measured against --ink;
     on white the same cyan reads 2.1:1, so anything that can render on either
     surface reads a role, never a primitive. Light values derived in OKLCH
     against #EDF0F2, the darkest light surface. Full rationale: DESIGN.md */
  --accent-on-light:#027787;--accent-hover-on-light:#06606D;--accent-line-on-light:#0094A8;
  --text-2-on-light:#606D7C;--index-on-light:#8F5B00;--index-line-on-light:#C37E05;

  /* defaults are the dark tier — body is --ink */
  --accent:var(--cyan-500);--accent-hover:var(--cyan-300);--accent-line:var(--cyan-500);
  --text-2:var(--slate);--index:var(--amber);--index-line:var(--amber);
}
/* a light band inside a dark page carries the light tier with it */
.on-light,.block.light{
  --accent:var(--accent-on-light);--accent-hover:var(--accent-hover-on-light);
  --accent-line:var(--accent-line-on-light);--text-2:var(--text-2-on-light);
  --index:var(--index-on-light);--index-line:var(--index-line-on-light);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-tap-highlight-color:transparent}
::selection{background:rgb(var(--cyan-rgb)/.3)}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{margin:0;font-family:var(--body);background:var(--ink);color:var(--paper);line-height:1.6;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
a{color:inherit;text-decoration:none}
a:hover{color:var(--accent-hover)}
/* Skip link (WCAG 2.4.1 Bypass Blocks). Every page repeats the same nav, so a
   keyboard user needs one stop that jumps past it. Hidden by moving it off the
   top edge rather than with display:none or visibility:hidden -- either of those
   would take it out of the tab order, which is the only place it needs to be.
   z-index clears the fixed .nav at 50. It is itself a target, so it carries the
   same 44px floor as the other controls.
   Deliberately not animated. A transform+transition version worked but its
   reveal could not be verified in a software-rendered browser -- the transition
   never advanced, leaving the link off-screen. A control whose only job is to
   become visible must not depend on a frame loop to do it, and instant is the
   better behaviour anyway: this is a keyboard shortcut, not a flourish. */
.skip{
  position:fixed;top:-100px;left:10px;z-index:70;
  display:inline-flex;align-items:center;min-height:44px;padding:0 18px;
  background:var(--graphite);color:var(--text-hi);
  border:1px solid var(--accent-line);border-radius:var(--r-chip);
  font-family:var(--body);font-size:var(--t-small);font-weight:500;
  box-shadow:var(--shadow-tray);
}
.skip:focus{top:10px}
/* The landmark takes focus programmatically via the skip link; it is not a
   control, so it must not paint a focus ring when it receives that focus. */
main[tabindex="-1"]:focus{outline:none}
button{font-family:inherit}
img{max-width:100%}

.wrap{max-width:1200px;margin:0 auto;padding:0 40px}
.narrow{max-width:820px;margin:0 auto;padding:0 40px;text-align:center}
/* 40px is 25% of a 320px screen; steps down twice */
@media(max-width:640px){.wrap,.narrow{padding:0 24px}}
@media(max-width:380px){.wrap,.narrow{padding:0 16px}}

/* viewport-fit=cover lets content run under the notch in landscape, so every
   horizontal gutter takes max(design, inset). LOAD-BEARING: a padding shorthand
   in a page sheet wins on source order and drops these. DESIGN.md sec.5 */
@supports(padding:max(0px)){
  .wrap,.narrow{padding-left:max(40px,env(safe-area-inset-left));padding-right:max(40px,env(safe-area-inset-right))}
  .navwrap,.mobilemenu{padding-left:max(40px,env(safe-area-inset-left));padding-right:max(40px,env(safe-area-inset-right))}
  @media(max-width:640px){
    .wrap,.narrow{padding-left:max(24px,env(safe-area-inset-left));padding-right:max(24px,env(safe-area-inset-right))}
  }
  @media(max-width:480px){
    .navwrap,.mobilemenu{padding-left:max(20px,env(safe-area-inset-left));padding-right:max(20px,env(safe-area-inset-right))}
  }
  @media(max-width:380px){
    .wrap,.narrow{padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right))}
  }
  .qtray{right:max(18px,env(safe-area-inset-right))}
}
.block{padding:160px 0;position:relative;scroll-margin-top:60px}
.block.light{background:var(--paper);color:var(--ink)}

.eyebrow{font-family:var(--body);font-size:0.75rem;font-weight:600;letter-spacing:.24em;text-transform:uppercase;color:var(--accent)}
/* Display headings: rem MAXIMUM, px MINIMUM, on purpose. The floor is what the
   heading falls back to on a narrow viewport, and in rem it scales with the
   reader's font setting -- at 200% that made .h-xl's floor 96px, which cannot
   fit "Precision," in the 342px a 390px phone has left after gutters, and the
   hero ran 130px off the side. A 48px floor is already far above any legibility
   threshold, so there is nothing to gain by scaling it and a broken layout to
   lose. The maximum still scales, so the headline does grow on a wide screen. */
.h-xl{font-family:var(--display);font-weight:600;font-size:clamp(48px,7.2vw,6.5rem);line-height:.98;letter-spacing:-.035em;margin:26px 0 0;text-wrap:balance}
.h-lg{font-family:var(--display);font-weight:600;font-size:clamp(38px,5vw,4.25rem);line-height:1.02;letter-spacing:-.03em;margin:22px 0 0;text-wrap:balance}
/* the hero's brand word, same solid cyan as the wordmark's SEC */
.solidcyan{color:var(--cyan-500)}
.sub{font-size:clamp(1.125rem,1.7vw,1.4375rem);color:var(--fog);max-width:56ch;margin:28px auto 0;line-height:1.55;text-wrap:pretty}
.light .sub{color:var(--steel)}

/* reveal choreography — gated on html.rv-ready, which only JS sets, so the 39
   .rv elements on the home page are visible by default. Ungated, opacity:0 was
   the whole page body with JS off, blocked, or IntersectionObserver missing.
   The class is set by an inline script in <head> so it lands before first paint
   (no flash of revealed content) and is withdrawn at DOMContentLoaded if
   reveal.js never ran.
   Every rule below is gated to the same specificity, including the reduced-motion
   escape hatch — ungated it would lose to html.rv-ready .rv and stop working. */
html.rv-ready .rv{opacity:0;transform:translateY(34px);transition:opacity .9s var(--ease-out),transform .9s var(--ease-out)}
html.rv-ready .rv.in{opacity:1;transform:none}
/* the stagger is gated too: left ungated it survives the gate being withdrawn as a
   zero-duration transition with a delay, which Chrome pins at the old opacity — the
   19 .d1-.d4 elements stayed invisible while the 20 without a delay class showed */
html.rv-ready .d1{transition-delay:.08s}html.rv-ready .d2{transition-delay:.16s}html.rv-ready .d3{transition-delay:.24s}html.rv-ready .d4{transition-delay:.32s}
@media(prefers-reduced-motion:reduce){html.rv-ready .rv{opacity:1;transform:none;transition:none}}

/* nav */
.nav{position:fixed;top:0;left:0;right:0;z-index:50;background:rgb(var(--ink-rgb)/.6);backdrop-filter:blur(20px) saturate(1.4);-webkit-backdrop-filter:blur(20px) saturate(1.4);border-bottom:1px solid rgb(var(--slate-rgb)/.1)}
.navwrap{max-width:1200px;margin:0 auto;padding:0 40px;height:56px;display:flex;align-items:center;justify-content:space-between}
.brandlink{display:flex;align-items:center;gap:10px;color:var(--text-hi)}
.brandlink svg{width:24px;height:24px}
.wmstack{display:flex;flex-direction:column;line-height:1.1}
.wm{font-family:var(--display);font-weight:700;font-size:1rem;letter-spacing:.14em;color:var(--text-hi)}
.wm .sec{color:var(--cyan-500)}
.submark{font-family:var(--body);font-size:0.5625rem;font-weight:500;letter-spacing:.03em;color:var(--text-2)}
.navlinks{display:flex;gap:34px}
.navlinks a{font-size:var(--t-fine);font-weight:500;letter-spacing:.02em;color:var(--fog)}
.navlinks a:hover{color:var(--text-hi)}
.navlinks a.here{color:var(--cyan-300)}
.navcta{font-size:0.75rem;font-weight:600;background:var(--cyan-500);color:var(--ink);padding:8px 18px;border-radius:var(--r-pill);transition:background .25s,transform .2s;white-space:nowrap}
.navcta:hover{background:var(--cyan-300);color:var(--ink)}
.navcta:active{transform:scale(.96)}
.fx{display:flex}.ac{align-items:center}.gap12{gap:12px}
/* visually hidden but still announced */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.menubtn{display:none;background:none;border:1px solid var(--steel);border-radius:999px;color:var(--text-hi);font-size:0.6875rem;letter-spacing:.08em;text-transform:uppercase;padding:7px 14px;cursor:pointer}
.mobilemenu{display:flex;flex-direction:column;background:rgb(var(--ink-rgb)/.97);border-bottom:1px solid var(--line-dark);padding:6px 40px 16px}
.mobilemenu[hidden]{display:none}
.mobilemenu a{font-size:0.875rem;color:var(--mist);padding:14px 0;border-bottom:1px solid var(--line-dark)}

/* buttons */
.btn{display:inline-flex;align-items:center;gap:8px;font-size:0.875rem;font-weight:600;padding:13px 28px;border-radius:var(--r-pill);border:1px solid transparent;cursor:pointer;transition:background .25s,border-color .25s,color .25s,transform .2s;white-space:nowrap}
.btn.primary{background:var(--cyan-500);color:var(--ink)}
.btn.primary:hover{background:var(--cyan-300);transform:translateY(-1px)}
.btn.ghost{border-color:rgb(var(--slate-rgb)/.45);color:var(--surface);background:rgb(var(--ink-rgb)/.35)}
.btn.ghost:hover{border-color:var(--cyan-500);color:var(--cyan-300)}
.btn.dark{background:var(--ink);color:var(--text-hi)}
.btn.dark:hover{background:var(--graphite);transform:translateY(-1px)}
.btn:active,.btn.primary:active,.btn.dark:active{transform:scale(.97)}
/* disabled still reads 4.5:1 and stops offering hover it won't honour */
.btn[disabled],.btn[aria-busy=true]{cursor:default;transform:none}
.btn.primary[disabled]{background:var(--accent-off);color:var(--accent-off-ink)}
.btn.primary[disabled]:hover{background:var(--accent-off);transform:none}
.btn[disabled]:active{transform:none}
.herocta{display:flex;gap:16px;justify-content:center;margin-top:38px;flex-wrap:wrap}

/* Shared component recipes -- written once here, page sheets keep only their
   deltas. Grouped selectors because CSS has no @extend. See DESIGN.md sec.4 */
.pcard,.appcard,.bcard,.relcard,.sidecard,.specpanel,.fempty{
  background:var(--surface);
  border-radius:var(--r-card);
  box-shadow:var(--shadow-rest);
}
/* dark sibling: a bordered panel on an --ink/--ink2 band, no elevation */
.jcard,.qcard{
  background:var(--graphite);
  border:1px solid var(--line-dark);
  border-radius:var(--r-card);
}
/* tracked uppercase kicker -- four sheets, only the colour differed. .eyebrow
   is the *section* kicker and stays a step up on purpose. DESIGN.md sec.6 */
.ptag,.appcard .tag,.jcard .tag,.bcard .tag{
  font-family:var(--body);font-weight:600;font-size:var(--t-kicker);
  letter-spacing:var(--track-kicker);text-transform:uppercase;color:var(--accent);
}
/* the lift is reserved for surfaces that navigate -- .appcard/.qcard stay put */
.pcard,.bcard,.relcard{transition:transform .35s var(--ease-out),box-shadow .35s}
.pcard:hover,.bcard:hover,.relcard:hover{transform:translateY(-6px);box-shadow:var(--shadow-lift)}

/* catalogue / product card (shared: home teaser card style not used, but pcard used on catalogue) */
.seghold{display:flex;justify-content:center;margin:56px 0 44px}
.seg{display:inline-flex;background:var(--surface-sunk);border-radius:var(--r-pill);padding:4px;gap:2px}
.seg button{font-size:var(--t-small);font-weight:500;color:var(--steel);background:none;border:none;border-radius:var(--r-pill);padding:9px 20px;cursor:pointer;transition:background .25s,color .25s,box-shadow .25s}
.seg button:hover{color:var(--ink)}
.seg button.on{background:var(--ink);color:var(--surface);box-shadow:var(--shadow-seg)}
.prodgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
/* min-width:0 -- grid items default to min-width:auto and overflow at 320px */
.pcard{min-width:0;padding:34px;display:flex;flex-direction:column}
.pcard-top{display:flex;justify-content:space-between;align-items:center}
.psize{font-family:var(--display);font-size:0.875rem;font-weight:600;color:var(--ink)}
.ppn{font-family:var(--mono);font-size:0.6875rem;color:var(--text-2)}
.ptorque{display:flex;align-items:baseline;gap:8px;margin-top:30px}
.ptorque .big{font-family:var(--display);font-weight:600;font-size:3.5rem;letter-spacing:-.03em;line-height:1;color:var(--ink)}
.ptorque .unit{font-family:var(--mono);font-size:0.875rem;color:var(--text-2)}
.plabel{font-size:var(--t-fine);color:var(--text-2);margin-top:8px}
/* A size that is orderable but has no published data sheet still has an answer
   for the headline slot — the answer is "On request". So it reuses .ptorque /
   .bigstat rather than inventing a notice component, and only steps the type
   down and drops to --text-2, which puts it below the cards that do carry a
   figure in exactly the scanning order an engineer wants. */
.ptorque.onreq .big,.bigstat.onreq .big{font-size:1.875rem;color:var(--text-2)}
/* label-and-value rows: .prow / .mrow / .srow share this skeleton */
.prow,.mrow,.srow{display:flex;justify-content:space-between;border-bottom:1px solid var(--line)}
.prows{margin-top:24px;border-top:1px solid var(--line)}
.prow{padding:10px 0;font-size:var(--t-small)}
.prow .l{color:var(--text-2)}
.prow .v{color:var(--ink);font-weight:500;font-family:var(--mono);font-size:var(--t-fine)}
.pcta{margin-top:24px;font-size:0.84375rem;font-weight:600;color:var(--accent);transition:transform .3s var(--ease-out),color .25s}
.pcta:hover{color:var(--accent-hover);transform:translateX(3px)}

/* footer */
.foot{background:var(--ink);color:var(--slate);padding:84px 0 36px;border-top:1px solid var(--line-dark)}
.ftop{display:grid;grid-template-columns:2.1fr 1.15fr 1fr 1.25fr 1.25fr;gap:44px 36px}
.fl{display:flex;align-items:center;gap:12px}
.fl svg{width:28px;height:28px}
.fwstack{display:flex;flex-direction:column;line-height:1.1}
.fw{font-family:var(--display);font-weight:700;font-size:0.9375rem;letter-spacing:.14em;color:var(--text-hi)}
.fw .sec{color:var(--cyan-500)}
.fsubmark{font-family:var(--body);font-size:0.5625rem;font-weight:500;letter-spacing:.03em;color:var(--slate)}
.fdesc{font-size:var(--t-small);line-height:1.7;color:var(--slate);margin:20px 0 16px;max-width:32ch}
.ftag{font-family:var(--mono);font-size:0.6875rem;letter-spacing:.1em}
.foot .amb{color:var(--amber)}
.fcol{display:flex;flex-direction:column;gap:11px}
.fcol h3{font-family:var(--body);font-size:var(--t-kicker);font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:var(--slate);margin:0 0 8px}
.fcol a,.fcol .faddr{font-size:var(--t-small);color:var(--fog);line-height:1.5}
.fcol a:hover{color:var(--cyan-300)}
.fcol .fall{color:var(--cyan-500);font-weight:600;font-size:var(--t-fine);margin-top:6px;transition:transform .3s var(--ease-out),color .25s}
.fcol .fall:hover{color:var(--cyan-300);transform:translateX(3px)}
.faddr{color:var(--slate)}
.fbot{display:flex;justify-content:space-between;align-items:center;gap:14px;flex-wrap:wrap;margin-top:68px;padding-top:28px;border-top:1px solid var(--line-dark);font-size:0.75rem;color:var(--slate)}
.fbot a{color:var(--slate)}
.fbot a:hover{color:var(--cyan-300)}
@media(pointer:coarse){.fbot a{display:inline-block;padding:8px 4px;margin:-8px 0}}

/* --accent-line, not brand cyan: a 2px ring needs 3:1 on both surfaces */
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--accent-line);outline-offset:2px}

/* 68px of padding in a 320px card leaves no measure for the spec rows */
@media(max-width:420px){.pcard{padding:26px 22px}}

@media(max-width:980px){.prodgrid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:980px){.ftop{grid-template-columns:1fr 1fr;gap:38px 30px}.fbrand{grid-column:1/-1}}
@media(max-width:860px){.navlinks{display:none}.menubtn{display:inline-flex}.block{padding:110px 0}}
@media(max-width:480px){.ftop{grid-template-columns:1fr}}
@media(max-width:640px){.prodgrid{grid-template-columns:1fr}.seg{flex-wrap:wrap;border-radius:var(--r-seg);justify-content:center}}
@media(max-width:480px){.navcta{display:none}.navwrap{padding:0 20px}}

/* Input method, not screen width -- a touchscreen laptop at 1440px is still a
   finger. Raises the controls you tap to change state; navigation link lists
   stay small on purpose (they clear WCAG 2.5.8 via spacing). DESIGN.md sec.5 */

/* Coarse pointer — finger or stylus. Raise the things you tap to *change state*
   to the 44px comfortable minimum. Navigation link lists are deliberately left
   alone: they already clear WCAG 2.5.8 via the spacing exception (verified at
   320-1440px), they sit in easy-to-hit vertical stacks, and inflating 30-odd
   footer links would add hundreds of pixels of scroll for no real gain. */
@media(pointer:coarse){
  .menubtn{min-height:44px;padding:11px 18px}
  .navcta{min-height:44px;padding:12px 20px}
  .btn{min-height:44px}
  .seg button{min-height:44px;padding:12px 20px}
  .qadd{min-height:44px;padding:12px 16px}
  .pcta{min-height:44px;display:inline-flex;align-items:center}
  .qclear,.qrm{min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  /* denser than 44px on purpose: three controls share one narrow row */
  .qstep button{width:36px;height:36px}
  .qn{min-width:26px}
}

/* a tap on iOS applies :hover and it sticks -- kill the lift, keep :active */
@media(hover:none){
  .pcard:hover,.jcard:hover,.bcard:hover,.relcard:hover{transform:none}
  .pcta:hover,.fcol .fall:hover{transform:none}
  .btn.primary:hover,.btn.dark:hover{transform:none}
}

/* quote list — floating tray + SKU chips (shared by tray and RFQ form) */
/* fixed, so anything past the fold inside it is unreachable -- 63 SKUs measured
   2889px against an 844px screen. Cap to viewport, scroll the list within. */
.qtray{position:fixed;right:18px;bottom:max(18px,env(safe-area-inset-bottom));z-index:60;background:var(--graphite);border:1px solid var(--line-dark);border-radius:var(--r-tray);padding:16px;width:min(320px,calc(100vw - 36px));box-shadow:var(--shadow-tray);color:var(--paper);display:flex;flex-direction:column;max-height:min(70vh,calc(100vh - 92px))}
.qtray[hidden]{display:none}
.qhead{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;flex-shrink:0}
.qhead b{font-family:var(--display);font-size:0.875rem;font-weight:600;color:var(--text-hi)}
.qclear{background:none;border:none;color:var(--slate);font-size:0.75rem;font-weight:500;cursor:pointer;padding:2px 4px}
.qclear:hover{color:var(--text-hi)}
.qskus{display:flex;flex-wrap:wrap;gap:6px}
.qsku{display:inline-flex;align-items:center;gap:4px;font-family:var(--mono);font-size:var(--t-meta);color:var(--cyan-300);background:rgb(var(--cyan-rgb)/.1);border:1px solid rgb(var(--cyan-rgb)/.28);border-radius:var(--r-pill);padding:4px 6px 4px 10px}
.qsku button{background:none;border:none;color:var(--slate);cursor:pointer;font-size:0.875rem;line-height:1;padding:0 4px}
.qsku button:hover{color:var(--text-hi)}
.qtray .qgo{width:100%;justify-content:center;margin-top:12px;font-size:var(--t-small);padding:11px 18px;flex-shrink:0}

/* tray line items; min-height:0 lets this flex child shrink and scroll */
.qlist{display:flex;flex-direction:column;gap:6px;overflow-y:auto;min-height:0;overscroll-behavior:contain;scrollbar-width:thin}
.qrow{display:flex;align-items:center;gap:8px;font-family:var(--mono);font-size:var(--t-meta);color:var(--cyan-300);background:rgb(var(--cyan-rgb)/.1);border:1px solid rgb(var(--cyan-rgb)/.28);border-radius:var(--r-input);padding:6px 6px 6px 10px}
.qskuname{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.qrm{background:none;border:none;color:var(--slate);cursor:pointer;font-size:0.875rem;line-height:1;padding:0 2px}
.qrm:hover{color:var(--text-hi)}

/* quantity stepper — shared by the tray rows and the product-page sidecard */
.qstep{display:inline-flex;align-items:center;gap:2px;background:rgb(255 255 255/.06);border-radius:var(--r-pill);padding:2px;flex-shrink:0}
.qstep button{background:none;border:none;color:var(--cyan-300);cursor:pointer;font-size:var(--t-small);line-height:1;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:999px}
.qstep button:hover{background:rgb(var(--cyan-rgb)/.18);color:var(--surface)}
.qn{min-width:18px;text-align:center;color:var(--text-hi);font-weight:600;font-family:var(--mono);font-size:0.75rem}
