/** Shopify CDN: Minification failed

Line 3473:0 Unexpected "}"

**/

/* ==========================================================================
   FRANCESCHI CHOCOLATE — Design System
   Concept: "The Origin Line" — vertical integration made visible. A single
   continuous rule runs farm -> creator through the whole site.

   Palette is sampled from the real packaging, not invented:
     #2F1913 wrapper frame · #3AAE2A Carenero 60 · #00A0E0 Rio Caribe 70
     #D53A96 Bakery/Reposteria · #C0A282 kraft case
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS — primitive
   -------------------------------------------------------------------------- */
:root {
  /* Cacao ramp — the brand's dark. 800 is the literal wrapper frame colour. */
  --cacao-900: #140B08;
  --cacao-850: #1C110D;
  --cacao-800: #2F1913;
  --cacao-700: #4C322A;
  --cacao-600: #5C3427;
  --cacao-500: #7A5344;
  --cacao-400: #9B7B6B;
  --cacao-300: #B9A493;

  /* Paper ramp — warm, unbleached. Never pure white. */
  --paper-50:  #FDFBF7;
  --paper-100: #FBF7F1;
  --paper-200: #F4EDE3;
  --paper-300: #EAE0D2;
  --paper-400: #E4D8C7;
  --paper-500: #C0A282;   /* kraft case */

  /* Brass — awards, heritage, the 1830 line */
  --brass-700: #8A5F1E;   /* text-safe on paper */
  --brass-500: #C08B3E;
  --brass-300: #DDB57C;

  /* Variety coding — real, off the wrappers */
  --v-milk:      #C98A3C;
  --v-blend:     #E08A1E;
  --v-carenero:  #3AAE2A;
  --v-riocaribe: #00A0E0;
  --v-intense:   #1F7A18;
  --v-pure:      #241511;
  --v-bakery:    #D53A96;
  --v-cocoa:     #8A5F1E;
  --v-butter:    #E3D2A8;

  --state-warn: #B8761A;
  --state-stop: #A8371F;
  --state-go:   #2E7D32;

  /* Spacing — 4px base */
  --sp-1: .25rem;  --sp-2: .5rem;   --sp-3: .75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4rem;
  --sp-9: 6rem;    --sp-10: 8rem;

  /* Fluid section rhythm. Round 2 (G-03): the blocks sat too far apart — the
     page read as finished before it was. 4–9rem became 2.25–3.75rem, so the top
     of the next section is on screen when the one above it ends. */
  --section-y: clamp(2.25rem, 4vw, 3.75rem);
  --gutter:    clamp(1.25rem, 5vw, 5rem);
  --measure:   68ch;

  /* Type scale — ONE scale for the whole site (round 2, G-02). Before this,
     the same level was set at different sizes on different pages (a page title
     at 4.5rem, a scene title at 5rem, a section title at 3.25rem or 3.5rem).
     Four heading levels, one lede, one body, one small, one button size.
     Every heading class below reads these and nothing else. */
  --fs-h1:    clamp(1.75rem, calc(4.6vw + .25rem), 4.5rem);   /* page title, hero */
  --fs-h2:    clamp(1.625rem, calc(3.4vw + .125rem), 3.25rem);  /* section title */
  --fs-h3:    clamp(1.375rem, 2.2vw, 1.75rem);  /* subsection, form title */
  --fs-h4:    clamp(1.125rem, 1.5vw, 1.25rem);  /* card title */
  --fs-lede:  clamp(1.0625rem, 1.4vw, 1.25rem);
  --fs-body:  1rem;
  --fs-small: .9375rem;                         /* eyebrow, label, chip, note */
  --fs-btn:   1rem;                             /* every button, every size */

  /* Primary button (G-01, option C, chosen by the Sr. Manuel on 11 Oct 2026):
     the gold stripe of the 2 lb Milk Chocolate 43% bag, with cacao ink on it —
     contrast 6.86:1. These two tokens are the only place the primary button is
     colored; the brass it replaced (#8A5F1E, white text) stays in the palette
     for awards and heritage. */
  --gold-500: #C7A24F;
  --btn-primary: var(--gold-500);
  --btn-primary-ink: var(--cacao-800);

  --radius-sm: 3px;
  --radius:    6px;
  --radius-lg: 14px;

  /* Motion */
  --ease-out:  cubic-bezier(.22, 1, .36, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --t-fast: 140ms;
  --t-base: 260ms;
  --t-slow: 620ms;

  /* Cinema — the 3D home (CINEMA=on, assets/css/cinema.css). One curve for
     everything it moves, two duration bands, and its hairline. Unused by the
     static site. */
  --ease-cinema: cubic-bezier(.16, 1, .3, 1);
  --t-cinema-ui: 400ms;
  --t-cinema-enter: 1200ms;
  --hairline: 1px;

  /* Header geometry. --sticky-top is where anything sticky (the About subnav,
     summaries, sticky columns) and every anchor jump must land: just under the
     sticky header, which grew a second row on desktop in Oct 2026. */
  --header-h:   5.75rem;
  --sticky-top: var(--header-h);

  --z-header: 100;
  --z-drawer: 200;
  --z-modal:  300;
  --z-base:   1;
  --z-raised: 2;
  --z-sticky: 50;
  --z-toast:  400;

  /* Grid — 12 columns from 1024px, 8 on a tablet, 4 on a phone. The container
     is the viewport minus two gutters, capped at --wrap-max; every section sits
     on it, so edges align from one page to the next. */
  --wrap-max:  1560px;
  --grid-gap:  clamp(1rem, 2vw, 1.75rem);

  /* Editorial motion — one curve (--ease-out), two duration bands. UI answers in
     --dur-ui; a block entering the screen takes --dur-reveal and rises --rise. */
  --dur-ui:     320ms;
  --dur-reveal: 900ms;
  --stagger:    70ms;
  --rise:       clamp(18px, 2.4vw, 30px);
  --ring:       0 0 0 3px color-mix(in srgb, var(--focus, var(--cacao-800)) 28%, transparent);

  /* One grade for the whole site. The source photography spans a bright
     production kitchen, a night drying shed and a laboratory bench; without a
     shared grade the grids read as uncurated stock. Thumbnails need a lighter
     hand than a full-bleed scene or they go to mud. */
  --grade-scene: brightness(.94) saturate(.95) contrast(1.04);
  --grade-card:  brightness(.88) saturate(.92) contrast(1.04);
}

/* --------------------------------------------------------------------------
   2. TOKENS — semantic. Sections opt into a surface; components never
   hardcode a colour, so an inverted band needs no component overrides.
   -------------------------------------------------------------------------- */
:root,
.surface-paper {
  --bg:          var(--paper-100);
  --bg-raised:   var(--paper-50);
  --bg-sunken:   var(--paper-200);
  --text:        var(--cacao-800);
  --text-strong: var(--cacao-900);
  --text-muted:  #6B5347;
  --line:        var(--paper-400);
  --line-soft:   var(--paper-300);
  --accent:      var(--brass-700);
  --on-accent:   var(--paper-50);
  --focus:       var(--cacao-800);
  --shadow: 0 1px 2px rgba(47,25,19,.05), 0 8px 24px -12px rgba(47,25,19,.16);
  --shadow-lg: 0 2px 4px rgba(47,25,19,.06), 0 24px 56px -20px rgba(47,25,19,.26);
}
/* :root never needed its own background/color rule — body's base styles
   already read --bg/--text. But .surface-paper used as a NESTED re-scope
   (e.g. a card sitting light-on-dark inside a .surface-cacao section) does:
   without this, .card and a plain <p> declare no color of their own, so a
   descendant <a> (color:inherit) keeps the dark section's pale text color
   instead of picking up the card's own re-scoped value. Same fix .surface-
   cacao already has, just never needed here until a card sat on a dark band. */
.surface-paper { background: var(--bg); color: var(--text); }

/* `.hero` opts into the same tokens without the flat background — it carries a
   photograph instead. Without this the ghost button inherits near-black text
   from the paper scope and disappears against the image. */
.surface-cacao, .hero {
  --bg:          var(--cacao-850);
  --bg-raised:   #241612;
  --bg-sunken:   var(--cacao-900);
  --text:        #EFE4D7;
  --text-strong: var(--paper-50);
  --text-muted:  var(--cacao-300);
  --line:        rgba(239,228,215,.16);
  --line-soft:   rgba(239,228,215,.09);
  --accent:      var(--brass-300);
  --on-accent:   var(--cacao-900);
  --focus:       var(--brass-300);
  --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px -12px rgba(0,0,0,.5);
  --shadow-lg: 0 2px 4px rgba(0,0,0,.3), 0 24px 56px -20px rgba(0,0,0,.6);
}
.surface-cacao { background: var(--bg); color: var(--text); }

.surface-kraft {
  --bg:          var(--paper-200);
  --bg-raised:   var(--paper-100);
  --bg-sunken:   var(--paper-300);
  --text:        var(--cacao-800);
  --text-strong: var(--cacao-900);
  --text-muted:  #6B5347;
  --line:        #DCC9AE;
  --line-soft:   var(--paper-400);
  --accent:      var(--brass-700);
  --on-accent:   var(--paper-50);
  --focus:       var(--cacao-800);
  background: var(--bg);
  color: var(--text);
}

/* --------------------------------------------------------------------------
   3. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* clears the sticky header when jumping to an anchor. Raised with the header:
     the desktop bar is 6.75rem tall now, and the FAQ's section jump-links land
     under it at the old 6rem. */
  scroll-padding-top: calc(var(--sticky-top) + 4.5rem);
  /* Oct 2026: the root no longer clips the x axis. Clipping hid any element
     that overflowed instead of fixing it; the responsive sweep (qa.mjs, 18
     widths) and check-responsive now measure the real scroll width. */
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* 17px root on desktop: nothing meant to be read drops below it. Every rem in
   this sheet scales with it, so spacing opens up along with the type. */
html { font-size: 17px; }
@media (max-width: 800px) { html { font-size: 16px; } }

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Barlow', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 1rem;
  line-height: 1.65;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  /* No overflow-x here. `hidden` on body makes body the scroll container, and
     every position:sticky descendant then resolves against a box that never
     scrolls — which is why the product gallery would not pin. The root already
     clips the axis with `overflow-x: clip`, which does not create a scrollport. */
}

img, picture, video, canvas, svg { display: block; max-width: 100%; }
/* An SVG in running text must not become a block-level 300x150 default box. */
.icon-inline { display: inline-block; vertical-align: -.15em; flex: none; }
img { height: auto; }
/* Loading placeholder belongs on the photographic containers, never on `img`
   itself — a blanket background paints a solid box behind every transparent
   PNG, which is exactly what happened to the wordmark and the B Corp mark. */
.card__media, .feature, .cover { background-color: var(--bg-sunken); }
input, button, textarea, select { font: inherit; color: inherit; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
ul[class], ol[class] { list-style: none; padding: 0; }
table { border-collapse: collapse; width: 100%; }
summary { cursor: pointer; }
summary::-webkit-details-marker { display: none; }

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

::selection { background: var(--cacao-800); color: var(--paper-50); }
.surface-cacao ::selection { background: var(--brass-300); color: var(--cacao-900); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute; top: 0; left: 50%;
  transform: translate(-50%, -110%);
  z-index: 999;
  background: var(--cacao-800); color: var(--paper-50);
  padding: .75rem 1.5rem; border-radius: 0 0 var(--radius) var(--radius);
  font-size: 1rem; font-weight: 600; text-decoration: none;
  transition: transform var(--t-fast) var(--ease-out);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* --------------------------------------------------------------------------
   4. TYPOGRAPHY
   Single family sitewide by request: Barlow (stand-in for the brand's Tivoli Gothic, see fonts.css), display and body alike.
   -------------------------------------------------------------------------- */
.display, h1, h2, h3, .h1, .h2, .h3, .h4 {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -.012em;
  color: var(--text-strong);
  font-variation-settings: 'SOFT' 24, 'WONK' 1;
  text-wrap: balance;
}

.display {
  font-size: var(--fs-h1);
  font-variation-settings: 'opsz' 144, 'SOFT' 30, 'WONK' 1;
  line-height: .95;
  letter-spacing: -.015em;
}
h1, .h1 {
  font-size: var(--fs-h1);
  font-variation-settings: 'opsz' 120, 'SOFT' 26, 'WONK' 1;
  line-height: .98;
  letter-spacing: -.012em;
}
h2, .h2 {
  font-size: var(--fs-h2);
  font-variation-settings: 'opsz' 84, 'SOFT' 24, 'WONK' 1;
  letter-spacing: -.01em;
}
h3, .h3 {
  font-size: var(--fs-h3);
  font-variation-settings: 'opsz' 40, 'SOFT' 20, 'WONK' 0;
  line-height: 1.15;
  letter-spacing: -.012em;
}
.h4 {
  font-size: var(--fs-h4);
  font-variation-settings: 'opsz' 24, 'SOFT' 16, 'WONK' 0;
  line-height: 1.25;
  letter-spacing: -.012em;
}

/* Italic inside a display heading is a voice, not an emphasis: it needs the
   optical-size and wonk settings the roman gets, or it reads as a mistake. */
h1 em, h2 em, h3 em, .h1 em, .h2 em, .h3 em, .h4 em, .display em, .feature__title em {
  font-style: italic;
  font-variation-settings: 'opsz' 84, 'SOFT' 22, 'WONK' 1;
  letter-spacing: -.014em;
}

/* Eyebrow — echoes the letterspaced caps of the wordmark.
   Round 2 (G-04): the short decorative rule that used to sit in front of every
   eyebrow is gone sitewide. It carried no information and, per the client, made
   the site read like a template. The label stands alone. */
.eyebrow {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: var(--sp-4);
}

.lede {
  font-size: var(--fs-lede);
  line-height: 1.55;
  color: var(--text-muted);
  max-width: 58ch;
}
.prose { max-width: var(--measure); }
.prose > * + * { margin-top: 1.1em; }
.prose h2 { margin-top: 1.6em; }
.prose h3 { margin-top: 1.4em; }
/* A heading straight after its eyebrow belongs to it: no section-sized gap
   (G-03 — this was ~100px of nothing under every eyebrow). */
.prose .eyebrow + h1, .prose .eyebrow + h2, .prose .eyebrow + h3 { margin-top: 0; }
.prose ul, .prose ol { padding-left: 1.25rem; }
.prose li + li { margin-top: .4em; }
.prose ul { list-style: none; padding-left: 0; }
.prose ul > li {
  position: relative;
  padding-left: 1.5rem;
}
.prose ul > li::before {
  content: "";
  position: absolute; left: .25rem; top: .72em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent);
}
.prose ol { padding-left: 1.4rem; }
.prose strong { font-weight: 600; color: var(--text-strong); }
.prose a { color: var(--text-strong); text-decoration-thickness: 1px; text-underline-offset: .18em; }

/* Numerals — tabular everywhere a number is compared */
.num { font-variant-numeric: tabular-nums; }

/* The signature graphic move: cacao % as an oversized display numeral */
.pct {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-variation-settings: 'opsz' 144, 'SOFT' 40, 'WONK' 1;
  font-weight: 400;
  line-height: .8;
  letter-spacing: -.05em;
  font-variant-numeric: lining-nums tabular-nums;
}

a { color: inherit; }
a:not([class]) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  transition: text-decoration-color var(--t-fast);
}
a:not([class]):hover { text-decoration-color: currentColor; }

/* Link that reveals its underline left-to-right */
/* 44px tall hit area (SWM tap-target rule); the underline sits under the
   text, not at the bottom of the hit area. */
.link {
  text-decoration: none;
  position: relative;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}
.link::after {
  content: "";
  position: absolute; left: 0; bottom: .5rem;
  width: 100%; height: 1px;
  background: currentColor;
  transform-origin: right;
  transform: scaleX(0);
  transition: transform var(--t-base) var(--ease-out);
}
.link--static::after { transform: scaleX(1); opacity: .35; }
.link:hover::after, .link:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
  opacity: 1;
}

/* --------------------------------------------------------------------------
   5. LAYOUT
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  /* Viewport minus two gutters (4–6vw each side), capped at --wrap-max: the
     content column grows with the screen until 1560px, then stops, so a 4K or
     ultrawide monitor doesn't inflate the lead banner's aspect-ratio height past
     the viewport or blow out orphaned grid cards. */
  max-width: calc(var(--wrap-max) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--wide { max-width: 1520px; }
/* Reading measure, not a column: at 19px body this lands near 70 characters */
.wrap--narrow { max-width: 1000px; }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(1.75rem, 3.5vw, 3rem); }
.section--flush-top { padding-top: 0; }

.stack > * + * { margin-top: var(--sp-4); }
.stack-lg > * + * { margin-top: var(--sp-6); }

/* auto-fit, not auto-fill: a section with a single card should fill its row
   rather than sit in a one-third column beside two ghosts. */
.grid { display: grid; gap: var(--sp-6); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(13.5rem, 100%), 1fr)); }
/* `1fr` on the track keeps auto-fit overflow-safe, but it also means an
   orphaned card alone in the last row stretches to fill the whole row. Capping
   the CARD's own max-width (not the track) stops that growth at any container
   width without risking the overflow a fixed track max would introduce.

   Opt-in via .grid--listing, not automatic on every .grid-N: a grid built
   from a fixed, hand-written array (three "how to buy" cards, four "how it
   works" steps) can never have an orphan — its item count always equals its
   column count. Capping those anyway left every card in the row narrower
   than the row itself, so the row's own right edge no longer lined up with
   a full-width sibling below it (e.g. the "cart does the math" note under
   How to Buy). Reserve the cap for grids whose item count is actual data —
   PRODUCTS/RECIPES/ARTICLES or a collection's product list — where the count
   isn't known until build time and an incomplete last row is a real case. */
.grid--listing.grid-2 > * { max-width: 28rem; }
.grid--listing.grid-3 > * { max-width: 22rem; }
.grid--listing.grid-4 > * { max-width: 17rem; }

.split {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
}
.split--top { align-items: start; }
/* Grid items default to min-width:auto, so a wide child — the shipping table,
   a code block — refuses to shrink and pushes the whole column past the
   viewport. This was previously masked by overflow-x:hidden on body. */
.split > *, .grid > * { min-width: 0; }
@media (min-width: 62rem) {
  .split { grid-template-columns: 1fr 1fr; }
  .split--60 { grid-template-columns: 1.35fr 1fr; }
  .split--40 { grid-template-columns: 1fr 1.35fr; }
  /* `start` collapses each grid item to its content height, which leaves a
     sticky child no room to travel — the product gallery was pinned in name
     only. `stretch` gives the column the full row height so it can track. */
  .split--sticky { align-items: stretch; }
}
/* The sticky element must be a child of the stretched grid item, never the
   item itself: a grid item stretched to the row height has no room to travel. */
.split__col { min-width: 0; }

.section-head {
  display: grid;
  gap: var(--sp-4);
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
@media (min-width: 60rem) {
  .section-head--split {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
    align-items: end;
    column-gap: clamp(2rem, 6vw, 5rem);
    row-gap: var(--sp-4);
  }
}

.hairline { border: 0; border-top: 1px solid var(--line); margin: 0; }

/* The Origin Line — a vertical rule that threads numbered stages */
.origin-line { position: relative; padding-left: 2.5rem; }
.origin-line::before {
  content: "";
  position: absolute; left: .4375rem; top: .5rem; bottom: .5rem;
  width: 1px;
  background: linear-gradient(to bottom,
    var(--accent) 0%, var(--line) 22%, var(--line) 78%, transparent 100%);
}
.origin-line > li { position: relative; padding-bottom: var(--sp-6); }
.origin-line > li:last-child { padding-bottom: 0; }
.origin-line > li::before {
  content: "";
  position: absolute; left: -2.5rem; top: .55em;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--accent);
}
.origin-line > li::after {
  content: "";
  position: absolute; left: -2.15rem; top: .93em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  transform: scale(0);
  transition: transform var(--t-base) var(--ease-out);
}
.origin-line > li.is-in::after { transform: scale(1); }

/* --------------------------------------------------------------------------
   6. BUTTONS — every state designed, not just default
   -------------------------------------------------------------------------- */
/* Client note, Aug 2026: "botones y colorido: más claro, es muy oscuro".
   The primary action on a light surface was --cacao-800 (#2F1913), which is the
   wrapper frame colour and reads as black at button scale. It is now --brass-700
   (#8A5F1E), the token already carried for awards and heritage: still inside the
   packaging palette, warmer, and measurably lighter.
   Contrast on --paper-50 measures 5.48:1 — above the 4.5:1 floor, and the hover
   state inverts to the same pair, so both states pass.
   Oct 2026, round 2: superseded — the brass read as an AI-interface brown.
   The primary button is now the gold packaging stripe with cacao ink (see
   --btn-primary / --btn-primary-ink in :root). Hover inverts the same pair:
   cacao fill, gold text, 6.86:1 both ways. */
.btn {
  --btn-bg: var(--btn-primary);
  --btn-fg: var(--btn-primary-ink);
  --btn-bd: var(--btn-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .625rem;
  min-height: 3rem;
  padding: .8125rem 1.75rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  border-radius: 999px;
  font-size: var(--fs-btn);
  font-weight: 600;
  letter-spacing: -.005em;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--t-base) var(--ease-out),
              border-color var(--t-base) var(--ease-out),
              transform var(--t-fast) var(--ease-out),
              box-shadow var(--t-base) var(--ease-out);
}
/* Wipe fill — reads as chocolate flowing, not a colour swap */
.btn::before {
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  background: var(--btn-fg);
  transform: translateY(101%);
  transition: transform var(--t-base) var(--ease-out);
}
.btn:hover::before, .btn:focus-visible::before { transform: translateY(0); }
.btn:hover, .btn:focus-visible { color: var(--btn-bg); }
.btn:active { transform: translateY(1px); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--text-strong);
  --btn-bd: var(--line);
}
.btn--ghost::before { background: var(--text-strong); }
.btn--ghost:hover, .btn--ghost:focus-visible {
  color: var(--bg);
  border-color: var(--text-strong);
}
.surface-cacao .btn, .hero .btn {
  --btn-bg: var(--paper-50);
  --btn-fg: var(--cacao-900);
  --btn-bd: var(--paper-50);
}
.surface-cacao .btn::before, .hero .btn::before { background: var(--brass-300); }
.surface-cacao .btn:hover, .surface-cacao .btn:focus-visible,
.hero .btn:hover, .hero .btn:focus-visible { color: var(--cacao-900); }

.surface-cacao .btn--ghost, .hero .btn--ghost {
  --btn-bg: transparent;
  --btn-fg: #EFE4D7;
  --btn-bd: rgba(239,228,215,.4);
}
.surface-cacao .btn--ghost::before, .hero .btn--ghost::before { background: var(--paper-50); }
.surface-cacao .btn--ghost:hover, .surface-cacao .btn--ghost:focus-visible,
.hero .btn--ghost:hover, .hero .btn--ghost:focus-visible {
  color: var(--cacao-900);
  border-color: var(--paper-50);
}

/* Hero secondary CTA only ("Shop Chocolate") — white at
   rest, gold on hover, no wipe-fill. Placed after every other .btn--ghost
   rule above so it wins on source order at equal specificity; scoped to its
   own class rather than editing .btn--ghost itself, which is still used
   as-is by the identical button in the closing CTA scene. */
.btn--ghost-gold {
  --btn-fg: var(--paper-50);
  --btn-bd: rgba(253, 251, 247, .5);
}
.btn--ghost-gold::before { display: none; }
.btn--ghost-gold:hover, .btn--ghost-gold:focus-visible {
  color: var(--brass-300);
  border-color: var(--brass-300);
}

/* Sizes differ in padding and height only — the type size is the one button
   token (--fs-btn), so a small button and a large one read as the same voice. */
.btn--sm { min-height: 2.75rem; padding: .4375rem 1.125rem; }
.btn--lg { min-height: 3.5rem; padding: 1rem 2.25rem; }
.btn--block { display: flex; width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: .42; cursor: not-allowed; pointer-events: none;
}
.btn.is-loading { color: transparent; pointer-events: none; }
.btn.is-loading::after {
  content: "";
  position: absolute; inset: 0; margin: auto;
  width: 1.125rem; height: 1.125rem;
  border: 2px solid var(--btn-fg);
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* --------------------------------------------------------------------------
   7. HEADER + NAVIGATION
   -------------------------------------------------------------------------- */
/* Round 2 (H-03): the announcement bar gets more presence — a little taller
   (2.375 -> 2.75rem) and a size up in type (.9375 -> 1.0625rem). */
.announce {
  background: var(--paper-50);
  color: var(--cacao-700);
  border-bottom: 1px solid var(--paper-300);
  font-size: 1.0625rem;
  letter-spacing: .02em;
  position: relative;
  z-index: calc(var(--z-header) + 1);
  overflow: hidden;
}
.announce__track {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0 1.25rem;
  min-height: 2.75rem;
  padding: .25rem var(--gutter);
  text-align: center;
}
.announce__item { display: flex; align-items: center; gap: .5rem; }
.announce__item strong { color: var(--cacao-900); font-weight: 600; }
.announce a { color: inherit; text-underline-offset: .2em; display: inline-flex; align-items: center; min-height: 2.75rem; }
.announce__sep {
  width: 3px; height: 3px; border-radius: 50%;
  background: currentColor; opacity: .45; flex: none;
  margin-right: 1rem;
}
/* The third message (bulk quote) only shows where all three fit on one line at
   the larger type size; below 80rem the bar keeps the offer and the weight rule. */
.announce__item--extra:last-child { display: none; }
@media (min-width: 80rem) { .announce__item--extra:last-child { display: flex; } }
/* Narrow screens keep only the offer. The long tail and the two secondary
   messages are what pushed the document past the viewport on a 390px phone. */
@media (max-width: 60rem) {
  .announce__track { gap: 0 1rem; font-size: 1rem; }
  .announce__item--extra { display: none; }
}
@media (max-width: 26rem) {
  .announce__long { display: none; }
}

/* Dark chrome throughout: it reads as one continuous frame over the black
   scenes and over the white bands alike, which is what makes the wipe feel
   like one object rather than a series of pages. */
.header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--cacao-900);
  color: var(--paper-100);
  /* The bar paints itself dark but never opted into the dark token scope, so
     --text-strong and --accent still resolved from the paper scope. The result
     was an active nav item set in near-black on near-black — on /shop,
     /academy, /about and /support the current page's label was invisible, with
     only its underline showing. Found while measuring the header for the
     bigger wordmark. */
  --text-strong: var(--paper-50);
  --accent: var(--brass-300);
  transition: box-shadow var(--t-base);
}
.header.is-stuck { box-shadow: 0 8px 30px -18px rgba(0,0,0,.9); }
/* Oct 2026, client note: "el logo se percibe demasiado pequeño — darle mayor
   tamaño y protagonismo; evaluar alternativas con el logo centrado".
   The wordmark used to share one row with six nav items and three icons, so
   it only ever got what they left over. Now it owns the center column:
     · mobile — menu left, wordmark center, cart right (search lives in the
       drawer). The two side columns are equal 1fr tracks, so the mark is
       optically centered, and at 320px each side still keeps its 44px target.
     · desktop (>=1024) — the navigation drops to its own row under the mark.
   Measured widths: 160px at 320, 180px at 360, 195px at 390, 238px from 768
   to 1439 and 272px from 1440 up — against 152 / 152 / 160 / 187 / 234 before. */
.header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  grid-template-areas: "start brand end";
  align-items: center;
  column-gap: var(--sp-2);
  min-height: var(--header-h);
  padding-block: var(--sp-2);
}
.header__start {
  grid-area: start;
  justify-self: start;
  display: flex; align-items: center; gap: .125rem;
  min-width: 0;
}
.brand { grid-area: brand; justify-self: center; display: block; line-height: 0; }
/* Round 2 / client approval: the header carries the original VERTICAL logotype
   (F mark over the name), sized by height. 76px on a phone — it fills the
   92px bar with the bar's own padding — and 6.5rem from desktop up, where the
   navigation still sits on its own row beneath it. */
.brand img { width: auto; height: 4.75rem; }
.header__actions {
  grid-area: end;
  justify-self: end;
  display: flex; align-items: center; gap: .125rem;
  min-width: 0;
}
/* .header prefix: .icon-btn (declared later) sets display:grid at the same specificity */
.header .header__search { display: none; }
.header .icon-btn { color: var(--paper-100); }
.header .icon-btn:hover { background: rgba(239,228,215,.12); }
.header .icon-btn__count {
  background: var(--paper-50);
  color: var(--cacao-900);
  border-color: var(--cacao-900);
}

.nav { display: none; }

@media (min-width: 1024px) {
  .header__inner {
    grid-template-areas: "start brand end" "nav nav nav";
    row-gap: var(--sp-2);
    padding-block: var(--sp-4) 0;
  }
  .header .header__search { display: grid; }
  .nav {
    display: block;
    grid-area: nav;
    border-top: 1px solid rgba(255,255,255,.10);
  }
  .nav__list { justify-content: center; }
}
@media (min-width: 1024px) { .brand img { height: 6.5rem; } }
/* Measured rendered header heights (17px root): 184.5px from 1024 up with the
   vertical logotype (round 2) — one value for every desktop width now that the
   logo no longer grows at 1440. Sticky offsets and anchor jumps read these. */
@media (min-width: 1024px) { :root { --header-h: 10.875rem; } }

.nav__list { display: flex; align-items: center; gap: clamp(1.25rem, 2.6vw, 2.75rem); }
.nav__link {
  display: block;
  padding: .625rem .125rem;
  font-size: .9375rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  position: relative;
  white-space: nowrap;
  transition: color var(--t-fast);
}
.nav__link::after {
  content: "";
  position: absolute; left: .25rem; right: .25rem; bottom: .3125rem;
  height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: right;
  transition: transform var(--t-base) var(--ease-out);
}
.nav__link:hover::after, .nav__link:focus-visible::after { transform: scaleX(1); transform-origin: left; }
.nav__link[aria-current="page"] { color: var(--text-strong); font-weight: 600; }
.nav__link[aria-current="page"]::after { transform: scaleX(1); background: var(--accent); height: 2px; }

.icon-btn {
  width: 2.75rem; height: 2.75rem;
  display: grid; place-items: center;
  background: none; border: 0; border-radius: 50%;
  cursor: pointer; position: relative;
  color: var(--text);
  transition: background var(--t-fast), color var(--t-fast);
}
.icon-btn:hover { background: var(--paper-300); }
.icon-btn svg { width: 1.25rem; height: 1.25rem; }
.icon-btn__count {
  position: absolute; top: .3125rem; right: .3125rem;
  min-width: 1.125rem; height: 1.125rem; padding: 0 .25rem;
  display: grid; place-items: center;
  background: var(--cacao-800); color: var(--paper-50);
  border-radius: 999px;
  font-size: .625rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
  border: 2px solid var(--paper-100);
  transition: transform var(--t-base) var(--ease-out);
}
.icon-btn__count[hidden] { display: none; }
.icon-btn__count.is-bump { animation: bump .45s var(--ease-out); }
@keyframes bump { 0%,100% { transform: scale(1); } 40% { transform: scale(1.38); } }

@media (min-width: 1024px) { .nav-toggle { display: none; } }

/* Mobile drawer */
.mobile-nav {
  position: fixed; inset: 0;
  z-index: var(--z-drawer);
  background: var(--cacao-850);
  color: #EFE4D7;
  display: grid;
  grid-template-rows: auto 1fr auto;
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--t-slow) var(--ease-out), visibility var(--t-slow);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.mobile-nav.is-open { transform: translateX(0); visibility: visible; }
.mobile-nav__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4) var(--gutter);
  border-bottom: 1px solid rgba(239,228,215,.14);
  min-height: 4.5rem;
}
.mobile-nav__head .icon-btn { color: #EFE4D7; }
.mobile-nav__head .icon-btn:hover { background: rgba(239,228,215,.1); }
/* .mobile-nav prefix: the ul[class] reset (0,1,1) was zeroing this padding */
.mobile-nav .mobile-nav__list { padding: var(--sp-5) var(--gutter); }
.mobile-nav__list li { border-bottom: 1px solid rgba(239,228,215,.1); }
.mobile-nav__list a {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1rem 0;
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-size: 1.75rem;
  font-variation-settings: 'opsz' 40, 'SOFT' 22, 'WONK' 1;
  letter-spacing: -.012em;
  text-decoration: none;
  color: var(--paper-50);
}
.mobile-nav__list a span { font-family: 'Barlow', sans-serif; font-size: 1rem; letter-spacing: .16em; text-transform: uppercase; color: var(--cacao-300); }
.mobile-nav__foot { padding: var(--sp-5) var(--gutter) var(--sp-6); border-top: 1px solid rgba(239,228,215,.14); }

.backdrop {
  position: fixed; inset: 0;
  z-index: calc(var(--z-drawer) - 1);
  background: rgba(20,11,8,.5);
  backdrop-filter: blur(2px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--t-base), visibility var(--t-base);
}
.backdrop.is-open { opacity: 1; visibility: visible; }

/* --------------------------------------------------------------------------
   7b. SCENES — full-viewport sticky imagery wiped by opaque bands.

   The image layer pins with position:sticky for the height of its scene while
   the copy scrolls across it. The next band is an ordinary opaque section, and
   because it comes later in the document it paints over the pinned image and
   wipes it away — revealing the next scene's image underneath. No scroll
   hijacking, no JS, and it degrades to a plain stacked page if sticky is
   unsupported.
   -------------------------------------------------------------------------- */
/* The scene itself is the sticky element, pinned at the top of the viewport
   for exactly one screen. Bands are ordinary opaque siblings, and because
   painting follows DOM order a band always covers the scene before it while
   the next scene covers that band — which is the wipe.

   The previous version made an inner layer sticky inside a container of the
   same height. A sticky element whose container is no taller than itself has
   zero travel, so it never pins: the whole sequence rendered static. */
.scene {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--cacao-900);
  --bg:          var(--cacao-850);
  --bg-raised:   #241612;
  --bg-sunken:   var(--cacao-900);
  --text:        #EFE4D7;
  --text-strong: var(--paper-50);
  --text-muted:  var(--cacao-300);
  --line:        rgba(239,228,215,.16);
  --line-soft:   rgba(239,228,215,.09);
  --accent:      var(--brass-300);
  --on-accent:   var(--cacao-900);
  --focus:       var(--brass-300);
  color: var(--text);
}
/* Round 2 (HM-12, Crafted for Creators): a compact scene. It keeps the photograph,
   the scrim and the plate, but it is no longer a pinned full screen — it is as
   tall as its copy needs plus air, so the section below it shows. */
.scene.scene--compact {
  position: relative;
  height: auto;
  min-height: 86svh;   /* was ~56svh: 30svh taller, per the Sr. Manuel (11 Oct) */
}
/* Parallax: the photograph is taller than its frame and drifts against the
   scroll (initParallax in app.js). Plate and copy are centered. Without JS, or
   with reduced motion, it is simply a still photograph. */
.scene--parallax .scene__media { top: -12%; bottom: -12%; will-change: transform; }
.scene.scene--compact .scene__content {
  height: auto;
  min-height: inherit;
  padding-block: clamp(2rem, 5vh, 3.5rem);
}
.scene__media { position: absolute; inset: 0; }
/* Hero video (home): fades in over the photograph once it is actually playing.
   No grade filter — it was shot on a cinema camera and keeps its own look; the
   scene's scrims still sit above it for the headline's contrast. */
.scene__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 1.2s var(--ease-out); }
.scene__video.is-playing { opacity: 1; }
/* The source photography ranges from a bright production kitchen to a night
   shot of drying trays. Grading it to one dark register is what makes a set of
   unrelated images read as a single campaign — and it buys the contrast the
   headline needs. */
.scene__media img {
  width: 100%; height: 100%; object-fit: cover;
  filter: var(--grade-scene);
}

/* Two rules govern the scrims, and the previous version broke both.

   1. The photograph has to stay a photograph. A grade, a vignette and a
      directional scrim stacked on top of each other compounded into a flat
      black sheet — the image was still loading, just no longer visible.
   2. Darkening is local. Only the band actually sitting under the copy needs
      it; the subject side of the frame is left alone.

   Contrast for the type is bought back with a soft shadow instead, which costs
   the image nothing. */

/* Edge vignette only: seats the frame, protects the header and the bottom. */
.scene__media::before {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background:
    radial-gradient(130% 100% at 50% 45%, transparent 62%, rgba(8,5,3,.3) 100%),
    linear-gradient(to bottom, rgba(8,5,3,.48) 0%, transparent 14%, transparent 84%, rgba(8,5,3,.42) 100%);
}
/* A short, modest gradient — it only has to lift copy that already sits on a
   dark part of the frame, so it clears well before the midpoint and leaves
   most of the photograph untouched. */
.scene__media::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(to right,
    rgba(8,5,3,.82) 0%, rgba(8,5,3,.6) 26%, rgba(8,5,3,.22) 44%, transparent 58%);
}
.scene--right .scene__media::after {
  background: linear-gradient(to left,
    rgba(8,5,3,.82) 0%, rgba(8,5,3,.6) 26%, rgba(8,5,3,.22) 44%, transparent 58%);
}
.scene--center .scene__media::after {
  background: radial-gradient(58% 54% at 50% 50%,
    rgba(8,5,3,.6) 0%, rgba(8,5,3,.42) 48%, rgba(8,5,3,.13) 78%, transparent 100%);
}

/* A soft halo buys contrast from the type instead of from the photograph.
   Invisible at reading distance; worth roughly two stops of separation. */
.scene__title,
.scene__lede,
.scene .eyebrow,
.scene .attrs { text-shadow: 0 1px 2px rgba(8,5,3,.5), 0 2px 28px rgba(8,5,3,.6); }
.scene__plate .scene__title,
.scene__plate .scene__lede { text-shadow: none; }
/* z-index 2 is load-bearing. The media layer's ::before and ::after carry
   z-index:1, and .scene__media does not create a stacking context, so those
   scrims join the scene's own stacking context. Without an explicit index
   here, `position: relative; z-index: auto` puts the copy BELOW them — the
   veils paint over the text rather than behind it, which is why the headline
   rendered grey while measuring near-white on a flat ground. */
.scene__content {
  position: relative;
  z-index: 2;
  height: 100%;
  display: grid;
  align-items: center;
  padding-block: clamp(3rem, 7vh, 4.5rem);
}
/* A pinned scene sits under the sticky header (9.4–10rem tall from 1024px), so
   its copy has to clear it: the top padding is the header plus a little air. */
@media (min-width: 1024px) {
  .scene--clear-header .scene__content { padding-top: calc(var(--header-h) + 1rem); padding-bottom: 2rem; }
}
/* Round 2 [PENDIENTE] marker for a scene's background photograph. It sits in a
   corner of the scene, outside the copy plate, so it never makes the plate
   taller than the screen it is pinned to. */
.scene__flag { padding: 0 var(--gutter) var(--sp-4); position: relative; z-index: 3; }
.scene__flag .provenance { margin-top: 0; max-width: 26rem; }
@media (min-width: 1024px) {
  .scene__flag { position: absolute; left: 0; bottom: 1.25rem; padding: 0 var(--gutter); }
}

.scene__inner { width: min(100%, 46rem); }
.scene--center .scene__inner { width: min(100%, 60rem); margin-inline: auto; text-align: center; }
.scene--center .eyebrow { justify-content: center; }
.scene--center .scene__lede { margin-inline: auto; }
.scene--right .scene__inner { margin-left: auto; text-align: right; }
.scene--right .eyebrow { justify-content: flex-end; }
.scene__lede {
  max-width: 54ch;
  color: #EFE6DC;                 /* 12:1 against the scrimmed image */
  margin-top: var(--sp-4);
  font-size: var(--fs-lede);
  line-height: 1.6;
}
.scene__title { color: var(--paper-50); }

/* A translucent plate for scenes where the copy needs its own ground */
/* A plate is the honest answer for a bright, busy frame. Luminance contrast
   alone does not make type readable over texture — the eye needs a quiet
   ground. This gives one without dimming the rest of the photograph. */
.scene__plate {
  background: rgba(10,6,4,.86);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  padding: clamp(1rem, 3vw, 2.5rem);
  border: 1px solid rgba(239,228,215,.16);
  width: min(100%, 44rem);
  margin-inline: 0;
}
.scene--center .scene__plate { margin-inline: auto; text-align: center; }
.scene--right .scene__plate { margin-left: auto; }
.scene--center .scene__plate .scene__lede { max-width: 58ch; margin-inline: auto; }
/* On a plate the scrim is redundant — let the photograph breathe around it. */
.scene:has(.scene__plate) .scene__media::after { opacity: .45; }

/* Opaque band — this is what wipes the pinned image */
.band {
  position: relative;
  z-index: 1;
  /* Tokens, not literals — so a section can opt into .surface-cacao or
     .surface-kraft the way the architecture note at the top of this file
     says every section should be able to. A hardcoded paper-50 here silently
     out-cascaded surface-cacao's own background rule (same specificity,
     later source order) and left a "dark" section rendering pale. */
  background: var(--bg, var(--paper-50));
  color: var(--text, var(--cacao-800));
  padding-block: clamp(2.5rem, 6vh, 4.5rem);
}
.band--kraft { background: var(--paper-200); }
.band--tight { padding-block: clamp(2rem, 4vh, 3rem); }
/* A masthead band: slim, all air, no grid — it announces the store */
.band--entry { padding-block: clamp(2.5rem, 6vh, 4rem) clamp(1.5rem, 3vh, 2rem); }
.band--flush-top { padding-top: 0; }
/* Set --band-vh inline per section (e.g. style="--band-vh:90vh") to reach a
   deliberate on-screen presence without hand-tuning padding. Content still
   centers gracefully if it's taller than the target on a short viewport. */
@media (min-width: 1024px) {
  .band--min-vh { min-height: var(--band-vh, 100svh); display: flex; align-items: center; }
  .band--min-vh > .wrap { width: 100%; }
}

/* --------------------------------------------------------------------------
   9d. HOW TO BUY — dark band, light cards. Three fixes on top of the base
   .card/.surface-paper/.section-head--split rules, scoped to this section:

   1. Square corners. The generic .card carries --radius-lg (14px) because
      most of its uses sit in ordinary light bands; every OTHER full-bleed
      moment added this pass (the accordion, the application grid) is
      square-edged, and next to those a rounded card here read inconsistent.
   2. A visible hover. .card:hover's default state is a dark box-shadow lifting
      a light card off a light background — cast onto THIS section's dark
      brown background instead, that shadow is close enough in value to the
      backdrop to nearly disappear. Swapped for a brass glow, which is bright
      against dark rather than merely darker than a background that's already
      dark.
   3. A centered header instead of the left/right split. section-head--split
      puts the eyebrow+title in one column and the lede in another; at this
      section's unusual height and drama, the empty gap between them read as
      the section coming apart rather than as intentional whitespace.
   -------------------------------------------------------------------------- */
#how-to-buy .card { border-radius: 0; }
#how-to-buy .card:hover {
  border-color: var(--brass-500);
  box-shadow: 0 22px 48px -18px rgba(0,0,0,.65), 0 0 0 1px var(--brass-500);
}
@media (min-width: 60rem) {
  #how-to-buy .section-head--split {
    grid-template-columns: 1fr;
    text-align: center;
  }
  #how-to-buy .section-head--split > div:first-child { margin-inline: auto; }
  #how-to-buy .section-head--split .eyebrow { justify-content: center; }
  #how-to-buy .section-head--split .lede { margin-inline: auto; }
}

/* Below the desktop breakpoint the scene stops being a fixed-height stage and
   becomes a section that grows with its copy. A pinned 100svh panel clips
   whatever does not fit, and on a 360x800 phone the hero's headline, lede,
   attribute strip and two buttons do not fit. Legibility outranks the effect. */
@media (max-width: 1023px) {
  .scene { position: relative; height: auto; min-height: 100svh; }
  .scene__content { height: auto; min-height: 100svh; }
}
/* Same reasoning for short viewports — a laptop in a shallow window, or a
   phone held sideways. */
@media (max-height: 620px) {
  .scene { position: relative; height: auto; min-height: 100svh; }
  .scene__content { height: auto; min-height: 100svh; padding-block: 4rem; }
}

/* Without sticky the sequence degrades to plain stacked full-height sections */
@supports not (position: sticky) {
  .scene { position: relative; height: auto; min-height: 100svh; }
}
/* Pinning a screen-height panel per section is disorienting for anyone who has
   asked for less motion; give them the same content as an ordinary stack. */
@media (prefers-reduced-motion: reduce) {
  .scene { position: relative; }
}

/* --------------------------------------------------------------------------
   7c. DISPLAY VOICE — roman and italic alternating inside one headline
   -------------------------------------------------------------------------- */
.dh {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-weight: 500;
  font-variation-settings: 'opsz' 144, 'SOFT' 18, 'WONK' 0;
  line-height: 1.02;
  letter-spacing: -.012em;
  text-wrap: balance;
  color: var(--text-strong);
}
.dh em, .dh i {
  font-style: italic;
  font-variation-settings: 'opsz' 144, 'SOFT' 22, 'WONK' 1;
  letter-spacing: -.012em;
}
/* Round 2 (G-02): the display voice sets the same two sizes as the plain
   headings — xl is the H1 level, lg and md are the H2 level. There is no third
   "big" size left for a section title to drift to. */
.dh--xl { font-size: var(--fs-h1); }
.dh--lg, .dh--md { font-size: var(--fs-h2); }

/* Attribute strip: letterspaced caps separated by lozenges */
.attrs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: inherit;
  gap: .5rem 1.125rem;
  margin-top: var(--sp-5);
  font-size: clamp(.6875rem, .85vw, .8125rem);
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
}
.scene--center .attrs { justify-content: center; }
.attrs li { display: flex; align-items: center; gap: 1.125rem; }
.attrs li + li::before {
  content: "◆";
  font-size: .5em;
  letter-spacing: 0;
  opacity: .65;
  transform: translateY(-.1em);
}

/* --------------------------------------------------------------------------
   8. HERO
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background: var(--cacao-900);
  color: #EFE4D7;
  min-height: min(94svh, 54rem);
  display: grid;
  align-items: end;
  overflow: hidden;
  isolation: isolate;
}
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
.hero::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to top, rgba(20,11,8,.94) 0%, rgba(20,11,8,.72) 34%, rgba(20,11,8,.22) 68%, rgba(20,11,8,.42) 100%),
    linear-gradient(to right, rgba(20,11,8,.7) 0%, transparent 62%);
}
.hero__inner { padding-block: clamp(2rem, 6vw, 4rem); position: relative; }
/* Round 2: the About hero is a compact banner, not a screen. */
.hero--compact { min-height: min(52svh, 28rem); }
.hero .eyebrow { color: var(--brass-300); }
/* The page-title size, same as every H1 on the site (G-02). */
.hero__title {
  color: var(--paper-50);
  max-width: 17ch;
  font-size: var(--fs-h1);
  letter-spacing: -.012em;
  line-height: .98;
}
.hero__lede { color: #DDCFC0; max-width: 52ch; margin-top: var(--sp-4); font-size: var(--fs-lede); }
.hero__lede + .hero__lede { margin-top: var(--sp-3); }
.hero__actions { margin-top: var(--sp-6); }
.hero__meta {
  margin-top: clamp(2.5rem, 6vw, 4rem);
  padding-top: var(--sp-5);
  border-top: 1px solid rgba(239,228,215,.2);
  display: flex; flex-wrap: wrap; gap: var(--sp-5) clamp(1.5rem, 4vw, 3.5rem);
}
.hero__stat { }
.hero__stat dt { font-size: .9375rem; letter-spacing: .18em; text-transform: uppercase; color: var(--cacao-300); margin-bottom: .3125rem; }
.hero__stat dd {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-size: clamp(1.25rem, 2.2vw, 1.75rem);
  font-variation-settings: 'opsz' 40, 'SOFT' 20, 'WONK' 1;
  line-height: 1;
  color: var(--paper-50);
}

.scroll-cue {
  position: absolute; bottom: var(--sp-5); right: var(--gutter);
  display: none; align-items: center; gap: .625rem;
  font-size: .9375rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--cacao-300);
  text-decoration: none;
}
@media (min-width: 62rem) { .scroll-cue { display: flex; } }
.scroll-cue__rule { width: 1px; height: 3rem; background: linear-gradient(var(--brass-300), transparent); }

/* --------------------------------------------------------------------------
   9. CARDS
   -------------------------------------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  background: var(--bg-raised);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  overflow: hidden;
  position: relative;
  transition: border-color var(--t-base), transform var(--t-base) var(--ease-out), box-shadow var(--t-base);
}
.card:hover { border-color: var(--line); transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.card__body { padding: var(--sp-5); display: flex; flex-direction: column; flex: 1; gap: var(--sp-3); }
.card__media { position: relative; overflow: hidden; background: var(--bg-sunken); }
.card__media img {
  width: 100%; height: 100%; object-fit: cover;
  filter: var(--grade-card);
  transition: transform var(--t-slow) var(--ease-out), filter var(--t-base);
}
.card:hover .card__media img { filter: none; }
/* Packshots are cut-outs on transparent, not photographs — grading them just
   dims the product. */
.product-card .card__media img { filter: none; }
.feature img { filter: var(--grade-card); }
.card:hover .card__media img { transform: scale(1.04); }
/* Whole card clickable, but the real link keeps its own semantics */
.card__link::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.card__link { text-decoration: none; }

/* --------------------------------------------------------------------------
   PRODUCT STAGE — the packshot's ground on a product page.
   A dark stage with a floor gradient reads as studio lighting; the beige box
   with a hairline border read as a placeholder frame.
   -------------------------------------------------------------------------- */
/* Round 2 (SH-07): the black stage is gone. The packshot now sits on the same
   light ground as the rest of the site — paper, with a faint wash of the
   variety color rising from the floor. */
.product-stage {
  position: relative;
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: clamp(1.75rem, 4vw, 3rem);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background:
    radial-gradient(90% 70% at 50% 108%, color-mix(in srgb, var(--v, var(--cacao-600)) 14%, transparent) 0%, transparent 68%),
    var(--bg-sunken);
}
/* width/height 100% + contain, not max-height: a percentage max-height inside
   this aspect-ratio grid never resolved, so the near-square 2 lb bags (Oct
   2026) overflowed the stage and lost their bottom edge. */
.product-stage img {
  width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 18px 24px rgba(47,25,19,.2));
}

/* Product card — the variety colour lives in a top rule + the % numeral */
.product-card { --v: var(--cacao-600); }
.product-card::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--v);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--t-base) var(--ease-out);
  z-index: 2;
}
.product-card:hover::before, .product-card:focus-within::before { transform: scaleX(1); }
.product-card .card__media {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  background:
    radial-gradient(120% 90% at 50% 108%, color-mix(in srgb, var(--v) 12%, transparent) 0%, transparent 62%),
    var(--bg-sunken);
}
.product-card .card__media img {
  width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 14px 22px rgba(47,25,19,.16));
}
.product-card__pct {
  position: absolute; top: .5rem; right: .875rem;
  font-size: clamp(2.75rem, 5vw, 3.75rem);
  color: var(--v);
  opacity: .17;
  pointer-events: none;
  transition: opacity var(--t-base);
}
.product-card:hover .product-card__pct { opacity: .3; }
/* Round 2 (SH-04..06): the product name is the first and largest thing on the
   card (card-title level of the scale, weight 500). "Single Origin Venezuela"
   drops a whole step: smallest label size, sentence case, no letterspacing —
   quiet, where it used to be an uppercase line competing with the name. The
   flavor notes are gone from the card; they live on the product page. */
.product-card__name { font-weight: 500; line-height: 1.2; }
.product-card__origin {
  font-size: var(--fs-small); letter-spacing: 0; text-transform: none; font-weight: 400;
  color: var(--text-muted);
  display: flex; align-items: center; gap: .5rem;
}
.product-card__origin::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--v); flex: none;
}
.product-card__foot {
  margin-top: auto; padding-top: var(--sp-3);
  border-top: 1px solid var(--line-soft);
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3);
}
.product-card__price { font-weight: 600; font-size: 1rem; font-variant-numeric: tabular-nums; }
.product-card__price small { font-weight: 400; font-size: 1rem; color: var(--text-muted); }
.product-card__from { font-size: .9375rem; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); }

/* --------------------------------------------------------------------------
   COLLECTION CARD — the entrance to the store.
   Full-bleed image, title set in the display serif over the photograph. Two
   per row on desktop so ten collections read as five deliberate pairs rather
   than a thumbnail grid.
   -------------------------------------------------------------------------- */
.collection-grid {
  display: grid;
  gap: clamp(1rem, 1.6vw, 1.75rem);
  grid-template-columns: 1fr;
}
@media (min-width: 768px) {
  .collection-grid { grid-template-columns: repeat(2, 1fr); }
  /* The deepest collection leads the grid at full width. Ten equal tiles gave
     Couverture (7 SKUs) the same weight as Cacao Butter (1) — no hierarchy by
     catalogue depth, which is the first thing a buyer scans for. */
  .collection-card--lead { grid-column: 1 / -1; aspect-ratio: 21 / 9; }
  .collection-card--lead .collection-card__title { font-size: var(--fs-h2); }
  .collection-card--lead .collection-card__blurb { max-width: 46ch; font-size: 1.0625rem; }
}

.collection-card {
  position: relative;
  display: block;
  aspect-ratio: 16 / 11;
  overflow: hidden;
  border-radius: 2px;
  text-decoration: none;
  color: var(--paper-50);
  isolation: isolate;
  background: var(--cacao-900);
}
@media (min-width: 768px) { .collection-card { aspect-ratio: 4 / 3; } }

.collection-card img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: var(--grade-card);
  transition: transform .8s var(--ease-out), filter var(--t-base);
}
/* The title sits about a third of the way up, not at the very bottom, so the
   gradient has to still be substantial there — several of these frames are
   pale (cocoa nibs on a light bench, a tasting flat-lay on wicker). */
.collection-card::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(8,5,3,.97) 0%, rgba(8,5,3,.94) 32%, rgba(8,5,3,.78) 50%, rgba(8,5,3,.35) 72%, transparent 94%);
  transition: background var(--t-base);
}
.collection-card:hover img,
.collection-card:focus-visible img { transform: scale(1.045); filter: brightness(.8) saturate(1); }

.collection-card__body {
  position: relative; z-index: 1;
  height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: clamp(1.5rem, 2.6vw, 2.5rem);
}
.collection-card__title {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-weight: 400;
  font-size: var(--fs-h3);
  font-variation-settings: 'opsz' 84, 'SOFT' 20, 'WONK' 1;
  line-height: 1.05;
  letter-spacing: -.012em;
  color: var(--paper-50);
}
.collection-card__blurb {
  margin-top: .5rem;
  color: rgba(240,231,220,.86);
  max-width: 34ch;
}
.collection-card__count {
  margin-top: 1rem;
  padding-top: .875rem;
  border-top: 1px solid rgba(239,228,215,.28);
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  font-size: .875rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(240,231,220,.78);
}
.collection-card__count span:last-child {
  transition: transform var(--t-base) var(--ease-out);
}
.collection-card:hover .collection-card__count span:last-child { transform: translateX(.375rem); }

/* --------------------------------------------------------------------------
   9b. SHOP ACCORDION — the full-screen "Shop by Product" entrance.
   Named shop-accordion, not accordion: the FAQ/legal pages already own
   .accordion/.accordion__item/.accordion__panel for their <details> Q&A
   component (see PAGE PROSE COMPONENTS below) — reusing that name here
   silently overrode their padding, height and flex layout. Different
   component, different name, even though both are "an accordion."

   Mobile-first: the base rule is a plain stacked list of image rows, no JS,
   nothing to hover. The horizontal expanding-panel behaviour is a >=1024px
   enhancement layered on top, because hover has nothing to attach to on a
   touch screen — degrading gracefully beats faking hover with a tap.
   -------------------------------------------------------------------------- */
.shop-accordion {
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--cacao-900);
}
/* Set by initShopAccordion for exactly one frame while it applies the panels'
   first --panel-w value, so that initial set doesn't itself animate. */
.shop-accordion--no-transition .shop-accordion__panel { transition: none !important; }
.shop-accordion__panel {
  position: relative;
  display: block;
  height: 16rem;
  overflow: hidden;
  text-decoration: none;
  color: var(--paper-50);
}
.shop-accordion__media,
.shop-accordion__media img { position: absolute; inset: 0; width: 100%; height: 100%; }
.shop-accordion__media img { object-fit: cover; filter: var(--grade-scene); }
/* Scrim: same two-layer logic as .scene__media — a vignette plus a local
   gradient under the copy, never a flat wash over the whole photograph. */
.shop-accordion__panel::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(to top, rgba(8,5,3,.88) 0%, rgba(8,5,3,.4) 42%, rgba(8,5,3,.05) 68%, transparent 100%);
}
.shop-accordion__label { position: absolute; inset: 0; z-index: 2; padding: 1.25rem; display: flex; align-items: flex-end; }
.shop-accordion__label-vertical { display: none; }
.shop-accordion__label-full {
  display: flex; flex-direction: column; gap: .375rem;
  width: 100%;
}
.shop-accordion__title {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-weight: 400;
  font-size: var(--fs-h3);
  font-variation-settings: 'opsz' 60, 'SOFT' 20, 'WONK' 1;
  letter-spacing: -.012em;
  color: var(--paper-50);
}
.shop-accordion__blurb { color: rgba(240,231,220,.86); font-size: .9375rem; max-width: 34ch; }
.shop-accordion__count {
  margin-top: .25rem;
  display: flex; align-items: center; gap: .5rem;
  font-size: .875rem; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(240,231,220,.78);
}
.shop-accordion__count svg { transition: transform var(--t-base) var(--ease-out); }
.shop-accordion__panel:hover .shop-accordion__count svg,
.shop-accordion__panel:focus-visible .shop-accordion__count svg { transform: translateX(.375rem); }

/* Round 2: seven panels, and no longer a full screen — the next section peeks
   in under it (G-03). The 80% has no photograph yet: its panel is the cacao
   ground washed with the variety color, plus a [PENDIENTE] line. */
.shop-accordion__media--empty {
  background:
    radial-gradient(90% 70% at 50% 100%, color-mix(in srgb, var(--v, var(--cacao-600)) 55%, transparent) 0%, transparent 70%),
    var(--cacao-850);
}
.shop-accordion__pending { font-size: var(--fs-small); color: var(--brass-300); }
@media (min-width: 1024px) {
  .shop-accordion {
    flex-direction: row;
    gap: 0;
    height: min(78svh, 44rem);
  }
  /* Calmer closed state (Sr. Manuel, 11 Oct): a closed panel is only the
     product's own color — the band of its bag — with its percentage. The
     photograph arrives when the panel opens. --ink is set per panel at build
     time for contrast on that color. */
  .shop-accordion__panel { background: var(--v, var(--cacao-850)); }
  .shop-accordion__panel .shop-accordion__media { opacity: 0; transition: opacity 480ms var(--ease-out); }
  .shop-accordion__panel.is-active .shop-accordion__media { opacity: 1; }
  .shop-accordion__panel::after { opacity: 0; transition: opacity 480ms var(--ease-out); }
  .shop-accordion__panel.is-active::after { opacity: 1; }
  .shop-accordion__label-vertical { color: var(--ink, var(--paper-50)); font-size: clamp(1.5rem, 2.2vw, 2.125rem); font-weight: 500; }
  .shop-accordion__panel {
    height: auto;
    flex: 0 0 var(--panel-w, 10%);
    min-width: 0;
    border-right: 1px solid rgba(239,228,215,.14);
  }
  /* Every panel also carries [data-reveal] for its scroll-in fade, and that
     selector declares its OWN transition (opacity + transform) — same
     specificity as .shop-accordion__panel, later in the file, so it was
     silently replacing this rule's flex-basis transition wholesale rather
     than merging with it. Result: zero transition on flex-basis, so the
     panel just snapped to its new width in one frame instead of sweeping.
     The compound selector below outranks both individual ones by specificity
     regardless of source order, and restates every property both rules need
     so nothing gets dropped again if either is edited later. */
  .shop-accordion__panel[data-reveal] {
    /* flex-basis is what actually animates the sweep — a percentage tweens
       cleanly and, unlike letting the track distribute leftover 1fr space,
       it can never overshoot because every panel's share is computed in JS
       so the row always sums to 100% (see initShopAccordion in app.js). The
       delay JS sets per panel (proportional to distance from the active one)
       is what turns this from ten panels snapping at once into a sweep. */
    transition: opacity .75s var(--ease-out), transform .75s var(--ease-out),
                flex-basis 480ms cubic-bezier(.4, 0, .2, 1);
    transition-delay: var(--reveal-delay, 0ms);
  }
  .shop-accordion__panel:last-child { border-right: 0; }
  /* The image pans as its panel widens, rather than just stretching in
     place — a small sideways drift is what reads as "sliding open" instead
     of "resizing." Direction is fixed (not mirrored per side) because a
     ten-panel row makes a per-panel-position rule more fussy than it's
     worth for an effect this subtle. */
  .shop-accordion__panel:hover .shop-accordion__media img,
  .shop-accordion__panel.is-active .shop-accordion__media img { transform: scale(1.08) translateX(-2.5%); }
  .shop-accordion__media img { transition: transform 480ms cubic-bezier(.4, 0, .2, 1), filter var(--t-base); }

  .shop-accordion__label { padding: clamp(1.25rem, 2vw, 2.25rem); align-items: flex-end; }

  /* Collapsed state: the collection's short name, set vertically so it reads
     top-to-bottom in the narrow sliver — the standard, legible answer for
     text in a column an order of magnitude taller than it is wide. */
  .shop-accordion__label-vertical {
    display: block;
    position: absolute; left: 50%; bottom: clamp(1.25rem, 2vw, 2.25rem);
    transform: translateX(-50%) rotate(180deg);
    writing-mode: vertical-rl;
    font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
    font-size: clamp(1rem, 1.3vw, 1.25rem);
    font-variation-settings: 'opsz' 24, 'SOFT' 16, 'WONK' 0;
    letter-spacing: .01em;
    white-space: nowrap;
    color: var(--paper-50);
    opacity: 1;
    transition: opacity 280ms var(--ease-out);
  }
  .shop-accordion__label-full {
    position: absolute; inset: auto 0 0 0;
    padding: clamp(1.25rem, 2vw, 2.25rem);
    opacity: 0;
    transform: translateY(10px);
    /* Text arrives after the width has room for it, not at the same instant
       the panel starts growing — racing the two reads as a glitch. */
    transition: opacity 380ms var(--ease-out) 140ms, transform 380ms var(--ease-out) 140ms;
  }
  .shop-accordion__panel.is-active .shop-accordion__label-vertical { opacity: 0; }
  .shop-accordion__panel.is-active .shop-accordion__label-full { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .shop-accordion__panel,
  .shop-accordion__media img,
  .shop-accordion__label-vertical,
  .shop-accordion__label-full { transition: none; }
}

/* --------------------------------------------------------------------------
   9c. APPLICATION GRID — editorial index, not a card grid.
   Fixed explicit tracks (2/4 columns, never auto-fit) so there is no orphan
   cell to stretch: 8 items always divide evenly. Four tiles span two columns
   at >=1024px for the asymmetric "magazine contents page" rhythm; the other
   four stay single-width. No index numbers — the grid order plus the name
   itself carries it, the way a contents page doesn't re-number its entries.
   -------------------------------------------------------------------------- */
/* Round 2 (HM-10): smaller, lighter tiles. The grid now lives inside the page
   width as an even 4 x 2 (2 x 4 on a phone) — no spanning lead tiles, no
   screen-tall rows — with a rounded frame and compact padding. */
.app-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border-top: 1px solid var(--line);
  border-left: 1px solid var(--line);
  overflow: hidden;
  margin-top: var(--sp-5);
  border-left: 0;
  /* Sr. Manuel, 11 Oct: Browse by Application is full width (100vw), outside
     the page wrap, tiles sharing the height evenly; lowered from 80 to 60% of
     the screen height the same evening. */
  min-height: 60svh;
  grid-template-rows: repeat(4, 1fr);
}
@media (min-width: 640px) { .app-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: repeat(2, 1fr); } }
.app-tile--lead { grid-column: auto; }

.app-tile {
  position: relative;
  display: flex; flex-direction: column; justify-content: space-between;
  gap: var(--sp-3);
  min-height: 8.5rem;
  padding: var(--sp-5);
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  text-decoration: none;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--t-base);
}
.app-tile::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: var(--cacao-800);
  transform: translateY(100%);
  transition: transform 480ms var(--ease-out);
}
.app-tile:hover, .app-tile:focus-visible { color: var(--paper-50); }
.app-tile:hover::before, .app-tile:focus-visible::before { transform: translateY(0); }

.app-tile__name {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-weight: 400;
  font-size: var(--fs-h3);
  font-variation-settings: 'opsz' 60, 'SOFT' 20, 'WONK' 1;
  letter-spacing: -.012em;
  line-height: 1.1;
  transition: transform 380ms var(--ease-out);
}
.app-tile:hover .app-tile__name, .app-tile:focus-visible .app-tile__name { transform: translateX(.4rem); }
/* Every title is the same size — the lead cells' extra width comes from the
   grid span alone, not from a bigger typeface. Requested after the first
   pass sized lead titles up; asymmetric spans already carry the hierarchy. */

.app-tile__desc {
  max-width: 26ch;
  font-size: var(--fs-small);
  color: var(--text-muted);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out), color var(--t-base);
}
.app-tile:hover .app-tile__desc, .app-tile:focus-visible .app-tile__desc {
  opacity: 1; transform: none; color: rgba(239,228,215,.82);
}

.app-tile__arrow {
  align-self: flex-end;
  display: block;
  width: 20px; height: 20px;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out);
}
.app-tile__arrow svg { display: block; width: 100%; height: 100%; }
.app-tile:hover .app-tile__arrow, .app-tile:focus-visible .app-tile__arrow { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .app-tile, .app-tile::before, .app-tile__name, .app-tile__desc, .app-tile__arrow { transition: none; }
}

/* Editorial / feature card */
.feature {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  min-height: 24rem;
  display: flex;
  align-items: flex-end;
  color: var(--paper-50);
  text-decoration: none;
  isolation: isolate;
}
.feature img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; transition: transform var(--t-slow) var(--ease-out); }
.feature::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top, rgba(20,11,8,.92) 4%, rgba(20,11,8,.5) 42%, rgba(20,11,8,.06) 78%);
}
.feature:hover img { transform: scale(1.045); }
.feature__body { padding: var(--sp-5); width: 100%; }
.feature__body .eyebrow { color: var(--brass-300); }
.feature__title { font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif; font-size: var(--fs-h3); font-variation-settings: 'opsz' 40, 'SOFT' 22, 'WONK' 1; letter-spacing: -.012em; line-height: 1.1; color: var(--paper-50); }
/* spans inside a link: without display:block the title and its description ran together on one line */
.feature__title, .feature__meta { display: block; }
.feature__meta { font-size: .9375rem; color: rgba(239,228,215,.76); margin-top: .5rem; }
.feature--tall { min-height: 32rem; }

/* --------------------------------------------------------------------------
   10. BADGES, CHIPS, PILLS
   -------------------------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: .375rem;
  padding: .3125rem .6875rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: .9375rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-muted);
  /* wrap rather than run off the container — award labels get long */
  white-space: normal;
  line-height: 1.35;
  text-align: left;
  max-width: 100%;
}
.badge--accent { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 42%, transparent); }
.badge--solid { background: var(--cacao-800); border-color: var(--cacao-800); color: var(--paper-50); }
.badge--award { color: var(--brass-700); border-color: color-mix(in srgb, var(--brass-500) 50%, transparent); background: color-mix(in srgb, var(--brass-500) 9%, transparent); }
.surface-cacao .badge--award { color: var(--brass-300); background: color-mix(in srgb, var(--brass-300) 12%, transparent); }
.badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.chip {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: 2.75rem;
  padding: .5rem 1rem;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: .9375rem; font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.chip:hover { border-color: var(--cacao-500); }
.chip[aria-pressed="true"], .chip.is-active {
  background: var(--cacao-800); border-color: var(--cacao-800); color: var(--paper-50);
}
.chip__count {
  font-size: .9375rem; font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  transition: color var(--t-fast);
}
.chip[aria-pressed="true"] .chip__count { color: rgba(253,251,247,.7); }
.chip--clear { border-style: dashed; }
/* Compact chip for the Shop filter bar: 44px on a phone (tap target), 36px from
   tablet up where a pointer, not a thumb, is doing the work. */
.chip--sm { padding: .375rem .875rem; font-size: var(--fs-small); }
@media (min-width: 48rem) { .chip--sm { min-height: 2.25rem; padding: .1875rem .625rem; gap: .375rem; } }

.chip-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.chip-scroll {
  display: flex; gap: .5rem;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: .25rem;
  scroll-snap-type: x proximity;
}
.chip-scroll::-webkit-scrollbar { display: none; }
.chip-scroll > * { scroll-snap-align: start; flex: none; }

/* Fluidity meter — the spec professionals actually read */
.fluidity { display: flex; align-items: center; gap: .3125rem; }
.fluidity__pip {
  width: 1.375rem; height: 4px; border-radius: 2px;
  background: var(--line);
}
.fluidity__pip.is-on { background: var(--v, var(--accent)); }

/* --------------------------------------------------------------------------
   11. FORMS
   -------------------------------------------------------------------------- */
.field { display: grid; gap: .4375rem; }
.field > label, .label {
  font-size: .9375rem; font-weight: 600; color: var(--text-strong);
  display: flex; align-items: baseline; gap: .375rem;
}
.field .req { color: var(--state-stop); font-weight: 400; }
.field .hint { font-size: 1rem; color: var(--text-muted); font-weight: 400; }

.input, .select, .textarea {
  width: 100%;
  min-height: 3rem;
  padding: .75rem 1rem;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 1rem;      /* 16px: prevents iOS zoom-on-focus */
  color: var(--text-strong);
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.textarea { min-height: 7.5rem; resize: vertical; line-height: 1.55; }
.input::placeholder, .textarea::placeholder { color: var(--cacao-400); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--cacao-400); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--cacao-700);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cacao-700) 16%, transparent);
}
.input[aria-invalid="true"], .textarea[aria-invalid="true"], .select[aria-invalid="true"] {
  border-color: var(--state-stop);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--state-stop) 14%, transparent);
}
.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%235C3427' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-right: 2.75rem;
}
.error-msg {
  display: flex; align-items: center; gap: .375rem;
  font-size: .9375rem; color: var(--state-stop); font-weight: 500;
}
.error-msg[hidden] { display: none; }

.checkbox, .radio {
  display: flex; align-items: flex-start; gap: .6875rem;
  padding: .875rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  background: var(--bg-raised);
  transition: border-color var(--t-fast), background var(--t-fast);
  min-height: 3rem;
}
.checkbox:hover, .radio:hover { border-color: var(--cacao-400); }
.checkbox input, .radio input { margin-top: .1875rem; width: 1.125rem; height: 1.125rem; accent-color: var(--cacao-800); flex: none; }
.checkbox:has(input:checked), .radio:has(input:checked) {
  border-color: var(--cacao-700);
  background: color-mix(in srgb, var(--cacao-700) 5%, var(--bg-raised));
}
.checkbox span, .radio span { font-size: 1rem; line-height: 1.4; }
.checkbox small, .radio small { display: block; color: var(--text-muted); font-size: 1rem; margin-top: .125rem; }

fieldset { border: 0; padding: 0; }
legend { padding: 0; }

.form-grid { display: grid; gap: var(--sp-4); }
@media (min-width: 44rem) {
  .form-grid--2 { grid-template-columns: 1fr 1fr; }
  .form-grid .span-2 { grid-column: 1 / -1; }
}

/* Quantity stepper — thumb-friendly, not two tiny arrows */
.stepper {
  display: inline-flex; align-items: center;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-raised);
  overflow: hidden;
}
.stepper button {
  width: 2.75rem; height: 2.75rem;
  display: grid; place-items: center;
  background: none; border: 0; cursor: pointer;
  color: var(--text-strong);
  transition: background var(--t-fast);
}
.stepper button:hover { background: var(--bg-sunken); }
.stepper button[disabled] { opacity: .3; cursor: not-allowed; }
.stepper input {
  width: 3rem; height: 2.75rem;
  border: 0; background: none; text-align: center;
  font-weight: 600; font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
}
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper input:focus { outline: none; }
.stepper:focus-within { border-color: var(--cacao-700); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cacao-700) 16%, transparent); }

/* --------------------------------------------------------------------------
   12. THE WEIGHT GAUGE — signature component.
   Shopify's 50 kg parcel ceiling made legible before checkout, not after.
   -------------------------------------------------------------------------- */
.gauge { display: grid; gap: .625rem; }
.gauge__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); }
.gauge__value { font-weight: 600; font-variant-numeric: tabular-nums; }
.gauge__value b { font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif; font-size: 1.375rem; font-variation-settings: 'opsz' 30, 'SOFT' 18; font-weight: 500; }
.gauge__limit { font-size: 1rem; color: var(--text-muted); letter-spacing: .04em; }

.gauge__track {
  position: relative;
  height: 10px;
  background: var(--bg-sunken);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  overflow: hidden;
}
.gauge__fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: var(--state-go);
  transition: width var(--t-slow) var(--ease-out), background var(--t-base);
}
.gauge[data-state="warn"] .gauge__fill { background: var(--state-warn); }
.gauge[data-state="bulk"] .gauge__fill { background: var(--state-stop); }
/* 45 kg notch — where the warning begins */
.gauge__notch {
  position: absolute; top: -2px; bottom: -2px; left: 90%;
  width: 1px; background: var(--cacao-500); opacity: .5;
}

.gauge__note {
  display: flex; align-items: flex-start; gap: .625rem;
  padding: .875rem 1rem;
  border-radius: var(--radius);
  font-size: .9375rem; line-height: 1.5;
  border: 1px solid;
}
.gauge__note svg { width: 1.125rem; height: 1.125rem; flex: none; margin-top: .0625rem; }
.gauge[data-state="ok"]   .gauge__note { border-color: color-mix(in srgb, var(--state-go) 30%, transparent);   background: color-mix(in srgb, var(--state-go) 7%, transparent);   color: #1F5C22; }
.gauge[data-state="warn"] .gauge__note { border-color: color-mix(in srgb, var(--state-warn) 40%, transparent); background: color-mix(in srgb, var(--state-warn) 9%, transparent); color: #8A5712; }
.gauge[data-state="bulk"] .gauge__note { border-color: color-mix(in srgb, var(--state-stop) 34%, transparent); background: color-mix(in srgb, var(--state-stop) 8%, transparent); color: #8A2C17; }

/* --------------------------------------------------------------------------
   13. CART
   -------------------------------------------------------------------------- */
.cart-line {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  gap: var(--sp-4);
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--line-soft);
  align-items: start;
}
@media (min-width: 48rem) {
  .cart-line { grid-template-columns: 6.5rem 1fr auto; align-items: center; }
}
.cart-line__media {
  aspect-ratio: 1; border-radius: var(--radius);
  background: var(--bg-sunken); display: grid; place-items: center; padding: .5rem;
  border: 1px solid var(--line-soft);
}
.cart-line__media img { max-height: 100%; width: auto; object-fit: contain; }
.cart-line__name { font-weight: 600; font-size: .9375rem; line-height: 1.3; }
.cart-line__name a { text-decoration: none; }
.cart-line__name a:hover { text-decoration: underline; }
.cart-line__meta { font-size: .9375rem; color: var(--text-muted); margin-top: .1875rem; }
.cart-line__controls { display: flex; align-items: center; gap: var(--sp-4); margin-top: var(--sp-3); flex-wrap: wrap; }
@media (min-width: 48rem) { .cart-line__controls { margin-top: 0; justify-content: flex-end; } }
.cart-line__total { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 5rem; text-align: right; }
.link-danger {
  background: none; border: 0; padding: .25rem; cursor: pointer;
  font-size: .9375rem; color: var(--text-muted); text-decoration: underline;
  text-underline-offset: .2em;
}
.link-danger:hover { color: var(--state-stop); }

.summary {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  display: grid; gap: var(--sp-4);
}
@media (min-width: 62rem) { .summary { position: sticky; top: calc(var(--sticky-top) + 1rem); } }
.summary__row { display: flex; justify-content: space-between; gap: var(--sp-3); font-size: .9375rem; }
.summary__row--total {
  padding-top: var(--sp-4); border-top: 1px solid var(--line);
  font-size: 1.125rem; font-weight: 600;
}
.summary__row .num { font-variant-numeric: tabular-nums; }
.summary__muted { color: var(--text-muted); }

.empty-state {
  text-align: center;
  padding: clamp(3rem, 8vw, 6rem) var(--sp-4);
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
}
.empty-state svg { width: 3rem; height: 3rem; margin: 0 auto var(--sp-4); color: var(--cacao-400); }

/* --------------------------------------------------------------------------
   14. TABLES
   -------------------------------------------------------------------------- */
.table-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-lg); }
.table { font-size: 1rem; min-width: 38rem; }
.table th, .table td { padding: .875rem 1rem; text-align: left; border-bottom: 1px solid var(--line-soft); }
.table thead th {
  background: var(--bg-sunken);
  font-size: .9375rem; letter-spacing: .12em; text-transform: uppercase;
  font-weight: 600; color: var(--text-muted);
  position: sticky; top: 0;
  white-space: nowrap;
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: color-mix(in srgb, var(--cacao-800) 3%, transparent); }
.table td.num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.table caption { caption-side: bottom; padding: .875rem 1rem; font-size: 1rem; color: var(--text-muted); text-align: left; }

/* Spec list — product technical data */
.specs { display: grid; gap: 0; }
.specs div {
  display: grid; grid-template-columns: minmax(8rem, 38%) 1fr;
  gap: var(--sp-4);
  padding: .8125rem 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 1rem;
}
.specs dt { color: var(--text-muted); }
.specs dd { font-weight: 500; color: var(--text-strong); }

/* --------------------------------------------------------------------------
   15. ACCORDION
   -------------------------------------------------------------------------- */
.accordion { border-top: 1px solid var(--line); }
.accordion__item { border-bottom: 1px solid var(--line); }
.accordion__item summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding: 1.25rem 0;
  font-weight: 600; font-size: 1rem;
  list-style: none;
  transition: color var(--t-fast);
}
.accordion__item summary:hover { color: var(--accent); }
.accordion__icon {
  width: 1.25rem; height: 1.25rem; flex: none;
  position: relative;
}
.accordion__icon::before, .accordion__icon::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  background: currentColor;
  transition: transform var(--t-base) var(--ease-out), opacity var(--t-base);
}
.accordion__icon::before { width: 100%; height: 1.5px; }
.accordion__icon::after  { width: 1.5px; height: 100%; }
.accordion__item[open] .accordion__icon::after { transform: rotate(90deg); opacity: 0; }
.accordion__panel { padding-bottom: 1.5rem; color: var(--text-muted); max-width: var(--measure); }
.accordion__panel > * + * { margin-top: .75rem; }

/* --------------------------------------------------------------------------
   16. AWARDS STRIP
   -------------------------------------------------------------------------- */
.awards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: var(--sp-4);
  align-items: stretch;
}
.award {
  display: grid; gap: .5rem;
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-align: center;
  background: var(--bg-raised);
}
.award__year {
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-size: 1.5rem; line-height: 1;
  font-variation-settings: 'opsz' 40, 'SOFT' 20, 'WONK' 1;
  color: var(--accent);
  font-variant-numeric: lining-nums;
}
.award__level { font-size: .9375rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 600; }
.award__body { font-size: 1rem; color: var(--text-muted); line-height: 1.35; }

/* --------------------------------------------------------------------------
   16b. PROVENANCE MARKERS
   Visible in the prototype so nobody in a meeting mistakes placeholder copy,
   or an unresolved contradiction between two source documents, for approved
   text. These come out when the real copy lands.
   -------------------------------------------------------------------------- */
.provenance {
  display: flex;
  align-items: flex-start;
  gap: .625rem;
  margin-top: var(--sp-5);
  padding: .8125rem 1rem;
  border-radius: var(--radius);
  border: 1px dashed;
  font-size: .9375rem;
  line-height: 1.5;
}
.provenance__tag {
  flex: none;
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: .1875rem .4375rem;
  border-radius: 3px;
  margin-top: .0625rem;
}
.provenance--draft {
  border-color: color-mix(in srgb, var(--state-warn) 45%, transparent);
  background: color-mix(in srgb, var(--state-warn) 7%, transparent);
  color: #7A4D10;
}
.provenance--draft .provenance__tag { background: var(--brass-700); color: var(--paper-50); }
.provenance--review {
  border-color: color-mix(in srgb, var(--state-stop) 42%, transparent);
  background: color-mix(in srgb, var(--state-stop) 6%, transparent);
  color: #8A2C17;
}
.provenance--review .provenance__tag { background: var(--state-stop); color: var(--paper-50); }
/* Round 2: a file or a decision that has not arrived. It follows the surface it
   sits on (light, kraft or dark) instead of carrying its own palette. */
.provenance--pending {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  color: var(--text);
  text-align: left;
}
.provenance--pending .provenance__tag { background: var(--accent); color: var(--on-accent, var(--paper-50)); }

/* Compact variant. Same markers, same on/off switch — it exists only so a page
   that carries a dozen unresolved answers (the FAQ) does not become a wall of
   full-size boxes. No new vocabulary: still Draft, still Conflict. */
.provenance--compact {
  margin-top: var(--sp-3);
  padding: .5rem .6875rem;
  font-size: .875rem;
}
.provenance--compact .provenance__tag { font-size: .875rem; }

/* --------------------------------------------------------------------------
   17. MARQUEE — the origin ticker
   -------------------------------------------------------------------------- */
.marquee {
  overflow: hidden;
  border-block: 1px solid var(--line);
  padding-block: var(--sp-4);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee__track {
  display: flex; gap: 3rem; width: max-content;
  animation: marquee 46s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__item {
  display: flex; align-items: center; gap: 3rem;
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-size: clamp(1.125rem, 2vw, 1.625rem);
  font-variation-settings: 'opsz' 40, 'SOFT' 24, 'WONK' 1;
  letter-spacing: -.012em;
  color: var(--text-muted);
  white-space: nowrap;
}
.marquee__item::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); flex: none;
}
@keyframes marquee { to { transform: translateX(-50%); } }

/* --------------------------------------------------------------------------
   18. FOOTER
   -------------------------------------------------------------------------- */
/* Round 2 (FO-01..05): one centered stack — the original vertical logotype, the
   B Corp seal on its own and larger, one row of links — then the legal row. */
/* Round 4 (G-01): compact. Phone — logotype and seal share the first row, the
   links run in two columns, one legal block underneath. From 64rem — a single
   row (logotype · links · seal) over a single legal line. */
.footer { background: var(--cacao-900); color: #DDCFC0; padding-block: var(--sp-5) var(--sp-3); }
.footer__top {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-areas: "logo seal" "nav nav";
  align-items: center; justify-content: space-between;
  gap: var(--sp-3) var(--sp-5);
}
.footer__logo { grid-area: logo; display: block; line-height: 0; }
.footer__logo img { width: auto; height: 4rem; }
.footer__bcorp { grid-area: seal; height: 4rem; width: auto; opacity: .9; filter: brightness(0) invert(1); }
.footer__nav { grid-area: nav; min-width: 0; }
.footer__links {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--sp-4);
}
.footer__links li + li { margin-top: 0; }
.footer__links a { display: flex; align-items: center; min-height: 2.75rem; min-width: 2.75rem; font-size: var(--fs-body); text-decoration: none; color: var(--cacao-300); transition: color var(--t-fast); }
.footer__links a:hover { color: var(--paper-50); }
.footer__bottom {
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid rgba(239,228,215,.14);
  display: flex; flex-wrap: wrap; gap: 0 var(--sp-4);
  align-items: center; justify-content: space-between;
  font-size: var(--fs-small); color: var(--cacao-400);
}
.footer__bottom > p { margin: 0; }
.footer__bottom nav { display: flex; flex-wrap: wrap; gap: 0 var(--sp-4); }
@media (min-width: 64rem) {
  .footer__top { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "logo nav seal"; gap: var(--sp-6); }
  .footer__links { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 var(--sp-5); }
  .footer__logo img { height: 4.5rem; }
  .footer__bcorp { height: 4.5rem; }
}
.footer__bottom a { display: inline-flex; align-items: center; justify-content: center; min-height: 2.75rem; min-width: 2.75rem; text-decoration: none; }
.footer__bottom a:hover { color: var(--paper-50); text-decoration: underline; }
/* 3D model attribution (CINEMA=on only). Outside .footer__bottom on purpose:
   there links lose their underline, and a licence link inside a sentence has
   to read as a link. --cacao-400 on --cacao-900 measures 5.0:1. */
.footer__credit { margin-top: var(--sp-5); color: var(--cacao-400); max-width: var(--measure); }
.footer__credit + .footer__credit { margin-top: var(--sp-2); }

/* --------------------------------------------------------------------------
   19. SEARCH OVERLAY
   -------------------------------------------------------------------------- */
.search-panel {
  position: fixed; inset: 0;
  z-index: var(--z-modal);
  background: color-mix(in srgb, var(--paper-100) 97%, transparent);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--t-base), visibility var(--t-base);
  overflow-y: auto;
  padding-top: clamp(3rem, 10vh, 7rem);
}
.search-panel.is-open { opacity: 1; visibility: visible; }
.search-panel__form { display: flex; align-items: center; gap: var(--sp-4); border-bottom: 2px solid var(--cacao-800); padding-bottom: var(--sp-4); }
.search-panel__input {
  flex: 1; border: 0; background: none;
  font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif;
  font-size: clamp(1.5rem, 4vw, 2.75rem);
  font-variation-settings: 'opsz' 72, 'SOFT' 24, 'WONK' 1;
  letter-spacing: -.012em;
  color: var(--text-strong);
  min-width: 0;
}
.search-panel__input:focus { outline: none; }
.search-panel__input::placeholder { color: var(--cacao-400); }
.search-results { margin-top: var(--sp-6); display: grid; gap: .25rem; padding-bottom: var(--sp-8); }
.search-hit {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: .875rem 1rem;
  border-radius: var(--radius);
  text-decoration: none;
  transition: background var(--t-fast);
}
.search-hit:hover, .search-hit:focus-visible { background: var(--paper-200); }
.search-hit__thumb {
  width: 3.25rem; height: 3.25rem; flex: none;
  border-radius: var(--radius-sm);
  background: var(--paper-200);
  display: grid; place-items: center; padding: .25rem;
  border: 1px solid var(--line-soft);
}
.search-hit__thumb img { max-height: 100%; width: auto; object-fit: contain; }
.search-hit__name { font-weight: 600; font-size: .9375rem; }
.search-hit__kind { font-size: .9375rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); }

/* --------------------------------------------------------------------------
   20. TOAST
   -------------------------------------------------------------------------- */
.toast-region {
  position: fixed; z-index: var(--z-modal);
  bottom: var(--sp-5); left: 50%; transform: translateX(-50%);
  display: grid; gap: .5rem; width: min(26rem, calc(100vw - 2rem));
  pointer-events: none;
}
@media (min-width: 48rem) { .toast-region { left: auto; right: var(--sp-5); transform: none; } }
.toast {
  display: flex; align-items: center; gap: .75rem;
  padding: .875rem 1.125rem;
  background: var(--cacao-850); color: var(--paper-100);
  border-radius: var(--radius);
  box-shadow: 0 18px 40px -14px rgba(20,11,8,.6);
  font-size: 1rem;
  pointer-events: auto;
  animation: toast-in var(--t-base) var(--ease-out);
}
.toast svg { width: 1.125rem; height: 1.125rem; flex: none; color: var(--brass-300); }
.toast a { color: var(--brass-300); margin-left: auto; white-space: nowrap; }
.toast.is-out { animation: toast-out var(--t-base) var(--ease-in-out) forwards; }
@keyframes toast-in  { from { opacity: 0; transform: translateY(12px); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px); } }

/* --------------------------------------------------------------------------
   21. BREADCRUMBS + PAGE HEAD
   -------------------------------------------------------------------------- */
.crumbs { font-size: 1rem; color: var(--text-muted); padding-block: var(--sp-4) 0; }
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; list-style: none; padding: 0; }
.crumbs a { text-decoration: none; }
.crumbs a:hover { text-decoration: underline; text-underline-offset: .2em; }
.crumbs li:not(:last-child)::after { content: "/"; margin-left: .5rem; opacity: .45; }
.crumbs [aria-current="page"] { color: var(--text-strong); font-weight: 500; }

.page-head { padding-block: clamp(1.5rem, 3vw, 2.5rem) clamp(1.25rem, 2.5vw, 2rem); }
.page-head--compact { padding-block: clamp(.5rem, 1.2vw, 1rem) clamp(.75rem, 1.5vw, 1.25rem); }
.page-head__title { max-width: 20ch; }
/* Title and lede side by side from tablet up: one band instead of two stacked
   ones, which is what lets Shop show its products on the first screen. */
@media (min-width: 62rem) {
  .page-head--compact { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); column-gap: clamp(2rem, 5vw, 4rem); align-items: end; }
  .page-head--compact .page-head__title { max-width: none; }
  .page-head--compact .lede { margin-top: 0; }
  .page-head--compact > .provenance, .page-head--compact > .eyebrow { grid-column: 1 / -1; }
}

/* --------------------------------------------------------------------------
   22. MOTION — reveal on scroll
   -------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .75s var(--ease-out), transform .75s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }
[data-reveal="fade"] { transform: none; }
[data-reveal="scale"] { transform: scale(.97); }
[data-reveal="scale"].is-in { transform: none; }

/* Everything above degrades to an equivalent static state, not a broken one */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .marquee__track { animation: none; transform: none; }
  .origin-line > li::after { transform: scale(1); }
}

/* --------------------------------------------------------------------------
   23. UTILITIES
   -------------------------------------------------------------------------- */
.t-center { text-align: center; }
.t-muted { color: var(--text-muted); }
.t-strong { color: var(--text-strong); }
/* Reading text has one size. The old .875/.75rem tiers rendered at 14 and 12px
   on desktop, which is below the floor this project works to. */
.t-sm { font-size: 1rem; }
.t-xs { font-size: .9375rem; }
.mt-0 { margin-top: 0; }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mt-6 { margin-top: var(--sp-6); }
.mt-7 { margin-top: var(--sp-7); }
.mb-4 { margin-top: 0; margin-bottom: var(--sp-4); }
.mx-auto { margin-inline: auto; }
.flow > * + * { margin-top: var(--sp-4); }
.rounded { border-radius: var(--radius-lg); overflow: hidden; }
.ratio-4-5 { aspect-ratio: 4 / 5; }
.ratio-3-2 { aspect-ratio: 3 / 2; }
.ratio-1-1 { aspect-ratio: 1; }
.ratio-16-9 { aspect-ratio: 16 / 9; }
.cover { width: 100%; height: 100%; object-fit: cover; }
/* `align-self: start` keeps the box at content height inside a taller grid
   area, which is what gives sticky somewhere to travel. */
.sticky-col { position: sticky; top: calc(var(--sticky-top) + 1rem); align-self: start; }
.no-wrap { white-space: nowrap; }
[hidden] { display: none !important; }


/* ==========================================================================
   OCT 2026 — consolidated client comments
   ========================================================================== */

/* Discovery Kit offer: "dar mayor protagonismo visual al 50% OFF". The
   percentage is the largest type in its block, set in the brand brass. */
.kit-offer {
  display: flex; align-items: baseline; justify-content: center; gap: var(--sp-2);
  margin-block: var(--sp-2) var(--sp-4);
  line-height: 1;
  color: var(--brass-300);
}
.kit-offer__pct { font-size: clamp(3.5rem, 9vw, 6rem); font-weight: 600; letter-spacing: -.012em; line-height: .9; }
.kit-offer__off { font-size: clamp(1.25rem, 3vw, 2rem); font-weight: 600; letter-spacing: .12em; text-transform: uppercase; }
.kit-offer--light { justify-content: flex-start; margin-block: 0; color: var(--brass-700); }
.card--accent { border-color: var(--brass-500); }

/* About subsections: a row of buttons under the header. Sticky so the
   sections stay one tap apart; scrolls sideways on a phone instead of
   wrapping into three rows. */
.subnav {
  position: sticky; top: var(--header-h);
  z-index: calc(var(--z-header) - 1);
  background: var(--paper-50);
  border-bottom: 1px solid var(--line);
}
.subnav__row {
  display: flex; gap: var(--sp-2);
  overflow-x: auto; overscroll-behavior-x: contain;
  padding-block: var(--sp-3);
  scrollbar-width: none;
}
.subnav__row::-webkit-scrollbar { display: none; }
.subnav__btn {
  flex: none;
  display: inline-flex; align-items: center;
  min-height: 2.75rem; padding: 0 var(--sp-4);
  border: 1px solid var(--line); border-radius: 999px;
  font-size: .9375rem; font-weight: 500; white-space: nowrap;
  color: var(--text); text-decoration: none;
  transition: background var(--t-base) var(--ease-out), color var(--t-base) var(--ease-out), border-color var(--t-base) var(--ease-out);
}
.subnav__btn:hover { border-color: var(--cacao-800); }
.subnav__btn[aria-current="true"] { background: var(--cacao-800); border-color: var(--cacao-800); color: var(--paper-50); }
@media (min-width: 768px) {
  .subnav__row { justify-content: center; flex-wrap: wrap; overflow: visible; }
}
.is-tabbed > section[hidden] { display: none; }

/* The Chocolate Guide: five visual entry points, one per category.
   1 column -> 2 with the lead spanning (2+2+1 has no orphan) -> 5 in a row. */
.learn-cats { display: grid; gap: var(--sp-4); grid-template-columns: minmax(0, 1fr); }
.learn-cat { min-height: 18rem; }
.learn-cat .feature__title { margin-top: var(--sp-2); }
@media (min-width: 640px) {
  .learn-cats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .learn-cat--lead { grid-column: 1 / -1; }
}
@media (min-width: 1024px) {
  .learn-cats { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .learn-cat--lead { grid-column: auto; }
  .learn-cat { min-height: 22rem; }
}

/* B Corp: the seal alone, no descriptive line (client note). */
.bcorp-seal { width: 4.5rem; height: auto; margin-top: var(--sp-5); }

/* Search moved into the mobile drawer to give the wordmark the header row. */
.mobile-nav__search {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  color: var(--paper-100); border-color: rgba(239,228,215,.32);
}
.mobile-nav__search svg { width: 1.125rem; height: 1.125rem; flex: none; }

/* Tap targets for links set inside running text (breadcrumbs, prose, lists,
   definition lists). Inline padding grows the hit box to 44px without moving a
   single line of text: padding on an inline box does not change the line box. */
main :where(p, li, dd, td) a:not([class]) {
  padding: .875rem .375rem;
  margin-inline: -.375rem;
}

/* The stage and the card media are aspect-ratio grids. With auto tracks the
   image's height:100% had nothing definite to resolve against and the bag ran
   past the bottom edge; a single minmax(0,1fr) track gives it the box. */
.product-stage, .product-card .card__media { grid-template: minmax(0, 1fr) / minmax(0, 1fr); }

/* Product gallery: a photograph (lifestyle scene, "in use", origin) fills the
   stage edge to edge; only the cut-out packshot sits padded on the dark floor. */
.product-stage.is-photo { padding: 0; }
.product-stage.is-photo img { object-fit: cover; filter: none; }
.product-stage.is-photo .pct { display: none; }

/* Application tiles with a photograph (Oct 2026). The photo sits under a
   bottom-weighted scrim so the white name always reads; on hover the same
   cacao panel slides up, translucent so the photograph stays present.
   Decorative image (alt=""): the tile's name is the link text. */
.app-tile--photo { color: var(--paper-50); background: var(--cacao-900); }
.app-tile__media { position: absolute; inset: 0; z-index: -2; }
.app-tile__media img {
  width: 100%; height: 100%; object-fit: cover;
  filter: var(--grade-card);
  transition: transform var(--t-slow) var(--ease-out);
}
.app-tile__media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,11,8,.8) 0%, rgba(20,11,8,.4) 52%, rgba(20,11,8,.12) 100%);
}
.app-tile--photo::before { background: rgba(47,25,19,.72); }
.app-tile--photo .app-tile__desc { color: rgba(239,228,215,.86); }
.app-tile--photo:hover .app-tile__media img,
.app-tile--photo:focus-visible .app-tile__media img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) { .app-tile__media img { transition: none; } }


/* ==========================================================================
   OCT 2026 — round 2 (client document of 10 Oct, sections 1 to 9)
   Mobile-first: the unprefixed rules describe a 360px phone.
   ========================================================================== */

/* SH-03 — Shop filters as one slim bar. Two rows of chips (product, then
   application) and the count + sort at the right of the first row. On a phone
   each chip row scrolls sideways instead of wrapping into five lines. */
.filter-bar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-2) var(--sp-5);
  padding-block: var(--sp-2);
  border-block: 1px solid var(--line);
  margin-bottom: var(--sp-4);
}
.filter-bar__group { display: flex; flex-direction: column; align-items: stretch; gap: .375rem; min-width: 0; width: 100%; }
.filter-bar__label {
  flex: none;
  font-size: .875rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-muted);
}
.filter-bar .chip-row { gap: .375rem; }
.filter-bar__tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); width: 100%; justify-content: space-between; }
.chip-row--scroll {
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  padding-bottom: 2px; min-width: 0;
}
.chip-row--scroll::-webkit-scrollbar { display: none; }
.chip-row--scroll > * { flex: none; }
.select--sm { width: auto; min-height: 2.75rem; padding-block: .25rem; }
@media (min-width: 48rem) {
  .select--sm { min-height: 2.25rem; }
  .filter-bar__group { flex-direction: row; align-items: center; gap: var(--sp-2); width: auto; }
  .filter-bar__group--apps { flex: 1 0 100%; }
  .filter-bar__tools { width: auto; margin-left: auto; flex-wrap: nowrap; justify-content: flex-end; }
  .chip-row--scroll { flex-wrap: wrap; overflow: visible; padding-bottom: 0; }
}

/* Learn — subsection panels (LE-02, LE-04). One template for all four. */
.learn-panel__head { max-width: 46rem; margin-bottom: var(--sp-5); }
.learn-panel .feature { min-height: 17rem; }
.learn-panel__more { margin-top: var(--sp-7); }
.back-link { padding-top: var(--sp-3); font-size: var(--fs-small); }
.back-link .link { color: var(--text-muted); }
.back-link .link:hover { color: var(--text-strong); }

/* About / Learn — the shared subnav sits right under the head; no extra air. */
.subsections > .subnav { margin-top: 0; }

/* HM-16 — the closing line holds to one line from tablet up; on a phone it
   breaks into two balanced lines (text-wrap: balance, set on every heading),
   so a lone word never hangs on the second line. */
.cta-closing__title { text-wrap: balance; }
@media (min-width: 48rem) { .cta-closing__title { white-space: nowrap; } }

/* Discovery Kit price (section 11). */
.kit-price { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.kit-price__label { font-size: var(--fs-small); font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); }
.kit-price__amount { font-size: var(--fs-h3); font-weight: 500; color: var(--text-strong); line-height: 1.1; }

/* Bulk Orders (BO-03): the form sits beside the introduction, in its own card. */
.bulk-lead__grid { align-items: start; }
.bulk-lead__form {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  min-width: 0;
}
.bulk-lead__intro { min-width: 0; }
.form-grid .textarea { min-height: 5rem; }
.field__note { margin: 0; }
.field__conv { font-variant-numeric: tabular-nums; }
.ratio-21-9 { aspect-ratio: 21 / 9; }

/* Support (SU-04, SU-05): the form is the card; "Faster routes" is a quiet list
   with hairlines, not a second card. */
.form-card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  display: grid; gap: var(--sp-4);
  min-width: 0;
}
.routes { min-width: 0; }
.routes__title {
  font-family: inherit; font-size: var(--fs-small); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; line-height: 1.4;
  color: var(--text-muted);
}
.routes__list { list-style: none; padding: 0; margin-top: var(--sp-2); }
.routes__list li { border-top: 1px solid var(--line-soft); font-size: var(--fs-small); color: var(--text-muted); }
.routes__list li:last-child { border-bottom: 1px solid var(--line-soft); }
.routes__list a { color: var(--text); }

/* B Corp seal on a light surface: the original artwork is black, so it needs
   no filter here (HM-15). Slightly larger than before. */
.bcorp-seal { width: 5rem; height: auto; margin-top: var(--sp-5); }

/* Proposals page (/propuestas-ronda-2.html) — internal, noindex. */
.prop { display: grid; gap: var(--sp-5); }
.prop__grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.prop__card { background: var(--bg-raised); border: 1px solid var(--line-soft); border-radius: var(--radius-lg); padding: var(--sp-5); display: grid; gap: var(--sp-3); align-content: start; min-width: 0; }
.prop__swatch { height: 3rem; border-radius: var(--radius); }
.prop__hdr { display: grid; place-items: center; background: var(--cacao-900); border-radius: var(--radius-lg); padding: var(--sp-5); }
.prop__hdr img { height: 7rem; width: auto; }
.prop__bg { position: relative; min-height: 14rem; border-radius: var(--radius-lg); overflow: hidden; display: grid; place-items: center; text-align: center; color: var(--paper-50); padding: var(--sp-5); }
.prop__bg img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: brightness(.55) saturate(.9); }
.prop__bg > * { position: relative; }


/* ==========================================================================
   HOW TO BUY — 3D coverflow (Sr. Manuel, 11 Oct). Geometry from the 21st.dev
   component it follows: a 330 x 500 card, neighbours at +-285px, 0.84 scale and
   +-24 degrees (second ring at 510px / 0.68 / 38), perspective 1400px.
   Texture: the photograph, a dark top-to-bottom vignette, a hairline border, and
   under the centered card a warm gold glow; the section's ground is a blurred,
   dimmed copy of the centered photograph. The accent is the brand gold token.
   Mobile-first: without JS the three cards stack; `.is-live` (set by
   initCoverflow) turns them into the stage.
   ========================================================================== */
.coverflow { position: relative; overflow: hidden; isolation: isolate; }
.coverflow__ambient { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.coverflow__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; filter: brightness(.22) blur(32px); transform: scale(1.15); transition: opacity 1000ms var(--ease-out); }
.coverflow__bg.is-on { opacity: 1; }
.coverflow__veil { position: absolute; inset: 0; background: radial-gradient(circle at center, rgba(20,11,8,.3) 0%, rgba(20,11,8,.92) 100%); }
.coverflow__inner { position: relative; }

.cf { --cf-w: min(72vw, 20.5rem); --cf-h: 31rem; --cf-step: calc(var(--cf-w) * .86); position: relative; }
.cf__stage { display: grid; gap: var(--sp-5); justify-items: center; }
.cf-card {
  position: relative; width: var(--cf-w); height: var(--cf-h);
  border-radius: var(--radius-lg); overflow: hidden;
  background: var(--cacao-850);
  border: 1px solid rgba(255,255,255,.12);
  box-shadow: 0 15px 35px rgba(0,0,0,.5);
  color: var(--paper-50);
}
.cf-card__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cf-card__veil { position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(180deg, rgba(0,0,0,.4) 0%, rgba(0,0,0,.1) 25%, rgba(0,0,0,.68) 60%, rgba(0,0,0,.96) 100%); }
.cf-card__body { position: relative; z-index: 2; height: 100%; padding: 1.25rem 1.125rem 1.375rem; display: flex; flex-direction: column; justify-content: space-between; text-align: center; }
.cf-card__tag { align-self: flex-end; font-size: var(--fs-small); font-weight: 600; letter-spacing: .06em; color: rgba(255,255,255,.92); text-shadow: 0 2px 6px rgba(0,0,0,.8); }
.cf-card__text { display: flex; flex-direction: column; align-items: center; gap: .25rem; }
.cf-card__title { font-size: var(--fs-h3); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; line-height: 1.1; color: var(--paper-50); text-shadow: 0 3px 12px rgba(0,0,0,.95); }
.cf-card__rule { width: 2.125rem; height: 2px; border-radius: 2px; background: var(--gold-500); box-shadow: 0 0 8px color-mix(in srgb, var(--gold-500) 70%, transparent); margin: .375rem 0 .25rem; }
.cf-card__desc { font-size: var(--fs-small); font-style: italic; line-height: 1.35; max-width: 17.5rem; margin: 0 0 .625rem; color: rgba(255,255,255,.92); text-shadow: 0 2px 8px rgba(0,0,0,.9); }

.cf__nav, .cf__dots { display: none; }

.coverflow .cf.is-live .cf__stage { position: relative; display: block; height: calc(var(--cf-h) + 2rem); perspective: 1400px; }
.cf.is-live .cf-card {
  position: absolute; left: 50%; top: 50%; margin: calc(var(--cf-h) / -2) 0 0 calc(var(--cf-w) / -2);
  transform-origin: center center; opacity: 0; z-index: 0; filter: brightness(.4) blur(2px);
  transform: translateX(0) scale(.4);
  transition: transform 800ms cubic-bezier(.25, 1, .5, 1), opacity 800ms cubic-bezier(.25, 1, .5, 1), filter 800ms cubic-bezier(.25, 1, .5, 1), box-shadow 800ms;
  cursor: pointer;
}
.cf.is-live .cf-card[data-pos="0"]  { transform: none; opacity: 1; z-index: 30; filter: none; cursor: default; box-shadow: 0 25px 60px rgba(0,0,0,.9), 0 0 35px color-mix(in srgb, var(--gold-500) 25%, transparent); }
.cf.is-live .cf-card[data-pos="1"]  { transform: translateX(var(--cf-step)) scale(.84) rotateY(-24deg); opacity: .65; z-index: 20; filter: brightness(.75); }
.cf.is-live .cf-card[data-pos="-1"] { transform: translateX(calc(var(--cf-step) * -1)) scale(.84) rotateY(24deg); opacity: .65; z-index: 20; filter: brightness(.75); }
.cf.is-live .cf-card[data-pos="2"]  { transform: translateX(calc(var(--cf-step) * 1.79)) scale(.68) rotateY(-38deg); opacity: .38; z-index: 10; filter: brightness(.55) blur(1px); }
.cf.is-live .cf-card[data-pos="-2"] { transform: translateX(calc(var(--cf-step) * -1.79)) scale(.68) rotateY(38deg); opacity: .38; z-index: 10; filter: brightness(.55) blur(1px); }
/* only the centered card shows its words — the others are textures */
.cf.is-live .cf-card .cf-card__body { opacity: 0; transform: translateY(16px); pointer-events: none; transition: opacity 500ms ease, transform 500ms ease; }
.cf.is-live .cf-card[data-pos="0"] .cf-card__body { opacity: 1; transform: none; pointer-events: auto; }

.cf.is-live .cf__nav {
  display: grid; place-items: center; position: absolute; top: 50%; z-index: 40; width: 2.75rem; height: 2.75rem; margin-top: -1.375rem;
  border-radius: 50%; background: rgba(0,0,0,.55); border: 1px solid rgba(255,255,255,.2); color: var(--paper-50); cursor: pointer;
  backdrop-filter: blur(8px); box-shadow: 0 8px 24px rgba(0,0,0,.4); transition: background var(--t-base), border-color var(--t-base);
}
.cf.is-live .cf__nav:hover, .cf.is-live .cf__nav:focus-visible { background: rgba(0,0,0,.8); border-color: var(--gold-500); }
.cf__nav--prev { left: 0; } .cf__nav--next { right: 0; }
.cf__nav--prev svg { transform: scaleX(-1); }
.cf__nav svg { width: 1.25rem; height: 1.25rem; }
.cf.is-live .cf__dots { display: flex; justify-content: center; gap: 0; }
.cf__dots button { height: 2.75rem; width: 2.75rem; position: relative; background: none; border: 0; cursor: pointer; }
.cf__dots button::after { content: ""; position: absolute; left: 50%; top: 50%; height: 8px; width: 8px; margin: -4px 0 0 -4px; border-radius: 999px; background: rgba(255,255,255,.25); transition: width var(--t-base) var(--ease-out), margin var(--t-base) var(--ease-out), background var(--t-base); }
.cf__dots button[aria-current="true"]::after { width: 28px; margin-left: -14px; background: var(--gold-500); box-shadow: 0 0 10px color-mix(in srgb, var(--gold-500) 70%, transparent); }
@media (min-width: 48rem) { .cf { --cf-w: 20.5rem; } .cf.is-live .cf__nav--prev { left: 1.5rem; } .cf.is-live .cf__nav--next { right: 1.5rem; } }
@media (prefers-reduced-motion: reduce) { .cf.is-live .cf-card, .cf.is-live .cf-card .cf-card__body, .coverflow__bg { transition: none; } }


/* ==========================================================================
   ROUND 2, third pass (Sr. Manuel, 11 Oct): hero centering, white banners, the
   commitment video.
   ========================================================================== */

/* Height of the announcement bar plus the header (px: it does not scale with the
   fluid root size). Fallbacks measured at 137px below 1024px, 233px from 1024px;
   initHeroFit in app.js sets the live value. The header is in flow above the hero, so a 100svh hero
   spills below the first screen and its centered copy reads as bottom-aligned. */
:root { --chrome-h: 137px; }   /* fallback; initHeroFit measures it */
@media (min-width: 1024px) { :root { --chrome-h: 233px; } }

/* Hero: a whole screen tall (100svh), Sr. Manuel 11 Oct. The announcement bar, the
   header and, on interior pages, the breadcrumb float over the top of the photograph
   (the hero is pulled up by --chrome-h), and the copy is centered in the area that
   stays visible under them. See section 29 for the header over the image. */
.scene.scene--hero { height: auto; min-height: 100svh; margin-top: calc(-1 * var(--chrome-h)); }
.scene.scene--hero .scene__content { height: auto; min-height: inherit; padding-top: calc(var(--chrome-h) + clamp(.5rem, 2vh, 1.5rem)); padding-bottom: clamp(2rem, 5vh, 3.5rem); }

/* White banners (Crafted for Creators, the closing call to action): flat warm
   white, ink type, everything centered. Warm paper-50, never #FFFFFF. */
.band--white { --bg: var(--paper-50); background: var(--paper-50); color: var(--cacao-800); padding-block: clamp(4rem, 11vh, 7.5rem); }
.banner { display: flex; flex-direction: column; align-items: center; text-align: center; }
.banner__rule { display: block; width: 3rem; height: 2px; background: var(--gold-500); margin-bottom: var(--sp-5); }
.banner .dh { color: var(--cacao-900); max-width: 24ch; }
.banner__lede { max-width: 58ch; margin: var(--sp-5) auto 0; font-size: var(--fs-lede); line-height: 1.6; color: var(--cacao-800); }
.band--closing { padding-block: clamp(5rem, 14vh, 9rem); }

/* More Than Chocolate: video ground, brown box centered on it. */
.commit { position: relative; z-index: 1; isolation: isolate; overflow: hidden; background: var(--cacao-900); min-height: clamp(34rem, 90svh, 56rem); display: grid; align-items: center; padding-block: clamp(2.5rem, 8vh, 5rem); }
.commit__media { position: absolute; inset: 0; z-index: -1; }
.commit__media img { width: 100%; height: 100%; object-fit: cover; }
.commit__media::after { content: ""; position: absolute; inset: 0; background: rgba(8,5,3,.16); pointer-events: none; }
.commit__inner { width: 100%; }
.commit__box {
  --text: #EFE4D7; --text-strong: var(--paper-50); --accent: var(--brass-300);
  width: min(100%, 38rem); margin-inline: auto; text-align: center;
  background: var(--cacao-800); color: var(--text);
  padding: clamp(1.5rem, 4vw, 3rem);
  border-radius: var(--radius-lg);
}
.commit__box .dh { color: var(--paper-50); }
.commit__box .eyebrow { justify-content: center; color: var(--brass-300); }
.commit__lede { margin-top: var(--sp-5); font-size: var(--fs-lede); line-height: 1.6; }
.commit__box p + p { margin-top: var(--sp-4); }
.commit__box .bcorp-seal { display: block; margin-inline: auto; }
.bcorp-seal--light { filter: brightness(0) invert(1); }
.commit__box .link { color: var(--paper-50); }
@media (prefers-reduced-motion: reduce) { .commit__media video { display: none; } }
.band--white .btn--ghost { border-color: color-mix(in srgb, var(--cacao-800) 55%, transparent); }

/* ==========================================================================
   INTERNAL PAGE HEROES (Shop, Bulk Orders, Learn, About, Contact) — the home
   hero's scene, not pinned. The photographs are bright, so the scrim is a flat
   dark layer plus the radial one; the copy carries its own text shadow.
   ========================================================================== */
.scene.scene--page { position: relative; }
.scene--page .scene__media::after {
  background:
    radial-gradient(70% 62% at 50% 50%, rgba(8,5,3,.5) 0%, rgba(8,5,3,.3) 70%, transparent 100%),
    linear-gradient(rgba(8,5,3,.38), rgba(8,5,3,.38));
}
.scene--page .scene__inner .btn-row { gap: var(--sp-3); }

/* ==========================================================================
   LEARN › RECIPES WITHOUT WORDS — editorial film grid. One lead film wide, the
   others in thirds; a numeral, the running time and the title under each frame.
   ========================================================================== */
.rw { background: var(--paper-100); color: var(--cacao-800); padding-block: clamp(3rem, 8vh, 6rem); }
.rw__head { text-align: center; margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.rw__head .eyebrow { justify-content: center; }
.rw__head .dh { color: var(--cacao-900); }
.rw__lede { max-width: 54ch; margin: var(--sp-4) auto 0; font-size: var(--fs-lede); line-height: 1.6; }
.rw__grid { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(2rem, 4vw, 3rem) var(--sp-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 17.5rem), 1fr)); }
.rw-card { min-width: 0; }
.rw-card__frame { position: relative; aspect-ratio: 16 / 9; border-radius: var(--radius); overflow: hidden; background: var(--cacao-900); }
.rw-card__play { position: absolute; inset: 0; display: block; }
.rw-card__play img, .rw-card__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.rw-card__video { background: var(--cacao-900); }
.rw-card__play img { transition: transform 1.2s var(--ease-out); }
.rw-card__play::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 55%, rgba(8,5,3,.4)); }
.rw-card__icon { position: absolute; z-index: 1; left: 50%; top: 50%; width: 3.5rem; height: 3.5rem; margin: -1.75rem 0 0 -1.75rem; display: grid; place-items: center; border-radius: 50%; background: var(--btn-primary); color: var(--btn-primary-ink); box-shadow: 0 8px 24px rgba(8,5,3,.35); transition: transform var(--t-base) var(--ease-out); }
.rw-card__icon svg { width: 1.5rem; height: 1.5rem; margin-left: .125rem; }
.rw-card__play:hover img, .rw-card__play:focus-visible img { transform: scale(1.04); }
.rw-card__play:hover .rw-card__icon, .rw-card__play:focus-visible .rw-card__icon { transform: scale(1.08); }
.rw-card__play:focus-visible { outline: 2px solid var(--focus); outline-offset: -4px; }
.rw-card__meta { display: flex; gap: var(--sp-3); margin-top: var(--sp-3); font-size: var(--fs-small); letter-spacing: .08em; text-transform: uppercase; color: var(--cacao-700); }
.rw-card__meta .num { color: var(--brass-700); font-weight: 600; }
.rw-card__title { margin-top: var(--sp-2); font-size: var(--fs-h3); line-height: 1.15; color: var(--cacao-900); }
@media (min-width: 64rem) {
  .rw__grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .rw-card { grid-column: span 4; }
  .rw-card--lead { grid-column: span 8; }
  .rw-card--lead .rw-card__title { font-size: var(--fs-h2); }
  .rw-card--lead .rw-card__icon { width: 4.5rem; height: 4.5rem; margin: -2.25rem 0 0 -2.25rem; }
  .rw-card:nth-child(2) .rw-card__frame { height: 100%; aspect-ratio: auto; }
  .rw-card:nth-child(2) { display: grid; grid-template-rows: 1fr auto auto; }
}
@media (prefers-reduced-motion: reduce) { .rw-card__play img, .rw-card__icon { transition: none; } }

/* ==========================================================================
   ABOUT › THE JOURNEY — a vertical timeline in editorial spreads. Each chapter:
   a large year and era on the rail, the words, then the photographs. Mobile:
   everything stacks, year first. From 1024px the chapter is a two-column spread
   (words | photographs), alternating sides, with a hairline spine behind.
   ========================================================================== */
.journey { background: var(--paper-100); color: var(--cacao-800); }
.journey__head { text-align: center; max-width: 44rem; margin: 0 auto clamp(2.5rem, 7vw, 5rem); }
.journey__head .eyebrow { justify-content: center; }
.journey__lede { margin-top: var(--sp-4); font-size: var(--fs-lede); line-height: 1.6; }
.jr-list { list-style: none; margin: 0; padding: 0; position: relative; display: grid; gap: clamp(3rem, 8vw, 6rem); }
.jr { display: grid; gap: var(--sp-5); min-width: 0; padding-left: var(--sp-5); border-left: 1px solid var(--line); position: relative; }
.jr::before { content: ""; position: absolute; left: -5px; top: .75rem; width: 9px; height: 9px; border-radius: 50%; background: var(--gold-500); }
.jr__when { display: flex; flex-direction: column; gap: .125rem; }
.jr__year { font-family: 'Barlow', ui-sans-serif, system-ui, sans-serif; font-weight: 300; font-size: clamp(3.25rem, 11vw, 6.5rem); line-height: .95; letter-spacing: -.02em; color: var(--brass-700); }
.jr__era { font-size: var(--fs-small); letter-spacing: .12em; text-transform: uppercase; color: var(--cacao-700); }
.jr__body { min-width: 0; max-width: 34rem; }
.jr__title { font-size: var(--fs-h2); line-height: 1.08; color: var(--cacao-900); }
.jr__body p { margin-top: var(--sp-4); line-height: 1.65; }
.jr__figs { display: grid; gap: var(--sp-4); min-width: 0; }
.jr-fig { margin: 0; min-width: 0; }
.jr-fig img { display: block; width: 100%; height: auto; border-radius: var(--radius); }
.jr-fig figcaption { margin-top: var(--sp-2); font-size: var(--fs-small); line-height: 1.4; color: var(--cacao-700); }
.jr-fig--small img { width: min(100%, 22rem); }
.jr-fig--tall img { width: min(100%, 24rem); }
@media (min-width: 40rem) {
  .jr__figs--2, .jr__figs--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  .jr__figs--3 .jr-fig:first-child { grid-column: 1 / -1; }
}
@media (min-width: 64rem) {
  .jr { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); grid-template-areas: "when figs" "body figs"; column-gap: clamp(2.5rem, 6vw, 5rem); row-gap: var(--sp-4); padding-left: clamp(2rem, 4vw, 3rem); align-items: start; }
  .jr--flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); grid-template-areas: "figs when" "figs body"; }
  .jr__when { grid-area: when; align-self: end; }
  .jr__body { grid-area: body; }
  .jr__figs { grid-area: figs; }
  .jr__figs--1 .jr-fig--small, .jr__figs--1 .jr-fig--tall { justify-self: center; }
}
@media (prefers-reduced-motion: reduce) { .jr[data-reveal] { transition: none; } }
/* A provenance note over a photograph needs its own ground */
.scene__flag .provenance { background: rgba(20,11,8,.86); border-color: rgba(239,228,215,.3); }
.scene__flag .provenance, .scene__flag .provenance p, .scene__flag .provenance span:not(.provenance__tag) { color: #EFE4D7; }

/* ==========================================================================
   AWARD MARKS (Why Franceschi) — minimal: the badges at one height, in their own
   colors, two groups under hairlines. No cards, no borders, no hover.
   ========================================================================== */
.marks { display: grid; gap: var(--sp-6) var(--sp-7); grid-template-columns: minmax(0, 1fr); --mark-h: clamp(5.5rem, 7.5vw, 7.5rem); }
.marks__group { border-top: 1px solid var(--line); padding-top: var(--sp-4); min-width: 0; }
.marks__label { font-size: var(--fs-small); font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); }
.marks__row { list-style: none; margin: var(--sp-5) 0 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-5) clamp(1.5rem, 3vw, 2.5rem); }
.marks__row li { display: block; }
.marks__row img { display: block; height: var(--mark-h); width: auto; mix-blend-mode: multiply; }
@media (min-width: 64rem) {
  .marks { grid-template-columns: max-content max-content; justify-content: space-between; }
  .marks__row { flex-wrap: nowrap; gap: clamp(1rem, 2vw, 1.75rem); }
}

/* About › 2010: the three photographs of the factory read as ONE mosaic (Sr. Manuel,
   11 Oct) — the portrait full height on the left, the bars and the gloves stacked
   on the right, one frame, captions set over the pictures. */
.jr__figs--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); height: clamp(24rem, 66vw, 40rem); align-items: stretch; }
.jr__figs--3 .jr-fig { position: relative; overflow: hidden; border-radius: var(--radius); }
.jr__figs--3 .jr-fig:first-child { grid-column: 2; grid-row: 1; }
.jr__figs--3 .jr-fig:nth-child(2) { grid-column: 1; grid-row: 1 / span 2; }
.jr__figs--3 .jr-fig:nth-child(3) { grid-column: 2; grid-row: 2; }
.jr__figs--3 .jr-fig img { width: 100%; height: 100%; max-width: none; border-radius: 0; object-fit: cover; }
.jr__figs--3 .jr-fig figcaption { position: absolute; left: 0; right: 0; bottom: 0; margin: 0; padding: var(--sp-5) var(--sp-3) var(--sp-2); font-size: var(--fs-small); line-height: 1.3; color: var(--paper-50); background: linear-gradient(to top, rgba(8,5,3,.7), transparent); }
.jr__figs--3 .jr-fig:nth-child(2) img { object-position: 50% 22%; }
/* On the internal heroes a provenance note must never sit over the copy or the
   buttons: it goes in flow, under the first screen, on a dark strip. */
.scene--page .scene__flag { position: static; padding: var(--sp-3) var(--gutter); background: var(--cacao-900); }

/* About › Venezuelan Cacao — editorial photo gallery, tree to tasting. Desktop: two
   rows of twelve columns (5·3·4 and 3·5·4), one height per row; phones: a wide
   frame, then pairs, then a wide frame. Captions sit over the pictures. */
.cg { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: clamp(11rem, 52vw, 16rem); gap: var(--sp-2); margin-top: clamp(1.5rem, 4vw, 2.5rem); }
.cg__item { position: relative; margin: 0; overflow: hidden; border-radius: var(--radius); min-width: 0; }
.cg__item:first-child, .cg__item:last-child { grid-column: 1 / -1; }
.cg__item img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 1.4s var(--ease-out); }
.cg__item:hover img { transform: scale(1.03); }
.cg__item figcaption { position: absolute; left: 0; right: 0; bottom: 0; margin: 0; padding: var(--sp-6) var(--sp-3) var(--sp-3); font-size: var(--fs-small); line-height: 1.3; color: var(--paper-50); background: linear-gradient(to top, rgba(8,5,3,.72), transparent); }
@media (min-width: 64rem) {
  .cg { grid-template-columns: repeat(12, minmax(0, 1fr)); grid-auto-rows: clamp(15rem, 25vw, 24rem); gap: var(--sp-3); }
  .cg__item:first-child, .cg__item:last-child { grid-column: auto; }
  .cg__item:nth-child(1) { grid-column: span 5; }
  .cg__item:nth-child(2) { grid-column: span 3; }
  .cg__item:nth-child(3) { grid-column: span 4; }
  .cg__item:nth-child(4) { grid-column: span 3; }
  .cg__item:nth-child(5) { grid-column: span 5; }
  .cg__item:nth-child(6) { grid-column: span 4; }
}
@media (prefers-reduced-motion: reduce) { .cg__item img { transition: none; } }
.marks--lg { --mark-h: clamp(6rem, 8.5vw, 9rem); margin-top: var(--sp-6); }
.marks--lg { margin-bottom: var(--sp-5); }
/* The first block after a page hero always gets air above it (several were built
   `flush-top` for the old text-only page head and sat glued to the photograph). */
.scene--page + .section, .scene--page + .section.section--flush-top { padding-top: var(--section-y); }

/* Accordion panel with only a packshot (no lifestyle scene yet): the bag sits
   whole and centered on the product's band color, no crop and no zoom. */
.shop-accordion__media--pack { background: var(--v); }
.shop-accordion__media--pack img { object-fit: contain; padding: clamp(1.5rem, 8%, 3rem); filter: none; transform: none !important; }

/* ABOUT › THE JOURNEY — chapter 1828 opens on the portrait of Vicente Franceschi
   Vicentelli: the portrait on the left, the two Carúpano postcards stacked beside
   it. On a phone everything stacks, portrait first. */
.jr-fig--portrait img { width: min(100%, 24rem); aspect-ratio: 3 / 4; object-fit: cover; object-position: 50% 30%; }
@media (min-width: 40rem) {
  .jr__figs--portrait { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); align-items: start; }
  .jr__figs--portrait .jr-fig--portrait { grid-column: 1; grid-row: 1 / span 2; }
  .jr__figs--portrait .jr-fig--portrait img { width: 100%; }
  .jr__figs--portrait .jr-fig:not(.jr-fig--portrait) { grid-column: 2; }
}

/* PRODUCT PAGE — fluidity in half steps (2.5 / 5) and the supplied Nutrition Facts
   label. The label is a flat white image, so it multiplies onto the warm paper
   instead of showing as a stark white card. */
.fluidity__pip.is-half { background: linear-gradient(90deg, var(--v, var(--accent)) 50%, var(--line) 50%); }
.fluidity__pip { flex: 0 1 1.375rem; min-width: .75rem; }
.fluidity__text { display: block; margin-top: var(--sp-1); }
.nutri { margin: 0; }
.nutri img { display: block; width: min(100%, 26rem); height: auto; mix-blend-mode: multiply; border-radius: var(--radius); }

/* ==========================================================================
   28. EDITORIAL LAYER — October 2026 design pass.
   Composition, motion and reach only. No copy, section, order, photograph or
   product is added, removed or changed here; everything below reads the tokens
   in :root (--dur-*, --rise, --stagger, --ease-out) so the whole site moves with
   one voice. Every motion is transform/opacity/clip-path, every one is off under
   prefers-reduced-motion, and nothing here hides content when JS is absent.
   ========================================================================== */

/* 28a. Pinned scenes that outgrow the screen. A scene is one screen tall and
   pinned; on a short laptop (1366x768 leaves ~580px under the header) its copy
   plate can be taller than that, and whatever falls below is unreachable: the
   Discovery Kit button was never on screen. initSceneFit() (app.js) measures the
   plate and, only when it does not fit, hands the scene its natural height. */
.scene.scene--grow { position: relative; height: auto; min-height: 100svh; }
.scene.scene--grow .scene__content { height: auto; min-height: inherit; }
.scene.scene--hero.scene--grow { min-height: 100svh; }

/* 28b. First-screen entrance. Transform only: the copy is painted from the first
   frame (an opacity-0 entrance would delay the largest paint), it just rises
   into place, block by block. */
@keyframes rise {
  from { transform: translate3d(0, var(--rise), 0); }
  to   { transform: none; }
}
.scene--hero .scene__inner[data-reveal],
.scene--page .scene__inner[data-reveal] { opacity: 1; transform: none; transition: none; }
.scene--hero .scene__inner > *,
.scene--page .scene__inner > * { animation: rise var(--dur-reveal) var(--ease-out) both; }
.scene--hero .scene__inner > :nth-child(2), .scene--page .scene__inner > :nth-child(2) { animation-delay: calc(var(--stagger) * 1.5); }
.scene--hero .scene__inner > :nth-child(3), .scene--page .scene__inner > :nth-child(3) { animation-delay: calc(var(--stagger) * 3); }
.scene--hero .scene__inner > :nth-child(4), .scene--page .scene__inner > :nth-child(4) { animation-delay: calc(var(--stagger) * 4.5); }
.scene--hero .scene__inner > :nth-child(n+5), .scene--page .scene__inner > :nth-child(n+5) { animation-delay: calc(var(--stagger) * 6); }
/* Hero depth: initHeroDepth() sets --hero-p (0 at the top of the page, 1 when the
   hero has scrolled out); the film drifts and the copy lifts away, transform and
   opacity only. */
.scene--hero .scene__media { transform: translate3d(0, calc(var(--hero-p, 0) * 6%), 0) scale(calc(1 + var(--hero-p, 0) * .05)); }
.scene--hero .scene__content { opacity: calc(1 - var(--hero-p, 0) * 1.15); }

/* 28c. Scroll reveal, one distance and one duration for every block. */
[data-reveal] {
  transform: translate3d(0, var(--rise), 0);
  transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal].is-in { transform: none; }
[data-reveal="fade"] { transform: none; }
[data-reveal="scale"] { transform: scale(.97); }
[data-reveal="scale"].is-in { transform: none; }

/* 28d. Photographs open like a shutter: a clip-path mask that lifts while the
   image settles from a slight zoom. Marked by initMotion(); an image JS never
   marks is simply visible. */
[data-mask] {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.15s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-mask].is-in { clip-path: inset(0 0 0 0); }
[data-mask=""] > img, [data-mask=""] > picture img {
  transform: scale(1.1);
  transition: transform 1.6s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-mask=""].is-in > img, [data-mask=""].is-in > picture img { transform: none; }

/* 28e. Display headings arrive word by word, each word rising out of its own
   line mask. Words are split in the browser from the existing text; the heading
   text content is unchanged. */
.w { display: inline-block; overflow: hidden; vertical-align: top; padding: 0 .07em .18em; margin: 0 -.07em -.18em; }
.w__i { display: inline-block; transform: translate3d(0, 115%, 0); transition: transform 1s var(--ease-out); transition-delay: calc(var(--wi, 0) * 42ms + var(--reveal-delay, 0ms)); }
.is-split-in .w__i { transform: none; }

/* 28f. About, the journey, drawn as it is read. The rail fills with gold as the
   page moves from 1828 to today (initSpine sets --spine, 0 to 1); each chapter
   marker lights when its chapter arrives. */
.jr-list::after {
  content: ""; position: absolute; left: -1px; top: 0; bottom: 0; width: 3px; border-radius: 2px;
  background: linear-gradient(var(--gold-500), var(--brass-500));
  transform: scaleY(var(--spine, 0)); transform-origin: top; pointer-events: none;
}
.jr::before { z-index: 1; transition: box-shadow var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out); transform: scale(.6); }
.jr.is-in::before { transform: none; box-shadow: 0 0 0 5px color-mix(in srgb, var(--gold-500) 24%, transparent); }

/* 28g. Header: always fixed to the top (Sr. Manuel, 11 Oct); it no longer hides on scroll. */
.subnav { top: var(--sticky-top); }

/* 28h. Typographic finish: no one-word last lines in running text. */
p, li, dd, figcaption, blockquote { text-wrap: pretty; }

/* 28i. How to buy, the note under the options. It sat as a hard-edged white
   slab on the dark band; it now belongs to the band: a hairline panel, the
   same radius as every other card, the same type. */
#how-to-buy > .wrap > .card.surface-paper {
  --text: #EFE4D7; --text-strong: var(--paper-50); --line: rgba(239,228,215,.18);
  background: rgba(253, 251, 247, .05);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: none;
}
#how-to-buy > .wrap > .card.surface-paper:hover { transform: none; box-shadow: none; border-color: var(--line); }

/* 28j. Interaction vocabulary, one for every control. Hover effects live under
   (hover: hover); on a touch screen the pressed state answers instead of a hover
   that would stay stuck after the tap. */
.btn svg, .link svg, .app-tile__arrow svg { transition: transform var(--dur-ui) var(--ease-out); }
@media (hover: hover) {
  .btn:hover svg, .link:hover svg { transform: translateX(.25rem); }
}
@media (hover: none) {
  .btn:hover::before { transform: translateY(101%); }
  .btn:hover, .btn--ghost:hover, .surface-cacao .btn:hover, .hero .btn:hover,
  .surface-cacao .btn--ghost:hover, .hero .btn--ghost:hover, .btn--ghost-gold:hover { color: var(--btn-fg); border-color: var(--btn-bd); }
  .btn:active::before { transform: translateY(0); }
  .btn:active, .btn--ghost:active, .surface-cacao .btn:active, .hero .btn:active,
  .surface-cacao .btn--ghost:active, .hero .btn--ghost:active { color: var(--btn-bg); }
  .card:hover { transform: none; box-shadow: var(--shadow); }
  .card:hover .card__media img { transform: none; }
  .card:active { transform: scale(.985); }
  .product-card:hover::before { transform: scaleX(0); }
  .app-tile:hover::before { transform: translateY(100%); }
  .app-tile:hover { color: inherit; }
  .app-tile:active::before { transform: translateY(0); }
  .app-tile:active { color: var(--paper-50); }
}
/* keyboard focus: the outline plus a soft halo, on every interactive element */
:focus-visible { box-shadow: var(--ring); }

@media (prefers-reduced-motion: reduce) {
  [data-mask], [data-mask] > img, .w__i { clip-path: none !important; transform: none !important; transition: none !important; }
  .scene--hero .scene__media, .scene--hero .scene__content { transform: none !important; opacity: 1 !important; }
  .scene--hero .scene__inner > *, .scene--page .scene__inner > * { animation: none !important; }
  .jr-list::after { transform: scaleY(1); }
}

/* 28k. Short desktop screens (1366x768, 1440x900): the Discovery Kit plate is tightened so
   the pinned scene still fits where it can. */
@media (min-width: 1024px) and (max-height: 960px) {
  .scene__plate { padding: clamp(1rem, 2.6svh, 1.75rem) clamp(1.5rem, 3vw, 2.5rem); }
  .kit-offer { margin-block: var(--sp-1) var(--sp-2); }
  .kit-offer__pct { font-size: clamp(3rem, 9.5svh, 5rem); }
}

/* 28l. Without JavaScript nothing waits to be revealed: every block is simply there. */
@media (scripting: none) {
  [data-reveal], [data-mask] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
}

/* 28m. Cart: the lines are drawn by JS after the first paint; the area is reserved so the
   footer does not jump when the empty state (or the lines) arrive. */
#cart-lines { min-height: 28rem; }

/* ==========================================================================
   29. FULL-SCREEN HEROES (Sr. Manuel, 11 Oct: every hero is 100vh). The photograph
   or film runs from the very top of the page; the header lies over it, clear at the
   top of the page and solid the moment the page moves (.is-stuck, set by initHeader).
   Interior pages carry a breadcrumb above the hero; it floats over the image too.
   ========================================================================== */
/* Round 4 (HM-01): the header no longer starts clear over a hero — it is fixed and
   the same brown from the first pixel to the last, so its text always reads. */
.header { transition: box-shadow var(--t-base), transform var(--dur-ui) var(--ease-out); }

main > .crumbs:has(+ .scene--hero) { position: relative; z-index: 3; color: rgba(253, 251, 247, .82); text-shadow: 0 1px 12px rgba(8, 5, 3, .55); }
main > .crumbs:has(+ .scene--hero) [aria-current="page"] { color: var(--paper-50); }
main > .crumbs:has(+ .scene--hero) a { color: inherit; }

/* 30. Footer credit: the agency line under the legal row. */
.footer__made { margin: 0; font-size: var(--fs-small); color: var(--cacao-300); }
.footer__made a { display: inline-flex; align-items: center; min-height: 2.75rem; padding-inline: .25rem; color: var(--paper-200); text-decoration: underline; text-underline-offset: .2em; text-decoration-thickness: 1px; transition: color var(--t-fast); }
.footer__made a:hover, .footer__made a:focus-visible { color: var(--brass-300); }

/* 31. Header and forms in brown (Sr. Manuel, 11 Oct). The header is fixed and brown;
   on a page that opens with a full-screen hero it starts clear and turns brown with
   the first scroll (section 29). The two forms (Bulk quote, Contact) are brown cards
   with cream fields, so they stand out from the paper page. */
/* Sr. Manuel, 19 Oct (HM-01, option 2): always the near-black the client saw at the
   top of the page, never changing on scroll — the same tone as the footer. */
.header { background: var(--cacao-900); }
.bulk-lead__form, .form-card {
  --bg: var(--cacao-800); --bg-raised: var(--cacao-700); --bg-sunken: var(--cacao-900);
  --text: #EFE4D7; --text-strong: var(--paper-50); --text-muted: var(--cacao-300);
  --line: rgba(239, 228, 215, .24); --line-soft: rgba(239, 228, 215, .12);
  --accent: var(--brass-300); --on-accent: var(--cacao-900); --focus: var(--brass-300);
  background: var(--cacao-800); color: var(--text);
  border-color: var(--cacao-600);
  padding: clamp(1.25rem, 3vw, 2.25rem);
  box-shadow: 0 24px 56px -28px rgba(47, 25, 19, .55);
}
:is(.bulk-lead__form, .form-card) .input,
:is(.bulk-lead__form, .form-card) .select,
:is(.bulk-lead__form, .form-card) .textarea { background-color: var(--paper-100); color: var(--cacao-900); border-color: transparent; }
:is(.bulk-lead__form, .form-card) .input::placeholder,
:is(.bulk-lead__form, .form-card) .textarea::placeholder { color: var(--cacao-500); }
:is(.bulk-lead__form, .form-card) .input:hover,
:is(.bulk-lead__form, .form-card) .select:hover,
:is(.bulk-lead__form, .form-card) .textarea:hover { border-color: var(--brass-300); }
:is(.bulk-lead__form, .form-card) .input:focus,
:is(.bulk-lead__form, .form-card) .select:focus,
:is(.bulk-lead__form, .form-card) .textarea:focus { border-color: var(--brass-300); box-shadow: 0 0 0 3px rgba(221, 181, 124, .38); }
:is(.bulk-lead__form, .form-card) .field .req { color: #FFB199; }
:is(.bulk-lead__form, .form-card) .error-msg { color: #FFB4A2; }
:is(.bulk-lead__form, .form-card) :is(.input, .select, .textarea)[aria-invalid="true"] { border-color: #FF8A70; box-shadow: 0 0 0 3px rgba(255, 138, 112, .3); }

/* ==========================================================================
   32. ROUND 4 (18 Oct 2026)
   ========================================================================== */

/* DK-11 / BO-05: words that describe, not controls. No border, no pill, no
   fill — set as a quiet run of small caps separated by a dot, so nothing about
   them suggests a click. */
.word-list {
  list-style: none; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 9rem), 1fr));
  gap: var(--sp-2) var(--sp-4);
  font-size: var(--fs-small); font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-muted);
}
.word-list li { display: flex; align-items: flex-start; gap: var(--sp-2); min-width: 0; }
.word-list li::before {
  content: ""; flex: none; width: 4px; height: 4px; border-radius: 50%;
  margin-top: .6em; background: var(--brass-500);
}

/* DK-06 / DK-07: What's Inside — seven sachets, each with its own image. */
/* The 4.23 oz mockups come on a white studio ground: the cards are paper and the
   image multiplies into them, so no white square ever shows. Seven cards — two
   per row on a phone, four on a tablet (4 + 3, centred), all seven in one row
   from 64rem. */
.kit-grid {
  list-style: none; margin: var(--sp-6) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-3);
}
.kit-item {
  flex: 0 1 calc(50% - var(--sp-3) / 2);
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--sp-2); min-width: 0;
  padding: var(--sp-3) var(--sp-3) var(--sp-4);
  border-radius: var(--radius-lg);
  background: var(--paper-50);
  --text-strong: var(--cacao-900); --text-muted: var(--cacao-600);
  color: var(--cacao-900);
}
@media (min-width: 40rem) { .kit-item { flex-basis: calc(25% - var(--sp-3) * 3 / 4); } }
@media (min-width: 64rem) { .kit-item { flex: 1 1 0; } }
.kit-item__img { width: 100%; max-width: 10rem; height: auto; aspect-ratio: 1; object-fit: contain; mix-blend-mode: multiply; }
.kit-item__body { min-width: 0; }
.kit-item__name { font-size: var(--fs-h4); line-height: 1.25; }
.kit-item__oz { margin-top: var(--sp-1); font-size: var(--fs-small); color: var(--text-muted); }

/* SH-04: front / back / lifestyle thumbnails under the product stage. */
.thumbs { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.thumbs__btn {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-1);
  padding: var(--sp-2); min-width: 2.75rem;
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--bg-sunken); color: var(--text-muted);
  font: inherit; font-size: var(--fs-small); cursor: pointer;
  transition: border-color var(--t-fast), color var(--t-fast);
}
.thumbs__btn img { width: 4.5rem; height: 4.5rem; object-fit: contain; border-radius: var(--radius-sm); }
.thumbs__btn:hover { color: var(--text); border-color: var(--line); }
.thumbs__btn[aria-current="true"] { border-color: var(--brass-500); color: var(--text-strong); }
.thumbs__btn:focus-visible { outline: 2px solid var(--focus, var(--brass-500)); outline-offset: 2px; }

/* SH-01: the Discovery Kit card is a SKU like the others — a cut-out packshot on the same ground (Sr. Manuel, 19 Oct). */
.product-card__flag {
  position: absolute; top: var(--sp-3); left: var(--sp-3); z-index: 2;
  padding: var(--sp-1) var(--sp-3); border-radius: 999px;
  background: var(--cacao-800); color: var(--paper-50);
  font-size: var(--fs-small); font-weight: 600; letter-spacing: .06em;
}
.product-card__from s, .cart-line__meta s { opacity: .75; }

/* Cart: the kit line has no stepper; the total row now includes shipping. */
#sum-shipping-note { margin: 0; }
#sum-shipping-note:empty { display: none; }

/* FP-02: policy and FAQ pages on the sitewide scale — the page title is a section
   title, the section titles are subsection titles, the third level is a card
   title. One hierarchy, the same steps as the rest of the site. */
.policy-page .page-head__title { font-size: var(--fs-h2); max-width: none; }
.policy-page .policy h2 { font-size: var(--fs-h3); line-height: 1.2; }
.policy-page .policy h3 { font-size: var(--fs-h4); line-height: 1.25; margin-top: 1.4em; }
.policy-page .summary .routes__list { margin-top: var(--sp-3); }

/* 19 Oct 2026: What's Inside cards link to the 2 lb bag in the shop. The whole
   card is the target; the "Shop the 2 lb Bag" line says where it goes. */
.kit-item--link { padding: 0; }
.kit-item__link {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  width: 100%; height: 100%; padding: var(--sp-3) var(--sp-3) var(--sp-4);
  border-radius: inherit; color: inherit; text-decoration: none;
  transition: box-shadow var(--t-base) var(--ease-out), transform var(--t-base) var(--ease-out);
}
.kit-item__shop {
  margin-top: var(--sp-2); display: inline-flex; align-items: center; gap: var(--sp-1);
  font-size: var(--fs-small); font-weight: 600; color: var(--brass-700);
  text-decoration: underline; text-underline-offset: .2em; text-decoration-thickness: 1px;
}
@media (hover: hover) {
  .kit-item__link:hover { box-shadow: var(--shadow-lg); transform: translateY(-3px); }
}
.kit-item__link:focus-visible { outline: 2px solid var(--brass-500); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .kit-item__link { transition: none; } .kit-item__link:hover { transform: none; } }
/* 19 Oct 2026: seven equal columns from 64rem (flex let long names widen a card),
   and the shop line stays on one line. */
@media (min-width: 64rem) {
  .kit-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
}
.kit-item__shop { white-space: nowrap; }
/* ==========================================================================
   33. DESKTOP FIT (Sr. Manuel, 19 Oct 2026): designed at 1280 x 800 (MacBook
   Air 13") and scaled proportionally from there up. Every presentational
   section fits one screen under the sticky header.
     · 16px root everywhere below 1280px (was 17px on desktop).
     · From 1280px the root follows the smaller of width and height
       (1.25vw = 16px at 1280; 2vh = 16px at 800), so a layout that fits
       1280 x 800 fits 1440 x 900, 1920 x 1080 and beyond, and a short
       1366 x 768 window shrinks instead of overflowing. Type tokens become
       fixed rems there, so they scale with the root and nothing else.
     · Compact header from 1024px: the vertical logotype at 3.5rem, the nav
       row tightened — 185px became ~110px.
   ========================================================================== */
html { font-size: 16px; }
@media (min-width: 80rem) {
  html { font-size: clamp(16px, min(1.25vw, 2vh), 18px); } /* R6: capped at 18px (was 28px: text read as enormous from 1920 px up) */
  :root {
    --fs-h1: 3.25rem;
    --fs-h2: 2.375rem;
    --fs-h3: 1.5rem;
    --fs-h4: 1.1875rem;
    --fs-lede: 1.125rem;
    --section-y: 3rem;
    --gutter: 4rem;
  }
}
@media (min-width: 64rem) {
  .header__inner { padding-block: .5rem 0; row-gap: .25rem; min-height: 0; }
  /* Ronda 5 (G-01): the logotype goes back up from 3.5rem to 4.75rem (the mobile size); the header grows by 1.25rem. */
  .brand img { height: 4.75rem; }
  .nav__link { padding-block: .5rem; }
  :root { --header-h: 8.125rem; }
  /* the announcement bar keeps one line: the third message only where it fits */
  .announce__track { min-height: 2.25rem; }
  .announce__item--extra:last-child { display: none; }
}
@media (min-width: 90rem) {
  .announce__item--extra:last-child { display: flex; }
}
/* The height left under the sticky header: what a section has to fit in. */
:root { --fit-h: calc(100svh - var(--header-h)); }
@media (min-width: 64rem) {
  /* Why Franceschi: the photograph takes the height of the copy beside it, and
     the whole block never outgrows the screen. */
  .band--fit { padding-block: clamp(1.5rem, 5svh, 3rem); }
  .why-split { align-items: stretch; }
  .why-split > .rounded { position: relative; min-height: 22rem; max-height: calc(var(--fit-h) - 4rem); }
  .why-split > .rounded img.ratio-4-5 { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; }
  .why-split .prose > * + * { margin-top: .9em; }
  .awards-band { padding-block: 0 clamp(1.5rem, 5svh, 3rem); }

  /* The store: two screens, each exactly the height under the header. */
  #store.band--entry { padding-block: 0; }
  .store-screen { height: var(--fit-h); display: flex; flex-direction: column; }
  .store-head {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5) var(--sp-7);
    align-items: end; text-align: left;
    padding-block: clamp(1.5rem, 5svh, 3rem);
  }
  .store-head .lede { max-width: 48ch; }
  .store-screen > .shop-accordion { flex: 1 1 auto; min-height: 0; height: auto; }
  .store-screen--apps > .wrap { padding-block: clamp(1.5rem, 5svh, 3rem) 0; }
  .store-screen--apps .section-head { margin-bottom: 0; }
  .store-screen > .app-grid { flex: 1 1 auto; min-height: 0; margin-top: clamp(1rem, 3svh, 1.5rem); }

  /* How to buy: the carousel card follows the screen height. */
  #how-to-buy { padding-block: clamp(1.5rem, 4svh, 2.5rem); }
  #how-to-buy .cf { --cf-h: clamp(19rem, calc(var(--fit-h) - 21rem), 31rem); --cf-w: calc(var(--cf-h) * .66); }

  /* Our commitment: one screen, the box centered in it. */
  .commit { min-height: var(--fit-h); padding-block: clamp(1.5rem, 5svh, 3rem); }

  /* Interior pages whose photograph sits in a sticky 4:5 column (Discovery Kit,
     recipes, collections): the photograph never outgrows the screen. */
  .sticky-col img.ratio-4-5, .sticky-col .rounded img.ratio-4-5 { max-height: calc(var(--fit-h) - 2.5rem); }
}
@media (min-width: 64rem) {
  /* Discovery Kit page: the first screen holds the whole offer. */
  .kit-top { padding-block: clamp(1rem, 3svh, 1.5rem); }
  .kit-top .lede.mt-5 { margin-top: var(--sp-3); }
  .kit-top .lede + .mt-4 { margin-top: var(--sp-3); }
  .kit-top .card.mt-6 { margin-top: var(--sp-4); }
  .kit-top .card .kit-offer { margin-top: var(--sp-2); }
  .kit-top .card .kit-offer__pct { font-size: clamp(2.75rem, 7svh, 4rem); }
  .kit-top .card .kit-price.mt-4, .kit-top .card .t-sm.mt-4, .kit-top .card .t-xs.mt-4 { margin-top: var(--sp-3); }
  .kit-top .card .btn-row.mt-5 { margin-top: var(--sp-4); }
}
/* Short desktop windows (1366 x 768, 1024 x 768): the root cannot drop below 16px
   without taking the smallest type under 14px, so the Discovery Kit's first
   screen tightens its own title and intro instead. */
@media (min-width: 64rem) and (max-height: 49.9rem) {
  .kit-top { padding-block: 1rem; }
  .kit-top h1 { font-size: 2.75rem; }
  .kit-top .lede { font-size: 1rem; }
  .kit-top .card .kit-offer__pct { font-size: 2.75rem; }
}
/* Product page (19 Oct, Sr. Manuel): on a laptop the Add to Cart button sits in
   the first screen, next to the bag. */
@media (min-width: 64rem) {
  .pdp { padding-block-start: var(--sp-4); }
  .pdp h1 { font-size: var(--fs-h2); }
  .pdp h1.mt-4 { margin-top: var(--sp-2); }
  .pdp .lede.mt-4 { margin-top: var(--sp-3); }
  .pdp .chip-row.mt-5 { margin-top: var(--sp-3); }
  .pdp form.mt-6 { margin-top: var(--sp-4); }
  .pdp form .mt-5 { margin-top: var(--sp-4); }
}
@media (min-width: 64rem) and (max-height: 49.9rem) {
  .pdp .lede { font-size: 1rem; }
}
/* Bulk: the "who we supply" words run as one line of text that wraps between
   words, never inside "Restaurant Groups" (19 Oct). */
.word-list { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); }
.word-list li { white-space: nowrap; }
/* Contact: the four policy summaries are reference blocks, titled at card
   size so the pair of columns fits one laptop screen (19 Oct). */
@media (min-width: 64rem) {
  .support-info h2 { font-size: var(--fs-h3); }
  .support-info h2.mt-7 { margin-top: var(--sp-6); }
}
/* ============================================================================
   RONDA 5 (aprobada 2026-10-21)
   LE-04 stage icons · AB-02 About "Today" closing · CO-07 Contact aside
   ========================================================================== */
.stage-title { display: flex; align-items: center; gap: var(--sp-3); }
.stage-icon { flex: none; width: 2rem; height: 2rem; color: var(--cacao-600); }
.stage-icon svg { width: 100%; height: 100%; display: block; }

.today { background: var(--paper-100); }
.today__grid { display: grid; gap: var(--sp-6); align-items: center; }
.today__body > * + * { margin-top: var(--sp-4); }
.today__mosaic { display: grid; gap: var(--sp-3); grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; }
.today__mosaic figure { margin: 0; border-radius: var(--radius-lg); overflow: hidden; background: var(--bg-sunken); }
.today__mosaic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.today__mosaic .today__tall { grid-row: span 2; min-height: 100%; }
.today__mosaic .today__small { aspect-ratio: 1 / 1; }
@media (min-width: 64rem) {
  .today__grid { grid-template-columns: 1fr 1.1fr; gap: var(--sp-8); }
}

/* CO-07: Find What You Need stays beside the form while it scrolls */
@media (min-width: 64rem) {
  .split--top > .routes { position: sticky; top: calc(var(--header-h) + 1rem); }
}

/* ============================================================================
   R6 · RESPIRO (Sr. Manuel, 21 Oct 2026: "las letras están gigantes, no hay espacio
   para respirar"). Diagnóstico: la sección 33 obligaba a cada bloque a caber en
   UNA pantalla bajo la cabecera y escalaba el root con el viewport. Resultado:
   tipografía grande, bloques sin aire, títulos pegados al fondo.
   Decisiones (whitespace antes que contenido, jerarquía por tamaño real):
     · root fijo en 16px: nada escala con la pantalla;
     · escala de títulos una nota más baja (h1 44, h2 32, lede 17);
     · cada bloque vuelve a su altura natural con padding vertical propio;
     · títulos centrados verticalmente respecto a su texto;
     · cabecera y barra de anuncios más discretas.
   ========================================================================== */
html { font-size: 16px; }
:root {
  --fs-h1:    clamp(1.75rem, calc(1.1rem + 2.2vw), 2.75rem);
  --fs-h2:    clamp(1.5rem, calc(1.1rem + 1.2vw), 2rem);
  --fs-h3:    clamp(1.25rem, 1.8vw, 1.375rem);
  --fs-h4:    1.125rem;
  --fs-lede:  clamp(1rem, 1.1vw, 1.0625rem);
  --section-y: clamp(3rem, 7vw, 5.5rem);
  --gutter:    clamp(1.25rem, 5vw, 4.5rem);
}
@media (min-width: 80rem) {
  html { font-size: 16px; }
  :root { --fs-h1: 2.75rem; --fs-h2: 2rem; --fs-h3: 1.375rem; --fs-h4: 1.125rem; --fs-lede: 1.0625rem; --section-y: 5.5rem; --gutter: 4.5rem; }
}

/* Cabecera y barra de anuncios más discretas */
.announce { font-size: .9375rem; }
.announce__track { min-height: 2.5rem; }
.nav__link { font-size: .875rem; letter-spacing: .09em; }

@media (min-width: 64rem) {
  /* Why Franceschi: foto y texto centrados entre sí, sin forzar la altura de pantalla */
  .band--fit { padding-block: var(--section-y) var(--sp-7); }
  .why-split { align-items: center; gap: clamp(2rem, 5vw, 5rem); }
  .why-split > .rounded { position: static; min-height: 0; max-height: none; }
  .why-split > .rounded img.ratio-4-5 { position: static; width: 100%; height: auto; aspect-ratio: 4 / 5; max-height: 36rem; }
  .why-split .prose > * + * { margin-top: 1.1em; }
  .awards-band { padding-block: var(--sp-6) var(--section-y); }

  /* La tienda: cada mitad con su propio aire; títulos centrados con su texto */
  .store-screen { height: auto; }
  .store-head { align-items: center; padding-block: var(--section-y); }
  .store-screen > .shop-accordion { flex: none; height: clamp(26rem, 64svh, 36rem); }
  .store-screen--apps > .wrap { padding-block: var(--section-y) 0; }
  .store-screen--apps .section-head { margin-bottom: 0; align-items: center; }
  .store-screen > .app-grid { flex: none; margin-top: var(--sp-6); }

  /* Cómo comprar y compromiso: altura propia */
  #how-to-buy { padding-block: var(--section-y); }
  #how-to-buy .cf { --cf-h: clamp(22rem, 52svh, 30rem); --cf-w: calc(var(--cf-h) * .66); }
  .commit { min-height: clamp(30rem, 72svh, 44rem); padding-block: var(--section-y); }

  .sticky-col img.ratio-4-5, .sticky-col .rounded img.ratio-4-5 { max-height: 80svh; }

  /* Discovery Kit (página): conserva su compactación propia (CTA en la primera pantalla) */
}
}

/* Encabezados de sección y bloques en dos columnas: centrados verticalmente */
@media (min-width: 60rem) {
  .section-head--split { align-items: center; }
}
.split { align-items: center; }
.split--top { align-items: start; }

/* Escena del Discovery Kit en el Home: placa más angosta y con más relleno */
.scene--clear-header .scene__content { display: flex; }
.scene--clear-header .scene__content > .wrap { margin-block: auto; }
.scene__plate { width: min(100%, 40rem); padding: clamp(1.5rem, 3.2vw, 3rem); }
.scene__plate > * + * { margin-top: var(--sp-4); }
.scene__plate .kit-offer { margin-top: var(--sp-3); }

/* Discovery Kit (página): la primera pantalla contiene la oferta y el botón también con la cabecera de R5 */
@media (min-width: 64rem) {
  .kit-top { padding-block: .75rem 1.5rem; }
  .kit-top h1 { font-size: var(--fs-h1); }
  .kit-top .lede { font-size: 1rem; }
  .kit-top .card.mt-6 { padding: var(--sp-4) var(--sp-5) !important; margin-top: var(--sp-3); }
  .kit-top .card .kit-offer__pct { font-size: 2.5rem; }
  .kit-top .card .btn-row.mt-5 { margin-top: var(--sp-3); }
  .kit-top .card .kit-price.mt-4 { margin-top: var(--sp-2); }
  .kit-top .card .eyebrow + .kit-offer { margin-top: var(--sp-1); }
}
@media (min-width: 64rem) {
  /* la oferta y el precio comparten renglón */
  .kit-top .card.mt-6 { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--sp-5); }
  .kit-top .card.mt-6 > .eyebrow, .kit-top .card.mt-6 > .t-sm, .kit-top .card.mt-6 > .t-xs, .kit-top .card.mt-6 > .btn-row { flex: 0 0 100%; }
  .kit-top h1 { font-size: 2.5rem; }
}
@media (min-width: 64rem) {
  .kit-top .card.mt-6 > .kit-offer, .kit-top .card.mt-6 > .kit-price { flex: 0 0 auto; width: auto; margin-top: var(--sp-2); }
  .kit-top .card.mt-6 > .t-sm { margin-top: var(--sp-2); }
  .kit-top .card.mt-6 > .btn-row { margin-top: var(--sp-3); }
  .kit-top .card.mt-6 .btn--lg { padding-block: .75rem; }
}

/* ============================================================================
   R7 · RESPONSIVE (mobile y tablet) + correcciones del centrado de R6
   ========================================================================== */
/* El centrado vertical de R6 no debe aplicar a columnas pegajosas ni al formulario de Bulk */
.split--sticky { align-items: start; }
.bulk-lead__grid { align-items: start; }

/* Tienda del Home: aire propio también en móvil y tablet (R6 solo lo daba desde 64rem) */
.store-head { display: grid; gap: var(--sp-4); padding-block: var(--section-y) var(--sp-6); }
.store-head .lede { max-width: none; }
.store-head .btn-row { margin-top: var(--sp-3); }
.store-screen--apps > .wrap { padding-block: var(--section-y) var(--sp-5); }
.store-screen--apps .section-head { margin-bottom: 0; }
.app-grid { margin-top: var(--sp-5); }

/* Acordeón de productos bajo 64rem: tarjetas con proporción propia, no franjas bajas que recortan la bolsa */
@media (max-width: 63.999rem) {
  .shop-accordion { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .shop-accordion__panel { height: auto; aspect-ratio: 1 / 1; }
  .shop-accordion__label { padding: var(--sp-5); }
}
@media (min-width: 40rem) and (max-width: 63.999rem) {
  .shop-accordion { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .shop-accordion__panel { aspect-ratio: 4 / 5; }
  .shop-accordion__panel:last-child:nth-child(odd) { grid-column: 1 / -1; aspect-ratio: 16 / 9; }
}

/* ---- Tablet (40rem–64rem): proporciones propias ---- */
@media (min-width: 40rem) and (max-width: 63.999rem) {
  /* Why Franceschi: una foto de 4:5 a todo el ancho ocupaba casi una pantalla */
  .why-split > .rounded img.ratio-4-5 { aspect-ratio: 3 / 2; max-height: 26rem; }
  /* Aplicaciones: baldosas más bajas */
  .app-grid .app-tile { aspect-ratio: 1 / 1.15; min-height: 0; }
  /* "How it works" y rejillas de 4: dos columnas, sin tarjeta huérfana */
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.jr__year { font-size: clamp(2.75rem, 7vw, 4.5rem); }

/* Ficha de producto: foto y compra lado a lado desde 48rem, con el botón en la primera pantalla */
@media (min-width: 48rem) and (max-width: 63.999rem) {
  .pdp .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-6); align-items: start; }
  .pdp .sticky-col { position: sticky; top: calc(var(--header-h) + 1rem); }
  .pdp h1 { font-size: var(--fs-h2); }
  .pdp .stepper { transform: none; }
}

/* Polish (impeccable): el botón de tarjeta no se parte en dos líneas; precio y botón envuelven en vez de apretarse */
.product-card__foot { flex-wrap: wrap; gap: var(--sp-3); }
.product-card__foot .btn { white-space: nowrap; }

/* Contact: el formulario no pega contra el hero (flush-top solo vale bajo un encabezado de página, no bajo una escena) */
.section--flush-top:has(.form-card) { padding-top: var(--section-y); }

/* R8 · FAQ: la lista (Jump to a Section / Find What You Need) va ARRIBA en móvil y tablet;
   en escritorio sigue en la columna derecha, pegajosa. */
.split--aside-first > aside { order: -1; }
@media (min-width: 62rem) {
  .split--aside-first > aside { order: 0; }
}
