/* ==========================================================================
   WISHpro — one stylesheet, no build step, no framework.

   The design brief: light and premium-clinical. A bright neutral ground, a lot
   of whitespace, large confident type, and ONE restrained accent — SYNOIA's
   brand purple #854bb3. Depth comes from soft shadows and hairline rules,
   never from gradient washes.

   The palette is deliberately just three colours: black, grey/white and that
   purple. Everything else here is a tint or shade of those, so nothing
   introduces a fourth hue. It is the SAME purple family as the sibling
   consumer site ../WishToGo, on purpose — the two SYNOIA product sites are
   meant to read as one family. WISHpro stays LIGHT where WISHtoGo is dark.
   The only exception is the capsule-line colours in catalog.mjs: those are
   the real printed label colours on the product, not brand colours.

   ⚠ THE PURPLE IS A GUEST, NOT THE HOST.

   An earlier pass had it doing the default job everywhere — every kicker, every
   active state, every hover, every small tag — and the page read as purple
   rather than as black and white with an accent. The ground is now firmly
   grey/white/black and the purple is allowed in four places and no others:

     1. the filled .btn — the primary call to action, one or two per screen
     2. the home hero: its kicker and the wash in the scrim, over violet-lit video
     3. the SYNOIA / BDR Group links in the footer, where it stands for the brand
     4. :focus-visible and the focused form field — transient, and an affordance

   Everything that used to be purple and is not on that list is now ink or grey:
   kickers, pull quotes, step rules, stat figures, card numbers, ingredient tags,
   the contact aside, ghost buttons, nav and footer hovers, the mobile sheet's
   current-page marker. Selected, current and hover states read through WEIGHT,
   FILL and RULES — black on white — not through hue. If you find yourself
   reaching for var(--accent) to mark a state, reach for var(--ink) instead.

   The per-line and per-head --tint colours are a separate system and are
   untouched by any of this: they are the product's own printed colours.

   ONE type family does all the work: Montserrat. Three weights are loaded and
   only three — 300 Light for body copy, 900 Black for every display line and
   heading, and 500 Medium for the small-caps UI chrome (kickers, buttons, nav,
   chips, field labels), which at 11-13px with wide letter-spacing is unreadable
   at 300. There is deliberately no 400, 600 or 700 in the budget: name one and
   the browser will synthesise it. Section colour is switched with a `tone-*`
   class on .sec rather than per-component overrides, so a section can be moved
   without its colours coming apart.
   ========================================================================== */

:root {
  /* ground — off-white, not pure white, so white cards read as raised */
  --paper: #ffffff;
  --bone: #f5f4f7;
  --bone-2: #e7e4ec;
  --ink: #0b0b0d;
  --ink-2: #17171a;

  /* text */
  --fg: #17171a;
  --fg-mid: #5a5a60;
  --fg-dim: #8a8a90;
  --on-ink: #f2f1f4;
  --on-ink-mid: #b4b2ba;

  /* brand — SYNOIA purple, the same four values as ../WishToGo uses */
  --violet: #854bb3;
  --violet-lit: #9a67c4;
  --violet-deep: #4a2a64;
  --violet-haze: #cbaee4;

  /* the accent IS that purple; every rule below reads the alias, not the hue */
  --accent: var(--violet);
  --accent-lit: var(--violet-lit);
  --accent-deep: var(--violet-deep);
  --accent-wash: #f2ecf8;

  --rule: #0b0b0d15;
  --rule-2: #0b0b0d26;
  --rule-on-ink: #ffffff1f;

  /* type — one family, three weights: 300 body, 500 UI chrome, 900 display */
  --sans: 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* kept named --serif so every call site stays put; it now means "display" */
  --serif: 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* rhythm */
  --gut: clamp(20px, 5vw, 60px);
  --sec-y: clamp(68px, 9vw, 132px);
  --max: 1220px;
  --max-narrow: 940px;
  --r: 14px;
  --r-lg: 24px;
  --r-xl: 34px;

  /* depth — one shadow scale, used everywhere */
  --sh-1: 0 1px 2px #0b0b0d08, 0 6px 18px #0b0b0d0a;
  --sh-2: 0 2px 4px #0b0b0d0a, 0 14px 40px #0b0b0d14;
  --sh-3: 0 4px 8px #0b0b0d0d, 0 26px 70px #0b0b0d1f;

  --ease: cubic-bezier(.22, .61, .36, 1);
}

*, *::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;
  font-family: var(--sans);
  font-size: clamp(16px, 1vw, 17px);
  font-weight: 300;
  line-height: 1.66;
  color: var(--fg);
  background: var(--bone);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
ul, ol { margin: 0; padding: 0; list-style: none; }
p { margin: 0 0 1em; }
h1, h2, h3, h4 { margin: 0; font-weight: 900; letter-spacing: -.01em; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.sr, .skip:not(:focus) {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip:focus {
  position: fixed; inset-block-start: 12px; inset-inline-start: 12px; z-index: 300;
  width: auto; height: auto; clip-path: none; margin: 0;
  padding: 10px 18px; background: var(--paper); border-radius: 999px; box-shadow: var(--sh-2);
}

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gut); }
.wrap.is-narrow { max-width: var(--max-narrow); }

/* ------------------------------------------------------------- typography */

.display {
  margin: 0 0 .44em;
  font-family: var(--serif);
  font-size: clamp(1.95rem, 3.9vw, 3rem);
  font-weight: 900;
  line-height: 1.1;
  letter-spacing: -.02em;
  text-wrap: balance;
}
.display-xl { font-size: clamp(2.2rem, 5vw, 3.9rem); }
.display-hero { font-size: clamp(2.5rem, 6.6vw, 5rem); line-height: 1.03; letter-spacing: -.03em; }

/*
 * Authored line breaks apply at EVERY width.
 *
 * The obvious-looking `@media (max-width:640px){ .display br{display:none} }`
 * is a trap: hiding a <br> removes the break without leaving a space, so
 * "Fifteen minutes.\nVisibly better skin." renders as "minutes.Visibly" on a
 * phone. Every headline here breaks at a sentence or phrase boundary, which is
 * where a narrow screen would want to break anyway.
 */

/*
 * Neutral by design. A kicker sits above almost every section heading on the
 * site, so colouring it with the accent makes the accent the page's dominant
 * hue — which is exactly the mistake this stylesheet used to make. Grey reads
 * as the quiet label it is. The ONE purple kicker is the home hero's.
 */
.kicker {
  margin: 0 0 1.1em;
  font-size: .715rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--fg-dim);
}
.lede {
  font-size: clamp(1.04rem, 1.35vw, 1.22rem);
  line-height: 1.56; color: var(--fg-mid);
  max-width: 58ch; text-wrap: pretty;
}
.body { max-width: 62ch; color: var(--fg-mid); }
.note { font-size: .875rem; color: var(--fg-dim); }
.center { text-align: center; }
.mono { font-variant-numeric: tabular-nums; font-size: .82rem; letter-spacing: .04em; color: var(--fg-dim); }

.pull {
  margin: 1.7em 0 0; max-width: 22ch;
  font-family: var(--serif);
  font-size: clamp(1.2rem, 2vw, 1.7rem); font-weight: 900;
  line-height: 1.22; letter-spacing: -.018em; color: var(--ink);
}
.tone-ink .pull { color: var(--on-ink); }

.mini-h {
  margin: 0 0 .8em; font-size: .7rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--fg-dim);
}

/*
 * The brand name set as artwork rather than as type — see brandify() in
 * layout.mjs, which only ever applies it to display lines, never to prose.
 *
 * Height is in `em`, so the mark tracks whatever clamp() the surrounding
 * headline resolved to instead of needing a size per call site. Both marks are
 * in the markup and this picks one: a headline can sit on the light ground or
 * inside a dark band and the template does not know which.
 */
.brandmark { display: inline-block; white-space: nowrap; }
.brandmark img {
  display: inline-block; width: auto; height: .72em;
  vertical-align: baseline; margin-block-end: -.055em;
}
.brandmark .bm-light { display: none; }
.tone-ink .brandmark .bm-dark, .hero .brandmark .bm-dark { display: none; }
.tone-ink .brandmark .bm-light, .hero .brandmark .bm-light { display: inline-block; }

/* A kicker is 11px uppercase with .18em tracking. At .72em the mark is a smudge,
   so it gets its own size — this is the one place the em rule is not enough. */
.kicker .brandmark img { height: 1.15em; margin-block-end: -.28em; }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  min-height: 50px; padding: 0 28px;
  border: 1px solid transparent; border-radius: 999px;
  background: var(--accent); color: #fff;
  font-size: .93rem; font-weight: 500; letter-spacing: -.005em;
  cursor: pointer; white-space: nowrap;
  transition: background .25s var(--ease), transform .2s var(--ease), box-shadow .25s var(--ease);
}
/*
 * Hover LIFTS, press SINKS PAST the resting position.
 *
 * The lift and the press have to be on the same axis or the button feels like
 * two unrelated effects: -2px on hover and +1px on press is a 3px travel that
 * reads as a real object being pushed. A press that only scaled — which is what
 * this was — gets lost under a cursor.
 *
 * Both stay small. This is a professional tool site; the reference for the pass
 * was a consumer DTC beauty site and the tactility is the part worth taking from
 * it, not the bounce.
 */
.btn:hover {
  background: var(--accent-lit);
  transform: translateY(-2px);
  box-shadow: 0 10px 30px #854bb340;
}
.btn:active { transform: translateY(1px) scale(.99); box-shadow: 0 3px 10px #854bb333; }
/* The ghost button is chrome, not a call to action, so it stays neutral — the
   filled .btn above is the one place on a light section that carries the hue. */
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--rule-2); box-shadow: none; }
.btn-ghost:hover {
  background: #0b0b0d0a; border-color: var(--ink);
  transform: translateY(-2px); box-shadow: var(--sh-1);
}
.btn-ghost:active { transform: translateY(1px) scale(.99); box-shadow: none; }
.btn-sm { min-height: 40px; padding: 0 20px; font-size: .86rem; }
.row-btns { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 1.8em; }

/* on dark bands the ghost button has to invert or it disappears */
.tone-ink .btn-ghost, .hero .btn-ghost {
  color: var(--on-ink); border-color: #ffffff45;
}
.tone-ink .btn-ghost:hover, .hero .btn-ghost:hover { background: #ffffff14; border-color: #ffffff80; }

/* ----------------------------------------------------------------- header */
/* Fixed, not sticky: the bar floats over the hero video. */

.hdr {
  position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 200;
  transition: background .3s var(--ease), box-shadow .3s var(--ease), backdrop-filter .3s;
}
.hdr-in {
  display: flex; align-items: center; gap: 20px;
  width: 100%; max-width: var(--max); margin-inline: auto;
  padding: 14px var(--gut);
}
.hdr.is-stuck {
  background: #f5f4f7e8; box-shadow: 0 1px 0 var(--rule);
  backdrop-filter: saturate(1.4) blur(14px);
}
.hdr-logo { display: flex; align-items: center; margin-inline-end: auto; }
.hdr-logo img { width: 132px; height: auto; }
.logo-light { display: none; }

/*
 * "Over media" state — the home page only, and only until the header sticks.
 * The hero there is dark video, so the whole bar has to invert or the black
 * wordmark and the grey nav links disappear into it.
 */
.p-index .hdr:not(.is-stuck) .logo-light { display: block; }
.p-index .hdr:not(.is-stuck) .logo-dark { display: none; }
.p-index .hdr:not(.is-stuck) .nav-link { color: #ffffffc7; }
.p-index .hdr:not(.is-stuck) .nav-link:hover,
.p-index .hdr:not(.is-stuck) .nav-link.is-current { color: #fff; background: #ffffff1f; }
.p-index .hdr:not(.is-stuck) .burger { background: #ffffff1a; border-color: #ffffff40; }
.p-index .hdr:not(.is-stuck) .burger-lines i { background: #fff; }
/* the panel itself is a light card in both states — only the trigger inverts */
.p-index .hdr:not(.is-stuck) .nav-panel .nav-link { color: var(--fg); }

.wordmark {
  font-family: var(--serif); font-size: 1.35rem; font-weight: 900;
  letter-spacing: -.03em; line-height: 1;
}
/* only ever seen if the brand artwork is missing — see wordmark() in layout.mjs */
.wordmark b { font-weight: 900; color: var(--fg-mid); }
.foot .wordmark { color: var(--on-ink); font-size: 1.5rem; }
.foot .wordmark b { color: var(--on-ink-mid); }

.hdr-nav { display: flex; align-items: center; gap: 2px; }
.nav-link {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 9px 14px; border: 0; background: none; border-radius: 999px;
  font-size: .885rem; font-weight: 500; color: var(--fg-mid); cursor: pointer;
  transition: color .2s var(--ease), background .2s var(--ease);
}
.nav-link:hover { color: var(--fg); background: #0b0b0d10; }
.nav-link.is-current { color: var(--fg); }
.nav-link.is-current::after {
  content: ''; position: absolute; /* placeholder — real marker below */
}
.nav-chev { transition: transform .25s var(--ease); opacity: .6; }

/* dropdown */
.nav-drop { position: relative; }
.nav-panel {
  position: absolute; inset-block-start: calc(100% + 10px); inset-inline-start: 0;
  min-width: 320px; padding: 10px;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-lg);
  box-shadow: var(--sh-3);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
}
.nav-drop.is-open .nav-panel { opacity: 1; visibility: visible; transform: none; }
.nav-drop.is-open .nav-chev { transform: rotate(180deg); }
.nav-sub {
  display: block; padding: 11px 14px; border-radius: var(--r);
  transition: background .18s var(--ease);
}
.nav-sub:hover { background: #0b0b0d0a; }
.nav-sub.is-current { background: #0b0b0d0f; }
.nav-sub-t { display: block; font-size: .93rem; font-weight: 500; color: var(--fg); }
.nav-sub-d { display: block; margin-top: 2px; font-size: .8rem; line-height: 1.4; color: var(--fg-dim); }

.hdr-end { display: flex; align-items: center; gap: 10px; }

/* burger + mobile sheet */
.burger {
  display: none; width: 42px; height: 42px; padding: 0;
  border: 1px solid var(--rule-2); border-radius: 999px; background: var(--paper); cursor: pointer;
}
.burger-lines { display: grid; gap: 5px; justify-items: center; }
.burger-lines i { display: block; width: 16px; height: 1.5px; background: var(--fg); }
.sheet {
  position: fixed; inset: 62px 0 0; z-index: 190;
  padding: 24px var(--gut) 40px;
  background: var(--bone); overflow-y: auto;
}
.sheet[hidden] { display: none; }
.sheet-nav { display: grid; }
.sheet-link {
  padding: 16px 0; border-block-end: 1px solid var(--rule);
  font-family: var(--serif); font-size: 1.5rem; font-weight: 900; letter-spacing: -.02em;
}
/* The current page is marked by a rule under it, not by a colour. */
.sheet-link.is-current {
  color: var(--ink);
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 7px;
}
.sheet-mail {
  display: inline-block; margin-top: 24px; font-size: .95rem;
  color: var(--ink); border-block-end: 1px solid var(--rule-2);
}
body.nav-open { overflow: hidden; }

@media (max-width: 1040px) {
  .hdr-nav { display: none; }
  .burger { display: grid; place-items: center; }
  .hdr-end .btn { display: none; }
  .hdr.is-stuck, .nav-open .hdr { background: var(--bone); backdrop-filter: none; }
}

/* ---------------------------------------------------------------- sections */

.sec { padding-block: var(--sec-y); }
.sec-h { max-width: 60ch; margin-bottom: clamp(32px, 4vw, 56px); }
.sec-h.is-center { margin-inline: auto; text-align: center; }
.sec-h.is-center .lede { margin-inline: auto; }

.tone-bone { background: var(--bone-2); }
.tone-paper { background: var(--paper); }
/* `tone: 'wash'` was a pale-purple section band. Nothing uses it and nothing
   should: a whole band of the accent is what this pass took out. Left defined
   so an old `tone: 'wash'` degrades to the neutral band rather than to nothing. */
.tone-wash { background: var(--bone-2); }
.tone-ink { background: var(--ink); color: var(--on-ink); }
.tone-ink .lede, .tone-ink .body { color: var(--on-ink-mid); }
.tone-ink .kicker { color: var(--on-ink-mid); }
.tone-ink .mini-h, .tone-ink .note, .tone-ink .mono { color: var(--on-ink-mid); }

/* ---------------------------------------------------------- scroll reveal */

[data-reveal] {
  opacity: 0; transform: translateY(18px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
  transition-delay: var(--d, 0ms);
}
[data-reveal].in { opacity: 1; transform: none; }

/*
 * Media settles out of a slight zoom as it reveals.
 *
 * Scoped to the two figure types that clip — .split-media and .band-media both
 * carry overflow:hidden — because a 1.06 scale on an unclipped packshot
 * (.phero-media.is-contain) would just overlap whatever sits beside it.
 *
 * The longer duration is deliberate: the frame lands after the text next to it
 * has finished, which is what makes it read as depth rather than as a second
 * copy of the same animation.
 */
.split-media[data-reveal] img,
.band-media[data-reveal] img,
.split-media[data-reveal] .film-poster {
  transform: scale(1.06);
  transition: transform 1.1s var(--ease);
  transition-delay: var(--d, 0ms);
}
.split-media[data-reveal].in img,
.band-media[data-reveal].in img,
.split-media[data-reveal].in .film-poster { transform: none; }

/*
 * Panel swaps in the two selectors. Not a reveal — these fire on click, every
 * time, so they are short. A panel that took as long as a scroll reveal would
 * make the tabs feel unresponsive.
 */
.head-panel:not([hidden]), .pick-panel:not([hidden]), .ing-panel:not([hidden]) {
  animation: panel-in .34s var(--ease) both;
}
@keyframes panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  /* everything the blocks above add, undone in one place: the settle-out-of-zoom
     on media, the panel swap, and the hover lifts on buttons and cards */
  .split-media[data-reveal] img,
  .band-media[data-reveal] img,
  .split-media[data-reveal] .film-poster { transform: none; transition: none; }
  .head-panel:not([hidden]),
  .pick-panel:not([hidden]), .ing-panel:not([hidden]) { animation: none; }
  .btn:hover, .btn:active, .chip:hover, .head-tab:hover, .pick-tab:hover,
  .cap-btn:hover, .card:hover, .film-play:hover span { transform: none; }
}

/* =========================================================== home — hero */

.hero {
  position: relative; isolation: isolate;
  min-height: min(94vh, 860px);
  display: flex; align-items: flex-end;
  padding-block: 160px clamp(48px, 7vw, 96px);
  background: var(--ink); color: var(--on-ink);
  overflow: hidden;
}
.hero-video {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover;
  /* the scroll parallax writes transform here from site.js — see the parallax
     block there for why the scale it applies and the drift strength are a pair.
     No transform is set in CSS: under prefers-reduced-motion the effect is
     skipped entirely and the frame must sit at its natural size. */
  will-change: transform;
}
/* Two scrims: a dark base so white type always clears AA contrast, and a
   bottom-weighted one so the copy block sits on the densest part. */
.hero-scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to top, #070709ee 0%, #070709ad 42%, #0707094d 74%, #0707096b 100%),
    /* the copy column runs down the inline-start edge, so it gets its own wash —
       without it the kicker sits on the brightest part of the frame */
    linear-gradient(to right, #0707099e, #0707091a 58%, transparent),
    radial-gradient(120% 80% at 18% 100%, #4a2a6466, transparent 70%);
}
.hero-in { position: relative; }
/* The one purple kicker on the site. The hero loop is violet-lit footage and the
   scrim already carries a violet wash, so this is where the accent belongs. */
.hero .kicker { color: var(--accent-lit); }
.hero .display-hero { max-width: 15ch; }
.hero-foot {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 28px; margin-top: 8px;
}
.hero-foot .lede { color: #e0dde5; max-width: 46ch; }
.hero-foot .row-btns { margin-top: 0; }
.scroll-cue {
  display: inline-flex; align-items: center; gap: 9px; margin-top: 40px;
  font-size: .72rem; letter-spacing: .18em; text-transform: uppercase; color: #ffffff8c;
}
.scroll-cue i {
  display: block; width: 1px; height: 30px;
  background: linear-gradient(#ffffff00, #ffffffb0);
}

/* ------------------------------------------------------------------ stats */

.stats {
  display: grid; gap: clamp(24px, 4vw, 48px);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.stats li { text-align: center; }
.stat-v {
  display: block; font-family: var(--serif);
  font-size: clamp(2.6rem, 5.5vw, 4rem); font-weight: 900; line-height: 1;
  letter-spacing: -.03em; color: var(--on-ink);
  /* the value counts up on entry (see countUp in site.js). Proportional digits
     change width as they cycle, which makes the whole number twitch sideways
     while it runs; tabular ones hold the column still. */
  font-variant-numeric: tabular-nums;
}
.stat-l {
  display: block; margin-top: .7em; font-size: .84rem;
  letter-spacing: .04em; color: var(--on-ink-mid); text-wrap: balance;
}
.sec-stats { padding-block: clamp(52px, 6vw, 84px); }

/* ------------------------------------------------------------------ split */

.split {
  display: grid; gap: clamp(32px, 5vw, 72px);
  grid-template-columns: 1fr; align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split.is-reverse .split-text { order: 2; }
  .split.is-wide-media { grid-template-columns: 0.85fr 1.15fr; }
}
.split-media { margin: 0; border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--sh-2); }
.split-media img { width: 100%; object-fit: cover; }
.split-media.is-tall img { aspect-ratio: 4 / 5; }
.split-media.is-wide img { aspect-ratio: 4 / 3; }
.split-media.is-plain { box-shadow: none; background: var(--paper); }
/* For a subject that must not be cropped: a white packshot, or a capsule lid,
   which is a masked circle on transparency and would lose its edge to `cover`. */
.split-media.is-contain img { aspect-ratio: 1; object-fit: contain; }

/* One image as a full-width band, between a split and the point list under it. */
.band-media {
  margin: clamp(30px, 3.6vw, 52px) 0 0;
  border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--sh-2);
}
.band-media img { width: 100%; aspect-ratio: 21 / 9; object-fit: cover; }
@media (max-width: 620px) { .band-media img { aspect-ratio: 3 / 2; } }

/* ------------------------------------------------------------ card grids */

/* 300px is chosen so a 1220px wrap resolves to THREE columns, not four: the
   card sets on this site are all threes and sixes, and a four-up grid leaves a
   ragged 4 + 2 on every one of them. */
.cards {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.card {
  padding: clamp(24px, 2.6vw, 34px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--sh-2); }
.card h3 { margin: 0 0 .5em; font-size: 1.06rem; font-weight: 500; letter-spacing: -.01em; }
.card p { margin: 0; font-size: .93rem; color: var(--fg-mid); }
.card-n {
  display: block; margin-bottom: 1.1em;
  font-family: var(--serif); font-size: .95rem; font-weight: 900; color: var(--fg-dim);
}
.tone-ink .card-n { color: var(--on-ink-mid); }

/* the four capsule lines — a glyph and a live count in the line's own tint,
   see LINE_ICON/lineCards() in pages.mjs for why a mark rather than a photo */
.card-line { position: relative; }
.line-icon {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; margin-bottom: 1.1em; border-radius: var(--r);
  background: color-mix(in srgb, var(--tint) 12%, transparent);
  color: var(--tint);
}
.line-icon svg { width: 22px; height: 22px; }
.card-line-n {
  display: inline-block; margin-top: 1em; padding: 4px 11px;
  border-radius: 999px; font-size: .74rem; font-weight: 500;
  color: var(--tint); background: color-mix(in srgb, var(--tint) 12%, transparent);
}
.tone-ink .card-line-n { background: color-mix(in srgb, var(--tint) 26%, transparent); }

.tone-ink .card {
  background: var(--ink-2); border-color: var(--rule-on-ink); box-shadow: none;
}
.tone-ink .card p { color: var(--on-ink-mid); }
.tone-ink .card:hover { box-shadow: none; background: #23232a; }

/* numbered steps */
.steps {
  display: grid; gap: 20px; counter-reset: s;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
/* A black rule reads as "step" just as well as a purple one, and there are up to
   four of them per section — enough to tint the whole band if they carried hue. */
.steps li { padding-block-start: 20px; border-block-start: 2px solid var(--ink); }
.step-n { display: block; margin-bottom: .8em; font-size: .74rem; letter-spacing: .14em; color: var(--fg-dim); }
.tone-ink .steps li { border-block-start-color: var(--on-ink); }
.tone-ink .step-n { color: var(--on-ink-mid); }
.steps h3 { margin: 0 0 .4em; font-size: 1.02rem; font-weight: 500; }
.steps p { margin: 0; font-size: .92rem; color: var(--fg-mid); }

/* simple two-column point list */
.points {
  display: grid; gap: 26px 40px;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  margin-top: 2.4em;
}
.points h3 { margin: 0 0 .35em; font-size: .98rem; font-weight: 500; }
.points p { margin: 0; font-size: .91rem; color: var(--fg-mid); }
.points li { padding-inline-start: 18px; border-inline-start: 1px solid var(--rule-2); }

/* a sub-block inside a section that already has its own split above it */
.sec-sub { margin-top: clamp(44px, 5vw, 76px); }

/* the four head names, listed as a plain typographic strip in a teaser */
.head-strip { display: flex; flex-wrap: wrap; gap: 8px 10px; margin: 1.6em 0 0; }
.head-strip li {
  padding: 7px 15px; border: 1px solid var(--rule-2); border-radius: 999px;
  font-size: .84rem; color: var(--fg-mid);
}

/* a static row of line chips, used as a teaser for the capsule explorer */
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 1.6em 0 0; }
.chip-row .chip { cursor: default; }

/* trust strip — a light band of short claims */
.trust {
  display: grid; gap: 1px; background: var(--rule-2);
  border: 1px solid var(--rule-2); border-radius: var(--r-lg); overflow: hidden;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.trust li { padding: clamp(22px, 2.4vw, 30px); background: var(--paper); }
.trust h3 { margin: 0 0 .45em; font-size: .96rem; font-weight: 500; }
.trust p { margin: 0; font-size: .89rem; color: var(--fg-mid); }

/* ================================================= technology head selector */

.headsel { display: grid; gap: clamp(24px, 3vw, 40px); }
.headsel-tabs {
  display: flex; flex-wrap: wrap; gap: 10px;
}
.head-tab {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 20px 10px 12px;
  background: var(--paper); border: 1px solid var(--rule-2); border-radius: 999px;
  font-size: .92rem; font-weight: 500; color: var(--fg-mid); cursor: pointer;
  transition: border-color .25s var(--ease), color .25s var(--ease),
              box-shadow .25s var(--ease), transform .25s var(--ease);
}
.head-tab:hover { color: var(--fg); box-shadow: var(--sh-1); transform: translateY(-2px); }
.head-tab:active { transform: translateY(0); }
.head-tab.is-on {
  color: var(--fg); border-color: var(--tint, var(--accent));
  box-shadow: 0 0 0 1px var(--tint, var(--accent)) inset, var(--sh-1);
}
.head-dot {
  width: 20px; height: 20px; border-radius: 999px;
  background: var(--tint, var(--accent));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tint, var(--accent)) 18%, transparent);
  transition: box-shadow .25s var(--ease);
}
/* the selected tab's dot gains a wider halo — the selection reads at a glance
   from the dot alone, which is what you actually look at in a colour selector */
.head-tab.is-on .head-dot {
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--tint, var(--accent)) 24%, transparent);
}

.head-panel {
  display: grid; gap: clamp(24px, 4vw, 56px); align-items: center;
  grid-template-columns: 1fr;
  padding: clamp(24px, 3vw, 44px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-xl);
  box-shadow: var(--sh-2);
}
@media (min-width: 860px) { .head-panel { grid-template-columns: 0.85fr 1.15fr; } }
.head-panel[hidden] { display: none; }
.head-shot {
  margin: 0; border-radius: var(--r-lg); overflow: hidden;
  background: linear-gradient(160deg, color-mix(in srgb, var(--tint) 12%, #fff), #fff 65%);
}
.head-shot img { width: 100%; aspect-ratio: 1; object-fit: contain; }
.head-tag {
  display: inline-block; margin: 0 0 1em; padding: 5px 13px;
  border-radius: 999px; background: color-mix(in srgb, var(--tint) 12%, transparent);
  color: color-mix(in srgb, var(--tint) 78%, #000);
  font-size: .74rem; font-weight: 500; letter-spacing: .09em; text-transform: uppercase;
}
.head-panel h3 {
  margin: 0 0 .3em; font-family: var(--serif); font-weight: 900;
  font-size: clamp(1.6rem, 2.6vw, 2.2rem); letter-spacing: -.02em;
}
.head-lead { font-size: 1.06rem; color: var(--fg); margin-bottom: .9em; }
.head-points { display: grid; gap: 9px; margin: 1.6em 0 0; }
.head-points li {
  position: relative; padding-inline-start: 24px; font-size: .92rem; color: var(--fg-mid);
}
.head-points li::before {
  content: ''; position: absolute; inset-inline-start: 0; inset-block-start: .62em;
  width: 9px; height: 9px; border-radius: 999px;
  background: var(--tint, var(--accent));
}
.head-best {
  margin-top: 1.6em; padding-top: 1.2em; border-top: 1px solid var(--rule);
  font-size: .88rem; color: var(--fg-dim);
}
.head-best b { color: var(--fg-mid); font-weight: 500; }

/* ================================================ at-home take-home picker
 *
 * Same tablist shape as the head selector above and the same JS (see tablist()
 * in site.js), but UNTINTED. The four heads and the four capsule lines are
 * colour-coded on the physical product, so `--tint` there is standing for
 * something real; the device, the serum and the cream are not, and per the
 * palette rule a selected state with no real colour behind it reads through
 * ink, weight and rules instead of borrowing the accent.
 */

.pickr { display: grid; gap: clamp(24px, 3vw, 40px); }
.pickr-tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.pick-tab {
  padding: 11px 22px;
  background: var(--paper); border: 1px solid var(--rule-2); border-radius: 999px;
  font-size: .92rem; font-weight: 500; color: var(--fg-mid); cursor: pointer;
  transition: border-color .25s var(--ease), color .25s var(--ease),
              background-color .25s var(--ease), box-shadow .25s var(--ease),
              transform .25s var(--ease);
}
/* the brandmark inside a tab label sits on the light ground and must not
   inflate the line box — same treatment the nav and chips give it */
.pick-tab .brandmark img { height: .82em; vertical-align: -0.02em; }
.pick-tab:hover { color: var(--fg); box-shadow: var(--sh-1); transform: translateY(-2px); }
.pick-tab:active { transform: translateY(0); }
.pick-tab.is-on {
  background: var(--ink); border-color: var(--ink); color: var(--on-ink);
  box-shadow: var(--sh-1);
}
.pick-tab.is-on .bm-dark { display: none; }
.pick-tab.is-on .bm-light { display: inline-block; }

.pick-panel {
  display: grid; gap: clamp(24px, 4vw, 56px); align-items: center;
  grid-template-columns: 1fr;
  padding: clamp(24px, 3vw, 44px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-xl);
  box-shadow: var(--sh-2);
}
@media (min-width: 860px) { .pick-panel { grid-template-columns: .8fr 1.2fr; } }
.pick-panel[hidden] { display: none; }
.pick-shot {
  margin: 0; border-radius: var(--r-lg); overflow: hidden; background: var(--bone);
}
.pick-shot img { width: 100%; aspect-ratio: 1; object-fit: contain; }
.pick-tag {
  display: inline-block; margin: 0 0 1em; padding: 5px 13px;
  border-radius: 999px; background: var(--bone); border: 1px solid var(--rule);
  color: var(--fg-mid);
  font-size: .74rem; font-weight: 500; letter-spacing: .09em; text-transform: uppercase;
}
.pick-panel h3 {
  margin: 0 0 .4em; font-family: var(--serif); font-weight: 900;
  font-size: clamp(1.5rem, 2.4vw, 2rem); letter-spacing: -.02em;
}
/* The line to say at the front desk. Set apart from the paragraph because it is
   the half of this block a cosmetician actually reuses. */
.pick-desk {
  margin: 1.6em 0 0; padding-inline-start: 16px;
  border-inline-start: 2px solid var(--ink);
  font-size: .92rem; color: var(--fg-mid);
}
.pick-desk b {
  display: block; margin-bottom: .35em; color: var(--fg);
  font-size: .72rem; font-weight: 500; letter-spacing: .16em; text-transform: uppercase;
}

/* Cream vs serum ingredient tabs — same `.pickr`/`.pick-tab` shell as the
   take-home picker above, but the panel is a plain block (summary line + the
   `.ings` grid) rather than the picker's fixed image/text split, since there
   is no per-panel photo here. */
.ing-panel {
  padding: clamp(24px, 3vw, 44px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-xl);
  box-shadow: var(--sh-2);
}
.ing-panel[hidden] { display: none; }
.ing-summary { max-width: 62ch; margin-bottom: 1.8em; color: var(--fg-mid); }

/* ------------------------------------------- US availability asterisk
 *
 * MicroCurrent and Blue are not sold in the United States yet, and both are
 * named in a dozen places — selector tabs, panel headings, the home teaser
 * strip, pairing tokens, running prose. Every one of those carries `.us-star`
 * and every block that contains one is followed by `.us-foot`.
 *
 * The brief for the look is "unobtrusive but genuinely present": muted grey, a
 * fraction of the type size, never red and never boxed. It must not read as a
 * warning — the heads are coming, they are simply not there yet.
 *
 * `line-height: 0` stops the raised glyph from opening up the line box, which
 * would otherwise make one row of a card grid taller than its neighbours.
 */
/*
 * .72em, not less. An asterisk is mostly white space, and the smallest type it
 * sits on is the 13.4px .head-strip — at the .62em this started on it resolved
 * to 8.3px and read as a speck of dust. --fg-mid rather than --fg-dim for the
 * same reason: --fg-dim on paper is about 3:1, which is under the bar for a
 * glyph this size. It is still grey, still quiet, and deliberately not red.
 */
.us-star {
  font-size: .72em; font-weight: 500; line-height: 0;
  vertical-align: super; color: var(--fg-mid);
  margin-inline-start: .12em;
}
.tone-ink .us-star { color: var(--on-ink); opacity: .75; }
.head-tab .us-star, .pair-tok .us-star { color: currentColor; opacity: .7; }

.us-foot {
  margin: 1.5em 0 0; max-width: 66ch;
  font-size: .79rem; line-height: 1.55; color: var(--fg-dim);
}
/* in the footnote itself the star sits on the baseline — it is the label of the
   line, not a mark raised off a word */
.us-foot .us-star {
  font-size: 1em; vertical-align: baseline; line-height: inherit;
  margin-inline: 0 .2em; color: var(--fg-mid);
}
/* The head's name inside the footnote. It is set off deliberately: the sentence
   has to read as being about a named technology head and not about whatever
   product the paragraph above it was describing — a reader took the older,
   unnamed version on the Collagen capsule page to mean the capsule itself. */
.us-name { font-weight: 500; color: var(--ink); }
.tone-ink .us-foot { color: var(--on-ink-mid); }
.tone-ink .us-name { color: var(--on-ink); }
/* under a strip or a paragraph that already has its own bottom margin */
.us-foot.is-tight { margin-top: .9em; }

/* The regional-availability block on Technology, directly under the selector
   tabs. The second line is the company's own published wording — see
   pages.technology.heads.usNote in content.mjs — and it is quoted verbatim. */
.us-note {
  padding: 16px 20px; margin-top: -6px;
  border: 1px dashed var(--rule-2); border-radius: var(--r);
  max-width: 74ch;
}
.us-note .us-foot { margin-top: 0; }
.us-note-q {
  margin: .7em 0 0; padding-top: .7em; border-top: 1px solid var(--rule);
  font-size: .82rem; color: var(--fg-dim);
}

/* ==================================================== capsules — explorer */

.capx { display: grid; gap: clamp(22px, 2.6vw, 34px); }
.capx-filters { display: flex; flex-wrap: wrap; gap: 9px; }
.chip {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 9px 18px; border: 1px solid var(--rule-2); border-radius: 999px;
  background: var(--paper); font-size: .88rem; font-weight: 500;
  color: var(--fg-mid); cursor: pointer;
  transition: border-color .22s var(--ease), color .22s var(--ease),
              background .22s var(--ease), transform .22s var(--ease),
              box-shadow .22s var(--ease);
}
.chip:hover { color: var(--fg); transform: translateY(-2px); box-shadow: var(--sh-1); }
.chip:active { transform: translateY(0); }
/* .chip-row is a static teaser, not a control — it must not offer feedback it
   cannot honour. `cursor: default` is already set on it; this kills the lift. */
.chip-row .chip:hover { transform: none; box-shadow: none; }
.chip.is-on { color: #fff; background: var(--tint, var(--ink)); border-color: var(--tint, var(--ink)); }
.chip i { width: 9px; height: 9px; border-radius: 999px; background: var(--tint, var(--fg-dim)); }
.chip.is-on i { background: #ffffffcc; }

/* The grid used to be one column of a two-column layout, with a sticky detail
   panel beside it. Each capsule now has its own page, the panel is gone, and
   the grid takes the full measure — so the cards can carry the lead line too
   and 260px is the narrowest that reads. */
.capx-list {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
/* Inside a capsule page, listing the rest of its own line: fewer cards, less
   text on each, so they can be tighter. */
.capx-list.is-tight {
  gap: 10px; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}

/* An <a>, not a <button>: the click navigates to /capsules/<slug>.html. Both
   the reset and the colour matter — an anchor brings its own underline and its
   own link colour, and this card is neither. */
.cap-btn {
  display: flex; align-items: flex-start; gap: 13px; width: 100%;
  padding: 13px 15px; text-align: start; text-decoration: none; color: inherit;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .2s var(--ease);
}
.cap-btn:hover { transform: translateY(-3px); box-shadow: var(--sh-2); border-color: var(--rule-2); }
.cap-btn:active { transform: translateY(0); box-shadow: var(--sh-1); }
.cap-btn[hidden] { display: none; }
.cap-btn-txt { min-width: 0; }
.cap-btn-t { display: block; font-size: .93rem; font-weight: 500; letter-spacing: -.005em; }
.cap-btn-l {
  display: block; margin-top: .12em;
  font-size: .7rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  color: color-mix(in srgb, var(--tint) 78%, #000);
}
.cap-btn-d { display: block; margin-top: .5em; font-size: .84rem; color: var(--fg-mid); }
.capx-list.is-tight .cap-btn-l {
  text-transform: none; letter-spacing: 0; font-weight: 300;
  font-size: .8rem; color: var(--fg-mid);
}

/*
 * The capsule chip.
 *
 * `.cap-shot` is the real thing: a plain, unedited photograph of the capsule —
 * see the policy note above `CAPSULES` in build-assets.mjs for why this is no
 * longer a masked crop. At the small grid size (42px) it's still shown circular
 * — `object-fit: cover` there just reads as a normal round icon/chip, the same
 * way a favicon or avatar gets cropped, and nothing is lost by that zoom at
 * icon size. At the large detail-panel size (`.is-lg`) it switches to
 * `object-fit: contain` on a plain card instead of a hard circle mask, so the
 * whole photographed capsule — its reflection, its real proportions — is
 * visible rather than cropped into a porthole.
 *
 * The ring is the line's own printed colour, so the explorer keeps its colour
 * coding via the chip's border/glow rather than a tinted illustration.
 *
 * `.puck` is the CSS-drawn fallback, kept for any capsule with no usable frame.
 */
.cap-shot {
  /* block, not the default inline: outside the flex row of a .cap-btn the
     width/height on an inline span are ignored and the big chip vanishes */
  display: block; position: relative; flex: none;
  width: 42px; height: 42px; border-radius: 999px;
  background: var(--paper);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--tint) 55%, transparent),
              0 1px 3px #0b0b0d1f;
  overflow: hidden;
}
.cap-shot img { width: 100%; height: 100%; object-fit: cover; border-radius: 999px; }
.cap-shot.is-lg {
  width: clamp(140px, 16vw, 190px); height: clamp(140px, 16vw, 190px);
  border-radius: var(--r-lg);
  padding: 10px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tint) 60%, transparent),
              0 6px 20px #0b0b0d1f;
}
.cap-shot.is-lg img { object-fit: contain; border-radius: calc(var(--r-lg) - 6px); }

.puck {
  display: block; position: relative; flex: none;
  width: 42px; height: 42px; border-radius: 999px;
  background: radial-gradient(120% 120% at 30% 22%, #fff, #f1f0f3 62%, #e3e1e7);
  box-shadow: inset 0 0 0 1px #0b0b0d0f, 0 1px 3px #0b0b0d14;
  overflow: hidden;
}
.puck::after {
  content: ''; position: absolute; inset-inline: -12%; inset-block-end: -18%;
  height: 62%; border-start-start-radius: 60% 100%; border-start-end-radius: 40% 100%;
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--tint) 88%, #fff),
    color-mix(in srgb, var(--tint) 100%, #000) 70%);
}
.puck::before {
  content: ''; position: absolute; inset-block-start: 12%; inset-inline-start: 16%;
  width: 34%; height: 22%; border-radius: 999px; z-index: 2;
  background: #ffffffb3; filter: blur(2px);
}
.puck.is-lg { width: clamp(96px, 12vw, 128px); height: clamp(96px, 12vw, 128px); }

/* ================================= one capsule — its own page */

/* The way back up. Only the per-capsule pages are nested, and they are reached
   by clicking through Capsules rather than from the nav, so the route back has
   to live on the page. */
.crumb { margin-bottom: clamp(18px, 2.4vw, 30px); }
.crumb a {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .78rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  color: var(--fg-dim); text-decoration: none;
  transition: color .2s var(--ease);
}
.crumb a:hover { color: var(--fg); }
.crumb svg { transition: transform .2s var(--ease); }
.crumb a:hover svg { transform: translateX(-3px); }

/* The line name over the capsule name. Tinted with the line's own printed
   label colour, which is the one place on this site a hue is allowed to mean
   something — see the palette note in CLAUDE.md. */
.cap-kicker { color: color-mix(in srgb, var(--tint) 80%, #000); }
.phero-cap .phero-in { align-items: start; }
.cap-hero-media { max-width: 420px; }
@media (max-width: 899px) { .cap-hero-media { max-width: 300px; } }

.cap-sub {
  margin: 0 0 1em; font-family: var(--serif); font-weight: 900;
  font-size: clamp(1.25rem, 2vw, 1.6rem); letter-spacing: -.02em;
}
.cap-suited { display: grid; gap: 0; }
.cap-suited li {
  padding: .85em 0; border-bottom: 1px solid var(--rule);
  font-size: .95rem; color: var(--fg-mid);
}
.cap-suited li:first-child { border-top: 1px solid var(--rule); }

.cap-pairname {
  margin: 0 0 .8em; font-family: var(--serif); font-weight: 900;
  font-size: clamp(1.5rem, 2.4vw, 2rem); letter-spacing: -.02em;
}
.cap-pairtag {
  display: block; margin-top: .5em;
  font-family: var(--sans); font-weight: 500; font-size: .74rem;
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-dim);
}
.cap-best {
  margin-top: 1.3em; padding-top: 1.1em; border-top: 1px solid var(--rule);
  font-size: .9rem; color: var(--fg-mid);
}
.cap-best b { font-weight: 500; color: var(--fg); }
.cap-note { margin-top: .8em; font-size: .85rem; color: var(--fg-dim); }

/* .points carries a 2.4em top margin to clear the heading it normally sits
   under. On a capsule page it stands alone in its own band, where that margin
   is just a gap at the top of an already-padded section. */
.cap-format .points { margin-top: 0; }

.cap-line { max-width: 62ch; }
.cap-line .display { font-size: clamp(1.6rem, 3vw, 2.3rem); }
.cap-also {
  margin: clamp(30px, 3.4vw, 46px) 0 1em;
  font-size: .74rem; font-weight: 500; letter-spacing: .16em; text-transform: uppercase;
  color: var(--fg-dim);
}


/* ---------------------------------------------------------- ingredients */

.ings {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.ing {
  padding: clamp(22px, 2.4vw, 30px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-lg);
}
.ing-tag {
  display: inline-block; margin-bottom: 1em; padding: 4px 11px;
  border-radius: 999px; background: var(--bone-2); color: var(--fg-mid);
  font-size: .68rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
}
.ing h3 { margin: 0 0 .45em; font-size: 1rem; font-weight: 500; }
.ing p { margin: 0; font-size: .9rem; color: var(--fg-mid); }

/* --------------------------------------------------------- pairing cards */

.pairs {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.pair {
  display: flex; flex-direction: column; gap: 16px;
  padding: clamp(24px, 2.6vw, 32px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
}
.pair-goal { font-family: var(--serif); font-size: 1.3rem; font-weight: 900; letter-spacing: -.02em; }
.pair-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pair-tok {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 14px 7px 8px; border-radius: 999px;
  background: var(--bone); font-size: .82rem; font-weight: 500;
}
.pair-tok i { width: 14px; height: 14px; border-radius: 999px; background: var(--tint, var(--accent)); }
.pair-plus { color: var(--fg-dim); font-size: .9rem; }
.pair p { margin: 0; font-size: .92rem; color: var(--fg-mid); }

/* ------------------------------------------------------------------ film */

.film {
  position: relative; margin: 0; border-radius: var(--r-xl); overflow: hidden;
  background: var(--ink); box-shadow: var(--sh-3);
}
.film video { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
/* The 9:16 social cut. Capped by height rather than width, or a phone-shaped
   video in a desktop column becomes taller than the viewport. */
.film.is-portrait { max-width: min(420px, 100%); margin-inline: auto; }
.film.is-portrait video, .film.is-portrait .film-poster { aspect-ratio: 9 / 16; }
.film-poster {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: opacity .4s var(--ease);
}
.film-play {
  position: absolute; inset: 0; display: grid; place-items: center;
  width: 100%; border: 0; background: #0b0b0d3d; cursor: pointer;
  transition: opacity .3s var(--ease), background .3s var(--ease);
}
.film-play:hover { background: #0b0b0d59; }
.film-play span {
  display: grid; place-items: center; width: 78px; height: 78px;
  border-radius: 999px; background: #ffffffe8; color: var(--ink);
  box-shadow: var(--sh-2);
  transition: transform .3s var(--ease), background .3s var(--ease);
}
/* the disc grows under the cursor — on a full-bleed play overlay the background
   tint alone is a very quiet acknowledgement that the whole frame is a button */
.film-play:hover span { transform: scale(1.08); background: #fff; }
.film-play:active span { transform: scale(1.01); }
.film.is-playing .film-play, .film.is-playing .film-poster { opacity: 0; pointer-events: none; }
.film-cap { margin: 14px 0 0; font-size: .84rem; color: var(--fg-dim); }

/* --------------------------------------------------------------- feature */
/* An image with a caption plate hanging off it — used for the Asia spotlight. */

.gal {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.gal figure { margin: 0; border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--sh-1); }
.gal img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 3 / 4; }
.gal .is-wide { grid-column: span 2; }
.gal .is-wide img { aspect-ratio: 3 / 2; }
@media (max-width: 620px) { .gal .is-wide { grid-column: span 1; } .gal .is-wide img { aspect-ratio: 3 / 4; } }

/* ------------------------------------------------------------ link cards */

.linkcards {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.linkcard {
  display: flex; flex-direction: column; gap: 14px;
  padding: clamp(26px, 3vw, 40px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-xl);
  box-shadow: var(--sh-1);
}
.linkcard h3 {
  font-family: var(--serif); font-size: clamp(1.4rem, 2.2vw, 1.9rem);
  font-weight: 900; letter-spacing: -.02em;
}
.linkcard p { margin: 0; color: var(--fg-mid); font-size: .95rem; }
.linkcard .btn { align-self: flex-start; margin-top: auto; }
.linkcard-media { margin: -8px 0 0; border-radius: var(--r-lg); overflow: hidden; background: var(--bone); }
.linkcard-media img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.tone-ink .linkcard { background: var(--ink-2); border-color: var(--rule-on-ink); box-shadow: none; }
.tone-ink .linkcard p { color: var(--on-ink-mid); }

/* ------------------------------------------------------------- page hero */

.phero {
  padding-block: clamp(130px, 15vw, 190px) clamp(40px, 5vw, 72px);
  background: linear-gradient(180deg, var(--paper), var(--bone));
  border-block-end: 1px solid var(--rule);
}
.phero-in { display: grid; gap: clamp(28px, 4vw, 56px); align-items: center; }
@media (min-width: 900px) { .phero-in { grid-template-columns: 1.05fr .95fr; } }
/* A hero with no media still constrains its measure — but on the text, not on
   the wrap, or the whole column centres and stops lining up with the sections
   below it. */
.phero.is-plain .phero-in { grid-template-columns: 1fr; }
.phero.is-plain .phero-text { max-width: 62ch; }
.phero-media { border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--sh-2); }
.phero-media img { width: 100%; aspect-ratio: 5 / 4; object-fit: cover; }
.phero-media.is-contain { background: var(--paper); box-shadow: var(--sh-1); }
.phero-media.is-contain img { object-fit: contain; aspect-ratio: 4 / 3; }

/* the "who is behind this" logo strip on the dark band */
.lockup {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 34px; margin: 2.4em 0 0;
}
.lockup img { width: auto; height: 26px; opacity: .78; transition: opacity .25s var(--ease); }
.lockup a:hover img { opacity: 1; }
/* the Company page states the chain in running prose, so its marks align left */
.lockup.is-left { justify-content: flex-start; margin-block: 2.2em; }
/* a stacked, near-square mark needs more height than a wide one-line mark to
   carry the same optical weight — matching them on height makes it a stamp */
.lockup .is-stacked img { height: 56px; }

/* --------------------------------------------------------------- end CTA */

.sec-end { text-align: center; }
.end-cta { max-width: 52ch; margin-inline: auto; }
.end-cta .sec-h { margin-bottom: 1.2em; }
.end-cta .body { color: var(--fg-mid); }
.tone-ink .end-cta .body { color: var(--on-ink-mid); }
.end-cta .lede { margin-inline: auto; }
.end-cta .row-btns { justify-content: center; }

/* ----------------------------------------------------------------- forms */

.form-grid { display: grid; gap: clamp(28px, 4vw, 56px); align-items: start; }
@media (min-width: 900px) { .form-grid { grid-template-columns: 1.15fr .85fr; } }

.form {
  display: grid; gap: 16px;
  padding: clamp(26px, 3vw, 40px);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-xl);
  box-shadow: var(--sh-2);
}
.form-row { display: grid; gap: 16px; }
@media (min-width: 560px) { .form-row.is-2 { grid-template-columns: 1fr 1fr; } }
.field { display: grid; gap: 7px; }
.field label { font-size: .82rem; font-weight: 500; color: var(--fg-mid); }
.field label .req { color: var(--fg-dim); }
.field input, .field select, .field textarea {
  width: 100%; padding: 13px 15px;
  font: inherit; font-size: .95rem; color: var(--fg);
  background: var(--bone); border: 1px solid transparent; border-radius: var(--r);
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; background: var(--paper); border-color: var(--accent);
}
.field input[aria-invalid='true'], .field textarea[aria-invalid='true'], .field select[aria-invalid='true'] {
  border-color: #c0433c; background: #c0433c0a;
}
.form-note { margin: 0; font-size: .88rem; color: var(--fg-mid); min-height: 1.2em; }
.form-note.is-ok { color: var(--ink); }
.form-note.is-err { color: #a8342d; }
.form .btn { justify-self: start; }

/* ---------------------------------------------------------------------------
   Clinic directory — Find a Cosmetician
   ---------------------------------------------------------------------------
   Utility furniture, so it borrows rather than invents: the two selectors are
   `.field` from the contact form, and a listing is a plain white card on the
   `tone-paper` band. No accent anywhere — a directory has no primary action,
   and per the palette rule a state with nothing real to colour reads through
   weight and rule, not hue. The only colour on the page is the focus ring the
   selects already inherit.
   -------------------------------------------------------------------------- */
.dir { margin-top: clamp(28px, 3.4vw, 44px); }

.dir-controls {
  display: grid; gap: 16px; align-items: end;
  padding: clamp(20px, 2.4vw, 28px);
  background: var(--bone-2); border: 1px solid var(--rule); border-radius: var(--r-lg);
}
@media (min-width: 720px) {
  .dir-controls { grid-template-columns: 1fr 1fr auto; gap: 20px 24px; }
}
.dir-controls .field select { background: var(--paper); border-color: var(--rule-2); }
.dir-controls .field select:disabled { color: var(--fg-dim); background: var(--bone); }

.dir-count {
  margin: 0; font-size: .9rem; color: var(--fg-mid);
  /* tabular so the number does not shift the line as the filter changes */
  font-variant-numeric: tabular-nums;
}
.dir-count b { font-weight: 500; color: var(--ink); }

/* auto-fit rather than a fixed column count: the list runs from one card to
   nearly three hundred and should not leave a lone card stretched across the
   full width. */
.dir-list {
  display: grid; gap: 14px; margin-top: clamp(22px, 2.6vw, 32px);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
}
.dir-card {
  padding: 20px 22px;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r);
  box-shadow: var(--sh-1);
}
.dir-card h3 { margin: 0 0 .35em; font-size: 1rem; font-weight: 500; letter-spacing: -.01em; }
.dir-where {
  margin: 0 0 .6em; font-size: .74rem; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-dim);
}
.dir-addr { margin: 0 0 .7em; font-size: .88rem; line-height: 1.55; color: var(--fg-mid); }
.dir-links { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 0; font-size: .86rem; }
.dir-links a { color: var(--ink); border-block-end: 1px solid var(--rule-2); }

/* The one card that isn't a clinic listing — an aggregate count for a country
   shown without individual contact details. See AGGREGATE in site.js and
   aggregateOnly in directory.mjs. Spans the row rather than sitting cramped
   into a 300px grid cell like a normal card. */
.dir-card-aggregate {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px;
  padding: 24px 26px;
}
.dir-card-aggregate p { margin: 0; max-width: 60ch; font-size: .92rem; line-height: 1.6; color: var(--fg-mid); }
.dir-card-aggregate .btn { flex: 0 0 auto; }
.dir-links a:hover { border-block-end-color: var(--ink); }
.dir-links:empty { display: none; }

.dir-empty { margin: clamp(22px, 2.6vw, 32px) 0 0; color: var(--fg-mid); }
.dir-missing { margin: clamp(28px, 3vw, 40px) 0 0; font-size: .92rem; color: var(--fg-mid); }
.dir-missing a { font-weight: 500; color: var(--ink); border-block-end: 1px solid var(--rule-2); }

/* Was a full purple panel beside the contact form — the single largest block of
   the accent anywhere on the site. Neutral card, hairline rule, same job. */
.aside-card {
  padding: clamp(24px, 2.8vw, 34px);
  background: var(--bone-2); border: 1px solid var(--rule); border-radius: var(--r-xl);
}
.aside-card h2 {
  margin: 0 0 .5em; font-family: var(--serif); font-size: 1.5rem;
  font-weight: 900; letter-spacing: -.02em;
}
.aside-mail {
  display: inline-block; margin: .4em 0 1em;
  font-size: 1.05rem; font-weight: 500; color: var(--ink);
  border-block-end: 1px solid var(--rule-2);
}
.aside-card p { font-size: .92rem; color: var(--fg-mid); }

.who { display: grid; gap: 22px; margin-top: 2.2em; }
.who h3 { margin: 0 0 .3em; font-size: .96rem; font-weight: 500; }
.who p { margin: 0; font-size: .9rem; color: var(--fg-mid); }

/* ---------------------------------------------------------------- footer */

.foot { background: var(--ink); color: var(--on-ink); padding-block: clamp(52px, 6vw, 84px) 28px; }
.foot-in {
  display: grid; gap: clamp(30px, 4vw, 52px);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
@media (min-width: 980px) { .foot-in { grid-template-columns: 1.6fr 1fr 1fr 1.1fr; } }
.foot-brand img { width: 140px; height: auto; }
.foot-tag {
  margin: 1em 0 .8em; font-size: .74rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase; color: var(--on-ink-mid);
}
.foot-blurb { font-size: .89rem; color: var(--on-ink-mid); max-width: 42ch; }
.foot-meta { margin: 0; font-size: .84rem; color: var(--on-ink-mid); }
.foot-meta a { color: var(--on-ink); border-block-end: 1px solid #ffffff33; }
.foot-meta a:hover { border-color: #ffffff99; color: #fff; }
.foot-h {
  margin: 0 0 1.1em; font-size: .7rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--on-ink-mid);
}
.foot-col li { margin-bottom: .6em; font-size: .9rem; }
.foot-col a:hover { color: #fff; }
.foot-family { margin: 1.4em 0 0; font-size: .84rem; color: var(--on-ink-mid); max-width: 32ch; }
/* Purple here is deliberate and is one of the four places it survives: these two
   links ARE the SYNOIA / BDR Group brands, so the hue is standing for something. */
.foot-family a { color: var(--accent-lit); border-block-end: 1px solid #9a67c450; }
/* The WISHtoGo mark as the link itself. A bordered chip rather than a filled
   button: this is a sideways link to a sibling product, not an action, and the
   footer should not compete with the page's own CTA. The artwork is white, so
   hover reads through opacity and the rule — no hue, per the accent rule. */
.foot-togo {
  display: inline-flex; align-items: center; gap: 12px;
  margin-top: 1.1em; padding: 9px 15px;
  border: 1px solid var(--rule-on-ink); border-radius: 999px;
  transition: border-color .25s var(--ease), background-color .25s var(--ease);
}
.foot-togo img { display: block; width: 110px; height: auto; opacity: .82; transition: opacity .25s var(--ease); }
.foot-togo-u {
  font-size: .72rem; font-weight: 500; letter-spacing: .1em; color: var(--on-ink-mid);
  transition: color .25s var(--ease);
}
.foot-togo:hover { border-color: #ffffff45; background: #ffffff0a; }
.foot-togo:hover img { opacity: 1; }
.foot-togo:hover .foot-togo-u { color: #fff; }
.foot-base {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 14px; margin-top: clamp(38px, 5vw, 60px); padding-top: 22px;
  border-top: 1px solid var(--rule-on-ink);
  font-size: .82rem; color: var(--on-ink-mid);
}
.foot-base p { margin: 0; }
.foot-top:hover { color: #fff; }

/* ------------------------------------------------------------------- 404 */

.p-404 main { display: grid; place-items: center; min-height: 70vh; text-align: center; }

/* ---------------------------------------------------------- clinic directory
 * Less top padding than a normal .sec. This is the first thing under the hero
 * on a page whose entire purpose is the lookup tool below, and the standard
 * var(--sec-y) pushed the country selector and the first cards past the fold --
 * which defeats resolving the visitor's country automatically, because they
 * still see nothing. See the note in pages.mjs where the second heading was
 * removed for the rest of that budget. */
.sec-dir { padding-block-start: clamp(20px, 2.5vw, 32px); }

/* The "call ahead to check availability" note, now printed AFTER the results
 * rather than in front of them: it is advice about what you are looking at, so
 * it reads as a footnote, not as a lede.
 *
 * The Hebrew sibling dropped its version of this paragraph entirely on review;
 * here it was kept but the technology-head caveat was removed from it (Lee,
 * 2026-09-09 -- the heads are not something to raise on this page in either
 * language). What remains is only "call ahead", which is true of any
 * third-party business we do not operate. */
.dir-note {
    margin-block-start: clamp(28px, 3.5vw, 44px);
    font-size: 0.95rem;
    opacity: 0.85;
}

/* A distributor shown in place of the card list, for a country where WISHpro is
 * sold but no room is published. 32 of the 43 countries in the selector are in
 * that state, so this is the common answer on this page, not a rare one. */
.dir-card-distributor { grid-column: 1 / -1; }
.dir-card-distributor p:first-child { font-size: 1.05rem; margin: 0 0 6px; }
.dir-card-distributor .btn { margin-top: 14px; }

/* The B2B line under the cards, for a country that has both. Quiet on purpose:
 * it is for the reader who owns a room, not the one looking for a treatment. */
.dir-trade {
    margin-block-start: clamp(20px, 2.5vw, 32px);
    font-size: 0.95rem;
    opacity: 0.75;
}

/* ------------------------------------------------- the territory list (Global Reach)
 * Forty markets, alphabetical, one cell each. A hairline grid rather than forty
 * cards: the cells are rows of one list, not forty separate objects, and giving
 * each a border and a radius would say otherwise. The 1px gap over a ruled
 * background draws every divider with no per-cell borders to collide.
 *
 * auto-fit at 268px so it lands on four columns on a desktop and one on a phone
 * without a media query -- and one column is the point on a phone, which is why
 * this shape was chosen over the five-column table considered alongside it. */
.mkt-grid {
    display: grid;
    gap: 1px;
    background: var(--rule-2);
    grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
    border: 1px solid var(--rule-2);
    border-radius: 10px;
    overflow: hidden;
}
.mkt-cell { background: var(--paper); padding: 14px 16px; }
.mkt-country { margin: 0; font-size: 0.92rem; font-weight: 700; color: var(--fg); }
.mkt-co { margin: 1px 0 0; font-size: 0.79rem; color: var(--fg-dim); }
.mkt-links { margin: 5px 0 0; font-size: 0.79rem; }
/* Phone numbers get tabular figures so a column of them reads as a column. */
.mkt-num { font-variant-numeric: tabular-nums; }
.mkt-none { color: var(--fg-dim); font-style: italic; }

/* The distributor's own contact, inside the referral card. Tabular figures on
 * the number so a stack of them lines up; the row is the point of the card, so
 * it is not dimmed the way a footnote would be. */
.dir-reach { margin: 6px 0 0; font-size: 0.9rem; }
.dir-reach a { color: var(--accent); }
.dir-num { font-variant-numeric: tabular-nums; }
