/* ============================================================================
   ACH Inc. - "World-class appliances, delivered across Guyana."
   Deep Harbor / "Harbor Pure": navy-forward, porcelain surfaces, an ALL-COOL
   accent layer (no gold / no warm hue - the only warm exception is --sun, scoped to /employment). Semantic roles (60-30-10): surfaces ~60%
   (paper/card), navy structure ~30%, cool accents ~10%. Every body/UI text pair
   meets WCAG AA - see scripts/contrast-test.mjs. Accent roles:
     --signal (brighter blue) = active/selected + recruitment; FILLS take white text.
     --crimson = sale/discount FILLS (white text); --crimson-bright = sale TEXT on dark.
     --whatsapp green = the "good option" signal (vs the crimson import negatives).
     --sky / --sky-bright = cool ornament (lines/dividers) + on-dark text accents.
   On-dark accent text uses the -bright values; an accent color is never plain TEXT
   on a light surface (see the guard in contrast-test.mjs).
   Type (Fontjoy): Titles Noto Sans · UI/subtitles Asap · Paragraphs Maitree.
   ============================================================================ */
:root {
  --paper:    #F5F7FA;         /* 60% dominant surface (cool porcelain) */
  --paper-2:  #EAF0F7;
  --hero-card-bg: #E4EBF4;   /* soft cool navy-tinted band under the hero (not stark white) */
  --card:     #FFFFFF;
  --ink:      #16202B;         /* body text */
  --muted:    #5A6B7B;         /* secondary text (AA on all surfaces) */
  --navy:     #003060;         /* 30% secondary structure / primary buttons */
  --navy-2:   #06243F;
  --azure:    #1B6299;         /* interactive accent: links, focus, hover (AA >=6:1) */
  --sky:      #6FA8D6;
  --signal:   #2A78BE;         /* active/selected + recruitment + count badges; FILL takes white text (AA 4.6:1); bars/dots/outlines */
  --crimson-bright:#F28B82;    /* sale/discount TEXT on dark navy (deals eyebrow/pct) - AA >=4.7:1 on #013a73 */
  --sky-bright:#7FB4DD;        /* cool decorative TEXT/link/heading/check accent on dark navy - AA >=5.1:1 on #013a73 */
  --whatsapp: #0E7A3E;         /* WhatsApp button fill (white text AA 5.4:1) */
  --whatsapp-bright:#25D366;   /* WhatsApp brand-green glyph: light surfaces + the .wa-inline icon link on dark navy (~5.7:1) */
  --crimson:  #9E2B25;         /* reserved semantic alert / sale only */
  --sun:      #FFC72C;         /* /employment ONLY: the recruitment flyer's warm yellow - navy-2 text on it 10:1, as display text on #013a73 7.3:1. The one warm exception to Harbor Pure; never a fill under white text, never used off the hiring page */
  --line:     rgba(6,36,63,0.12);
  --line-2:   rgba(6,36,63,0.20);
  --radius:   14px;
  --shadow:   0 30px 60px -34px rgba(6,36,63,0.45), 0 8px 22px -14px rgba(6,36,63,0.25);
  --shadow-sm:0 12px 30px -18px rgba(6,36,63,0.35);
  --z-toast:  1000;            /* toasts: above every overlay/modal (highest is .adm-modal-back at 200); fallback when the Popover top layer is unsupported */
  --font:     'Asap', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;   /* UI / subtitle tier */
  --display:  'Noto Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; /* titles / headings */
  --prose:    'Maitree', Georgia, 'Times New Roman', serif;                       /* paragraph / long-form copy */

  /* Backward-compatible aliases for inline styles on cart/success pages */
  --accent:   var(--azure);
  --accent-2: var(--navy);
  --panel:    var(--card);
  --panel-2:  var(--paper-2);
  --danger:   var(--crimson);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--paper); color: var(--ink); font-family: var(--font); -webkit-font-smoothing: antialiased; }
body { overflow-x: hidden; line-height: 1.6; }
/* Storefront pages declare viewport-fit=cover so the phone tab bar and bottom bars can
   pad themselves clear of the iPhone home indicator (env(safe-area-inset-bottom)). That
   also lets a landscape notch overlap the page, so the page and every full-width fixed
   bar are inset by it here. All of these are 0 on a device without a notch. */
body, .nav { padding-left: env(safe-area-inset-left, 0px); padding-right: env(safe-area-inset-right, 0px); }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; height: auto; }
button, input, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
h1, h2, h3, h4 { font-family: var(--display); font-weight: 600; line-height: 1.08; letter-spacing: -0.015em; margin: 0; }
/* Paragraph / long-form copy - Maitree (Fontjoy paragraph font) */
.prose p, .page-lead, .hero-sub, .pdp-overview p, .info-card p, .callout p { font-family: var(--prose); }
input, select {
  background: var(--card); border: 1px solid var(--line); color: var(--ink);
  padding: 12px 14px; border-radius: 10px; outline: none; transition: border-color .2s, box-shadow .2s;
}
input:focus, select:focus { border-color: var(--azure); box-shadow: 0 0 0 3px rgba(30,111,176,.15); }
::selection { background: rgba(30,111,176,.2); }

.container { max-width: 1240px; margin: 0 auto; padding: 0 28px; }

/* ---- Nav ---------------------------------------------------------------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  backdrop-filter: blur(16px) saturate(140%); -webkit-backdrop-filter: blur(16px) saturate(140%);
  background: rgba(246,248,251,0.72);
  border-bottom: 1px solid transparent;
  transition: background .3s, border-color .3s, box-shadow .3s;
}
.nav.scrolled { background: rgba(255,255,255,0.92); border-bottom-color: var(--line); box-shadow: 0 8px 30px -22px rgba(6,36,63,.5); }
/* Vertical padding is trimmed from 12px to 9px so the enlarged 62px badge (was
   52px) lifts the bar height by only ~4px while keeping equal breathing room. */
.nav-inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 9px 28px; max-width: 1440px; margin: 0 auto; }
.brand { display: flex; align-items: center; gap: 14px; min-height: 44px; min-width: 44px; }
.brand-mark { width: 62px; height: 62px; border-radius: 50%; flex: 0 0 auto; box-shadow: 0 6px 16px -8px rgba(0,48,96,.6); }
.brand-name { font-family: var(--display); font-weight: 600; font-size: 19px; color: var(--navy); letter-spacing: -0.01em; white-space: nowrap; }
.nav-links { display: flex; gap: 26px; font-size: 14.5px; color: var(--muted); font-weight: 500; }
.nav-links a { position: relative; padding: 4px 0; transition: color .2s; }
.nav-links a::after { content: ''; position: absolute; left: 0; right: 100%; bottom: -2px; height: 2px; background: var(--azure); transition: right .25s ease; }
.nav-links a:hover { color: var(--navy); }
.nav-links a:hover::after, .nav-links a.active::after { right: 0; }
.nav-links a.active { color: var(--navy); font-weight: 600; }
/* "We're hiring" stays in the primary bar as just the words; a subtle --signal
   underline periodically draws itself in and fades - a gentle, recognizable
   "there's something here" cue for a job-seeker, without a loud badge or dot. */
.nav-hiring::before {
  content: ''; position: absolute; left: 0; bottom: -2px; height: 2px; width: 100%;
  background: var(--signal); border-radius: 2px;
  transform: scaleX(0); transform-origin: left center;
  animation: nav-hiring-underline 6s ease-in-out infinite;
}
.nav-hiring:hover::before { animation: none; transform: scaleX(0); }   /* hover shows the standard underline instead */
@keyframes nav-hiring-underline {
  0%, 68% { transform: scaleX(0); opacity: 1; }
  80%, 90% { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; }
}

/* ---- Shop dropdown (collapses the department links into one item) -------- */
.nav-shop { position: relative; display: flex; align-items: center; }
.nav-shop-trigger {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; cursor: pointer; padding: 4px 0;
  font-family: inherit; font-size: 14.5px; font-weight: 500; color: var(--muted);
  position: relative; transition: color .2s;
}
.nav-shop-trigger::after { content: ''; position: absolute; left: 0; right: 100%; bottom: -2px; height: 2px; background: var(--azure); transition: right .25s ease; }
.nav-shop-trigger:hover, .nav-shop-trigger.active { color: var(--navy); }
.nav-shop-trigger.active { font-weight: 600; }
/* Subtle azure shimmer that sweeps across the "Shop" label once every ~5s to
   draw the eye to the primary entry point (text-clipped gradient, so only the
   word shimmers - the caret keeps the trigger's own color). */
.nav-shop-label {
  background: linear-gradient(100deg, var(--muted) 0%, var(--muted) 45%, var(--azure) 50%, var(--muted) 55%, var(--muted) 100%);
  background-size: 300% 100%; background-position: 0 0;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  animation: nav-shop-shimmer 5s ease-in-out infinite;
}
@keyframes nav-shop-shimmer {
  0% { background-position: 0 0; }
  16% { background-position: 100% 0; }
  100% { background-position: 100% 0; }
}
/* On hover/focus/active the trigger goes solid navy - drop the shimmer + clip. */
.nav-shop:hover .nav-shop-label, .nav-shop:focus-within .nav-shop-label, .nav-shop-trigger.active .nav-shop-label {
  background: none; -webkit-text-fill-color: var(--navy); animation: none;
}
.nav-shop:hover .nav-shop-trigger::after,
.nav-shop:focus-within .nav-shop-trigger::after,
.nav-shop-trigger.active::after { right: 0; }
.nav-caret { flex: 0 0 auto; margin-top: 1px; transition: transform .25s ease; }
.nav-shop:hover .nav-caret, .nav-shop:focus-within .nav-caret, .nav-shop.open .nav-caret { transform: rotate(180deg); }
.nav-menu {
  position: absolute; top: calc(100% + 12px); left: 50%; transform: translate(-50%, -6px);
  min-width: 212px; padding: 8px; display: flex; flex-direction: column; gap: 2px;
  background: rgba(255,255,255,.98); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  border: 1px solid var(--line-2); border-radius: 14px;
  box-shadow: var(--shadow); z-index: 60;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .2s ease, transform .2s ease, visibility .2s;
}
.nav-menu::before { content: ''; position: absolute; left: 0; right: 0; top: -12px; height: 12px; }  /* hover bridge */
.nav-shop:hover .nav-menu, .nav-shop:focus-within .nav-menu, .nav-shop.open .nav-menu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translate(-50%, 0);
}
.nav-menu a {
  display: flex; align-items: center; min-height: 42px; padding: 9px 14px; border-radius: 9px;
  font-size: 14.5px; font-weight: 500; color: var(--ink); white-space: nowrap;
  transition: background .15s, color .15s;
}
.nav-menu a::after { display: none; }
.nav-menu a:hover { background: var(--paper-2); color: var(--navy); }
.nav-menu a.active { color: var(--navy); font-weight: 600; background: var(--paper-2); }
.nav-menu-all { margin-top: 4px; padding-top: 13px; border-top: 1px solid var(--line); }
/* `.nav-menu a` qualifies these (0,1,1): the bare class alone (0,1,0) loses to the
   `.nav-menu a { color: var(--ink) }` rule above and the crimson never applied. */
.nav-menu a.nav-menu-clearance { color: var(--crimson); font-weight: 600; }
.nav-menu a.nav-menu-clearance:hover, .nav-menu a.nav-menu-clearance.active { color: var(--crimson); }

.nav-actions { display: flex; align-items: center; gap: 10px; }
.icon-btn {
  position: relative; padding: 9px 13px; border-radius: 100px; border: 1px solid var(--line); color: var(--navy);
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; font-size: 14px; font-weight: 500;
  min-height: 44px; min-width: 44px;     /* comfortable touch target */
  transition: border-color .2s, background .2s, color .2s;
}
.icon-btn:hover { border-color: var(--azure); background: var(--card); }
/* Marks the account pill while on any of the account pages. --signal draws the outline
   (an outline is one of its sanctioned roles) while the label stays --navy, like every
   other active nav item: --signal is FILL-only and is never plain text on a light
   surface. Guard: npm run test:contrast. */
.account-btn.active { border-color: var(--signal); color: var(--navy); font-weight: 600; }
/* Account rides the ACTIONS bar on desktop (the cart/search convention) and the
   DROPDOWN on mobile - never both. A fourth control does not fit the 320px bar: it
   collides with the brand name, which `body { overflow-x: hidden }` hides from the
   overflow gate, so this is eyeballed, not measured. The mobile swap is at 900px, the
   width where the hamburger takes over. */
.nav-account-mobile { display: none; }
.cart-count {
  position: absolute; top: -7px; right: -7px;
  background: var(--signal); color: #fff;
  border-radius: 100px; padding: 2px 7px; font-size: 11px; font-weight: 700;
  min-width: 20px; text-align: center; display: none; box-shadow: 0 4px 10px -3px rgba(42,120,190,.55);
}
.cart-count.show { display: inline-block; }
.nav-toggle { display: none; }            /* desktop: links are inline, no hamburger */
.nav-toggle .i-close { display: none; }   /* X icon shown only while the menu is open */

/* ---- Nav search (icon that expands into an input) ----------------------- */
.nav-inner { position: relative; }        /* positioning context for the expanding field */
.nav-search { position: relative; display: flex; align-items: center; }
.nav-search-input {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  width: 0; min-width: 0; padding: 0; height: 44px; border-radius: 100px;
  border: 1px solid transparent; background: var(--card); color: var(--ink);
  opacity: 0; pointer-events: none; z-index: 1;
  transition: width .28s ease, opacity .2s ease, padding .28s ease, border-color .2s ease, box-shadow .2s ease;
}
.nav.search-open .nav-search-input {
  width: clamp(180px, 24vw, 300px); padding: 0 50px 0 16px; opacity: 1; pointer-events: auto;
  border-color: var(--line-2); box-shadow: var(--shadow-sm);
}
.nav-search-btn { position: relative; z-index: 2; }   /* stays clickable above the field */
.nav.search-open .nav-search-btn { border-color: transparent; background: transparent; }

/* ---- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 14px 24px; border-radius: 100px; font-weight: 600; font-size: 15px;
  min-height: 48px;     /* comfortable touch target */
  transition: transform .2s, box-shadow .2s, background .2s, border-color .2s, color .2s;
  border: 1px solid transparent; white-space: nowrap;
}
.btn:hover { transform: translateY(-1px); }
.btn:disabled, .btn.is-disabled { opacity: .45; pointer-events: none; transform: none; cursor: not-allowed; }
.btn-primary { background: var(--navy); color: #fff; }
.btn-primary:hover { background: var(--azure); }
.btn-ghost { background: transparent; border-color: var(--line-2); color: var(--navy); }
.btn-ghost:hover { border-color: var(--navy); background: var(--card); }

/* ---- Hero --------------------------------------------------------------- */
/* Landing = nav (fixed overlay) + hero + brand strip fill the first screen. */
.landing { min-height: 100svh; display: flex; flex-direction: column; position: relative; }
.hero {
  position: relative; flex: 1 1 auto; display: flex; align-items: center;
  padding: 104px 0 40px; overflow: hidden;
  background:
    radial-gradient(circle at 88% 8%, rgba(111,168,214,.18), transparent 42%),
    radial-gradient(circle at 0% 60%, rgba(196,154,72,.08), transparent 40%),
    linear-gradient(180deg, #FBFDFF 0%, var(--paper) 100%);
}
.hero > .container { width: 100%; }
.hero-copy { position: relative; z-index: 2; max-width: 780px; }
h1.hero-title {
  font-family: var(--display); font-size: clamp(36px, 5.2vw, 62px); line-height: 1.04;
  letter-spacing: -.015em; margin: 20px 0 22px; font-weight: 700; color: var(--navy-2); max-width: 22ch;
  text-transform: uppercase;
}
.hero-title .grad { color: var(--azure); }  /* duotone = same face, azure colour only */
.hero-sub { max-width: 50ch; color: var(--muted); font-size: clamp(15.5px, 1.2vw + 12px, 18px); line-height: 1.65; margin: 0 0 30px; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.hero-card {
  margin-top: 0; padding-top: 14px;   /* sits tight under the hero - no top gap/divider */
  /* Column gap trimmed from 56px: the bigger value text (below) needs the reclaimed
     width to keep all four cards on one row at 1280/1440 - the row was already within
     13px of wrapping to two lines before this change. */
  display: flex; flex-wrap: wrap; justify-content: center; gap: 14px 24px; font-size: 14px; color: var(--muted);
}
.hero-card .hc { display: flex; align-items: center; gap: 12px; min-height: 44px; color: var(--muted); }
.hero-card a.hc { transition: color .2s; }
.hero-card a.hc:hover { color: var(--navy); }
.hero-card a.hc:hover .hc-ico { background: var(--navy); color: #fff; }
.hero-card .hc-ico { width: 40px; height: 40px; flex: 0 0 auto; border-radius: 50%; background: var(--paper-2); color: var(--navy); display: grid; place-items: center; transition: background .2s, color .2s; }
/* Value/label sizes are up two/one steps from 15px/10.5px (captain: bigger text without
   growing the strip) - line-height is tightened to hold the text block inside the
   40px icon + 44px min-height floor that already sets each card's rendered height. */
.hero-card .hc-txt { display: flex; flex-direction: column; line-height: 1.2; gap: 1px; }
.hero-card .hc b { font-family: var(--font); font-weight: 700; font-size: 11.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--azure); }
.hero-card .hc-txt > span { color: var(--ink); font-size: 17px; font-weight: 500; }

/* Hero stage - the rotating 3D wireframe that morphs through our appliances. */
.hero-grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,.82fr); gap: 44px; align-items: center; }
.hero-stage { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.hero-stage::before { content: ''; position: absolute; width: 72%; height: 60%; border-radius: 50%; background: radial-gradient(circle, rgba(111,168,214,.16), transparent 70%); filter: blur(12px); pointer-events: none; }
#hero-canvas { position: relative; z-index: 1; width: 100%; height: clamp(320px, 46vh, 460px); display: block; }
.hero-cap { position: relative; z-index: 1; text-align: center; margin-top: 4px; }
.hero-cap .pre { font-size: 11px; letter-spacing: .22em; text-transform: uppercase; color: var(--azure); font-weight: 700; }
#hero-appliance { font-family: var(--display); font-size: clamp(22px, 4vw, 28px); color: var(--navy-2); margin-top: 4px; font-weight: 600; }
.hero-dots { display: flex; gap: 9px; justify-content: center; margin-top: 14px; position: relative; z-index: 1; }
.hero-dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--line-2); transition: transform .3s, background .3s; }
.hero-dots i.on { background: var(--azure); transform: scale(1.5); }

/* Background map: pushed back, anchored right, top ~2/3 showing; right & bottom
   edges fade out cleanly (mask) as the cropped outline nears the hero edges. */
.hero-map {
  position: absolute; z-index: 0; top: 10%; right: 4%;
  height: 94%; aspect-ratio: 0.678; pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 60%, transparent 88%), linear-gradient(to right, #000 52%, transparent 82%);
          mask-image: linear-gradient(to bottom, #000 60%, transparent 88%), linear-gradient(to right, #000 52%, transparent 82%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
}
.hero-map .gy { display: block; width: 100%; height: 100%; overflow: visible; }
.gy-region { fill: rgba(30,111,176,.045); stroke: rgba(30,111,176,.53); stroke-width: .7; stroke-linejoin: round; }
.gy-r4 { fill: rgba(27,98,153,.18); stroke: var(--azure); stroke-width: 1.2; }
.gy-link { stroke: rgba(30,111,176,.14); stroke-width: .4; }
.gy-pulse { fill: var(--azure); filter: drop-shadow(0 0 1.8px rgba(27,98,153,.9)); }
.gy-glow { fill: var(--azure); }

/* ---- Image-led hero carousel ------------------------------------------- */
/* Full-width banner carousel (generated scenes) with HTML/CSS text overlays.
   Slides are stacked and cross-faded, so nothing sits off-canvas (overflow-safe). */
/* Full-bleed immersive hero: the carousel spans the whole viewport width (100%,
   NOT 100vw, so the scrollbar can't cause horizontal overflow) and fills the
   height under the fixed nav. Nav clearance is the only top padding; no side
   padding (edge-to-edge); block flow so the contact-card band sits below. */
.hero-band {
  position: relative; padding: 72px 0 0;
  /* Desktop: flex-grow so the hero fills exactly the viewport space LEFT OVER after
     the contact-card band + brand strip - i.e. nav + hero + card + brand all fit in
     one screen (`.landing` is a 100svh flex column). No magic numbers. */
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
  background:
    radial-gradient(circle at 88% 8%, rgba(111,168,214,.16), transparent 44%),
    radial-gradient(circle at 0% 70%, rgba(196,154,72,.07), transparent 42%),
    linear-gradient(180deg, #FBFDFF 0%, var(--paper) 100%);
}
.hero-carousel {
  position: relative; width: 100%;
  flex: 1 1 auto; min-height: 420px;    /* fills the band; floor for short screens */
  overflow: hidden; background: var(--navy-2); outline: none;
  /* sleek full-bleed: sharp edges, no radius, no shadow. A shorter band than a full
     100svh means object-fit:cover crops TOP/BOTTOM not the sides, so nearly the full
     21:9 banner WIDTH shows (captain: "see more of the width"). */
  /* Double-tap to pause/resume (see hero-carousel.js) must not also trigger the
     browser's default double-tap-to-zoom gesture. */
  touch-action: manipulation;
}
.hero-carousel:focus-visible { box-shadow: inset 0 0 0 3px rgba(30,111,176,.6); }
/* Portrait tablet/phone: fixed, taller-but-reasonable heights (no flex-fill) so the
   landscape banner variant (21:9 -> 3:2 -> 4:3 via <picture>) fills without an
   extreme centre-crop - there are no portrait variants. */
@media (max-width: 1024px) {
  .hero-band { display: block; flex: 0 0 auto; }
  .hero-carousel { flex: 0 0 auto; min-height: 64svh; }
}
@media (max-width: 640px)  { .hero-carousel { min-height: 56svh; } }
/* The contact card sits in its own band just below the full-bleed hero: a soft
   cool-tint bg, tight under the hero (margin-top:0) with internal breathing room. */
.hero-card-band { margin-top: 0; padding: 1.7rem 0; background: var(--hero-card-bg); }
.hc-slide { position: absolute; inset: 0; opacity: 0; visibility: hidden; transition: opacity 1s ease, visibility 0s linear 1s; }
.hc-slide.is-active { opacity: 1; visibility: visible; transition: opacity 1s ease, visibility 0s; }
/* The <img> fills the slide absolutely so the <picture> wrapper can't letterbox
   it in the now height-driven (min-height) band. */
.hc-slide picture { display: block; }
.hc-media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }

.hc-overlay {
  position: absolute; top: 0; bottom: 0; z-index: 3;
  display: flex; flex-direction: column; justify-content: center; gap: 15px;
  width: 44%; max-width: 600px; padding: 4% 5.4%;
}
.hc-right { right: 0; align-items: flex-end; text-align: right;
  background: linear-gradient(270deg, rgba(246,248,251,.98) 30%, rgba(246,248,251,.85) 60%, rgba(246,248,251,0) 97%); }
.hc-left { left: 0; align-items: flex-start; text-align: left;
  background: linear-gradient(90deg, rgba(246,248,251,.98) 30%, rgba(246,248,251,.85) 60%, rgba(246,248,251,0) 97%); }
/* The open-plan home hero image is mirrored so its negative space lands on the LEFT,
   matching the promo so both slides read with copy on the left. The overlay is
   a sibling of <picture>, so only the image flips (text stays correct). */
.hc-slide--hero .hc-media { transform: scaleX(-1); }
.hc-eyebrow { margin: 0; font-size: clamp(11px, .9vw, 13px); letter-spacing: .18em; text-transform: uppercase; font-weight: 700; color: var(--sky-bright); }
@media (min-width: 1025px) { .hc-slide--aircon .hc-eyebrow { color: var(--azure); } }
.hc-title { margin: 0; font-family: var(--display); font-weight: 700; color: var(--navy-2);
  font-size: clamp(21px, 2.7vw, 40px); line-height: 1.06; letter-spacing: -.015em; max-width: 13ch;
  text-transform: uppercase; }
.hc-sub { margin: 0; font-family: var(--prose); color: var(--muted);
  font-size: clamp(13px, 1.1vw, 17px); line-height: 1.55; max-width: 34ch; }
.hc-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
.hc-right .hc-cta { justify-content: flex-end; }
/* .hc-on-dark overrides the (now light) .hc-left scrim back to dark for the promo,
   whose left space is dark navy; plus white text. */
.hc-on-dark { background: linear-gradient(90deg, rgba(4,20,38,.9) 24%, rgba(4,20,38,.58) 56%, rgba(4,20,38,0) 96%); }
.hc-on-dark .hc-title { color: #fff; }
.hc-on-dark .hc-sub { color: #d8e3ef; }
/* Open-plan home hero (slide 1), DESKTOP only: a soft brand-navy left scrim gives the
   white copy + CTA a clean, premium backdrop over the busy kitchen without becoming a
   heavy bar. The box grows with the viewport (max-width clamp lifts the shared 600px cap)
   and the gradient fades to transparent only at the box edge, so on wide desktops the
   scrim extends comfortably PAST the whole copy block (title, subline, both buttons)
   with a soft fade instead of running out under the last words of the subline.
   Tablet/mobile keep their bottom-anchored overlay (the <=1024 rules below), so this is
   min-width gated. The hero's ghost CTA is lightened to read on the darker scrim. */
@media (min-width: 1025px) {
  .hc-slide--hero .hc-overlay {
    max-width: clamp(600px, 46vw, 820px);
    background: linear-gradient(90deg, rgba(4,20,38,.6) 0%, rgba(4,20,38,.5) 46%, rgba(4,20,38,.32) 72%, rgba(4,20,38,.1) 90%, rgba(4,20,38,0) 100%);
  }
  .hc-slide--hero .btn-ghost { color: #fff; border-color: rgba(255,255,255,.55); background: rgba(255,255,255,.06); }
  .hc-slide--hero .btn-ghost:hover { border-color: #fff; background: rgba(255,255,255,.14); }
}
/* Hero-carousel CTAs are navy primary buttons (Deep Harbor: accents are cool ornament, not
   buttons). A hairline light edge lifts the navy pill off the dark banner photo. */
.hc-cta .btn-primary { border-color: rgba(255,255,255,.28); }
.hc-cta .btn-primary:hover { border-color: rgba(255,255,255,.55); }

/* Banner 3: authorized-dealer logo lockup - Samsung + Whirlpool + GE + "and more"
   in a 2x2 grid with no divider between the cells. All
   three marks are forced to ONE light monochrome so they read uniformly on the dark
   navy backdrop (Samsung uses a dedicated ellipse-less white wordmark so the mono
   filter doesn't flatten its logo into a blob). Per-logo heights are optically
   normalised to one common cap height - Samsung is all-caps so it equals the unit;
   Whirlpool's script and GE's monogram are nudged up so their caps match. Banner 4:
   crimson starburst clearance sticker. */
.hc-lockup { position: absolute; right: 6%; top: 50%; transform: translateY(-50%); z-index: 3;
  --hc-cap: clamp(20px, 2.7vw, 34px);
  display: grid; align-items: center; justify-items: center;
  /* Equal tracks keep the cells evenly centred - auto tracks put the flagship-wide
     Samsung column off-centre. */
  grid-template-columns: repeat(2, calc(var(--hc-cap) * 6.4));
  grid-template-rows: repeat(2, calc(var(--hc-cap) * 2.7)); }
.hc-lockup-cell { display: flex; align-items: center; justify-content: center; }
.hc-lockup-logo { width: auto; display: block;
  filter: brightness(0) invert(1) drop-shadow(0 2px 9px rgba(0,0,0,.5)); }
.hc-ll-samsung   { height: var(--hc-cap); }
.hc-ll-whirlpool { height: calc(var(--hc-cap) * 1.62); }
.hc-ll-ge        { height: calc(var(--hc-cap) * 2); }  /* roundel scaled up so its "GE" cap height matches the wordmarks' mass */
/* "and more" is the fourth cell - set in the same white as the monochrome
   logos, at a wordmark's weight, so it reads as a fourth brand, not a caption. */
.hc-lockup-more { font-size: calc(var(--hc-cap) * 0.72); letter-spacing: .2em; text-transform: uppercase;
  font-weight: 700; color: #fff; text-shadow: 0 2px 9px rgba(0,0,0,.5); }

/* Classic sale-sticker: a tilted CRIMSON starburst (captain-approved design A,
   2026-09-10) - SVG polygon with a thin inner white outline, white "UP TO / X% / OFF"
   stacked over it. The text stack is grid-centred in the square so the percentage sits
   visually centred in the burst at any digit count (captain's one condition). */
.hc-medallion { position: absolute; right: 6%; top: 50%; transform: translateY(-50%) rotate(-10deg); z-index: 3;
  width: clamp(140px, 15vw, 250px); aspect-ratio: 1; color: #fff; text-align: center;
  display: grid; place-items: center;
  filter: drop-shadow(0 20px 30px rgba(0,0,0,.5)); }
.hc-medallion svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.hc-medallion polygon { fill: var(--crimson); }
.hc-medallion polygon + polygon { fill: none; stroke: rgba(255,255,255,.55); stroke-width: 1.2; }
.hc-medallion .hc-med-t { position: relative; font-family: var(--display); line-height: 1; }
.hc-medallion span { display: block; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; font-size: clamp(10px, .95vw, 15px); }
.hc-medallion b { display: block; font-weight: 900; line-height: 1; letter-spacing: -.02em; margin: 3px 0;
  font-size: clamp(30px, 4vw, 64px); }
/* A 3+ digit percent ("100%") would poke past the burst's inner valleys at the full
   size, so it shrinks; index.html's module script sets the class (the figure is
   server-injected text, so CSS alone can't count digits). */
.hc-medallion.hc-med-wide b { font-size: clamp(24px, 3vw, 48px); letter-spacing: -.04em; }

.hc-controls { position: absolute; left: 0; right: 0; bottom: 6px; z-index: 4; display: flex; align-items: center; justify-content: center; gap: 4px; }
.hc-dots { display: flex; gap: 2px; }
.hc-dot { width: 44px; height: 44px; display: grid; place-items: center; }
/* Discreet by default: double-click/double-tap on the slide (hero-carousel.js) is the
   everyday way to pause, so this fallback control is visually hidden (standard
   clip-based sr-only, not display:none/visibility:hidden, so it stays in the
   accessibility tree) and only rejoins the visible controls row on genuine keyboard
   focus. Same 44px hit-box + white-fill/dark-halo treatment as .hc-dot once visible,
   for the same reason: it must read on both dark slides and the bright
   clearance-floor banner. */
.hc-playpause { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0,0,0,0); clip-path: inset(50%); white-space: nowrap;
  background: transparent; border: none; cursor: pointer;
  border-radius: 50%; color: rgba(255,255,255,.85); }
.hc-playpause:focus-visible { position: static; width: 44px; height: 44px; margin: 0;
  overflow: visible; clip: auto; clip-path: none; white-space: normal;
  display: grid; place-items: center; outline: none;
  box-shadow: 0 0 0 2px rgba(2,12,24,.7), 0 0 0 4px #fff; }
.hc-playpause:hover { color: #fff; }
.hc-playpause .hc-pp-icon { filter: drop-shadow(0 0 1px rgba(2,12,24,.9)) drop-shadow(0 1px 3px rgba(2,12,24,.7)); }
.hc-playpause .hc-pp-play { display: none; }
.hc-playpause[aria-pressed="true"] .hc-pp-pause { display: none; }
.hc-playpause[aria-pressed="true"] .hc-pp-play { display: block; }

/* Permanently visually-hidden live region: announces the pause/resume gesture to
   screen readers without a redundant visible message (the glass pill below is the
   sighted-user feedback and never persists, so it can't be read on demand). */
.hc-live { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0,0,0,0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* Temporary "glass" gesture indicator shown on double-click/double-tap pause+resume
   (hero-carousel.js). Centered over the active slide, frosted/translucent, fades in
   and out over ~1s, and never persists - it is feedback for the gesture, not a
   control. */
.hc-gesture { position: absolute; inset: 0; z-index: 6; display: grid; place-items: center; pointer-events: none; }
.hc-gesture-pill {
  display: flex; align-items: center; gap: 9px;
  padding: 12px 22px; border-radius: 999px;
  background: rgba(8,28,48,.4);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  border: 1px solid rgba(255,255,255,.35);
  box-shadow: 0 10px 28px rgba(2,12,24,.35), inset 0 1px 0 rgba(255,255,255,.25);
  color: #fff; font-family: var(--display); font-weight: 600; font-size: 14px;
  opacity: 0; transform: scale(.92);
  transition: opacity .35s ease, transform .35s ease;
}
.hc-gesture-pill.show { opacity: 1; transform: scale(1); transition-duration: .18s; }
.hc-gesture-pill .hc-gi-icon { width: 18px; height: 18px; display: block; }
.hc-gesture-pill .hc-gi-play { display: none; }
.hc-gesture-pill[data-state="playing"] .hc-gi-pause { display: none; }
.hc-gesture-pill[data-state="playing"] .hc-gi-play { display: block; }
@media (prefers-reduced-motion: reduce) {
  .hc-gesture-pill { transition: none; }
}
/* White dots on photography, so the ring is load-bearing, not decoration: the strip
   crosses bright banner regions (the clearance floor leaves a pure-white dot at ~2.4:1),
   where the fill alone fails WCAG 1.4.11 and only the dark ring carries it. It costs
   nothing on the dark slides. test:contrast checks token pairs and cannot catch this. */
.hc-dot::before { content: ''; width: 9px; height: 9px; border-radius: 50%;
  background: rgba(255,255,255,.55);
  box-shadow: 0 0 0 1px rgba(2,12,24,.6), 0 1px 4px rgba(2,12,24,.7);
  transition: background .3s, transform .3s; }
.hc-dot.on::before { background: #fff; transform: scale(1.4); }
/* Keyboard focus: the UA outline hugs the 44px hit-box, not the 9px dot, and its system
   color is invisible over some banner photography. A dark+white double shadow ring on the
   dot itself stays visible on both light and dark slides. :focus-visible only, so
   pointer clicks don't flash it. */
.hc-dot:focus-visible { outline: none; }
.hc-dot:focus-visible::before {
  box-shadow: 0 0 0 2px rgba(2,12,24,.7), 0 0 0 4px #fff, 0 1px 4px rgba(2,12,24,.7); }

@media (prefers-reduced-motion: reduce) {
  .hc-slide, .hc-slide.is-active { transition: none; }
}
/* Tablet + mobile: the taller 3:2 / 4:3 variants centre the products, so the copy
   moves into a bottom-anchored panel over a scrim (legible on any scene) and the
   arrows give way to swipe + dots. The wide desktop banner keeps its side overlay.

   The slides STACK IN A GRID here rather than being absolutely positioned, so the
   copy panel is in flow and the band's height is driven by the tallest panel (with
   64svh as a floor, not a cap). This is load-bearing: with an absolute panel the band
   height was fixed, so a panel taller than the band - a long headline, or any short
   viewport such as landscape - overflowed upward and clipped the headline into the
   nav. In flow, the band grows instead. Desktop keeps its absolute side overlay. */
@media (max-width: 1024px) {
  .hero-carousel { display: grid; }
  .hc-slide { position: relative; inset: auto; grid-area: 1 / 1;
    display: grid; align-content: end; }   /* copy panel hugs the bottom of the band */
  .hc-overlay, .hc-right, .hc-left {
    /* --hc-scrim-fade is BOTH the scrim's fade length and the panel's top padding, and
       the two must stay equal - that equality is what fixes the headline's contrast.
       The scrim is anchored to the COPY (this box), not to the overlay's height or the
       band's: the alpha ramp is measured in px DOWN FROM the content-box top, so the
       fade lives entirely in the top padding and the copy always starts at alpha .62
       (>= 4.9:1 for white text over even a pure-white banner pixel - the AA large-text
       floor is 3.0:1). Previously the gradient's stops were percentages of the overlay
       box, so alpha hit 0 at 92% of its height while the title's top edge sat at exactly
       92% - i.e. the LONGER the headline, the further it pushed into the transparent
       part of its own scrim. Sizing the fade in px, above the copy, makes copy length
       structurally irrelevant. It also guarantees the dots (top:12px, 44px tall) clear
       the headline, since 96px > 56px. If you change this, re-measure: see the hero
       contrast note in the ach-frontend-ui skill. */
    --hc-scrim-fade: 96px;
    position: relative; z-index: 3;   /* in flow, but still painted over the media */
    top: auto; bottom: auto; left: auto; right: auto;
    width: 100%; max-width: none;
    align-items: flex-start; text-align: left; gap: 12px;
    padding: var(--hc-scrim-fade) 30px 34px;
    background: linear-gradient(to top,
      rgba(4,20,38,.95) 0,
      rgba(4,20,38,.62) calc(100% - var(--hc-scrim-fade)),
      rgba(4,20,38,0) 100%);
  }
  .hc-right .hc-cta, .hc-left .hc-cta { justify-content: flex-start; }
  /* Secondary/ghost CTA sits on the dark scrim now - light it up so it stays legible. */
  .hc-cta .btn-ghost { color: #fff; border-color: rgba(255,255,255,.5); background: rgba(255,255,255,.05); }
  .hc-cta .btn-ghost:hover { border-color: #fff; background: rgba(255,255,255,.14); }
  .hc-title { color: #fff; font-size: clamp(24px, 3.6vw, 34px); max-width: 22ch; }
  .hc-sub { color: #dbe6f0; font-size: clamp(13px, 1.6vw, 15px); max-width: 46ch; }
  .hc-controls { bottom: auto; top: 12px; }
  /* copy is bottom-anchored now, so park the lockup/medallion top-right, clear of it + the dots */
  /* keep the 2x2 lockup top-right at a reduced scale (tracks are all
     --hc-cap-derived, so shrinking the cap shrinks the whole lockup). */
  .hc-lockup { right: 16px; top: 40px; transform: none; --hc-cap: clamp(16px, 4.6vw, 28px); }
  .hc-lockup-more { letter-spacing: .16em; }
  .hc-medallion { right: 16px; top: 40px; transform: rotate(-10deg); width: clamp(106px, 26vw, 150px); }
  /* font clamps re-tied to the 24vw sticker width so the stack scales with the burst */
  .hc-medallion span { font-size: clamp(9px, 1.5vw, 11px); }
  .hc-medallion b { font-size: clamp(24px, 6.4vw, 40px); }
  .hc-medallion.hc-med-wide b { font-size: clamp(19px, 4.8vw, 30px); }
}
/* Phones: shorter nav clearance, one strong CTA, tighter copy, snug padding. */
@media (max-width: 640px) {
  .hero-band { padding-top: 64px; }
  /* Keep the top padding == --hc-scrim-fade (see the <=1024 block); a literal here
     would put the headline back inside the scrim's fade and undo the contrast fix. */
  .hc-overlay, .hc-right, .hc-left { gap: 11px; padding: var(--hc-scrim-fade) 18px 30px; }
  .hc-cta { width: 100%; }
  /* One strong CTA on phones - the secondary link lives in the nav/Shop menu. */
  .hc-cta .btn-ghost { display: none; }
  .hc-title { font-size: clamp(21px, 6.2vw, 30px); max-width: 18ch; }
  .hc-sub { font-size: 13.5px; max-width: 32ch; }
}

/* ---- Section scaffolding ------------------------------------------------ */
section { padding: 84px 0; }
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 40px; }
.section-head h2 { font-size: clamp(28px, 3.6vw, 42px); color: var(--navy-2); }
.section-head p { color: var(--muted); margin: 10px 0 0; font-size: 16px; max-width: 56ch; }
.section-link { display: inline-flex; align-items: center; min-height: 44px; color: var(--azure); font-weight: 600; font-size: 15px; white-space: nowrap; transition: gap .2s; }
.section-link:hover { color: var(--navy); }

/* ---- Category cards ----------------------------------------------------- */
.cat-grid { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 18px; }
.cat-card {
  position: relative; display: flex; flex-direction: column; gap: 18px; justify-content: space-between;
  min-height: 178px; padding: 24px; border-radius: var(--radius); background: var(--card);
  border: 1px solid var(--line); box-shadow: var(--shadow-sm); overflow: hidden;
  transition: transform .25s, box-shadow .25s, border-color .25s;
}
.cat-card::after { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: linear-gradient(90deg, var(--navy), var(--azure)); transform: scaleX(0); transform-origin: left; transition: transform .3s; }
.cat-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: rgba(30,111,176,.4); }
.cat-card:hover::after { transform: scaleX(1); }
.cat-card .glyph { color: var(--azure); width: 52px; height: 52px; display: grid; place-items: center; border-radius: 12px; background: var(--paper-2); }
.cat-card .glyph svg { width: 27px; height: 27px; }
.cat-card .meta h3 { font-size: 20px; color: var(--navy-2); margin-bottom: 4px; }
.cat-card .meta span { color: var(--muted); font-size: 13.5px; }

/* ---- Brand strip (marquee) --------------------------------------------- */
.brand-strip { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--card); overflow: hidden; padding: 30px 0; }
.brand-eyebrow { text-align: center; font-size: 15px; letter-spacing: .13em; text-transform: uppercase; font-weight: 700; color: var(--azure); margin: 0 0 22px; }
.brand-track { -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent); mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent); overflow: hidden; }
/* No flex gap - spacing is per-item margin so the two duplicated sets tile exactly
   and the -50% shift loops with no seam/jump. */
/* will-change promotes the track to its OWN live GPU layer. On iOS Safari the masked
   parent (.brand-track) otherwise caches its compositor layer and never repaints against
   the transform-animated child - the marquee freezes on the phone while it animates fine
   on desktop. Promoting the moving element (paired with the translate3d keyframe below)
   makes the mask recomposite each frame. Layout-neutral; desktop unchanged. */
.brand-strip-inner { display: flex; align-items: center; width: max-content; animation: marquee 46s linear infinite; will-change: transform; }
.bitem { display: inline-flex; align-items: center; justify-content: center; gap: 11px; height: 46px; min-width: 44px; margin-right: 46px;
  text-decoration: none; border-radius: 10px; transition: opacity .2s ease; }
.bitem:hover { opacity: .66; }
.bitem:focus-visible { outline: 2px solid var(--azure); outline-offset: 6px; }
.blogo { width: auto; max-width: 210px; display: block; transition: transform .2s ease; }  /* height set per logo inline (optically normalized); max-width holds the widest wordmark (Frigidaire) at its equal cap-height */
.bitem:hover .blogo, .bitem:focus-visible .blogo { transform: scale(1.06); }
/* translate3d (not translateX) so the animation is GPU-composited on mobile WebKit;
   -50% still loops seamlessly against the duplicated track. */
@keyframes marquee { to { transform: translate3d(-50%, 0, 0); } }

/* ---- Product grid + cards ---------------------------------------------- */
.prod-grid { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 22px; }
.prod-card {
  position: relative; display: flex; flex-direction: column; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow-sm); transition: transform .25s, box-shadow .25s, border-color .25s;
}
.prod-card:hover { transform: translateY(-5px); box-shadow: var(--shadow); border-color: rgba(30,111,176,.4); }
.prod-img { aspect-ratio: 1/1; background: #fff; display: grid; place-items: center; padding: 20px; border-bottom: 1px solid var(--line); overflow: hidden; }
/* Letterbox BOTH orientations inside the 1:1 box. width/height:100% would let a TALL
   source overflow (PDP crop) or stretch the card off-square. min-*:0 removes the img's
   automatic grid-item minimum (its intrinsic height) so the box's aspect-ratio height
   stays definite and the max-height:100% cap actually resolves. */
.prod-img img { min-width: 0; min-height: 0; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; mix-blend-mode: multiply; }
.prod-body { display: flex; flex-direction: column; gap: 6px; padding: 16px 18px 18px; flex: 1; }
.prod-brand { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--azure); font-weight: 600; }
/* One fixed-height slot for the card's brand line, whether it holds the brand's
   logo (prodBrand in store.js, sized per-brand from its marquee optical size) or
   the text fallback - so logo and text cards align across a grid row. The logo
   keeps its aspect when a narrow card clamps its width (object-fit). */
.prod-brand-row { display: flex; align-items: center; min-height: 24px; }
.prod-brand-logo { max-width: 100%; object-fit: contain; object-position: left center; }
.prod-name { font-size: 14.5px; color: var(--ink); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: 40px; }
.prod-foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px 12px; margin-top: auto; padding-top: 10px; }
/* Fluid so the price never wraps in the 2-col mobile grid, where a card is only ~105px
   wide at 320px but "$520,000 GYD" (the catalog's widest) needs ~138px at 21px. Wrapping
   orphaned "GYD" onto its own line under the number. Reaches the designed 21px by ~428px,
   so tablet/desktop are unchanged; only the price text scales (.pr-lab/.pr-reg are fixed
   px). Prices are the thing customers read hardest - shrink them, never break them. */
.prod-price { font-family: var(--display); font-weight: 600; font-size: clamp(15.5px, 4.9vw, 21px); color: var(--navy); font-variant-numeric: tabular-nums; display: flex; flex-direction: column; align-items: flex-start; gap: 1px; line-height: 1.15; min-width: 0; }
/* Discount treatment (see .pdp-price): crimson label names the paid price; the
   regular price sits plainly (no strike) with a compact crimson "Save %". */
.prod-price .pr-lab { font-family: var(--font); font-size: 11.5px; font-weight: 600; color: var(--crimson); letter-spacing: .01em; margin-bottom: 1px; }
.prod-price .pr-reg { font-family: var(--font); font-size: 12.5px; font-weight: 400; color: var(--muted); font-variant-numeric: tabular-nums; display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; margin-top: 3px; max-width: 100%; }
.prod-price .pr-reg .rl { font-weight: 500; }
.prod-price .pr-reg .pr-save { color: var(--crimson); font-weight: 700; }
.prod-add { padding: 10px 16px; border-radius: 100px; border: 1px solid var(--navy); color: var(--navy); font-weight: 600; font-size: 13px; min-height: 44px; transition: background .2s, color .2s; }
.prod-add:hover { background: var(--navy); color: #fff; }
.badge-sale { position: absolute; top: 12px; left: 12px; z-index: 2; background: var(--crimson); color: #fff; font-size: 11px; font-weight: 700; letter-spacing: .08em; padding: 4px 10px; border-radius: 100px; }

/* ---- Value strip (homepage trust ribbon) -------------------------------- */
/* The reinforced "value strip" from the proposal: in-stock / warranty / parts /
   service / certified, sitting directly under the hero + brand marquee so the
   ACH promise is unmistakable before the shopper scrolls. */
.valuestrip { padding: 24px 0; background: var(--card); border-bottom: 1px solid var(--line); }
.vs-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: 20px; }
.vs-list li { display: flex; align-items: center; gap: 12px; min-width: 0; }
.vs-ico { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 11px; background: var(--paper-2); color: var(--navy); display: grid; place-items: center; }
.vs-ico svg { width: 22px; height: 22px; }
.vs-txt { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.vs-txt b { font-family: var(--display); font-size: 14.5px; color: var(--navy-2); font-weight: 600; }
.vs-txt > span { color: var(--muted); font-size: 12.5px; }

/* ---- Import-vs-ACH comparison (the value-proposition spine) ------------- */
.vs-compare { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; align-items: stretch; }
.vs-col { border-radius: var(--radius); padding: 30px 30px 34px; border: 1px solid var(--line); }
.vs-ach { background: linear-gradient(150deg, #013a73, var(--navy-2)); border-color: var(--navy-2); color: #fff; box-shadow: var(--shadow); }
.vs-import { background: var(--card); box-shadow: var(--shadow-sm); }
.vs-col-head { margin-bottom: 20px; }
.vs-tag { display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; padding: 4px 12px; border-radius: 100px; margin-bottom: 12px; }
.vs-tag-good { background: var(--whatsapp); color: #fff; }
.vs-tag-bad { background: var(--paper-2); color: var(--muted); }
.vs-col-head h3 { font-size: clamp(19px, 2vw, 23px); line-height: 1.2; }
.vs-ach .vs-col-head h3 { color: #fff; }
.vs-import .vs-col-head h3 { color: var(--navy-2); }
.vs-points { list-style: none; margin: 0; padding: 0; display: grid; gap: 13px; }
.vs-points li { position: relative; padding-left: 32px; font-size: 15px; line-height: 1.5; }
.vs-ach .vs-points li { color: rgba(255,255,255,.92); }
.vs-import .vs-points li { color: var(--ink); }
.vs-points li::before { content: '✓'; position: absolute; left: 0; top: 1px; width: 21px; height: 21px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 700; }
.vs-ach .vs-points li::before { background: var(--whatsapp); color: #fff; }
.vs-points-x li::before { content: '✕'; background: var(--paper-2); color: var(--crimson); }

/* ---- CTA strip ---------------------------------------------------------- */
.cta-strip {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: space-between; gap: 28px; flex-wrap: wrap;
  padding: 52px 52px; border-radius: 28px; color: #fff;
  background:
    radial-gradient(120% 140% at 88% -30%, rgba(111,168,214,.30), transparent 55%),
    radial-gradient(90% 120% at 0% 130%, rgba(196,154,72,.18), transparent 60%),
    linear-gradient(135deg, #013a73, var(--navy-2));
  box-shadow: var(--shadow), inset 0 1px 0 rgba(255,255,255,.08);
}
.cta-strip > * { position: relative; z-index: 1; }
.cta-strip h3 { font-size: clamp(26px, 3vw, 32px); color: #fff; margin-bottom: 8px; letter-spacing: -.01em; }
.cta-strip p { color: rgba(255,255,255,.82); margin: 0; max-width: 52ch; }
/* WhatsApp CTA: WhatsApp green - white text AA 5.4:1, hover 7.2:1 */
.cta-strip .btn-primary { background: var(--whatsapp); color: #fff; font-weight: 700; }
.cta-strip .btn-primary:hover { background: #0B6533; color: #fff; }

/* ---- Footer ------------------------------------------------------------- */
footer { background: var(--navy-2); color: rgba(255,255,255,.78); padding: 70px 0 36px; border-top: 3px solid var(--sky); }
.foot-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1.2fr; gap: 40px; }
/* Logo is 2.5x its old footer size (150px vs 60px) - stacked above the wordmark
   rather than beside it, or a mark that big would dwarf the 19px name next to it. */
.foot-brand { flex-direction: column; align-items: flex-start; gap: 14px; margin-bottom: 20px; }
.foot-brand .brand-mark { width: 150px; height: 150px; }
.foot-brand .brand-name { color: #fff; }
footer p { font-size: 14px; line-height: 1.7; margin: 0 0 8px; color: rgba(255,255,255,.72); }
/* Footer link-group labels. <h2> (not <h5>) so they never skip a heading level:
   the footer renders on every page, and a level INCREASE of more than one is what
   fails axe's heading-order - an h2 after any h1/h2/h3 is a decrease or a match, so
   it is safe on every page, where an h4 would skip on an h2-only page. */
footer .foot-grid h2 { font-family: var(--display); font-weight: 600; color: #fff; font-size: 15px; margin: 0 0 16px; letter-spacing: .02em; line-height: normal; }
footer .foot-grid > div > a { display: block; color: rgba(255,255,255,.72); font-size: 14px; padding: 7px 0; transition: color .2s; }
footer .foot-grid > div > a:hover { color: var(--sky-bright); }
.foot-bottom { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 48px; padding-top: 22px; border-top: 1px solid rgba(255,255,255,.12); font-size: 12.5px; color: rgba(255,255,255,.55); }
/* The Reboot Labs credit is a link. Its 44px tap target hangs over the row's own
   spacing on negative margins, so the row stays only as tall as the logo; the focus
   ring is drawn around the logo, not that taller box. */
.foot-credit { display: inline-flex; align-items: center; min-height: 44px; margin: -9px 0; transition: opacity .2s; }
.foot-credit:hover { opacity: .8; }
.foot-credit:focus-visible { outline: none; }
.foot-credit:focus-visible .foot-credit-logo { outline: 2px solid var(--sky-bright); outline-offset: 5px; border-radius: 2px; }
.foot-credit-logo { height: 26px; width: auto; }

/* ---- Short pages -------------------------------------------------------- */
/* Everything between the header and the footer sits in .page-fill (server/index.js
   withChrome). A page shorter than the screen gets the first screen's height, so the
   footer starts just below the visible area and is reached by scrolling. The header is
   fixed and each page clears it with its own top padding, so the full viewport is the
   right height. Phones subtract the tab bar, which stays fixed over the bottom edge; the
   pages that swap it for a bottom bar hide it, so --tabs-reserve (set with the tab bar's
   body padding, Phone app shell) is only there while it shows. Long pages are taller than
   this and are unaffected. */
.page-fill { min-height: calc(100vh - var(--tabs-reserve, 0px)); min-height: calc(100svh - var(--tabs-reserve, 0px)); }

/* ---- Shop --------------------------------------------------------------- */
/* Amazon-style: a compact left filter rail beside the grid on desktop; on mobile
   the rail collapses into a slide-in drawer so the PRODUCT GRID loads first. */
.shop-layout { display: grid; grid-template-columns: 244px minmax(0,1fr); gap: 36px; padding-top: 116px; padding-bottom: 90px; align-items: start; }
.filters { position: sticky; top: 96px; display: flex; flex-direction: column; gap: 18px; max-height: calc(100vh - 116px); overflow-y: auto; }
.filters-head { display: none; }   /* drawer header - mobile only */
.filter-block { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 18px 14px; box-shadow: var(--shadow-sm); }
.filter-block h5 { font-family: var(--display); font-size: 14px; letter-spacing: .04em; color: var(--navy-2); margin: 0 0 12px; }
.filter-actions { display: flex; flex-direction: column; gap: 10px; }
.filters-apply { display: none; }  /* "Show results" only matters inside the mobile sheet */
.filter-list { display: flex; flex-direction: column; gap: 2px; max-height: 260px; overflow-y: auto; }
.filter-list label { display: flex; align-items: center; gap: 9px; padding: 7px 8px; border-radius: 8px; font-size: 14px; color: var(--muted); cursor: pointer; transition: background .15s, color .15s; }
.filter-list label:hover { background: var(--paper-2); color: var(--ink); }
.filter-list input { accent-color: var(--navy); width: 18px; height: 18px; flex: 0 0 auto; }
.filter-list .filter-name { flex: 1; }
.filter-list .filter-logo { width: 34px; height: 22px; flex: 0 0 auto; object-fit: contain; border-radius: 3px; }
.filter-list .filter-logo--whirlpool { width: 44px; }
.filter-list .count { font-size: 11.5px; color: var(--muted); background: var(--paper-2); border-radius: 100px; padding: 1px 8px; }
.shop-top { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; margin-bottom: 28px; }
#shop-title { font-size: clamp(24px, 3.4vw, 38px); color: var(--navy-2); margin-right: auto; min-width: 0; }
.shop-search { min-width: 200px; flex: 1; max-width: 420px; }
.filters-btn { display: none; }    /* desktop has the rail; button is for mobile */
.filters-count { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 100px; background: var(--signal); color: #fff; font-size: 11px; font-weight: 700; }
.filters-count[hidden] { display: none; }
.filters-backdrop { display: none; }

/* ---- Clearance page ("Markdown event") ---------------------------------- */
/* Full-bleed navy promo header; starts below the fixed nav (home/contact
   nav-clearance convention, so the translucent nav frosts over paper, not navy),
   then the product grid + empty state render below in the standard .container. */
.clearance-hero {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-2) 100%);
  color: #fff; text-align: center; margin-top: 72px; padding: 68px 0 44px; margin-bottom: 40px;
  border-bottom: 3px solid var(--sky);
}
@media (max-width: 640px) { .clearance-hero { margin-top: var(--phone-header-h); } }  /* phones: the solid app header's height */
.ch-big {
  margin: 10px 0 6px; font-family: var(--display); font-weight: 700; line-height: 1.02;
  font-size: clamp(40px, 8vw, 84px); letter-spacing: -.02em; color: #fff; text-transform: uppercase;
}
.ch-pct { color: var(--crimson-bright); }
.ch-sub { margin: 0 auto; max-width: 44ch; color: rgba(255,255,255,.86); font-size: clamp(15px, 1.6vw, 18px); line-height: 1.5; }
.clearance-main { padding-bottom: 90px; }
.clearance-empty { text-align: center; padding: 60px 0 100px; }
.clearance-empty h2 { font-size: clamp(22px, 3vw, 30px); color: var(--navy-2); }
.clearance-empty p { margin: 12px auto 24px; max-width: 46ch; color: var(--muted); font-size: 16px; line-height: 1.55; }
.empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }

/* ---- /clearance: "Last units" -------------------------------------------- */
/* The band keeps the navy promo language: the word, then the real "up to X% off"
   (.ch-pct, worked out from the ticked products - server/index.js clearanceMarkers),
   and one line of what these pieces are. With nothing ticked it is the word and the
   empty-state sentence only. */
.cl-band { padding: 46px 0 38px; }
.cl-band .ch-big { margin: 0; }
.ch-line { display: block; }
.cl-band .ch-sub { margin-top: 16px; max-width: 50ch; }
.cl-narrow { max-width: 1168px; }

/* One piece per row, two across: photo (the saving as a percent in its badge), then the
   full name, category and model, and the ledger - regular price, clearance price, you
   save. Rendered by clearanceRow() in public/js/markup.js. */
.cl-rows { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 20px; }
.cl-row { display: flex; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.cl-row-img { position: relative; flex: 0 0 38%; display: grid; place-items: center; padding: 22px; background: #fff; border-right: 1px solid var(--line); }
.cl-row-img img { min-width: 0; min-height: 0; max-width: 100%; max-height: 230px; width: auto; height: auto; object-fit: contain; mix-blend-mode: multiply; }
.cl-row-body { flex: 1; min-width: 0; padding: 20px 22px; display: flex; flex-direction: column; }
.cl-row-name { font-family: var(--font); font-size: 17px; font-weight: 600; line-height: 1.35; letter-spacing: 0; color: var(--ink); margin-top: 6px; }
.cl-row-name a:hover { color: var(--azure); }
.cl-row-meta { margin: 4px 0 0; font-size: 13px; color: var(--muted); }
.cl-ledger { margin: 14px 0 12px; border-top: 1px solid var(--line); }
.cl-ledger div { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.cl-ledger dt { font-size: 13px; color: var(--muted); }
.cl-ledger dd { margin: 0; font-size: 14px; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The sale is the loudest thing on the row (the client's ask, 2026-10-06): the regular
   price is struck through and muted, and the clearance price takes a line of its own so
   it can be the biggest figure at every width - beside its label a seven-figure price
   only fits at ledger size. The clamp keeps "$1,300,000 GYD" inside the narrowest
   two-across row (901px). */
.cl-ledger .was dd { color: var(--muted); text-decoration: line-through; }
.cl-ledger .now { flex-direction: column; align-items: flex-start; gap: 2px; padding: 10px 0; }
.cl-ledger .now dt { color: var(--crimson); font-weight: 700; }
.cl-ledger .now dd { font-family: var(--display); font-size: clamp(24px, 2.6vw, 32px); font-weight: 700; line-height: 1.1; color: var(--navy); }
.cl-row-img .badge-sale { top: 14px; left: 14px; font-size: 16px; font-weight: 800; letter-spacing: .02em; padding: 7px 15px; }
.cl-ledger .save dd { color: var(--crimson); font-weight: 700; }
.cl-stock { margin: 0 0 12px; font-size: 13px; color: var(--muted); display: flex; align-items: center; gap: 8px; }
.cl-stock i { width: 8px; height: 8px; border-radius: 50%; background: var(--whatsapp); flex: 0 0 auto; }
.cl-row-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; margin-top: auto; }
.cl-row .prod-add { width: auto; }
.cl-ask { color: var(--azure); font-weight: 600; font-size: 13.5px; min-height: 44px; display: inline-flex; align-items: center; }
.cl-ask:hover { color: var(--navy); }

/* "Already sold": the ticked pieces ACH has marked out of stock - named, greyed, not
   for sale. Shown only when there are some. */
.cl-sec-title { margin: 48px 0 18px; font-size: clamp(20px, 2.2vw, 26px); color: var(--navy-2); }
.cl-solds { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 12px; }
.cl-sold { display: flex; align-items: center; gap: 14px; padding: 10px 16px 10px 10px; border: 1px dashed var(--line-2); border-radius: var(--radius); color: var(--muted); font-size: 14px; }
.cl-sold-img { flex: 0 0 56px; height: 56px; display: grid; place-items: center; background: #fff; border-radius: 10px; }
.cl-sold-img img { max-width: 44px; max-height: 44px; filter: grayscale(1); opacity: .55; }
.cl-sold-name { flex: 1; min-width: 0; }
.cl-sold-tag { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--line-2); border-radius: 100px; padding: 3px 10px; }

/* Nothing ticked: a way to hear about the next piece, then the featured products. */
.cl-notify { display: flex; align-items: center; justify-content: space-between; gap: 24px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 26px 28px; }
.cl-notify h2 { font-size: 22px; color: var(--navy-2); }
.cl-notify p { margin: 8px 0 0; color: var(--muted); font-size: 15px; line-height: 1.55; max-width: 52ch; }
.cl-notify-cta { display: flex; flex-direction: column; align-items: center; flex: 0 0 auto; }
.cl-notify-cta .wa-btn { width: auto; padding: 0 28px; }
.cl-notify-cta p { font-size: 13px; }
.cl-notify-cta p a { color: inherit; white-space: nowrap; }
.cl-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 52px 0 18px; }
.cl-sec-head h2 { font-size: clamp(20px, 2.2vw, 26px); color: var(--navy-2); }

@media (max-width: 900px) {
  .cl-rows, .cl-solds { grid-template-columns: minmax(0,1fr); }
  /* The name is a way into the product, so on touch widths its link is a 44px target
     even when the name is one line; the margins around it give the height back. */
  .cl-row-name { margin-top: 0; }
  .cl-row-name a { display: flex; align-items: center; min-height: 44px; }
  .cl-row-meta { margin-top: 0; }
}
@media (max-width: 640px) {
  .cl-band { padding: 30px 0 26px; margin-bottom: 20px; }
  .cl-band .ch-sub { margin-top: 12px; }
  .clearance-main { padding-bottom: 40px; }
  .cl-rows { gap: 12px; }
  .cl-row-img { flex: 0 0 112px; padding: 14px 8px 8px 12px; border-right: 0; place-items: start center; }
  .cl-row-img img { max-height: 120px; }
  .cl-row-img .badge-sale { top: 8px; left: 8px; font-size: 13px; padding: 5px 11px; }
  .cl-row-img:has(.badge-sale) { padding-top: 46px; }
  .cl-row-body { padding: 12px 14px 12px 6px; }
  .cl-row-name { font-size: 14.5px; }
  .cl-row-meta { font-size: 12.5px; }
  .cl-ledger { margin: 10px 0 8px; }
  .cl-ledger div { padding: 5px 0; }
  .cl-ledger dt { font-size: 12.5px; }
  .cl-ledger dd { font-size: 13px; }
  .cl-ledger .now { padding: 7px 0; }
  .cl-ledger .now dd { font-size: clamp(18px, 6vw, 24px); }
  .cl-stock { font-size: 12.5px; margin-bottom: 6px; }
  .cl-sec-title { margin-top: 32px; }
  .cl-sec-head { margin-top: 32px; margin-bottom: 10px; }
  .cl-notify { flex-direction: column; align-items: stretch; padding: 20px 18px; }
  .cl-notify-cta .wa-btn { width: 100%; }
}

/* A clearance-only grid's card (dealCard, markup.js - the phone home's Deals rail): the
   badge carries the percent, so the line under the price says the saving in money at
   every width. */
.prod-card--pct .sv-pct { display: none; }
.prod-card--pct .sv-amt { display: inline; white-space: nowrap; }

/* ---- Product detail (Direction B: gallery-forward) ---------------------- */
.pdp-wrap { padding-top: 104px; padding-bottom: 18px; }
/* Inline text breadcrumb (kept non-flex so the links stay inline prose links). */
.pdp-crumb { color: var(--muted); font-size: 13px; margin: 0 0 16px; line-height: 1.9; }
.pdp-crumb a { color: var(--azure); }
.pdp-crumb span { margin: 0 4px; }
.pdp-crumb a:hover { text-decoration: underline; }
.pdp-crumb em { font-style: normal; color: var(--ink); }
.pdp-crumb span { color: var(--line-2); }
/* Wrapper around the product-name tail (hidden on mobile); neutralize the generic
   .pdp-crumb span margin/color so desktop spacing is unchanged. */
.pdp-crumb .crumb-tail { margin: 0; color: inherit; }
/* Product name promoted above the image on mobile only; on desktop the name lives
   in the buy rail beside the gallery, so this is hidden. */
.pdp-title-m { display: none; }
/* dominant gallery + compact sticky buy rail */
.pb { display: grid; grid-template-columns: minmax(0,1.4fr) minmax(0,1fr); gap: 44px; align-items: start; padding-bottom: 8px; }
/* All three children are placed EXPLICITLY: giving only the rail a definite row makes
   grid place it before the auto-positioned gallery, which silently swaps the columns.
   The rail spans both rows so the import card sits directly under the gallery rather
   than below the taller rail, and stays sticky within that taller area. */
.pb > .pdp-gallery { grid-column: 1; grid-row: 1; }
.pb > .pdp-import  { grid-column: 1; grid-row: 2; }
.pb-rail { position: sticky; top: 96px; min-width: 0; grid-column: 2; grid-row: 1 / span 2; }
.pb-badges { display: flex; gap: 8px; margin-bottom: 12px; }
.pb-badges span { font-size: 11px; font-weight: 700; letter-spacing: .08em; padding: 4px 11px; border-radius: 100px; }
.pb-clear { background: var(--crimson); color: #fff; }
.pb-sale { background: var(--crimson); color: #fff; }
.pb-rail h1 { font-size: clamp(24px, 2.6vw, 32px); color: var(--navy-2); margin: 6px 0 8px; line-height: 1.14; }
.pb-meta { color: var(--muted); font-size: 14px; margin: 0 0 20px; }
/* Legacy single-image box (superseded by .pdp-gallery .g-main); kept for the letterbox pattern note. */
.pdp-img { background: #fff; border: 1px solid var(--line); border-radius: 20px; aspect-ratio: 1/1; display: grid; place-items: center; padding: 40px; box-shadow: var(--shadow-sm); overflow: hidden; }
.pdp-img img { min-width: 0; min-height: 0; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; mix-blend-mode: multiply; }
.pdp-brand { font-size: 12px; letter-spacing: .16em; text-transform: uppercase; color: var(--azure); font-weight: 600; }
/* Discount treatment: a crimson label names the paid price, which is the hero;
   the regular price sits plainly beneath (NO strike) with a crimson "Save" pill.
   A full-price product renders just `.now` (no label, no foot). */
.pdp-price { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; flex-wrap: wrap; }
.pb-rail .pdp-price { margin-bottom: 18px; }
.pdp-price .pr-lab { font-size: 14.5px; font-weight: 600; color: var(--crimson); letter-spacing: .005em; }
.pdp-price .now { font-family: var(--display); font-size: clamp(34px, 4.5vw, 44px); font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; line-height: 1.14; }
.pdp-price .pr-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin-top: 6px; }
.pdp-price .pr-reg { font-size: 15.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.pdp-price .pr-reg .rl { font-weight: 500; }
.pdp-price .pr-save { font-size: 13.5px; font-weight: 700; color: #fff; background: var(--crimson); padding: 6px 13px; border-radius: 100px; letter-spacing: .01em; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pb-stock { font-size: 14.5px; font-weight: 600; color: var(--azure); margin: 0 0 4px; }
.pb-stock.out { color: var(--crimson); }
.pb-fulfil { color: var(--muted); font-size: 13.5px; margin: 0 0 20px; }
.pb-buy { display: grid; gap: 11px; margin-bottom: 18px; }
.pb-qtyrow { display: flex; gap: 11px; }
.pb-qtyrow .btn { flex: 1; }
.qty { display: inline-flex; align-items: center; border: 1px solid var(--line-2); border-radius: 100px; overflow: hidden; flex: 0 0 auto; }
.qty button { width: 46px; height: 46px; min-width: 44px; font-size: 18px; color: var(--navy); transition: background .15s; }
.qty button:hover { background: var(--paper-2); }
.qty input { width: 48px; text-align: center; border: 0; border-radius: 0; padding: 12px 0; background: transparent; -moz-appearance: textfield; appearance: textfield; }
.qty input::-webkit-outer-spin-button, .qty input::-webkit-inner-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }
/* Contextual WhatsApp enquiry - a prominent green action. */
.wa-btn { display: flex; align-items: center; justify-content: center; gap: 9px; width: 100%; background: var(--whatsapp); color: #fff; border-radius: 100px; min-height: 48px; font-weight: 600; font-size: 14.5px; }
.wa-btn:hover { background: #0b6533; }
/* Icon-only WhatsApp link set inline beside a mobile-number link on a dark
   surface (bright glyph is the only one of the two greens that clears AA
   contrast against navy - see --whatsapp-bright). Sized to a 44px tap target
   (touch-target gate minimum) via a negative vertical margin so the hit area
   doesn't inflate the surrounding line height; the glyph itself stays small. */
.wa-inline { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin: -14px 0 -14px 4px; vertical-align: middle; color: var(--whatsapp-bright); }
.wa-inline:hover { color: #fff; }
.pb-why { list-style: none; padding: 16px 0 0; margin: 0; border-top: 1px solid var(--line); display: grid; gap: 10px; }
.pb-why li { position: relative; padding-left: 26px; font-size: 13.5px; color: var(--ink); }
.pb-why li::before { content: '✓'; position: absolute; left: 0; top: -1px; width: 18px; height: 18px; border-radius: 50%; background: var(--navy); color: var(--sky-bright); font-size: 11px; display: grid; place-items: center; }

/* full-bleed navy feature-story band (reuses the hero / .vs-ach gradient language) */
.feature-band { background: linear-gradient(160deg, #013a73, var(--navy-2)); border-top: 3px solid var(--sky); margin-top: 18px; padding: 56px 0 60px; }
.feature-band .fb-eyebrow { font-size: 12px; letter-spacing: .2em; text-transform: uppercase; color: var(--sky-bright); font-weight: 700; }
.feature-band h2 { color: #fff; font-size: clamp(26px, 3vw, 38px); margin: 10px 0 8px; }
.fb-lead { color: rgba(255,255,255,.82); font-family: var(--prose); font-size: 16px; max-width: 64ch; margin: 0 0 34px; }
.fb-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 20px; }
.fb-card { background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.14); border-radius: 14px; padding: 22px; }
.fb-card .n { width: 34px; height: 34px; border-radius: 9px; background: var(--sky); color: var(--navy-2); font-family: var(--display); font-weight: 700; display: grid; place-items: center; margin-bottom: 14px; }
.fb-card b { display: block; font-family: var(--display); color: #fff; font-size: 16px; margin-bottom: 7px; }
.fb-card span { color: rgba(255,255,255,.78); font-size: 13.5px; line-height: 1.6; }

/* light overview (graceful degrade when the description has no parseable features) */
.pdp-overview { padding: 40px 0 4px; }
.pdp-overview .section-head { margin-bottom: 16px; }
.pdp-overview p { color: var(--muted); font-size: 15.5px; line-height: 1.75; max-width: 72ch; margin: 0; }

/* Import-vs-ACH card in the gallery column - the PDP's reinforcement of the homepage
   value proposition. Reuses the homepage .vs-compare pattern (same value-prop spine,
   same navy/paper contrast), tightened for the narrower column. */
.pdp-import { margin: 26px 0 0; }
.pdp-import .pi-eyebrow { display: block; font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--azure); }
.pdp-import h2 { font-size: clamp(19px, 2vw, 23px); color: var(--navy-2); margin: 7px 0 16px; line-height: 1.2; }
.pdp-import .vs-compare { gap: 16px; }
.pdp-import .vs-col { padding: 20px 20px 22px; }
.pdp-import .vs-tag { margin-bottom: 14px; }
.pdp-import .vs-points { gap: 10px; }
.pdp-import .vs-points li { font-size: 14px; line-height: 1.45; padding-left: 28px; }
.pdp-import .vs-points li::before { width: 19px; height: 19px; font-size: 11px; }
.pdp-related { padding-bottom: 40px; }

/* Sticky mobile buy bar (client-appended, shown only on the stacked layout). */
.pdp-mobilebar { display: none; }

/* ---- Cart + checkout -----------------------------------------------------
   One flow on two pages (cart.html, checkout.html) in one frame: the title row with the
   steps beside it, the page's own column on the left (the cart's rows, the checkout's
   form) and the same summary card on the right. Below 901px it is a single column in
   document order; the phone layout is in "Phone foundation" further down. */
.cart-layout { display: grid; grid-template-columns: minmax(0,1fr) 372px; column-gap: 40px; padding-top: 118px; padding-bottom: 90px; align-items: start; }
.cart-top { grid-column: 1; margin-bottom: 20px; }
.cart-head { font-family: var(--display); font-size: clamp(28px, 6vw, 36px); letter-spacing: -.02em; margin: 0; }
.cart-sub { margin: 8px 0 0; color: var(--muted); font-size: 14.5px; line-height: 1.45; }
.cart-main, .co-form, .co-refused { grid-column: 1; min-width: 0; }
/* Cart, Checkout, Confirmed: where the customer is. Not links - the pages' own buttons
   and the header's way back do the moving. */
.co-steps { grid-column: 2; justify-self: end; align-self: end; list-style: none; margin: 0 0 16px; padding: 0; display: flex; align-items: center; font-size: 13px; font-weight: 600; color: var(--muted); }
.co-steps li { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.co-steps li + li::before { content: ''; width: 24px; height: 2px; margin: 0 2px 0 10px; border-radius: 2px; background: var(--line-2); }
.co-steps i { width: 24px; height: 24px; display: grid; place-items: center; border-radius: 50%; border: 1.5px solid currentColor; font-style: normal; font-size: 12px; }
.co-steps .now { color: var(--navy-2); }
.co-steps .now i { border-color: var(--navy); box-shadow: 0 0 0 4px rgba(42,120,190,.2); }
.co-steps .done i { background: var(--navy); border-color: var(--navy); color: #fff; }
.co-steps .done + li::before { background: var(--navy); }
/* The cart's empty and full states hang off one root class that an inline script in
   cart.html sets before the first frame. */
html.cart-is-empty .cart-layout { grid-template-columns: minmax(0, 1fr); }
html.cart-is-empty :is(.cart-summary, .co-steps, .cart-sub, .cart-all), html:not(.cart-is-empty) .cart-empty { display: none; }

/* A tick box: in or out of this order. The input is the 24px box; its .pick wrapper is
   the 44px tap target, hung over the gaps either side so the row's grid is not widened. */
.pick { display: grid; place-items: center; width: 44px; height: 44px; margin: 0 -10px; cursor: pointer; }
.tick {
  -webkit-appearance: none; appearance: none; display: block; width: 24px; height: 24px; margin: 0; padding: 0;
  border: 1.5px solid var(--muted); border-radius: 7px; background: var(--card) center / 16px no-repeat; cursor: pointer;
  transition: background-color .15s, border-color .15s;
}
.tick:checked, .tick:indeterminate { background-color: var(--navy); border-color: var(--navy); }
.tick:checked { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E"); }
.tick:indeterminate { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.2' stroke-linecap='round'%3E%3Cpath d='M6 12h12'/%3E%3C/svg%3E"); }
.tick:focus-visible { box-shadow: 0 0 0 3px rgba(30,111,176,.3); }
/* "Select all" above the rows, its box in line with theirs. */
.cart-all { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 0 21px; margin-bottom: 4px; font-size: 13.5px; color: var(--muted); }
.cart-all[hidden] { display: none; }
.cart-all label { display: inline-flex; align-items: center; gap: 20px; min-height: 44px; font-weight: 600; color: var(--navy-2); cursor: pointer; }

.cart-items { display: flex; flex-direction: column; gap: 12px; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
/* Row grid: tick | thumbnail | name+unit-price, the unticked note, then the row's
   actions | qty stepper | line price. The line-price track is fixed-width +
   right-aligned so prices line up across rows; the stepper sits in its own track so
   every row's controls align. */
.cart-row {
  display: grid;
  grid-template-columns: 24px 76px minmax(0, 1fr) auto minmax(96px, auto);
  grid-template-areas:
    "pick img info qty price"
    "pick img note qty price"
    "pick img acts qty price";
  column-gap: 20px; align-items: center;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 20px 6px; box-shadow: var(--shadow-sm);
}
.cart-row .pick { grid-area: pick; }
.cart-row .img { grid-area: img; width: 76px; height: 76px; background: #fff; border-radius: 10px; border: 1px solid var(--line); display: grid; place-items: center; padding: 8px; }
.cart-row .img img { max-width: 100%; max-height: 100%; object-fit: contain; mix-blend-mode: multiply; }
.cart-row .info { grid-area: info; align-self: end; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cart-row .name { font-weight: 600; color: var(--ink); line-height: 1.4; }
.cart-row a.name:hover { color: var(--azure); }
.cart-row .each { color: var(--muted); font-size: 13px; }
.cart-row .qty { grid-area: qty; }
.cart-row .price { grid-area: price; font-family: var(--display); font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.cart-row .row-acts { grid-area: acts; align-self: start; display: flex; align-items: center; gap: 4px; margin-left: -8px; }
.cart-row .save { display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; padding: 0 8px; color: var(--azure); font-size: 13px; font-weight: 600; }
.cart-row .save:hover { text-decoration: underline; }
.cart-row .rm { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; padding: 0 8px; color: var(--muted); font-size: 13px; transition: color .2s; }
.cart-row .rm:hover { color: var(--crimson); }
.cart-row .rm svg { display: none; }   /* the phone row's Remove is the bin alone */
/* An unticked line: still in the cart, set back from the order. */
.cart-row.off { background: transparent; border-style: dashed; border-color: var(--line-2); box-shadow: none; }
.cart-row.off .img img { opacity: .5; }
.cart-row.off .price { color: var(--muted); }
.cart-row .off-note { grid-area: note; justify-self: start; margin-top: 6px; padding: 3px 10px; border-radius: 12px; background: var(--paper-2); color: var(--navy-2); font-size: 12px; font-weight: 600; line-height: 1.4; }
/* A line the store can no longer sell: kept in the cart, dimmed, and left out of the order
   (cart.html), so it has no tick. It is information, not an error, so it does not use the
   alert colour. */
.cart-row.sold { grid-template-columns: 24px 76px minmax(0, 1fr) auto; grid-template-areas: ". img info sold"; padding-bottom: 14px; scroll-margin-block: 100px 130px; }   /* scrolled to, it clears the fixed nav and the pinned phone bar */
.cart-row.sold .info { align-self: center; }
.cart-row.sold .img img { opacity: .45; }
.cart-row.sold .name { color: var(--muted); }
.cart-row.sold .sold-note { display: block; margin-top: 2px; font-size: 13px; font-weight: 600; color: var(--ink); }
.cart-row .sold-actions { grid-area: sold; display: flex; align-items: center; gap: 4px; }
/* What "Save for later" kept, one tap away under the rows. */
.cart-saved { display: flex; align-items: center; gap: 12px; min-height: 52px; margin-top: 14px; padding: 0 20px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); color: var(--navy); font-size: 14.5px; font-weight: 600; transition: border-color .2s; }
.cart-saved[hidden] { display: none; }
.cart-saved > span { flex: 1; }
.cart-saved:hover { border-color: var(--azure); }
.cart-empty { text-align: center; padding: 80px 20px; color: var(--muted); }
.cart-empty h2 { font-family: var(--display); margin-bottom: 12px; }
.cart-empty .btn { margin-top: 22px; }

/* The summary card: the cart's "This order" and the checkout's "Your order". */
.cart-summary { grid-column: 2; position: sticky; top: 100px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 24px 28px 26px; box-shadow: var(--shadow); }
.cart-summary h2 { font-family: var(--display); font-size: 21px; color: var(--navy-2); margin-bottom: 10px; }
.summary-row { display: flex; justify-content: space-between; gap: 16px; padding: 10px 0; color: var(--muted); font-size: 14.5px; border-bottom: 1px solid var(--line); }
.summary-row > span:last-child { color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Overrides the nowrap above: unlike every other value in this column (a GYD amount or
   "Free"), this one holds words ("confirmed by ACH after checkout"), which nowrap would
   force to overflow the summary card at narrow widths. */
.summary-row > span.co-wrap { white-space: normal; text-align: right; max-width: 72%; }
.summary-row.total { border-bottom: 0; margin-top: 6px; padding-top: 16px; color: var(--ink); font-family: var(--display); font-size: 20px; font-weight: 600; }
.summary-row.total > span:last-child { color: var(--navy); }
.summary-row.total small { font-family: var(--font); font-size: 13px; font-weight: 400; color: var(--muted); }
/* Overrides .btn's global `white-space: nowrap`. The checkout's button carries an
   unbounded number ("Place order · $980,000 GYD" - an order total, not a single product
   price, so it can run to 7+ digits). Nowrap made its min-content the whole string,
   which the summary track then had to honour, pushing the page wide at 320px. Wrapping
   is only ever reached when the label genuinely cannot fit on one line. */
#checkout { width: 100%; justify-content: center; margin-top: 18px; white-space: normal; }
.cart-bar-sum { display: none; }   /* the pinned phone bar's count and total */
.co-note { color: var(--muted); font-size: 12px; line-height: 1.5; margin: 6px 0 14px; }
.co-pay-note { text-align: center; margin: 12px 0 0; text-wrap: balance; }
.co-stays { text-align: center; margin: 2px 0 0; }
.co-ask { display: flex; width: 100%; margin-top: 14px; font-size: 14.5px; }
.co-ask svg { color: var(--whatsapp); }
/* The checkout's card lists the order: thumbnail with its quantity, name, line price. */
.co-sum-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: -8px 0 4px; }
.co-sum-head h2 { margin: 0; }
.co-edit { display: inline-flex; align-items: center; justify-content: flex-end; min-width: 44px; min-height: 44px; color: var(--azure); font-size: 13.5px; font-weight: 600; }
.co-edit:hover { text-decoration: underline; }
html.co-buy .co-edit { visibility: hidden; }   /* "Buy now" was not formed in the cart */
.co-lines { display: grid; gap: 12px; padding-bottom: 14px; margin-bottom: 4px; border-bottom: 1px solid var(--line); }
.co-line { display: grid; grid-template-columns: 52px minmax(0, 1fr) auto; gap: 12px; align-items: center; font-size: 13.5px; }
.co-line .img, .co-strip .img, .co-refused .img { position: relative; width: 52px; height: 52px; display: grid; place-items: center; padding: 6px; background: #fff; border: 1px solid var(--line); border-radius: 10px; }
.co-line .img img, .co-strip .img img, .co-refused .img img { max-width: 100%; max-height: 100%; object-fit: contain; mix-blend-mode: multiply; }
.co-line .img b { position: absolute; top: -7px; right: -7px; min-width: 20px; height: 20px; padding: 0 5px; display: grid; place-items: center; border-radius: 100px; background: var(--navy); color: #fff; font-size: 11.5px; font-weight: 600; line-height: 1; }
.co-line .nm { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; line-height: 1.35; color: var(--ink); }
.co-line .pr { font-family: var(--display); font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---- Checkout form (checkout.html) --------------------------------------- */
.co-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.co-strip { display: none; }   /* single column only: the order, above the form */
.co-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px 24px 9px; box-shadow: var(--shadow-sm); }
.co-title { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; font-size: 18px; letter-spacing: 0; color: var(--navy-2); }
.co-title i { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%; background: var(--paper-2); color: var(--navy); font-style: normal; font-size: 13px; }
.co-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 14px; }
.co-wide { grid-column: 1 / -1; }
/* Segmented control: two equal pills; the checked radio fills its label navy. */
.seg { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.seg.seg-single { grid-template-columns: 1fr; }
.seg.seg-3 { grid-template-columns: 1fr 1fr 1fr; }
.seg input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.seg label { display: flex; align-items: center; justify-content: center; min-height: 46px; padding: 10px 12px; border: 1px solid var(--line-2); border-radius: 100px; color: var(--navy); font-weight: 600; font-size: 14.5px; cursor: pointer; text-align: center; transition: background .18s, color .18s, border-color .18s; }
.seg label:hover { border-color: var(--azure); }
.seg label[hidden] { display: none; }
.seg input:checked + label { background: var(--navy); border-color: var(--navy); color: #fff; }
.seg input:focus-visible + label { box-shadow: 0 0 0 3px rgba(30,111,176,.3); }
.seg input:disabled + label { opacity: .45; cursor: not-allowed; }
/* What the fulfilment choice means, under the choice. */
.co-info { display: flex; gap: 10px; margin: 12px 0 13px; padding: 11px 14px; border-radius: 10px; background: var(--paper-2); color: var(--ink); font-size: 13.5px; line-height: 1.45; }
.co-info svg { flex: 0 0 auto; margin-top: 1px; color: var(--azure); }
/* "Buy now" only: the product the store refused when the order was placed, in the form's
   place (checkout.html). Information, not an error, like the cart's refused line. */
.co-refused-item { display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 14px; }
.co-refused .img img { opacity: .45; }
.co-refused-msg { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.45; color: var(--ink); }
.co-refused-msg:focus { outline: none; }   /* focused to be read out, not to be operated */
.co-refused .co-note { margin: 4px 0 0; font-size: 13px; }
.co-refused-acts { display: flex; flex-wrap: wrap; gap: 10px; margin: 18px 0 13px; }
.co-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 13px; }
.co-field label { font-size: 13px; font-weight: 600; color: var(--navy-2); }
.co-field input { width: 100%; min-height: 46px; font-size: 15px; }
.co-opt { color: var(--muted); font-weight: 400; }
.co-pickup { display: flex; flex-direction: column; gap: 3px; background: var(--paper-2); border: 1px solid var(--line); border-radius: 10px; padding: 13px 14px; margin-bottom: 14px; font-size: 13px; color: var(--muted); line-height: 1.45; }
.co-pickup strong { color: var(--navy-2); font-size: 14px; }
/* The checkout's focused header (checkoutNavMarkup, server/chrome.js): the way back
   and the logo. Solid, since nothing wires the store header's scroll state here. */
.co-nav { background: var(--card); border-bottom-color: var(--line); -webkit-backdrop-filter: none; backdrop-filter: none; }
.co-nav .nav-inner { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
.co-back { justify-self: start; display: inline-flex; align-items: center; gap: 6px; min-height: 44px; color: var(--azure); font-size: 14.5px; font-weight: 600; white-space: nowrap; }
.co-back:hover { text-decoration: underline; }

/* Cash "pay on pickup/delivery" callout on the confirmation page. */
/* The order page (/success). Its phone status screen is in "Phone after-order". */
.success-page { padding-top: 160px; padding-bottom: 120px; text-align: center; max-width: 640px; }
.success-callout { margin: 26px auto 0; max-width: 460px; padding: 18px 22px; border-radius: var(--radius); background: var(--paper-2); border: 1px solid var(--line-2); display: flex; flex-direction: column; gap: 6px; text-align: center; }
.success-callout strong { font-family: var(--display); font-size: 18px; color: var(--navy-2); }
.success-callout span { color: var(--muted); font-size: 14px; line-height: 1.5; }

/* Saved for later (/saved): the products this browser saved, at every width (only the
   phone product page offers the heart that fills it). */
.saved-page { padding-top: 120px; padding-bottom: 80px; }
.saved-page h1 { font-size: clamp(26px, 3.6vw, 40px); color: var(--navy-2); }
.saved-count { margin: 6px 0 18px; color: var(--muted); font-size: 14px; }
.saved-share { margin-bottom: 20px; }
.saved-share[hidden] { display: none; }
.saved-share svg { color: var(--whatsapp); }
.saved-item { position: relative; display: flex; min-width: 0; }
.saved-item > .prod-card { flex: 1 1 auto; min-width: 0; }
.saved-rm {
  position: absolute; z-index: 2; top: 8px; right: 8px; width: 44px; height: 44px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--card); border: 1px solid var(--line); color: var(--navy);
  box-shadow: 0 4px 12px -6px rgba(6,36,63,.35);
}
.saved-empty { padding: 32px 0 12px; }
.saved-empty h2 { font-size: 22px; color: var(--navy-2); }
.saved-empty p { margin: 6px 0 18px; color: var(--muted); }

/* ---- Toast -------------------------------------------------------------- */
/* Both toasts are popover="manual" elements (store.js / admin.js) so they render
   in the top layer above any overlay; `inset: auto; margin: 0` undo the popover
   UA defaults (inset: 0; margin: auto) that would otherwise re-center them. */
.toast {
  position: fixed; inset: auto; margin: 0; left: 50%; top: 76px; transform: translate(-50%, -24px);
  background: var(--navy-2); color: #fff; padding: 14px 24px; border-radius: 100px;
  font-size: 14.5px; font-weight: 500; box-shadow: var(--shadow); z-index: var(--z-toast);
  opacity: 0; pointer-events: none; transition: opacity .3s, transform .3s; border: 1px solid rgba(111,168,214,.3);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---- Reveal (progressive-enhancement) ----------------------------------- */
html.js-ready .reveal { opacity: 0; transform: translateY(20px); }

/* ---- Responsive --------------------------------------------------------- */
@media (max-width: 1080px) {
  .cat-grid, .prod-grid { grid-template-columns: repeat(3, minmax(0,1fr)); }
  .foot-grid { grid-template-columns: 1fr 1fr; gap: 30px; }
  /* The gallery column is too narrow for two comparison columns well before .pb itself
     collapses (900px), so this stacks earlier than the homepage .vs-compare. */
  .pdp-import .vs-compare { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: minmax(0,1fr); gap: 24px; }
  .hero-stage { order: -1; }
  #hero-canvas { height: 300px; }
  .hero-copy { max-width: 100%; }
  .vs-list { grid-template-columns: repeat(3, minmax(0,1fr)); gap: 16px 20px; }
  .vs-compare { grid-template-columns: 1fr; }

  /* Shop: product grid loads first; filters live in a slide-in drawer. */
  .shop-layout { grid-template-columns: 1fr; }
  .filters-btn { display: inline-flex; }
  .filters {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 90;
    width: min(86vw, 360px); max-height: none; margin: 0;
    padding: 18px 18px calc(18px + env(safe-area-inset-bottom)) calc(18px + env(safe-area-inset-left, 0px)); gap: 16px;
    background: var(--paper); box-shadow: 30px 0 60px -30px rgba(6,36,63,.5);
    overflow-y: auto; overscroll-behavior: contain;
    transform: translateX(-100%); transition: transform .3s ease; visibility: hidden;
  }
  .shop-layout.filters-open .filters { transform: none; visibility: visible; }
  .filters-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
  .filters-title { font-family: var(--display); font-size: 22px; color: var(--navy-2); }
  .filters-apply { display: inline-flex; }
  .filter-list { max-height: 46vh; }
  .filters-backdrop {
    display: block; position: fixed; inset: 0; z-index: 89;
    background: rgba(6,36,63,.42); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    opacity: 0; pointer-events: none; transition: opacity .3s ease;
  }
  .shop-layout.filters-open .filters-backdrop { opacity: 1; pointer-events: auto; }

  /* minmax(0,…) like the desktop rule above: a bare `1fr` is minmax(auto,1fr), whose
     automatic minimum is min-content, so the track refuses to shrink below its widest
     unbreakable child and pushes the whole page wide instead of letting the child adapt. */
  .cart-layout { grid-template-columns: minmax(0, 1fr); }
  .co-steps, .cart-summary { grid-column: 1; }
  .co-steps { justify-self: start; margin-bottom: 14px; }
  .cart-top { margin-bottom: 12px; }
  .cart-summary { position: static; margin-top: 18px; }
  /* The checkout's order, above the form: the summary card is below it here. The
     height is the thumbnails', held before the script that draws them has run. */
  .co-strip { display: flex; align-items: center; gap: 12px; min-height: 68px; padding: 10px 16px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
  .co-strip-imgs { display: flex; }
  .co-strip .img { width: 46px; height: 46px; }
  .co-strip .img + .img { margin-left: -12px; }
  .co-strip-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 13px; line-height: 1.35; color: var(--muted); }
  .co-strip-txt b { font-family: var(--display); font-size: 16.5px; font-weight: 600; color: var(--navy-2); white-space: nowrap; }
  html.co-buy .co-strip .co-edit { display: none; }
  /* PDP: gallery + buy rail stack; the rail un-sticks and the feature grid narrows. */
  .pb { grid-template-columns: 1fr; gap: 26px; }
  /* single column: drop the explicit placement so the three children just stack */
  .pb > .pdp-gallery, .pb > .pdp-import, .pb-rail { grid-column: auto; grid-row: auto; }
  .pb-rail { position: static; }
  .fb-grid { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .pdp-gallery .g-zoom { display: none; }   /* stacked layout is touch-first */
  /* Mobile: show the product name ONCE, promoted above the image (SAMSUNG eyebrow +
     big bold name as the page <h1>). Drop the duplicate breadcrumb tail and the
     in-rail title/brand; the promoted <h1> is the single visible heading here, while
     the desktop rail <h1> is display:none (out of the a11y tree) at this width. */
  .pdp-crumb .crumb-tail { display: none; }
  .pdp-title-m { display: block; margin: 0 0 16px; }
  .pdp-title-m-name { margin: 4px 0 0; font-family: var(--display); font-size: clamp(24px, 6vw, 30px); font-weight: 600; line-height: 1.14; color: var(--navy-2); }
  .pb-rail > .pdp-brand, .pb-rail > h1 { display: none; }
  /* Sticky bottom buy bar: price + WhatsApp + Add-to-cart, pinned as the story scrolls. */
  .pdp-page.has-mobilebar { padding-bottom: 80px; }
  /* Spacing is fluid so the bar still fits a 12-character price ("$520,000 GYD" = the
     catalog's widest, at 18px display) beside the 48px WhatsApp target and Add-to-cart
     on a 320px phone. It reaches the designed 16px/10px/24px at ~414px and up, so only
     the narrowest phones tighten - no new breakpoint, and the price NEVER shrinks or
     truncates (it is the thing customers read hardest). */
  .pdp-mobilebar {
    display: flex; align-items: center; gap: clamp(8px, 2.5vw, 10px);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    padding: 10px calc(clamp(12px, 4vw, 16px) + env(safe-area-inset-right, 0px)) calc(10px + env(safe-area-inset-bottom, 0px)) calc(clamp(12px, 4vw, 16px) + env(safe-area-inset-left, 0px));
    background: var(--card); border-top: 1px solid var(--line);
    box-shadow: 0 -8px 24px -16px rgba(6,36,63,.5);
  }
  .pdp-mobilebar .mb-price { font-family: var(--display); font-weight: 600; font-size: 18px; color: var(--navy); font-variant-numeric: tabular-nums; white-space: nowrap; }
  /* Price sits on the LEFT; WhatsApp + Add-to-cart are grouped on the RIGHT
     (margin-left:auto on the first of the pair). Add-to-cart is content-width now,
     not full-bleed. The bar stays always-pinned - only the button sizing changed. */
  .pdp-mobilebar .mb-wa { display: inline-flex; align-items: center; justify-content: center; width: 48px; min-width: 48px; height: 48px; border-radius: 100px; background: var(--whatsapp); color: #fff; flex: 0 0 auto; margin-left: auto; }
  .pdp-mobilebar .mb-add { flex: 0 0 auto; padding-inline: clamp(16px, 5vw, 24px); }

  /* Mobile nav: a PROMINENT hamburger reveals a stacked dropdown panel. */
  .nav-toggle { display: inline-flex; }
  /* Account moves out of the crowded actions bar and into the dropdown (see the
     .nav-account-mobile note above). */
  .account-btn { display: none; }
  .nav-account-mobile { display: block; }
  /* Filled navy pill so the menu control is unmistakable, never a faint afterthought. */
  .nav-toggle.icon-btn {
    background: var(--navy); border-color: var(--navy); color: #fff;
    min-width: 46px; min-height: 46px; padding: 0;
    box-shadow: 0 6px 16px -8px rgba(0,48,96,.6);
  }
  .nav-toggle.icon-btn:hover { background: var(--azure); border-color: var(--azure); }
  .nav-toggle.icon-btn svg { width: 22px; height: 22px; }
  /* Compact header: badge scales to 58px and padding trims to 7px so the bar
     height stays at its ~72px baseline (no taller header, no wrapped title). */
  .nav-inner { padding: 7px 18px; gap: 12px; }
  .brand-mark { width: 58px; height: 58px; }
  .nav-links {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; gap: 0; align-items: stretch;
    background: rgba(255,255,255,.98); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--line); box-shadow: 0 20px 44px -26px rgba(6,36,63,.55);
    padding: 6px 0; font-size: 16px;
    max-height: calc(100svh - 70px); overflow-y: auto;     /* long menus stay reachable on short screens */
    opacity: 0; visibility: hidden; transform: translateY(-8px); pointer-events: none;
    transition: opacity .25s ease, transform .25s ease, visibility .25s;
  }
  .nav.menu-open { background: rgba(255,255,255,.97); border-bottom-color: var(--line); box-shadow: 0 8px 30px -22px rgba(6,36,63,.5); }
  .nav.menu-open .nav-links { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
  .nav-links a { display: flex; align-items: center; min-height: 48px; padding: 13px 22px; color: var(--ink); }
  .nav-links a::after { display: none; }
  .nav-links a.active { color: var(--navy); background: var(--paper-2); box-shadow: inset 3px 0 0 var(--signal); }
  .nav.menu-open .nav-toggle .i-open { display: none; }
  .nav.menu-open .nav-toggle .i-close { display: inline; }

  /* Shop dropdown inside the hamburger panel: a tap-to-expand disclosure row. */
  .nav-shop { display: block; }
  .nav-shop-trigger {
    width: 100%; justify-content: space-between;
    min-height: 48px; padding: 13px 22px; font-size: 16px; color: var(--ink);
  }
  .nav-shop-trigger::after { display: none; }
  /* The nav micro-animations are a desktop-bar flourish; in the stacked
     hamburger panel the items read as plain rows. */
  .nav-shop-label { background: none; -webkit-text-fill-color: currentColor; animation: none; }
  .nav-hiring::before { display: none; }
  .nav-menu {
    position: static; transform: none; min-width: 0; z-index: auto;
    opacity: 1; visibility: visible; pointer-events: auto;
    display: none; flex-direction: column; gap: 0; padding: 0;
    background: var(--paper); border: 0; border-radius: 0; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .nav-menu::before { display: none; }
  /* Override the desktop open/hover transform (translate(-50%)) which otherwise
     wins on specificity and shifts the inline mobile submenu off-screen. */
  .nav-shop.open .nav-menu { display: flex; transform: none; }
  .nav-menu a { min-height: 46px; padding: 12px 22px 12px 40px; border-radius: 0; color: var(--ink); }
  .nav-menu a.active { background: var(--card); box-shadow: none; }  /* dropdown items also match `.nav-links a.active` above; keep its bar off submenu items */
  .nav-menu-all { margin-top: 0; padding-top: 12px; border-top: 1px solid var(--line); }

  /* Mobile search takeover: the open field spans the bar (logo stays), and the
     cart + hamburger step aside. The submit button stays pinned at the far right. */
  .nav.search-open .brand-name { display: none; }
  .nav.search-open .cart-btn,
  .nav.search-open .account-btn,
  .nav.search-open .nav-toggle { display: none; }
  .nav.search-open .nav-search { position: static; }
  .nav.search-open .nav-search-input {
    position: absolute; left: 86px; right: 54px; top: 50%; transform: translateY(-50%);   /* clear of the 58px badge (18px gutter + 58 + 10) */
    width: auto; padding: 0 16px;
  }
  .nav.search-open .nav-search-btn { position: absolute; right: 0; top: 50%; transform: translateY(-50%); }
}
@media (max-width: 640px) {
  /* Only adjust horizontal padding here - the `padding` shorthand would reset the
     top offset that .shop-layout/.pdp/.cart-layout add to clear the fixed nav,
     dropping their headings behind it on mobile. */
  .container { padding-left: 18px; padding-right: 18px; }
  /* The eyebrow sits outside .container because .brand-strip is full-bleed for the
     marquee, so it needs the gutter applied to itself to match its neighbours. */
  .brand-eyebrow { padding: 0 18px; }
  .cat-grid, .prod-grid { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 14px; }
  /* PDP: single-column feature story + tighter top clearance on phones. */
  .pdp-wrap { padding-top: calc(var(--phone-header-h) + 20px); }
  .fb-grid { grid-template-columns: 1fr; }
  .feature-band { padding: 44px 0 46px; }
  .vs-list { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 16px; }
  .vs-col { padding: 24px 22px 28px; }
  section { padding: 56px 0; }
  .section-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  /* Narrow 2-col cards can't fit price + button on one line: drop the Add button
     to its own full-width line for a clean, large touch target (no clipping).
     "Add to Cart" fits inside it at every width down to 320 - measured, see addBtn
     in js/store.js before shortening the label or swapping it for an icon. */
  .prod-body { padding: 14px 14px 16px; }
  .prod-add { width: 100%; }
  /* Reflow the cart row: tick + thumbnail + name on top with the line price and the
     unticked note under the name, then a full-width control bar - qty stepper on the
     left, Save for later and the Remove bin on the right. Both controls share the bar's
     one cell; where they cannot fit side by side (the narrowest phones, below) the
     actions take a row of their own. */
  .cart-row {
    grid-template-columns: 24px 64px minmax(0, 1fr);
    grid-template-areas:
      "pick img info"
      "pick img price"
      "pick note note"
      "bar  bar  bar";
    column-gap: 12px; padding: 14px 16px 12px;
  }
  .cart-row .img { width: 64px; height: 64px; align-self: start; }
  .cart-row .info { align-self: start; }
  .cart-row .name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
  .cart-row .each { display: none; }
  .cart-row .price { justify-self: start; margin-top: 2px; font-size: 16px; }
  .cart-row .qty, .cart-row .row-acts { grid-area: bar; margin-top: 12px; }
  .cart-row .qty { justify-self: start; }
  .cart-row .qty input { width: 40px; }
  .cart-row .row-acts { justify-self: end; align-self: center; margin-left: 0; margin-right: -8px; }
  .cart-row .rm span { display: none; }
  .cart-row .rm svg { display: block; }
  .cart-row.sold { grid-template-columns: 24px 64px minmax(0, 1fr); grid-template-areas: ". img info" "sold sold sold"; }
  .cart-row.sold .info { align-self: center; }
  .cart-row .sold-actions { justify-self: start; margin: 4px 0 -8px -8px; }
  .cta-strip { padding: 32px 28px; flex-direction: column; align-items: flex-start; gap: 22px; }
  .cta-strip .btn-primary { width: 100%; justify-content: center; }
  /* Icon alone is enough; frees room for the hamburger. The account pill drops its
     label on the same rule - four labelled controls never fit a 320px bar. */
  .cart-label, .account-label { display: none; }
  /* Footer: brand + Visit span full width; the two short link lists (Shop,
     Company) sit side by side so the footer reads as an intentional block,
     not one long stacked dump. */
  footer { padding: 52px 0 32px; }
  .foot-grid { grid-template-columns: 1fr 1fr; gap: 32px 28px; }
  .foot-grid > div:first-child,
  .foot-grid > div:last-child { grid-column: 1 / -1; }
  footer .foot-grid > div > a { padding: 11px 0; }   /* comfortable tap height on touch */
  .foot-bottom { flex-direction: column; align-items: flex-start; gap: 6px; margin-top: 36px; }
  .foot-credit { margin: -11px 0; }
  .foot-credit-logo { height: 22px; }

  .filter-list label { padding: 11px 8px; }          /* roomier filter rows on touch */
}

/* ---- Homepage mobile order + rails ("Direction C", <=640px ONLY) -----------
   The phone reorders the landing into a dense storefront: hero -> category
   image tiles -> featured rail -> brand strip -> why
   buy -> WhatsApp CTA -> footer. Desktop is untouched: every rule lives in
   this block, and the mobile-only element (.cat-tiles) is
   display:none outside it. Reordering reuses the contact page's `order`
   pattern; `.landing` dissolves (display:contents) so
   its three children order independently of the sibling sections. */
@media (max-width: 640px) {
  .home { display: flex; flex-direction: column; }
  /* Default slot 5 (between Featured and the brand strip): a homepage section
     with no explicit order lands there instead of jumping above the hero. */
  .home > * { order: 5; }
  .home .landing { display: contents; }
  .home .hero-band { order: 1; }
  .home #categories { order: 2; }
  .home #featured { order: 4; }
  .home .brand-strip { order: 6; }
  .home #why { order: 7; }
  .home #cta { order: 8; }
  /* The value strip's five claims are verbatim the "Why buy" checklist below -
     a phone shouldn't scroll the same pitch twice. Desktop keeps it. */
  .home .valuestrip { display: none; }

  /* Shared horizontal rail: native scroll-snap, same pattern as the PDP
     .g-track. The phone home's Deals rail reuses this class. Its scroll
     region is exempted in scripts/responsive-test.mjs alongside
     .brand-track/.g-track. */
  .rail-m {
    display: flex; gap: 12px;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .rail-m::-webkit-scrollbar { display: none; }
  .rail-m > * { flex: 0 0 auto; min-width: 0; scroll-snap-align: start; }

  /* Featured becomes a product rail of lean cards: two and a bit visible, so the
     peek advertises the swipe; all 8 products stay (vs a vertical 2.2-screen wall).
     The heading and its link share one row so the first product sits no lower than
     it did before the category tiles grew taller than the old chip row. */
  #featured .rail-m > * { flex-basis: 156px; }
  .home #featured { padding: 16px 0 30px; }
  .home #featured .section-head { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 12px; margin-bottom: 12px; }
  .home #featured .section-head > div { display: contents; }
  .home #featured .section-head h2 { font-size: 22px; }
  .home #featured .section-head p { order: 3; flex-basis: 100%; margin: 0; font-size: 13px; }

  /* The four department cards give way to a swipeable row of category image tiles
     directly under the hero (.cat-tiles, filled from /api/meta by index.html). */
  .home #categories { padding: 16px 0 6px; }
  .home #categories .section-head, .home #categories .cat-grid { display: none; }
  /* 88px tiles: three and a half show at 390px, so the cut-off fourth advertises the swipe. */
  .cat-tiles.rail-m { gap: 10px; scroll-snap-type: x proximity; min-height: 122px; }
  .cat-tile { width: 88px; display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--ink); text-align: center; line-height: 1.25; }
  .ct-img { width: 84px; height: 84px; flex: 0 0 auto; display: grid; place-items: center; padding: 10px; border-radius: 16px; background: #fff; border: 1px solid var(--line); overflow: hidden; }
  .ct-img img { min-width: 0; min-height: 0; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
  .cat-tile-all .ct-img { background: var(--paper-2); color: var(--navy); }

  /* The contact band is desktop/tablet only. Its whole band goes on a phone -
     not just the card - so no empty tinted stripe is left behind; the footer
     + /contact keep the full showroom/phone/hours details. */
  .home .hero-card-band { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .brand-strip-inner { animation: none; }
  * { scroll-behavior: auto !important; }
  /* No motion: the search field and the filter drawer change state instantly. */
  .nav-search-input, .filters, .filters-backdrop { transition: none !important; }
  /* No motion: the Shop shimmer + We're-hiring underline rest in their idle state. */
  .nav-shop-label { animation: none; background: none; -webkit-text-fill-color: var(--muted); }
  .nav-hiring::before { animation: none; transform: scaleX(0); }
}

/* ---- Info pages (About / Parts / Employment) ---------------------------- */
.page-head { padding: 140px 0 44px; border-bottom: 1px solid var(--line);
  background: radial-gradient(circle at 88% 10%, rgba(111,168,214,.16), transparent 46%), linear-gradient(180deg, #FBFDFF 0%, var(--paper) 100%); }
.page-head .container { max-width: 900px; }
.page-head h1 { font-size: clamp(34px, 5vw, 56px); color: var(--navy-2); margin: 14px 0 0; }
.page-lead { font-size: 19px; color: var(--muted); margin: 18px 0 0; max-width: 62ch; line-height: 1.6; }
.page-body { padding: 60px 0 84px; }
.page-body .container { max-width: 900px; }
.prose h2 { font-size: clamp(24px, 3vw, 32px); color: var(--navy-2); margin: 46px 0 14px; }
.prose h2:first-child { margin-top: 0; }
.prose p { color: var(--ink); font-size: 16.5px; line-height: 1.75; margin: 0 0 16px; }
.brand-list { display: flex; flex-wrap: wrap; gap: 10px; margin: 20px 0 0; }
.brand-list span { border: 1px solid var(--line); border-radius: 100px; padding: 7px 16px; font-size: 14px; color: var(--navy); font-weight: 500; background: var(--card); }
.info-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 18px; margin: 24px 0 0; }
.info-card { border: 1px solid var(--line); border-radius: 14px; padding: 24px; background: var(--card); box-shadow: var(--shadow-sm); }
.info-card h3 { font-size: 19px; color: var(--navy-2); margin: 0 0 8px; }
.info-card p { color: var(--muted); font-size: 14.5px; margin: 0; line-height: 1.6; }
.info-card a { color: var(--navy-2); font-weight: 600; }
.callout { margin: 34px 0 0; background: linear-gradient(135deg, #013a73, var(--navy-2)); color: #fff; border-radius: 18px; padding: 32px 36px; }
/* h2 as well as h3: pages whose callout is the first heading under the <h1> (e.g. /faq,
   where the FAQ list itself contributes no headings) must not skip a level. */
.callout h2, .callout h3 { color: #fff; font-size: 23px; margin: 0 0 10px; }
.callout p { color: rgba(255,255,255,.82); margin: 0 0 8px; font-size: 15px; line-height: 1.6; }
.callout a { color: var(--sky-bright); font-weight: 600; }
/* Standalone phone/CTA links sitting directly in a callout get a comfortable tap
   height (prose links nested in <p> keep their inline flow). */
.callout > a { display: inline-flex; align-items: center; min-height: 44px; }
.callout .big { font-family: var(--display); font-size: 26px; color: #fff; display: inline-block; margin-top: 2px; }
.closing { margin: 46px 0 0; text-align: center; font-family: var(--display); font-style: italic; font-size: clamp(22px, 3vw, 30px); color: var(--navy-2); line-height: 1.3; }
.page-cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 34px; }
@media (max-width: 640px) { .info-grid { grid-template-columns: 1fr; } }

/* ---- Contact page (Direction B: full-bleed map wall + light editorial panel) ---
   Two columns edge-to-edge: LEFT an immersive Google-Maps "map wall" (no frame /
   radius, floating action pills - the same full-bleed language as the homepage
   hero band); RIGHT a light editorial panel carrying the title + lead, hairline
   detail rows (NOT boxed cards), and the contact form. DESKTOP: `.contact-b`
   clears the fixed nav with `padding-top`, and the two-up section is sized so
   nav + section = 100vh (the map wall starts BELOW the nav and fills the
   viewport; the panel fills the same height and scrolls INSIDE itself if its
   content is taller - footer sits below the fold). MOBILE is form-first: the
   panel leads (title, form, then details) and the map wall drops to the bottom
   (see the max-width:900 block). */
.contact-b { padding-top: 72px; }   /* nav clearance (nav is ~69px); map starts below it */
.cb-split { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: minmax(0, 1fr);
  align-items: stretch; height: calc(100vh - 72px); }
.cb-mapcol { position: relative; background: var(--navy-2); grid-column: 1; grid-row: 1; }   /* after the panel in the document (contact.html) */
.cb-mapwall { position: absolute; inset: 0; }
.cb-mapwall iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
.cb-mapwall-actions { position: absolute; left: 22px; bottom: 22px; display: flex; flex-wrap: wrap; gap: 10px;
  background: rgba(6,36,63,.72); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  padding: 10px; border-radius: 100px; max-width: calc(100% - 44px); }
/* Panel fills the section height; min-height:0 + overflow-y let a tall form scroll
   inside the panel instead of overflowing the 100vh section. */
.cb-panel { background: var(--card); padding: 48px 52px 56px; display: flex; flex-direction: column;
  min-height: 0; overflow-y: auto; }

.cb-tl { margin-bottom: 22px; }
.cb-tl h1 { font-size: clamp(28px, 3vw, 40px); color: var(--navy-2); line-height: 1.06; }
.cb-lead { font-family: var(--prose); font-size: 16px; color: var(--ink); margin: 12px 0 0; max-width: 56ch; line-height: 1.62; }
.cb-lead b { color: var(--navy-2); }

.cb-details { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--line); margin: 0 0 30px; }
.cb-d { padding: 16px 4px; border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 5px; }
.cb-d:nth-child(odd) { padding-right: 18px; }
.cb-lab { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--navy); font-weight: 700; }
.cb-v { font-size: 14px; color: var(--navy-2); line-height: 1.6; font-family: var(--prose); margin: 0; }
/* Detail tel:/mailto: links are inline prose links (WCAG 2.5.5 inline exception -
   the audit exempts inline <a> inside a <p>); keep them display:inline. */
.cb-v a { color: var(--navy-2); font-weight: 600; }
.cb-v a:hover { color: var(--azure); }

.cb-formwrap h2 { font-size: 22px; color: var(--navy-2); margin: 0 0 18px; }

/* Contact form - scoped to .cform so checkout/admin inputs are untouched. The
   .cform-line variant renders the light-panel fields as editorial underlines. */
.cform { display: flex; flex-direction: column; gap: 14px; }
.cform .frow2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.cform .fld { display: flex; flex-direction: column; gap: 6px; }
.cform .fld > span { font-size: 13px; font-weight: 600; color: var(--navy-2); }
.cform .fld > span i { color: var(--muted); font-weight: 400; font-style: normal; }
.cform .req { color: var(--crimson); }
.cform input, .cform select, .cform textarea { width: 100%; font-family: var(--font); font-size: 15px; min-height: 46px; color: var(--ink); }
.cform textarea { min-height: 104px; resize: vertical; font-family: var(--prose); }
.cform ::placeholder { color: var(--muted); opacity: 1; }
.cform-line input, .cform-line select, .cform-line textarea { border: 0; border-bottom: 1.5px solid var(--line-2); border-radius: 0; background: transparent; padding: 11px 2px; }
.cform-line input:focus, .cform-line select:focus, .cform-line textarea:focus { border-bottom-color: var(--azure); box-shadow: none; outline: none; }
.fbtns { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 4px; }
.fbtns .wa-btn { width: auto; }
/* Honeypot kept in the DOM (for bots) but pulled out of the visual + a11y flow;
   the input is opacity:0 + pointer-events:none so it is inert and exempt from the
   tap-target audit (a real user never sees or focuses it). */
.cf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.cf-hp input { opacity: 0; pointer-events: none; }
.cf-status { margin: 2px 0 0; font-size: 14px; font-weight: 600; line-height: 1.5; }
.cf-status.ok { color: var(--whatsapp); }
.cf-status.err { color: var(--crimson); }

@media (max-width: 900px) {
  /* Mobile is form-first: drop the desktop 100vh two-up. The panel leads (title,
     then form via order, then details) and the map wall moves to the bottom, so a
     phone visitor lands on the message form. The panel's card bg runs up behind
     the fixed nav; its top padding clears the nav. */
  .contact-b { padding-top: 0; }
  .cb-split { grid-template-columns: 1fr; grid-template-rows: none; height: auto; }
  .cb-mapcol { min-height: 0; height: 58svh; grid-column: auto; grid-row: auto; }
  .cb-panel { padding: 78px 20px 56px; overflow: visible; }
  .cb-formwrap { order: 1; }
  .cb-details { order: 2; }
  .cb-formwrap h2 { font-size: 20px; }
}
@media (max-width: 560px) {
  .cform .frow2 { grid-template-columns: 1fr; }
  .cb-details { grid-template-columns: 1fr; }
  .cb-d:nth-child(odd) { padding-right: 4px; }
  .cb-mapcol { height: 52svh; min-height: 280px; }
  .fbtns { flex-direction: column; align-items: stretch; }
  .fbtns .btn { width: 100%; }
}

/* ---- FAQ (About + /faq) ------------------------------------------------- */
.faq { margin: 46px 0 0; }
.faq-item { border: 1px solid var(--line); border-radius: 12px; margin: 12px 0 0; background: var(--card); overflow: hidden; }
.faq-item summary { cursor: pointer; list-style: none; padding: 16px 20px; font-family: var(--display); font-weight: 600; font-size: 17px; color: var(--navy-2); display: flex; justify-content: space-between; align-items: center; gap: 14px; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: '+'; color: var(--azure); font-size: 22px; line-height: 1; transition: transform .2s ease; }
.faq-item[open] summary::after { content: '−'; }
.faq-item p { font-family: var(--prose); color: var(--ink); font-size: 16px; line-height: 1.7; margin: 0; padding: 0 20px 18px; }
/* An admin-written answer is the only FAQ prose that can carry a link or bold
   (renderAnswer() in server/faq.js allows exactly those two). Without this the anchor
   inherits body ink and reads as plain text - a link nobody can see is not a link.
   --azure is the theme's documented link accent and is AA on --card (contrast-test). */
.faq-item p a { color: var(--azure); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.faq-item p a:hover { color: var(--navy-2); }
.faq-item p strong { font-weight: 700; color: var(--navy-2); }

/* /faq with nothing published yet - an intentional "not written yet" state, not a
   broken page. Mirrors .clearance-empty's visual language (the other page-level empty
   state) with tighter padding, because the contact callout sits directly beneath it. */
.faq-empty { text-align: center; padding: 46px 0 8px; }
.faq-empty h2 { font-size: clamp(22px, 3vw, 30px); color: var(--navy-2); }
.faq-empty p { margin: 12px auto 0; max-width: 52ch; color: var(--muted); font-size: 16px; line-height: 1.7; }

/* ---- Hiring bar (home) - absolute overlay, dismissible; no layout effect -- */
.hiring-bar {
  position: absolute; top: 62px; left: 0; right: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center; gap: 14px;
  background: linear-gradient(90deg, #013a73, var(--navy-2)); color: #fff;
  padding: 10px 46px; font-size: 14px; text-align: center; border-bottom: 1px solid rgba(111,168,214,.25);
}
.hiring-bar.closed { display: none; }
.hiring-bar .hb-link { display: inline-flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; color: inherit; }
.hiring-bar .hb-tag { background: var(--signal); color: #fff; font-weight: 700; font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; padding: 3px 11px; border-radius: 100px; }
.hiring-bar .hb-msg { color: rgba(255,255,255,.92); }
.hiring-bar .hb-cta { color: var(--sky-bright); font-weight: 600; white-space: nowrap; }
.hiring-bar .hb-link:hover .hb-cta { text-decoration: underline; }
.hb-close { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); width: 26px; height: 26px; border-radius: 50%; color: rgba(255,255,255,.85); font-size: 19px; line-height: 1; display: grid; place-items: center; transition: background .2s, color .2s; }
.hb-close:hover { background: rgba(255,255,255,.16); color: #fff; }

/* ---- Brand logo row (info pages - replaces brand chips) ----------------- */
.brand-row { display: flex; flex-wrap: wrap; align-items: center; gap: 22px 40px; margin: 22px 0 0; }
.brand-row .bitem { margin-right: 0; height: 46px; }  /* same 46px logo band + gap as the home marquee (.bitem) so all three surfaces size the roster identically */

/* ---- Employment lead: urgently-hiring repair-tech section --------------- */
.btn-ghost-light { background: transparent; border-color: rgba(255,255,255,.4); color: #fff; }
.btn-ghost-light:hover { border-color: #fff; background: rgba(255,255,255,.08); color: #fff; }

/* ---- /employment: "We're hiring" (modelled on ACH's own recruitment flyer) --------
   One continuous deep-blue field (navy gradient + faint diagonal stripes + two glossy
   CSS streaks) under an image-led hero, white slanted role banners, white rounded cards
   with signal-blue check icons, a white "join our team" band with the --sun APPLY pill,
   and three white contact tiles. --sun is the flyer's warm yellow and is scoped to this
   page only (see the token comment). Fonts are the site's own: Noto Sans 800 uppercase
   carries the flyer's condensed display feel. */
/* Nav clearance (home/contact convention): the dark page starts below the fixed nav,
   so the translucent nav frosts over the paper body instead of reading as a solid
   grey bar on the navy field. */
.hire-page { position: relative; isolation: isolate; color: #fff; overflow: hidden; margin-top: 72px;
  background: linear-gradient(160deg, var(--navy-2) 0%, #013a73 45%, #0A4C8C 100%); }
.hire-page::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: repeating-linear-gradient(-34deg, rgba(255,255,255,.045) 0 3px, transparent 3px 26px); }
.hire-page::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(112deg, transparent 22%, rgba(255,255,255,.16) 33%, transparent 39%),
    linear-gradient(112deg, transparent 58%, rgba(255,255,255,.09) 66%, transparent 71%); }
/* Image-led hero (homepage hero-band pattern): the generated 21:9 banner fills the
   section absolutely (`.hire-hero-media`, <picture> with the 3x2 / 4x3 tiers), a
   left-heavy navy scrim keeps the copy on its clear left third legible (white >= 8:1,
   --sun >= 5:1 over the pale wall under the .85 stop), and the copy sits on top. */
.hire-hero { position: relative; isolation: isolate; display: flex; align-items: center; min-height: min(760px, 88vh); padding: 46px 0 56px; overflow: hidden; }
.hire-hero picture { display: contents; }
.hire-hero-media { position: absolute; left: 0; right: 0; top: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; object-position: 62% 25%; display: block; }
.hire-hero-scrim { position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(90deg, rgba(6,36,63,.94) 0%, rgba(6,36,63,.86) 36%, rgba(6,36,63,.42) 58%, rgba(6,36,63,.10) 100%),
    linear-gradient(180deg, rgba(6,36,63,.55) 0%, rgba(6,36,63,0) 28%, rgba(6,36,63,0) 78%, var(--navy-2) 100%); }
.hire-hero-inner { width: 100%; max-width: 1240px; margin: 0 auto; padding: 0 28px; }
.hire-hero-copy { max-width: 620px; }
.hire-title { display: inline-grid; font-family: var(--display); font-weight: 800; text-transform: uppercase; line-height: .88; letter-spacing: -0.035em;
  font-size: clamp(64px, 10.5vw, 150px); transform: rotate(-4deg); transform-origin: left bottom; margin: 6px 0 30px 6px;
  text-shadow: 0 12px 34px rgba(0,0,0,.4); }
.hire-title-a { color: #fff; }
.hire-title-b { color: var(--sun); padding-left: .32em; }
.hire-lead { font-family: var(--prose); color: rgba(255,255,255,.9); font-size: clamp(16px, 1.4vw, 19px); line-height: 1.6; max-width: 52ch; margin: 0 0 28px; }
.hire-hero-cta { display: flex; flex-wrap: wrap; gap: 14px; }
/* The --sun pill: dark text on the warm fill (10:1); hover lightens the fill. */
.btn-sun { background: var(--sun); color: var(--navy-2); font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; font-size: 16.5px; padding: 15px 32px;
  box-shadow: 0 14px 28px -14px rgba(0,0,0,.6); }
.btn-sun:hover { background: #FFD65C; color: var(--navy-2); }
/* Roles */
.hire-roles { max-width: 1040px; margin: 0 auto; padding: 52px 28px 40px; display: grid; gap: 52px; }
.hire-banner { display: inline-block; background: #fff; color: var(--navy-2); font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: -0.02em;
  font-size: clamp(24px, 3.6vw, 40px); line-height: 1; padding: 13px 26px 11px 20px; margin: 0 0 18px 8px; transform: skewX(-9deg); box-shadow: 0 16px 30px -18px rgba(0,0,0,.6); }
.hire-banner span { display: inline-block; transform: skewX(9deg); }
.hire-intro { display: flex; align-items: flex-start; gap: 12px; font-family: var(--prose); color: rgba(255,255,255,.92); font-size: 17px; line-height: 1.55; max-width: 62ch; margin: 0 0 18px; }
.hire-hex { fill: var(--signal); flex: 0 0 auto; }
.hire-intro .hire-hex { fill: #fff; }
.hire-intro .hire-hex path + path { stroke: var(--navy-2); }
.hire-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.hire-card { background: var(--card); color: var(--ink); border-radius: 18px; padding: 22px 24px 24px; }
.hire-card h3 { display: flex; align-items: center; gap: 10px; font-size: 17px; font-weight: 800; text-transform: uppercase; letter-spacing: .03em; color: var(--navy-2); margin: 0 0 14px; }
.hire-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.hire-list li { display: flex; align-items: flex-start; gap: 10px; font-size: 15px; line-height: 1.5; }
.hire-check { fill: var(--signal); flex: 0 0 auto; margin-top: 2px; }
/* Band */
.hire-band { background: #fff; color: var(--navy-2); }
.hire-band-inner { max-width: 1040px; margin: 0 auto; padding: 24px 28px; display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.hire-band-copy { display: flex; align-items: center; gap: 16px; flex: 1 1 420px; }
.hire-band-ic { fill: var(--signal); flex: 0 0 auto; }
.hire-band h2 { font-size: clamp(22px, 3vw, 32px); font-weight: 800; font-style: italic; text-transform: uppercase; letter-spacing: -0.02em; line-height: 1.02; color: var(--navy-2); }
.hire-band h2 b { color: var(--azure); }
.hire-band p { font-family: var(--prose); color: var(--muted); font-size: 14.5px; line-height: 1.55; max-width: 60ch; margin: 8px 0 0; }
/* Contact tiles */
.hire-contact { max-width: 1040px; margin: 0 auto; padding: 36px 28px 60px; }
.hire-tiles { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 16px; }
.hire-tile { display: grid; grid-template-columns: 48px minmax(0,1fr); column-gap: 14px; align-items: center; background: var(--card); color: var(--ink); border-radius: 16px; padding: 16px 18px; min-height: 80px;
  transition: transform .2s, box-shadow .2s; }
.hire-tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.hire-tile-ic { grid-row: span 2; width: 48px; height: 48px; border-radius: 50%; background: var(--signal); color: #fff; display: grid; place-items: center; }
.hire-tile-ic svg { fill: currentColor; }
.hire-tile-wa .hire-tile-ic { background: var(--whatsapp); }
.hire-tile-k { font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: .1em; font-size: 12.5px; color: var(--navy-2); }
.hire-tile-v { font-weight: 600; font-size: 15px; color: var(--azure); overflow-wrap: anywhere; }
.hire-fine { font-family: var(--prose); color: rgba(255,255,255,.84); font-size: 14px; line-height: 1.65; max-width: 80ch; margin: 26px 0 0; }
.hire-fine a { color: #fff; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.hire-fine a:hover { color: var(--sun); }
@media (max-width: 900px) {
  /* Stacked: the copy sits on the navy field and the banner becomes a photo band beneath
     it (a scrim heavy enough for AA body text left the technician a ghost behind the
     headline). Only the band's top/bottom edges fade into the field. */
  .hire-hero { display: flex; flex-direction: column; min-height: 0; padding: 24px 0 0; }
  .hire-hero-copy { padding-bottom: 30px; }
  /* The band's size lives on the <picture> (stretched to the column, ratio set here), not
     on the <img>: an <img> that has not picked its <source> yet has no width to take a
     ratio from, so the first frame painted the openings where the photo goes and the
     photo then pushed them down. */
  .hire-hero picture { display: block; position: relative; order: 2; align-self: stretch; aspect-ratio: 3 / 2; }
  .hire-hero picture::after { content: ""; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(180deg, var(--navy-2) 0%, rgba(6,36,63,0) 22%, rgba(6,36,63,0) 80%, var(--navy-2) 100%); }
  .hire-hero-media { position: relative; top: 0; z-index: auto; height: 100%; object-position: 70% 20%; }
  .hire-hero-scrim { display: none; }
}
@media (max-width: 640px) { .hire-hero picture { aspect-ratio: 4 / 3; } }
@media (max-width: 640px) {
  .hire-page { margin-top: var(--phone-header-h); }   /* phones: the solid app header's height */
  .hire-cards, .hire-tiles { grid-template-columns: 1fr; }
  .hire-hero-cta .btn, .hire-band .btn-sun { width: 100%; }
  .hire-title { margin-left: 4px; }
  .hire-banner { margin-left: 6px; }
}

/* ---- Online job application (/employment/apply) ---------------------------
   The paper "Application for Employment" as a form: a navy masthead that carries
   on from the /employment page, then the form's sections as cards on the paper
   surface. Fields reuse the .cform system; this block adds the page layout, the
   Yes/No question rows, the repeatable rows and the inline error state. */
.apply-page { margin-top: 72px; }
.apply-head { color: #fff; background: linear-gradient(160deg, var(--navy-2) 0%, #013a73 45%, #0A4C8C 100%); }
.apply-head-inner { max-width: 880px; margin: 0 auto; padding: 34px 28px 40px; }
.apply-back { display: inline-flex; align-items: center; min-height: 44px; color: rgba(255,255,255,.86); font-weight: 600; font-size: 14px; }
.apply-back:hover { color: #fff; text-decoration: underline; }
.apply-head h1 { font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: -.02em; font-size: clamp(30px, 5.2vw, 50px); line-height: 1; margin: 6px 0 14px; }
.apply-head p { font-family: var(--prose); color: rgba(255,255,255,.9); font-size: 16px; line-height: 1.6; max-width: 56ch; margin: 0 0 22px; }
.apply-body { max-width: 880px; margin: 0 auto; padding: 30px 28px 90px; display: grid; gap: 22px; }
.apply-notice { border-left: 4px solid var(--navy); background: var(--paper-2); border-radius: 0 var(--radius) var(--radius) 0; padding: 20px 24px; }
.apply-notice p { font-family: var(--prose); font-size: 14px; line-height: 1.65; color: var(--ink); margin: 0 0 10px; }
.apply-notice p:last-child { margin-bottom: 0; }
.apply-notice b { font-family: var(--font); color: var(--navy-2); }
.apply-form { gap: 22px; }
/* The author display values on .btn / .fld would otherwise defeat [hidden]. */
.apply-page [hidden] { display: none !important; }
.apply-card { display: flex; flex-direction: column; gap: 18px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 28px 30px 30px; }
.apply-card h2 { font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: .02em; font-size: 19px; color: var(--navy-2); padding-bottom: 12px; border-bottom: 2px solid var(--navy-2); }
.apply-help { font-family: var(--prose); font-size: 14px; line-height: 1.65; color: var(--muted); margin: 0; }
.apply-help b { font-family: var(--font); color: var(--navy-2); }
/* Each field is a 3-row subgrid (label / control / error) so the controls of a row
   stay on one line whether a neighbour's label wraps or shows an error. The 8px
   row gap plus the empty error row's 6px equals the form's 14px rhythm. */
.apply-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; }
.apply-grid > .fld { display: grid; grid-template-rows: subgrid; grid-row: span 3; row-gap: 6px; }
.apply-grid > .fld > span { align-self: end; }
.apply-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.apply-grid-name { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 132px; }
.apply-wide { grid-column: 1 / -1; }
.apply-form textarea { background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; outline: none; font-size: 15px; line-height: 1.5; transition: border-color .2s, box-shadow .2s; }
.apply-form textarea:focus { border-color: var(--azure); box-shadow: 0 0 0 3px rgba(30,111,176,.15); }
.apply-form input, .apply-form select, .apply-form textarea { border-color: var(--line-2); }
.apply-form fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.apply-form legend { padding: 0; }
/* A Yes/No (or tick-any) question: the legend is the question, the options are
   chips whose whole 46px box is the tap target. */
.apply-q { display: flex; flex-direction: column; gap: 10px; }
.apply-q > legend { font-size: 14.5px; font-weight: 600; line-height: 1.5; color: var(--navy-2); margin-bottom: 10px; }
.apply-q > legend i, .apply-sub > legend i { color: var(--muted); font-weight: 400; font-style: normal; }
.apply-opts { display: flex; flex-wrap: wrap; gap: 10px; }
.apply-opt { display: inline-flex; align-items: center; gap: 10px; min-height: 46px; padding: 0 18px 0 14px; border: 1px solid var(--line-2); border-radius: 100px; background: var(--card); font-size: 15px; font-weight: 500; color: var(--ink); cursor: pointer; transition: border-color .2s, background .2s; }
.apply-opt:hover { border-color: var(--navy); }
.apply-opt:has(input:checked) { border-color: var(--navy); background: var(--paper-2); color: var(--navy-2); font-weight: 600; }
.apply-opt:has(input:focus-visible) { box-shadow: 0 0 0 3px rgba(30,111,176,.3); }
.apply-form .apply-opt input { width: 20px; height: 20px; min-height: 0; padding: 0; margin: 0; flex: 0 0 auto; accent-color: var(--navy); box-shadow: none; }
/* A group of related fields (other names, one employer, one school). */
.apply-sub { display: flex; flex-direction: column; gap: 14px; background: var(--paper); border: 1px solid var(--line) !important; border-radius: 12px; padding: 18px 18px 20px !important; }
.apply-sub > legend { float: left; width: 100%; font-family: var(--display); font-weight: 700; font-size: 14px; letter-spacing: .04em; text-transform: uppercase; color: var(--navy-2); margin-bottom: 2px; }
.apply-sub > legend + * { clear: both; }
.apply-plain { background: transparent; border: 0 !important; padding: 0 !important; }
.apply-rows { display: flex; flex-direction: column; gap: 14px; counter-reset: apply-row; }
.apply-rows > .apply-sub { counter-increment: apply-row; }
.apply-rows > .apply-sub > legend::after { content: " " counter(apply-row); }
.apply-row { display: flex; flex-direction: column; gap: 10px; }
.apply-add { align-self: flex-start; background: var(--card); }
.apply-remove { align-self: flex-start; min-height: 44px; padding: 0 4px; color: var(--crimson); font-weight: 600; font-size: 14px; }
.apply-remove:hover { text-decoration: underline; }
/* Statement + its initials box. */
.apply-stmt { display: grid; grid-template-columns: minmax(0, 1fr) 128px; gap: 20px; align-items: start; padding-bottom: 18px; border-bottom: 1px solid var(--line); }
.apply-stmt p, .apply-final { font-family: var(--prose); font-size: 14px; line-height: 1.65; color: var(--ink); margin: 0; }
.apply-initials input { text-transform: uppercase; text-align: center; letter-spacing: .12em; font-weight: 600; }
.apply-sign { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; }
.apply-date { display: flex; align-items: center; min-height: 46px; font-size: 15px; font-weight: 600; color: var(--navy-2); border-bottom: 1.5px solid var(--line-2); }
/* Inline error: crimson rule + message under the field it belongs to. */
.fld-err { margin: 0; font-size: 13px; font-weight: 600; color: var(--crimson); }
.apply-form .has-err > input, .apply-form .has-err > select, .apply-form .has-err > textarea { border-color: var(--crimson); }
.apply-form .has-err > input:focus, .apply-form .has-err > textarea:focus { box-shadow: 0 0 0 3px rgba(158,43,37,.15); }
.apply-q.has-err > .apply-opts .apply-opt { border-color: var(--crimson); }
.apply-form .cf-status { font-size: 15px; }
/* Once sent, the masthead drops its "how to apply" line and PDF alternative. */
.apply-page.is-done .apply-head p, .apply-page.is-done .apply-head .btn { display: none; }
.apply-done p { font-family: var(--prose); font-size: 15.5px; line-height: 1.65; margin: 0; }
.apply-done .btn { align-self: flex-start; }
.apply-done:focus { outline: none; }
@media (max-width: 640px) {
  .apply-page { margin-top: var(--phone-header-h); }
  .apply-head-inner { padding: 22px 20px 30px; }
  .apply-head .btn { width: 100%; white-space: normal; text-align: center; }
  .apply-body { padding: 20px 14px 64px; gap: 16px; }
  .apply-form { gap: 16px; }
  .apply-notice { padding: 16px 16px; }
  .apply-card { padding: 22px 16px 24px; }
  .apply-sub { padding: 16px 14px 18px !important; }
  .apply-plain { padding: 0 !important; }
  .apply-grid, .apply-grid-3, .apply-grid-name, .apply-sign { grid-template-columns: 1fr; }
  .apply-stmt { grid-template-columns: 1fr; gap: 12px; }
  .apply-initials { max-width: 160px; }
  .apply-form .fbtns .btn { width: 100%; }
}

/* ---- Category chips (icon + label, on About / Parts) -------------------- */
.cat-chips { display: flex; flex-wrap: wrap; gap: 10px; margin: 20px 0 0; }
.cat-chip { display: inline-flex; align-items: center; gap: 8px; border: 1px solid var(--line); border-radius: 100px; padding: 8px 16px 8px 13px; font-size: 14px; color: var(--navy); font-weight: 500; background: var(--card); }
.cat-chip .cc-ico { color: var(--azure); flex: 0 0 auto; }

/* ---- Product-page gallery (big main image + horizontal filmstrip below) --- */
.pdp-gallery { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
/* The strip scrolls sideways once its thumbs no longer fit. Its padding (taken back by
   the margin, so nothing moves) keeps the hover lift inside the clip and the scrollbar
   off the thumbs; the focus ring is inset for the same reason. */
.pdp-gallery .g-thumbs { display: flex; flex-direction: row; gap: 12px; overflow-x: auto; padding: 4px 0 8px; margin: -4px 0 -8px; scrollbar-width: thin; }
.pdp-gallery .g-thumbs img { flex: 1 1 0; min-width: 0; max-width: 108px; width: auto; height: auto; aspect-ratio: 1/1; object-fit: contain; border: 1px solid var(--line); border-radius: 11px; padding: 8px; background: #fff; cursor: pointer; transition: border-color .15s, transform .15s; }
/* Up to eight photos share the row as above. Nine or more stop shrinking: each keeps
   the size that shows seven and a half, so the cut-off one says there is more. */
.pdp-gallery .g-thumbs img:nth-last-child(n+9),
.pdp-gallery .g-thumbs img:nth-last-child(n+9) ~ img { flex: 0 0 calc((100% - 84px) / 7.5); }
.pdp-gallery .g-thumbs img:hover { border-color: var(--azure); transform: translateY(-2px); }
.pdp-gallery .g-thumbs img:focus-visible { outline: 2px solid var(--azure); outline-offset: -2px; }
.pdp-gallery .g-thumbs img.active { border-color: var(--navy); border-width: 2px; }
.pdp-gallery .g-main { position: relative; background: #fff; border: 1px solid var(--line); border-radius: 22px; aspect-ratio: 4/3; display: grid; place-items: center; padding: 38px; box-shadow: var(--shadow); overflow: hidden; }
/* Covers the desktop main image (#g-main-img) AND every mobile carousel slide
   (.g-slide img is a descendant of .g-main), so both letterbox tall + wide sources. The
   <picture> wrappers (per-width sources, /p/:slug in server/index.js) step aside so each
   <img> stays the box's own grid item. */
.pdp-gallery picture { display: contents; }
.pdp-gallery picture > source { display: none; }   /* else it is an empty grid item beside the photo, pushing it off centre */
.pdp-gallery .g-main img { min-width: 0; min-height: 0; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; transition: opacity .2s, transform .3s ease; }
@media (min-width: 901px) and (hover: hover) and (prefers-reduced-motion: no-preference) {
  .pdp-gallery:not(.single) .g-main:hover #g-main-img { transform: scale(1.12); }
}
@media (prefers-reduced-motion: no-preference) { .pdp-gallery .g-thumbs { scroll-behavior: smooth; } }
.pdp-gallery .g-zoom { position: absolute; top: 16px; left: 16px; z-index: 2; font-size: 12px; font-weight: 600; color: var(--navy); background: rgba(255,255,255,.85); border: 1px solid var(--line); border-radius: 100px; padding: 5px 13px; display: inline-flex; gap: 6px; align-items: center; }
.pdp-gallery .g-count { position: absolute; bottom: 14px; right: 16px; font-size: 12px; color: var(--muted); background: var(--paper-2); border-radius: 100px; padding: 3px 11px; }
/* Mobile swipe carousel + dots: hidden on desktop, shown only at <=520px below. */
.pdp-gallery .g-track,
.pdp-gallery .g-dots { display: none; }
@media (max-width: 520px) {
  /* Mobile: the main image reverts to a square swipe carousel. */
  .pdp-gallery .g-main { aspect-ratio: 1/1; padding: 24px; }
  /* No thumbnail squares or hover-zoom hint on mobile - the swipe carousel replaces them. */
  .pdp-gallery .g-thumbs,
  .pdp-gallery .g-zoom { display: none; }
  /* The single swap-image + count badge are redundant with the carousel + dots. */
  .pdp-gallery:not(.single) #g-main-img,
  .pdp-gallery .g-count { display: none; }
  /* Horizontal scroll-snap track of full-width slides driven by native touch. */
  .pdp-gallery .g-track {
    display: flex; width: 100%;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .pdp-gallery .g-track::-webkit-scrollbar { display: none; }
  .pdp-gallery .g-slide { flex: 0 0 100%; aspect-ratio: 1/1; display: grid; place-items: center; scroll-snap-align: center; }
  /* Centered, non-interactive dot indicators (swiping navigates, not tapping). */
  .pdp-gallery .g-dots {
    display: flex; justify-content: center; gap: 7px;
    position: absolute; left: 0; right: 0; bottom: 12px;
    pointer-events: none;
  }
  .pdp-gallery .g-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--line); transition: background-color .2s, transform .2s;
  }
  .pdp-gallery .g-dot.active { background: var(--navy); transform: scale(1.25); }
}
@media (prefers-reduced-motion: reduce) {
  .pdp-gallery .g-dot { transition: none; }
}

/* ---- Phone storefront (<=640px ONLY) -----------------------------------------
   Slice 1 rebuilt listing, product and cart behavior. Slice 2 adds the app shell,
   search screen and feed home. Desktop and tablet stay untouched: everything that
   exists only for phones is hidden here, and every phone rule lives in a matching
   media block. Phone-only JS checks the same breakpoint (phoneMq in store.js). */
.shop-count, .shop-bar, .shop-more, .filter-price, .filter-all,
.prod-meta, .sv-amt, .cat-tiles, .pb-get, .pdp-more, .pdp-readmore, .nav-suggest,
.co-days-field, .co-field.co-collector,
.phone-tabs, .phone-more, .phone-search-back, .home-promo-wrap, .home-deals,
.home-trust, .shop-categories, .phone-link,
.home-recent, .order-track, .pdp-save { display: none; }

/* Chip: the listing's filter/sort bar and the search panel's recent searches. */
.chip { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px; border-radius: 100px; border: 1px solid var(--line-2); background: var(--card); color: var(--navy); font-size: 13.5px; font-weight: 600; white-space: nowrap; }
.chip.on { background: var(--navy); border-color: var(--navy); color: #fff; }

/* Bottom sheet: a native <dialog> (openSheet in store.js) pinned to the bottom edge. */
.sheet { position: fixed; inset: auto 0 0 0; z-index: 95; width: 100%; max-width: 640px; max-height: 86vh; max-height: 86svh; margin: 0 auto; padding: 0; border: 0; border-radius: 20px 20px 0 0; background: var(--card); color: var(--ink); box-shadow: 0 -20px 50px -24px rgba(6,36,63,.5); overflow: hidden; }
dialog.sheet:not([open]) { display: none; }   /* for a browser with no <dialog> (see openSheet) */
.sheet[open] { display: flex; animation: sheet-up .26s ease; }
.sheet::backdrop { background: rgba(6,36,63,.42); }
html:has(.sheet[open]) { overflow: hidden; }   /* the page behind does not scroll */
@keyframes sheet-up { from { transform: translateY(100%); } }
.sheet-in { display: flex; flex-direction: column; width: 100%; min-height: 0; max-height: 86vh; max-height: 86svh; }
.sheet-hd { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 18px 6px; }
.sheet-hd h2 { font-size: 19px; color: var(--navy-2); }
.sheet-hd button { min-height: 44px; min-width: 44px; padding: 0 4px; font-size: 14px; font-weight: 600; color: var(--navy); text-align: right; }
.sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px 18px 18px; }
.sheet-ft { flex: 0 0 auto; display: grid; gap: 10px; padding: 12px 18px calc(16px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--line); }
.sheet-opt { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 50px; font-size: 15px; color: var(--ink); text-align: left; border-bottom: 1px solid var(--line); }
.sheet-opt:last-child { border-bottom: 0; }
.sheet-opt::before { content: ''; box-sizing: border-box; flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; border: 1.5px solid var(--line-2); background: var(--card); }
.sheet-opt[aria-pressed="true"] { font-weight: 600; }
.sheet-opt[aria-pressed="true"]::before { border: 6px solid var(--signal); }
.sheet-prose { font-family: var(--prose); font-size: 15.5px; line-height: 1.7; color: var(--ink); margin: 0; }
.sheet-added h2::before { content: '✓'; display: inline-grid; place-items: center; width: 22px; height: 22px; margin-right: 8px; border-radius: 50%; background: var(--whatsapp); color: #fff; font-size: 12px; font-weight: 700; vertical-align: 2px; }
.added { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 14px; align-items: center; padding: 4px 0 2px; }
.added-img { width: 64px; height: 64px; display: grid; place-items: center; padding: 6px; background: #fff; border: 1px solid var(--line); border-radius: 10px; }
.added-img img { max-width: 100%; max-height: 100%; object-fit: contain; }
.added-name { font-size: 14px; font-weight: 500; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.added b { display: block; margin-top: 3px; font-family: var(--display); font-weight: 600; font-size: 16px; color: var(--navy); font-variant-numeric: tabular-nums; }
.pdp-spec { width: 100%; border-collapse: collapse; font-size: 14px; }
.pdp-spec th, .pdp-spec td { text-align: left; padding: 11px 0; border-bottom: 1px solid var(--line); vertical-align: top; font-weight: 400; }
.pdp-spec th { width: 40%; padding-right: 12px; color: var(--muted); }
.pdp-spec td { color: var(--ink); font-weight: 500; }
.sheet .pb-why { display: grid; border-top: 0; padding-top: 4px; }
@media (prefers-reduced-motion: reduce) { .sheet[open] { animation: none; } }

@media (max-width: 640px) {
  /* -- Product card: leaner. The price labels, the regular price and the SALE pill go
     (.prod-card markup: prodCard in store.js); the saving reads as money; the name
     gets a third line because the name is where the specification lives. -- */
  .prod-grid { gap: 10px; }
  .prod-img { aspect-ratio: 7/6; padding: 10px; }
  .prod-body { padding: 10px 12px 12px; gap: 3px; }
  .prod-brand { font-size: 10.5px; }
  .prod-name { font-size: 13.5px; line-height: 1.35; -webkit-line-clamp: 3; line-clamp: 3; min-height: 0; }
  .prod-foot { gap: 8px; padding-top: 6px; }
  /* Fluid for the same reason as the base rule: "$520,000 GYD" must fit a 320px card. */
  .prod-price { font-size: clamp(14.5px, 4.3vw, 16px); }
  .prod-price .pr-lab, .prod-price .pr-reg .rl, .prod-price .pr-reg .rv, .sv-pct, .badge-plain { display: none; }
  .sv-amt { display: inline; white-space: nowrap; }
  .prod-price .pr-reg { margin-top: 2px; }
  .badge-sale { top: 8px; left: 8px; font-size: 10px; padding: 3px 8px; }
  /* Rails (homepage featured, product-page related): two-line names keep every card
     in the row the same height. */
  .rail-m .prod-name { -webkit-line-clamp: 2; line-clamp: 2; min-height: 36px; }

  /* -- Listing: one pinned row of chips ending in the view switch, then the count. The
     title row is gone; its heading stays for screen readers (clip-based sr-only). -- */
  /* minmax(0, ...): the chip row is a no-wrap scroller, and a bare 1fr track would
     grow to its full content width and push the page wide. */
  .shop-layout { grid-template-columns: minmax(0, 1fr); padding-top: calc(var(--phone-header-h) + 12px); padding-bottom: 40px; }
  .shop-top { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0,0,0,0); clip-path: inset(50%); white-space: nowrap; border: 0; }
  .shop-count { display: block; margin: 0 0 10px; color: var(--muted); font-size: 13px; }
  .shop-view { display: flex; flex: 0 0 auto; border: 1px solid var(--line-2); border-radius: 100px; overflow: hidden; background: var(--card); }
  .shop-view button { flex: 0 0 44px; width: 44px; height: 44px; display: grid; place-items: center; color: var(--muted); }
  .shop-view button[aria-pressed="true"] { background: var(--navy); color: #fff; }
  .shop-top .filters-btn, .shop-search, #sort { display: none; }
  /* Sticks directly under the fixed header for the whole list, bled to the screen
     edges so cards never show beside it. */
  .shop-bar {
    display: flex; position: sticky; top: var(--phone-header-h); z-index: 40; gap: 8px; align-items: center;
    margin: 0 -18px 8px; padding: 8px 18px 10px;
    background: var(--paper); border-bottom: 1px solid var(--line);
  }
  /* One line at any filter count, so the pinned bar never grows: Filter, the removable
     chips, then Sort and the shortcuts. The chips fade out before the view switch rather
     than being cut against it; the spacer lets the last chip scroll clear of the fade. A
     long search term truncates inside its chip. */
  .shop-chips { flex: 1 1 auto; min-width: 0; gap: 8px; scroll-snap-type: none;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent); }
  .shop-chips::after { content: ''; flex: 0 0 10px; }
  .shop-chips .chip.on { max-width: 75%; }
  .chip-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .shop-more { display: block; padding: 18px 0 0; text-align: center; }
  .shop-more[hidden] { display: none; }
  .shop-more .btn { width: 100%; }
  .shop-more p { margin: 10px 0 0; font-size: 13px; color: var(--muted); }

  /* One product per row, with the whole name. */
  /* html.is-list: set by shop.html's head script from the remembered choice, so the list
     shows from the first frame; the switch's pressed state follows it until the page
     script syncs aria-pressed. */
  .is-list #grid { grid-template-columns: minmax(0, 1fr); }
  .is-list #grid .prod-card { flex-direction: row; align-items: flex-start; }
  .is-list #grid .prod-img { flex: 0 0 112px; width: 112px; aspect-ratio: 1/1; border-bottom: 0; }
  .is-list #grid .prod-body { min-width: 0; padding: 12px 14px 14px 4px; }
  .is-list #grid .prod-name { display: block; font-size: 14.5px; font-weight: 500; }
  .is-list #grid .prod-meta { display: block; font-size: 12.5px; color: var(--muted); }
  .is-list #grid .prod-add { width: auto; }
  .is-list #grid .badge-sale { top: 6px; left: 6px; }
  .is-list .shop-view [data-view="list"] { background: var(--navy); color: #fff; }
  .is-list .shop-view [data-view="grid"] { background: none; color: var(--muted); }

  /* -- Filters: the drawer becomes a bottom sheet with price bands, short lists and
     a live count on its button. -- */
  .filters {
    top: auto; left: 0; right: 0; bottom: 0; width: 100%; max-height: 86vh; max-height: 86svh;
    padding: 0 18px; gap: 14px; border-radius: 20px 20px 0 0;
    box-shadow: 0 -20px 50px -24px rgba(6,36,63,.5);
    transform: translateY(100%);
  }
  .filters-head { position: sticky; top: 0; z-index: 1; padding: 14px 0 6px; background: var(--paper); }
  .filters-title { font-size: 19px; }
  .filter-price { display: block; }
  .filter-block { scroll-margin-top: 64px; }   /* a jump chip lands a block below the pinned sheet header */
  .price-bands { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .price-bands button { min-height: 52px; padding: 8px 10px; border-radius: 12px; border: 1px solid var(--line-2); background: var(--card); color: var(--ink); font-size: 13.5px; font-weight: 600; }
  .price-bands button[aria-pressed="true"] { border-color: var(--navy); background: var(--paper-2); box-shadow: inset 0 0 0 1px var(--navy); }
  .filter-list { max-height: none; overflow: visible; }
  .filter-list.is-short label:nth-child(n+6) { display: none; }
  .filter-all { display: inline-flex; align-items: center; min-height: 44px; margin-top: 2px; padding: 0 8px; font-size: 14px; font-weight: 600; color: var(--navy); text-decoration: underline; text-underline-offset: 3px; }
  .filter-block.filter-actions {
    position: sticky; bottom: 0; z-index: 1; flex-direction: row; margin: 0 -18px;
    padding: 12px 18px calc(12px + env(safe-area-inset-bottom, 0px));
    border: 0; border-top: 1px solid var(--line); border-radius: 0; box-shadow: none;
  }
  .filter-actions .btn { flex: 1 1 0; min-width: 0; padding: 12px 10px; font-size: 14.5px; }

  /* -- Search: a screen between the header and the tab bar with recent searches and
     popular categories, then live product matches (mountSearchSuggest in store.js). -- */
  .nav-suggest {
    display: block; position: fixed; top: var(--phone-header-h); bottom: var(--phone-tabs-h); left: 0; right: 0;
    overflow-y: auto; overscroll-behavior: contain; padding: 4px 18px 24px; background: var(--paper);
  }
  .nav-suggest[hidden] { display: none; }
  .nav-suggest h3 { margin: 14px 0 8px; font-family: var(--font); font-size: 13px; font-weight: 600; letter-spacing: 0; color: var(--muted); }
  .ns-chips { display: flex; flex-wrap: wrap; gap: 8px; }
  .ns-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; min-height: 48px; padding: 0; font-size: 15px; color: var(--ink); text-align: left; border-bottom: 1px solid var(--line); }
  .ns-row small { color: var(--muted); font-size: 13px; white-space: nowrap; }
  .ns-row:last-child { border-bottom: 0; }
  .ns-all { font-weight: 600; color: var(--navy); }
  .ns-item { display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 12px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--line); }
  .ns-img { width: 52px; height: 52px; display: grid; place-items: center; padding: 4px; background: #fff; border: 1px solid var(--line); border-radius: 10px; }
  .ns-img img { max-width: 100%; max-height: 100%; object-fit: contain; }
  .ns-name { font-size: 14px; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .ns-txt b { display: block; margin-top: 2px; font-family: var(--display); font-weight: 600; font-size: 14.5px; color: var(--navy); font-variant-numeric: tabular-nums; }
  .ns-none { margin: 18px 0 6px; font-size: 14.5px; color: var(--muted); }

  /* -- Homepage category tiles (the tile rules sit with the homepage rail block). -- */
  .cat-tiles { display: flex; }

  /* -- Product page. One set of buttons: the pinned bar (.pdp-mobilebar) is the only
     Add to Cart / WhatsApp, so the inline pair goes; "Buy now" (straight to checkout
     with this product alone) stays, under "How to get it". Long content sits behind rows
     that open as sheets: the ticks, the import comparison and the feature band are
     hidden here and shown on demand (product.html clones them into the sheet). -- */
  .pb { gap: 16px; }
  .pb-badges:not(:has(.pb-clear)) { display: none; }
  .pb-badges .pb-sale, .pdp-price .pr-lab { display: none; }   /* the Save pill by the price says it once */
  .pb-meta { margin-bottom: 12px; }
  .pb-rail .pdp-price { margin-bottom: 12px; }
  .pb-stock:not(.out) + .pb-fulfil { display: none; }   /* replaced by the "How to get it" rows */
  .pb-fulfil { margin-bottom: 0; }
  .pb-buy .pb-qtyrow, .pb-buy .wa-btn, .pb-buy .is-disabled, .pb-rail .pb-why, .pb > .pdp-import, .feature-band { display: none; }
  .pb-buy { margin: 14px 0 0; }
  .pb-get { display: block; margin-top: 16px; }
  .pb-get h2 { margin-bottom: 10px; font-size: 15px; color: var(--navy-2); }
  .pb-getrows, .pdp-rows { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
  .pb-getrow { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 12px; align-items: center; padding: 12px 14px; }
  .pb-getrow + .pb-getrow { border-top: 1px solid var(--line); }
  .pb-getrow .gi { width: 40px; height: 40px; display: grid; place-items: center; border-radius: 12px; background: var(--paper-2); color: var(--navy); }
  .pb-getrow b { display: block; font-size: 14.5px; font-weight: 600; color: var(--navy-2); }
  .pb-getrow small { display: block; font-size: 13px; line-height: 1.35; color: var(--muted); }
  .pdp-wrap { padding-bottom: 0; }
  .pdp-overview { padding: 22px 0 0; }
  .pdp-overview .section-head { margin-bottom: 8px; }
  .pdp-overview .section-head h2 { font-size: 19px; }
  .pdp-overview p { display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; font-size: 15px; line-height: 1.6; }
  .pdp-readmore { display: inline-flex; align-items: center; min-height: 44px; font-size: 14px; font-weight: 600; color: var(--navy); text-decoration: underline; text-underline-offset: 3px; }
  .pdp-readmore[hidden] { display: none; }
  .pdp-more { display: block; margin-top: 14px; }
  .pdp-rows button { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; min-height: 54px; padding: 0 14px; font-size: 15px; font-weight: 500; color: var(--navy-2); text-align: left; }
  .pdp-rows button + button { border-top: 1px solid var(--line); }
  .pdp-rows svg { flex: 0 0 auto; color: var(--muted); }
  /* "You may also like" is a rail, not another screen and a half of grid. */
  .pdp-related { padding: 30px 0 34px; }
  .pdp-related .section-head { margin-bottom: 14px; }
  .pdp-related .section-head h2 { font-size: 22px; }
  #related.rail-m > * { flex-basis: 156px; }

  /* -- Cart and checkout. Both read top to bottom in document order: the title and
     steps, the rows (or the order strip and the form), then the summary card. The
     page's button is pinned: on the cart with this order's count and total beside it,
     on the checkout with the total on it. -- */
  .cart-layout { padding-top: calc(var(--phone-header-h) + 20px); padding-bottom: 28px; }
  .cart-head { font-size: 26px; }
  .cart-sub { margin-top: 6px; font-size: 14px; }
  /* The three steps on one line down to 320px: the joining lines give way first. */
  .co-steps { font-size: 12.5px; }
  .co-steps li { gap: 6px; }
  .co-steps li + li::before { width: clamp(8px, calc(10vw - 22px), 24px); margin: 0 0 0 6px; }
  .co-steps i { width: 22px; height: 22px; }
  .cart-all { padding: 0 17px; }
  .cart-all label { gap: 12px; }
  .cart-saved { padding: 0 16px; }
  .cart-summary { padding: 16px 16px 14px; box-shadow: none; }
  .cart-summary h2 { font-size: 17px; margin-bottom: 4px; }
  .summary-row.total { font-size: 17px; padding-bottom: 4px; }
  .co-sum-head { margin: -6px 0 4px; }
  .co-form { gap: 12px; }
  .co-card { padding: 16px 16px 3px; box-shadow: none; }
  .co-title { margin-bottom: 14px; font-size: 17px; }
  .co-grid { grid-template-columns: minmax(0, 1fr); }
  .co-field input { font-size: 16px; }   /* iOS zooms the page into any field set smaller */
  .co-field.co-time-field { display: none; }
  .co-days-field { display: block; margin-bottom: 14px; }
  .co-days-label { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 600; color: var(--navy-2); }
  .co-days.rail-m { gap: 8px; margin: 0 -16px; padding: 0 16px; scroll-snap-type: none; }
  .co-days button { width: 62px; min-height: 60px; display: flex; flex-direction: column; align-items: center; justify-content: center; border-radius: 12px; border: 1px solid var(--line-2); background: var(--card); font-size: 12px; color: var(--muted); }
  .co-days button b { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--navy-2); }
  .co-days button[aria-pressed="true"] { background: var(--navy); border-color: var(--navy); color: #fff; }
  .co-days button[aria-pressed="true"] b { color: #fff; }
  .co-field.co-collector { display: flex; }
  .co-refused-acts .btn { flex: 1 1 180px; }   /* side by side, or a full row each */
  /* Always on screen, like the product page's buy bar. */
  .cart-orderbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    padding: 10px 18px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--card); border-top: 1px solid var(--line);
    box-shadow: 0 -8px 24px -16px rgba(6,36,63,.5);
  }
  .cart-orderbar #checkout { margin-top: 0; }
  .cart-orderbar .co-pay-note { margin: 6px 0 0; }
  /* The cart's bar: what this order holds on the left, the way to checkout on the right. */
  .cart-bar { display: flex; align-items: center; gap: 14px; }
  .cart-bar-sum { flex: 1; min-width: 0; display: flex; flex-direction: column; margin: 0; font-size: 13px; line-height: 1.35; color: var(--muted); }
  .cart-bar-sum b { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--navy-2); white-space: nowrap; }
  .cart-bar #checkout { flex: 0 0 auto; width: auto; padding-inline: 26px; }
  .cart-bar .co-n { display: none; }
  .cart-summary > .co-pay-note { margin-top: 6px; }
  body.has-orderbar { padding-bottom: 100px; }
}
/* The narrowest phones: the stepper and the row's actions do not fit one bar (below
   346px the row is under 276px wide), so the actions drop to a row of their own. */
@media (max-width: 345px) {
  /* ...and the checkout's order strip keeps one photo, so its total stays on one line. */
  .co-strip .img + .img { display: none; }
  .co-strip-txt b { font-size: 15px; }
  .cart-row { grid-template-areas: "pick img info" "pick img price" "pick note note" "bar bar bar" "acts acts acts"; }
  .cart-row .row-acts { grid-area: acts; justify-self: start; margin: 2px 0 0 -8px; }
}
/* The narrowest phones: the wordmark and the three header controls do not fit one bar
   (at 320px the search button sat on top of "ACH Inc." by ~29px). The badge beside it
   already carries the name, so the wordmark steps aside. */
@media (max-width: 350px) { .nav .brand-name { display: none; } }
/* The phone product gallery (the <=520px swipe carousel above) runs edge to edge,
   and shows its position as a count as well as dots. */
@media (max-width: 520px) {
  .pdp-gallery { margin: 0 -18px; }
  .pdp-gallery .g-main { padding: 12px; border-left: 0; border-right: 0; border-radius: 0; box-shadow: none; }
  .pdp-gallery .g-count { display: block; top: 12px; right: 14px; bottom: auto; }
}

/* ---- Phone app shell (<=640px ONLY) -------------------------------------------
   Slice 2 of the phone redesign: a 60px header (logo + search field), a labelled tab
   bar (Home, Shop, Deals, Cart, More) in place of the hamburger, search and More as
   screens between the two, the feed homepage and the Shop tab's category landing.
   The tab bar gives way to the product page's buy bar, the cart's order bar and the
   pay page's bar, so two bottom bars never stack. */
@media (max-width: 640px) {
  :root {
    --phone-header-h: calc(60px + env(safe-area-inset-top, 0px));
    --phone-tabs-h: calc(64px + env(safe-area-inset-bottom, 0px));
  }
  body.has-tabbar:not(.has-mobilebar):not(.has-orderbar):not(.pay-page) { --tabs-reserve: var(--phone-tabs-h); padding-bottom: var(--tabs-reserve); }
  body.phone-search-open, body.phone-more-open { overflow: hidden; }

  /* -- Header: solid (no blur, which would also make .nav the containing block of
     the fixed search screen), logo + a real search field. -- */
  .nav, .nav.scrolled, .nav.menu-open {
    padding-top: env(safe-area-inset-top, 0px);
    background: var(--card); -webkit-backdrop-filter: none; backdrop-filter: none;
    border-bottom-color: var(--line); box-shadow: none;
  }
  .nav-inner { height: 60px; padding: 0 12px; gap: 10px; }
  .nav .brand-mark { width: 40px; height: 40px; }
  .nav .brand-name, .nav .nav-links, .nav .cart-btn, .nav .account-btn, .nav .nav-toggle { display: none; }
  /* Where the tab bar gives way to the buy bar, the header keeps the cart (icon only). */
  body.has-mobilebar .nav .cart-btn { display: inline-flex; flex: 0 0 44px; width: 44px; height: 44px; padding: 0; }
  body.has-mobilebar .nav.search-open .cart-btn { display: none; }
  .nav-actions { flex: 1 1 auto; min-width: 0; }
  .nav-search, .nav.search-open .nav-search { position: relative; flex: 1 1 auto; min-width: 0; }
  /* 16px text: iOS zooms the page into any field set smaller when it takes focus. */
  .nav-search-input, .nav.search-open .nav-search-input {
    position: static; transform: none; width: 100%; height: 44px; padding: 0 44px 0 16px;
    opacity: 1; pointer-events: auto; border: 1px solid transparent; background: var(--paper-2);
    box-shadow: none; font-size: 16px; text-overflow: ellipsis;
  }
  .nav-search-input::placeholder { color: var(--muted); }
  .nav.search-open .nav-search-input { border-color: var(--azure); background: var(--card); }
  .nav-search-btn, .nav.search-open .nav-search-btn {
    position: absolute; z-index: 2; top: 0; right: 0; transform: none;
    width: 44px; height: 44px; padding: 0; border: 0; background: transparent;
  }
  .phone-search-back { flex: 0 0 44px; height: 44px; place-items: center; margin-left: -4px; border-radius: 50%; color: var(--navy); }
  .nav.search-open .phone-search-back { display: grid; }
  .nav.search-open .brand { display: none; }
  /* Where the tab bar gave way, the search screen runs to the bottom edge instead, over
     the page's own pinned bar. */
  body:is(.has-mobilebar, .has-orderbar, .pay-page) .nav-suggest { bottom: 0; padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
  body.phone-search-open :is(.pdp-mobilebar, .cart-orderbar) { display: none; }

  /* -- More: a screen between the header and the tab bar, like search. -- */
  .phone-more {
    display: block; position: fixed; z-index: 55; top: var(--phone-header-h); bottom: var(--phone-tabs-h); left: 0; right: 0;
    overflow-y: auto; overscroll-behavior: contain; padding: 20px 18px 28px; background: var(--paper);
  }
  .phone-more[hidden] { display: none; }
  .phone-more:focus { outline: none; }   /* focus moves to the screen so the next Tab lands on its first row */
  .phone-more h2 { margin: 0 0 14px; font-size: 24px; color: var(--navy-2); }
  .phone-more-list { overflow: hidden; background: var(--card); border: 1px solid var(--line); border-radius: 16px; }
  .phone-more-list a { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 54px; padding: 0 16px; color: var(--ink); font-size: 15px; font-weight: 600; }
  .phone-more-list a + a { border-top: 1px solid var(--line); }
  .phone-more-list svg { flex: 0 0 auto; color: var(--muted); }
  .phone-showroom { margin-top: 16px; padding: 18px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; }
  .phone-showroom h3 { margin: 0 0 6px; font-size: 17px; color: var(--navy-2); }
  .phone-showroom p { margin: 0 0 2px; color: var(--muted); font-size: 14px; line-height: 1.5; }
  .phone-showroom-acts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 14px 0 10px; }
  .phone-showroom-acts .btn { justify-content: center; min-height: 46px; padding: 0 12px; font-size: 14px; }

  /* -- Tab bar. -- */
  .phone-tabs {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    position: fixed; z-index: 60; left: 0; right: 0; bottom: 0;
    height: var(--phone-tabs-h); padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--card); border-top: 1px solid var(--line);
  }
  body.has-mobilebar .phone-tabs, body.has-orderbar .phone-tabs, body.pay-page .phone-tabs { display: none; }
  .phone-tabs > a, .phone-tabs > button {
    position: relative; min-width: 0; min-height: 44px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    color: var(--muted); font-size: 11px; font-weight: 500; line-height: 1;
  }
  .pt-ico { position: relative; display: block; }
  .pt-ico svg { display: block; width: 22px; height: 22px; }
  /* The page's own tab is marked; while More is open, More is marked instead. */
  .phone-tabs > .active, .phone-tabs.more-open > #phone-more-toggle { color: var(--navy); font-weight: 700; }
  .phone-tabs > .active::before, .phone-tabs.more-open > #phone-more-toggle::before {
    content: ''; position: absolute; top: -1px; left: 50%; width: 28px; height: 3px; margin-left: -14px;
    border-radius: 0 0 3px 3px; background: var(--signal);
  }
  .phone-tabs.more-open > .active:not(#phone-more-toggle) { color: var(--muted); font-weight: 500; }
  .phone-tabs.more-open > .active:not(#phone-more-toggle)::before { content: none; }
  .phone-tab-count {
    display: none; position: absolute; top: -6px; left: 13px; min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 9px; background: var(--signal); color: #fff; font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
  }
  .phone-tab-count.show { display: block; }

  /* -- Category tiles in a three-column grid: the search screen and the Shop tab. The
     tile itself is the homepage rail's .cat-tile. -- */
  .tile-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px 10px; }
  .tile-grid .cat-tile { width: auto; min-width: 0; }
  .tile-grid .ct-img { width: 100%; height: auto; aspect-ratio: 1; }
  .cat-tile small { display: block; margin-top: 2px; font-size: 11.5px; font-weight: 500; color: var(--muted); }

  /* -- Home as a feed: the compact slides, category tiles, handpicked deals, featured, a
     compact trust card, then help. The full carousel, brand strip and the two
     comparison cards are desktop's. -- */
  .home .hero-band, .home .brand-strip, .home #why { display: none; }
  .home-promo-wrap { display: block; order: 1; padding: calc(var(--phone-header-h) + 14px) 18px 0; }
  .home-promo {
    position: relative; display: flex; align-items: flex-end; min-height: 156px; overflow: hidden;
    padding: 14px 16px; border-radius: 16px; background: var(--navy-2); color: #fff;
  }
  .home-promo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 70% 50%; }
  /* Bright studio banner: the scrim carries the copy (>= 6:1 for white text across
     the copy's 68% width), and fades out over the products on the right. */
  .home-promo::after { content: ''; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(4,20,38,.94), rgba(4,20,38,.86) 60%, rgba(4,20,38,.2)); }
  .home-promo-copy { position: relative; z-index: 1; max-width: 68%; }
  .home-promo-eyebrow { display: block; font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--sky-bright); }
  .home-promo h1 { margin: 4px 0 10px; color: #fff; font-size: 19px; line-height: 1.15; }
  .home-promo-cta { display: inline-flex; align-items: center; min-height: 38px; padding: 0 16px; border-radius: 100px; background: #fff; color: var(--navy); font-size: 13.5px; font-weight: 600; }

  /* -- The slides ACH has switched on for phones (server/hero-slides.js
     phoneSlidesHtml), one per screen in the promo card's slot: a native scroll-snap
     rail, full bleed inside the wrap's gutters so a swipe runs edge to edge. The card
     takes its height from its text - the picture is a backdrop - so nothing moves
     when a banner arrives, and every card stretches to the tallest. With none switched
     on the server keeps the .home-promo card above instead. -- */
  .home-slides { position: relative; margin: 0 -18px; padding: 0; }
  .hs-track { gap: 18px; padding: 0 18px; scroll-padding: 0 18px; }
  .hs-track > .hs-slide { display: flex; flex: 0 0 100%; scroll-snap-stop: always; }   /* one slide per swipe, however hard the flick */
  .hs-card {
    position: relative; display: flex; align-items: flex-end; flex: 1 1 auto; min-width: 0; min-height: 156px; overflow: hidden;
    padding: 14px 16px; border-radius: 16px; background: var(--navy-2); color: #fff;
  }
  .hs-card:focus-visible { outline: 3px solid var(--sky-bright); outline-offset: -3px; }
  .hs-media { position: absolute; inset: 0; }
  .hs-media picture img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 70% 50%; }
  /* The scrim carries the copy (the banners are composed with their subject right of
     centre) and is gone by 92% of the width, so the right of the picture shows as it
     is. Under the words it is as thin as the sky-blue label allows: at .72-.78 the
     label on the bright air-conditioner banner fell to 3.4:1. Measured on real pixels
     by the [slides] section of test:phone - re-run it after touching these stops. */
  .hs-media::after { content: ''; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(4,20,38,.86), rgba(4,20,38,.82) 71%, rgba(4,20,38,0) 92%); }
  /* Only the first picture loads with the page: the others are loading="lazy" and out
     of the layout (so not fetched) until mountPhoneSlides arms their slide. html.hs-all
     is the page script's fallback when that module fails. */
  html.js-ready:not(.hs-all) .hs-slide:not(:first-child):not(.is-armed) .hs-media { display: none; }
  .hs-copy { position: relative; z-index: 4; max-width: 72%; }
  .hs-eyebrow { display: block; font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--sky-bright); }
  .hs-title { margin: 4px 0 10px; color: #fff; font-size: 19px; line-height: 1.15; }
  .hs-cta { display: inline-flex; align-items: center; min-height: 38px; padding: 0 16px; border-radius: 100px; background: #fff; color: var(--navy); font-size: 13.5px; font-weight: 600; }
  /* Automatic crop: one focal point per banner. Slide 1 uses its 4:3 file, mirrored as
     on desktop and enlarged so the fridge lands in the clear right third. */
  .hs-slide--hero .hs-media picture img { transform: scale(-1.4, 1.4); transform-origin: 55.75% 50%; object-position: 50% 58%; }
  .hs-slide--promo .hs-media picture img { object-position: 88% 50%; }
  .hs-slide--samsung .hs-media picture img { object-position: 62% 60%; }
  .hs-slide--clearance .hs-media picture img { object-position: 78% 40%; }
  /* The brand lockup as one column, and the clearance starburst, on the right; on a
     narrow phone their slides' copy stops short of them. */
  .hs-slide--samsung .hs-copy { max-width: min(72%, calc(100% - 96px)); }
  .hs-slide--clearance .hs-copy { max-width: min(72%, calc(100% - 104px)); }
  .hs-slide .hc-lockup { right: 12px; top: 50%; transform: translateY(-50%); --hc-cap: 11px;
    grid-template-columns: calc(var(--hc-cap) * 7.4); grid-template-rows: repeat(4, calc(var(--hc-cap) * 2.5)); }
  .hs-slide .hc-medallion { right: 12px; top: 50%; transform: translateY(-50%) rotate(-10deg); width: 92px; }
  .hs-slide .hc-medallion span { font-size: 8px; }
  .hs-slide .hc-medallion b { font-size: 23px; margin: 2px 0; }
  .hs-slide .hc-medallion.hc-med-wide b { font-size: 18px; }
  /* Dots are indicators, not buttons (swiping is the control), so nothing here is a
     small tap target. */
  .hs-dots { position: absolute; right: 32px; bottom: 14px; z-index: 5; display: flex; gap: 5px; pointer-events: none; }
  .hs-dots i { width: 6px; height: 6px; border-radius: 3px; background: rgba(255,255,255,.55); box-shadow: 0 0 0 1px rgba(4,20,38,.35); transition: width .2s, background .2s; }
  .hs-dots i.on { width: 18px; background: #fff; }
  @media (prefers-reduced-motion: reduce) { .hs-dots i { transition: none; } }
  .home #categories { padding: 18px 0 6px; }
  .home #categories .section-head { display: flex; flex-direction: row; align-items: center; justify-content: space-between; margin-bottom: 10px; }
  .home #categories .section-head p, .home #categories .section-head .section-link { display: none; }
  .home #categories .section-head .phone-link, .home-deals .section-head .phone-link { display: inline-flex; align-items: center; min-height: 44px; }
  .home #categories .section-head h2, .home-deals h2, .home #featured .section-head h2 { font-size: 20px; }
  .home-deals { display: block; order: 3; padding: 12px 0 6px; }
  .home-deals:has(#deals-grid:empty) { display: none; }   /* no handpicked deal: the rail goes */
  .home-deals .section-head { flex-direction: row; align-items: center; justify-content: space-between; margin-bottom: 12px; }
  .home-deals .rail-m > * { flex-basis: 156px; }
  .home-trust { display: block; order: 6; padding: 12px 0 8px; }
  .home-trust-card { padding: 16px 18px 6px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; }
  .home-trust-card ul { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
  .home-trust-card li { position: relative; padding-left: 28px; color: var(--ink); font-size: 14px; line-height: 1.45; }
  .home-trust-card li:nth-child(n+4) { display: none; }
  .home-trust-card li::before {
    content: '✓'; position: absolute; left: 0; top: 1px; width: 19px; height: 19px; display: grid; place-items: center;
    border-radius: 50%; background: var(--whatsapp); color: #fff; font-size: 11px; font-weight: 700;
  }
  .home-trust-card a { display: inline-flex; align-items: center; min-height: 44px; margin-top: 4px; color: var(--navy); font-size: 14px; font-weight: 600; }
  .home #cta { padding: 14px 0 28px; }

  /* -- The Shop tab (/shop?browse=categories) opens on every category. Plain /shop
     links keep listing products, so shared and filtered links mean what they say. -- */
  body.shop-category-landing .shop-categories { display: block; }
  body.shop-category-landing :is(.filters, .filters-backdrop, .shop-top, .shop-bar, .shop-count, #grid, .shop-more, #no-results) { display: none; }
  body.shop-category-landing .shop-layout { padding-top: calc(var(--phone-header-h) + 18px); }
  .shop-categories, .shop-category-group { padding: 0; }
  .shop-categories h1 { margin: 0 0 14px; font-size: 24px; color: var(--navy-2); }
  .shop-category-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 0 0 24px; }
  .shop-category-action { display: flex; flex-direction: column; justify-content: center; min-height: 64px; padding: 10px 14px; border-radius: 14px; background: var(--navy); color: #fff; }
  .shop-category-action.deals { background: var(--crimson); }
  .shop-category-action b { font-size: 15px; }
  .shop-category-action small { margin-top: 2px; font-size: 12px; color: rgba(255,255,255,.85); }
  .shop-category-group { margin-bottom: 24px; }
  .shop-category-group h2 { margin: 0 0 10px; font-size: 18px; color: var(--navy-2); }
}

/* ---- Phone after-order (<=640px ONLY) -----------------------------------------
   Slice 3 of the phone redesign: the order status screen, the home's order card and
   "Jump back in" rail, saving a product for later, and a person one tap away on the
   product page and in the cart. Every element is in the base display:none list above. */
@media (max-width: 640px) {
  /* -- Status screen (/success): the tracker replaces the desktop header. -- */
  .success-page { padding-top: calc(var(--phone-header-h) + 26px); padding-bottom: 32px; }
  /* !important: these carry inline display styles (the page's own markup and script). */
  body.has-track :is(.success-check, #headline, #lede, #review-callout, .success-acts) { display: none !important; }
  .order-track { display: block; }
  .order-track[hidden] { display: none; }
  .ot-icon { width: 56px; height: 56px; margin: 0 auto 14px; display: grid; place-items: center; border-radius: 50%; background: var(--whatsapp); color: #fff; }
  .order-track h1 { margin: 0; font-size: 24px; line-height: 1.2; color: var(--navy-2); }
  .ot-lede { max-width: 34ch; margin: 6px auto 0; color: var(--muted); font-size: 15px; line-height: 1.5; }
  .ot-steps { margin: 20px 0 0; padding: 6px 16px; list-style: none; text-align: left; background: var(--card); border: 1px solid var(--line); border-radius: 16px; }
  .ot-steps li { position: relative; display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 12px; padding: 12px 0; }
  .ot-steps li + li::before { content: ''; position: absolute; left: 12px; top: -12px; width: 2px; height: 24px; background: var(--line-2); }
  .ot-steps li.done + li::before { background: var(--signal); }
  .ot-steps i { position: relative; z-index: 1; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%; border: 2px solid var(--line-2); background: var(--card); }
  .ot-steps .done i, .ot-steps .now i { border-color: var(--signal); background: var(--signal); }
  .ot-steps .done i::after { content: ''; width: 10px; height: 5px; margin-top: -3px; border: solid #fff; border-width: 0 0 2.5px 2.5px; transform: rotate(-45deg); }
  .ot-steps .now i { box-shadow: inset 0 0 0 5px var(--card); }
  .ot-steps b { display: block; font-size: 15px; font-weight: 600; color: var(--navy-2); }
  .ot-steps small { display: block; margin-top: 2px; font-size: 13px; line-height: 1.4; color: var(--muted); }
  .ot-steps .todo b { color: var(--muted); font-weight: 500; }
  .ot-acts { display: grid; gap: 10px; margin-top: 18px; }

  /* -- Home: an open order's card above the promo, and "Jump back in" after Featured. -- */
  .home-orders { display: grid; gap: 10px; margin-bottom: 12px; }
  .home-orders[hidden] { display: none; }
  /* Before the order cards arrive: one skeleton per remembered order (index.html's head
     script sets data-orders, at most 3). */
  html[data-orders] .home-orders[hidden] { display: grid; }
  html[data-orders="1"] .home-orders .skel:nth-child(n+2), html[data-orders="2"] .home-orders .skel:nth-child(n+3) { display: none; }
  .home-order { display: grid; grid-template-columns: 52px minmax(0, 1fr) 18px; gap: 12px; align-items: center; padding: 12px 14px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; color: var(--ink); }
  .home-order > svg { color: var(--muted); }
  .ho-img { width: 52px; height: 52px; display: grid; place-items: center; padding: 5px; background: #fff; border: 1px solid var(--line); border-radius: 10px; }
  .ho-img img { min-width: 0; min-height: 0; max-width: 100%; max-height: 100%; object-fit: contain; }
  .ho-txt b { display: block; font-family: var(--display); font-size: 15px; font-weight: 600; line-height: 1.25; color: var(--navy-2); }
  .ho-txt small { display: block; margin-top: 2px; font-size: 12.5px; color: var(--muted); }
  .ho-segs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; margin-top: 8px; }
  .ho-segs i { height: 4px; border-radius: 2px; background: var(--line-2); }
  .ho-segs i.on { background: var(--signal); }
  .home-recent { display: block; order: 5; padding: 8px 0 10px; }
  .home-recent[hidden] { display: none; }
  .home-recent .section-head { margin-bottom: 12px; }
  .home-recent .section-head h2 { font-size: 20px; }
  /* A recently viewed tile: photo and price (the search screen has the same rail). */
  .rv-rail { gap: 10px; }
  .rv-tile { width: 100px; display: flex; flex-direction: column; gap: 6px; }
  .rv-tile .ct-img { width: 100px; height: 100px; }
  .rv-tile b { font-family: var(--display); font-size: 13px; font-weight: 600; color: var(--navy); white-space: nowrap; font-variant-numeric: tabular-nums; }

  /* -- Product page: save for later on the photo, then a person one tap away. -- */
  .pdp-save {
    display: grid; position: absolute; z-index: 3; top: 10px; right: 10px; width: 44px; height: 44px;
    place-items: center; border-radius: 50%; background: var(--card); border: 1px solid var(--line); color: var(--navy);
    box-shadow: 0 4px 12px -6px rgba(6,36,63,.35);
  }
  .pdp-save svg { fill: none; }
  .pdp-save[aria-pressed="true"] svg { fill: currentColor; }
  .pdp-ask { margin-top: 14px; padding: 16px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
  .pdp-ask h2 { font-size: 16px; color: var(--navy-2); }
  .pdp-ask p { margin: 4px 0 12px; font-size: 13.5px; line-height: 1.45; color: var(--muted); }
  .pdp-ask-two { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; }
  .pdp-ask-two .btn { min-height: 46px; padding: 0 12px; font-size: 14px; }

  /* -- Saved for later. -- */
  .saved-page { padding-top: calc(var(--phone-header-h) + 20px); padding-bottom: 28px; }
  .saved-page h1 { font-size: 26px; }
  .saved-share { width: 100%; }
}
/* The phone gallery's count moves left: the save heart takes the top-right corner. */
@media (max-width: 520px) { .pdp-gallery .g-count { right: auto; left: 14px; } }
/* A phone page paints complete: nothing above the fold waits for the desktop scroll
   reveal (GSAP), which would leave headings blank until the scripts arrive. */
@media (max-width: 640px) { html.js-ready .reveal { opacity: 1; transform: none; } }

/* ---- Loading skeletons ----------------------------------------------------------
   Where the server cannot render the content (it lives in this browser: the cart, the
   saved list, the home's order card), an inline script stands skeletons in before the
   first frame. Each skeleton is built from the SAME classes as the real markup, so it
   takes the same grid, size and spacing at every width, and the real content replaces
   it without moving anything. Its text is "ghost" text: representative words in
   transparent ink, so each line wraps where the real line will. */
.skel { pointer-events: none; }
.skel, .skel * { color: transparent; }       /* incl. a clamped line's ellipsis */
.skel .sk, .skel.sk {
  color: transparent;
  background: linear-gradient(90deg, var(--paper-2) 35%, #F7F9FC 50%, var(--paper-2) 65%) 0 0 / 300% 100%;
  animation: skel 1.4s ease-in-out infinite;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.skel [class="sk"] { border-radius: 6px; }   /* a ghost-text line, not a shaped box */
.skel .sk > * { visibility: hidden; }        /* a box keeps its children's size, not their paint */
@keyframes skel { from { background-position: 100% 0; } to { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .skel .sk, .skel.sk { animation: none; } }

/* ============================================================================
   Catalog admin (/admin) - same navy/white/cool-accent system, mobile-first.
   Rendered by server/admin.js; behaviour in public/js/admin.js.
   ============================================================================ */
body.admin { background: var(--paper); min-height: 100vh; }

/* ---- Admin top bar ------------------------------------------------------- */
.adm-top {
  position: sticky; top: 0; z-index: 40;
  background: rgba(255,255,255,0.94); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.adm-top-inner {
  position: relative;
  display: flex; align-items: center; gap: 12px 18px;
  max-width: 1440px; margin: 0 auto; padding: 10px 28px;
}
/* Hamburger - only shown on narrow screens (see responsive block). */
.adm-nav-toggle {
  display: none; align-items: center; justify-content: center; margin-left: auto;
  width: 44px; height: 44px; border-radius: 10px; border: 1px solid var(--line-2);
  background: var(--card); color: var(--navy); cursor: pointer;
}
.adm-nav-toggle:hover { border-color: var(--navy); }
.adm-brand {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px;
  font-family: var(--display); font-size: 18px; color: var(--navy);
}
.adm-brand img { border-radius: 50%; box-shadow: 0 5px 14px -7px rgba(0,48,96,.6); }
.adm-brand b { color: var(--azure); font-weight: 700; }
.adm-nav { display: flex; align-items: center; gap: 6px; flex: 1 1 auto; }
.adm-nav a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 6px 11px; border-radius: 100px; white-space: nowrap;
  font-size: 14.5px; font-weight: 500; color: var(--muted); transition: background .15s, color .15s;
}
.adm-nav a:hover { background: var(--paper-2); color: var(--navy); }
.adm-nav a.active { color: var(--navy); font-weight: 600; background: var(--paper-2); }
.adm-logout { margin: 0; }
.adm-logout-btn { padding: 9px 18px; min-height: 44px; }
/* Account menu: a native <details> holding Change password + Log out. */
.adm-account { position: relative; margin-left: auto; }
.adm-account > summary { list-style: none; display: inline-flex; align-items: center; gap: 6px; padding: 9px 14px; white-space: nowrap; cursor: pointer; }
.adm-account > summary::-webkit-details-marker { display: none; }
.adm-account > summary svg { transition: transform .15s; }
.adm-account[open] > summary svg { transform: rotate(180deg); }
.adm-account > summary.active { border-color: var(--navy); }
.adm-account-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60; min-width: 200px;
  display: flex; flex-direction: column; gap: 2px; padding: 6px;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow);
}
.adm-nav .adm-account-menu a, .adm-account-menu button {
  display: flex; align-items: center; width: 100%; min-height: 44px; padding: 8px 12px; border-radius: 9px;
  font-size: 14.5px; font-weight: 500; color: var(--ink); text-align: left;
}
.adm-nav .adm-account-menu a:hover, .adm-account-menu button:hover { background: var(--paper-2); color: var(--navy); }

/* ---- Layout shells ------------------------------------------------------- */
/* Full-width admin pages (Homepage slides, Products - the `bodyClass` option of
   page() in server/admin.js): the top bar drops its 1360px cap and takes the
   page's 20px gutter. Each page turns the body into a one-screen column at its
   own breakpoint (body.adm-wide:has(...)); the top bar must not shrink in it. */
body.adm-wide .adm-top { flex: 0 0 auto; }
body.adm-wide .adm-top-inner { max-width: none; }
@media (min-width: 641px) { body.adm-wide .adm-top-inner { padding-left: 20px; padding-right: 20px; } }
.adm-wrap { max-width: 1120px; margin: 0 auto; padding: 30px 28px 72px; }
.adm-back, .adm-auth-back {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--azure); font-weight: 600; font-size: 14.5px;
}
.adm-back:hover, .adm-auth-back:hover { color: var(--navy); }
.adm-editor-wrap h1 { margin: 6px 0 22px; }
.adm-sub { color: var(--muted); font-size: 14.5px; margin: 6px 0 0; }
.adm-hint { color: var(--muted); font-size: 14px; }
.req { color: var(--crimson); }

.adm-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.adm-head h1 { font-size: clamp(26px, 4vw, 34px); }
.adm-empty, .adm-loading, .adm-gallery-empty {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 26px; color: var(--muted); text-align: center;
}
.adm-empty a, .adm-gallery-empty a { color: var(--azure); font-weight: 600; }

/* ---- Product list (taxonomy rows reuse .adm-row) ------------------------- */
.adm-row {
  display: grid; grid-template-columns: 64px minmax(0,1fr) auto auto;
  grid-template-areas: "img main price actions"; gap: 18px; align-items: center;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 16px; box-shadow: var(--shadow-sm);
}
.adm-row-img { grid-area: img; display: block; width: 64px; height: 64px; border-radius: 10px; overflow: hidden; background: var(--paper-2); }
.adm-row-img img { width: 100%; height: 100%; object-fit: cover; }
.adm-row-main { grid-area: main; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.adm-row-name { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; color: var(--ink); line-height: 1.3; }
.adm-row-name:hover { color: var(--azure); }
.adm-row-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.adm-tag {
  font-size: 11.5px; font-weight: 600; letter-spacing: .02em; padding: 3px 9px; border-radius: 100px;
  background: var(--paper-2); color: var(--navy);
}
.adm-tag.ghost { background: transparent; border: 1px solid var(--line-2); color: var(--muted); font-weight: 500; }
.adm-row-price { grid-area: price; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.adm-row-price .now { display: block; font-weight: 700; color: var(--navy); }
.adm-row-price .was { display: block; font-size: 12.5px; color: var(--muted); text-decoration: line-through; }
.adm-row-actions { grid-area: actions; display: flex; gap: 10px; justify-content: flex-end; }
.adm-sm { padding: 8px 16px; min-height: 44px; font-size: 14px; }
.adm-danger { background: var(--crimson); color: #fff; }
.adm-danger:hover { background: #b73831; }
.adm-danger:disabled { background: var(--paper-2); color: var(--muted); }

/* ---- Categories manager --------------------------------------------------- */
.adm-tax-section { margin-top: 24px; }
.adm-tax-list { display: flex; flex-direction: column; gap: 10px; }
.adm-brand-nologo { font-size: 12px; font-weight: 600; color: var(--muted); }
.adm-tax-row { grid-template-columns: minmax(0,1fr) auto; grid-template-areas: "main actions"; }
/* --signal is a fill/indicator, never text: keep the soft signal tint + a
   signal border for identity, but darken the label to navy so it passes AA. */
.adm-tag.unused { background: rgba(42,120,190,.14); border: 1px solid var(--signal); color: var(--navy); }
.adm-tax-move {
  margin: 8px 2px 2px; padding: 14px 16px; background: var(--paper-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  display: flex; flex-wrap: wrap; gap: 12px 16px; align-items: flex-end;
}
/* A closed move panel carries the `hidden` attribute; without this the flex
   display above would defeat it and render an empty grey bar under every row. */
.adm-tax-move[hidden] { display: none; }
.adm-tax-move-label { display: flex; flex-direction: column; gap: 6px; flex: 1 1 220px; min-width: 0; font-size: 13.5px; font-weight: 600; color: var(--navy); }
.adm-tax-move-label select { min-height: 44px; }
.adm-tax-move-actions { display: flex; gap: 10px; }

/* ---- FAQ manager --------------------------------------------------------- */
.adm-faq-status {
  display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: center; justify-content: space-between;
  margin-top: 22px; padding: 14px 18px; background: var(--paper-2);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.adm-faq-status p { margin: 0; color: var(--ink); font-size: 14.5px; }
.adm-faq-status b { color: var(--navy); }
.adm-faq-view { color: var(--azure); font-weight: 600; font-size: 14px; white-space: nowrap; display: inline-flex; align-items: center; min-height: 44px; }
.adm-faq-help { color: var(--muted); font-size: 13.5px; margin: 14px 2px 0; }
.adm-faq-help code {
  font-size: 12.5px; padding: 2px 6px; border-radius: 5px;
  background: var(--paper-2); border: 1px solid var(--line); color: var(--navy);
}
.adm-faq-list { display: flex; flex-direction: column; gap: 14px; margin-top: 16px; }
.adm-faq-card {
  display: flex; flex-direction: column; gap: 14px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow-sm);
}
/* Wraps because the three 44px tap targets (44*3 + gaps = 148px) plus the state pill
   do not fit beside each other on a 320px screen. The buttons stay full size and drop
   to their own line rather than shrinking below the tap-target floor. */
.adm-faq-cardhead { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; flex-wrap: wrap; }
.adm-faq-order { display: flex; gap: 8px; margin-left: auto; }
.adm-faq-drag { cursor: grab; }
.adm-faq-drag:active { cursor: grabbing; }
.adm-faq-card.dragging { opacity: .4; }
/* The drop indicator: a rule on the edge the dragged card will land against. */
.adm-faq-card.drag-over-top { box-shadow: inset 0 3px 0 0 var(--azure); }
.adm-faq-card.drag-over-bottom { box-shadow: inset 0 -3px 0 0 var(--azure); }
/* A question is a single line and an answer is a paragraph: the textarea is the one
   that grows. Shorter than the product editor's 120px min - an FAQ answer is a few
   sentences, and a tall empty box on 18 stacked cards reads as a chore. */
.adm-faq-card .adm-faq-a { min-height: 92px; }
.adm-faq-cardfoot { display: flex; align-items: center; justify-content: space-between; gap: 12px 18px; flex-wrap: wrap; }

/* ---- Contact inbox (/admin/messages) -------------------------------------- */
/* Message cards reuse the FAQ card's head/foot rows; the card itself mirrors
   .adm-faq-card (same surface, tighter gap - the content is read-only). */
.adm-inbox-list { display: flex; flex-direction: column; gap: 14px; margin-top: 16px; }
.adm-inbox-card {
  display: flex; flex-direction: column; gap: 10px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow-sm);
}
.adm-inbox-card[data-handled] { background: var(--paper-2); }
.adm-inbox-when { color: var(--muted); font-size: 13px; white-space: nowrap; }
.adm-inbox-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline; font-size: 14px; }
.adm-inbox-meta b { color: var(--navy); }
.adm-inbox-meta a { color: var(--azure); font-weight: 600; overflow-wrap: anywhere; }
/* On touch widths the phone / email links are standalone controls (flex items, not
   running prose), so they carry a full 44px hit area. Guard: npm run test:responsive. */
@media (max-width: 640px) { .adm-inbox-meta a { display: inline-flex; align-items: center; min-height: 44px; } }
.adm-inbox-tag {
  font-size: 12px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: rgba(0,48,96,.10); color: var(--navy);
}
.adm-inbox-noemail { color: var(--crimson); font-size: 12.5px; font-weight: 600; }
.adm-app-links { display: flex; flex-wrap: wrap; gap: 8px; }
.adm-inbox-msg { margin: 0; color: var(--ink); font-size: 14.5px; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---- Product editor form ------------------------------------------------- */
.adm-editor { margin-top: 4px; }
/* The form is a column of cards (Basics, Pricing, On the storefront, Product
   type, Photos). Once the editor itself is 860px wide (the standalone page on a
   desktop - never the docked panel) Basics and Photos take the left column and
   the settings cards (.adm-ed-side) the right; the 1fr second row soaks up a
   taller settings column so Photos stays directly under Basics. */
#adm-editor-pane, #adm-editor { container-type: inline-size; }
.adm-form, .adm-ed-side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.adm-form .adm-section {
  margin: 0; padding: 16px 18px 18px; background: var(--card);
  border: 1px solid var(--line); border-radius: 12px;
}
.adm-form .adm-section-head { margin-bottom: 12px; }
.adm-ed-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 0 4px 6px; }
.adm-ed-view { display: inline-flex; align-items: center; min-height: 44px; color: var(--azure); font-weight: 600; font-size: 14px; }
.adm-ed-view:hover { color: var(--navy); }
@container (min-width: 860px) {
  .adm-form { display: grid; grid-template-columns: minmax(0, 1fr) 340px; grid-template-rows: auto 1fr; align-items: start; gap: 14px 16px; }
  .adm-form > * { grid-column: 1; }
  .adm-form > .adm-ed-foot { grid-column: 1 / -1; }
  .adm-form > .adm-ed-side { grid-column: 2; grid-row: 1 / span 2; }
  .adm-ed-side .adm-form-grid { grid-template-columns: 1fr; }
  .adm-ed-side .adm-col-2 { grid-column: auto; }
}
.adm-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 20px; }
.adm-col-2 { grid-column: 1 / -1; }
.adm-field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.adm-field > label { font-size: 13.5px; font-weight: 600; color: var(--navy); }
.adm-field input, .adm-field select, .adm-field textarea { width: 100%; }
.adm-field textarea {
  background: var(--card); border: 1px solid var(--line); color: var(--ink); font-family: var(--prose);
  padding: 12px 14px; border-radius: 10px; outline: none; resize: vertical; min-height: 120px;
  transition: border-color .2s, box-shadow .2s;
}
.adm-field textarea:focus { border-color: var(--azure); box-shadow: 0 0 0 3px rgba(30,111,176,.15); }
.adm-check { display: inline-flex; align-items: center; gap: 9px; font-size: 14.5px; font-weight: 500; color: var(--ink); min-height: 44px; cursor: pointer; }
.adm-check input { width: 20px; height: 20px; accent-color: var(--navy); flex: 0 0 auto; }
.adm-sale-field { gap: 10px; }
.adm-seg.adm-sale-mode button { flex: 1 1 auto; padding-inline: 8px; white-space: nowrap; }
.adm-sale-mode[hidden], .adm-pct[hidden] { display: none; }
.adm-pct { display: flex; align-items: center; gap: 10px; }
.adm-pct input { flex: 1 1 0; min-width: 0; }
.adm-pct span { flex: 0 0 auto; font-size: 14.5px; font-weight: 600; color: var(--muted); white-space: nowrap; }
/* "Price + %": the normal price is worked out from the sale fields, not typed. */
#f-price[readonly] { background: var(--paper-2); cursor: default; }
.adm-toggles { flex-direction: column; align-items: flex-start; gap: 0; }

/* ---- Photos & gallery ---------------------------------------------------- */
.adm-media .adm-sub { font-size: 13.5px; margin-top: 0; }
.adm-media-live { color: var(--navy); }
.adm-upload {
  display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap;
  margin-top: 14px; padding: 16px; min-height: 44px;
  border: 2px dashed var(--line-2); border-radius: 12px; background: var(--paper);
  cursor: pointer; transition: border-color .2s, background .2s;
}
.adm-upload:hover, .adm-upload.over { border-color: var(--azure); background: var(--paper-2); }
.adm-upload.busy { opacity: .6; pointer-events: none; }
.adm-upload-cta { font-weight: 700; color: var(--navy); }
.adm-upload-hint { color: var(--muted); font-size: 14px; }
.adm-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; margin-top: 14px; }
.adm-thumb {
  margin: 0; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--card);
}
.adm-thumb.is-cover { outline: 2px solid var(--signal); outline-offset: -1px; border-color: var(--sky); }
.adm-thumb img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; background: var(--paper-2); }
.adm-thumb figcaption { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px; }
.adm-thumb-btn {
  flex: 1 1 auto; min-height: 44px; padding: 6px 4px; white-space: nowrap; border-radius: 8px;
  border: 1px solid var(--line-2); background: var(--card); color: var(--navy);
  font-size: 13px; font-weight: 600; cursor: pointer; transition: background .15s, border-color .15s, color .15s;
}
.adm-thumb-btn:hover { border-color: var(--azure); background: var(--paper-2); }
.adm-thumb-btn.danger { color: var(--crimson); }
.adm-thumb-btn.danger:hover { border-color: var(--crimson); background: rgba(158,43,37,.08); }
/* Drag-to-reorder grip + insert marks (grid flows row-major, so before = left edge). */
.adm-thumb-drag {
  position: absolute; top: 8px; right: 8px; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--line);
  background: rgba(255,255,255,.92); color: var(--muted); cursor: grab; box-shadow: var(--shadow-sm);
}
.adm-thumb-drag:active { cursor: grabbing; }
.adm-thumb.dragging { opacity: .4; }
.adm-thumb.drag-over-left { box-shadow: inset 3px 0 0 0 var(--azure); }
.adm-thumb.drag-over-right { box-shadow: inset -3px 0 0 0 var(--azure); }
.adm-cover-badge {
  flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center; min-height: 44px;
  border-radius: 8px; background: rgba(42,120,190,.12); border: 1px solid var(--signal);
  /* signal is fill-only: the signal tint + border keep the active-cover identity
     (echoing the .is-cover thumb outline); navy label text passes AA. */
  color: var(--navy); font-size: 13px; font-weight: 700;
}

/* ---- Auth (login) -------------------------------------------------------- */
.adm-auth { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 40px 20px; }
.adm-auth-card {
  width: 100%; max-width: 420px; background: var(--card); border: 1px solid var(--line);
  border-radius: 20px; padding: 34px 32px; box-shadow: var(--shadow); text-align: left;
}
.adm-auth-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.adm-auth-brand img { border-radius: 50%; box-shadow: 0 6px 16px -8px rgba(0,48,96,.6); }
.adm-auth-card h1 { font-size: 30px; }
.adm-auth-lead { color: var(--muted); font-size: 14.5px; margin: 8px 0 20px; }
.adm-auth-form { display: flex; flex-direction: column; gap: 10px; }
.adm-auth-form label { font-size: 13.5px; font-weight: 600; color: var(--navy); }
.adm-auth-form input { width: 100%; }
.adm-auth-form .btn { margin-top: 8px; width: 100%; }
.adm-auth-back { margin-top: 18px; }
.adm-alert {
  background: rgba(158,43,37,.1); border: 1px solid rgba(158,43,37,.3); color: var(--crimson);
  padding: 11px 14px; border-radius: 10px; font-size: 14px; font-weight: 500; margin-bottom: 16px;
}
.adm-alert--ok { background: rgba(42,120,190,.1); border-color: var(--signal); color: var(--navy); }
/* Password input + show/hide toggle (login + /admin/password). The button sits
   inside the input's right edge; the input reserves that space. */
.adm-pw-field { position: relative; }
.adm-pw-field input { padding-right: 52px; }
.adm-pw-toggle {
  position: absolute; top: 50%; right: 2px; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 8px; color: var(--muted);
}
.adm-pw-toggle[hidden] { display: none; }
.adm-pw-toggle:hover { color: var(--navy); }
.adm-pw-toggle:focus-visible { outline: 2px solid var(--azure); outline-offset: -2px; color: var(--navy); }
.adm-pw-toggle .adm-pw-eye-off, .adm-pw-toggle[aria-pressed="true"] .adm-pw-eye { display: none; }
.adm-pw-toggle[aria-pressed="true"] .adm-pw-eye-off { display: block; }
.adm-pw-page .adm-auth-card { margin: 12px auto 0; }
.adm-pw-page .adm-auth-form .adm-field-hint { margin-top: -4px; }
.adm-msg { text-align: center; }
.adm-msg h1 { font-size: 24px; margin-bottom: 10px; }
.adm-msg p { color: var(--muted); }

/* ---- Toast (admin) ------------------------------------------------------- */
.adm-toast {
  position: fixed; inset: auto; margin: 0; left: 50%; bottom: 28px; transform: translate(-50%, 24px);
  background: var(--navy-2); color: #fff; padding: 13px 22px; border-radius: 100px;
  font-size: 14.5px; font-weight: 600; box-shadow: var(--shadow); z-index: var(--z-toast);
  opacity: 0; pointer-events: none; transition: opacity .3s, transform .3s;
  border: 1px solid rgba(111,168,214,.3); max-width: calc(100vw - 32px);
}
.adm-toast.show { opacity: 1; transform: translate(-50%, 0); }
.adm-toast.ok { border-color: rgba(30,111,176,.5); }
.adm-toast.err { background: #6d1f1a; border-color: rgba(158,43,37,.6); }

/* ---- Workspace: master-detail dashboard ---------------------------------- */
/* These panels use flex/grid, which would defeat the `hidden` attribute's
   display:none (same lesson as .adm-tax-move) - restore it at higher specificity. */
.adm-facets[hidden], .adm-menu-pop[hidden],
.adm-upload-status[hidden], .adm-price-preview[hidden], .adm-pager[hidden],
.adm-orphan-alert[hidden], .adm-attention[hidden] { display: none; }

.adm-workspace { max-width: 1360px; margin: 0 auto; padding: 26px 28px 64px; }
.adm-head-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* The two-pane split. Orders sets its own columns (#adm-orders, below) and so
   do Products and Brands (#adm-dashboard, #adm-brands: a full-width table + a docked editor panel). */
.adm-split { display: grid; grid-template-columns: minmax(0, 444px) minmax(0, 1fr); gap: 22px; align-items: start; margin-top: 22px; }

/* Left pane: a scannable list with its own scroll region. */
.adm-master {
  min-width: 0; position: sticky; top: 78px; max-height: calc(100vh - 98px);
  display: flex; flex-direction: column; gap: 12px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 14px;
}
.adm-master-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.adm-master-tools #adm-filter, .adm-master-tools #adm-order-filter { flex: 1 1 150px; min-width: 0; }
.adm-master-tools select { min-height: 44px; padding: 9px 10px; }
.adm-sort { display: inline-flex; align-items: center; gap: 6px; }
.adm-sort-label { font-size: 12.5px; color: var(--muted); font-weight: 600; }
.adm-facets { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; align-items: end; padding: 12px; background: var(--paper-2); border-radius: 10px; }
.adm-facet { display: flex; flex-direction: column; gap: 5px; font-size: 12px; font-weight: 700; color: var(--navy); text-transform: uppercase; letter-spacing: .03em; }
.adm-facet select { min-height: 44px; }
.adm-facet-check { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; font-size: 14px; font-weight: 500; color: var(--ink); cursor: pointer; text-transform: none; letter-spacing: 0; }
.adm-facet-check input { width: 18px; height: 18px; accent-color: var(--navy); flex: 0 0 auto; }
.adm-facet-clear { grid-column: 1 / -1; justify-self: start; min-height: 44px; background: none; border: 0; color: var(--azure); font-weight: 600; font-size: 13px; cursor: pointer; }
.adm-facet-clear:hover { color: var(--navy); }

.adm-table { flex: 1 1 auto; min-height: 120px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.adm-lrow { display: flex; align-items: stretch; gap: 2px; border: 1px solid transparent; border-radius: 10px; }
.adm-lrow:hover { background: var(--paper-2); }
.adm-lrow.is-selected { background: var(--paper-2); border-color: var(--sky); }
.adm-lrow-open {
  flex: 1 1 auto; min-width: 0; display: grid; grid-template-columns: 40px minmax(0,1fr) auto auto;
  align-items: center; gap: 10px; text-align: left; background: none; border: 0; cursor: pointer;
  padding: 8px; border-radius: 10px; min-height: 44px;
}
.adm-lrow-img { width: 40px; height: 40px; border-radius: 8px; overflow: hidden; background: var(--paper-2); flex: 0 0 auto; }
.adm-lrow-img img { width: 100%; height: 100%; object-fit: cover; }
.adm-lrow-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.adm-lrow-name { font-weight: 600; color: var(--ink); font-size: 13.5px; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-lrow:hover .adm-lrow-name, .adm-lrow.is-selected .adm-lrow-name { color: var(--azure); }
.adm-lrow-meta { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-flag { font-size: 10px; font-weight: 700; letter-spacing: .02em; padding: 2px 6px; border-radius: 6px; white-space: nowrap; }
.adm-flag.out { background: rgba(158,43,37,.12); color: var(--crimson); }
.adm-flag.sale { background: transparent; border: 1px solid rgba(158,43,37,.5); color: var(--crimson); padding: 1px 5px; }
.adm-flag.clearance { background: var(--crimson); color: #fff; }
.adm-lrow-menu { position: relative; display: flex; align-items: center; }

.adm-iconbtn {
  width: 44px; height: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px; border: 1px solid transparent; background: none; color: var(--muted); cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.adm-iconbtn:hover { background: var(--paper-2); color: var(--navy); border-color: var(--line); }
.adm-iconbtn.danger:hover { color: var(--crimson); border-color: rgba(158,43,37,.4); background: rgba(158,43,37,.06); }
.adm-iconbtn:disabled { opacity: .35; pointer-events: none; }
.adm-menu-pop {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 50; min-width: 190px;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow);
  padding: 6px; display: flex; flex-direction: column;
}
/* Flip upward when there is no room below (the bottom rows of a table), so every item
   stays reachable instead of dropping past the viewport. */
.adm-menu-pop.is-up { top: auto; bottom: calc(100% + 4px); }
.adm-menu-item { display: flex; align-items: center; min-height: 44px; padding: 8px 12px; border-radius: 7px; font-size: 13.5px; font-weight: 500; color: var(--ink); background: none; border: 0; text-align: left; cursor: pointer; }
.adm-menu-item:hover { background: var(--paper-2); }
.adm-menu-item.danger { color: var(--crimson); }
.adm-menu-item.danger:hover { background: rgba(158,43,37,.08); }

.adm-pager { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.adm-pager-info { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- Products workspace (/admin) ------------------------------------------ */
/* Full window width (body.adm-wide): a compact header, then the catalogue as a
   table. Opening a product docks the editor in a panel on the right; the table
   narrows and sheds columns BY ITS OWN WIDTH (container queries on .adm-master),
   so the same rules serve a small window and a table squeezed by the panel.
     1101px and up   table | panel side by side, one screen tall, each scrolls inside
     901 - 1100px    the panel slides over the table as a modal sheet (admin.js
                     syncOverlay: scrim, inert background, Escape closes)
     900px and down  the table only, in normal page flow; a row opens the
                     standalone edit page (admin.js isNarrow())
   Everything is scoped to #adm-dashboard + #adm-brands (Brands is the same
   workspace - see its block below): Orders shares .adm-split/.adm-master. */
:is(#adm-dashboard, #adm-brands).adm-workspace { max-width: none; width: 100%; margin: 0; padding: 0; }
:is(#adm-dashboard, #adm-brands) > .adm-head { align-items: center; padding: 10px 20px; background: var(--card); border-bottom: 1px solid var(--line); }
:is(#adm-dashboard, #adm-brands) > .adm-head h1 { font-size: 21px; }
:is(#adm-dashboard, #adm-brands) > .adm-head .adm-sub { font-size: 13.5px; margin-top: 2px; }
:is(#adm-dashboard, #adm-brands) .adm-split { grid-template-columns: minmax(0, 1fr); gap: 0; align-items: stretch; margin: 0; }
:is(#adm-dashboard, #adm-brands) .adm-master {
  position: static; max-height: none; container-type: inline-size; gap: 10px; padding: 12px 20px 8px;
  border: 0; border-radius: 0; box-shadow: none;
}

/* Toolbar: search + sort on the left, the selection count + Print labels on the right. */
:is(#adm-dashboard, #adm-brands) .adm-master-tools #adm-filter { flex: 1 1 240px; max-width: 420px; }
.adm-select-bar { display: flex; align-items: center; gap: 12px; margin-left: auto; }
.adm-select-count { font-size: 12.5px; font-weight: 600; color: var(--muted); white-space: nowrap; }

/* Filters: an always-visible row of chips - a select chip per facet, toggle
   chips for On sale / Clearance. A chip that is filtering turns navy. */
:is(#adm-dashboard, #adm-brands) .adm-facets { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 0; background: none; border-radius: 0; }
:is(#adm-dashboard, #adm-brands) .adm-facet { display: block; }
:is(#adm-dashboard, #adm-brands) .adm-facet > span, .adm-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:is(#adm-dashboard, #adm-brands) .adm-facet select {
  -webkit-appearance: none; appearance: none; width: auto; min-height: 44px; padding: 0 34px 0 14px;
  border-radius: 100px; border-color: var(--line-2); cursor: pointer;
  font-size: 13.5px; font-weight: 600; color: var(--navy);
  background: var(--card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23003060' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 13px center;
}
:is(#adm-dashboard, #adm-brands) .adm-facet select:has(option:checked:not([value=""])) {
  background-color: var(--navy); border-color: var(--navy); color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
:is(#adm-dashboard, #adm-brands) .adm-facet select option { background: var(--card); color: var(--ink); }
:is(#adm-dashboard, #adm-brands) .adm-facet-check {
  min-height: 44px; padding: 0 14px 0 12px; border: 1px solid var(--line-2); border-radius: 100px;
  background: var(--card); font-size: 13.5px; font-weight: 600; color: var(--navy); text-transform: none; letter-spacing: 0;
}
:is(#adm-dashboard, #adm-brands) .adm-facet-check input { width: 16px; height: 16px; }
:is(#adm-dashboard, #adm-brands) .adm-facet-check:has(input:checked) { background: var(--navy); border-color: var(--navy); color: #fff; }
:is(#adm-dashboard, #adm-brands) .adm-facet-check:has(input:checked) input { accent-color: #fff; }
:is(#adm-dashboard, #adm-brands) .adm-facet-check:has(input:focus-visible), :is(#adm-dashboard, #adm-brands) .adm-facet select:focus-visible { box-shadow: 0 0 0 3px rgba(30,111,176,.3); }
:is(#adm-dashboard, #adm-brands) .adm-facet-clear { padding: 0 6px; }

/* The table. .adm-tscroll scrolls; the header row sticks to its top. */
.adm-tscroll { flex: 1 1 auto; min-height: 0; overflow: auto; border-top: 1px solid var(--line); }
:is(#adm-dashboard, #adm-brands) .adm-table { display: block; overflow: visible; min-height: 0; }
:is(#adm-dashboard, #adm-brands) .adm-table .adm-empty { margin: 18px 0; }
.adm-thead-row, .adm-trow {
  display: grid; align-items: center; column-gap: 14px;
  grid-template-columns: 40px minmax(240px, 3fr) minmax(90px, .8fr) minmax(130px, 1.1fr) minmax(128px, .9fr) 118px minmax(150px, 1.15fr) 104px 44px;
}
.adm-thead { position: sticky; top: 0; z-index: 2; background: var(--paper); border-bottom: 1px solid var(--line-2); }
.adm-thead-row { min-height: 40px; font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.adm-tc { min-width: 0; }
.adm-tc-check { display: flex; align-items: center; justify-content: center; align-self: stretch; cursor: pointer; }
.adm-tc-check input { width: 18px; height: 18px; accent-color: var(--navy); cursor: pointer; }
.adm-trow { min-height: 62px; border-bottom: 1px solid var(--line); cursor: pointer; scroll-margin: 48px 0 8px; }
.adm-trow:hover { background: var(--paper); }
.adm-trow.is-selected { background: #EAF2FA; box-shadow: inset 3px 0 0 var(--navy); }
.adm-tc-open { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 62px; padding: 8px 0; text-align: left; border-radius: 8px; }
.adm-tc-open .adm-lrow-img { width: 44px; height: 44px; }
.adm-tc-name { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0; }
/* The full product name, wrapped - never cut short. */
.adm-tc-title { font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.adm-trow:hover .adm-tc-title, .adm-trow.is-selected .adm-tc-title { color: var(--azure); }
.adm-tc-inflags { display: none; flex-wrap: wrap; gap: 4px; }
.adm-tc-inflags .adm-flag.out { display: none; }
.adm-tc-brand, .adm-tc-cat { font-size: 13.5px; color: var(--ink); overflow-wrap: anywhere; }
.adm-tc-none { color: var(--muted); }
.adm-tc-cat small { display: block; font-size: 12px; color: var(--muted); }
.adm-tc-price { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.adm-tc-price .now { display: block; font-weight: 700; color: var(--navy); font-size: 13.5px; }
.adm-tc-price .was { display: block; font-size: 11.5px; color: var(--muted); text-decoration: line-through; }
.adm-tc-flags { display: flex; flex-wrap: wrap; gap: 4px; }
.adm-tc-updated { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.adm-flag.featured { background: rgba(42,120,190,.13); color: var(--navy); }
.adm-stock { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--ink); white-space: nowrap; }
.adm-stock::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--whatsapp); }
.adm-stock.out { color: var(--crimson); }
.adm-stock.out::before { background: var(--crimson); }
/* The row whose product holds unsaved edits: a crimson ring on its photo, plus
   the "Not saved" pill admin.js adds under its name. */
.adm-trow.is-dirty .adm-lrow-img { box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--crimson); }
.adm-row-unsaved { font-size: 10.5px; padding: 2px 8px; }
/* Columns give way as the table narrows: Updated and Brand first, then Tags
   (they move under the name), then Stock (an "Out of stock" tag joins the tags
   under the name), then Section; on a phone the price drops under the name. */
@container (max-width: 1320px) {
  .adm-thead-row, .adm-trow { grid-template-columns: 40px minmax(240px, 3fr) minmax(130px, 1.1fr) minmax(128px, .9fr) 118px minmax(150px, 1.15fr) 44px; }
  .adm-tc-updated, .adm-tc-brand { display: none; }
}
@container (max-width: 1020px) {
  .adm-thead-row, .adm-trow { grid-template-columns: 40px minmax(220px, 3fr) minmax(110px, 1fr) minmax(120px, .9fr) 108px 44px; }
  .adm-tc-flags { display: none; }
  .adm-tc-inflags:not(:empty) { display: flex; }
}
@container (max-width: 860px) {
  .adm-thead-row, .adm-trow { grid-template-columns: 40px minmax(200px, 3fr) minmax(110px, 1fr) minmax(120px, .9fr) 44px; }
  .adm-tc-stock { display: none; }
  .adm-tc-inflags .adm-flag.out { display: inline; }
}
@container (max-width: 640px) {
  .adm-thead-row, .adm-trow { grid-template-columns: 40px minmax(0, 1fr) minmax(110px, auto) 44px; column-gap: 10px; }
  .adm-tc-cat { display: none; }
  :is(#adm-dashboard, #adm-brands) .adm-master-tools #adm-filter { flex-basis: 100%; max-width: none; }
  :is(#adm-dashboard, #adm-brands) .adm-select-bar { margin-left: 0; flex: 1 1 auto; justify-content: space-between; }
}
@container (max-width: 480px) {
  .adm-thead-row, .adm-trow { grid-template-columns: 40px minmax(0, 1fr) 44px; column-gap: 6px; }
  .adm-thead-row .adm-tc-price { display: none; }
  .adm-trow .adm-tc-check, .adm-trow .adm-tc-menu { grid-row: 1 / span 2; }
  .adm-trow .adm-tc-product { grid-column: 2; grid-row: 1; }
  .adm-trow .adm-tc-price { grid-column: 2; grid-row: 2; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; padding: 0 0 10px 56px; text-align: left; }
  .adm-tc-open { min-height: 52px; padding-bottom: 4px; }
}

/* The docked editor panel. */
.adm-scrim { position: fixed; inset: 0; z-index: 44; background: rgba(6,36,63,.32); }
.adm-scrim[hidden] { display: none; }
:is(#adm-dashboard, #adm-brands) .adm-detail { display: none; }
.adm-ed-head { display: flex; align-items: flex-start; gap: 12px; padding: 12px 10px 12px 18px; background: var(--card); border-bottom: 1px solid var(--line); }
.adm-ed-titles { flex: 1 1 auto; min-width: 0; }
.adm-ed-head .adm-iconbtn { flex: 0 0 auto; }
.adm-ed-kicker { margin: 0; font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.adm-ed-name { margin: 2px 0 0; font-size: 17.5px; line-height: 1.25; color: var(--ink); overflow-wrap: anywhere; }
.adm-ed-state { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); }
.adm-ed-state[data-state="unsaved"] { color: var(--crimson); font-weight: 700; }
@media (min-width: 901px) {
  body.adm-wide:has(#adm-dashboard, #adm-brands) { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 600px; }
  :is(#adm-dashboard, #adm-brands).adm-workspace { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  :is(#adm-dashboard, #adm-brands) > .adm-head { flex: 0 0 auto; flex-wrap: nowrap; }
  :is(#adm-dashboard, #adm-brands) .adm-split { flex: 1 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); }
  :is(#adm-dashboard, #adm-brands) .adm-master { min-height: 0; overflow: hidden; }
  :is(#adm-dashboard, #adm-brands).is-editing .adm-split { grid-template-columns: minmax(0, 1fr) clamp(560px, 46vw, 840px); }
  :is(#adm-dashboard, #adm-brands).is-editing .adm-detail {
    display: flex; flex-direction: column; min-height: 0; background: var(--paper);
    border-left: 1px solid var(--line-2); box-shadow: -22px 0 34px -30px rgba(6,36,63,.55);
  }
  :is(#adm-dashboard, #adm-brands) .adm-detail > .adm-editor { flex: 1 1 auto; min-height: 0; margin: 0; overflow-y: auto; padding: 16px 18px 0; display: flex; flex-direction: column; }
  :is(#adm-dashboard, #adm-brands) .adm-detail .adm-savebar { position: sticky; bottom: 0; margin: auto -18px 0; }
  :is(#adm-dashboard, #adm-brands) .adm-detail .adm-form { padding-bottom: 16px; }
  :is(#adm-dashboard, #adm-brands) .adm-detail-loading { flex: 1 1 auto; min-height: 0; margin: 18px; }
}
@media (min-width: 901px) and (max-width: 1100px) {
  :is(#adm-dashboard, #adm-brands).is-editing .adm-split { grid-template-columns: minmax(0, 1fr); }
  :is(#adm-dashboard, #adm-brands).is-editing .adm-detail { position: fixed; top: 0; right: 0; bottom: 0; width: min(720px, 92vw); z-index: 45; }
}
@media (max-width: 640px) {
  :is(#adm-dashboard, #adm-brands) > .adm-head { padding: 10px 18px; }
  :is(#adm-dashboard, #adm-brands) .adm-head-actions { flex-wrap: nowrap; }
  :is(#adm-dashboard, #adm-brands) #adm-new-btn { padding: 8px 16px; min-height: 44px; font-size: 14px; white-space: nowrap; }
  :is(#adm-dashboard, #adm-brands) .adm-master { padding: 12px 18px 8px; }
}

/* ---- Brands workspace (/admin/taxonomy) ----------------------------------- */
/* The Products workspace above with a brand table in it: the header, toolbar
   chips, table shell, row menu, docked panel and save bar are all shared (the
   :is(#adm-dashboard, #adm-brands) rules). Only the columns and two cells are its own:
     Brand | Brand strip | Products | Tags | menu
   Tags give way first (they move under the name), then Brand strip + Products
   (the status pill moves under the name) - by the table's own width, so the same
   rules serve a phone and a table squeezed by the open panel. */
.adm-btable .adm-thead-row, .adm-btable .adm-trow {
  grid-template-columns: minmax(220px, 2.2fr) minmax(230px, 1.5fr) minmax(100px, .8fr) minmax(100px, .8fr) 44px;
  padding-left: 8px;
}
/* A brand that is in the storefront strip carries a green edge. */
.adm-btable .adm-trow.is-instrip { box-shadow: inset 3px 0 0 var(--whatsapp); }
.adm-btable .adm-trow.is-selected { box-shadow: inset 3px 0 0 var(--navy); }
.adm-btable .adm-trow.is-dirty .adm-blogo { box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--crimson); }
.adm-blogo {
  flex: 0 0 auto; width: 68px; height: 44px; padding: 6px; display: flex; align-items: center; justify-content: center;
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
}
.adm-blogo img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.adm-blogo.is-empty { background: var(--paper); border-style: dashed; border-color: var(--line-2); font-size: 11px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.adm-tc-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.adm-tc-why { font-size: 13px; color: var(--muted); }
.adm-tc-count b { display: block; font-size: 13.5px; color: var(--navy); font-variant-numeric: tabular-nums; }
.adm-tc-count small { display: block; font-size: 12px; color: var(--muted); }
.adm-btable .adm-menu-item { white-space: nowrap; }
.adm-b-under { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.adm-b-upill, .adm-b-utags { display: none; }
.adm-b-utags { flex-wrap: wrap; gap: 4px; }
.adm-status--todo { background: transparent; color: var(--muted); box-shadow: inset 0 0 0 1px var(--line-2); }   /* needs a logo: not started */
.adm-flag.unused { background: transparent; border: 1px solid var(--signal); color: var(--navy); padding: 1px 5px; }
@container (max-width: 900px) {
  .adm-btable .adm-thead-row, .adm-btable .adm-trow { grid-template-columns: minmax(200px, 2fr) minmax(210px, 1.5fr) minmax(90px, .7fr) 44px; }
  .adm-btable .adm-tc-flags { display: none; }
  .adm-b-utags { display: flex; }
}
@container (max-width: 600px) {
  .adm-btable .adm-thead-row, .adm-btable .adm-trow { grid-template-columns: minmax(0, 1fr) 44px; column-gap: 6px; }
  .adm-btable .adm-tc-strip, .adm-btable .adm-tc-count { display: none; }
  .adm-btable .adm-trow .adm-tc-menu { grid-row: auto; }
  .adm-btable .adm-tc-open { min-height: 62px; padding-bottom: 8px; }
  .adm-b-upill { display: inline-flex; }
  #adm-brands .adm-master-tools #adm-filter { flex-basis: 100%; max-width: none; }
  #adm-brands .adm-seg { flex: 1 1 100%; }
  #adm-brands .adm-seg button { flex: 1 1 auto; padding-inline: 8px; white-space: nowrap; }
}
/* The count line wraps beside the button instead of pushing it to its own row. */
#adm-brands > .adm-head { flex-wrap: nowrap; }
#adm-brands > .adm-head > div:first-child { min-width: 0; }
#adm-brands #adm-new-btn { white-space: nowrap; }
#adm-brands .adm-seg button { font-size: 13.5px; font-weight: 600; color: var(--navy); }
#adm-brands .adm-seg button.active { color: #fff; }
#adm-brands .adm-seg button span { font-variant-numeric: tabular-nums; }
/* The panel. Docked beside the table from 1101px (the shared rules above);
   below that it is a sheet over the table, and the whole screen on a phone. */
#adm-brands .adm-detail > .adm-editor { flex: 1 1 auto; min-height: 0; margin: 0; overflow-y: auto; padding: 16px 18px 0; display: flex; flex-direction: column; }
#adm-brands .adm-detail .adm-savebar { position: sticky; bottom: 0; margin: auto -18px 0; }
#adm-brands .adm-detail .adm-form { padding-bottom: 16px; }
@media (max-width: 1100px) {
  #adm-brands.is-editing .adm-detail {
    display: flex; flex-direction: column; position: fixed; top: 0; right: 0; bottom: 0; width: min(720px, 92vw); z-index: 45;
    background: var(--paper); border-left: 1px solid var(--line-2); box-shadow: -22px 0 34px -30px rgba(6,36,63,.55);
  }
}
@media (max-width: 900px) { #adm-brands.is-editing .adm-detail { width: 100%; border-left: 0; } }
/* Logo section: the logo at its storefront size beside the upload control. */
.adm-blogo-edit { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 14px 16px; margin-bottom: 16px; }
.adm-logo-preview {
  flex: 1 1 200px; max-width: 320px; min-height: 104px; padding: 12px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
}
.adm-logo-preview img { max-width: 100%; }
.adm-logo-preview.is-empty { background: var(--paper); border-style: dashed; border-color: var(--line-2); }
.adm-blogo-side { flex: 1 1 200px; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.adm-blogo-side .adm-textbtn { padding: 0; }
#adm-brand-form .adm-pct { max-width: 220px; }
/* The line under a tick-box, indented to sit under its label. */
.adm-toggles .adm-bnote { margin: -4px 0 8px 29px; font-size: 12.5px; }
#b-strip-note { color: var(--ink); }
.adm-ed-acts { display: flex; flex-wrap: wrap; gap: 0 14px; }

/* ---- Unsaved changes in the product editor -------------------------------- */
/* A changed field: a crimson edge, a dot after its label, and the saved value
   on a ghost line under it. A changed tick-box gets a "Not saved" pill. */
.adm-form .adm-field { position: relative; }
.adm-form .adm-field.is-dirty::before {
  content: ""; position: absolute; left: -11px; top: 0; bottom: 0; width: 3px; border-radius: 3px; background: var(--crimson);
}
.adm-form .adm-field.is-dirty > label:first-child::after {
  content: ""; display: inline-block; width: 7px; height: 7px; margin-left: 7px; border-radius: 50%; background: var(--crimson); vertical-align: middle;
}
.adm-check.is-dirty::after {
  content: "Not saved"; margin-left: 4px; padding: 2px 8px; border-radius: 100px;
  background: var(--crimson); color: #fff; font-size: 10.5px; font-weight: 700; letter-spacing: .02em; white-space: nowrap;
}
.adm-was { margin: 2px 0 0; font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.adm-was b { font-weight: 600; color: var(--ink); }
/* The save bar: quiet when everything is saved, tinted with a crimson edge and
   the names of the changed fields the moment anything differs from the server.
   Docked at the foot of the panel; floating at the foot of the standalone page. */
.adm-savebar {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px 16px;
  padding: 10px 18px; background: var(--card); border-top: 1px solid var(--line-2); z-index: 4;
}
.adm-savebar-state { margin: 0; min-width: 0; font-size: 13.5px; color: var(--muted); }
.adm-savebar[data-dirty="clean"] .adm-savebar-state::before { content: "✓"; margin-right: 7px; color: var(--whatsapp); font-weight: 700; }
.adm-savebar[data-dirty="dirty"] { background: #FBEDEB; box-shadow: inset 0 3px 0 var(--crimson); }
.adm-savebar[data-dirty="dirty"] .adm-savebar-state { color: var(--ink); }
.adm-savebar-state b { color: var(--crimson); font-weight: 700; }
.adm-savebar-state b::before { content: ""; display: inline-block; width: 9px; height: 9px; margin-right: 7px; border-radius: 50%; background: var(--crimson); }
.adm-savebar-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.adm-savebar [hidden] { display: none; }
.adm-editor-wrap .adm-savebar { position: sticky; bottom: 12px; margin-top: 16px; border: 1px solid var(--line-2); border-radius: 12px; box-shadow: var(--shadow-sm); }
.adm-editor-wrap .adm-savebar[data-dirty="dirty"] { box-shadow: inset 0 3px 0 var(--crimson), var(--shadow-sm); }
#adm-form-alert { margin: 0 0 14px; }

/* ---- Product labels (/admin/labels): one US Letter page per product -------
   Two captain-approved layouts, FROZEN - do not restyle without a new approval:
   .lp-a Landscape (the desktop product page: photo left, price column right) and
   .lp-b Portrait (the same page stacked as a showroom poster). Every class is
   `lp-`-scoped so no storefront rule reaches a label. A .lp box is the page's
   printable area (Letter minus the 0.5in @page margin the label page sets in its
   <head>); on screen it is shown as a sheet of paper, scaled to fit by admin.js. */
.adm-labels-page .adm-head { margin-bottom: 20px; }
.adm-seg a { display: inline-flex; align-items: center; justify-content: center; color: var(--muted); font-size: 13px; padding: 7px 14px; min-height: 44px; min-width: 44px; }
.adm-seg a + a { border-left: 1px solid var(--line); }
.adm-seg a.active { background: var(--navy); color: #fff; }
.adm-label-sheet { display: flex; flex-direction: column; align-items: center; gap: 24px; }
/* Fills (sale pill, ticks) must print even with "Background graphics" unticked. */
.lp { -webkit-print-color-adjust: exact; print-color-adjust: exact; display: flex; flex-direction: column; flex: 0 0 auto; overflow: hidden; break-after: page; background: #fff; color: var(--ink); font-family: var(--font); line-height: 1.6; }
.lp:last-child { break-after: auto; }
.lp-a { width: 10in; height: 7.48in; }
.lp-b { width: 7.5in; height: 9.98in; }
.lp p { margin: 0; }
.lp img { max-width: none; }

.lp-top { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding-bottom: 12px; border-bottom: 1px solid var(--line-2); }
.lp-ach { display: flex; align-items: center; gap: 12px; font-family: var(--display); font-weight: 600; font-size: 22px; color: var(--navy); letter-spacing: -0.01em; }
.lp-ach img { width: 48px; height: 48px; }
.lp-top-r { text-align: right; font-size: 13px; line-height: 1.5; color: var(--muted); }
.lp-top-r b { color: var(--navy-2); font-weight: 600; }
.lp-foot { flex: 0 0 auto; display: flex; justify-content: space-between; gap: 20px; margin-top: auto; padding-top: 9px; border-top: 1px solid var(--line-2); font-size: 11.5px; line-height: 1.4; color: var(--muted); }

.lp-photo { position: relative; background: #fff; border: 1px solid var(--line-2); border-radius: 22px; overflow: hidden; min-height: 0; }
.lp-photo > img { position: absolute; object-fit: contain; }

.lp-brand { display: flex; align-items: center; }
.lp-brand-text { letter-spacing: .16em; text-transform: uppercase; color: var(--azure); font-weight: 600; }
.lp-name { color: var(--navy-2); line-height: 1.14; display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
.lp-meta { color: var(--muted); }
.lp-price { display: flex; flex-direction: column; align-items: flex-start; }
.lp-pr-lab { font-weight: 600; color: var(--crimson); letter-spacing: .005em; line-height: 1.4; }
.lp-now { font-family: var(--display); font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; line-height: 1.14; white-space: nowrap; }
.lp-pr-foot { display: flex; flex-wrap: wrap; align-items: center; }
.lp-pr-reg { color: var(--muted); font-variant-numeric: tabular-nums; }
.lp-pr-reg span { font-weight: 500; }
.lp-pr-save { font-weight: 700; color: #fff; background: var(--crimson); border-radius: 100px; letter-spacing: .01em; white-space: nowrap; font-variant-numeric: tabular-nums; line-height: 1.6; }
.lp-fulfil { color: var(--muted); }
.lp-why { list-style: none; margin: 0; padding: 0; display: grid; }
.lp-why li { position: relative; color: var(--ink); }
.lp-why li::before { content: '✓'; position: absolute; left: 0; border-radius: 50%; background: var(--navy); color: var(--sky-bright); display: grid; place-items: center; }

.lp-scan { display: flex; align-items: center; border: 1px solid var(--line-2); border-radius: 14px; }
.lp-qr { flex: 0 0 auto; }
.lp-qr svg { display: block; width: 100%; height: 100%; }
.lp-scan-t { display: flex; flex-direction: column; min-width: 0; }
.lp-scan-t b { font-family: var(--display); font-weight: 600; color: var(--navy-2); line-height: 1.2; }
.lp-scan-t span { color: var(--muted); line-height: 1.4; }

/* A - Landscape: the desktop buy block (photo 1.4fr | rail 1fr). */
.lp-a .lp-body { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0,1.4fr) minmax(0,1fr); gap: 38px; padding: 20px 0 14px; }
.lp-a .lp-left { display: flex; flex-direction: column; gap: 12px; min-height: 0; }
.lp-a .lp-photo { flex: 1; }
.lp-a .lp-photo > img { inset: 26px; width: calc(100% - 52px); height: calc(100% - 52px); }
.lp-a .lp-why { grid-template-columns: 1fr; gap: 5px; }
.lp-a .lp-why li { padding-left: 25px; font-size: 13px; line-height: 1.45; }
.lp-a .lp-why li::before { top: 0; width: 17px; height: 17px; font-size: 10.5px; }
.lp-a .lp-rail { display: flex; flex-direction: column; min-height: 0; }
.lp-a .lp-brand { min-height: 67px; margin-bottom: 9px; }
.lp-a .lp-brand-text { font-size: 24px; line-height: 1.2; }
/* Never shrunk by the column: a name that does not fit loses whole lines (admin.js), not a slice of one. */
.lp-a .lp-name { flex: 0 0 auto; font-size: 29px; -webkit-line-clamp: 4; }
.lp-a .lp-meta { font-size: 14.5px; margin: 8px 0 16px; }
.lp-a .lp-pr-lab { font-size: 16px; }
.lp-a .lp-now { font-size: 56px; }
.lp-a .lp-pr-foot { gap: 8px 14px; margin-top: 5px; }
.lp-a .lp-pr-reg { font-size: 16.5px; }
.lp-a .lp-pr-save { font-size: 14px; padding: 5px 13px; }
.lp-a .lp-fulfil { font-size: 12.5px; line-height: 1.4; }
.lp-a .lp-scan { margin-top: auto; gap: 16px; padding: 12px 16px 12px 12px; }
.lp-a .lp-qr { width: 1.5in; height: 1.5in; }
.lp-a .lp-scan-t b { font-size: 19px; }
.lp-a .lp-scan-t span { font-size: 13.5px; margin-top: 5px; }

/* B - Portrait: the showroom poster, price sized to read from across the aisle. */
.lp-b .lp-photo { flex: 1; margin-top: 18px; }
.lp-b .lp-photo > img { inset: 24px; width: calc(100% - 48px); height: calc(100% - 48px); }
.lp-b .lp-head { padding: 18px 0 14px; }
.lp-b .lp-brand { justify-content: space-between; gap: 16px; min-height: 84px; margin-bottom: 8px; }
.lp-b .lp-brand-text { font-size: 30px; line-height: 1.2; }
.lp-b .lp-name { font-size: 33px; -webkit-line-clamp: 3; }
.lp-b .lp-meta { font-size: 17px; margin-top: 8px; }
.lp-b .lp-buy { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding-top: 14px; border-top: 1px solid var(--line-2); }
.lp-b .lp-pr-lab { font-size: 21px; }
.lp-b .lp-now { font-size: 74px; letter-spacing: -0.02em; }
.lp-b .lp-pr-foot { gap: 8px 16px; margin-top: 6px; }
.lp-b .lp-pr-reg { font-size: 21px; }
.lp-b .lp-pr-save { font-size: 17px; padding: 5px 15px; }
.lp-b .lp-scan { flex: 0 0 auto; flex-direction: column; gap: 4px; padding: 8px 8px 6px; text-align: center; }
.lp-b .lp-qr { width: 1.25in; height: 1.25in; }
.lp-b .lp-scan-t b { font-size: 13px; }
.lp-b .lp-scan-t span { display: none; }
.lp-b .lp-why { grid-template-columns: repeat(3, minmax(0,1fr)); gap: 16px; margin: 14px 0 12px; padding-top: 13px; border-top: 1px solid var(--line-2); }
.lp-b .lp-why li { padding-left: 26px; font-size: 13px; line-height: 1.4; }
.lp-b .lp-why li::before { top: 0; width: 18px; height: 18px; font-size: 11px; }

@media screen {
  /* The sheet of paper: the 0.5in page margin becomes padding around the same
     printable box, and --lp-zoom (admin.js) shrinks it to the window's width. */
  .lp { box-sizing: content-box; padding: 0.5in; border-radius: 4px; box-shadow: 0 0 0 1px var(--line), var(--shadow-sm); zoom: var(--lp-zoom, 1); }
}
@media print {
  .no-print { display: none !important; }
  body.admin { background: #fff; min-height: 0; }
  .adm-labels-page { max-width: none; padding: 0; margin: 0; }
  .adm-label-sheet { display: block; }
  @page { margin: 12mm; }
}

/* Right pane: the inline editor. */
.adm-detail { min-width: 0; }
.adm-detail-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  text-align: center; min-height: 420px; padding: 40px;
  background: var(--card); border: 1px dashed var(--line-2); border-radius: var(--radius); color: var(--muted);
}
.adm-detail-empty svg { color: var(--sky); }
.adm-detail-empty p { font-size: 15px; max-width: 30ch; }
.adm-detail-loading {
  display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 420px; color: var(--muted);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
}
.adm-detail-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.adm-detail-head h2 { font-size: 22px; }

/* ---- Sectioned editor form ----------------------------------------------- */
/* These are <section> elements; neutralize the storefront's global
   `section { padding: 84px 0 }` (.adm-master and the product form's cards set
   their own padding). */
.adm-od .adm-section, .adm-detail, .adm-tax-section { padding: 0; }
.adm-section { margin-bottom: 20px; }
.adm-section:last-child { margin-bottom: 0; }
.adm-section-head { margin-bottom: 14px; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.adm-section-head h3 { font-size: 13px; font-weight: 700; color: var(--navy); text-transform: uppercase; letter-spacing: .06em; }
.adm-field-hint { color: var(--muted); font-size: 12px; margin: 0; }
.adm-field-error { color: var(--crimson); font-size: 12.5px; font-weight: 600; margin: 2px 0 0; }
.adm-field.has-error > input, .adm-field.has-error > select, .adm-field.has-error > textarea { border-color: var(--crimson); }
.adm-field.has-error > input:focus, .adm-field.has-error > select:focus, .adm-field.has-error > textarea:focus { box-shadow: 0 0 0 3px rgba(158,43,37,.15); }
#adm-form-alert:not([hidden]) { display: block; }

.adm-price-preview { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 12px 14px; background: var(--paper-2); border-radius: 10px; font-variant-numeric: tabular-nums; }
.pp-was { color: var(--muted); text-decoration: line-through; font-weight: 600; }
.pp-arrow { color: var(--sky); font-weight: 700; }
.pp-now { color: var(--navy); font-weight: 800; font-size: 17px; }
.pp-save { margin-left: auto; background: var(--crimson); color: #fff; font-weight: 700; font-size: 12.5px; padding: 3px 10px; border-radius: 100px; }
.pp-hint { color: var(--muted); font-size: 13px; }

.adm-textbtn { background: none; border: 0; cursor: pointer; font-weight: 600; font-size: 14px; color: var(--muted); min-height: 44px; padding: 0 6px; }
.adm-textbtn:hover { color: var(--navy); }
.adm-textbtn.danger { color: var(--crimson); }
.adm-textbtn.danger:hover { color: #b73831; text-decoration: underline; }

/* ---- Gallery: cover flag + upload progress ------------------------------- */
.adm-thumb { position: relative; }
.adm-cover-flag { position: absolute; top: 8px; left: 8px; background: var(--signal); color: #fff; font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: 100px; box-shadow: var(--shadow-sm); }
.adm-upload-status { margin-top: 12px; font-size: 13.5px; color: var(--muted); display: flex; align-items: center; gap: 8px; }
.adm-spinner { width: 15px; height: 15px; border-radius: 50%; border: 2px solid var(--line-2); border-top-color: var(--azure); display: inline-block; animation: adm-spin .7s linear infinite; }
@keyframes adm-spin { to { transform: rotate(360deg); } }

/* ---- Taxonomy: column tools + fixed-department note ---------------------- */
.adm-tax-colhead { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.adm-tax-colhead h2 { font-size: 18px; }
.adm-tax-count { font-size: 12.5px; color: var(--muted); font-weight: 600; }
.adm-tax-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.adm-tax-tools .adm-tax-search { flex: 1 1 180px; min-width: 0; }
.adm-tax-note { color: var(--muted); font-size: 12.5px; margin: 0 0 12px; }

/* ---- Modal dialog (replaces native prompt/confirm) ----------------------- */
.adm-modal-back {
  position: fixed; inset: 0; z-index: 200; background: rgba(6,36,63,.5);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.adm-modal {
  width: 100%; max-width: 440px; background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; box-shadow: var(--shadow); padding: 24px; animation: adm-pop .16s ease-out;
}
@keyframes adm-pop { from { opacity: 0; transform: translateY(6px) scale(.98); } }
.adm-modal-title { font-size: 20px; margin-bottom: 8px; }
.adm-modal-msg { color: var(--muted); font-size: 14.5px; line-height: 1.55; }
.adm-modal-field { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; font-size: 13.5px; font-weight: 600; color: var(--navy); }
.adm-modal-field input, .adm-modal-field select { width: 100%; min-height: 44px; }
.adm-modal-field textarea {
  width: 100%; min-height: 76px; resize: vertical; font: inherit; font-weight: 400;
  background: var(--card); border: 1px solid var(--line); color: var(--ink);
  padding: 12px 14px; border-radius: 10px; outline: none; transition: border-color .2s, box-shadow .2s;
}
.adm-modal-field textarea:focus { border-color: var(--azure); box-shadow: 0 0 0 3px rgba(30,111,176,.15); }
.adm-modal-money { min-height: 1.3em; font-size: 12.5px; font-weight: 500; color: var(--muted); font-variant-numeric: tabular-nums; }
.adm-modal-error { margin: 14px 0 0; font-size: 13.5px; font-weight: 600; color: var(--crimson); }
.adm-modal-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
/* dialog({ altLabel }): the third, destructive choice sits apart on the left. */
.adm-modal-alt { margin-right: auto; order: -1; white-space: nowrap; }
.adm-modal:has(.adm-modal-alt) { max-width: 520px; }

@media (prefers-reduced-motion: reduce) {
  .adm-modal { animation: none; }
  .adm-spinner { animation-duration: 1.6s; }
}

/* ---- Orders (read-only view) --------------------------------------------- */
/* Status pill. One tone per operational meaning, never per payment method - a
   status is readable on its own (server/order-status.js). Every pairing below is
   AA on the surface it sits on: crimson/navy/muted are the tokens' documented
   text colors, and the two FILLED tones (critical, action) take white per the
   --crimson / --signal token notes.
   Shared with the FAQ manager's Live/Draft/Not-answered pills, which map onto the
   same tones (done/ready/idle) - the modifiers are tiers of "how settled is this",
   not order vocabulary, and reusing them keeps one contrast-tested pill. */
.adm-status {
  display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: .02em;
  padding: 3px 8px; border-radius: 100px; white-space: nowrap;
}
.adm-status--critical { background: var(--crimson); color: #fff; }        /* orphaned: real money, no order */
.adm-status--action   { background: var(--signal); color: #fff; }         /* awaiting_approval: ACH owes a decision */
.adm-status--ready    { background: rgba(0,48,96,.10); color: var(--navy); }   /* awaiting_pickup: customer is coming */
.adm-status--done     { background: rgba(14,122,62,.12); color: var(--whatsapp); }
.adm-status--idle     { background: var(--paper-2); color: var(--muted); }     /* dead carts + closed states recede */

/* ---- Server log (/admin/logs) - read-only, server-rendered ---------------- */
.adm-log-list { display: flex; flex-direction: column; gap: 8px; }
.adm-log-row {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 16px; display: flex; flex-direction: column; gap: 6px; box-shadow: var(--shadow-sm);
}
.adm-log-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.adm-log-time { color: var(--muted); font-size: 13px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.adm-log-path { color: var(--muted); font-size: 13px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere; }
.adm-log-msg { margin: 0; color: var(--ink); font-size: 14.5px; line-height: 1.5; overflow-wrap: anywhere; }
.adm-log-stack summary { display: inline-flex; align-items: center; min-height: 44px; color: var(--azure); font-size: 13.5px; font-weight: 600; cursor: pointer; }
.adm-log-stack pre {
  margin: 4px 0 0; padding: 12px 14px; background: var(--paper-2); border: 1px solid var(--line);
  border-radius: 10px; overflow-x: auto; font-size: 12.5px; line-height: 1.5;
}

/* Orphaned banner: the highest-severity row that can appear, so it is a
   full-width alert above the list rather than a flag inside it. */
.adm-orphan-alert {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 18px; padding: 14px 16px; border-radius: 12px;
  background: var(--crimson); color: #fff; box-shadow: var(--shadow-sm);
}
.adm-orphan-alert svg { flex: 0 0 auto; }
.adm-orphan-alert span { flex: 1 1 260px; min-width: 0; font-size: 14px; line-height: 1.5; }
.adm-orphan-alert .btn { flex: 0 0 auto; background: #fff; border-color: #fff; color: var(--crimson); }
.adm-orphan-alert .btn:hover { background: rgba(255,255,255,.86); border-color: transparent; }

/* Attention band: the work a human owes, on screen without filtering first. */
.adm-attention { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
.adm-att-chip {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 6px 16px 6px 6px;
  border-radius: 100px; border: 1px solid var(--line-2); background: var(--card);
  cursor: pointer; transition: border-color .15s, box-shadow .15s;
}
.adm-att-chip:hover { border-color: var(--navy); }
.adm-att-chip.is-on { border-color: var(--navy); box-shadow: 0 0 0 2px rgba(0,48,96,.18); }
.adm-att-n {
  display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 32px;
  padding: 0 8px; border-radius: 100px; font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.adm-att-chip--action .adm-att-n { background: var(--signal); color: #fff; }
.adm-att-chip--ready .adm-att-n { background: rgba(0,48,96,.10); color: var(--navy); }
.adm-att-label { font-size: 14px; font-weight: 600; color: var(--navy); }

/* An order row carries more text than a product row (number + name + date +
   method + status + amount) and has no thumbnail, so it gets a wider master pane
   and stacks into two lines instead of competing for one. Scoped to the
   two-column breakpoint on purpose: an id-specificity rule here would otherwise
   beat the single-column `.adm-split` mobile rule below, which media queries
   cannot outrank. */
@media (min-width: 901px) {
  #adm-orders .adm-split { grid-template-columns: minmax(0, 560px) minmax(0, 1fr); }
}
/* Orders runs the full window width (body.adm-wide, like Products), so the order
   pane is wide enough for its item lines to be a table. */
#adm-orders.adm-workspace { max-width: none; }
@media (min-width: 641px) { #adm-orders.adm-workspace { padding-left: 20px; padding-right: 20px; } }
/* align-items:stretch undoes the base .adm-lrow-open's `align-items:center`,
   which centers the CHILDREN once the axis flips to column. */
.adm-orow-open { display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 10px 8px; }
.adm-orow-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; min-width: 0; }
.adm-orow-amount { flex: 0 0 auto; font-weight: 700; color: var(--navy); font-size: 13px; font-variant-numeric: tabular-nums; }
.adm-orow-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
.adm-orow-when { min-width: 0; font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-orow-phone { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Order detail: label/value lines + the line-item block. */
.adm-od {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 22px 24px;
}
.adm-od-warn {
  margin: 0 0 18px; padding: 12px 14px; border-radius: 10px; font-size: 13.5px; font-weight: 600; line-height: 1.5;
  background: rgba(158,43,37,.10); color: var(--crimson); border: 1px solid rgba(158,43,37,.35);
}
.adm-od-line {
  display: flex; justify-content: space-between; align-items: baseline; gap: 18px;
  padding: 7px 0; font-size: 14px; min-width: 0;
}
.adm-od-line > span:first-child { color: var(--muted); flex: 0 0 auto; }
.adm-od-line > span:last-child { text-align: right; min-width: 0; overflow-wrap: anywhere; font-weight: 500; }
.adm-od-line a { color: var(--azure); font-weight: 600; }
.adm-od-line a:hover { color: var(--navy); }
/* The tel:/mailto: links are tap-to-call on a phone: 44px tall without making the row taller. */
.adm-od-line a { display: inline-flex; align-items: center; min-height: 44px; margin: -14px 0; }
.adm-od-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--muted); }
/* Stripe's own figure on an orphan. Deliberately NOT styled like .adm-od-total:
   it is a reference amount in Stripe's currency, never the GYD contract, so it
   stays body-sized and muted-labelled rather than big/navy/tabular. The "from
   Stripe" tag rides with it everywhere it appears so it cannot be read as GYD. */
.adm-od-stripe-amt { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.adm-od-stripe-src {
  margin-left: 8px; padding: 1px 7px; border-radius: 100px; white-space: nowrap;
  background: var(--paper-2); color: var(--muted); font-size: 11px; font-weight: 600;
}
.adm-od-items { display: flex; flex-direction: column; }
.adm-od-item { display: flex; justify-content: space-between; gap: 18px; padding: 7px 0; font-size: 14px; color: var(--muted); }
.adm-od-item > span:last-child { white-space: nowrap; font-variant-numeric: tabular-nums; }
.adm-od-noitems { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.55; }
.adm-od-total {
  display: flex; justify-content: space-between; gap: 18px; margin-top: 10px; padding-top: 12px;
  border-top: 1px solid var(--line); font-family: var(--display); font-weight: 700; font-size: 17px;
  color: var(--navy); font-variant-numeric: tabular-nums;
}
/* Order detail: the status audit trail, oldest first. A quiet timeline - a pill
   for the state reached, who moved it and when, and any note ACH left. */
.adm-od-history { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.adm-od-hitem { padding-left: 16px; border-left: 2px solid var(--line-2); }
.adm-od-hhead { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.adm-od-hmeta { font-size: 12.5px; color: var(--muted); }
.adm-od-hnote {
  margin: 6px 0 0; font-size: 13.5px; color: var(--ink); line-height: 1.5; overflow-wrap: anywhere;
}
/* Order detail: the cash lane's actions. The only block in this pane that WRITES,
   so it is set off on its own surface rather than reading as one more row of
   detail. Beats `.adm-od .adm-section { padding: 0 }` above, hence the two-class
   selector. Buttons inherit .adm-sm's 44px tap target. */
.adm-od .adm-od-actions {
  padding: 16px 18px; margin-bottom: 20px;
  border: 1px solid var(--line-2); border-radius: 12px; background: var(--paper);
}
.adm-od-actions .adm-section-head { margin-bottom: 6px; padding-bottom: 0; border-bottom: none; }
.adm-od-actions-hint { margin: 0 0 14px; color: var(--muted); font-size: 13px; line-height: 1.55; }
.adm-od-actbar { display: flex; flex-wrap: wrap; gap: 10px; }
.adm-od-actbar .btn { flex: 1 1 auto; justify-content: center; }
/* Reject/cancel: crimson TEXT on a ghost button, matching every other in-page
   destructive action here (.adm-textbtn.danger, .adm-menu-item.danger). The
   filled .adm-danger stays reserved for the confirm button inside the dialog, so
   the weight escalates only once the operator is being asked to be sure. */
.adm-od-actbar .btn-ghost.danger { color: var(--crimson); border-color: rgba(158,43,37,.35); }
.adm-od-actbar .btn-ghost.danger:hover { color: #fff; background: var(--crimson); border-color: var(--crimson); }

/* ---- Order editor --------------------------------------------------------
   An editable order's Items section is the editor (public/js/admin.js, "the
   order editor"): lines edited in place, nothing saved until the save bar's
   Save. A changed line carries the Products editor's markers - crimson edge,
   "Saved: ..." line (.adm-was) - plus its own Undo.
   The lines are a table (item / quantity / total / actions) only when the pane
   itself is wide enough, so the layout follows the pane, not the window: the
   container query keeps a narrow pane on a wide screen in the stacked form. */
.adm-od-tag {
  display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); background: var(--paper-2); border: 1px solid var(--line-2);
  border-radius: 6px; padding: 0 6px; vertical-align: middle;
}
.adm-od-resend { margin-top: 14px; width: 100%; justify-content: center; }
.adm-oe .adm-section-head h3 { display: flex; align-items: center; gap: 10px; }
.adm-oe .adm-section-head .adm-status { text-transform: none; letter-spacing: 0; }
.adm-oe-lines { container-type: inline-size; display: flex; flex-direction: column; }
.adm-oe-head { display: none; }
.adm-oe-line {
  position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px;
  padding: 14px 4px 10px 12px; border-bottom: 1px solid var(--line); font-size: 14px; color: var(--ink);
}
.adm-oe-item { display: flex; align-items: flex-start; gap: 12px; flex: 1 1 100%; min-width: 0; }
.adm-oe-text { min-width: 0; }
.adm-oe-thumb {
  width: 44px; height: 44px; flex: 0 0 auto; border-radius: 8px; background: #fff; border: 1px solid var(--line);
  overflow: hidden; display: grid; place-items: center; color: var(--muted);
}
.adm-oe-thumb img { width: 100%; height: 100%; object-fit: contain; }
.adm-oe-thumb--charge { background: var(--paper-2); }
.adm-oe-name {
  font-weight: 600; color: var(--navy); font-size: 14.5px; line-height: 1.3; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.adm-oe-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin-top: 3px; font-size: 12.5px; color: var(--muted); }
.adm-oe-mtotal { color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.adm-oe-total { display: none; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.adm-oe-qtycell:empty { display: none; }
.adm-oe-acts { display: flex; align-items: center; justify-content: flex-end; gap: 2px; margin-left: auto; }
.adm-oe-acts .adm-textbtn { padding: 0 8px; }
.adm-oe-step {
  display: inline-flex; align-items: center; border: 1px solid var(--line-2); border-radius: 10px;
  background: #fff; overflow: hidden;
}
.adm-oe-step button {
  width: 44px; height: 44px; border: 0; background: none; font-size: 20px; line-height: 1; color: var(--navy); cursor: pointer;
}
.adm-oe-step button:hover { background: var(--paper-2); }
.adm-oe-step button:disabled { color: var(--line-2); cursor: default; background: none; }
.adm-oe-step .adm-oe-qty {
  width: 44px; height: 44px; min-height: 0; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none;
  text-align: center; font-weight: 700; font-size: 15px; color: var(--ink); font-variant-numeric: tabular-nums;
}
.adm-oe-step .adm-oe-qty:focus { outline: 2px solid var(--azure); outline-offset: -2px; }
.adm-oe-line.is-changed { background: #FDF6F5; }
.adm-oe-line.is-changed::before {
  content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 3px; background: var(--crimson);
}
.adm-oe-line.is-removed .adm-oe-name, .adm-oe-line.is-removed .adm-oe-total,
.adm-oe-line.is-removed .adm-oe-sub { text-decoration: line-through; color: var(--muted); }
.adm-oe-line.is-removed .adm-oe-mtotal { color: var(--muted); }
.adm-oe-line.is-removed .adm-oe-thumb { opacity: .45; }
.adm-oe-line .adm-was { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; margin-top: 4px; font-size: 12.5px; }
/* A 44px tap target that does not make the "Saved:" line 44px tall. */
.adm-oe-undo {
  display: inline-flex; align-items: center; min-width: 44px; min-height: 44px; margin: -14px 0; padding: 0; border: 0; background: none;
  font: inherit; font-weight: 700; color: var(--azure); text-decoration: underline; cursor: pointer; vertical-align: middle;
}
.adm-oe-undo:hover { color: var(--navy); }
.adm-oe .adm-menu-item:disabled { opacity: .5; cursor: not-allowed; background: none; }
.adm-oe-menunote { margin: 0 12px 8px; font-size: 12px; line-height: 1.4; color: var(--muted); }
@container (min-width: 640px) {
  .adm-oe-head, .adm-oe-line { display: grid; grid-template-columns: minmax(0, 1fr) 134px 144px 152px; align-items: center; gap: 14px; }
  .adm-oe-head {
    padding: 0 12px 8px; border-bottom: 1px solid var(--line-2);
    font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
  }
  .adm-oe-r { text-align: right; }
  .adm-oe-line { padding: 12px; }
  .adm-oe-item { align-items: center; }
  .adm-oe-total { display: block; }
  .adm-oe-mtotal { display: none; }
  .adm-oe-qtycell:empty { display: block; }
}
/* The add box: a button dressed as the search field it opens. */
.adm-oe-add {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 48px; margin-top: 14px; padding: 8px 12px 8px 14px;
  border: 1px solid var(--line-2); border-radius: 12px; background: #fff; color: var(--muted);
  font: inherit; font-size: 15px; text-align: left; cursor: text;
}
.adm-oe-add:hover { border-color: var(--sky); }
.adm-oe-add span { flex: 1 1 auto; min-width: 0; }
.adm-pal-keys kbd {
  font: 600 11.5px/1 var(--font); padding: 4px 7px; border-radius: 6px; border: 1px solid var(--line-2);
  background: var(--paper); color: var(--muted);
}
.adm-oe-warn {
  margin: 14px 0 0; padding: 10px 12px; border-radius: 10px; background: #FBEDEB; border: 1px solid rgba(158,43,37,.3);
  color: var(--ink); font-size: 13px; line-height: 1.5;
}
.adm-oe-totals { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-2); display: flex; flex-direction: column; gap: 6px; align-items: flex-end; }
.adm-oe-totals > div { display: flex; justify-content: space-between; gap: 24px; width: min(100%, 380px); font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }
.adm-oe-totals > .adm-od-total { margin-top: 2px; padding-top: 8px; font-size: 19px; color: var(--navy); }
/* The order's save bar: only on screen while something is unsaved, stuck to the
   foot of the window for as long as the order card is in view. In flow at the
   card's end, so the last lines and the totals always scroll clear of it. */
.adm-oe-bar { position: sticky; bottom: 0; margin: 20px -24px -22px; border-radius: 0 0 var(--radius) var(--radius); }
.adm-oe-bar[hidden] { display: none; }
.adm-oe-bar .adm-savebar-state span { color: var(--muted); }
.adm-oe-bar .adm-savebar-state strong { color: var(--navy); }
.adm-oe-bar[data-dirty="dirty"] { box-shadow: inset 0 3px 0 var(--crimson), 0 -10px 24px -18px rgba(6,36,63,.5); }
.adm-lrow.is-dirty { border-color: var(--crimson); }
.adm-orow-pills { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }

/* The product picker (swap / add): a search box at the top of the window over a
   scrolling list of results. Rows never shrink (the old list squeezed 60 rows
   into 340px, so names overprinted each other); the list scrolls instead. */
.adm-pal-back {
  position: fixed; inset: 0; z-index: 200; background: rgba(6,36,63,.42);
  display: flex; justify-content: center; align-items: flex-start; padding: 9vh 20px 20px;
}
.adm-pal {
  width: 100%; max-width: 680px; max-height: min(640px, 82vh); display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); overflow: hidden;
}
.adm-pal-input { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; padding: 6px 8px 6px 18px; border-bottom: 1px solid var(--line-2); color: var(--muted); }
.adm-pal-input svg { flex: 0 0 auto; }
.adm-pal-input input {
  flex: 1 1 auto; min-width: 0; min-height: 52px; padding: 0; border: 0; border-radius: 0; outline: 0; box-shadow: none;
  background: none; font: inherit; font-size: 17px; color: var(--ink);
}
.adm-pal-ctx { flex: 0 0 auto; margin: 0; padding: 9px 18px; font-size: 12.5px; line-height: 1.5; color: var(--muted); background: var(--paper); border-bottom: 1px solid var(--line); }
.adm-pal-ctx b { color: var(--navy); }
.adm-pal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 6px 8px; }
.adm-pal-group { margin: 0; padding: 10px 12px 4px; font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.adm-pal-none { margin: 0; padding: 10px 12px; font-size: 13.5px; color: var(--muted); }
.adm-pal-row { display: flex; align-items: center; gap: 14px; padding: 8px 12px; border-radius: 12px; cursor: pointer; }
.adm-pal-row.is-active { background: var(--paper-2); }
.adm-pal-row[aria-disabled="true"] { cursor: not-allowed; }
.adm-pal-row .adm-oe-thumb { width: 56px; height: 56px; border-radius: 10px; }
.adm-pal-main { flex: 1 1 auto; min-width: 0; }
.adm-pal-price { flex: 0 0 auto; text-align: right; }
.adm-pal-price strong { display: block; font-size: 14.5px; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.adm-pal-row.is-out .adm-oe-name, .adm-pal-row.is-out .adm-pal-price strong,
.adm-pal-row[aria-disabled="true"] .adm-oe-name, .adm-pal-row[aria-disabled="true"] .adm-pal-price strong { color: var(--muted); }
.adm-pal-delta { font-size: 12.5px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.adm-pal-foot {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px 16px;
  padding: 10px 18px; border-top: 1px solid var(--line-2); background: var(--paper); font-size: 12.5px; color: var(--muted);
}
.adm-pal-total { margin: 0; display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; font-size: 14px; font-variant-numeric: tabular-nums; }
.adm-pal-total strong { font-size: 18px; color: var(--navy); }
.adm-pal-keys { margin: 0; display: flex; align-items: center; gap: 14px; }
@media (max-width: 640px) {
  /* A full-screen sheet on a phone. */
  .adm-pal-back { padding: 0; }
  .adm-pal { max-width: none; max-height: none; height: 100vh; height: 100dvh; border: 0; border-radius: 0; }
  .adm-pal-keys { display: none; }
  .adm-pal-row { gap: 10px; padding: 8px; }
  .adm-pal-row .adm-oe-thumb { width: 48px; height: 48px; }
  .adm-pal-model { display: none; }
  /* A narrower card edge, so a line's stepper and its actions share one row. */
  .adm-od:has(.adm-oe) { padding: 18px 14px; }
  .adm-oe-line { padding-right: 0; }
  .adm-oe-bar { margin: 20px -14px -18px; padding: 10px 12px; }
  .adm-oe-bar .adm-savebar-actions { width: 100%; }
  .adm-oe-bar .adm-savebar-actions .btn { flex: 1 1 0; justify-content: center; }
}

/* ---- Admin responsive ---------------------------------------------------- */
@media (max-width: 900px) {
  /* Master-detail collapses to a single list; a tapped product opens the full
     editor page (public/js/admin.js isNarrow()), so the detail pane is unused. */
  .adm-split { grid-template-columns: 1fr; }
  .adm-master { position: static; max-height: none; }
  .adm-detail { display: none; }
  /* Orders have no standalone page to fall back to (the products list opens
     /admin/products/:id/edit on narrow screens), so the order detail keeps
     rendering below the list instead of being hidden. Id beats the class above. */
  #adm-orders .adm-detail { display: block; margin-top: 18px; }
}
/* The inline nav row keeps growing as pages are added (Inbox, Applications, Server
   log, Homepage slides, the Account menu), so it collapses to the hamburger below
   1400px - the full row (nowrap labels) needs ~1366px, so 1400 leaves margin and no
   width wraps a label onto two lines (.adm-top-inner's max-width must stay above
   that figure too, or the row never fits at any width). Measure the row's max-content width and
   raise this again when the next link lands. The form-grid rules stay on their own
   760px query below. */
@media (max-width: 1400px) {
  .adm-nav-toggle { display: inline-flex; }
  .adm-nav {
    position: absolute; top: calc(100% + 6px); left: 18px; right: 18px; z-index: 60;
    flex-direction: column; align-items: stretch; gap: 2px; display: none;
    background: var(--card); border: 1px solid var(--line); border-radius: 12px;
    box-shadow: var(--shadow); padding: 8px;
  }
  .adm-nav.open { display: flex; }
  .adm-nav a { min-height: 46px; padding: 8px 12px; border-radius: 9px; }
  .adm-account { margin: 4px 0 0; }
  .adm-logout-btn { width: 100%; justify-content: center; }
  .adm-account-menu { position: static; box-shadow: none; border: 0; padding: 4px 0 0; }
}
@media (max-width: 760px) {
  .adm-form-grid { grid-template-columns: 1fr; }
  .adm-col-2 { grid-column: auto; }
}
@media (max-width: 640px) {
  .adm-wrap { padding: 22px 18px 60px; }
  .adm-workspace { padding: 20px 16px 56px; }
  .adm-master { padding: 12px; }
  .adm-facets { grid-template-columns: 1fr; }
  .adm-top-inner { padding: 10px 18px; }
  .adm-row {
    grid-template-columns: 56px minmax(0,1fr) auto;
    grid-template-areas: "img main price" "actions actions actions";
    gap: 10px 14px;
  }
  .adm-row-img { width: 56px; height: 56px; }
  .adm-row-actions { justify-content: flex-start; }
  .adm-row-actions .btn { flex: 1 1 auto; }
  /* Taxonomy rows have no image/price track - stack main over actions (this must
     follow the generic .adm-row rule above to win at equal specificity). Three
     action buttons don't fit one line at 320px, so let them wrap (the 2-button
     product rows never needed this). */
  .adm-tax-row { grid-template-columns: 1fr; grid-template-areas: "main" "actions"; }
  .adm-tax-row .adm-row-actions { flex-wrap: wrap; }
}

/* ============================================================================
   Customer accounts (/signin, /signup, /account, /reset-password)
   Reuses the .cform field system + .btn - these pages add layout, not a second
   form language. See server/auth.js for the flows behind them.
   ============================================================================ */
/* padding-top clears the fixed nav, same as .cart-layout / .shop-layout. */
.auth-layout { max-width: 480px; padding-top: 132px; padding-bottom: 90px; }
.auth-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 34px 30px 30px; }
.auth-card h1 { font-family: var(--display); font-size: clamp(24px, 5vw, 30px); letter-spacing: -.02em; color: var(--navy-2); margin: 0 0 8px; }
.auth-sub { font-family: var(--prose); font-size: 14px; color: var(--muted); line-height: 1.6; margin: 0 0 22px; }
.auth-hint { font-size: 12px; color: var(--muted); font-style: normal; }
.auth-submit { width: 100%; justify-content: center; margin-top: 4px; }
.auth-alt { font-size: 14px; color: var(--muted); text-align: center; margin: 16px 0 0; }
.auth-alt a { color: var(--azure); font-weight: 600; }
.auth-alt a:hover { text-decoration: underline; }
/* Guest checkout is not a lesser path - accounts are additive, so say so plainly
   rather than implying a sign-in wall that does not exist. */
.auth-guest { font-size: 13px; color: var(--muted); text-align: center; margin: 18px 0 0; padding-top: 16px; border-top: 1px solid var(--line); }
.auth-guest a { color: var(--azure); font-weight: 600; }

.account-layout { padding-top: 132px; padding-bottom: 90px; }
.account-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: 34px; }
.account-head h1 { font-family: var(--display); font-size: clamp(28px, 6vw, 36px); letter-spacing: -.02em; margin: 0 0 6px; }
.account-who { font-size: 14px; color: var(--muted); margin: 0; overflow-wrap: anywhere; }
.account-orders h2 { font-family: var(--display); font-size: 20px; color: var(--navy-2); margin: 0 0 16px; }
.account-note { font-family: var(--prose); font-size: 14px; color: var(--muted); line-height: 1.6; margin: 0; }
.account-empty { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 34px 28px; text-align: center; }
.account-empty p { margin: 0 0 10px; }
.account-empty .btn { margin-top: 16px; }

.order-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px 22px; margin-bottom: 12px; }
.oc-top { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.oc-num { font-family: var(--display); font-weight: 600; color: var(--navy-2); margin-right: 10px; }
.oc-date { font-size: 13px; color: var(--muted); }
/* Status is a quiet outlined chip, not a colour-coded fill: the vocabulary has
   six values (server/order-status.js) and colouring them would need six AA-safe
   pairs to earn its keep. */
.oc-status { font-size: 12px; font-weight: 600; color: var(--navy); border: 1px solid var(--line-2); border-radius: 100px; padding: 4px 11px; white-space: nowrap; }
.oc-items { font-family: var(--prose); font-size: 14px; color: var(--muted); line-height: 1.6; margin: 12px 0 14px; overflow-wrap: anywhere; }
.oc-foot { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.oc-total { font-family: var(--display); font-weight: 600; color: var(--navy-2); }
/* A standalone control, NOT running prose, so the WCAG 2.5.5 inline exception does
   not apply and it carries a full 44px hit area of its own. The negative inline
   margin lets the box reach past the text without pushing the link off the card's
   right edge. Guard: npm run test:responsive. */
.oc-link {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 8px; margin-right: -8px;
  color: var(--azure); font-weight: 600; font-size: 14px; white-space: nowrap;
}
.oc-link:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .auth-layout { padding-top: 104px; }
  .auth-card { padding: 26px 20px 24px; }
  .account-layout { padding-top: 104px; }
  .account-head { margin-bottom: 26px; }
  .order-card { padding: 18px 16px; }
}

/* ---- Parts page (Direction B "Kept Running": warm photographic editorial) -----
   A magazine-style story, purely design + copy: a clean full-width hero photo with
   the headline in a navy band below it, drop-cap lede, two photo-caption pairs, a
   navy pull-quote band, the brand row, and a serif closing. Two deliberate,
   PAGE-SCOPED breaks from Deep Harbor (everything is under `.parts-b` so nothing
   leaks): Maitree (--prose) is promoted to display type, and the paper warms from
   cool porcelain to a soft cream with a brass accent (the hero rule + the closing
   band's hairline). Navy stays the anchor. Text on cream uses AA-checked values:
   --navy-2 headings, #4A5A6A body (6.7:1), #6F614B captions/meta (5.7:1 - the
   mock's lighter brass-brown was 3.9:1 and failed).
   Photography is parts-specific generated art standing in for a counter/shelf
   shoot; the hero swaps to the 4:3 variant on phones via <picture>. */
.parts-b { background: #FBF8F3; color: #4A5A6A; }
/* Every section below sets its own padding shorthand, which is what overrides the
   global `section { padding: 84px 0 }` - do NOT add a `.parts-b section` reset here: at
   (0,1,1) it would outrank the `.pb-*` rules and collapse the page's rhythm. */
.parts-b h1, .parts-b h2 { font-family: var(--prose); font-weight: 600; letter-spacing: 0; text-wrap: balance; }
.parts-b p { font-family: var(--prose); }

/* Hero ("Photo First"): the photo is a clean full-width plate with nothing over it,
   running up under the fixed nav (the translucent nav frosts over the photo's bright
   top band, not a bare navy field, so no grey-bar bug); the headline sits in its own
   opaque navy band directly below. The plate's aspect-ratio matches each <picture>
   source (21:9 master, 4:3 at <=640), so its space is reserved before the image loads.
   100% not 100vw. */
.pb-hero { text-align: center; background: var(--navy-2); }
.pb-hero picture { display: block; }
.pb-hero-bg { display: block; width: 100%; height: auto; aspect-ratio: 2400 / 1018; max-height: 680px;
  object-fit: cover; object-position: 50% 50%; }   /* the cap only bites past ~1600px wide, where the native ratio would push the headline off the first screen */
.pb-hero-c { padding: 44px 28px 46px; max-width: 1240px; margin: 0 auto; }   /* wide enough to hold the headline on one line at desktop widths */
.pb-hero h1 { font-size: clamp(36px, 4.1vw, 54px); line-height: 1.12; color: #fff; }
.pb-sub { font-family: var(--font); font-size: clamp(15px, 1.4vw, 18px); line-height: 1.6; color: rgba(255,255,255,.88);
  max-width: 52ch; margin: 20px auto 0; }
.pb-rule { width: 52px; height: 2px; background: #E8C9A0; margin: 26px auto 0; }

/* Lede with a drop cap */
.pb-intro { max-width: 760px; margin: 0 auto; padding: 74px 28px 60px; }
.pb-lede { font-size: clamp(19px, 2vw, 25px); line-height: 1.6; color: var(--navy-2); margin: 0; }
.pb-lede::first-letter { font-size: 3.1em; font-weight: 600; float: left; line-height: .82; padding: 6px 12px 0 0; color: var(--azure); }
.pb-intro p + p { font-size: 16.5px; line-height: 1.8; margin: 22px 0 0; }

/* Photo + copy pairs (the second is mirrored) */
.pb-pair { max-width: 1180px; margin: 0 auto; padding: 30px 28px 56px; display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 5vw; align-items: center; }
.pb-pair.pb-rev { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
.pb-pair.pb-rev figure { order: 2; }
.pb-pair figure { margin: 0; position: relative; }
.pb-pair figure img { border-radius: 6px; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; filter: saturate(.92); }
.pb-pair figure::after { content: ""; position: absolute; inset: 0 0 auto 0; aspect-ratio: 4 / 3; border-radius: 6px;
  background: linear-gradient(180deg, rgba(6,36,63,.06), rgba(6,36,63,.16)); pointer-events: none; }
.pb-pair figcaption { font-family: var(--prose); font-size: 13.5px; line-height: 1.5; color: #6F614B; margin-top: 12px; letter-spacing: .02em; }
.pb-pair h2 { font-size: clamp(24px, 2.6vw, 34px); line-height: 1.25; color: var(--navy-2); margin: 0 0 14px; }
.pb-pair p { font-size: 16px; line-height: 1.8; margin: 0 0 14px; }
.pb-pair p b { color: var(--navy-2); font-weight: 600; }
.pb-pair p a { color: var(--navy-2); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.pb-pair p a:hover { color: var(--azure); }

/* Pull-quote band: the storefront's navy gradient (measured against #013a73) with an
   oversized ghost quote mark; --sky-bright for the attribution (AA on dark). */
.pb-quote { background: linear-gradient(135deg, #013a73, var(--navy-2)); color: #fff; text-align: center;
  padding: 80px 28px; position: relative; overflow: hidden; }
.pb-quote::before { content: "\201C"; position: absolute; top: -40px; left: 50%; transform: translateX(-50%);
  font-family: var(--prose); font-size: 280px; line-height: 1; color: rgba(127,180,221,.16); pointer-events: none; }
.pb-quote blockquote { font-family: var(--prose); font-weight: 500; font-size: clamp(24px, 3vw, 40px); line-height: 1.4;
  max-width: 26ch; margin: 0 auto; position: relative; text-wrap: balance; }
.pb-quote cite { display: block; font-style: normal; font-family: var(--prose); font-size: 15px; letter-spacing: .02em;
  color: var(--sky-bright); margin-top: 26px; position: relative; }

/* Brand row: the shared mountBrandStrip() logos (linking to /shop as everywhere else),
   centred under a serif caption. */
.pb-brands { padding: 58px 28px 64px; max-width: 1180px; margin: 0 auto; text-align: center; }
.pb-capt { font-size: 14.5px; color: #6F614B; margin: 0 0 28px; }
.pb-brandrow { justify-content: center; gap: 26px 46px; margin: 0; }
.pb-brandrow .blogo { opacity: .85; }

/* Closing: warmer cream band under a brass hairline; serif headline, prose with the
   tel: links inline, then the two CTAs and the hours line. */
.pb-close { border-top: 1px solid rgba(176,138,80,.25); background: #F6F0E6; text-align: center; padding: 74px 28px 70px; scroll-margin-top: 96px; }
.pb-close h2 { font-size: clamp(26px, 3.2vw, 42px); line-height: 1.3; color: var(--navy-2); margin: 0 auto 14px; max-width: 22ch; }
.pb-close p { font-size: 16px; line-height: 1.7; color: #6A5F4E; max-width: 56ch; margin: 0 auto; }
.pb-close p a { color: var(--navy-2); font-weight: 600; }
.pb-close p a:hover { color: var(--azure); }
.pb-btns { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin-top: 30px; }
.pb-wa { background: var(--whatsapp); color: #fff; }
.pb-wa:hover { background: #0b6533; color: #fff; }
.parts-b .parts-hours { font-family: var(--font); font-size: 13.5px; color: #6F614B; margin-top: 22px; line-height: 1.8; }

@media (max-width: 900px) {
  .pb-pair, .pb-pair.pb-rev { grid-template-columns: 1fr; gap: 26px; }
  .pb-pair.pb-rev figure { order: 0; }
  .pb-pair figure { max-width: 640px; }
}
@media (max-width: 640px) {
  .pb-hero-bg { aspect-ratio: 4 / 3; }
  .pb-hero-c { padding: 42px 20px 42px; }
  .pb-intro { padding: 56px 20px 44px; }
  .pb-pair { padding: 20px 20px 44px; }
  .pb-quote { padding: 64px 20px; }
  .pb-brands { padding: 44px 20px 52px; }
  .pb-close { padding: 60px 20px 56px; }
  .pb-btns { flex-direction: column; align-items: stretch; }
}

/* ---- /about - Direction C "The showroom is the proof" ---------------------
   The About page leads with the place: a full-bleed street photo of the
   building carrying the facts card (address, hours, phones) in the first
   viewport, the drawn wayfinding strip (Movie Town -> 3 minutes east -> ACH), then the import-vs-ACH ledger, the
   authorized roster, the range, the owner's line (SSR via the seo-owner marker
   -> .ab-quote) and the closing. Structured facts, not photography, carry the
   page. All scoped under .about-c; Deep Harbor tokens only, no page-scoped
   palette break. */
.about-c { background: var(--paper); }
.ab-wrap { max-width: 1160px; margin: 0 auto; padding: 0 28px; }

/* Place-led hero: the building photo full bleed. Starts below the fixed nav
   (nav-clearance convention: margin-top, so the translucent nav frosts over
   paper, never over the photo). The photo is mostly sky with the frontage along
   the bottom, so the copy and the facts card sit in the sky over a scrim that
   fades clear above the roofline, and nothing covers the building. The crop is
   anchored to the bottom, and the hero is never shorter than the photo's own
   aspect (830/1448), so the roofline stays at ~55% of the hero's height and
   short laptops (1280x720) keep the card clear of it. */
.ab-hero { position: relative; margin-top: 72px; overflow: hidden; display: grid; align-items: start;
  min-height: max(680px, calc(100vh - 72px), calc(100vw * 830 / 1448)); }
.ab-hero picture { position: absolute; inset: 0; }
.ab-hero picture img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 100%; }
.ab-scrim { position: absolute; inset: 0; background:
  radial-gradient(ellipse 55% 48% at 22% 30%, rgba(6,36,63,.5) 0%, rgba(6,36,63,.22) 60%, rgba(6,36,63,0) 100%),
  linear-gradient(180deg, rgba(6,36,63,.62) 0%, rgba(6,36,63,.38) 34%, rgba(6,36,63,0) 56%); }
.ab-hero-c { position: relative; z-index: 1; max-width: 1240px; margin: 0 auto; width: 100%;
  padding: 40px; display: grid; grid-template-columns: minmax(0, 1fr) 476px; gap: 40px; align-items: start; }
.ab-eyebrow { font-weight: 600; font-size: 13.5px; letter-spacing: .14em; text-transform: uppercase;
  color: #fff; text-shadow: 0 1px 10px rgba(6,36,63,.6); margin: 0 0 18px; }
.ab-hero h1 { color: #fff; font-size: clamp(34px, 4vw, 52px); line-height: 1.06; letter-spacing: -0.02em;
  max-width: 17ch; text-wrap: balance; text-shadow: 0 2px 40px rgba(6,36,63,.45); }
.ab-lead { font-family: var(--prose); color: rgba(255,255,255,.9); font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.6; max-width: 46ch; margin: 14px 0 0; text-shadow: 0 1px 14px rgba(6,36,63,.7); }
.ab-card { background: var(--card); border-radius: 12px; box-shadow: 0 18px 50px -18px rgba(0,48,96,.5);
  padding: 22px 26px; }
.ab-card h2 { color: var(--navy-2); font-size: 18px; letter-spacing: -0.01em; margin: 0 0 12px; }
/* Two by two, so the card stays short enough to sit in the sky. */
.ab-card dl { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 12px 22px; }
.ab-card dt { font-weight: 600; font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--azure); }
.ab-card dd { margin: 3px 0 0; font-family: var(--prose); color: var(--ink); font-size: 15px; line-height: 1.5; }
.ab-card dd a { color: var(--navy); font-weight: 600; white-space: nowrap; }
.ab-card dd a:hover { color: var(--azure); }
/* The icon-only WhatsApp link is a control on WHITE here, so it takes the dark
   --whatsapp green (clears 1.4.11's 3:1), not the --whatsapp-bright brand glyph
   green the dark navy contexts use. */
.ab-card .wa-inline { color: var(--whatsapp); }
.ab-card .wa-inline:hover { color: var(--navy); }
.ab-card .btn { margin-top: 14px; width: 100%; }
/* Tablets and phones: the photo flows with the copy over its sky and the card
   follows on paper, overlapping only the road. The photo's height is the
   crop's below-the-roofline band (370 source px of 1448 here, 340 of 440 on
   phones) at this width plus a fixed sky, so the copy clears the building at
   every width and the scrim, in px, is clear by the roofline (>=270px down on
   tablets, 300px on phones). */
@media (max-width: 1100px) {
  .ab-hero { min-height: 0; background: var(--paper); }
  .ab-hero picture, .ab-scrim { position: relative; grid-area: 1 / 1; align-self: stretch; }
  .ab-hero picture img { height: calc(100vw * 370 / 1448 + 330px); }
  .ab-scrim { background:
    radial-gradient(ellipse 75% 230px at 25% 140px, rgba(6,36,63,.4) 0%, rgba(6,36,63,0) 100%),
    linear-gradient(180deg, rgba(6,36,63,.72) 0, rgba(6,36,63,.55) 200px, rgba(6,36,63,0) 270px); }
  .ab-hero-c { display: contents; }
  .ab-hero-c > div { grid-area: 1 / 1; position: relative; z-index: 1; padding: 26px 22px 0; }
  .ab-card { grid-row: 2; position: relative; z-index: 1; margin: -36px 16px 32px; }
}
@media (max-width: 640px) {
  /* The phone crop (ach-building-phone-440, centred on the ACH roundel). */
  .ab-hero picture img { height: calc(100vw * 340 / 440 + 300px); }
  .ab-scrim { background: linear-gradient(180deg, rgba(6,36,63,.8) 0, rgba(6,36,63,.62) 230px, rgba(6,36,63,0) 300px); }
  .ab-hero h1 { font-size: clamp(28px, 8.7vw, 34px); }
  .ab-card dl { grid-template-columns: 1fr; }
}

/* Wayfinding strip: a drawn route, not a photo - honest and unmistakably local. */
.ab-way { background: var(--navy-2); color: #fff; padding: 40px clamp(22px, 4vw, 40px);
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 16px 22px; }
.ab-stop { display: flex; align-items: center; gap: 12px; font-weight: 600; font-size: 15px; }
.ab-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--sky-bright); flex: 0 0 auto; }
.ab-dot.here { width: 16px; height: 16px; background: var(--signal); box-shadow: 0 0 0 5px rgba(74,222,128,.22); }
.ab-leg { display: flex; align-items: center; gap: 10px; color: rgba(255,255,255,.66);
  font-family: var(--prose); font-size: 14px; font-style: italic; }
.ab-leg::before, .ab-leg::after { content: ""; width: clamp(20px, 5vw, 70px); border-top: 2px dashed rgba(255,255,255,.35); }

/* The argument, now on paper: ONE composed ledger field, the ACH side wider,
   navy and check-marked so it visibly outweighs the dimmer import side. */
.ab-arg { padding: 92px 0; }
.ab-arg h2 { color: var(--navy-2); font-size: clamp(26px, 3vw, 40px); line-height: 1.12; letter-spacing: -0.015em;
  text-align: center; margin: 0 auto; max-width: 20ch; text-wrap: balance; }
.ab-sub { font-family: var(--prose); color: var(--muted); text-align: center; font-size: 17px;
  line-height: 1.6; max-width: 56ch; margin: 16px auto 0; }
.ab-ledger { display: grid; grid-template-columns: 1fr 1.25fr; margin-top: 52px; border-radius: 16px;
  overflow: hidden; box-shadow: var(--shadow); border: 1px solid var(--line); }
.ab-col { padding: clamp(26px, 3vw, 44px); }
.ab-col.imp { background: var(--paper-2); border-right: 1px solid var(--line); }
.ab-col.ach { background: var(--navy-2); }
.ab-col h3 { letter-spacing: -0.01em; margin: 0 0 4px; font-size: clamp(19px, 1.8vw, 24px); }
.ab-col.imp h3 { color: var(--muted); }
.ab-col.ach h3 { color: #fff; }
.ab-tag { font-weight: 600; font-size: 12.5px; letter-spacing: .1em; text-transform: uppercase; margin: 0 0 22px; }
.ab-col.imp .ab-tag { color: var(--azure); }
.ab-col.ach .ab-tag { color: var(--sky-bright); }
.ab-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 15px; }
.ab-list li { position: relative; padding-left: 34px; font-family: var(--prose); line-height: 1.5; }
.ab-col.imp .ab-list li { color: var(--muted); font-size: 15px; }
.ab-col.ach .ab-list li { color: #fff; font-size: 16.5px; }
.ab-list li::before { position: absolute; left: 0; top: 0; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; font-size: 12px; font-weight: 700; }
.ab-col.imp .ab-list li::before { content: "\2013"; background: rgba(0,48,96,.08); color: var(--muted); }
.ab-col.ach .ab-list li::before { content: "\2713"; background: var(--signal); color: #fff; }
@media (max-width: 760px) {
  .ab-ledger { grid-template-columns: 1fr; }
  .ab-col.imp { border-right: 0; border-bottom: 1px solid var(--line); }
}

/* Brand band: porcelain (the black wordmarks need a light surface); the roster
   paragraph names all 12 brands - the 7 logos above are the display subset. */
.ab-brands { background: var(--paper-2); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: 44px 0; text-align: center; }
.ab-brandcap { font-weight: 600; font-size: 14px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 26px; }
.ab-brandrow { justify-content: center; gap: 26px 46px; margin: 0; }
.ab-brandrow .blogo { opacity: .92; }
.ab-brandmore { font-family: var(--prose); color: var(--muted); font-size: 15px; line-height: 1.6;
  margin: 26px auto 0; max-width: 60ch; }

/* The range: copy + category chips beside the TV scene. */
.ab-range { padding: 92px 0; }
.ab-range-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 64px); align-items: center; }
.ab-kicker { font-weight: 600; font-size: 13px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--azure); margin: 0 0 14px; }
.ab-range h2 { color: var(--navy-2); font-size: clamp(26px, 3vw, 38px); line-height: 1.14; letter-spacing: -0.015em; text-wrap: balance; }
.ab-p { font-family: var(--prose); color: var(--ink); font-size: 17px; line-height: 1.78; margin: 16px 0 0; }
.ab-range figure { margin: 0; }
.ab-range figure img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-radius: 8px; box-shadow: var(--shadow); }
@media (max-width: 760px) { .ab-range-grid { grid-template-columns: 1fr; } }

/* Owner pull-quote band (rendered by seo.js ownerMessageHtml via seo-owner). */
.ab-quote { background: linear-gradient(135deg, #013a73, var(--navy-2)); color: #fff; text-align: center; padding: 80px 28px; }
.ab-quote blockquote { margin: 0 auto; font-family: var(--prose); font-weight: 500; font-style: italic;
  font-size: clamp(24px, 3.2vw, 40px); line-height: 1.3; letter-spacing: -0.01em; max-width: 20ch; text-wrap: balance; }
.ab-quote-rule { width: 54px; height: 2px; background: var(--sky-bright); margin: 28px auto 0; }
.ab-quote cite { display: block; font-style: normal; font-weight: 600; font-size: 14px; letter-spacing: .06em;
  color: var(--sky-bright); margin-top: 20px; }

/* FAQ (SSR via seo-faq) in a readable measure; then the closing line. */
.ab-faq { max-width: 860px; margin: 0 auto; padding: 40px 28px 0; }
.ab-closing { text-align: center; font-family: var(--display); font-style: italic; font-weight: 500;
  font-size: clamp(22px, 3vw, 32px); color: var(--navy-2); line-height: 1.3; max-width: 26ch;
  margin: 0 auto; padding: 84px 24px; text-wrap: balance; }

@media (max-width: 640px) {
  .ab-hero { margin-top: var(--phone-header-h); }   /* phones: the solid app header's height */
  .ab-arg { padding: 64px 0; }
  .ab-range { padding: 64px 0; }
  .ab-wrap { padding: 0 22px; }
  .ab-closing { padding: 64px 22px; }
}

/* ---- Payment link page (/pay/:token) ------------------------------------ */
/* Deep Harbor throughout. MOTION SPEC (mirrors the PR's motion section):
   every entrance/selection/crossfade below runs on transform+opacity only,
   through CSS transitions (never keyframes on retriggerable elements), with
   --pay-ease (a strong ease-out) and no duration over 300ms. Hover motion is
   gated on (hover:hover)+(pointer:fine); prefers-reduced-motion keeps the
   opacity changes and drops all movement. The only keyframes are the skeleton
   shimmer (constant, linear, removed under reduced motion). */
.pay-page { --pay-ease: cubic-bezier(0.23, 1, 0.32, 1); }
.pay-main { padding: 96px 0 72px; min-height: 62svh; }
@media (max-width: 640px) { .pay-main { padding-top: 84px; } }
body.pay-has-bar .pay-main { padding-bottom: 140px; }

/* Staggered entry reveal: elements start faded + 10px low; .is-in transitions
   them home. JS assigns each a 60ms-per-item transition-delay for the entrance
   and clears it afterwards, so selection/hover states are never lagged. */
.pay-anim { opacity: 0; transform: translateY(10px); transition: opacity 260ms var(--pay-ease), transform 260ms var(--pay-ease); }
.pay-anim.is-in { opacity: 1; transform: none; }

/* Skeleton -> content handoff (opacity only, 180ms out). */
.pay-skel { transition: opacity 180ms var(--pay-ease); }
.pay-skel.is-out { opacity: 0; }
.pay-skel-bar, .pay-skel-block {
  border-radius: 10px; margin-bottom: 14px;
  background: linear-gradient(100deg, var(--paper-2) 40%, #F3F7FC 50%, var(--paper-2) 60%);
  background-size: 200% 100%;
  animation: pay-shimmer 1.4s linear infinite;
}
.pay-skel-bar { height: 16px; }
.pay-skel-bar.pay-skel-title { height: 38px; margin: 18px 0; }
.pay-skel-cols { display: grid; grid-template-columns: minmax(0,1fr) 400px; gap: 28px; margin-top: 34px; }
@media (max-width: 900px) { .pay-skel-cols { grid-template-columns: 1fr; } }
@keyframes pay-shimmer { to { background-position: -200% 0; } }

/* Header */
.pay-eyebrow {
  display: inline-flex; align-items: center; gap: 7px; margin: 0 0 10px;
  font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--azure);
}
.pay-head h1 { font-size: clamp(30px, 5vw, 44px); color: var(--navy-2); margin: 0 0 10px; }
.pay-sub { margin: 0; color: var(--muted); font-size: 15.5px; }
.pay-sub b { color: var(--ink); }
.pay-dot { margin: 0 4px; }
.pay-note {
  margin: 14px 0 0; padding: 12px 16px; border-radius: 10px; font-size: 14px;
  background: rgba(42,120,190,.08); border: 1px solid rgba(42,120,190,.3); color: var(--navy);
}

/* Layout: chooser left, order summary rail right; single column on mobile with
   the summary first (verify, then choose). */
.pay-grid { display: grid; grid-template-columns: minmax(0,1fr) 400px; gap: 40px; align-items: start; margin-top: 30px; }
/* The chooser is a <section>: undo the global `section { padding: 84px 0 }` so
   it tops out level with the summary rail. */
.pay-choose { padding: 0; }
.pay-h2 { font-size: 19px; color: var(--navy-2); margin: 0 0 16px; }
@media (max-width: 900px) {
  .pay-grid { grid-template-columns: 1fr; gap: 28px; }
  .pay-aside { order: -1; }
}

/* Order summary rail */
.pay-aside {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 24px; box-shadow: var(--shadow-sm); position: sticky; top: 96px;
}
@media (max-width: 900px) { .pay-aside { position: static; } }
.pay-items { list-style: none; margin: 0; padding: 0; }
.pay-item { display: flex; justify-content: space-between; gap: 16px; padding: 11px 0; border-bottom: 1px solid var(--line); font-size: 14.5px; }
.pay-item-name { display: grid; gap: 2px; min-width: 0; }
.pay-item-name small { color: var(--muted); font-size: 12.5px; }
.pay-item-total { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--navy); font-weight: 600; }
.pay-sum-total {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: 14px 0 0; margin-top: 4px; font-family: var(--display);
}
.pay-sum-total span { font-size: 13.5px; color: var(--muted); }
.pay-sum-total b { font-size: 22px; color: var(--navy); font-variant-numeric: tabular-nums; }
.pay-fulfil { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); display: grid; gap: 3px; font-size: 14px; }
.pay-fulfil b { color: var(--navy-2); font-family: var(--display); font-size: 13px; letter-spacing: .04em; text-transform: uppercase; }
.pay-fulfil span { color: var(--ink); }
.pay-fulfil small { color: var(--muted); font-size: 12.5px; }

/* Method cards. Selection feedback is transform+opacity only: the press
   scales the card to .97 (160ms), release settles back on the same curve, the
   check chip fades/scales in (200ms), the ring is a border+shadow color
   change. transform-origin stays at the card's centre. */
.pay-methods { display: grid; gap: 14px; }
.pay-method {
  display: flex; align-items: center; gap: 16px; text-align: left; width: 100%;
  background: var(--card); border: 1.5px solid var(--line-2); border-radius: var(--radius);
  padding: 18px 20px; min-height: 76px; cursor: pointer; transform-origin: center;
  transition: transform 200ms var(--pay-ease), border-color 200ms var(--pay-ease), box-shadow 200ms var(--pay-ease);
}
.pay-method:active { transform: scale(0.97); }
.pay-method:focus-visible { outline: 3px solid rgba(42,120,190,.4); outline-offset: 2px; }
.pay-method.is-selected {
  border-color: var(--signal);
  box-shadow: 0 0 0 1px var(--signal), 0 14px 30px -18px rgba(6,36,63,.4);
}
@media (hover: hover) and (pointer: fine) {
  .pay-method:hover { transform: translateY(-2px); border-color: var(--sky); box-shadow: 0 14px 30px -18px rgba(6,36,63,.35); }
  .pay-method.is-selected:hover { border-color: var(--signal); box-shadow: 0 0 0 1px var(--signal), 0 14px 30px -18px rgba(6,36,63,.4); }
}
.pay-m-ico {
  flex: 0 0 auto; width: 52px; height: 52px; border-radius: 12px; display: grid; place-items: center;
  background: var(--paper-2); color: var(--navy);
  transition: background 200ms var(--pay-ease), color 200ms var(--pay-ease);
}
.pay-method.is-selected .pay-m-ico { background: var(--navy); color: #fff; }
.pay-m-body { display: grid; gap: 2px; min-width: 0; flex: 1 1 auto; }
.pay-m-body b { font-family: var(--display); font-size: 16.5px; color: var(--navy-2); }
.pay-m-body small { color: var(--muted); font-size: 13px; line-height: 1.45; }
.pay-m-check {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--signal); color: #fff;
  opacity: 0; transform: scale(0.6);
  transition: opacity 200ms var(--pay-ease), transform 200ms var(--pay-ease);
}
.pay-method.is-selected .pay-m-check { opacity: 1; transform: scale(1); }

.pay-secure { display: flex; align-items: center; gap: 8px; margin: 18px 0 0; color: var(--muted); font-size: 13px; }
.pay-secure svg { flex: 0 0 auto; color: var(--azure); }

/* The honest "being switched on" / error panel: enters and leaves with the
   same ease-out on opacity + a 6px rise, 220ms. */
.pay-panel { opacity: 0; transform: translateY(6px); transition: opacity 220ms var(--pay-ease), transform 220ms var(--pay-ease); }
.pay-panel.is-in { opacity: 1; transform: none; }
.pay-panel-in {
  margin-top: 16px; padding: 20px 22px; border-radius: var(--radius);
  background: var(--paper-2); border: 1px solid var(--line-2);
}
.pay-panel-in b { font-family: var(--display); color: var(--navy-2); font-size: 15.5px; }
.pay-panel-in p { margin: 8px 0 14px; color: var(--muted); font-size: 14px; line-height: 1.55; }

/* Sticky pay bar: frosted paper pinned to the viewport bottom; slides up 12px
   + fades on entry (260ms). Both text slots crossfade between two stacked
   spans (180ms, opacity only) whenever the method changes. */
.pay-ctabar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  padding: 0 env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
  background: rgba(246,248,251,.88); backdrop-filter: blur(14px) saturate(140%); -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-top: 1px solid var(--line-2); box-shadow: 0 -14px 40px -26px rgba(6,36,63,.4);
  opacity: 0; transform: translateY(12px);
  transition: opacity 260ms var(--pay-ease), transform 260ms var(--pay-ease);
}
.pay-ctabar.is-in { opacity: 1; transform: none; }
.pay-ctabar-in { display: flex; align-items: center; gap: 20px; padding-top: 14px; padding-bottom: 14px; }
.pay-ctabar-total { display: grid; line-height: 1.25; }
.pay-ctabar-total small { font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.pay-ctabar-total b { font-family: var(--display); font-size: 19px; color: var(--navy); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pay-ctabar-method { color: var(--muted); font-size: 13.5px; }
.pay-ctabar-info { display: flex; align-items: center; gap: 18px; min-width: 0; flex: 1 1 auto; }
.pay-cta { flex: 0 0 auto; padding: 14px 30px; transition: transform 140ms var(--pay-ease), box-shadow .2s, background .2s, border-color .2s, color .2s; }
.pay-cta:active { transform: scale(0.97); }
.pay-swap { display: grid; overflow: hidden; }
.pay-swap > span { grid-area: 1 / 1; opacity: 0; transition: opacity 180ms var(--pay-ease); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pay-swap > span.is-on { opacity: 1; }
@media (max-width: 640px) {
  .pay-ctabar-method { display: none; }
  .pay-ctabar-in { gap: 14px; }
  .pay-cta { flex: 1 1 auto; padding: 14px 18px; }
}

/* Non-payable states: one centered card, revealed with the same stagger. */
.pay-state-card {
  max-width: 560px; margin: 24px auto 0; text-align: center;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 44px 34px;
}
.pay-state-ico {
  width: 76px; height: 76px; border-radius: 50%; display: grid; place-items: center; margin: 0 auto 22px;
  background: var(--paper-2); color: var(--navy);
}
.pay-state-ico svg { width: 30px; height: 30px; }
.pay-state-card.is-good .pay-state-ico { background: linear-gradient(135deg, var(--azure), var(--navy)); color: #fff; }
.pay-state-card h1 { font-size: clamp(24px, 4.6vw, 32px); color: var(--navy-2); margin: 0 0 12px; text-wrap: balance; }
.pay-state-body { color: var(--muted); font-size: 15.5px; line-height: 1.6; margin: 0 0 8px; }
.pay-state-body b { color: var(--ink); }
.pay-state-ref { color: var(--muted); font-size: 13.5px; margin: 0 0 6px; }
.pay-state-ref b { color: var(--ink); }
.pay-state-home { margin: 20px 0 0; font-size: 14px; }
.pay-state-home a { color: var(--azure); font-weight: 600; }
.pay-contact { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 20px; }
.pay-contact-btn { width: auto; padding: 12px 22px; min-height: 48px; font-size: 14.5px; }
@media (max-width: 640px) {
  .pay-state-card { padding: 34px 20px; }
  .pay-contact { flex-direction: column; }
  .pay-contact-btn { width: 100%; }
}

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

/* Reduced motion: keep every opacity change, drop all movement (and the
   shimmer). Comprehension transitions stay; nothing translates or scales. */
@media (prefers-reduced-motion: reduce) {
  .pay-anim, .pay-panel, .pay-ctabar { transform: none; transition: opacity 200ms ease; }
  .pay-method, .pay-cta { transition: border-color 200ms ease, box-shadow 200ms ease, background 200ms ease, color 200ms ease; }
  .pay-method:active, .pay-cta:active { transform: none; }
  .pay-m-check { transform: none; transition: opacity 200ms ease; }
  .pay-skel-bar, .pay-skel-block { animation: none; }
}
.pay-panel-in .pay-contact { justify-content: flex-start; margin-top: 4px; }

/* ---- Homepage slides editor (/admin/slides) -------------------------------- */
/* A three-pane workspace that runs the full window width (2026-10-01): a section
   rail with the publish bar at its foot, the live preview, and the selected
   section's fields. The four panes are direct children of the .adm-slides-ws
   grid, so each breakpoint only re-places them:
     1101px and up   rail | preview | fields, one screen tall, panes scroll inside
     981 - 1100px    the rail becomes a strip of section chips above preview | fields
     980px and down  stacked: preview, chips, fields, publish bar stuck to the bottom
   The base rules below are the stacked layout; the wider ones add to it.
   body.adm-wide (shared with the Products page) runs the top bar full width. */
.adm-wrap.adm-slides { max-width: none; width: 100%; margin: 0; padding: 0; }
.adm-slides .adm-head { align-items: center; padding: 10px 18px; background: var(--card); border-bottom: 1px solid var(--line); }
.adm-slides .adm-head h1 { font-size: 21px; }
.adm-slides .adm-sub { max-width: 150ch; font-size: 13.5px; margin-top: 2px; }
.adm-slides-ws {
  display: grid; grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "canvas" "rail" "panel" "pub";
}

/* The canvas work surface. The dotted grid marks it as the preview canvas
   (cloned deliberately from the reference editor's canvas treatment); the faux
   browser chrome frames the real hero so it reads as "the site", not a form. */
.adm-slides-canvas {
  grid-area: canvas; min-width: 0; padding: 12px 14px 16px;
  background: radial-gradient(rgba(6,36,63,.13) 1px, transparent 1px) 0 0 / 16px 16px, #F0F4F9;
}
.adm-slides-pbar { display: flex; align-items: center; gap: 10px 12px; flex-wrap: wrap; padding: 2px 2px 12px; }
.adm-slides-size { font-size: 12px; color: var(--muted); white-space: nowrap; }
.adm-slides-note { flex-basis: 100%; font-size: 12px; color: var(--muted); }
.adm-seg { display: inline-flex; border: 1px solid var(--line); border-radius: 100px; overflow: hidden; background: var(--card); }
.adm-seg button { border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 13px; padding: 7px 14px; min-height: 44px; min-width: 44px; cursor: pointer; }
.adm-seg button + button { border-left: 1px solid var(--line); }
.adm-seg button.active { background: var(--navy); color: #fff; }
/* admin.js caps max-width at the scaled page's width; auto margins centre it. */
.adm-slides-browser { margin: 0 auto; background: var(--card); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow-sm); overflow: hidden; }
.adm-slides-chrome { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-bottom: 1px solid var(--line); }
.adm-slides-chromedots { display: flex; gap: 5px; flex: 0 0 auto; }
.adm-slides-chromedots i { width: 9px; height: 9px; border-radius: 50%; background: var(--paper-2); border: 1px solid var(--line); }
.adm-slides-url {
  flex: 1; min-width: 0; max-width: 520px; margin: 0 auto; padding: 4px 14px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 100px;
  font-size: 12px; color: var(--muted); text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.adm-slides-stage { position: relative; overflow: hidden; background: var(--paper-2); min-width: 0; }
.adm-slides-frame { display: block; border: 0; transform-origin: top left; background: #fff; }

/* The section rail. Narrow: a wrapping strip of chips (wrapping, not scrolling
   sideways, so every section stays in sight), where a chip shows its status
   pill only when the section needs attention. */
.adm-slides-rail {
  grid-area: rail; min-width: 0; display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px 18px; background: var(--card);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.adm-rail-item {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto; max-width: 100%; min-height: 44px;
  padding: 6px 14px 6px 9px; border: 1px solid var(--line); border-radius: 100px;
  background: var(--card); font: inherit; text-align: left; cursor: pointer;
}
.adm-rail-item:hover { border-color: var(--line-2); }
.adm-rail-item.active { background: var(--paper-2); border-color: var(--navy); }
.adm-rail-item:focus-visible { outline: 2px solid var(--azure); outline-offset: -2px; }
.adm-rail-num {
  position: relative; width: 22px; height: 22px; flex: 0 0 auto; border-radius: 50%;
  background: var(--paper-2); color: var(--navy);
  font-size: 11.5px; font-weight: 700; display: grid; place-items: center;
}
.adm-rail-item.active .adm-rail-num { background: var(--card); }
.adm-rail-num--cmp, .adm-rail-item.active .adm-rail-num--cmp { background: #E4F1E8; color: #1F6B3A; }
.adm-rail-item[data-key="import"] .adm-rail-num--cmp { background: #F8E3E1; color: var(--crimson); }
/* A dot on the section's mark while it differs from the live homepage (blue) or
   holds an edit the server does not have (red) - the same two colours as its pill. */
.adm-rail-item[data-state="changed"] .adm-rail-num::after,
.adm-rail-item[data-state="saving"] .adm-rail-num::after,
.adm-rail-item[data-state="unsaved"] .adm-rail-num::after {
  content: ""; position: absolute; top: -3px; right: -3px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--signal); border: 2px solid var(--card);
}
.adm-rail-item[data-state="unsaved"] .adm-rail-num::after { background: var(--crimson); }
.adm-rail-name { min-width: 0; font-size: 14px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-rail-item .adm-sl-pill { flex: 0 0 auto; }
.adm-rail-item .adm-status--idle, .adm-rail-item .adm-status--done, .adm-rail-group { display: none; }

/* The fields of the selected section. */
.adm-slides-panel { grid-area: panel; min-width: 0; padding: 16px 18px 20px; background: var(--card); }
/* .adm-sl-pane is a <section>: zero out the storefront's global section padding. */
.adm-sl-pane { display: flex; flex-direction: column; gap: 14px; padding: 0; }
/* The authored display would beat the UA's [hidden] rule - restate it. */
.adm-sl-pane[hidden] { display: none; }
.adm-sl-panehead { padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.adm-sl-panehead h2 { font-size: 17px; font-weight: 700; color: var(--ink); }
.adm-sl-state { margin: 4px 0 0; font-size: 12.5px; color: var(--muted); }
/* azure, not --signal: signal is fill-only (test:contrast guards this). */
.adm-sl-state[data-state="changed"], .adm-sl-state[data-state="saving"] { color: var(--azure); font-weight: 600; }
.adm-sl-state[data-state="unsaved"] { color: var(--crimson); font-weight: 600; }
.adm-sl-actions { display: flex; align-items: center; justify-content: space-between; gap: 4px 12px; flex-wrap: wrap; }
.adm-sl-actions .adm-textbtn { font-size: 13px; padding: 0 2px; }

.adm-sl-fhead { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.adm-sl-count { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.adm-sl-count.over { color: var(--crimson); font-weight: 700; }
/* The ghost line under a CHANGED field: what the live homepage shows right now. */
.adm-sl-live { margin-top: 6px; font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.adm-sl-live b { font-weight: 600; }
/* The clearance slide's note: its starburst figure is worked out, not typed. */
/* "Show on phones": a tick box drawn as a switch (still a native checkbox, role=switch).
   The off track is --muted so the control keeps 3:1 against the panel either way. */
.adm-switch input { -webkit-appearance: none; appearance: none; position: relative; width: 40px; height: 24px; margin: 0; border-radius: 12px; background: var(--muted); cursor: pointer; transition: background .15s; }
.adm-switch input::after { content: ''; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: transform .15s; }
.adm-switch input:checked { background: var(--navy); }
.adm-switch input:checked::after { transform: translateX(16px); }
.adm-switch input:focus-visible { outline: 2px solid var(--azure); outline-offset: 2px; }
.adm-sl-phone { padding-top: 4px; border-top: 1px solid var(--line); }
.adm-sl-phone .adm-check { font-weight: 600; color: var(--navy-2); }
.adm-sl-phone .adm-help { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .adm-switch input, .adm-switch input::after { transition: none; } }
.adm-sl-auto { margin: 0; padding: 10px 12px; font-size: 12.5px; line-height: 1.5; color: var(--navy); background: rgba(0,48,96,.06); border-radius: 8px; }
.adm-cmp-help { margin: 0; font-size: 12.5px; color: var(--muted); }
.adm-cmp-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.adm-cmp-row { display: flex; flex-direction: column; gap: 4px; }
.adm-cmp-input {
  width: 100%; background: var(--card); border: 1px solid var(--line); color: var(--ink); font: inherit; font-size: 14px;
  padding: 8px 10px; border-radius: 8px; outline: none; resize: vertical; min-height: 0;
}
.adm-cmp-input:focus { border-color: var(--azure); box-shadow: 0 0 0 3px rgba(30,111,176,.15); }
.adm-cmp-input.bad { border-color: var(--crimson); }
.adm-cmp-input.bad:focus { box-shadow: 0 0 0 3px rgba(158,43,37,.15); }
.adm-cmp-tools { display: flex; align-items: center; justify-content: flex-end; gap: 2px; }
.adm-cmp-tools .adm-sl-count { margin-right: auto; }
.adm-cmp-add { align-self: flex-start; }
.adm-cmp-live ul { margin: 4px 0; padding-left: 18px; }

/* The publish bar. Stacked, it sticks to the bottom of the window (exactly where
   it is wanted on a phone); wider, it is pinned in its pane. While anything is
   unpublished it carries a blue edge and tint, so the state reads at a glance. */
.adm-slides-publishbar {
  grid-area: pub; position: sticky; bottom: 0; z-index: 5; min-width: 0;
  display: flex; flex-direction: column; align-items: stretch; gap: 6px;
  padding: 12px 16px; background: var(--paper); border-top: 1px solid var(--line-2);
}
.adm-slides-publishbar[data-dirty="dirty"] { background: #EAF2FA; box-shadow: inset 0 3px 0 var(--signal); }
.adm-slides-actions { display: flex; align-items: center; gap: 10px; margin-top: 3px; }
.adm-slides-actions .btn { flex: 1 1 0; justify-content: center; min-width: 0; padding-left: 10px; padding-right: 10px; }
.adm-slides-dirty, .adm-slides-save { margin: 0; font-size: 13px; color: var(--muted); }
.adm-slides-dirty[data-dirty="dirty"] { color: var(--navy); font-weight: 700; }
.adm-slides-dirty[data-dirty="dirty"]::before {
  content: ""; display: inline-block; width: 9px; height: 9px; margin-right: 7px;
  border-radius: 50%; background: var(--signal);
}
.adm-slides-save { font-size: 12.5px; }
.adm-slides-save[data-save="bad"] { color: var(--crimson); font-weight: 700; }

/* The preview-iframe field ring: only public/js/slides-preview.js (loaded solely
   into /admin/slides/preview) ever adds .slides-hl, so the public homepage never
   renders it. The label tag carries the field name from the editor. */
.slides-hl { position: relative; outline: 2px solid var(--signal); outline-offset: 5px; box-shadow: 0 0 0 9px rgba(42,120,190,.22); border-radius: 4px; }
.slides-hl::before {
  content: attr(data-hl); position: absolute; top: -34px; left: -7px; z-index: 5;
  background: var(--signal); color: #fff; font: 700 12px/1 var(--font);
  letter-spacing: .04em; text-transform: none; padding: 5px 9px;
  border-radius: 6px 6px 6px 0; white-space: nowrap;
}

@media (min-width: 981px) {
  /* The workspace fills the window under the top bar and page header: no page
     scroll, each pane scrolls inside itself, and Publish never leaves the screen.
     admin.js sizePreview() uses this same 981px breakpoint. The min-height keeps
     a very short window usable (the page scrolls instead of crushing the panes). */
  body.adm-wide:has(.adm-slides) { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 600px; }
  .adm-wrap.adm-slides { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .adm-slides .adm-head { flex: 0 0 auto; flex-wrap: nowrap; padding: 10px 20px; }
  .adm-slides-ws {
    flex: 1 1 auto; min-height: 0;
    grid-template-columns: minmax(0, 1fr) 380px;
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas: "rail rail" "canvas panel" "canvas pub";
  }
  .adm-slides-rail { border-top: 0; padding: 10px 20px; }
  .adm-slides-canvas { min-height: 0; overflow: hidden; padding: 12px 20px 18px; }
  .adm-slides-note { flex-basis: auto; margin-left: auto; }
  .adm-slides-panel { min-height: 0; overflow-y: auto; padding: 18px 20px 22px; border-left: 1px solid var(--line); }
  .adm-slides-publishbar { position: static; border-left: 1px solid var(--line); }
}

@media (min-width: 1101px) {
  .adm-slides-ws {
    grid-template-columns: 316px minmax(0, 1fr) clamp(340px, 24vw, 440px);
    grid-template-rows: minmax(0, 1fr) auto;
    grid-template-areas: "rail canvas panel" "pub canvas panel";
  }
  /* The rail turns into a column of rows; every row shows its status pill. */
  .adm-slides-rail {
    flex-direction: column; flex-wrap: nowrap; gap: 0; overflow: hidden auto; padding: 0;
    border-bottom: 0; border-right: 1px solid var(--line);
  }
  .adm-rail-item {
    gap: 10px; min-height: 46px; padding: 8px 14px 8px 14px;
    border: 0; border-left: 3px solid transparent; border-bottom: 1px solid var(--line); border-radius: 0;
  }
  .adm-rail-item.active { border-left-color: var(--navy); }
  .adm-rail-name { flex: 1 1 auto; min-width: 0; white-space: normal; }
  .adm-rail-item .adm-status--idle, .adm-rail-item .adm-status--done { display: inline-flex; }
  .adm-rail-group {
    display: block; margin: 0; padding: 14px 17px 6px;
    font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
  }
  .adm-slides-publishbar { padding: 12px 14px; border-left: 0; border-right: 1px solid var(--line); }
  .adm-slides-dirty, .adm-slides-save { font-size: 12.5px; }
  /* Side by side in the narrow rail (Discard at its own width, Publish taking
     the rest), so the bar stays short and the section list keeps its room on a
     768px-tall laptop. */
  .adm-slides-actions { gap: 8px; }
  .adm-slides-actions .btn-ghost { flex: 0 0 auto; }
}
