/* =====================================================================================
   ZF.Life — demo shopfront
   ---------------------------------------------------------------------------------------
   Loaded AFTER /demo/_shared/fossil.css, which owns the palette floor, the five local
   webfonts, focus rings, 44px touch targets, safe-area insets and the reduced-motion clamp.
   This file owns everything fossil.css deliberately does not: layout, rhythm, component
   shapes, motion. Every demo has to look like a different studio built it.

   The world here is the brand's own: a near-black espresso ground, a kraft-brown figure, a
   copper mid-tone and a warm cream. Those two anchor values were sampled off the brand's own
   profile mark — #ab7f5a on #0e0b06 — which lands, unplanned, within a hair of fossil's
   --ds-mark and --ds-matrix. So the demo runs on the shared tokens almost unmodified.

   Shape language: nothing is a pill and nothing is a rounded card. The apothecary reference is
   a printed label — square corners, hairline rules, letterspaced Roman caps — so radii stay at
   2px and separation is done with a 1px line rather than a box shadow.
   ===================================================================================== */

:root {
  /* the demo's one fossil override */
  --accent: #ab7f5a;

  /* ground */
  --zf-void: #080605;
  --zf-ink: #0e0b06;          /* sampled: the mark's ground */
  --zf-ink-2: #14100b;
  --zf-ink-3: #1c1610;
  --zf-ink-4: #241c14;

  /* figure */
  --zf-kraft: #ab7f5a;        /* the kraft of the packaging and the photography */
  --zf-teal: #0682a0;         /* sampled: the logotype. 5.03:1 on the espresso ground */
  --zf-kraft-lo: #8a6544;
  --zf-kraft-hi: #c49a72;
  --zf-copper: #7a3b22;
  --zf-copper-lo: #3d1c10;

  /* light */
  --zf-cream: #f1e8dc;
  --zf-cream-2: #e0d3c1;
  --zf-cream-3: #b8a68f;
  --zf-mute: #9c8a76;
  /* Two quieter greys, tuned so they still clear WCAG AA (4.5:1) on EVERY ground this page
     paints — #080605 through #1c1610 — because "secondary" is not a licence to be unreadable.
     Measured by scripts/check-contrast.cjs, not eyeballed. */
  --zf-dim: #907d68;
  --zf-dimmer: #907c6a;
  /* secondary text on the cream field — 6.96:1 on #f1e8dc */
  --zf-on-cream-soft: var(--zf-on-cream-soft);

  --zf-line: rgba(241, 232, 220, 0.14);
  --zf-line-strong: rgba(241, 232, 220, 0.28);
  --zf-line-dark: rgba(14, 11, 6, 0.16);

  /* type */
  --zf-display: 'Cinzel', 'Times New Roman', serif;
  --zf-han: 'ZF Serif HK', 'ZF Sans HK', 'Noto Serif TC', 'Songti TC', 'PingFang TC', serif;
  --zf-han-sans: 'ZF Sans HK', 'ZF Serif HK', 'PingFang HK', 'PingFang TC', 'Microsoft JhengHei', sans-serif;
  --zf-sans: 'Inter', 'ZF Sans HK', 'PingFang HK', system-ui, sans-serif;
  --zf-mono: 'Space Grotesk', 'Inter', system-ui, sans-serif;

  /* a fluid ramp with a density floor: nothing below 14px, nothing above 76px */
  --t--2: clamp(0.75rem, 0.72rem + 0.14vw, 0.8rem);
  --t--1: clamp(0.81rem, 0.78rem + 0.16vw, 0.9rem);
  --t-0: clamp(0.95rem, 0.91rem + 0.2vw, 1.06rem);
  --t-1: clamp(1.12rem, 1.05rem + 0.35vw, 1.35rem);
  --t-2: clamp(1.35rem, 1.2rem + 0.7vw, 1.85rem);
  --t-3: clamp(1.7rem, 1.4rem + 1.4vw, 2.7rem);
  --t-4: clamp(2.1rem, 1.5rem + 2.7vw, 4.1rem);
  --t-5: clamp(2.6rem, 1.6rem + 4.4vw, 5.6rem);

  --gutter: clamp(1.15rem, 4vw, 3.25rem);
  --measure: 62ch;
  --rule: 1px;
  --r: 2px;

  --dur-1: 180ms;
  --dur-2: 340ms;
  --dur-3: 720ms;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------------------------------------------------------------------------- reset-ish */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--zf-ink);
  color: var(--zf-cream);
  font-family: var(--zf-sans);
  font-size: var(--t-0);
  line-height: 1.65;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

:lang(zh-Hant-HK) body,
html[lang^='zh'] body { font-family: var(--zf-han-sans); line-height: 1.9; letter-spacing: 0.015em; }

h1, h2, h3, h4 { margin: 0; font-weight: 500; line-height: 1.14; letter-spacing: -0.005em; }
html[lang^='zh'] :is(h1, h2, h3) { font-family: var(--zf-han); font-weight: 600; line-height: 1.38; letter-spacing: 0.01em; }
/* The one long literary line on a product page belongs with the headings, not the UI. */
html[lang^='zh'] .pdp-note { font-family: var(--zf-han); font-weight: 600; }
html[lang='en'] :is(h1, h2) { font-family: var(--zf-display); font-weight: 600; letter-spacing: 0.005em; }

p { margin: 0; }
a { color: inherit; text-decoration: none; }
img, video, canvas { display: block; max-width: 100%; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, select { font: inherit; font-size: max(16px, 1em); }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
[hidden] { display: none !important; }

/* ------------------------------------------------------------------------ shared devices */
.wrap { width: min(1320px, 100%); margin-inline: auto; padding-inline: var(--gutter); }
.wrap-narrow { width: min(880px, 100%); margin-inline: auto; padding-inline: var(--gutter); }
.measure { max-width: var(--measure); }

/* Roman caps, tracked. The Latin stack has no Han coverage, so any Chinese string uses
   .label-cjk instead — fossil's own rule, enforced by check-register.mjs. */
.label {
  font-family: var(--zf-mono);
  font-size: var(--t--2);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--zf-kraft-hi);
}
.label-cjk {
  font-family: var(--zf-han-sans);
  font-size: var(--t--1);
  font-weight: 500;
  letter-spacing: 0.22em;
  color: var(--zf-kraft-hi);
}

.rule { height: var(--rule); background: var(--zf-line); border: 0; margin: 0; }

/* The one button shape on the site: a square-cornered slab with a hairline. */
.btn {
  --btn-fg: var(--zf-ink);
  --btn-bg: var(--zf-kraft);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  min-block-size: 46px;
  padding: 0.72em 1.6em;
  border-radius: var(--r);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--zf-mono);
  font-size: var(--t--1);
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  border: var(--rule) solid var(--btn-bg);
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease),
              border-color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
}
html[lang^='zh'] .btn { font-family: var(--zf-han-sans); font-weight: 500; letter-spacing: 0.16em; text-transform: none; }
.btn-ghost { --btn-bg: transparent; --btn-fg: var(--zf-cream); border-color: var(--zf-line-strong); }
.btn-light { --btn-bg: var(--zf-ink); --btn-fg: var(--zf-cream); }

@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--zf-kraft-hi); border-color: var(--zf-kraft-hi); color: var(--zf-ink); }
  .btn-ghost:hover { background: var(--zf-cream); border-color: var(--zf-cream); color: var(--zf-ink); }
}
.btn:active { transform: translateY(1px); }

/* A text link that draws its own underline rather than borrowing the browser's. */
.link {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  min-block-size: 44px;
  font-family: var(--zf-mono);
  font-size: var(--t--1);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--zf-kraft-hi);
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% var(--rule);
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--dur-2) var(--ease), color var(--dur-1) var(--ease);
}
html[lang^='zh'] .link { font-family: var(--zf-han-sans); text-transform: none; letter-spacing: 0.16em; }
@media (hover: hover) and (pointer: fine) {
  .link:hover { color: var(--zf-cream); background-size: 100% var(--rule); }
}

/* ------------------------------------------------------------------------- demo ribbon */
.ds-demo-ribbon { font-family: var(--zf-sans); }

/* --------------------------------------------------------------------------------- nav */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--zf-ink) 88%, transparent);
  backdrop-filter: blur(14px);
  border-block-end: var(--rule) solid var(--zf-line);
}
@supports not (backdrop-filter: blur(1px)) { .nav { background: var(--zf-ink); } }

.nav-row {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2vw, 2rem);
  min-block-size: 64px;
}
.nav-brand { display: flex; align-items: center; margin-inline-end: auto; min-block-size: 44px; }
/* The logotype IS the wordmark — there is no separate type to set beside it. */
.brandmark { block-size: 34px; inline-size: auto; }
@media (max-width: 480px) { .brandmark { block-size: 28px; } }

.nav-links { display: flex; align-items: center; gap: clamp(0.4rem, 1.6vw, 1.5rem); }
.nav-links a {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-inline: 0.4rem;
  font-family: var(--zf-mono);
  font-size: var(--t--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--zf-cream-2);
  transition: color var(--dur-1) var(--ease);
}
html[lang^='zh'] .nav-links a { font-family: var(--zf-han-sans); text-transform: none; letter-spacing: 0.18em; }
.nav-links a[aria-current='page'] { color: var(--zf-kraft-hi); }
@media (hover: hover) and (pointer: fine) { .nav-links a:hover { color: var(--zf-cream); } }

.nav-tools { display: flex; align-items: center; gap: 0.25rem; }
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-inline-size: 44px;
  min-block-size: 44px;
  padding-inline: 0.55rem;
  border-radius: var(--r);
  color: var(--zf-cream-2);
  font-family: var(--zf-mono);
  font-size: var(--t--2);
  letter-spacing: 0.12em;
  transition: color var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .icon-btn:hover { color: var(--zf-cream); background: rgba(241, 232, 220, 0.07); }
}
.icon-btn svg { inline-size: 19px; block-size: 19px; }
.bag-count {
  min-inline-size: 1.35em;
  padding: 0.05em 0.35em;
  border-radius: var(--r);
  background: var(--zf-kraft);
  color: var(--zf-ink);
  font-size: var(--t--2);
  font-weight: 700;
  line-height: 1.45;
  text-align: center;
}
.bag-count[data-empty='1'] { display: none; }

.nav-burger { display: none; }

@media (max-width: 860px) {
  .nav-burger { display: inline-flex; }
  .nav-links {
    position: fixed;
    inset: auto 0 0 0;
    top: var(--nav-offset, 104px);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.5rem var(--gutter) calc(1.5rem + env(safe-area-inset-bottom));
    background: var(--zf-ink);
    border-block-start: var(--rule) solid var(--zf-line);
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
    transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease),
                visibility 0s linear var(--dur-2);
  }
  .nav-links[data-open='1'] {
    transform: none; opacity: 1; pointer-events: auto; visibility: visible;
    transition-delay: 0s;
  }
  .nav-links a {
    min-block-size: 56px;
    font-size: var(--t-1);
    border-block-end: var(--rule) solid var(--zf-line);
  }
}

/* -------------------------------------------------------------------------------- hero */
.hero {
  position: relative;
  min-block-size: min(92svh, 900px);
  display: grid;
  align-items: end;
  overflow: hidden;
  background: var(--zf-void);
  isolation: isolate;
}
.hero-layer { position: absolute; inset: 0; z-index: 0; }
.hero-layer video,
.hero-layer img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.hero-video { opacity: 0; transition: opacity 900ms var(--ease); }
.hero-video[data-ready='1'] { opacity: 0.5; }
.hero-canvas { position: absolute; inset: 0; z-index: 1; inline-size: 100%; block-size: 100%; }
/* Once the live scene is up, the still behind it is redundant — and visibly a different
   candle. Fade rather than cut, so the swap is not a flash. */
.hero[data-3d='1'] .hero-layer { opacity: 0; transition: opacity 800ms var(--ease); }
@media (prefers-reduced-motion: reduce) { .hero[data-3d='1'] .hero-layer { transition: none; } }
.hero-canvas[hidden] { display: none; }

/* The vignette is what stops a video background from eating the type. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    radial-gradient(120% 90% at 62% 34%, transparent 0%, rgba(8, 6, 5, 0.35) 52%, rgba(8, 6, 5, 0.86) 100%),
    linear-gradient(to top, var(--zf-ink) 2%, rgba(8, 6, 5, 0.55) 34%, transparent 72%);
  pointer-events: none;
}
.hero-content { position: relative; z-index: 3; padding-block: clamp(3rem, 12svh, 8rem) clamp(2.5rem, 7svh, 5rem); }
.hero-tagline {
  font-family: var(--zf-display);
  font-size: var(--t-1);
  letter-spacing: 0.3em;
  color: var(--zf-kraft-hi);
  margin-block: 0.9rem 1.1rem;
}
.hero h1 { font-size: var(--t-5); max-width: 16ch; }
/* `ch` is the advance of "0" — about half an em — so a ch-based measure on Han text is half
   the width it looks like, and the headline re-wraps past its own <br>, stranding a single
   glyph on the last line. Han is one em per character: measure it in em. */
html[lang^='zh'] .hero h1 { max-width: 9.5em; }
.hero-sub { margin-block-start: 1.4rem; font-size: var(--t-1); color: var(--zf-cream-2); }
.hero-lede { margin-block-start: 0.9rem; color: var(--zf-mute); max-width: 46ch; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-block-start: 2.2rem; }

.hero-motion-note {
  margin-block-start: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
  font-size: var(--t--1);
  color: var(--zf-mute);
}

/* -------------------------------------------------------------------------- pillar rail */
.pillars {
  border-block: var(--rule) solid var(--zf-line);
  background: var(--zf-ink-2);
}
.pillars ul {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.pillars li {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  padding: 1.15rem 1rem;
  border-inline-start: var(--rule) solid var(--zf-line);
  text-align: center;
}
.pillars li:first-child { border-inline-start: 0; }
.pillars svg { inline-size: 20px; block-size: 20px; flex: none; color: var(--zf-kraft); }

/* ----------------------------------------------------------------------------- sections */
.section { padding-block: clamp(3.75rem, 11vw, 8.5rem); }
.section-alt { background: var(--zf-ink-2); }
.section-cream { background: var(--zf-cream); color: var(--zf-ink); }
.section-cream .label,
.section-cream .label-cjk { color: var(--zf-copper); }
.section-cream .rule { background: var(--zf-line-dark); }
.section-cream .link { color: var(--zf-copper); }
.section-cream .btn-ghost { --btn-fg: var(--zf-ink); border-color: var(--zf-line-dark); }
@media (hover: hover) and (pointer: fine) {
  .section-cream .btn-ghost:hover { background: var(--zf-ink); border-color: var(--zf-ink); color: var(--zf-cream); }
  .section-cream .link:hover { color: var(--zf-ink); }
}

.head { display: grid; gap: 1rem; margin-block-end: clamp(2.25rem, 5vw, 4rem); }
.head h2 { font-size: var(--t-4); max-width: 20ch; }
.head p { color: var(--zf-mute); max-width: 52ch; }
.section-cream .head p { color: var(--zf-on-cream-soft); }

/* --------------------------------------------------------------------------- the ritual */
.ritual-grid {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  counter-reset: step;
}
.step { position: relative; padding-block-start: 2rem; border-block-start: var(--rule) solid var(--zf-line-dark); }
.step .step-n {
  font-family: var(--zf-display);
  font-size: var(--t-2);
  letter-spacing: 0.18em;
  color: var(--zf-copper);
}
.step h3 { margin-block: 0.85rem 0.7rem; font-size: var(--t-1); }
.step p { color: var(--zf-on-cream-soft); }
.step-art { margin-block-end: 1.75rem; color: var(--zf-copper); opacity: 0.85; }
.step-art svg { inline-size: 100%; height: auto; max-inline-size: 280px; }

/* ------------------------------------------------------------------------ candle feature */
.feature {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .feature { grid-template-columns: 1.05fr 0.95fr; } }
.feature-media { position: relative; }
.feature-media img { inline-size: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.feature h2 { font-size: var(--t-4); }
.feature p { margin-block-start: 1.3rem; color: var(--zf-mute); }
.feature-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0 clamp(1.25rem, 3vw, 2.5rem);
  margin-block-start: 2rem;
  padding-block-start: 1.5rem;
  border-block-start: var(--rule) solid var(--zf-line);
}
.feature-facts li { padding-block: 0.4rem; font-family: var(--zf-mono); font-size: var(--t--1); letter-spacing: 0.1em; color: var(--zf-cream-2); }
html[lang^='zh'] .feature-facts li { font-family: var(--zf-han-sans); }

/* ---------------------------------------------------------------------------- education */
/* The loupe is the brand's own carousel device — a circle drawn over a detail. */
.edu-note { margin-block-start: clamp(2rem, 4vw, 3rem); padding-block-start: 1.25rem; border-block-start: var(--rule) solid var(--zf-line); font-size: var(--t--1); color: var(--zf-dim); }

/* -------------------------------------------------------------------------- product grid */
/* One column width, one image ratio, one baseline. The first build gave the hero products a
   wider span and dropped every third card on a stagger; with six products of unequal name and
   blurb length that produced two image sizes, two aspect ratios and rows whose tops were 56px
   apart — it read as broken rather than as editorial.
   What keeps this from being a generic card grid is the type and the hairline rule, not
   irregular sizing: no boxes, no shadows, no rounded corners, image flush to the column. */
.products {
  display: grid;
  gap: clamp(2.25rem, 4.5vw, 3.75rem) clamp(1.25rem, 2.5vw, 2rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  align-items: start;
}
.product { display: grid; gap: 1rem; align-content: start; }

.product-media {
  position: relative;
  overflow: hidden;
  background: var(--zf-ink-3);
  aspect-ratio: 4 / 5;      /* every card, no exceptions */
}
.product-media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform var(--dur-3) var(--ease), filter var(--dur-3) var(--ease);
}
/* The botanical line-art sits under the photo and is drawn on as the pointer arrives. */
.product-bot {
  position: absolute;
  inset-block-end: 0.85rem;
  inset-inline-end: 0.85rem;
  inline-size: 84px;
  color: var(--zf-cream);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
  pointer-events: none;
  mix-blend-mode: screen;
}
.product-bot svg { inline-size: 100%; height: auto; }
@media (hover: hover) and (pointer: fine) {
  .product:hover .product-media img { transform: scale(1.045); filter: brightness(1.06); }
  .product:hover .product-bot { opacity: 0.85; transform: none; }
}
.product-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding-block-end: 0.7rem;
  border-block-end: var(--rule) solid var(--zf-line);
  /* The rule is the alignment device, so it has to land at the same height in every card of a
     row even when one name wraps and its neighbour does not. */
  min-block-size: 3.5rem;
}
.product h3 { font-size: var(--t-0); }
/* The title is a link in its own right, so it carries its own 44px target rather than leaning
   on the image link above it — a thumb aiming at the words must not miss. */
.product h3 a { display: inline-flex; align-items: center; min-block-size: 44px; }
.product-price { font-family: var(--zf-mono); font-size: var(--t-0); letter-spacing: 0.06em; color: var(--zf-kraft-hi); white-space: nowrap; }
.product-price s { color: var(--zf-dimmer); margin-inline-end: 0.45em; }
.product-blurb { color: var(--zf-mute); font-size: var(--t--1); }
.product-cat { font-family: var(--zf-mono); font-size: var(--t--2); letter-spacing: 0.2em; text-transform: uppercase; color: var(--zf-dim); }
html[lang^='zh'] .product-cat { font-family: var(--zf-han-sans); text-transform: none; }

/* --------------------------------------------------------------------------- shop toolbar */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1.25rem;
  padding-block: 1rem;
  border-block: var(--rule) solid var(--zf-line);
  margin-block-end: clamp(2rem, 5vw, 3.5rem);
}
.filters { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-inline-end: auto; }
.filter {
  min-block-size: 44px;
  padding: 0.4em 1.05em;
  border: var(--rule) solid var(--zf-line);
  border-radius: var(--r);
  font-family: var(--zf-mono);
  font-size: var(--t--1);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--zf-cream-2);
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
html[lang^='zh'] .filter { font-family: var(--zf-han-sans); text-transform: none; letter-spacing: 0.16em; }
.filter[aria-pressed='true'] { background: var(--zf-kraft); border-color: var(--zf-kraft); color: var(--zf-ink); }
@media (hover: hover) and (pointer: fine) {
  .filter:not([aria-pressed='true']):hover { border-color: var(--zf-line-strong); color: var(--zf-cream); }
}
.sort { display: flex; align-items: center; gap: 0.6rem; }
.sort select {
  min-block-size: 44px;
  padding: 0.4em 2.2em 0.4em 0.8em;
  background: transparent;
  color: var(--zf-cream);
  border: var(--rule) solid var(--zf-line);
  border-radius: var(--r);
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--zf-kraft-hi) 50%),
                    linear-gradient(135deg, var(--zf-kraft-hi) 50%, transparent 50%);
  background-position: right 1.1em top 55%, right 0.75em top 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.sort select option { background: var(--zf-ink-2); color: var(--zf-cream); }
.count { font-family: var(--zf-mono); font-size: var(--t--1); letter-spacing: 0.12em; color: var(--zf-dim); }

/* --------------------------------------------------------------------------------- PDP */
.pdp { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 960px) { .pdp { grid-template-columns: 1.1fr 0.9fr; } }
@media (min-width: 960px) { .pdp-media { position: sticky; top: 88px; } }
.pdp-media img { inline-size: 100%; aspect-ratio: 4 / 5; object-fit: cover; background: var(--zf-ink-3); }
.pdp-latin { font-family: var(--zf-display); font-size: var(--t-1); letter-spacing: 0.3em; color: var(--zf-kraft-hi); }
.pdp h1 { margin-block: 0.9rem 0; font-size: var(--t-3); }
.pdp-note { margin-block-start: 1.2rem; font-size: var(--t-1); color: var(--zf-cream-2); font-style: italic; }
html[lang^='zh'] .pdp-note { font-style: normal; }
.pdp-blurb { margin-block-start: 1.2rem; color: var(--zf-mute); }
.pdp-price { margin-block-start: 1.8rem; font-family: var(--zf-mono); font-size: var(--t-2); letter-spacing: 0.04em; color: var(--zf-cream); }

.variants { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-block-start: 1.4rem; }
.variant {
  min-block-size: 46px;
  padding: 0.5em 1.25em;
  border: var(--rule) solid var(--zf-line);
  border-radius: var(--r);
  font-family: var(--zf-mono);
  font-size: var(--t--1);
  letter-spacing: 0.1em;
  color: var(--zf-cream-2);
  transition: border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
.variant[aria-pressed='true'] { background: var(--zf-cream); border-color: var(--zf-cream); color: var(--zf-ink); }

.pdp-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-block-start: 1.8rem; }

.spec { margin-block-start: clamp(2.5rem, 5vw, 3.5rem); display: grid; gap: 0; }
.spec details { border-block-start: var(--rule) solid var(--zf-line); }
.spec details:last-of-type { border-block-end: var(--rule) solid var(--zf-line); }
.spec summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-block-size: 56px;
  padding-block: 0.9rem;
  cursor: pointer;
  list-style: none;
  font-family: var(--zf-mono);
  font-size: var(--t--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--zf-cream);
}
html[lang^='zh'] .spec summary { font-family: var(--zf-han-sans); font-weight: 500; text-transform: none; letter-spacing: 0.18em; }
.spec summary::-webkit-details-marker { display: none; }
.spec summary::after {
  content: '';
  inline-size: 11px; block-size: 11px;
  border-inline-end: var(--rule) solid var(--zf-kraft-hi);
  border-block-end: var(--rule) solid var(--zf-kraft-hi);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur-2) var(--ease);
  flex: none;
}
.spec details[open] summary::after { transform: rotate(225deg) translate(-2px, -2px); }
.spec-body { padding-block: 0 1.5rem; color: var(--zf-mute); font-size: var(--t--1); }
.spec-body ol { display: grid; gap: 0.7rem; counter-reset: r; }
.spec-body ol li { display: grid; grid-template-columns: 1.8rem 1fr; gap: 0.4rem; counter-increment: r; }
.spec-body ol li::before { content: counter(r, decimal-leading-zero); font-family: var(--zf-mono); color: var(--zf-kraft); }
.spec-body ul { display: grid; gap: 0.7rem; }
.spec-body ul li { display: grid; grid-template-columns: 1.1rem 1fr; gap: 0.5rem; }
.spec-body ul li::before { content: ''; inline-size: 5px; block-size: 5px; margin-block-start: 0.62em; background: var(--zf-kraft); }
.spec-inci { font-family: var(--zf-mono); font-size: var(--t--2); line-height: 1.9; letter-spacing: 0.02em; word-break: break-word; }
.spec-plain { margin-block-start: 0.7rem; color: var(--zf-cream-2); font-size: var(--t--1); line-height: 1.85; }

/* ------------------------------------------------------------------------ education rows */
/* Was three equal cards in an auto-fit grid — the exact icon-heading-text shape this house
   bans, and it read as template no matter what was inside it. It is now a numbered register:
   a full-width rule, a large loupe held in a narrow left column, and the question and answer
   set against it. Three rows that scan down, not three boxes that sit side by side. */
.edu-list { display: grid; }
.edu-row {
  display: grid;
  gap: 0.75rem clamp(1.5rem, 4vw, 3.5rem);
  grid-template-columns: 1fr;
  padding-block: clamp(1.75rem, 4vw, 2.75rem);
  border-block-start: var(--rule) solid var(--zf-line);
}
.edu-row:last-child { border-block-end: var(--rule) solid var(--zf-line); }
@media (min-width: 760px) {
  /* em, not ch: 20ch of Han is ten characters, and the questions are fifteen — they wrapped
     to three lines against a one-line answer. */
  .edu-row { grid-template-columns: 150px minmax(0, 11em) minmax(0, 1fr); align-items: start; }
}
.edu-mark { display: flex; align-items: center; gap: 0.9rem; color: var(--zf-kraft); }
.edu-mark svg { inline-size: 74px; block-size: 74px; flex: none; }
.edu-n {
  font-family: var(--zf-display);
  font-size: var(--t-2);
  letter-spacing: 0.18em;
  color: var(--zf-kraft-hi);
}
html[lang^='zh'] .edu-n { font-family: var(--zf-han); }
.edu-row h3 { font-size: var(--t-1); }
.edu-row p { color: var(--zf-mute); }

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: var(--rule); background: var(--zf-line); border: var(--rule) solid var(--zf-line); }
.facts div { background: var(--zf-ink); padding: 1rem 1.1rem; }
.facts dt { font-family: var(--zf-mono); font-size: var(--t--2); letter-spacing: 0.16em; text-transform: uppercase; color: var(--zf-dim); }
html[lang^='zh'] .facts dt { font-family: var(--zf-han-sans); text-transform: none; }
.facts dd { margin: 0.35rem 0 0; font-size: var(--t-0); color: var(--zf-cream); }

/* scent pyramid */
.pyramid { display: grid; gap: 1.1rem; justify-items: center; text-align: center; }
.pyramid svg { inline-size: min(100%, 300px); height: auto; }
/* The pyramid's three notes are a diagram legend, not a bulleted list — the square markers
   the accordion puts on every <li> land off-centre under centred text. */
.spec-body .pyramid ul { display: grid; gap: 0.45rem; justify-items: center; }
.spec-body .pyramid ul li { display: block; grid-template-columns: none; font-family: var(--zf-mono); font-size: var(--t--1); letter-spacing: 0.12em; color: var(--zf-cream-2); }
html[lang^='zh'] .spec-body .pyramid ul li { font-family: var(--zf-han-sans); }
.spec-body .pyramid ul li::before { content: none; }

/* --------------------------------------------------------------------------------- about */
.about-grid { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: 1fr; }
@media (min-width: 900px) { .about-grid { grid-template-columns: repeat(2, 1fr); } }
.about-block { display: grid; gap: 0.9rem; align-content: start; padding-block-start: 1.75rem; border-block-start: var(--rule) solid var(--zf-line); }
.about-block h3 { font-size: var(--t-2); }
.about-block p { color: var(--zf-mute); }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--rule); background: var(--zf-line); border-block: var(--rule) solid var(--zf-line); }
.stats div { background: var(--zf-ink-2); padding: clamp(1.35rem, 3vw, 2.25rem) 1.25rem; text-align: center; }
.stats dt { font-family: var(--zf-display); font-size: var(--t-4); line-height: 1; color: var(--zf-kraft-hi); }
.stats dd { margin: 0.7rem 0 0; font-size: var(--t--1); color: var(--zf-dim); }

.callout { border: var(--rule) solid var(--zf-line-strong); padding: clamp(1.5rem, 4vw, 2.75rem); }
.callout h3 { font-size: var(--t-2); margin-block-end: 0.9rem; }
.callout p { color: var(--zf-mute); }

/* ------------------------------------------------------------------------ instagram feed */
/* Three tiles, not a carousel and not an embed — an embed would be an external request, and
   this page makes none. Square crops, because that is the shape the source grid is in. */
.feed { display: grid; gap: clamp(0.75rem, 2vw, 1.25rem); grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }
.feed-tile a { display: grid; gap: 0.85rem; }
.feed-tile img {
  inline-size: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  background: var(--zf-ink-3);
  transition: filter var(--dur-2) var(--ease);
}
.feed-cap { font-size: var(--t--1); color: var(--zf-mute); }
@media (hover: hover) and (pointer: fine) {
  .feed-tile a:hover img { filter: brightness(1.1); }
  .feed-tile a:hover .feed-cap { color: var(--zf-cream-2); }
}

/* -------------------------------------------------------------------------------- footer */
.foot { background: var(--zf-void); border-block-start: var(--rule) solid var(--zf-line); padding-block: clamp(3rem, 7vw, 5rem) calc(2rem + env(safe-area-inset-bottom)); }
.foot-top { display: grid; gap: 2rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 760px) { .foot-top { grid-template-columns: 1.4fr 1fr 1fr; } }
/* The footer takes the full lockup, tagline included — so the two lines of type that used to
   sit under the mark are now part of the artwork. */
.foot-logo { block-size: clamp(58px, 8vw, 84px); inline-size: auto; }
.foot-col :is(h2, h4) { font-family: var(--zf-mono); font-size: var(--t--2); font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: var(--zf-dim); margin-block-end: 0.9rem; }
html[lang^='zh'] .foot-col :is(h2, h4) { font-family: var(--zf-han-sans); text-transform: none; }
.foot-col li a { display: inline-flex; align-items: center; min-block-size: 44px; color: var(--zf-cream-2); font-size: var(--t--1); }
@media (hover: hover) and (pointer: fine) { .foot-col li a:hover { color: var(--zf-kraft-hi); } }
.foot-bottom { display: flex; flex-wrap: wrap; gap: 0.6rem 1.5rem; align-items: center; margin-block-start: clamp(2.5rem, 5vw, 4rem); padding-block-start: 1.5rem; border-block-start: var(--rule) solid var(--zf-line); font-size: var(--t--2); color: var(--zf-dimmer); }
.foot-bottom .link { font-size: var(--t--2); margin-inline-start: auto; }

/* ---------------------------------------------------------------------------- bag drawer */
.bag-scrim {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(8, 6, 5, 0.66);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-2) var(--ease), visibility 0s linear var(--dur-2);
}
.bag-scrim[data-open='1'] { opacity: 1; visibility: visible; transition-delay: 0s; }
.bag {
  position: fixed; z-index: 91;
  inset-block: 0; inset-inline-end: 0;
  inline-size: min(420px, 100%);
  display: flex; flex-direction: column;
  background: var(--zf-ink-2);
  border-inline-start: var(--rule) solid var(--zf-line);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--dur-2) var(--ease), visibility 0s linear var(--dur-2);
}
.bag[data-open='1'] { transform: none; visibility: visible; transition-delay: 0s; }
.bag-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.1rem var(--gutter); border-block-end: var(--rule) solid var(--zf-line); padding-block-start: calc(1.1rem + env(safe-area-inset-top)); }
.bag-head h2 { font-size: var(--t-1); }
.bag-items { flex: 1; overflow-y: auto; padding: var(--gutter); display: grid; gap: 1.25rem; align-content: start; }
.bag-item { display: grid; grid-template-columns: 68px 1fr; gap: 1rem; padding-block-end: 1.25rem; border-block-end: var(--rule) solid var(--zf-line); }
.bag-item img { inline-size: 68px; block-size: 85px; object-fit: cover; background: var(--zf-ink-3); }
.bag-item h3 { font-size: var(--t--1); }
.bag-item .meta { margin-block-start: 0.3rem; font-family: var(--zf-mono); font-size: var(--t--2); letter-spacing: 0.1em; color: var(--zf-dim); }
.bag-item .row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; margin-block-start: 0.6rem; }
.qty { display: inline-flex; align-items: center; border: var(--rule) solid var(--zf-line); border-radius: var(--r); }
.qty button { min-inline-size: 44px; min-block-size: 44px; color: var(--zf-cream-2); font-family: var(--zf-mono); }
.qty span { min-inline-size: 2.2em; text-align: center; font-family: var(--zf-mono); font-size: var(--t--1); }
.bag-empty { padding: var(--gutter); display: grid; gap: 1.25rem; justify-items: start; color: var(--zf-mute); }
.bag-foot { padding: var(--gutter); padding-block-end: calc(var(--gutter) + env(safe-area-inset-bottom)); border-block-start: var(--rule) solid var(--zf-line); display: grid; gap: 1rem; }
.bag-sub { display: flex; align-items: baseline; justify-content: space-between; font-family: var(--zf-mono); letter-spacing: 0.08em; }
.bag-sub strong { font-size: var(--t-1); color: var(--zf-cream); }
.bag-note { font-size: var(--t--2); color: var(--zf-dimmer); }

/* -------------------------------------------------------------------------------- motion */
/* Everything below is gated on --ds-motion, which fossil.css clamps to 0 under
   prefers-reduced-motion with a doubled :root selector so a later :root cannot win it back. */
.reveal {
  opacity: calc(1 - var(--ds-motion));
  transform: translateY(calc(18px * var(--ds-motion)));
  transition: opacity calc(var(--dur-3) * var(--ds-motion)) var(--ease),
              transform calc(var(--dur-3) * var(--ds-motion)) var(--ease);
  transition-delay: calc(var(--reveal-delay, 0ms) * var(--ds-motion));
}
.reveal[data-seen='1'] { opacity: 1; transform: none; }

/* The line-art draws itself once, on reveal. */
.draw path,
.draw line,
.draw circle,
.draw ellipse {
  stroke-dasharray: var(--len, 400);
  stroke-dashoffset: calc(var(--len, 400) * var(--ds-motion));
  transition: stroke-dashoffset calc(1400ms * var(--ds-motion)) var(--ease);
  transition-delay: calc(var(--reveal-delay, 0ms) * var(--ds-motion));
}
.draw[data-seen='1'] path,
.draw[data-seen='1'] line,
.draw[data-seen='1'] circle,
.draw[data-seen='1'] ellipse { stroke-dashoffset: 0; }

/*
 * The --ds-motion multiplier above only reaches the two things that opt into it, .reveal and
 * .draw. Every other transition on the page — buttons, links, the nav sheet, the product-image
 * hover, the accordion chevron, the bag drawer — runs at full duration regardless, which is not
 * a reduced-motion contract, it is a reduced-motion gesture. Collapse the lot.
 *
 * 0.01ms rather than 0: transitionend and animationend still fire, so anything that waits on
 * them completes instead of hanging.
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  /* The product-image scale/brightness is decoration, not feedback — drop it entirely rather
     than making it instant, which would read as a flicker. */
  .product:hover .product-media img { transform: none; filter: none; }
}

/* --------------------------------------------------------------------------------- print */
@media print {
  .nav, .bag, .bag-scrim, .hero-layer, .hero-canvas, .ds-demo-ribbon { display: none !important; }
  body { background: #fff; color: #000; }
}
