/* ============================================================
   KOTIVA™ — Design System v2.0
   Three-theme CSS architecture
   [data-theme="ritual"]   — KOTIVA white (default)
   [data-theme="editorial"]— KOTIVA purple photographic sections
   [data-theme="clinical"] — White / science (KOTIVA blue accent)
   ============================================================ */

/* FONTS */
@font-face {
  font-family: 'FuturaNow';
  src: url('../fonts/FuturaNowVar-Roman.woff2?v=sub01') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: 'Manus';
  src: url('../fonts/Manus.woff2?v=sub01') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'MyriadPro';
  src: url('../fonts/MyriadPro-Regular.woff2?v=sub01') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/Montserrat-VariableFont_wght_25.woff2?v=sub01') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}

/* GLOBAL TOKENS */
:root {
  --font-display: 'FuturaNow', 'Futura', 'Century Gothic', sans-serif;
  --font-script: 'Manus', cursive;
  --font-body: 'MyriadPro', 'Myriad Pro', Georgia, serif;
  --font-ui: 'Montserrat', sans-serif;
  --section-pad: clamp(80px, 10vw, 160px);
  --container-max: 1380px;
  --container-pad: clamp(24px, 4vw, 80px);
  --radius-pill: 100px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --nav-h: 72px;
  --transition: 0.3s ease;
  --transition-slow: 0.6s ease;

  /* ── KOTIVA official palette (Brand Guidelines, Amendment 0) ── */
  --k-white:      #FFFFFF;
  --k-black:      #231F20;
  --k-blue-light: #8AB7E9;
  --k-blue:       #005DBA;
  --k-purple:     #6A3277;
  --k-red:        #D7282F;
  --k-lilac:      #D39DD8;
  --k-green:      #004539;
  --k-orange:     #EC7725;
  --k-grey-blue:  #C0CEDB;

  /* ── Legacy aliases (about.html / contact.html / older pages) ── */
  --font-logo: 'Montserrat', sans-serif;
  --gap-section: clamp(80px, 10vw, 160px);
  --off-white: #FFFFFF;
  --black: #231F20;
  --bronze: #8AB7E9;
  --cream: #FFFFFF;
  --muted: rgba(35,31,32,0.62);
  --border-color: rgba(35,31,32,0.12);
  --font-sans: 'Montserrat', sans-serif;
  --font-serif: 'MyriadPro', Georgia, serif;
}

/* SKIP LINK (accessibility) */
.skip-link {
  position: absolute;
  top: -100%;
  left: 16px;
  padding: 12px 20px;
  background: #005DBA;
  /* K34 intent kept: the skip link is the first control a keyboard or screen-reader user meets on
     all 36 pages. It is theme-explicit (brief §4.5) rather than derived from --accent-deep, which
     resolves to white on dark surfaces. Light: white on KOTIVA blue. Editorial / dark mode: below. */
  color: #FFFFFF;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  z-index: 9999;
  border-radius: var(--radius-sm);
  transition: top 0.2s;
}
.skip-link:focus { top: 16px; }
[data-theme="editorial"] .skip-link,
html[data-mode="dark"] .skip-link { background: #FFFFFF; color: #231F20; }

/* THEME: RITUAL — default (KOTIVA white) */
[data-theme="ritual"], html {
  --bg:           #FFFFFF;
  --bg-alt:       rgba(138,183,233,0.18);
  --bg-card:      rgba(138,183,233,0.10);
  --fg:           #231F20;
  --fg-mid:       rgba(35,31,32,0.72);
  --fg-dim:       rgba(35,31,32,0.62);
  --accent:       #8AB7E9;
  --accent-light: #8AB7E9;
  --accent-deep:  #005DBA; /* legacy token name: the high-contrast interaction colour, not a "darker accent" */
  /* --accent-text (K12): the accent for TEXT. #8AB7E9 is never text on a light surface (brief §2.1),
     so every text role resolves to KOTIVA blue instead. */
  --accent-text:  #005DBA;
  --border:       rgba(35,31,32,0.12);
  --border-strong:rgba(35,31,32,0.30);
  --script:       #D7282F; /* KOTIVA red — handwritten/script typography in every theme */
  --shadow:       0 8px 32px rgba(35,31,32,0.08);
  --shadow-hover: 0 16px 48px rgba(35,31,32,0.14);
}

/* THEME: EDITORIAL — photographic sections (KOTIVA purple, Amendment 0 mockup) */
[data-theme="editorial"] {
  --bg:           #6A3277;
  --bg-alt:       #6A3277;
  --bg-card:      rgba(255,255,255,0.07);
  --fg:           #FFFFFF;
  --fg-mid:       rgba(255,255,255,0.78);
  --fg-dim:       rgba(255,255,255,0.64);
  --accent:       #8AB7E9;
  --accent-light: #8AB7E9;
  --accent-deep:  #FFFFFF; /* legacy token: the high-contrast interaction colour on this dark surface */
  --accent-text:  #FFFFFF; /* K12 + migration: #8AB7E9 measured 4.29:1 on #6A3277 (< 4.5:1 for small text), so text roles take white here */
  --border:       rgba(255,255,255,0.18);
  --border-strong:rgba(255,255,255,0.40);
  --script:       #D7282F; /* KOTIVA red in every theme — see docs/COLOUR-MIGRATION.md (script on purple) */
  --shadow:       0 8px 32px rgba(0,0,0,0.30);
  --shadow-hover: 0 16px 48px rgba(0,0,0,0.45);
}

/* THEME: EDITORIAL-BG-WHITE — editorial layout on a white surface (dark ink, KOTIVA blue text accent) */
[data-theme="editorial-bg-white"] {
  --bg:           #FFFFFF;
  --bg-alt:       rgba(138,183,233,0.18);
  --bg-card:      rgba(138,183,233,0.10);
  --fg:           #231F20;
  --fg-mid:       rgba(35,31,32,0.72);
  --fg-dim:       rgba(35,31,32,0.62);
  --accent:       #8AB7E9;
  --accent-light: #8AB7E9;
  --accent-deep:  #005DBA;
  --accent-text:  #005DBA; /* #8AB7E9 is never text on a light surface (brief §2.1) */
  --border:       rgba(35,31,32,0.12);
  --border-strong:rgba(35,31,32,0.30);
  --script:       #D7282F;
  --shadow:       0 8px 32px rgba(35,31,32,0.08);
  --shadow-hover: 0 16px 48px rgba(35,31,32,0.14);
  background: var(--bg);
  color: var(--fg);
}
[data-theme="editorial-bg-white"] .credential-badge {
  border-color: var(--border-strong);
  color: var(--fg-mid);
}
[data-theme="editorial-bg-white"] .credential-badge:hover {
  border-color: var(--accent-text);
  color: var(--accent-text);
}

/* THEME: CLINICAL — white science */
[data-theme="clinical"] {
  --bg:           #FFFFFF;
  --bg-alt:       rgba(138,183,233,0.18);
  --bg-card:      rgba(138,183,233,0.10);
  --fg:           #231F20;
  --fg-mid:       rgba(35,31,32,0.72);
  --fg-dim:       rgba(35,31,32,0.62);
  --accent:       #005DBA;
  --accent-light: #005DBA;
  --accent-deep:  #005DBA;
  --accent-text:  #005DBA;
  --border:       rgba(0,93,186,0.15);
  --border-strong:rgba(0,93,186,0.40);
  --script:       #D7282F; /* script is KOTIVA red in every theme */
  --shadow:       0 8px 32px rgba(35,31,32,0.06);
  --shadow-hover: 0 16px 48px rgba(35,31,32,0.12);
}

/* RESET & BASE */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.7;
  color: var(--fg);
  background: var(--bg);
  overflow-x: hidden;
  overflow-x: clip;
}

/* Film grain overlay — luxury texture, perceivable warmth */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  opacity: 0.032;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 200px;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { cursor: pointer; border: none; background: none; font: inherit; }
ul, ol { list-style: none; }
input, textarea, select { font: inherit; }

/* LAYOUT */
.container {
  max-width: var(--container-max);
  padding: 0 var(--container-pad);
  margin: 0 auto;
}
.section-pad { padding: var(--section-pad) 0; }
.section-pad-sm { padding: clamp(48px, 6vw, 96px) 0; }

/* TYPOGRAPHY */
.t-eyebrow {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-text); /* K12: --accent-deep measured 4.26:1 on --bg-alt — just under AA. */
}
.t-display {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.0;
}
.t-display-xl { font-size: clamp(52px, 8vw, 112px); }
.t-display-lg { font-size: clamp(40px, 5.5vw, 80px); }
.t-display-md { font-size: clamp(28px, 3.5vw, 52px); }
.t-display-sm { font-size: clamp(20px, 2.5vw, 36px); }
.t-title, .t-headline { color: var(--fg); }
.t-script {
  font-family: var(--font-script);
  font-size: clamp(32px, 4vw, 60px);
  color: var(--script);
  line-height: 1.2;
  font-weight: 400;
  font-style: italic;
}
.t-body { font-family: var(--font-body); font-size: clamp(14px, 1.1vw, 17px); line-height: 1.75; color: var(--fg-mid); }
.t-ui { font-family: var(--font-ui); font-weight: 600; letter-spacing: 0.04em; }

/* BUTTONS */
.btn {
  display: inline-flex;
  align-items: center;
  /* Centred, not start-aligned: .btn also rides on <button>, and a button
     stretched by its parent would otherwise hug its left edge. */
  justify-content: center;
  text-align: center;
  gap: 8px;
  padding: 14px 32px;
  /* A transparent hairline on the base so a filled .btn and an outlined one
     measure the same height, instead of differing by the outline's 3px. */
  border: 1.5px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
  min-height: 48px;
}
.btn:focus-visible { outline: 2px solid var(--accent-deep); outline-offset: 3px; }
.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

/* PRIMARY — the single solid, unmissable action in a view: add to cart, go to
   checkout, place order. Ink fill, page-background text.
   Hover resolves to KOTIVA blue literally rather than through --accent-deep,
   which flips to #FFFFFF on dark and editorial surfaces and would leave the
   hover state indistinguishable from the resting one. */
.btn-primary {
  background: var(--fg);
  color: var(--bg);
  border-color: var(--fg);
}
.btn-primary:hover:not([disabled]) {
  background: var(--k-blue);
  color: var(--k-white);
  border-color: var(--k-blue);
  transform: translateY(-1px);
}
.btn-gold {
  background: var(--accent);
  color: #231F20; /* dark ink on the accent fill — DEC-161 */
}
/* clinical theme accent is blue, not gold: keep light text there (defensive — clinical unused today) */
[data-theme="clinical"] .btn-gold { color: #FFFFFF; }
.btn-gold:hover { background: var(--accent-deep); color: var(--bg); transform: translateY(-1px); }
/* Primary button on purple editorial surfaces: white pill, black text (Amendment 0 mockup, brief §4.2). */
[data-theme="editorial"] .btn-gold { background: #FFFFFF; color: #231F20; border-color: #FFFFFF; }
[data-theme="editorial"] .btn-gold:hover { background: var(--accent); color: #231F20; }
.btn-outline {
  border: 1.5px solid var(--fg);
  color: var(--fg);
  background: transparent;
}
.btn-outline:hover { border-color: var(--accent); color: var(--accent-text); }
.btn-outline-light {
  border: 1.5px solid rgba(255,255,255,0.40);
  color: var(--fg);
  background: transparent;
}
.btn-outline-light:hover { border-color: var(--accent); color: var(--accent-text); }
.btn-text {
  padding: 0;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-deep);
  border-bottom: 1px solid transparent;
  border-radius: 0;
  min-height: auto;
}
.btn-text:hover { border-color: var(--accent); }
.btn-sm { padding: 10px 24px; font-size: 11px; min-height: 40px; }

/* NAVIGATION */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--nav-h);
  z-index: 1000;
  display: flex;
  align-items: center;
  transition: background var(--transition), border-color var(--transition), box-shadow var(--transition), transform 0.35s ease;
}
.nav.transparent {
  background: transparent;
  border-bottom: 1px solid transparent;
}
.nav.scrolled {
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 2px 20px rgba(35,31,32,0.06);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
.nav.nav-hidden {
  transform: translateY(-100%);
  pointer-events: none;
}
.nav-inner {
  display: flex;
  align-items: center;
  gap: 40px;
  width: 100%;
  max-width: var(--container-max);
  padding: 0 var(--container-pad);
  margin: 0 auto;
}
.nav-logo { flex-shrink: 0; display: flex; align-items: center; }
.nav-logo img, .nav-logo svg { height: 28px; width: auto; }
.nav-logo-text {
  font-family: var(--font-ui);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #231F20;
}
.nav-logo-text.light { color: #FFFFFF; }
.nav-links {
  display: flex;
  align-items: center;
  gap: 32px;
  flex: 1;
  justify-content: center;
}
.nav-link {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #FFFFFF; /* always white when transparent — safe over the dark hero */
  transition: color var(--transition);
}
.nav-link:hover { color: var(--accent); }
.nav.scrolled .nav-link { color: var(--fg-mid); }
.nav.scrolled .nav-link:hover { color: var(--accent-text); }
.nav-right { display: flex; align-items: center; gap: 16px; margin-left: auto; }
.nav-theme-btn {
  width: 36px; height: 36px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid rgba(255,255,255,0.40);
  color: #FFFFFF;
  font-size: 16px;
  transition: all var(--transition);
  background: transparent;
}
.nav.scrolled .nav-theme-btn {
  border-color: var(--border);
  color: var(--fg);
}
.nav-theme-btn:hover { border-color: var(--accent); color: var(--accent); }
.nav-hamburger {
  display: none;
  flex-direction: column;
  gap: 5px;
  width: 36px; height: 36px;
  align-items: center;
  justify-content: center;
}
.nav-hamburger span {
  display: block;
  width: 22px; height: 1.5px;
  background: #FFFFFF;
  transition: all var(--transition);
}
.nav.scrolled .nav-hamburger span { background: var(--fg); }
.nav-hamburger.open span:nth-child(1) { transform: rotate(45deg) translate(4.5px, 4.5px); }
.nav-hamburger.open span:nth-child(2) { opacity: 0; }
.nav-hamburger.open span:nth-child(3) { transform: rotate(-45deg) translate(4.5px, -4.5px); }

/* MOBILE OVERLAY */
.nav-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 40px;
  opacity: 0;
  transform: translateY(-16px);
  pointer-events: none;
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.nav-overlay.open { opacity: 1; pointer-events: all; transform: translateY(0); }
.nav-overlay .nav-link {
  font-size: 28px;
  color: var(--fg);
  font-weight: 700;
  letter-spacing: 0.06em;
}
.nav-overlay .nav-link:hover { color: var(--accent-text); }

/* HERO */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--bg);
}
.hero-bg {
  position: absolute;
  inset: 0;
  /* Atmospheric editorial gradient — suggests warm skin photography + MENA golden light */
  background:
    radial-gradient(ellipse at 72% 20%, rgba(106,50,119,0.50) 0%, transparent 52%),
    radial-gradient(ellipse at 18% 85%, rgba(106,50,119,0.40) 0%, transparent 48%),
    radial-gradient(ellipse at 55% 55%, rgba(106,50,119,0.70) 0%, transparent 65%),
    linear-gradient(160deg, #6A3277 0%, #6A3277 25%, #6A3277 55%, #6A3277 80%, #6A3277 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-size: 11px;
  color: rgba(255,255,255,0.07);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-align: center;
}
.hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(106,50,119,0.85) 0%, rgba(106,50,119,0.3) 50%, rgba(106,50,119,0.1) 100%);
}
.hero-content {
  position: relative;
  z-index: 2;
  padding: clamp(60px, 8vw, 120px) var(--container-pad);
  max-width: var(--container-max);
  margin: 0 auto;
  width: 100%;
  padding-bottom: clamp(80px, 10vw, 140px);
}
.hero-tagline {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-deep);
  margin-bottom: 20px;
}
.hero-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(60px, 10vw, 140px);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 0.95;
  color: #FFFFFF;
  margin-bottom: 24px;
  max-width: 900px;
  text-shadow: 0 4px 32px rgba(35,31,32,0.55), 0 1px 8px rgba(35,31,32,0.35);
}
.hero-sub {
  font-family: var(--font-body);
  font-size: clamp(15px, 1.3vw, 18px);
  color: rgba(255,255,255,0.78);
  margin-bottom: 40px;
  max-width: 480px;
}
.hero-ctas { display: flex; gap: 16px; flex-wrap: wrap; }
.hero-scroll {
  position: absolute;
  bottom: 32px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: rgba(255,255,255,0.64);
  font-family: var(--font-ui);
  font-size: 10px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  animation: scrollBounce 2s ease-in-out infinite;
}
.hero-scroll svg { width: 20px; height: 20px; }
@keyframes scrollBounce { 0%, 100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(6px); } }

/* TRUST BAR */
.trust-bar {
  background: var(--bg-alt);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 32px 0;
}
.trust-bar-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
.trust-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 32px;
  border-right: 1px solid var(--border);
}
.trust-item:last-child { border-right: none; }
.trust-icon {
  width: 36px; height: 36px;
  flex-shrink: 0;
  color: var(--accent-deep);
  display: flex;
  align-items: center;
  justify-content: center;
}
.trust-icon svg { width: 24px; height: 24px; stroke: var(--accent); fill: none; stroke-width: 1.5; }
.trust-label {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-deep);
  line-height: 1.3;
}
.trust-sub {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--fg-mid); /* --fg-dim measured 4.43:1 on --bg-alt */
  margin-top: 2px;
}

/* BRAND PHILOSOPHY */
.philosophy-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(48px, 6vw, 96px);
  align-items: center;
}
.philosophy-left { display: flex; flex-direction: column; gap: 16px; }
.philosophy-right { display: flex; flex-direction: column; gap: 36px; }
.philosophy-value { border-top: 1px solid var(--border); padding-top: 24px; }
.philosophy-value h3 {  /* K36: was h4 — the three value blocks sat directly under the
   page <h1> with no h2 between them, a two-level outline skip. */
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg);
  margin-bottom: 8px;
}
.philosophy-value p { font-size: 14px; color: var(--fg-mid); }

/* CATEGORY GRID */
.category-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
}
.category-card {
  position: relative;
  aspect-ratio: 3/4;
  overflow: hidden;
  cursor: pointer;
  background: var(--bg-alt);
}
.category-card-bg {
  position: absolute; inset: 0;
  background: var(--bg-alt);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; color: var(--fg-dim);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: transform var(--transition-slow);
}
.category-card:hover .category-card-bg { transform: scale(1.04); }
.category-card-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(35,31,32,0.75) 0%, transparent 50%);
}
.category-card-info {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: 28px;
  color: #FFFFFF;
}
.category-card-name {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.1;
}
.category-card-count {
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: rgba(255,255,255,0.78);
  margin-top: 4px;
  text-transform: uppercase;
}
.category-card-arrow {
  position: absolute;
  top: 20px; right: 20px;
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.40);
  display: flex; align-items: center; justify-content: center;
  color: #FFFFFF;
  font-size: 16px;
  transition: all var(--transition);
}
.category-card:hover .category-card-arrow { background: var(--accent); border-color: var(--accent); }

/* PRODUCT CARDS */
.product-card {
  /* --bg-card is translucent; composite it over the page ground so grid separators (var(--border))
     behind the card do not tint the whole card surface. */
  background: linear-gradient(var(--bg-card), var(--bg-card)), var(--bg);
  display: flex;
  flex-direction: column;
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
  border: 1px solid var(--border);
  cursor: pointer;
}
.product-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-hover); border-color: var(--border-strong); }
.product-card-img {
  aspect-ratio: 1 / 1;
  position: relative;
  overflow: hidden;
  /* Matched to .bs-card-img — warm cream ground, see the note there. */
  background: radial-gradient(ellipse 82% 66% at 50% 38%, #FFFFFF 0%, #FFFFFF 68%, #FFFFFF 100%);
  transition: background var(--transition);
}
.product-card:hover .product-card-img { background: radial-gradient(ellipse 82% 66% at 50% 38%, #FFFFFF 0%, #FFFFFF 68%, #FFFFFF 100%); }
/* Safari/WebKit fix: replaced elements (img) resolve width:auto using intrinsic
   dimensions, not opposing insets. Use explicit calc() to force the inset size. */
.product-card-img img {
  position: absolute;
  top: 28px;
  left: 28px;
  width: calc(100% - 56px);
  height: calc(100% - 56px);
  object-fit: contain;
  object-position: center center;
  transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1);
}
.product-card:hover .product-card-img img { transform: scale(1.04); }
.product-card-body { padding: 20px 20px 24px; flex: 1; display: flex; flex-direction: column; gap: 10px; }
.product-card-name {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg);
  line-height: 1.2;
}
.product-card-desc { font-size: 13px; color: var(--fg-dim); line-height: 1.5; }
.product-card-price { font-family: var(--font-display); font-size: 13px; font-weight: 700; letter-spacing: 0.04em; color: var(--fg); margin-top: 8px; }
.product-card-price small { font-size: 8px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--fg-dim); margin-left: 6px; }
.product-card-footer { display: flex; align-items: center; justify-content: space-between; margin-top: auto; }
.badge-concern {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-deep);
  border: 1px solid var(--border-strong);
  padding: 4px 12px;
  border-radius: var(--radius-pill);
}
.badge-doctor {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--accent);
  color: #231F20; /* dark ink on the accent fill — matches .btn-gold's DEC-161 fix */
  padding: 4px 12px;
  border-radius: var(--radius-pill);
}

/* PRODUCT GRID */
.product-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--border);
}
.product-grid .product-card { border: none; }

/* CAROUSEL */
.carousel-wrap {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  cursor: grab;
  user-select: none;
  scrollbar-width: none;           /* Firefox */
  -ms-overflow-style: none;        /* IE */
}
.carousel-wrap::-webkit-scrollbar { display: none; } /* Chrome/Safari */
.carousel-wrap:active { cursor: grabbing; }
.carousel-track {
  display: flex;
  gap: 2px;
  will-change: transform;
  padding-bottom: 4px;
}
.carousel-track .product-card {
  min-width: 280px;
  flex-shrink: 0;
  border: 1px solid var(--border);
  scroll-snap-align: start;
}

/* FEATURED SECTION HEADER */
.section-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: clamp(40px, 5vw, 64px);
}
.section-header-left { max-width: 560px; }

/* DOCTOR APPROVED */
.doctor-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 560px;
} 
.doctor-content {
  padding: clamp(60px, 8vw, 120px) clamp(40px, 5vw, 80px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 28px;
}
.doctor-image {
  background: var(--bg-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: var(--fg-dim);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  min-height: 480px;
}
.credential-badges { display: flex; gap: 12px; flex-wrap: wrap; }
.credential-badge {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 1.5px solid var(--border-strong);
  color: var(--fg);
  padding: 8px 16px;
  border-radius: var(--radius-pill);
}

/* ROUTINE FINDER CTA */
.routine-cta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 520px;
}
.routine-cta-image {
  background: #6A3277;
  position: relative;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: var(--fg-dim);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.routine-cta-content {
  padding: clamp(60px, 8vw, 120px) clamp(40px, 5vw, 80px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 24px;
}

/* INGREDIENT SPOTLIGHT */
.ingredient-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
.ingredient-card {
  padding: clamp(36px, 4vw, 56px);
  background: var(--bg-card);
  display: flex;
  flex-direction: column;
  gap: 16px;
  border: 1px solid var(--border);
}
.ingredient-name {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg);
}
.ingredient-benefit {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-text); /* K12 */
  letter-spacing: 0.04em;
}
.ingredient-desc { font-size: 14px; color: var(--fg-mid); line-height: 1.65; }

/* Baseline alignment across the three ingredient columns.
   Measured defect: the names wrap to different line counts (NIACINAMIDE 1 line,
   HYALURONIC ACID / RETINYL PALMITATE 2), so benefit labels landed at y 93/124/124
   and the Learn More links at 187/219/219. This adopts the pattern the Kotiva
   Standard section already uses one section later: reserve the name's tallest
   case, and pin the link to the card foot regardless of description length. */
.ingredient-name { line-height: 1.25; min-height: 2.5em; }
.ingredient-card .btn-text { margin-top: auto; }

/* TESTIMONIALS */
.testimonial-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
.testimonial-card {
  padding: clamp(36px, 4vw, 56px);
  background: var(--bg-card);
  display: flex;
  flex-direction: column;
  gap: 20px;
  border: 1px solid var(--border);
  position: relative;
  overflow: hidden;
}
.testimonial-card::before {
  content: '\201C';
  position: absolute;
  top: -8px;
  left: 28px;
  font-family: 'Georgia', serif;
  font-size: 100px;
  line-height: 1;
  color: var(--accent);
  opacity: 0.12;
  pointer-events: none;
  user-select: none;
}
.testimonial-stars { color: var(--accent); letter-spacing: 4px; font-size: 14px; }
.testimonial-quote {
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.7;
  color: var(--fg-mid);
  font-style: italic;
  position: relative;
  padding-top: 16px;
}
.testimonial-quote::before {
  content: '\201C';
  font-family: var(--font-display);
  font-size: 72px;
  color: var(--accent);
  opacity: 0.18;
  line-height: 0;
  position: absolute;
  top: 28px;
  left: -4px;
  font-style: normal;
}
/* Brand-statement variant (2026-08-11, K27). Same card layout, spacing and
   border as the approved component — but the decorative “ glyphs and the
   italic voice are quotation signalling, and the section no longer contains
   quotations. Leaving them would present KOTIVA's own brand statements as
   someone's speech, which is the defect being removed. Additive modifier
   only: the base component is untouched and this is reversible. */
.testimonial-card.is-statement::before { content: none; }
.testimonial-card.is-statement .testimonial-quote { font-style: normal; padding-top: 0; }
.testimonial-card.is-statement .testimonial-quote::before { content: none; }

.testimonial-meta { margin-top: auto; border-top: 1px solid var(--border); padding-top: 20px; }
.testimonial-name {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg);
}
.testimonial-skin { font-size: 12px; color: var(--fg-dim); margin-top: 2px; }

/* INSTAGRAM STRIP */
.ritual-grid {
  display: grid;
  /* K30-C (2026-08-19): 3x2, not 6x1. The six ritual frames are macro studies — droplets,
     prism refraction, a dried rosehip — whose entire value is texture. At the previous
     6-across the tiles rendered 175px on a 1380px container and that texture was not
     legible, which defeats the point of the section. 3 columns renders them ~440px. */
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  max-width: 1040px;
  margin-inline: auto;
}
.ritual-tile {
  aspect-ratio: 1;
  background: var(--bg-alt);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; color: var(--fg-dim);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  padding: 12px;
  overflow: hidden;
  position: relative;
}
/* K33: the hover wash that lived here is REMOVED. These tiles are not links and never were
   (six <div>s, no href) — deliberately, because the section must not imply a routine order
   (routine-model.json marks stepOrder "dem-inferred"/"ratify":true) and there is no per-frame
   destination to send anyone to. A hover state on a non-interactive element is a false
   affordance: it advertises a click that does not exist. Component also renamed from
   .instagram-* — nothing here links to Instagram, there is no handle and no feed, so the name
   promised a social-proof pattern the section does not implement. */

/* NEWSLETTER */
.newsletter-form {
  display: flex;
  gap: 0;
  max-width: 480px;
  margin: 32px auto 0;
}
.newsletter-input {
  flex: 1;
  padding: 14px 24px;
  border: 1.5px solid var(--border-strong);
  border-right: none;
  background: transparent;
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 14px;
  border-radius: var(--radius-pill) 0 0 var(--radius-pill);
  outline: none;
  transition: border-color var(--transition);
}
.newsletter-input::placeholder { color: var(--fg-dim); }
.newsletter-input:focus { border-color: var(--accent-deep); }
.newsletter-form .btn-gold { border-radius: 0 var(--radius-pill) var(--radius-pill) 0; }

/* FOOTER */
.footer {
  background: var(--bg-alt);
  border-top: 1px solid var(--border);
}
.footer-main {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr;
  gap: clamp(32px, 4vw, 64px);
  padding: clamp(60px, 8vw, 96px) 0 clamp(48px, 6vw, 72px);
}
.footer-brand-logo { height: 28px; margin-bottom: 16px; }
.footer-tagline { font-size: 13px; color: var(--fg-mid); line-height: 1.6; max-width: 240px; }
.footer-social { display: flex; gap: 12px; margin-top: 24px; }
.footer-social a,
.footer-social .footer-social-icon {
  width: 36px; height: 36px;
  border: 1px solid var(--border);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px;
  color: var(--fg-mid);
  transition: all var(--transition);
}
.footer-social a:hover { border-color: var(--accent); color: var(--accent); }
/* Pending accounts: visible brand presence, deliberately NOT interactive.
   No href, no pointer, no hover-accent -- so nothing invites a click that
   would go nowhere (the C1-4 defect). Swap span -> a to activate. */
.footer-social .footer-social-icon { opacity: 0.5; cursor: default; }
.footer-social-soon {
  display: block;
  margin-top: 10px;
  font-family: var(--font-display);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-mid); /* --fg-dim measured 4.43:1 on the --bg-alt footer */
}
.footer-col-title {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg);
  margin-bottom: 20px;
}
.footer-links { display: flex; flex-direction: column; gap: 12px; }
.footer-links a {
  font-size: 13px;
  color: var(--fg-mid);
  transition: color var(--transition);
  min-height: 44px;  /* WCAG touch target */
  display: flex; align-items: center;
}
.footer-links a:hover { color: var(--accent-text); }
.footer-bottom {
  border-top: 1px solid var(--border);
  padding: 24px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  color: var(--fg-mid); /* --fg-dim measured 4.43:1 on the --bg-alt footer */
  font-family: var(--font-ui);
  letter-spacing: 0.04em;
}

/* FILTER PILLS */
.filter-pills { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.filter-pill {
  padding: 10px 22px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--border);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-mid);
  background: transparent;
  transition: all var(--transition);
  cursor: pointer;
  min-height: 44px;
}
.filter-pill:hover, .filter-pill.active {
  background: var(--fg);
  color: var(--bg);
  border-color: var(--fg);
}

/* REVEAL ANIMATIONS — premium motion language */
.reveal {
  opacity: 0;
  transform: translateY(36px);
  transition: opacity 0.85s cubic-bezier(0.22,1,0.36,1), transform 0.85s cubic-bezier(0.22,1,0.36,1);
}
.reveal.visible { opacity: 1; transform: translateY(0); }

.reveal-fade { opacity: 0; transition: opacity 1.1s ease; }
.reveal-fade.visible { opacity: 1; }

.reveal-left { opacity: 0; transform: translateX(-48px); transition: opacity 0.85s cubic-bezier(0.22,1,0.36,1), transform 0.85s cubic-bezier(0.22,1,0.36,1); }
.reveal-left.visible { opacity: 1; transform: translateX(0); }

.reveal-right { opacity: 0; transform: translateX(48px); transition: opacity 0.85s cubic-bezier(0.22,1,0.36,1), transform 0.85s cubic-bezier(0.22,1,0.36,1); }
.reveal-right.visible { opacity: 1; transform: translateX(0); }

.reveal-scale { opacity: 0; transform: scale(0.90); transition: opacity 0.85s cubic-bezier(0.22,1,0.36,1), transform 0.85s cubic-bezier(0.22,1,0.36,1); }
.reveal-scale.visible { opacity: 1; transform: scale(1); }

.reveal-clip { clip-path: inset(0 0 100% 0); transition: clip-path 0.9s cubic-bezier(0.77,0,0.18,1); }
.reveal-clip.visible { clip-path: inset(0 0 0% 0); }

.reveal-delay-1 { transition-delay: 0.10s; }
.reveal-delay-2 { transition-delay: 0.20s; }
.reveal-delay-3 { transition-delay: 0.32s; }
.reveal-delay-4 { transition-delay: 0.46s; }
.reveal-delay-5 { transition-delay: 0.62s; }

/* Prevent flash of invisible on editorial dark sections */
[data-theme="editorial"] .reveal,
[data-theme="editorial"] .reveal-fade { }

/* ============================================================
   SCROLL PROGRESS BAR
   ============================================================ */
.scroll-progress-bar {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 0%;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-light) 100%);
  z-index: 10000;
  pointer-events: none;
  will-change: width;
  transition: width 0.06s linear;
}

/* ============================================================
   CUSTOM CURSOR
   ============================================================ */
.k-cursor {
  position: fixed;
  width: 36px; height: 36px;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  pointer-events: none;
  z-index: 9998;
  will-change: transform;
  transition: width 0.28s cubic-bezier(0.22,1,0.36,1),
              height 0.28s cubic-bezier(0.22,1,0.36,1),
              border-color 0.28s ease,
              background 0.28s ease,
              opacity 0.2s ease;
}
.k-cursor.k-cursor--hover {
  width: 56px; height: 56px;
  border-color: var(--accent);
  background: rgba(138,183,233,0.10);
}
.k-cursor-dot {
  position: fixed;
  width: 4px; height: 4px;
  background: var(--accent);
  border-radius: 50%;
  pointer-events: none;
  z-index: 9999;
  will-change: transform;
  transition: opacity 0.2s ease;
}
@media (hover: none) {
  .k-cursor, .k-cursor-dot { display: none !important; }
}

/* ============================================================
   HERO IMAGE PARALLAX CONTAINER
   ============================================================ */
.hero-bg img { will-change: transform; transform: scale(1.06); }

/* ============================================================
   SECTION HOVER ENHANCEMENTS
   ============================================================ */
.category-card {
  transition: transform 0.4s cubic-bezier(0.22,1,0.36,1);
}
.category-card:hover { transform: scale(1.015); }
.category-card-bg {
  transition: transform 0.7s cubic-bezier(0.22,1,0.36,1), filter 0.5s ease;
}
.category-card:hover .category-card-bg {
  transform: scale(1.08);
  filter: brightness(1.10) saturate(1.15);
}
.category-card-info { transition: transform 0.45s cubic-bezier(0.22,1,0.36,1); }
.category-card:hover .category-card-info { transform: translateY(-6px); }

/* product card — subtle glow on hover */
.product-card { will-change: transform; }
.product-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 0 0 0 transparent;
  transition: box-shadow 0.4s ease;
  pointer-events: none;
}
.product-card:hover::after {
  box-shadow: 0 0 0 1.5px rgba(138,183,233,0.25);
}

/* bs-card hover */
.bs-card { will-change: transform; }

/* Ingredient card hover */
.ingredient-card {
  transition: transform 0.4s cubic-bezier(0.22,1,0.36,1), box-shadow 0.4s ease, border-color 0.3s ease;
  cursor: default;
}

/* Trust bar items — stagger-in */
.trust-item { overflow: hidden; }

/* Philosophy values — slide right on reveal */
.philosophy-value { transition: border-color 0.4s ease; }
.philosophy-value:hover { border-color: var(--accent); }

/* Testimonial card hover */
.testimonial-card {
  transition: transform 0.45s cubic-bezier(0.22,1,0.36,1), box-shadow 0.45s ease;
  cursor: default;
}
.testimonial-card:hover {
  transform: translateY(-8px);
  box-shadow: var(--shadow-hover);
}

/* Nav links hover underline */
.nav-link { position: relative; }
.nav-link::after {
  content: '';
  position: absolute;
  bottom: -3px; left: 0; right: 0;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.3s cubic-bezier(0.22,1,0.36,1);
}
.nav-link:hover::after { transform: scaleX(1); transform-origin: left; }
.nav.scrolled .nav-link::after { background: var(--accent); }

/* ============================================================
   LOADING ENTRANCE — removed (DEC-219, 2026-07-06)
   A body-level bodyFadeIn (0.5s + 0.05s delay, fill both) held the
   ENTIRE page at opacity:0 for ~550ms on every load — the measured
   FCP gap vs sos-fire.com. Entrance polish lives in the hero's own
   staggered secondary-element animation (animations.js, K11 soften);
   the page itself must paint the moment HTML+CSS arrive.
   ============================================================ */

/* ============================================================
   SMOOTH SECTION TRANSITION (bg color blend)
   ============================================================ */
[data-theme] { transition: background-color 0.6s ease; }

/* PAGE HERO (non-homepage) */
.page-hero {
  padding-top: calc(var(--nav-h) + clamp(60px, 8vw, 120px));
  padding-bottom: clamp(60px, 8vw, 120px);
  padding-left: var(--container-pad);
  padding-right: var(--container-pad);
}
.page-hero.editorial-bg {
  background: var(--bg);
}

/* ACCORDION */
.accordion-item { border-top: 1px solid var(--border); }
.accordion-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 0;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--fg);
  cursor: pointer;
  text-align: left;
  background: none; border: none;
  transition: color var(--transition);
}
.accordion-trigger:hover { color: var(--accent-text); }
.accordion-trigger .icon { font-size: 20px; flex-shrink: 0; transition: transform var(--transition); }
.accordion-trigger.open .icon { transform: rotate(45deg); }
.accordion-body { display: none; padding-bottom: 20px; font-size: 14px; color: var(--fg-mid); line-height: 1.7; }
.accordion-body.open { display: block; }

/* SHOP HERO HEADER */
.shop-hero {
  min-height: 360px;
  display: flex;
  align-items: flex-end;
  padding: var(--nav-h) 0 0;
  overflow: hidden;
  position: relative;
}
.shop-hero-content {
  position: relative;
  z-index: 2;
  padding: 60px var(--container-pad);
  width: 100%;
  max-width: var(--container-max);
  margin: 0 auto;
}

/* PRODUCT DETAIL */
.product-detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(48px, 6vw, 96px);
  align-items: start;
}
.product-detail-img-wrap {
  background: var(--bg-card);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px;
  aspect-ratio: 1;
  position: sticky;
  top: calc(var(--nav-h) + 24px);
}
.product-detail-img-wrap img { width: 100%; height: 100%; object-fit: contain; }
.breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-dim);
  margin-bottom: 32px;
  flex-wrap: wrap;
}
.breadcrumb a:hover { color: var(--accent-text); }
.breadcrumb span { color: var(--fg-dim); }

/* ROUTINE FINDER STEPS */
.step-cards { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
.step-card {
  background: var(--bg-card);
  border: 2px solid var(--border);
  padding: 28px 20px;
  text-align: center;
  cursor: pointer;
  transition: all var(--transition);
  border-radius: var(--radius-md);
}
.step-card:hover, .step-card.selected { border-color: var(--accent); background: var(--bg-alt); }
.step-card-icon { font-size: 32px; margin-bottom: 12px; }
.step-card-label {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg);
}
.concern-pills { display: flex; flex-wrap: wrap; gap: 10px; }
.concern-pill {
  padding: 10px 20px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--border);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: all var(--transition);
  min-height: 44px;
}
.concern-pill:hover, .concern-pill.selected { background: var(--accent); color: #231F20; border-color: var(--accent); } /* dark ink on the accent fill, matches .btn-gold's DEC-161 fix */

/* JOURNAL */
.article-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
.article-card { background: var(--bg-card); border: 1px solid var(--border); overflow: hidden; cursor: pointer; }
.article-card:hover .article-img { transform: scale(1.04); }
.article-img-wrap { aspect-ratio: 16/10; overflow: hidden; background: var(--bg-alt); }
.article-img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--transition-slow); display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--fg-dim); letter-spacing: 0.06em; text-transform: uppercase; }
.article-body { padding: 28px; display: flex; flex-direction: column; gap: 12px; }
.article-category {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-deep);
}
.article-title {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg);
  line-height: 1.2;
}
.article-excerpt { font-size: 13px; color: var(--fg-mid); line-height: 1.6; }
.article-date { font-family: var(--font-ui); font-size: 11px; color: var(--fg-dim); letter-spacing: 0.06em; }

/* CONTACT */
.contact-grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: clamp(48px, 6vw, 96px); }
.form-group { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }
.form-label { font-family: var(--font-ui); font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-mid); }
.form-control {
  padding: 14px 20px;
  border: 1.5px solid var(--border);
  background: var(--bg-card);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 14px;
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color var(--transition);
  min-height: 48px;
}
.form-control:focus { border-color: var(--accent-deep); }
textarea.form-control { min-height: 140px; resize: vertical; }

/* SCIENCE RESULTS CALLOUT */
.results-bar {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
}
.result-item {
  padding: clamp(36px, 5vw, 64px);
  background: var(--bg-card);
  text-align: center;
  border: 1px solid var(--border);
}
.result-number {
  font-family: var(--font-display);
  font-size: clamp(40px, 5vw, 72px);
  font-weight: 800;
  color: var(--accent-deep);
  letter-spacing: 0.02em;
  line-height: 1;
}
.result-label { font-size: 14px; color: var(--fg-mid); margin-top: 8px; line-height: 1.5; }

/* STEP INDICATOR */
.step-indicator { display: flex; gap: 0; align-items: center; margin-bottom: 48px; }
.step-dot {
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 2px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  color: var(--fg-dim);
  transition: all var(--transition);
}
.step-dot.active { border-color: var(--accent); background: var(--accent); color: #231F20; } /* dark ink on the accent fill, matches DEC-161 */
.step-dot.done { border-color: var(--accent); color: var(--accent-text); }
.step-line { flex: 1; height: 1px; background: var(--border); }
.step-block { display: none; }
.step-block.active { display: block; }

/* UTILITY */
.text-center { text-align: center; }
.text-accent { color: var(--accent-text); }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; }
.mt-32 { margin-top: 32px; }
.mt-48 { margin-top: 48px; }
.mb-8 { margin-bottom: 8px; }
.mb-16 { margin-bottom: 16px; }
.mb-24 { margin-bottom: 24px; }
.mb-32 { margin-bottom: 32px; }
.gap-8 { gap: 8px; }
.gap-16 { gap: 16px; }
.gap-24 { gap: 24px; }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }

/* RESPONSIVE */
@media (max-width: 1024px) {
  .nav-links { display: none; }
  .nav-hamburger { display: flex; }
  .product-grid { grid-template-columns: repeat(3, 1fr); }
  .doctor-section, .routine-cta { grid-template-columns: 1fr; }
  .doctor-image, .routine-cta-image { min-height: 320px; }
  .philosophy-grid { grid-template-columns: 1fr; }
  .product-detail-grid { grid-template-columns: 1fr; }
  .product-detail-img-wrap { position: static; }
  .footer-main { grid-template-columns: 1fr 1fr; gap: 40px; }
  .category-grid { grid-template-columns: repeat(2, 1fr); }
  .step-cards { grid-template-columns: repeat(3, 1fr); }
  .testimonial-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 768px) {
  .nav-right .btn { display: none; } /* CTA hidden on mobile only, visible on tablet */
  .trust-bar-grid { grid-template-columns: repeat(2, 1fr); }
  .trust-item { border-right: none; border-bottom: 1px solid var(--border); padding: 20px; }
  .trust-item:nth-child(odd) { border-right: 1px solid var(--border); }
  .trust-item:last-child, .trust-item:nth-last-child(2) { border-bottom: none; }
  .product-grid { grid-template-columns: repeat(2, 1fr); }
  .ingredient-grid { grid-template-columns: 1fr; }
  .testimonial-grid { grid-template-columns: 1fr; }
  .article-grid { grid-template-columns: repeat(2, 1fr); }
  .results-bar { grid-template-columns: 1fr; }
  .contact-grid { grid-template-columns: 1fr; }
  .footer-main { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; gap: 12px; text-align: center; }
  .footer-main > div:first-child { text-align: center; } /* centre logo on mobile */
  .footer-main > div:first-child .footer-social { justify-content: center; }
  .ritual-grid { grid-template-columns: repeat(3, 1fr); }
  .step-cards { grid-template-columns: repeat(2, 1fr); }
  .category-grid { grid-template-columns: repeat(2, 1fr); }
  .section-header { flex-direction: column; align-items: flex-start; gap: 20px; }
}
@media (max-width: 480px) {
  .hero-ctas { flex-direction: column; }
  .newsletter-form { flex-direction: column; }
  .newsletter-input { border-right: 1.5px solid var(--border-strong); border-bottom: none; border-radius: var(--radius-pill); }
  .newsletter-form .btn-gold { border-radius: var(--radius-pill); }
  .product-grid { grid-template-columns: 1fr 1fr; gap: 1px; }
  .article-grid { grid-template-columns: 1fr; }
  .step-cards { grid-template-columns: repeat(2, 1fr); }
  .ritual-grid { grid-template-columns: repeat(2, 1fr); }
  .category-grid { grid-template-columns: 1fr; }
  .hero-title { font-size: clamp(44px, 13vw, 80px); }
  .hero-script-accent { font-size: clamp(22px, 5vw, 36px); }
}

/* ============================================================
   MARQUEE STRIP
   ============================================================ */
.marquee-strip {
  overflow: hidden;
  background: var(--fg);
  padding: 14px 0;
  position: relative;
}
[data-theme="editorial"] .marquee-strip {
  background: var(--accent);
}
.marquee-track {
  display: flex;
  gap: 0;
  animation: marqueeScroll 28s linear infinite;
  white-space: nowrap;
  width: max-content;
}
.marquee-track:hover { animation-play-state: paused; }
@keyframes marqueeScroll {
  0%   { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}
.marquee-item {
  display: inline-flex;
  align-items: center;
  gap: 20px;
  padding: 0 28px;
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bg);
  flex-shrink: 0;
}
.marquee-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-light);
  flex-shrink: 0;
}
[data-theme="editorial"] .marquee-item { color: var(--fg); }
[data-theme="editorial"] .marquee-dot { background: var(--fg); opacity: 0.4; }

/* ============================================================
   HERO SCRIPT ACCENT
   ============================================================ */
.hero-script-accent {
  font-family: var(--font-script);
  font-size: clamp(24px, 3vw, 42px);
  color: var(--script);
  font-weight: 400;
  font-style: italic;
  line-height: 1.2;
  margin-bottom: 16px;
  opacity: 0.88;
}

/* ============================================================
   CATEGORY CARD — per-category editorial gradients
   ============================================================ */
.category-card[href*="face"] .category-card-bg {
  background: linear-gradient(145deg, var(--bg-alt) 0%, var(--bg-alt) 45%, var(--bg-alt) 100%) !important;
}
.category-card[href*="body"] .category-card-bg {
  background: linear-gradient(145deg, var(--bg-alt) 0%, var(--bg-alt) 50%, var(--bg-alt) 100%) !important;
}
.category-card[href*="serums"] .category-card-bg {
  background: linear-gradient(145deg, var(--bg-alt) 0%, var(--bg-alt) 50%, var(--bg-alt) 100%) !important;
}
.category-card[href*="treatments"] .category-card-bg {
  background: linear-gradient(145deg, var(--bg-alt) 0%, var(--bg-alt) 50%, var(--bg-alt) 100%) !important;
}
.category-card[href*="sunscreen"] .category-card-bg {
  background: linear-gradient(145deg, var(--bg-alt) 0%, var(--bg-alt) 50%, var(--bg-alt) 100%) !important;
}
.category-card[href*="hair"] .category-card-bg {
  background: linear-gradient(145deg, var(--bg-alt) 0%, var(--bg-alt) 50%, var(--bg-alt) 100%) !important;
}
.category-card-bg {
  font-size: 10px;
  letter-spacing: 0.2em;
  color: rgba(255,255,255,0.18);
}

/* ============================================================
   STICKY FILTER (shop page)
   ============================================================ */
.filter-sticky {
  position: sticky;
  top: var(--nav-h);
  z-index: 100;
  background: var(--bg);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  padding: 16px 0;
}

/* ============================================================
   SCROLL ANCHOR OFFSET
   ============================================================ */
section[id] { scroll-margin-top: calc(var(--nav-h) + 16px); }

/* ============================================================
   LIGHT / DARK MODE TOGGLE
   Switches html[data-mode] — does NOT touch data-theme on sections.
   Section-level theming always wins over page-level mode.
   ============================================================ */

/* Button styling — always visible */
.nav-theme-btn {
  display: flex !important;
  width: 36px; height: 36px;
  border-radius: 50%;
  align-items: center; justify-content: center;
  border: 1.5px solid rgba(255,255,255,0.40);
  background: transparent;
  color: #FFFFFF;
  font-size: 15px;
  transition: all var(--transition);
  cursor: pointer;
}
.nav.scrolled .nav-theme-btn { border-color: var(--border-strong); color: var(--fg-mid); }
.nav-theme-btn:hover { border-color: var(--accent); color: var(--accent); }

/* PATCH-EDITORIAL-BG: paint editorial sections so cream text is not invisible
   on the cream body (fixes Doctor + Routine CTA + Instagram on the homepage). */
[data-theme="editorial"] { background: var(--bg); color: var(--fg); }
/* PATCH-EDITORIAL-FG: headings/inherited text follow the theme token in editorial sections */
[data-theme="editorial"] .t-title,
[data-theme="editorial"] .t-headline,
[data-theme="editorial"] .t-display { color: var(--fg); }

/* Dark mode base — ritual sections AND the page root (pages without an explicit
   data-theme on <html>, e.g. inner pages) get the KOTIVA dark neutral. */
html[data-mode="dark"],
html[data-mode="dark"] [data-theme="ritual"],
html[data-mode="dark"] [data-theme="editorial-bg-white"] {
  --bg:           #231F20;
  --bg-alt:       rgba(255,255,255,0.04);
  --bg-card:      rgba(255,255,255,0.07);
  --fg:           #FFFFFF;
  --fg-mid:       rgba(255,255,255,0.78);
  --fg-dim:       rgba(255,255,255,0.64);
  --accent:       #8AB7E9;
  --accent-light: #8AB7E9;
  --accent-deep:  #FFFFFF; /* legacy token: the high-contrast interaction colour on the dark surface */
  --accent-text:  #8AB7E9; /* verified against #231F20 — see docs/COLOUR-MIGRATION.md */
  --border:       rgba(255,255,255,0.18);
  --border-strong:rgba(255,255,255,0.40);
  --script:       #D7282F; /* KOTIVA red in every theme and mode */
}
html[data-mode="dark"] .nav.scrolled {
  background: rgba(35,31,32,0.97);
  border-color: rgba(138,183,233,0.18);
}
html[data-mode="dark"] .filter-sticky {
  background: rgba(35,31,32,0.97);
  border-bottom-color: var(--border-strong);
}
/* Dark-mode pill contrast (DEC-159): border at 0.22 opacity is invisible on the dark bar.
   Raise border to 0.60 (3:1 WCAG 1.4.11), sharpen text to full-opacity --fg. */
html[data-mode="dark"] .filter-pill {
  border-color: rgba(138,183,233,0.60);
  color: var(--fg);
}
/* Active pill in dark mode: --accent-deep is white here, so the label takes the dark ground. */
html[data-mode="dark"] .filter-pill.active {
  color: var(--bg);
  border-color: var(--accent-deep);
}
html[data-mode="dark"] .filter-pill:hover:not(.active) {
  background: rgba(255,255,255,0.07);
  color: var(--fg);
  border-color: var(--accent-light);
}
/* Dark-mode scrolled nav theme-btn: sharpen icon + border */
html[data-mode="dark"] .nav.scrolled .nav-theme-btn {
  border-color: rgba(138,183,233,0.60);
  color: var(--fg);
}
html[data-mode="dark"] .nav-overlay {
  background: #231F20;
}
/* Footer brand logo: invert dark SVG to cream in dark mode so it stays visible */
html[data-mode="dark"] .footer-brand-logo { filter: brightness(0) invert(1); opacity: 0.9; }

/* Nav transparent state — always cream text when over dark hero OR dark-mode page */
.nav-theme-btn .icon-moon { display: block; }
.nav-theme-btn .icon-sun  { display: none; }
html[data-mode="dark"] .nav-theme-btn .icon-moon { display: none; }
html[data-mode="dark"] .nav-theme-btn .icon-sun  { display: block; }

/* Match the cart control beside it (shop.css .nav-cart): same 38px circle,
   1px hairline, colours and hover, so the right-hand cluster reads as one set.
   padding:0 drops the UA button padding; the SVG is block so it centres exactly
   instead of sitting on the text baseline. */
.nav-theme-btn {
  width: 38px; height: 38px;
  padding: 0;
  border-width: 1px;
  color: rgba(255,255,255,0.78);
  flex-shrink: 0;
}
.nav-theme-btn svg { display: block; }
.nav-theme-btn:hover { border-color: #FFFFFF; color: #FFFFFF; }
.nav.scrolled .nav-theme-btn { border-color: var(--border); color: var(--fg-mid); }
.nav.scrolled .nav-theme-btn:hover { border-color: var(--border-strong); color: var(--fg); }
html[data-mode="dark"] .nav.scrolled .nav-theme-btn { border-color: rgba(255,255,255,0.18); color: rgba(255,255,255,0.78); }
html[data-mode="dark"] .nav.scrolled .nav-theme-btn:hover { border-color: rgba(255,255,255,0.40); color: #FFFFFF; }

/* ============================================================
   CREDENTIAL BADGE — checkmark prefix
   ============================================================ */
.credential-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.credential-badge::before {
  content: '';
  display: inline-block;
  width: 12px;
  height: 7px;
  border-left: 1.5px solid var(--fg);
  border-bottom: 1.5px solid var(--fg);
  transform: rotate(-45deg) translateY(-2px);
  flex-shrink: 0;
}

/* ============================================================
   PHILOSOPHY SECTION — enhance script text
   ============================================================ */
.philosophy-left .t-script {
  font-size: clamp(36px, 4.5vw, 64px);
  opacity: 0.92;
}

/* ============================================================
   HERO SCROLL INDICATOR — add backdrop
   ============================================================ */
.hero-scroll {
  background: rgba(255,255,255,0.07);
  border-radius: 50%;
  padding: 12px;
  width: 52px;
  height: 52px;
  justify-content: center;
}

/* ============================================================
   PAGE HERO IMAGE PLACEHOLDER — doctor + routine CTA
   ============================================================ */
.doctor-image {
  background:
    radial-gradient(ellipse at 40% 60%, rgba(106,50,119,0.25) 0%, transparent 60%),
    linear-gradient(160deg, #6A3277 0%, #6A3277 50%, #6A3277 100%);
}
.routine-cta-image {
  background:
    radial-gradient(ellipse at 60% 35%, rgba(106,50,119,0.30) 0%, transparent 55%),
    linear-gradient(135deg, #6A3277 0%, #6A3277 50%, #6A3277 100%);
}
.shop-hero {
  background:
    radial-gradient(ellipse at 30% 70%, rgba(106,50,119,0.35) 0%, transparent 50%),
    linear-gradient(160deg, #6A3277 0%, #6A3277 40%, #6A3277 70%, #6A3277 100%);
}

/* ============================================================
   PRODUCT BADGE — showcase mode (no price)
   ============================================================ */
.product-card-cta {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--accent-text); /* K12: 11px gold measured 2.29:1 on --bg-card; 33 nodes, the single
                                largest contrast family on the site (every product card, every page
                                that renders one). */
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: gap var(--transition);
}
.product-card:hover .product-card-cta { gap: 10px; }
.product-card-cta::after { content: '→'; }

/* ============================================================
   INSTAGRAM TILES — editorial gradient placeholders
   ============================================================ */
.ritual-tile:nth-child(1) { background: linear-gradient(135deg, #6A3277 0%, var(--accent) 100%); }
.ritual-tile:nth-child(2) { background: linear-gradient(135deg, #6A3277 0%, var(--accent) 100%); }
.ritual-tile:nth-child(3) { background: linear-gradient(135deg, #6A3277 0%, var(--accent) 100%); }
.ritual-tile:nth-child(4) { background: linear-gradient(135deg, #6A3277 0%, var(--accent) 100%); }
.ritual-tile:nth-child(5) { background: linear-gradient(135deg, #6A3277 0%, var(--accent) 100%); }
.ritual-tile:nth-child(6) { background: linear-gradient(135deg, #6A3277 0%, var(--accent) 100%); }
.ritual-tile { color: rgba(255,255,255,0.40); font-size: 10px; }

/* ============================================================
   BEST SELLERS — editorial showcase section
   ============================================================ */
.bestsellers-section {
  position: relative;
  overflow: hidden;
  padding: clamp(80px, 10vw, 140px) 0;
}
.bestsellers-bg {
  position: absolute;
  inset: 0;
  background: var(--bg);
}
.bestsellers-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: clamp(40px, 5vw, 64px);
}
.bestsellers-scroll {
  overflow-x: auto;
  cursor: grab;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0 var(--container-pad) clamp(24px,3vw,40px);
}
.bestsellers-scroll::-webkit-scrollbar { display: none; }
.bestsellers-scroll:active { cursor: grabbing; }
.bestsellers-track {
  display: flex;
  gap: 16px;
  width: max-content;
  /* K31: ONE source of truth for rail item width. .bs-card and .bs-end are different
     elements by design (see the terminus block), which means two width declarations that
     must agree at three breakpoints -- and they already didn't: cards drop to 200px at
     768px while the terminus stayed 300px. Both now read this, so a breakpoint can only
     be changed in one place. .bs-card appears nowhere outside this track (verified), so
     the property reaches every consumer. */
  --bs-card-w: 300px;
}
.bs-card {
  display: flex;
  flex-direction: column;
  width: 240px; /* superseded by the product-rail block below (300px); kept for the non-rail default */
  flex-shrink: 0;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 4px;
  overflow: hidden;
  transition: transform 0.35s cubic-bezier(0.23,1,0.32,1), border-color var(--transition), background var(--transition);
}
/* .reveal's own `transition` shorthand would otherwise lose the cascade to this rule (equal
   0-1-0 specificity, this one later in the file) -- opacity would jump instead of fade when
   the entrance-stagger tags a card .reveal. This compound selector wins on specificity and
   carries every property either state needs, so both the entrance and the hover animate. */
.bs-card.reveal {
  transition: opacity 0.85s cubic-bezier(0.22,1,0.36,1), transform 0.85s cubic-bezier(0.22,1,0.36,1),
    border-color var(--transition), background var(--transition);
}
.bs-card:hover {
  transform: translateY(-6px);
  border-color: rgba(255,255,255,0.40);
  background: rgba(255,255,255,0.07);
}
.bs-card-img {
  aspect-ratio: 1;
  /* Light plinth for the transparent product renders (K31 rationale: the tile must read as a lit
     surface, not a swatch). Brand-colour migration: KOTIVA white. Superseded below by the
     product-rail block (background: none). */
  background:
    radial-gradient(ellipse 82% 66% at 50% 38%, #FFFFFF 0%, #FFFFFF 68%, #FFFFFF 100%);
  display: flex; align-items: center; justify-content: center;
  padding: 16px 16px 22px;
  overflow: hidden;
}
.bs-card-img img {
  width: 100%; height: 100%;
  object-fit: contain;
  /* The renders are transparent RGBA, so drop-shadow follows the bottle silhouette
     rather than boxing it — this is what seats a cutout on a surface instead of
     floating it in a swatch. */
  filter: drop-shadow(0 16px 20px rgba(35,31,32,0.22)) drop-shadow(0 2px 3px rgba(35,31,32,0.16));
  transition: transform 0.5s cubic-bezier(0.23,1,0.32,1);
}
.bs-card:hover .bs-card-img img { transform: scale(1.06); }
.bs-card-body {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* K31 (2026-08-19): .bs-card-num is retired. The 01-06 numerals under a "Most Loved"
   heading implied a popularity RANKING that the data does not contain — products carry a
   bestSeller boolean, not a rank — and they occupied the one slot on the card where
   commercial information belongs. Replaced by price + volume. The detector independently
   flagged the numerals as the numbered-section-marker AI scaffold, which agreed. */
/* K31: .pin-rail-sticky is a column flex container, so a .container child with
   `margin: 0 auto` shrink-wraps to its content (measured 722px inside a 1158px sticky) and
   the header's space-between collapsed — "View All 25" ended up jammed against the headline
   instead of held at the right edge. Stretch it explicitly. */
.pin-rail-sticky > .container {
  width: 100%;
  align-self: stretch;
}
/* The pinned header is a persistent frame, not a page heading with a page heading's air. */
.pin-rail-sticky .bestsellers-header {
  margin-bottom: clamp(20px, 2.4vw, 32px);
  width: 100%;
}
/* Product slider: arrows over the rail's left/right edges, dots below */
.bs-slider { position: relative; }
.bs-arrow {
  position: absolute;
  top: 50%;
  z-index: 3;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,0.55);
  background: rgba(106,50,119,0.85);
  box-shadow: 0 6px 20px rgba(0,0,0,0.25);
  color: #FFFFFF;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease, opacity 0.3s ease;
}
.bs-arrow:hover:not(:disabled) { background: #FFFFFF; color: #231F20; border-color: #FFFFFF; }
.bs-arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.bs-arrow:disabled { opacity: 0; pointer-events: none; }
.bs-arrow-prev { left: clamp(12px, 2vw, 32px); }
.bs-arrow-next { right: clamp(12px, 2vw, 32px); }
.bs-dots {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: clamp(8px, 1.5vw, 20px);
  position: relative;
  z-index: 2;
}
.bs-dot {
  width: 28px;
  height: 28px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.bs-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: rgba(255,255,255,0.45);
  transition: width 0.3s ease, background 0.3s ease;
}
.bs-dot:hover::before { background: rgba(255,255,255,0.8); }
.bs-dot.is-active::before { width: 24px; background: #FFFFFF; }
.bs-dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 999px; }
@media (max-width: 768px) {
  .bs-arrow { width: 42px; height: 42px; font-size: 17px; }
}
.bs-card-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  /* The price now carries an "excl. VAT" qualifier, so on a narrow card the
     row is allowed to wrap rather than push the volume out of the card. */
  flex-wrap: wrap;
}
.bs-card-price {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--accent-light);
}
/* Same treatment as .product-card-price small on the shop listing, so the two
   price labels read as one system. Inherits colour from the price rather than
   setting its own: the rail sits on a dark plinth where the shop's --fg-dim
   would disappear. */
.bs-card-price small {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-left: 5px;
  opacity: 0.72;
}
.bs-card-vol {
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: rgba(255,255,255,0.64);
}
.bs-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 2px;
}
.bs-card-cta {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-light);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 0.35s cubic-bezier(0.22,1,0.36,1), transform 0.35s cubic-bezier(0.22,1,0.36,1);
  white-space: nowrap;
}
/* The CTA is the reward for focus: it appears on the card the rail has brought to centre,
   and on hover. It is never the only affordance — the whole card is a link, and its
   aria-label already carries name + price for assistive tech. */
.bs-card:hover .bs-card-cta,
.bs-card:focus-visible .bs-card-cta,
.bs-card.is-focal .bs-card-cta { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .bs-card-cta { transition: none; transform: none; }
}
.bs-card-name {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #FFFFFF;
  line-height: 1.3;
}
.pin-rail-wrapper.pin-active .bs-card-name,
.pin-rail-wrapper.pin-active .bs-card-price {
  display: inline-block;
  transform-origin: left center;
}
@media (max-width: 768px) {
  .bestsellers-header { flex-direction: column; align-items: flex-start; gap: 20px; }
  .bestsellers-track { --bs-card-w: 200px; }
}

/* ============================================================
   SMOOTH IMAGE LOAD
   ============================================================ */
img { transition: opacity 0.4s ease; }
img[loading="lazy"] { opacity: 0; }
img[loading="lazy"].loaded { opacity: 1; }

/* ============================================================
   UI POLISH — FINAL PASS
   ============================================================ */

/* Hero — stronger text contrast, improved sub-line */
.hero-title {
  text-shadow: 0 4px 48px rgba(35,31,32,0.75), 0 1px 12px rgba(35,31,32,0.55);
  letter-spacing: -0.01em;
}
.hero-sub { text-shadow: 0 2px 16px rgba(35,31,32,0.60); }

/* Hero CTA spacing */
.hero-ctas { gap: 12px; }

/* Doctor section — richer visual */
.doctor-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 580px;
  overflow: hidden;
}
.doctor-content {
  padding: clamp(60px,8vw,120px) clamp(40px,5vw,80px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 28px;
}
.doctor-image {
  position: relative;
  overflow: hidden;
}

/* Category card — visible name contrast */
.category-card-name { text-shadow: 0 2px 12px rgba(35,31,32,0.6); }
.category-card-count { text-shadow: 0 1px 6px rgba(35,31,32,0.4); }

/* Philosophy section — quote sizing */
.philosophy-left .t-script {
  font-size: clamp(30px, 4vw, 52px);
  line-height: 1.25;
}

/* Section header eyebrow / headline spacing */
.section-header { margin-bottom: clamp(40px,5vw,64px); }

/* Ingredient card — sharper left border accent on hover */
.ingredient-card { border-left: 3px solid transparent; transition: border-left-color 0.35s ease, transform 0.4s cubic-bezier(0.22,1,0.36,1), box-shadow 0.4s ease; }
.ingredient-card:hover { border-left-color: var(--accent); box-shadow: var(--shadow-hover); }

/* Credential badges — improved spacing */
.credential-badges { display: flex; flex-wrap: wrap; gap: 8px; }
.credential-badge {
  padding: 8px 16px;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--radius-pill);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.78);
  transition: border-color 0.3s ease, color 0.3s ease;
}
.credential-badge:hover { border-color: var(--accent); color: var(--accent-text); }

/* Filter pill active state — gold fill */
.filter-pill.active {
  /* K12 intent kept: a FILLED active pill with light text. The fill is --accent-deep (KOTIVA blue in
     light mode), so the label is white; dark mode swaps label and border in the dark-mode block. */
  background: var(--accent-deep);
  color: #FFFFFF;
  border-color: var(--accent-deep);
}
.filter-pill {
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease, transform 0.2s ease;
}
.filter-pill:hover:not(.active) { transform: translateY(-1px); border-color: var(--accent-light); }

/* Footer brand logo */
.footer-brand-logo { height: 24px; width: auto; opacity: 0.85; }
.footer-tagline { font-size: 13px; line-height: 1.65; max-width: 260px; }

/* Scroll-into-view class for bestsellers track */
.bestsellers-scroll { cursor: grab; }
.bestsellers-scroll:active { cursor: grabbing; }

/* Nav overlay font — larger impact */
.nav-overlay .nav-link {
  font-size: 36px;
  letter-spacing: 0.04em;
  transition: color var(--transition), transform var(--transition);
}
.nav-overlay .nav-link:hover { transform: translateX(6px); }

/* Shop hero content — center align */
.shop-hero {
  min-height: 50vh;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: calc(var(--nav-h) + 60px) var(--container-pad) 60px;
  position: relative;
  overflow: hidden;
}
.shop-hero-content { position: relative; z-index: 2; }

/* Mobile — category grid single column → horizontal carousel */
@media (max-width: 640px) {
  .category-grid {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 2px;
  }
  .category-grid::-webkit-scrollbar { display: none; }
  .category-grid .category-card {
    flex: 0 0 80vw;
    scroll-snap-align: start;
    aspect-ratio: 3/4;
  }
}

/* Performance */
.hero-bg, .bestsellers-bg, .doctor-image, .routine-cta-image { will-change: auto; }
.hero-bg img { transform-origin: center center; }

/* Dark mode improvements */
html[data-mode="dark"] .nav.scrolled .nav-hamburger span { background: rgba(255,255,255,0.78); }
html[data-mode="dark"] .nav-theme-btn { border-color: rgba(255,255,255,0.18); color: rgba(255,255,255,0.78); }
html[data-mode="dark"] .scroll-progress-bar { background: linear-gradient(90deg, var(--accent-deep) 0%, var(--accent) 100%); }


/* ================================================================
   KOTIVA V2 — REVAMP R1 (2026-06-03)
   Grounded in: MISFITS X KOTIVA creative direction +
   Aesop / Byoma / premium brand research
   ================================================================ */

/* 1. HERO SCRIPT — dominant, editorial scale */
.hero-script-accent {
  font-size: clamp(56px, 9vw, 100px) !important;
  opacity: 0.92;
  letter-spacing: -0.01em;
}

/* 2. TRUST BAR — stats as visual heroes */
.trust-item {
  flex-direction: column !important;
  align-items: flex-start !important;
  justify-content: center !important;
  padding: 36px !important;
  gap: 4px !important;
  min-height: 156px !important;
}
.trust-icon { display: none !important; }
.trust-stat-num {
  font-family: var(--font-display);
  font-size: clamp(52px, 7vw, 84px);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.0;
  color: var(--fg);
}
.trust-label {
  font-size: clamp(13px, 1.6vw, 19px) !important;
  font-weight: 700 !important;
  letter-spacing: 0.08em !important;
  line-height: 1.2 !important;
  color: var(--fg) !important;
  text-transform: uppercase !important;
}
.trust-sub {
  font-size: 11px !important;
  letter-spacing: 0.06em !important;
}

/* 3. CATEGORY CARDS — bold typographic scale.
   Name is sized to the card's own width so long labels (e.g. TREATMENTS) never clip.
   Fallback clamp first (covers Safari < 16); container-query refinement where supported. */
.category-card { container-type: inline-size; }
.category-card-name {
  font-size: clamp(32px, 4.6vw, 58px) !important;
  letter-spacing: -0.03em !important;
  line-height: 0.95 !important;
  font-weight: 800 !important;
  overflow-wrap: break-word;
}
@supports (width: 1cqi) {
  .category-card-name { font-size: min(88px, 13.5cqi) !important; }
}

/* PDP — Science expander (verbatim actives + references) */
.pdp-science {
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin: 8px 0 28px;
}
.pdp-science > summary {
  list-style: none;
  cursor: pointer;
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 18px 2px;
  font-family: var(--font-display);
  font-size: 15px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--fg);
}
.pdp-science > summary::-webkit-details-marker { display: none; }
.pdp-science > summary::after {
  content: "+"; font-size: 22px; line-height: 1; color: var(--accent-text);
  transition: transform var(--transition);
}
.pdp-science[open] > summary::after { content: "\2212"; }
.pdp-science-hint {
  font-family: var(--font-ui); font-size: 11px; font-weight: 500;
  letter-spacing: 0.08em; color: var(--fg-dim); text-transform: none; margin-left: auto;
}
.pdp-science-body {
  font-family: var(--font-ui);
  font-size: 13.5px; line-height: 1.7; color: var(--fg-mid);
  padding: 4px 2px 24px; max-height: 420px; overflow-y: auto;
  overflow-wrap: anywhere;
}
.pdp-science-body a { color: var(--accent-text); text-decoration: none; font-weight: 600; white-space: nowrap; }
.pdp-science-body a:hover { text-decoration: underline; }
.category-card-count {
  font-size: 10px !important;
  letter-spacing: 0.2em !important;
  margin-top: 10px !important;
  /* Was opacity .6 on top of a .6 colour alpha = .36 effective, measuring 2.46-3.07:1
     against the brighter category photography -- below the 4.5:1 WCAG AA floor for
     small text. Sampling the real rendered backdrop, .75 effective gives 5.41:1 on
     the worst tile; .60 only reaches 4.09. Accessibility fix, not a restyle. */
  opacity: 1 !important;
  text-transform: uppercase !important;
}
.category-card-info {
  padding: 16px 24px 24px !important;
}

/* 4. DOCTOR SECTION — claim stamp */
.doctor-approved-stamp {
  font-family: var(--font-display);
  font-size: clamp(48px, 6.5vw, 90px);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 0.88;
  color: var(--script);
  margin-bottom: 20px;
  border-left: 3px solid var(--accent);
  padding-left: 20px;
}

/* 5. PHILOSOPHY — script as centrepiece */
.philosophy-headline {
  font-family: var(--font-script);
  font-size: clamp(52px, 9vw, 108px) !important;
  color: var(--script);
  line-height: 0.92;
  letter-spacing: -0.01em;
  font-weight: 400;
  font-style: italic;
  margin-bottom: 28px;
  display: block;
}

/* 6. INGREDIENTS — clinical editorial */
.ingredient-name {
  font-size: clamp(28px, 4vw, 54px) !important;
  font-weight: 800 !important;
  letter-spacing: -0.02em !important;
  line-height: 1.0 !important;
  margin-bottom: 4px !important;
}
.ingredient-benefit {
  font-size: 10px !important;
  letter-spacing: 0.16em !important;
  color: var(--accent-text) !important; /* K12: 10px gold measured 2.40:1 on --bg */
  font-family: var(--font-ui) !important;
  font-weight: 600 !important;
  margin-bottom: 14px !important;
}
.ingredient-card {
  border: none !important;
  border-top: 2px solid var(--accent-deep) !important;
  background: transparent !important;
  padding: 32px 0 !important;
  box-shadow: none !important;
  border-radius: 0 !important;
}
.ingredient-grid {
  gap: 0 !important;
  border-top: none !important;
}
.ingredient-grid .ingredient-card {
  padding: 32px 40px 32px 0 !important;
}
.ingredient-grid .ingredient-card:last-child {
  padding-right: 0 !important;
}

/* 7. MARQUEE — faster, branded ✦ accent */
.marquee-track {
  animation-duration: 20s !important;
}
.marquee-dot {
  display: inline-block !important;
  color: var(--accent) !important;
  margin: 0 16px !important;
  font-size: 9px !important;
  vertical-align: middle !important;
  opacity: 0.75 !important;
  font-family: var(--font-display) !important;
}
.marquee-item {
  font-family: var(--font-display) !important;
  font-size: 11px !important;
  font-weight: 600 !important;
  letter-spacing: 0.18em !important;
}

/* 8. SECTION HEADERS — slight scale increase for presence */
.t-display-md {
  font-size: clamp(32px, 4.5vw, 62px) !important;
}

/* Category card arrow — direct override (previous string mismatch fixed) */
.category-card-arrow {
  background: rgba(35,31,32,0.35) !important;
  backdrop-filter: blur(8px) !important;
  -webkit-backdrop-filter: blur(8px) !important;
  border-color: rgba(255,255,255,0.40) !important;
  z-index: 4 !important;
}

/* KOTIVA-MOBILE-OVERFLOW-FIX: prevent fixed nav/overlay from inflating mobile layout viewport (DEC-137 safe, no typography change) */
html { overflow-x: hidden; overflow-x: clip; }
.nav, .nav-overlay { max-width: 100vw; }
.nav-overlay { overflow: hidden; }

/* DOCTOR-SECTION-MOBILE-FIX v=th9: re-assert 1-col grid at <=1024px - line-1790 richer-visual override resets grid-template-columns:1fr 1fr and comes AFTER the 1024px media query in the cascade. DEC-137 safe. */
@media (max-width: 1024px) {
  .doctor-section { grid-template-columns: 1fr !important; }
}

/* SHOP-GRID-MOBILE-FIX: #product-grid has inline style so class-based media queries can't override it — !important required. Mirrors .product-grid breakpoints at 768px/480px. */
@media (max-width: 768px) {
  #product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}
@media (max-width: 480px) {
  #product-grid { gap: 1px !important; }
}

/* SHOP-GRID-ORPHAN-CARD-FIX (client feedback, 2026-07-04): with an odd count of *visible* products
   (all, or any filtered subset), the last card on the 2-col mobile grid lands alone in its row,
   leaving a bare empty cell beside it. Center the orphan card at the same column width instead.
   `.grid-orphan` is applied/removed by initFilters() in js/layout.js, since the filter pills hide
   cards via display:none rather than removing them from the DOM — CSS :last-child can't see past
   hidden siblings, so this has to be JS-driven to work for filtered views too, not just "All". */
@media (max-width: 768px) {
  #product-grid .product-card.grid-orphan {
    grid-column: 1 / -1;
    max-width: calc(50% - 0.5px);
    margin: 0 auto;
  }
}

/* PRODUCT-CARD-MOBILE-FIX: on narrow 2-col mobile cards, hide the Discover CTA (card itself is the link) and tighten body padding so the concern badge has room. */
@media (max-width: 768px) {
  .product-card-body { padding: 14px 14px 18px; gap: 7px; }
  .product-card-cta { display: none; }
}


/* KOTIVA-A11Y-REDUCED-MOTION: respect reduced motion + reveal fail-safe (never leave content invisible).
   Extended from the original .reveal*-only scope — audit found the marquee, hero-scroll bounce, and
   body fade-in were still running unconditionally for prefers-reduced-motion users (2026-07-04 QA pass).
   JS-driven effects (initCursor/initCardTilt/initMagneticButtons/initCountUp in js/animations.js) are
   separately gated in JS via the same matchMedia check — see animations.js. */
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal-fade, .reveal-left, .reveal-right, .reveal-scale, .reveal-clip {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }
  .marquee-track, .hero-scroll, body {
    animation: none !important;
  }
  html { scroll-behavior: auto; }
}

/* ── G2: ICON-LED PRODUCT FACTS (2026-08-11) ──
   At-a-glance strip on the PDP. Monochrome line icons on the same 24×24 grid
   and 1.5 stroke as the site's existing icon convention (theme toggle, footer,
   and the E2 purchase-type set), so it reads as one family. */
/* TWO COLUMNS, DECLARED — not auto-fit.
   This was `repeat(auto-fit, minmax(150px, 1fr))` with the note "the PDP column only
   ever resolves to 1 or 2 columns, so spanning the final odd item is safe". That
   assumption was false: the PDP info column measures ~573px at 1440px, so auto-fit
   resolved to THREE columns and the span rule below pushed the last fact onto its own
   row — leaving the row above half empty, rendering this element's own `background`
   (the border tint) as a bare cell that reads exactly like the missing fact the rule
   existed to prevent. Visible on all 25 PDPs; measured 2026-08-11 (gate F2).
   Declaring the column count makes the original intent true at every width instead of
   depending on how a container happens to measure. */
.pdp-facts {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 2px; background: var(--border);
  border: 1px solid var(--border); margin: 0 0 28px;
}
.pdp-fact {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 16px 18px; background: linear-gradient(var(--bg-card), var(--bg-card)), var(--bg); /* translucent card composited over the ground, not over the grid separator */
}
/* An odd number of facts (products without a stated volume have 4, the rest 5)
   otherwise leaves a bare grid cell that reads as a missing fact. With the column
   count now declared as 2, spanning the final odd item always closes the last row. */
.pdp-fact:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (max-width: 480px) {
  .pdp-facts { grid-template-columns: 1fr; }
}
.pdp-fact-icon { flex-shrink: 0; color: var(--accent-deep); margin-top: 1px; }
html[data-mode="dark"] .pdp-fact-icon { color: var(--bronze); }
.pdp-fact-label {
  font-family: var(--font-display);
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--fg-mid); margin-bottom: 3px;
}
.pdp-fact-value {
  font-family: var(--font-body);
  font-size: 13px; line-height: 1.45; color: var(--fg);
}

/* ── E7: STRUCTURED PRODUCT SCIENCE (2026-08-11) ──
   Presentation only. The same client-supplied science text, rendered with the
   hierarchy it was written with instead of flattened to <br>-separated prose.
   Uses the existing token set — no new colours, type scale or spacing values. */
.sci-block { padding: 22px 0; border-bottom: 1px solid var(--border); }
.sci-block:first-child { padding-top: 0; }
.sci-block:last-child { border-bottom: none; padding-bottom: 0; }
.sci-name {
  font-family: var(--font-display);
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--fg); margin: 0 0 10px;
}
.sci-tag {
  display: inline-block; margin-right: 8px;
  font-family: var(--font-display);
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--accent-deep);
}
html[data-mode="dark"] .sci-tag { color: var(--bronze); }
.sci-sub {
  font-family: var(--font-display);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--fg-mid); margin: 14px 0 6px;
}
.sci-line {
  font-family: var(--font-body);
  font-size: 14px; line-height: 1.7;
  color: var(--fg-mid); margin: 0 0 10px;
}
.sci-list {
  margin: 0 0 10px; padding-left: 18px;
  font-family: var(--font-body);
  font-size: 14px; line-height: 1.7; color: var(--fg-mid);
}
.sci-list li { margin-bottom: 4px; }
.sci-refs {
  font-family: var(--font-body);
  font-size: 12px; line-height: 1.9; color: var(--fg-mid);
  margin: 10px 0 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
}
.sci-refs a { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 3px; }
html[data-mode="dark"] .sci-refs a { color: var(--bronze); }

/* ── ROUTINE HANDOFF NOTICE (E5, 2026-08-11) ──
   Injected by layout.js on shop.html when arriving from the Routine Finder. */
.routine-notice{
  display:flex;flex-wrap:wrap;align-items:center;gap:12px;
  border:1px solid var(--border);border-left:2px solid var(--bronze);
  background:var(--bg-card);padding:16px 20px;margin-bottom:24px;
  font-family:var(--font-body);font-size:13px;line-height:1.5;color:var(--fg-mid);
}
.routine-notice-clear{
  background:none;border:none;padding:0;cursor:pointer;
  font-family:var(--font-display);font-size:9px;font-weight:700;
  letter-spacing:.2em;text-transform:uppercase;color:var(--fg);
  border-bottom:1px solid var(--border);
}
.routine-notice-clear:hover{border-color:var(--bronze);color:var(--accent-text);}

/* ═══════════════════════════════════════════════════════════════════
   MINIMAL POLISH PASS — 2026-08-18
   Appended rather than threaded through the file so the whole pass is
   reviewable and revertible as one block.
   ═══════════════════════════════════════════════════════════════════ */

/* — Footer wordmark is now a home link (the nav wordmark always was one).
     alt="" on the image so the link is announced once, not twice. */
.footer-brand-link { display: inline-block; border-radius: 2px; }
.footer-brand-link:focus-visible { outline: 2px solid var(--accent-deep); outline-offset: 4px; }

/* — Ritual shelf. A warm cream plane inside the dark editorial band: it gives the
     section the light it was missing, seats the transparent renders on a real surface,
     and reads as one composition rather than another card grid (no borders, no boxes —
     the client's written note was that "outlined boxes add visual noise"). */
.ritual-shelf {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(8px, 2vw, 28px);
  align-items: end;
  padding: clamp(26px, 4vw, 46px) clamp(18px, 4vw, 54px) clamp(22px, 3vw, 36px);
  background: linear-gradient(175deg, #FFFFFF 0%, #FFFFFF 62%, #FFFFFF 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.55);
}
.ritual-item {
  display: flex; flex-direction: column; align-items: center;
  text-align: center; text-decoration: none; gap: 4px;
}
.ritual-item-img {
  display: block; width: 100%;
  aspect-ratio: 1 / 1.12;
  display: flex; align-items: flex-end; justify-content: center;
}
.ritual-item-img img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  transform: scale(var(--s, 1));
  transform-origin: center bottom;
  /* Follows the bottle silhouette — the renders are transparent RGBA, so this seats
     them on the shelf instead of floating them. Slightly deeper than the bestseller
     cards because these sit larger and lower. */
  filter: drop-shadow(0 18px 22px rgba(35,31,32,0.24)) drop-shadow(0 3px 4px rgba(35,31,32,0.18));
  transition: transform 0.45s cubic-bezier(0.22,1,0.36,1);
}
.ritual-item:hover .ritual-item-img img,
.ritual-item:focus-visible .ritual-item-img img { transform: translateY(-6px); }
.ritual-item:focus-visible { outline: 2px solid #005DBA; outline-offset: 6px; }
.ritual-item-name {
  margin-top: 16px;
  font-family: var(--font-display);
  font-size: 12px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: #231F20; line-height: 1.35;
}
.ritual-item-role {
  font-family: var(--font-ui);
  font-size: 11px; letter-spacing: 0.06em; color: #005DBA;
}
.ritual-foot {
  margin-top: 22px; text-align: center;
  font-family: var(--font-ui); font-size: 13px; letter-spacing: 0.03em;
  color: var(--fg-mid);
}
.ritual-foot a { color: var(--accent-text); text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 1px; }
.ritual-foot a:hover { color: var(--fg); }
@media (max-width: 640px) {
  .ritual-shelf { grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 22px 12px 18px; }
  .ritual-item-name { font-size: 10px; letter-spacing: 0.04em; }
  .ritual-item-role { font-size: 9.5px; }
  /* the trailing arrow was orphaning onto its own line at 375px */
  .ritual-foot { display: flex; flex-direction: column; gap: 6px; align-items: center; }
}

/* — Vertical rhythm. The measured problem was not the padding value but that two
     consecutive runs came out at 2,110px and 2,134px (1.01:1), so the page read as a
     repeat rather than an alternation. These trim the two longest blocks and close the
     dead gap under the bestseller rail, without moving a single section. */
.bestsellers-section { padding-bottom: clamp(40px, 5vw, 64px); }
.section-pad-sm { padding-top: clamp(52px, 6vw, 76px); padding-bottom: clamp(52px, 6vw, 76px); }

/* — Adjacent-section connection. A hairline seam where a cream section meets the next
     cream section, so the sequence reads as continuous rather than as stacked slabs. */
[data-theme="ritual"] + [data-theme="ritual"] > .container { position: relative; }
[data-theme="ritual"] + [data-theme="ritual"] > .container::before {
  content: ""; position: absolute; top: calc(-1 * clamp(26px, 3vw, 40px)); left: 0;
  width: 64px; height: 1px; background: var(--accent); opacity: 0.5;
}

/* — PRODUCT RAIL — 2026-08-18 (round 2). Reworked from a bordered-box grid into the
     Ritual shelf's visual language: a continuous warm plinth, shared baseline, per-item
     optical-scale correction, and native scroll-snap (drag/trackpad/touch all work exactly
     as they already did — snap only adds a settle point, no wheel-hijacking, no JS). */
.bestsellers-scroll { scroll-snap-type: x proximity; scroll-padding-left: var(--container-pad); }
.bs-card {
  width: var(--bs-card-w);
  background: linear-gradient(175deg, #FFFFFF 0%, #FFFFFF 62%, #FFFFFF 100%);
  border: none;
  border-radius: 2px;
  scroll-snap-align: start;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.5);
}
.bs-card:hover { background: linear-gradient(175deg, #FFFFFF 0%, #FFFFFF 62%, #FFFFFF 100%); transform: translateY(-4px); }
.bs-card-img {
  aspect-ratio: 1 / 1.05;
  /* Tightened from 22px/22px/14px (round 2) now that the source images themselves are
     pre-cropped to their silhouette bounds (assets/products/hero/*.webp) -- the old padding
     was compensating for wasted transparent canvas that no longer exists, and kept the
     product reading closer to a thumbnail than a hero object at any card size. */
  padding: 8px 8px 6px;
  background: none;
}
.bs-card-img img {
  /* --s is now a residual per-SKU correction only (the pre-crop pipeline already normalises
     ~83% fill across all six -- see assets/products/hero/README below); the focus-driven
     boost that makes the centred product read as a hero object is applied per-frame by
     initPinRail() directly to this element's transform, composed with --s, not by this
     static rule. transform-origin: centre -- the hero crops are built as SQUARE canvases
     with uniform padding on every side, so there is no bottom-heavy dead space left to
     anchor against (that asymmetry was the actual cause of product 06 drifting toward the
     top of its plinth when scaled from a bottom origin). */
  transform: scale(var(--s, 1));
  transform-origin: center center;
}
.pin-rail-wrapper.pin-active .bs-card,
.pin-rail-wrapper.pin-active .bs-card-img {
  /* Lets the focused card's image grow past its own padding box without being clipped by
     the card's border/background -- the "independent of the card/plinth" requirement. The
     card's own footprint (width, spacing from neighbours) is unchanged; only the image is
     allowed to visually exceed it. */
  overflow: visible;
}
.bs-card-body { padding: 4px 22px 22px; }
.bs-card-price { color: #231F20; opacity: 0.78; } /* K31: price is information, so it is ink on the white plinth. KOTIVA blue at this 0.78 opacity would fall below 4.5:1 (docs/COLOUR-MIGRATION.md); the JS focus ramp peaks higher. */
.bs-card-name { color: #231F20; }
/* K31 WCAG fix, measured not assumed. .bs-card-vol and .bs-card-cta were first authored in the
   dark-card idiom (near-white / light accent) — but the product-rail block above gives EVERY
   .bs-card the light plinth (KOTIVA white), where dark-idiom colours are effectively invisible.
   The colours below are chosen for the white plinth, not for the purple section around it. */
.bs-card-vol { color: rgba(35,31,32,0.62); }   /* muted, ranks below price */
.bs-card-cta { color: #005DBA; }   /* KOTIVA blue — reads as an action, not a whisper */
.bs-card .badge-concern {
  display: inline-block; margin-top: 2px;
  font-family: var(--font-ui); font-size: 10.5px; letter-spacing: 0.05em;
  color: rgba(35,31,32,0.72); border: 1px solid rgba(35,31,32,0.30); border-radius: 20px;
  padding: 3px 10px;
}
@media (max-width: 640px) {
  .bestsellers-track { --bs-card-w: 220px; }
}

/* ═══════════════════════════════════════════════════════════════════
   PIN-SCRUB PRODUCT RAIL — 2026-08-18 round 4
   Default state (below) is a no-op: same-height wrapper, no sticky,
   renders identically to the plain drag/scroll-snap rail that already
   shipped. js/animations.js initPinRail() adds .pin-active only after
   checking eligibility (no reduced motion, >=900px, fine pointer) --
   see the comment on the wrapper in index.html for the full reasoning.
   ═══════════════════════════════════════════════════════════════════ */
.pin-rail-wrapper { position: relative; }
.pin-rail-sticky { display: block; }

.pin-rail-wrapper.pin-active {
  height: var(--pin-rail-vh, 260vh);
}
.pin-rail-wrapper.pin-active .pin-rail-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
}
.pin-rail-wrapper.pin-active .bestsellers-scroll {
  overflow: visible;
  cursor: default;
  padding-bottom: 0;
}
.pin-rail-wrapper.pin-active .bestsellers-track {
  will-change: transform;
}
.pin-rail-wrapper.pin-active .bs-card {
  /* No transition -- scroll-linked scale/opacity must track the user's own scroll
     input 1:1. Any CSS transition here creates a 'chasing' lag where the card visibly
     catches up after the user stops scrolling, which reads as laggy, not premium. */
  transition: none;
}
/* A quiet progress read-out -- the one piece of UI chrome that tells a keyboard/screen-reader
   user (and anyone who pauses mid-scrub) that this section behaves differently on purpose,
   not by accident. Purely decorative to sighted pointer users; the motion itself carries the
   information for them. */
.pin-rail-progress {
  position: absolute;
  left: 50%;
  bottom: clamp(28px, 5vh, 56px);
  transform: translateX(-50%);
  display: none;
  gap: 6px;
  z-index: 3;
}
.pin-rail-wrapper.pin-active .pin-rail-progress { display: flex; }
.pin-rail-progress span {
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255,255,255,0.40);
  transition: background 0.25s ease, transform 0.25s ease;
}
.pin-rail-progress span.is-active {
  background: var(--accent-light, #8AB7E9);
  transform: scale(1.6);
}

/* ============================================================
   K31 — PRODUCT-RAIL TERMINUS
   The rail's centre-last geometry (Founder-approved) structurally leaves the viewport
   half-empty at scroll-end: the final card parks at centre and the right half of a 1158px
   sticky has nothing in it. Previously that read as "the rail ran out". This panel makes the
   end of the journey a destination instead — and it is the correct commercial terminus, since
   a visitor who scrubbed through all seven has demonstrated interest and the next useful move
   is the other eighteen products.

   Deliberately NOT a .bs-card, for two independent reasons:
   1. Design — eight identical plinths would make the ending indistinguishable from the middle.
      The rail is cream plinths; the terminus is their negative (open, ruled, typographic), so
      it reads as punctuation rather than one more product.
   2. Test integrity — scripts/check-consistency.js requires EVERY .bs-card to link to a
      /product/<slug>.html carrying bestSeller:true. That check is right and must stay strict;
      a navigational tile earns its own class rather than loosening it.

   Colour comes entirely from theme tokens. This section is data-theme="editorial" in both site
   modes, and --fg / --fg-mid / --accent-text are already contrast-verified against that ground
   (K12), so the terminus inherits that work instead of restating hex values that would then
   need re-auditing on their own.
   ============================================================ */
.bs-end {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: var(--bs-card-w);
  flex-shrink: 0;
  padding: 0 34px;
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  background: rgba(255,255,255,0.04);
  scroll-snap-align: start;
  text-decoration: none;
  transition: background var(--transition), border-color var(--transition);
}
.bs-end:hover { background: rgba(255,255,255,0.07); border-color: var(--accent); }
.bs-end-count {
  font-family: var(--font-display);
  font-size: 68px;
  line-height: 0.9;
  color: var(--accent-text);
  letter-spacing: -0.03em;
}
.bs-end-label {
  margin-top: 10px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--fg-mid);
}
.bs-end-cta {
  margin-top: 22px;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg);
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 4px;
  transition: border-color var(--transition);
}
.bs-end:hover .bs-end-cta { border-color: var(--accent); }
@media (max-width: 640px) {
  .bs-end { padding: 0 24px; }   /* width comes from --bs-card-w */
  .bs-end-count { font-size: 52px; }
}

/* ============================================================
   K32 — STICKY OFFSET FOLLOWS THE HIDE-ON-SCROLL NAV
   The nav hides itself on scroll-down (translateY(-100%)), but every sticky element beneath
   it kept reserving `--nav-h` of space for a header that was no longer on screen. On the shop
   grid that left a 72px band at the top of the viewport showing half-cropped product imagery
   scrolling behind the filter bar -- measured: header bottom at 0, filter bar top at 72.
   It only appeared while scrolling DOWN, which is the dominant direction on a product grid.

   `top` is transitioned at the nav's own duration and easing (0.35s ease) so the bar rises
   into the vacated space with the header rather than snapping after it. This is a layout
   property and normally worth avoiding, but it runs only for the 0.35s of a nav toggle, on
   one element, and the alternative (transform) cannot move a sticky element's pin point.
   ============================================================ */
.filter-sticky { transition: top 0.35s ease; }
html.nav-hidden .filter-sticky { top: 0; }

/* `.product-detail-img-wrap` is NOT given the same treatment: it is declared in this
   stylesheet but no HTML uses it (checked across every page and both generators) -- the
   generated product pages have no sticky element at all. Adding a nav-aware rule for it
   would have been a selector matching nothing, which reads like coverage without being it.
   The dead declaration itself is logged, not removed here. */

@media (prefers-reduced-motion: reduce) {
  .filter-sticky { transition: none; }
}

/* ============================================================
   K32 — MOBILE FILTER BAR: ONE SCROLLING ROW, NOT THREE WRAPPED ONES
   At 375px the seven pills wrapped to 3 rows and the sticky bar measured 181px — 22.3% of
   the viewport, held there for the entire scroll through 25 products. Combined with the
   72px dead band fixed above, a third of the mobile screen was chrome.

   A single horizontal row is the standard chip pattern and is also the site's own established
   idiom (the Best Sellers rail), so this is consistency rather than a new interaction. The
   pills keep their 44px touch target.

   `overflow-x: auto` here is DELIBERATE component-level scroll. The documented trap is a
   component scrolling sideways UNNOTICED while a page-level check reads clean; this one is
   intended, and the page-level check is still asserted separately (0 page overflow at 375px).
   ============================================================ */
@media (max-width: 768px) {
  .filter-pills {
    flex-wrap: nowrap;
    overflow-x: auto;
    justify-content: flex-start;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* Bleed to the viewport edge so the row reads as continuing past the screen rather than
       stopping at a margin, then restore the inset with padding. Without this the last pill
       ends flush at the container edge and the row looks complete when it is not. */
    margin-inline: calc(var(--container-pad) * -1);
    padding-inline: var(--container-pad);
    scroll-padding-inline: var(--container-pad);
  }
  .filter-pills::-webkit-scrollbar { display: none; }
  .filter-pill { flex: 0 0 auto; }
}

/* ============================================================
   K33 — BRAND FACT CARDS (replaces testimonial-card for KOTIVA's own statements)
   Rationale in the index.html comment above the markup. Short version: K27 correctly replaced
   three fabricated testimonials with sourced brand statements, but left them in the testimonial
   LAYOUT — body first, rule, bottom-pinned attribution — which is the grammar of a quotation
   whatever glyphs you hide. Label-first instead, matching the pattern this page already uses in
   Brand philosophy and The Ingredients.
   ============================================================ */
.fact-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
.fact-card {
  padding: clamp(36px, 4vw, 56px);
  background: var(--bg-card);
  border: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.fact-card-title {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg);
  margin: 0;
}
.fact-card-body {
  font-size: 15px;
  line-height: 1.65;
  color: var(--fg-mid);
  margin: 0;
}
/* Provenance, not a signature. No top border and no `margin-top: auto` — both were what made
   the old block read as an attribution line under a quote. It stays visible and honest, but it
   is the least prominent thing in the card rather than its punchline. */
.fact-card-source {
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--fg-dim);
  margin: 0;
}
@media (max-width: 900px) {
  .fact-grid { grid-template-columns: 1fr; gap: 1px; }
}

/* K33: the ritual section's framing line, moved above the grid (see index.html comment).
   Inherits the foot's quiet register — it introduces the sequence, it does not compete with
   the display heading above it. */
.ritual-lede {
  font-size: 14px;
  letter-spacing: 0.04em;
  color: var(--fg-mid);
  text-align: center;
  margin: 0 0 32px;
}

/* ============================================================
   K35 — CROSS-DOCUMENT PAGE TRANSITIONS
   This is a multi-page static site with no transition of any kind between documents: every
   navigation was a hard cut, which on a premium editorial site reads as a stall rather than a
   move. The native cross-document View Transition gives the browser a same-origin crossfade
   with no JS, no router, and no interception of link clicks.

   Chosen over the usual JS approach (fade out on click, fade in on load) on purpose: that
   pattern has to hijack every <a>, it strands the user on a faded page if the next document is
   slow, and it fights the back button. It is also the exact shape of the DEC-218 trap — a
   page-level opacity animation that caps FCP for its whole duration. The native mechanism runs
   on a snapshot after the next document is ready, so it cannot delay first paint.

   Progressive by construction: browsers without support ignore the at-rule entirely and get
   today's behaviour. Nothing is required of the markup.
   ============================================================ */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 260ms;
  animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

/* The nav is fixed and identical across pages, so letting it crossfade with the page body
   makes it appear to blink on every navigation. Naming it gives it its own transition group,
   which for an unchanged element resolves to no visible movement at all. */
.nav { view-transition-name: site-nav; }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* K36: heading for the category grid. The grid itself is full-bleed, so the heading needs its
   own container inset and bottom rhythm to sit with the page rather than with the tiles. */
.category-grid-heading {
  color: var(--fg);
  margin-bottom: clamp(28px, 3.5vw, 48px);
}

/* K36: .philosophy-headline and .doctor-approved-stamp changed from <p>/<div> to <h2> so the
   two sections they title appear in the document outline at all — a screen-reader user
   navigating by heading previously skipped both. Both already declare their own font, size,
   colour and spacing, so the change is visually inert; these two lines only neutralise the
   generic heading margins that now apply. */
h2.philosophy-headline, h2.doctor-approved-stamp { margin-top: 0; }

/* ============================================================
   K39 — CURRENT-PAGE INDICATION, REBUILT (K38's version rendered NOTHING)

   K38 added `.nav-link.is-current { color: var(--fg) }` + its own `::after` underline. Verified
   by asserting the class was applied — which it was, in every state, the whole time. It was still
   invisible to a human, for four separate reasons that only rendered inspection exposes:

   1. `.nav-link::after` ALREADY EXISTS (the hover underline) and carries `transform: scaleX(0)`.
      K38's `::after` never set a transform, so it inherited the collapsed one — the underline was
      scaled to zero width and NEVER PAINTED, in any state, on any page.
   2. Its `background` lost to `.nav.scrolled .nav-link::after` (0,3,0 vs 0,2,0), so even had it
      rendered it would not have been the intended colour.
   3. Scrolled state: `.nav.scrolled .nav-link { color: var(--fg-mid) }` (0,3,0) beats
      `.nav-link.is-current { color }` (0,2,0) — the current link was identical to its siblings.
   4. Transparent state: there the colour override DID win, replacing the deliberate cream
      (`.nav-link` is cream by design, "safe over dark hero") with dark ink over a dark hero —
      making the current page LESS legible than every other item. The one state where it took
      effect is the one where it did harm.

   THE FIX DELIBERATELY CHANGES NO TEXT COLOUR. Colour was the whole failure: any fixed colour has
   to be legible over both a dark photograph and a cream bar, and `--fg` cannot be. The state is
   carried by the design system's OWN motif instead — the bronze rule already used for hover —
   held permanently open on the current item. Bronze reads on both grounds (it is the brand accent
   over the dark hero and over cream), the treatment is already part of the visual language rather
   than a new decoration, and "always present" vs "animates in on hover" is a legible distinction.

   Specificity is stated explicitly against BOTH nav states rather than relying on source order,
   because source order is exactly what silently defeated the previous attempt.
   ============================================================ */
.nav .nav-link.is-current,
.nav.scrolled .nav-link.is-current,
.nav.transparent .nav-link.is-current { font-weight: 700; }

.nav .nav-link.is-current::after,
.nav.scrolled .nav-link.is-current::after,
.nav.transparent .nav-link.is-current::after {
  transform: scaleX(1);
  transform-origin: left;
  background: var(--accent);
  opacity: 1;
}

/* Section-level (the 25 product pages sit under Shop, the glossary under Science): the same rule,
   held at lower opacity and without the weight change. "You are inside this" must read as weaker
   than "you are on this", or the two states say the same thing. */
.nav .nav-link.is-current-section::after,
.nav.scrolled .nav-link.is-current-section::after,
.nav.transparent .nav-link.is-current-section::after {
  transform: scaleX(1);
  transform-origin: left;
  background: var(--accent);
  opacity: 0.45;
}

/* Mobile overlay: links are large, stacked and on a solid ground, where a 1px rule under a 20px+
   item reads as a stray line rather than as state. Weight plus a bronze marker instead. */
.nav-overlay .nav-link.is-current { font-weight: 700; color: var(--accent-text); }
.nav-overlay .nav-link.is-current::after { content: none; }
.nav-overlay .nav-link.is-current-section { color: var(--accent-text); }
.nav-overlay .nav-link.is-current-section::after { content: none; }

/* K39: the header CTA as a current-page state. Find My Routine is already the loudest element in
   the header, so this must not shout — a ring at the brand accent, reading as "you are here"
   rather than as a second call to action. Without it, the routine finder was the only page in the
   site with no orientation at all, precisely because its entry point is a button not a nav link. */
.btn.is-current-cta {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 3px var(--accent);
}
.nav.transparent .btn.is-current-cta {
  box-shadow: 0 0 0 2px rgba(35,31,32,0.55), 0 0 0 3px var(--accent);
}
.nav-overlay .btn.is-current-cta { box-shadow: 0 0 0 3px var(--accent); }
