/* LUMEN C — THE CRAFT LAYER · "The Formulary"
 * Kosas density / Nécessaire index lineage. Clinical, dense, asymmetric. The
 * page carries a PERSISTENT LEFT MARGIN of folios (owned by lumen.css: .c-page,
 * .c-margin, .c-folio). This file owns the chrome, the imagery modules and the
 * motion tokens — never the register itself.
 *
 * OWNERSHIP CONTRACT (trap 9 — "one owner per selector"). Every section
 * re-emits lumen.css, so the <link> order between lumen.css and THIS sheet is
 * non-deterministic. Therefore:
 *   - lumen.css OWNS the tokens and every selector it declares (.c-check,
 *     .c-cfbar, .c-nameplate, .c-margin, .c-arow, .c-mrow, .c-manifest,
 *     .c-card__*, .c-btn, .c-folio, .c-h2/.c-h3, .c-row/.c-reg, .c-mrow2, …).
 *     This file NEVER redefines any of them.
 *   - Where craft chrome must touch a lumen.css component, it does so through a
 *     DISTINCT, higher-specificity selector (a compound / co-class), so the
 *     outcome is decided by specificity, not by which link won the race.
 *   - Motion tokens (--ease, --dur-*) and engine surfaces (spinner/skeleton)
 *     are unset by lumen.css, so this file owns them outright.
 *   - Bare .c-mrow2__name is NOT declared by lumen.css (only its `a` descendant
 *     is), so this file owns the bare container to host .c-reg__thumb.
 *
 * CONTRAST AUDIT (WCAG 2.2 AA, sRGB relative luminance; tokens live in
 * lumen.css and are not redefined, so these are the values that render):
 *   --c-muted  #5C5E58 on --c-ground #F5F4EF → 5.96:1  ✓ AA body text (≥4.5)
 *   --c-accent #0F5C4C on --c-ground #F5F4EF → 7.18:1  ✓ AA text (≥4.5)
 *   --c-line   #7C7A70 on --c-ground #F5F4EF → 3.91:1  ✓ AA UI border (≥3),
 *              bounds every INTERACTIVE control; exempt from text minima.
 *   --c-hair   #D7D6CF  → DECORATIVE hairline / row rule only (exempt 1.4.11).
 *   error red  #A3231F on --c-ground #F5F4EF → 6.63:1  ✓ AA text (≥4.5).
 * TEXT OVER MEDIA: by design NONE. Every module keeps copy on the --c-ground
 * (captions below tiles, nameplate/meta beside the plate, spec card on ground).
 * No copy is composited over a photograph, so no scrim is required and no
 * media-contrast floor has to be computed (trap 10 satisfied by avoidance).
 * The only rule that carries interactive borders is --c-line; the only rule
 * that is decorative is --c-hair — the two are never swapped (hard requirement).
 */

:root {
  /* C's curve — clinical, no overshoot (Kosas signature). Overrides the
     lumen-motion.css defaults; those tokens are unowned there. */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-card: 600ms;      /* card scale + SHADOW lift — the Kosas hover */
  --dur-reveal: 550ms;
  --dur-control: 150ms;

  /* Shared-engine surfaces (loading spinner / skeleton) — unset by lumen.css. */
  --spinner-color: var(--c-on-accent);
  --skeleton-base: #E7E5DE;
  --skeleton-sheen: #F3F1EC;

  /* Chrome geometry. Two stacked announcement bars, then the pinned head. */
  --c-bar-h: 2.125rem;
  --c-bars-h: calc(var(--c-bar-h) * 2);   /* both bars scroll out on pin */
  --c-head-h: 4.25rem;
  --c-head-h-condensed: 3.25rem;
  --c-shadow-lift: 0 0.75rem 1.75rem rgb(28 29 25 / 0.16);
}

/* ============================================================ header / chrome
 * A sticky element is confined to its CONTAINING BLOCK, and Shopify nests each
 * section in .shopify-section inside #header-group (trap 4). Sticking the inner
 * box gives it a travel range of its own height — none. #header-group is the
 * first ancestor tall enough to travel, so IT sticks, pulled up by the two
 * announcement bars so they scroll out while the head pins. */
#header-group { position: sticky; top: calc(-1 * var(--c-bars-h)); z-index: 50; }
/* The bars are optional. Without this guard, blanking them leaves the group
   pinned two-bars too high and the wordmark is clipped above the viewport
   forever (trap 4). */
#header-group:not(:has(.c-bars)) { top: 0; }
/* The engine still toggles .is-condensed on [data-lumen-header] for the shrink;
   we only neutralise that element's OWN stickiness so it can't double-pin
   inside the already-sticky group. */
#header-group [data-lumen-header] { position: static; }
.c-bar-wrap { position: static; background: var(--c-ground); }

/* Two stacked mono announcement bars. Ruled with the decorative hairline. */
.c-bars { display: block; }
.c-bar {
  min-height: var(--c-bar-h);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  padding: 0.25rem clamp(1rem, 3vw, 2rem);
  border-bottom: 1px solid var(--c-hair);
  background: var(--c-ground);
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-muted);
}
.c-bar--accent { background: var(--c-accent); color: var(--c-on-accent); border-bottom-color: var(--c-accent); }
.c-bar b { color: var(--c-ink); font-weight: 700; }
.c-bar--accent b { color: var(--c-on-accent); }
.c-bar span { white-space: nowrap; }

/* The pinned head. Dense, mono, ruled underneath with the strong line so the
   chrome reads as a register header rather than decoration. */
.c-head {
  background: var(--c-ground);
  border-bottom: 1px solid var(--c-line);
  color: var(--c-ink);
}
.c-head__inner {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2.5vw, 2rem);
  min-height: var(--c-head-h);
  max-width: 82rem;
  margin-inline: auto;
  padding-inline: clamp(1rem, 3vw, 2rem);
  /* NO transition on min-height. #header-group is sticky and therefore still in
     flow, so tweening its height reflows every section below it on every frame
     (trap 5, shipped in both A and B). The height STEPS once; the wordmark
     carries the motion on a composited transform. */
}
.c-head.is-condensed .c-head__inner { min-height: var(--c-head-h-condensed); }

.c-head__mark {
  font-family: var(--c-display);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--c-ink);
  text-decoration: none;
  transform-origin: left center;
  transition: transform var(--dur-card) var(--ease);
}
.c-head.is-condensed .c-head__mark { transform: scale(0.82); }

.c-head__nav {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  margin-left: auto;
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.c-head__nav a { color: var(--c-ink); text-decoration: none; padding-block: 0.5rem; }

.c-head__acts { display: flex; align-items: center; gap: 0.25rem; }
.c-head__acts .c-head__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  min-width: 44px;
  min-height: 44px;
  padding-inline: 0.5rem;
  background: none;
  border: 0;
  color: var(--c-ink);
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}
.c-head__count {
  font-variant-numeric: tabular-nums;
  min-width: 1.25rem;
  padding: 0 0.25rem;
  text-align: center;
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-size: 0.625rem;
  line-height: 1.25rem;
}
/* A cross-page live compare count needs JS/cart, so this is a LABELLED link, not
   a number. Bordered with the interactive line (a control boundary, ≥3:1). */
.c-head__compare {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 0.75rem;
  border: 1px solid var(--c-line);
  color: var(--c-accent);
  text-decoration: none;
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* Every interactive element in the chrome gets a focus-visible ring; lumen.css's
   .c-sec scope does not reach the header, so it is declared here (WCAG 2.4.7). */
.c-head__mark:focus-visible,
.c-head__nav a:focus-visible,
.c-head__btn:focus-visible,
.c-head__compare:focus-visible,
.c-bar a:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 2px;
}
@media (max-width: 52rem) {
  .c-head__nav { display: none; }
}

/* ================================================================= lab hero
 * Masthead nameplate on the ground BESIDE a flat-lab hero band. The plate is a
 * background <picture>, taken out of flow at the <picture> (trap 6) — NOT via
 * display:contents, which would promote <source> into a flex/grid item. No copy
 * is placed over the plate, so no scrim is needed (trap 10). */
.c-labhero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: end;
}
.c-labhero__nameplate {
  font-family: var(--c-display);
  font-weight: 700;
  font-size: clamp(2.5rem, 7vw, 5rem);
  line-height: 0.9;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--c-ink);
  margin: 0 0 1rem;
  /* Display type must never break mid-word; size the measure in rem, not ch
     (ch resolves against the box font-size, not the display line) (trap 17). */
  overflow-wrap: normal;
  word-break: keep-all;
  hyphens: none;
  max-width: 18rem;
}
.c-labhero__meta {
  font-family: var(--c-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  line-height: 1.7;
  color: var(--c-muted);
  margin: 0;
}
.c-labhero__meta b { color: var(--c-accent); font-weight: 400; }
/* 5:2 band desktop; the plate fills it, absolutely positioned. */
.c-labhero__band {
  position: relative;
  aspect-ratio: 5 / 2;
  overflow: hidden;
  border: 1px solid var(--c-hair);   /* decorative frame → hair */
  background: var(--c-surface);       /* solid fallback if the plate is absent */
}
.c-labhero__plate { position: absolute; inset: 0; }
.c-labhero__plate img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 60rem) {
  .c-labhero { grid-template-columns: 1fr; }
  .c-labhero__band { aspect-ratio: 2 / 3; order: 0; }  /* DOM order already puts
     the band last; no visual reorder of interactive content (WCAG 1.3.2). */
}

/* ============================================================== contact sheet
 * 6-column square grid on desktop; a snap-scroll rail on mobile. The element
 * carries [data-rail], which lumen-motion.css styles as display:flex
 * unconditionally. We beat that with a DESKTOP compound (.c-sheet__grid[data-rail],
 * 0,2,0 > 0,1,0) that flips it back to a grid and kills the scroller — so below
 * 60rem it falls through to motion.css's flex rail with drag + snap. */
.c-sheet__grid { gap: 1px; padding-block: 0.375rem 0.75rem; }
.c-sheet__grid > * { width: min(62vw, 15rem); }   /* rail-item width (mobile) */
@media (min-width: 60rem) {
  .c-sheet__grid[data-rail] {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    overflow: visible;                 /* not a scroller when it is a grid */
  }
  .c-sheet__grid[data-rail] > * { width: auto; }
}
.c-sheet__grid[data-rail]:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 4px; }

.c-sheet__tile {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;                    /* clips the scaling image (trap: Kosas) */
  background: var(--c-surface);
  color: inherit;
  text-decoration: none;
  /* box-shadow is a paint property, but the lift IS the Kosas signature and it
     runs only on a single element's hover/focus, never scroll-linked. Named
     transition, never `transition: all` (trap 17). */
  transition: box-shadow var(--dur-card) var(--ease);
}
.c-sheet__tile img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-card) var(--ease);   /* composite */
}
@media (hover: hover) and (pointer: fine) {
  .c-sheet__tile:hover { box-shadow: var(--c-shadow-lift); z-index: 1; }
  .c-sheet__tile:hover img { transform: scale(1.03); }
}
/* Keyboard parity — the focused tile gets the same lift the mouse gets. */
.c-sheet__tile:focus-within { box-shadow: var(--c-shadow-lift); z-index: 1; outline: 2px solid var(--c-accent); outline-offset: 2px; }
.c-sheet__tile:focus-within img { transform: scale(1.03); }
.c-sheet__cap {
  display: block;
  padding: 0.5rem 0 0;
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-muted);
}
.c-sheet__cap b { color: var(--c-accent); font-weight: 400; }

/* ================================================================= statement
 * One oversized grotesque line, left-aligned into the folio margin. */
.c-statement { padding-block: clamp(1rem, 3vw, 2rem); }
.c-statement__text {
  font-family: var(--c-display);
  font-weight: 700;
  font-size: clamp(1.75rem, 4.5vw, 3.5rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--c-ink);
  margin: 0;
  /* Measure in rem, NOT ch (ch would resolve against body font-size, not the
     display line) and never break inside a word (trap 17). */
  max-width: 34rem;
  overflow-wrap: normal;
  word-break: keep-all;
  hyphens: none;
  text-wrap: balance;
}
.c-statement__text b { color: var(--c-accent); font-weight: 700; }

/* ================================================================== tone row
 * On-skin swatch documentation. Three 1:1 tiles, mono labels. No hover
 * spectacle — this is data, not a card. */
.c-tonerow { padding-block: clamp(0.5rem, 2vw, 1.5rem); }
.c-tonerow__head {
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-muted);
  margin: 0 0 1rem;
  padding-bottom: 0.625rem;
  border-bottom: 1px solid var(--c-line);   /* a section rule → strong line */
}
.c-tonerow__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.75rem, 2vw, 1.5rem);
}
.c-tone { display: block; }
.c-tone img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border: 1px solid var(--c-hair);          /* decorative frame → hair */
  background: var(--c-surface);
}
.c-tone__label {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.5rem 0 0;
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-muted);
}
.c-tone__label b { color: var(--c-ink); font-weight: 400; }

/* =============================================================== mega-footer
 * Mono footer with an oversized MONO wordmark. Newsletter is a native
 * {% form 'customer' %} (NOT AJAX — an opaque redirect resolves a fetch even on
 * failure, so a native submit is the honest control). data-newsletter rides on
 * the WRAPPER div, not the form. */
.c-foot {
  background: var(--c-ground);
  border-top: 1px solid var(--c-line);
  padding-top: var(--c-pad);
  color: var(--c-ink);
}
.c-foot__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
  max-width: 82rem;
  margin-inline: auto;
  padding-inline: clamp(1rem, 3vw, 2rem);
}
.c-foot__grid h2 {
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-muted);
  margin: 0 0 1rem;
}
.c-foot__grid ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.625rem; }
.c-foot__grid a {
  color: var(--c-ink);
  text-decoration: none;
  font-family: var(--c-mono);
  font-size: 0.75rem;
}
.c-foot__grid a:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 3px; }
.c-foot__note {
  color: var(--c-muted);
  font-size: 0.8125rem;
  line-height: 1.6;
  max-width: 32ch;
  margin: 0 0 1.25rem;
}
@media (max-width: 60rem) { .c-foot__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 34rem) { .c-foot__grid { grid-template-columns: 1fr; } }

/* The one indulgence: the wordmark set in mono at the scale of a facade.
   overflow:hidden clips the descenders the tight line-height would spill. */
.c-foot__word {
  display: block;
  margin-top: var(--c-pad);
  padding-inline: clamp(1rem, 3vw, 2rem);
  font-family: var(--c-mono);
  font-weight: 700;
  font-size: clamp(3rem, 15vw, 12rem);
  line-height: 0.82;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--c-ink);
  overflow: hidden;
  padding-bottom: 0.06em;
}

.c-sign { display: flex; gap: 0; max-width: 24rem; margin-top: 1rem; }
.c-sign input {
  flex: 1;
  min-height: 48px;
  padding-inline: 0.875rem;
  border: 1px solid var(--c-line);          /* interactive → strong line (≥3:1) */
  border-right: 0;
  background: var(--c-surface);
  color: var(--c-ink);
  font-family: var(--c-mono);
  font-size: 0.75rem;
  border-radius: 0;
}
.c-sign input:focus-visible { outline: 2px solid var(--c-accent); outline-offset: -2px; }
.c-sign button {
  min-height: 48px;
  padding-inline: 1.25rem;
  border: 1px solid var(--c-accent);
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: 0;
}
.c-sign button:focus-visible { outline: 2px solid var(--c-ink); outline-offset: 2px; }
.c-sign__ok  { color: var(--c-accent); font-family: var(--c-mono); font-size: 0.6875rem; margin: 0.75rem 0 0; }
/* #A3231F on --c-ground → 6.63:1 ✓ AA text. */
.c-sign__err { color: #A3231F; font-family: var(--c-mono); font-size: 0.6875rem; margin: 0.75rem 0 0; }

/* ==================================================================== drawer
 * The cart drawer must live in sections/header-group.json — the engine
 * re-renders it via /?section_id=<id>, which only returns sections the requested
 * page renders. lumen-motion.css owns the overlay + slide; here we dress the
 * panel internals only, as an "order manifest": mono, ruled, a composition line.
 *
 * The panel itself does not scroll; the line list inside it does — else the
 * sticky head and the checkout foot scroll away with the items. We beat
 * motion.css's [data-lumen-drawer-panel]{overflow-y:auto} with a co-class
 * compound (0,2,0 > 0,1,0), so order can't decide it. */
[data-lumen-drawer-panel].c-drawer__panel {
  overflow: hidden;
  background: var(--c-ground);
  color: var(--c-ink);
}
.c-drawer__top { position: relative; padding: 1.25rem clamp(1.25rem, 5vw, 1.75rem); border-bottom: 1px solid var(--c-line); }
.c-drawer__title {
  font-family: var(--c-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-accent);
  margin: 0;
}
.c-drawer__x {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  min-width: 44px;
  min-height: 44px;
  background: none;
  border: 0;
  color: var(--c-ink);
  font-family: var(--c-mono);
  font-size: 0.875rem;
  cursor: pointer;
}
.c-drawer__x:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

/* Free-ship progress in $ remaining. motion.css owns .ship__track/.ship__fill
   geometry (scaleX via --ship-progress); we only colour them here. */
.c-dship { padding: 1rem clamp(1.25rem, 5vw, 1.75rem); font-family: var(--c-mono); font-size: 0.6875rem; color: var(--c-muted); }
.c-dship .ship__track { background: var(--c-hair); margin-top: 0.625rem; }
.c-dship .ship__fill { background: var(--c-accent); }
.c-dship b { color: var(--c-accent); font-variant-numeric: tabular-nums; }

.c-drawer__lines { list-style: none; margin: 0; padding: 0 clamp(1.25rem, 5vw, 1.75rem); flex: 1; overflow-y: auto; }
/* The composition line: index | thumb | name+INCI | price/qty, ruled with the
   decorative hair (a row separator, not a control boundary). */
.c-dline {
  display: grid;
  grid-template-columns: 3.5rem 1fr auto;
  gap: 1rem;
  align-items: start;
  padding-block: 1.25rem;
  border-bottom: 1px solid var(--c-hair);
}
.c-dline img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; border: 1px solid var(--c-hair); background: var(--c-surface); }
.c-dline__name { font-family: var(--c-display); font-weight: 700; font-size: 0.8125rem; letter-spacing: -0.015em; margin: 0; }
.c-dline__name a { color: inherit; text-decoration: none; }
.c-dline__inci { font-family: var(--c-mono); font-size: 0.625rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--c-muted); margin: 0.25rem 0 0.75rem; }
.c-dline__price { font-family: var(--c-mono); font-size: 0.75rem; font-variant-numeric: tabular-nums; text-align: right; }

/* Quantity stepper — the +/- keys are [data-qty-step]; the value is an <output>
   at [data-qty-input]. Bounded by the interactive line (≥3:1), zero radius. */
.c-dstep {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--c-line);
  border-radius: 0;
}
.c-dstep [data-qty-step] {
  min-width: 44px;
  min-height: 44px;
  background: none;
  border: 0;
  color: var(--c-ink);
  font-family: var(--c-mono);
  cursor: pointer;
}
.c-dstep [data-qty-step]:focus-visible { outline: 2px solid var(--c-accent); outline-offset: -2px; }
.c-dstep [data-qty-input] { min-width: 2.25rem; text-align: center; font-family: var(--c-mono); font-variant-numeric: tabular-nums; font-size: 0.75rem; }
.c-dline__rm {
  display: block;
  margin-top: 0.5rem;
  background: none;
  border: 0;
  padding: 0;
  color: var(--c-muted);
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.c-dline__rm:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

.c-drawer__foot { padding: 1.25rem clamp(1.25rem, 5vw, 1.75rem); border-top: 1px solid var(--c-line); background: var(--c-ground); }
.c-drawer__sum { display: flex; justify-content: space-between; align-items: baseline; font-family: var(--c-mono); font-variant-numeric: tabular-nums; margin-bottom: 1rem; }
.c-drawer__sum b { font-size: 0.9375rem; }
.c-drawer__foot .c-btn--solid { width: 100%; }

.c-dempty {
  padding: 3.5rem clamp(1.25rem, 5vw, 1.75rem);
  text-align: center;
  font-family: var(--c-mono);
  font-size: 0.75rem;
  line-height: 1.7;
  color: var(--c-muted);
}
.c-dempty p { margin: 0 0 1.5rem; }

/* ====================================================================== PDP
 * Three zones inside lumen.css's .c-page--pdp grid (9rem margin | 1fr | 24rem):
 * folio margin | centre plate gallery | right sticky spec card.
 *
 * REMINDER (trap 1/2, enforced in the section Liquid, not here): a bespoke PDP
 * MUST emit <script type="application/ld+json">{{ product | structured_data }}
 * </script> (Horizon prints ProductGroup only from its own main-product), and a
 * theme replacing the header MUST hand-write an Organization node. */
.c-pdp__crumb {
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-muted);
  margin: 0 0 1rem;
}
.c-pdp__crumb a { color: inherit; text-decoration: none; }
.c-pdp__crumb a:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

/* The plate column: a [data-gallery] stack. The track holds [data-slide]s; the
   dots are [data-dot]. lumen-motion.css owns dialog[data-zoom] (the zoom modal);
   these selectors are scoped under .c-pdp__gallery so nothing leaks. */
.c-pdp__gallery { display: block; }
.c-pdp__gallery [data-gallery-track] {
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  gap: 1px;
}
.c-pdp__gallery [data-gallery-track]::-webkit-scrollbar { display: none; }
.c-pdp__gallery [data-slide] {
  flex: 0 0 100%;
  scroll-snap-align: start;
}
.c-pdp__gallery [data-slide] img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border: 1px solid var(--c-hair);   /* decorative plate frame → hair */
  background: var(--c-surface);
}
.c-pdp__zoom {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 0.5rem;
  background: none;
  border: 0;
  padding: 0;
  color: var(--c-accent);
  font-family: var(--c-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}
.c-pdp__zoom:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.c-pdp__dots { display: flex; gap: 0.375rem; margin-top: 0.75rem; }
.c-pdp__dots [data-dot] {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  cursor: pointer;
}
.c-pdp__dots [data-dot]::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border: 1px solid var(--c-line);   /* control boundary → strong line */
  background: transparent;
}
.c-pdp__dots [data-dot][aria-current]::before { background: var(--c-accent); border-color: var(--c-accent); }
.c-pdp__dots [data-dot]:focus-visible { outline: 2px solid var(--c-accent); outline-offset: -2px; }

/* The sticky spec card (right zone). lumen.css owns .c-card__* internals; this
   is the DISTINCT positioning wrapper only. */
.c-pdp__spec {
  position: sticky;
  top: calc(var(--header-group-height, 4rem) + 1.5rem);
  align-self: start;
}
@media (max-width: 64rem) {
  .c-pdp__spec { position: static; }
}

/* Sticky mobile ATC bar — hidden at ≥60rem where the spec card's add is visible.
   Fixed to the viewport bottom; bounded/filled with the accent. */
.c-pdp__atc {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 45;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem clamp(1rem, 4vw, 1.5rem);
  padding-bottom: max(0.625rem, env(safe-area-inset-bottom));
  background: var(--c-ground);
  border-top: 1px solid var(--c-line);
}
.c-pdp__atc-price { font-family: var(--c-mono); font-size: 0.8125rem; font-variant-numeric: tabular-nums; color: var(--c-ink); }
.c-pdp__atc .c-btn--solid { width: auto; flex: 1; padding: 0 1.5rem; }
@media (min-width: 60rem) {
  .c-pdp__atc { display: none; }
}

/* ============================================================== register thumb
 * A small vessel+smudge thumbnail for the existing manifest rows (lumen.css owns
 * .c-mrow2 and .c-mrow2__name's `a`; the bare .c-mrow2__name container is NOT
 * declared there, so this file owns it). The thumb rides at the HEAD of the name
 * cell as a flex child, so the six-column ruled grid is untouched. */
.c-mrow2__name { display: flex; align-items: center; gap: 0.75rem; }
.c-reg__thumb {
  flex: 0 0 auto;
  width: 2.5rem;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border: 1px solid var(--c-hair);   /* decorative frame → hair */
  background: var(--c-surface);
}
@media (max-width: 60rem) {
  /* lumen.css collapses .c-mrow2 to two columns on mobile; keep the thumb inline
     but let the name wrap beside it. */
  .c-mrow2__name { align-items: baseline; }
  .c-reg__thumb { align-self: center; }
}


/* Drawer-wide focus ring. The drawer overlay lives outside every section scope
   that lumen.css hangs its :focus-visible rules on, so its checkout button,
   line-item links and empty-state CTA would otherwise fall through to the UA
   default (WCAG 2.4.7). One rule on the drawer attribute covers every control
   inside it. Found by theme C's adversarial review; applied to all three. */
[data-lumen-drawer] :is(a, button):focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 2px;
}
