/* ===========================================================================
   Tortilleria Hermanos Reyes
   One stylesheet for the whole site. Every page links to it.

   Order matters:
     1. Fonts
     2. Design tokens and base elements  (the colours, type and spacing scale)
     3. Site-wide layout and shared roles
     4. Per-section rules, grouped by the part of the site they style

   Colours, radii and spacing all come from the custom properties in section 2.
   Change one there and it updates everywhere.
   =========================================================================== */

/* ===========================================================================
   Fonts. Self-hosted; files live in ../fonts/.

   One family for the whole site: Archivo, as a variable font, so every weight
   from 100 to 900 comes out of a single file per character set. Headings use
   700 and body copy 400; both are set in section 2.

   Two files rather than one only because the accented characters Spanish needs
   (a with an acute, n with a tilde) live in the latin-ext range. The browser
   downloads that second file only when a page actually uses those characters.
   =========================================================================== */

@font-face {
  font-family: 'Archivo Variable';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/archivo-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo Variable';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/archivo-latin-ext-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* ===========================================================================
   2. Design tokens, base elements and components
   =========================================================================== */

/* Organic design system — vendored verbatim from the handoff bundle.
   design_handoff_tortilleria_site/design-system/styles.css

   Two changes from source:

   1. The Google Fonts @import was removed. The typeface is self-hosted via
      @fontsource and imported in src/layouts/Base.astro, per the handoff README
      ("in production self-host or preload them properly").

   2. The typeface itself changed. The handoff specified Caprasimo over Figtree;
      the site now uses Archivo throughout. See NOTES.md section 5 for why.

   This file is the source of truth for visual values. Do not edit it to style a
   page; add to site.css or use a scoped style block instead. */


:root {
  --color-bg: #f5ead8;
  --color-surface: #ebddc5;
  --color-text: #201e1d;
  --color-accent: #c67139;
  --color-accent-2: #7a8a5e;
  --color-divider: color-mix(in srgb, #201e1d 16%, transparent);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f9f4ed;
  --color-neutral-200: #eee7db;
  --color-neutral-300: #dcd3c4;
  --color-neutral-400: #c0b6a5;
  --color-neutral-500: #a19786;
  --color-neutral-600: #82796a;
  --color-neutral-700: #645c50;
  --color-neutral-800: #474238;
  --color-neutral-900: #2e2b25;

  --color-accent-100: #fff2eb;
  --color-accent-200: #ffe1d0;
  --color-accent-300: #ffc6a5;
  --color-accent-400: #f6a06b;
  --color-accent-500: #d67f48;
  --color-accent-600: #b2622d;
  --color-accent-700: #8c491a;
  --color-accent-800: #643312;
  --color-accent-900: #402310;

  --color-accent-2-100: #f0fae1;
  --color-accent-2-200: #e1eecc;
  --color-accent-2-300: #ccdbb2;
  --color-accent-2-400: #aebf92;
  --color-accent-2-500: #8fa073;
  --color-accent-2-600: #728157;
  --color-accent-2-700: #56633f;
  --color-accent-2-800: #3d472b;
  --color-accent-2-900: #272e1b;

  /* One family throughout. Archivo is an industrial grotesque; it matches the
     weight and posture of the logo, which is set in a heavy straight sans, so
     the headline stops competing with the mark.

     Hierarchy comes from size and weight rather than from a second family:
     headings at 700, body at 400. */
  --font-heading: "Archivo Variable", system-ui, sans-serif;
  --font-heading-weight: 700;
  --font-body: "Archivo Variable", system-ui, sans-serif;

  --space-1: 4.4px;
  --space-2: 8.8px;
  --space-3: 13.2px;
  --space-4: 17.6px;
  --space-6: 26.4px;
  --space-8: 35.2px;

  --radius-sm: 8px;
  --radius-md: 16px;
  --radius-lg: 28px;

  /* Header height. Set here rather than in the header itself because the
     banner below it subtracts this value to fill the rest of the first
     screen. Change it in one place and both follow. The two overrides are
     directly below, at the same widths the header collapses at. */
  --header-h: 180px;

  /* Elevation — derived from the ground: soft ink-tinted shadows on a
     light theme, a hairline edge + ambient darkness on a dark one. */
  --shadow-sm: 0 1px 2px color-mix(in srgb, #2e2b25 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2e2b25 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2e2b25 22%, transparent);
}

/* Matches the two breakpoints in Header.astro. */
@media (max-width: 1080px) {
  :root { --header-h: 84px; }
}
@media (max-width: 400px) {
  :root { --header-h: 68px; }
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }

/* The handoff's `.washed` rule lived here:
     filter: saturate(0.6) contrast(0.85) brightness(1.1) opacity(0.94)
   Removed 3 Sep 2026 at the client's instruction. It was written for a
   prototype full of grey placeholder boxes; against the finished
   photography it was taking 40% of the saturation out of every frame on
   the site. A knowing departure from design-system/readme.md, which still
   documents the class. The radii already depart from the handoff the same
   way, 6px instead of 40/48/56. */

/* ══════════════════════════════════════════════════════════════════════════
   Components — built with the tokens above. Plain CSS
   on plain HTML: no JavaScript, no build step. Each class is documented in
   readme.md and demonstrated in foundations/ and components/.
   ══════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; }
h6 { letter-spacing: 0.08em; text-transform: uppercase; }
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-underline-offset: 3px; }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
.hr {
  height: 1px; border: 0; margin: var(--space-4) 0;
  background: var(--color-divider);
}

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn svg { display: block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
/* Was the base accent, which measured 3.03:1 against the cream label text and
   failed WCAG AA for 15px type. Moved 28 Sep 2026 to the same deep ramp step
   the inline links use: 5.72:1. Hover and active step darker from there. */
.btn-primary { background: var(--color-accent-700); color: var(--color-bg); }
.btn-primary:hover { background: var(--color-accent-800); }
.btn-primary:active { background: var(--color-accent-900); }
.btn-secondary { border-color: var(--color-divider); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.btn-icon { width: 36px; height: 36px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); }

/* — forms — */
.field > label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
textarea.input { min-height: 90px; resize: vertical; }
.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
.radio input, .seg-opt input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.radio .dot {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--color-divider);
}
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot {
  border-color: var(--color-accent); background: var(--color-accent);
  box-shadow: inset 0 0 0 4px var(--color-bg);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.seg {
  display: inline-flex; overflow: hidden;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
}
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt:has(input:checked) { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
.card-meta {
  display: flex; align-items: center; gap: 6px; font-size: 11px;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* — tags — */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
.tag-accent-2 { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }
.tag-neutral { background: var(--color-neutral-100); color: var(--color-neutral-800); }
.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }

/* — navigation — */
.nav {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: none;
}
.nav-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 18px; margin-right: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
.nav a:hover, .nav a[aria-current='page'] { color: var(--color-accent); }

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 1px solid var(--color-divider);
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
}
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

/* — dialog — */
.dialog-backdrop {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
}
.dialog {
  width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-lg);
}
.dialog-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 20px;
}
.dialog-body { font-size: 14px; opacity: 0.85; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }

/* — rounded frame: everything softens, small controls go pill — */
.card, .dialog { border-radius: calc(var(--radius-lg) * 1.15); }
.btn, .tag, .seg, .input { border-radius: 999px; }
.input { padding-inline: 14px; }

/* ===========================================================================
   3. Site-wide layout and shared roles
   =========================================================================== */

/* Site layer — the conventions this design repeats on top of the Organic system.
   The prototype set these inline on every element; they are named here instead.
   Visual values still come from the design system's tokens. */

/* ── base ──────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  /* Design base is 17/28, coarser than the design system's 15px default. */
  font-size: 17px;
  line-height: 28px;
  text-wrap: pretty;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4, h5, h6 { text-wrap: balance; }

/* Anchor links land below the sticky header, not under it. Added 28 Sep 2026
   with the FAQ's links to #pricing-request, which otherwise hid the form's
   heading behind the header. --header-h already tracks each breakpoint. */
html { scroll-padding-top: calc(var(--header-h) + 16px); }

/* The base accent is only ~3:1 on this ground: fine for chrome, not for text.
   Every inline link in running copy uses the deep ramp step instead. */
a {
  color: var(--color-accent-700);
  text-underline-offset: 3px;
}
a:hover { color: var(--color-accent-800); }

/* ── layout ────────────────────────────────────────────────────────────── */

.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding-inline: clamp(20px, 5vw, 72px);
}

.site-main {
  flex: 1;
  /* Kept as a safety net against anything bleeding sideways and causing
     horizontal scroll. Scoped to the content region rather than html/body:
     overflow on the root propagates to the viewport and is a known source of
     trouble for `position: sticky` descendants, and the header is a sibling of
     this element, so it stays out of the clip entirely. */
  overflow-x: clip;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  border-radius: 0 0 var(--radius-md) 0;
  background: var(--color-accent-700);
  color: var(--color-bg);
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus-visible { left: 0; }

/* ── shared type roles ─────────────────────────────────────────────────── */

/* Kickers and field labels: 13px, uppercase, 0.06em, weight 600. */
.kicker {
  display: block;
  font-size: 13px;
  line-height: 18px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-accent-700);
  margin: 0 0 16px;
}

/* Page H1s add an optical flush-left correction so the first glyph's
   left sidebearing does not read as an indent against the gutter. */
.page-title {
  font-size: clamp(34px, 4.6vw, 58px);
  line-height: 1.1;
  margin: 0 0 20px;
  margin-left: -0.028em;
  max-width: 18ch;
}

.page-intro {
  font-size: 18px;
  line-height: 30px;
  max-width: 56ch;
  margin: 0;
}

.muted { color: color-mix(in srgb, var(--color-text) 78%, transparent); }
.muted-soft { color: color-mix(in srgb, var(--color-text) 70%, transparent); }

/* ── sections ──────────────────────────────────────────────────────────── */

/* Section rhythm here is coarser than the --space-* scale on purpose:
   72px top / 48-64px bottom, 56px between major blocks. */
.section-head { padding: 72px 0 48px; }
.section { padding: 0 0 56px; }
.section-lg { padding: 0 0 64px; }
.section-last { padding: 0 0 72px; }

/* ── tinted panels ─────────────────────────────────────────────────────── */

/* Flat tinted panels instead of elevation.

   This is now the ONLY tinted, rounded container on a page, and each page gets
   one: the closing call to action. It used to be one of nine such shapes on the
   home page alone, which is why nothing on the page looked more important than
   anything else. The radius came down from 56px for the same reason. */
.panel {
  border-radius: 20px;
  padding: 48px clamp(24px, 4vw, 64px);
}
.panel-accent { background: var(--color-accent-100); }
.panel-accent-2 { background: var(--color-accent-2-100); }
.panel-tight { padding: 44px clamp(24px, 4vw, 64px); }

.panel-title {
  font-size: clamp(26px, 3vw, 36px);
  line-height: 1.16;
  margin: 0 0 14px;
  max-width: 22ch;
}
.panel-body {
  font-size: 16px;
  line-height: 28px;
  max-width: 52ch;
  margin: 0 0 28px;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

/* The closing panel that ends the Products hub and both category pages. Set
   here rather than in each component: it was defined identically in two of
   them, which meant whichever stylesheet section came last silently won. */
.closing-title {
  font-size: clamp(25px, 2.8vw, 34px);
  line-height: 1.18;
  margin: 0 0 12px;
}
.closing-body {
  font-size: 16px;
  line-height: 28px;
  max-width: 52ch;
  margin: 0 0 24px;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

/* ── buttons ───────────────────────────────────────────────────────────── */

/* The design system's .btn is 14px for form rows. Page CTAs run larger. */
.btn-cta {
  font-size: 15px;
  padding: 12px 24px;
  text-decoration: none;
  white-space: nowrap;
}
.btn-cta-wide { padding: 12px 26px; }

.btn-row {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

/* ── figures ───────────────────────────────────────────────────────────── */

/* Every content photograph sits in a clipped figure.

   The radius used to run 40/48/56px, which read as a bubble and was the same
   shape language as the panels, the cards, and the buttons. Photographs now
   sit almost square so the picture is the shape, not the container. The three
   sizes are kept as separate rules so a slot can be tuned on its own. */
.figure {
  margin: 0;
  overflow: hidden;
  border-radius: 6px;
}
.figure-md { border-radius: 6px; }
.figure-lg { border-radius: 6px; }

/* Product shots come off a white sweep, and a white rectangle on this cream
   ground reads as a sticker pasted onto the page. Multiplying the image into
   the ground turns its white to cream and leaves the product itself dark, so
   the tortillas sit directly on the page with no visible box.

   Only for photographs actually shot on white. On a normal photograph this
   would darken the whole frame.

   The blend sits on the figure, not on the img inside it. That was forced by
   `.washed`: a filter creates a stacking context that isolates any blending
   inside it, so a mix-blend-mode on the child composited against the figure
   and did nothing visible. `.washed` is gone as of 3 Sep 2026 and either
   element would work now, but the blend is left where it is. Note the product
   shots multiply harder without the filter softening them first. */
.figure-on-white {
  background: none;
  mix-blend-mode: multiply;
}

/* Sizing only. Kept clear of `display` so it does not fight the placeholder
   rule below, which needs grid to stack its two lines. */
.figure > img,
.figure > .image-placeholder {
  width: 100%;
  height: 100%;
}

.figure > img {
  display: block;
  object-fit: cover;
}

/* Standing in for the seven photographs the client has not supplied yet.
   Delete this block, and the placeholder branch in Photo.astro, once every
   slot has a real image. */
.figure > .image-placeholder {
  display: grid;
  place-content: center;
  gap: 6px;
  padding: 24px;
  text-align: center;
  background: var(--color-accent-2-200);
  color: var(--color-accent-2-800);
}
.image-placeholder span {
  font-size: 13px;
  line-height: 18px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
}
.image-placeholder small {
  font-size: 12px;
  letter-spacing: 0.02em;
  opacity: 0.75;
  text-transform: none;
}

/* ── tags ──────────────────────────────────────────────────────────────── */

/* The system's .tag is an 11px micro-label; this design runs them larger. */
.tag-lg { font-size: 14px; padding: 6px 16px; }
.tag-chip { font-size: 15px; padding: 8px 18px; }

/* ── grids ─────────────────────────────────────────────────────────────── */


.cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 24px;
  padding: 0 0 64px;
}

.photos-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
  padding: 0 0 64px;
}

.details-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 28px 40px;
  padding: 0 0 56px;
}

/* ===========================================================================
   4. Header: logo, nav row, language pill, mobile menu
   =========================================================================== */

/* The header's ground is two layers under the content that crossfade:
     ::before is solid cream, shown at the top of the page; ::after is a
     top-to-bottom gradient from nearly solid to mostly clear, shown only
     while the home page's photograph is under the header, so the photo shows
     through it more the closer it gets to the bottom edge. Two layers because
     a gradient cannot be transitioned as a background; opacity can.

     Until 28 Sep 2026 the gradient came on at any scroll, on every page, and
     body text scrolling under the bottom edge showed through at about a third
     strength. Jason found it distracting. Now text only ever passes under the
     solid ground; see the script at the bottom of this file.

     The two percentages on ::after are the dial. Lower either to show more
     photograph at that edge.

     Deliberately translucency only, no backdrop-filter. A backdrop-filter on
     this element would turn it into the containing block for the phone menu,
     which is position:fixed inside it, and the panel would pin to the header
     instead of the viewport. */
  .site-header {
    position: sticky;
    top: 0;
    z-index: 20;
    background: transparent;
  }
  .site-header::before,
  .site-header::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    transition: opacity 0.4s ease;
  }
  .site-header::before {
    background: var(--color-bg);
    opacity: 1;
  }
  .site-header::after {
    background: linear-gradient(
      to bottom,
      color-mix(in srgb, var(--color-bg) 94%, transparent),
      color-mix(in srgb, var(--color-bg) 66%, transparent)
    );
    opacity: 0;
  }
  .site-header.is-over-photo::before { opacity: 0; }
  .site-header.is-over-photo::after  { opacity: 1; }

  /* The open phone menu is a solid panel; keep the bar behind it solid too,
     so nothing bleeds through above the links. */
  .site-header:has(.header-bar.is-open)::before { opacity: 1; }
  .site-header:has(.header-bar.is-open)::after  { opacity: 0; }

  /* One row: links, logo, links. Three columns with the outer two at 1fr pins
     the logo to the true centre of the header regardless of how much sits
     either side of it. */
  .header-bar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: clamp(16px, 2.5vw, 32px);
    /* Height comes from --header-h in design-system.css, not from padding,
       because the banner below subtracts the same token to fill the rest of
       the first screen. */
    height: var(--header-h);
    /* The header runs to a wider container than the page content below it
       (1320 against 1200), which is what pushes the two link groups out away
       from the logo. They no longer line up with the body copy, and that is
       fine here: a full-screen photograph sits between the header and the
       first line of text, so the two edges are never read against each
       other. */
    padding-inline: max(
      clamp(20px, 5vw, 72px),
      calc((100% - 1320px) / 2 + clamp(20px, 5vw, 72px))
    );
  }

  .hb-logo {
    grid-column: 2;
    grid-row: 1;
    display: block;
    line-height: 0;
    border-radius: var(--radius-sm);
  }

  .hb-logo img {
    display: block;
    /* The mark is ~2.4:1, so height drives it and width follows: at 120px tall
       it is ~288px wide, which is why this is capped well below the header
       height rather than filling it. */
    height: clamp(72px, 8vw, 104px);
    width: auto;
  }

  /* The wrapper exists only so the two link groups can become one full-screen
     panel on mobile. On desktop it disappears and its children go straight
     back to being grid items. */
  .hb-menu { display: contents; }

  .hb-side {
    grid-row: 1;
    display: flex;
    align-items: center;
    gap: clamp(14px, 1.9vw, 26px);
    min-width: 0;
  }
  .hb-start { grid-column: 1; justify-self: start; }
  .hb-end { grid-column: 3; justify-self: end; }

  .hb-nav {
    display: flex;
    align-items: center;
    gap: clamp(14px, 2.2vw, 32px);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .hb-nav a {
    display: block;
    white-space: nowrap;
    text-decoration: none;
    color: inherit;
    font-size: 15px;
    padding: 4px 0;
  }
  .hb-nav a:hover,
  .hb-nav a[aria-current='page'] { color: var(--color-accent-700); }

  /* — language switch — */
  .lang-switch {
    border: 1px solid var(--color-divider);
    white-space: nowrap;
  }

  .lang-opt {
    border: 0;
    border-radius: 999px;
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.04em;
    line-height: 1;
    padding: 5px 11px;
    text-decoration: none;
    background: transparent;
    color: var(--color-text);
  }
  .lang-opt:hover { background: color-mix(in srgb, var(--color-text) 8%, transparent); }
  /* Deep ramp step, matching .btn-primary: the base accent is 3.03:1 here. */
  .lang-opt.is-active { background: var(--color-accent-700); color: var(--color-bg); }
  .lang-opt.is-active:hover { background: var(--color-accent-700); }

  /* Plain text, no button. On a narrow screen this is the first thing read
     left to right, so position gives it all the prominence it needs; a pill
     around it only competed with the logo. Padding stays generous enough to
     remain an easy tap target. */
  .hb-phone,
  .hb-phone-compact {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
    padding: 10px 2px;
    color: var(--color-text);
  }
  .hb-phone:hover,
  .hb-phone-compact:hover { color: var(--color-accent-700); }

  /* — collapsed state — */
  .hb-phone-compact,
  .hb-toggle { display: none; }

  .hb-toggle {
    width: 42px;
    height: 42px;
    padding: 0;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--color-divider);
    border-radius: 999px;
    cursor: pointer;
    color: var(--color-text);
  }
  .hb-toggle:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }

  .hb-toggle-bars { display: grid; gap: 4px; width: 18px; }
  .hb-toggle-bars span {
    display: block;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
  }

  /* Five nav items either side of a logo, plus social, language and a phone
     number, need real width. Below this the header collapses to logo + phone +
     menu button, and the links open as a full-screen panel.

     Without JavaScript the panel is not fixed and simply sits under the logo,
     so the navigation still works. */
  @media (max-width: 1080px) {
    /* Three columns with equal-width outer tracks keeps the logo dead centre
       here too, the same way it works on desktop. The phone sits left and the
       menu button right, so the two flanks balance and the button stays in the
       corner where it also becomes the close X for the panel. */
    .header-bar {
      display: grid;
      grid-template-columns: 1fr auto 1fr;
      align-items: center;
      column-gap: 10px;
      height: var(--header-h);
    }

    .hb-logo {
      grid-column: 2;
      justify-self: center;
    }
    .hb-logo img { height: 52px; }

    .hb-phone-compact {
      grid-column: 1;
      justify-self: start;
      display: inline-flex;
    }
    .hb-toggle {
      grid-column: 3;
      justify-self: end;
      display: inline-flex;
    }

    /* The panel. Covers the viewport and centres the links on both axes.
       z-index sits below the button so the button stays tappable on top of it
       and doubles as the close control. */
    html.js .hb-menu {
      display: none;
      position: fixed;
      inset: 0;
      z-index: 1;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 0;
      padding: 88px 24px 40px;
      background: var(--color-bg);
      overflow-y: auto;
      overscroll-behavior: contain;
    }
    html.js .header-bar.is-open .hb-menu { display: flex; }

    /* Dissolve the two groups inside the panel so all five links, the social
       icons, the language pill and the phone button become siblings and can be
       ordered freely. Without this the social icons land between "Wholesale"
       and "Our Story" and cut the link list in half. */
    html.js .header-bar.is-open .hb-side { display: contents; }

    .hb-nav { order: 1; }
    .hb-menu .social { order: 2; margin-top: 30px; }
    .hb-menu .lang-toggle { order: 3; margin-top: 24px; }
    .hb-menu .hb-phone { order: 4; margin-top: 24px; }

    /* Links lead: large, centred, generously spaced. */
    .hb-nav {
      flex-direction: column;
      align-items: center;
      gap: 2px;
    }
    .hb-nav a {
      font-size: clamp(28px, 8vw, 40px);
      line-height: 1.25;
      font-family: var(--font-heading);
      font-weight: var(--font-heading-weight);
      letter-spacing: -0.015em;
      padding: 8px 12px;
      text-align: center;
    }

    /* The phone reappears inside the panel at full size; the compact one in
       the top row is hidden while the panel is open so they do not stack. */
    .hb-phone { font-size: 15px; padding: 12px 26px; }
    .header-bar.is-open .hb-phone-compact { visibility: hidden; }

    /* The button rides above the panel and becomes the close control. */
    .hb-toggle {
      position: relative;
      z-index: 2;
    }
  }

  /* Three bars fold into an X. The bars are 2px tall with a 4px gap, so the
     outer two travel 6px to meet in the middle. */
  .hb-toggle-bars span { transition: transform 180ms ease, opacity 120ms ease; }
  .header-bar.is-open .hb-toggle-bars span:nth-child(1) {
    transform: translateY(6px) rotate(45deg);
  }
  .header-bar.is-open .hb-toggle-bars span:nth-child(2) { opacity: 0; }
  .header-bar.is-open .hb-toggle-bars span:nth-child(3) {
    transform: translateY(-6px) rotate(-45deg);
  }

  /* Stops the page scrolling behind the open panel. */
  html.menu-open,
  html.menu-open body { overflow: hidden; }

  /* On the narrowest handsets the phone button is wider than the menu button,
     so the equal-width outer tracks cannot balance and the logo drifts right.
     Tightening the button and the toggle brings the two flanks back level. */
  @media (max-width: 400px) {
    .hb-logo img { height: 38px; }
    .hb-phone-compact {
      font-size: 13px;
      padding: 10px 0;
    }
    .hb-toggle { width: 38px; height: 38px; }
    .header-bar { column-gap: 6px; }
  }

/* ===========================================================================
   5. Social links
   =========================================================================== */

.social {
    display: flex;
    align-items: center;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .social-link {
    display: grid;
    place-content: center;
    width: 34px;
    height: 34px;
    border-radius: 999px;
    color: var(--color-text);
  }
  .social-link:hover {
    background: color-mix(in srgb, var(--color-accent) 12%, transparent);
    color: var(--color-accent-700);
  }

  .social-link svg {
    width: 17px;
    height: 17px;
    display: block;
  }

  /* Yelp as a word until the official mark is dropped in. Sized to sit on the
     same optical line as the two glyphs beside it. */
  .social-link-word {
    width: auto;
    padding-inline: 9px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1;
    text-decoration: none;
  }

/* ===========================================================================
   6. Banner photograph and the name across it
   =========================================================================== */

.header-banner {
    position: relative;
    width: 100%;
    background: var(--color-surface);
    overflow: hidden;

    /* PHONE: the first screen, less the header, less 250px so the kicker and
       headline below show without scrolling. Until 28 Sep 2026 it filled the
       whole first screen and the headline started ~990px down on a 390 x 844,
       under a slideshow with no words on it. 250px is what the home hero
       needs above its body copy: 88px of top padding (HomeSections.astro), up
       to three kicker lines, and a two-line Spanish headline. Change that
       padding and this changes with it. Still a photograph, not a letterbox:
       526px tall on a 390 x 844, and it shows 42% of each frame's width
       instead of 28%. svh rather than vh so the browser's address bar does
       not push the bottom of the image off-screen.

       Nothing is set over the photographs. A wordmark ran across the old
       single hero once and was pulled for repeating the logo directly above;
       a headline was tried on 24 Aug 2026 and pulled too. The H1 sits directly
       below and does the talking. `bannerLine` is still in copy.ts if this is
       ever reversed. */
    height: calc(100vh - var(--header-h) - 250px);
    height: calc(100svh - var(--header-h) - 250px);
    min-height: 240px;
  }

  /* DESKTOP: 16:9, which is now the shape of the source files, so the whole
     frame shows at every width with no crop. The earlier 4:3 hero was cropped
     to this box and the ratio was chosen as the best compromise; with 16:9
     sources it is simply the photograph. */
  @media (min-width: 761px) {
    .header-banner {
      height: auto;
      aspect-ratio: 16 / 9;
    }
  }

  .hb-slides {
    position: absolute;
    inset: 0;
  }

  /* Every slide fills the box and sits on top of the last; only .is-active is
     visible. Positioned rather than sized with height:100% because on desktop
     the box gets its height from aspect-ratio with height:auto, and a
     percentage height cannot resolve against that. */
  .header-banner img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 40%;
    opacity: 0;
    transition: opacity 1.2s ease-in-out;
  }
  .header-banner img.is-active {
    opacity: 1;
  }

  /* Vertical photos are composed centred, so they sit centred. The 40% above
     suits the wide frames. Must match PORTRAIT in the frontmatter. */
  @media (max-width: 760px) and (max-aspect-ratio: 2/3) {
    .header-banner img { object-position: 50% 50%; }
  }

  @media (prefers-reduced-motion: reduce) {
    .header-banner img { transition: none; }
  }

/* ===========================================================================
   7. Home: hero, stat circles, product cards
   =========================================================================== */

.hero {
    padding: 88px 0 64px;
  }

  .hero-kicker { margin-bottom: 20px; }

  .hero-title {
    font-size: clamp(38px, 5.4vw, 72px);
    line-height: 1.08;
    margin: 0 0 24px;
    margin-left: -0.028em;
    max-width: 17ch;
  }

  .hero-body {
    font-size: 18px;
    line-height: 30px;
    max-width: 58ch;
    margin: 0 0 28px;
  }


  /* — product cards —
     Not cards any more. A rule across the top and the type doing the work,
     rather than two tinted lozenges sitting next to two tinted lozenges. */
  .product-card {
    background: none;
    border-radius: 0;
    border-top: 1px solid var(--color-divider);
    padding: 22px 0 0;
  }

  .product-card-title {
    font-size: clamp(28px, 3.4vw, 44px);
    line-height: 1.06;
    letter-spacing: -0.025em;
    margin: 8px 0 12px;
  }

  .product-card-body {
    font-size: 16px;
    line-height: 27px;
    margin: 0 0 18px;
  }

  .product-card-link {
    font-weight: 600;
    font-size: 15px;
    text-decoration: none;
  }
  .product-card-link:hover { text-decoration: underline; }

/* ===========================================================================
   8. Products
   =========================================================================== */

.product-rows {
    display: grid;
    gap: 32px;
  }

  .product-row {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 32px clamp(24px, 4vw, 64px);
    align-items: center;
  }

  .product-title {
    font-size: clamp(27px, 3.2vw, 38px);
    line-height: 1.14;
    margin: 16px 0;
  }

  .product-body {
    font-size: 17px;
    line-height: 29px;
    max-width: 50ch;
    margin: 0 0 14px;
  }


  .product-title a {
    color: inherit;
    text-decoration: none;
  }
  .product-title a:hover { color: var(--color-accent-700); }

  .row-schedule {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 12px;
    margin: 0 0 4px;
    font-size: 16px;
    line-height: 26px;
    max-width: 50ch;
    color: color-mix(in srgb, var(--color-text) 78%, transparent);
  }

  .row-schedule-label {
    font-size: 13px;
    line-height: 18px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--color-accent-700);
  }

  .row-link {
    display: flex;
    align-items: baseline;
    gap: 14px;
    flex-wrap: wrap;
    margin: 16px 0 0;
    font-size: 16px;
  }
  .row-link > a {
    font-weight: 600;
    text-decoration: none;
  }
  .row-link > a:hover { text-decoration: underline; }

  .row-count { font-size: 15px; }

  .row-photo { display: block; }


  /* The 5fr/7fr split stops working once the image column drops under about
     240px; below that the row stacks, photo first. */
  @media (max-width: 760px) {
    .product-row { grid-template-columns: minmax(0, 1fr); }
  }

/* ===========================================================================
   9. Corn and flour: the size run and the families
   =========================================================================== */

.back-link {
    color: inherit;
    text-decoration: none;
  }
  .back-link:hover { text-decoration: underline; }

  .cat-row {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 32px clamp(24px, 4vw, 64px);
    align-items: center;
  }

  /* Flour has no hero photograph, so the blurb and the schedule run on their
     own rather than sitting in a 7fr column beside an empty 5fr one. */
  .cat-row-solo {
    grid-template-columns: minmax(0, 1fr);
  }

  .cat-blurb {
    font-size: 17px;
    line-height: 29px;
    max-width: 50ch;
    margin: 0;
    color: color-mix(in srgb, var(--color-text) 78%, transparent);
  }

  /* A labelled block on the ground colour, not a tinted pill. The rule does
     the separating that a background fill used to. */
  .cat-schedule {
    display: block;
    margin: 24px 0 0;
    padding: 16px 0 0;
    border-top: 1px solid var(--color-divider);
    max-width: 50ch;
  }

  .cat-schedule-label {
    display: block;
    font-size: 12px;
    line-height: 16px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--color-accent-700);
    margin-bottom: 4px;
  }

  .cat-schedule-value {
    display: block;
    font-size: 17px;
    line-height: 27px;
  }

  .list-title {
    font-size: clamp(24px, 2.6vw, 32px);
    line-height: 1.18;
    margin: 0 0 10px;
  }

  .list-intro {
    font-size: 16px;
    line-height: 28px;
    max-width: 56ch;
    margin: 0 0 36px;
  }

  /* ── flour: the size run ────────────────────────────────────────────────
     Each cell is the tortilla itself at the size it is sold, with the size
     and the pack set over the bottom left of the frame. The grid used to be
     a wall of display numerals; showing the product says the same thing and
     shows what the buyer actually receives.

     Sizes with no frame yet keep the numeral, so the grid stays complete
     while the rest of the photography arrives. */

  /* `stretch`, so every cell in a row is the same height, with the photograph
     pinned to the top and the label pushed to the bottom by margin-top:auto.

     `start` used to leave a short text-only cell's label floating level with
     the middle of its neighbour's photograph, where it read as that
     photograph's caption; two columns on a phone made it far worse than five
     on a desktop. `end` fixed the labels but then a two-line label pushed its
     own photograph out of line with the rest of the row. Stretching aligns
     both. */
  .size-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    align-items: stretch;
    gap: clamp(14px, 1.8vw, 24px);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .size-cell {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  /* The photograph is its own square. The caption used to sit over the bottom
     of it, which worked while the frames had white margin to spare; once the
     crops tightened, the type landed on the packaging graphics. It sits
     underneath now and nothing overlaps. */
  .size-photo {
    display: block;
    position: relative;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: 6px;
  }

  .size-cell img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .size-label {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 2px 8px;
    margin-top: auto;
  }

  /* CORN LABELS: one plane across every row.

     The name block is always two lines tall, with the text sitting on the
     lower line, and the pack line always sits under it. So a one-line name
     ("Cal"), a two-line name ("Regular, medium pack"), a cell with a photo
     and one without all end up the same height, and because every label is
     pinned to the bottom of a stretched cell, the rules, the names, and the
     packs each line up straight across the row. The cost is an empty line
     above a short name; that reads as padding, and it is the price of the
     alignment. */
  .size-label-stack {
    display: grid;
    grid-template-rows: auto auto;
    align-content: end;
    gap: 4px;
  }
  .size-label-stack .size-name {
    display: flex;
    align-items: flex-end;
    min-height: 2.2em;
  }
  .size-meta {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 2px 8px;
    min-height: 18px;
  }

  /* A qualifier chip beside the pack, the sage of the "Made daily" tag so it
     reads as information rather than as a NEEDS marker. */
  .size-tag {
    display: inline-block;
    padding: 0 8px;
    border-radius: var(--radius-sm);
    background: var(--color-accent-2-100);
    color: var(--color-accent-2-800);
    font-size: 11px;
    line-height: 18px;
    letter-spacing: 0.04em;
    font-weight: 600;
    text-transform: uppercase;
  }

  /* Matches .faq-todo, so every unanswered thing on the site looks the same. */
  /* Both chips are exactly one pack line tall (18px), so a cell carrying a
     chip sits on the same plane as one carrying a pack. */
  .size-todo {
    display: inline-block;
    padding: 0 8px;
    border-radius: var(--radius-sm);
    background: var(--color-accent-200);
    color: var(--color-accent-800);
    font-size: 11px;
    line-height: 18px;
    letter-spacing: 0.04em;
    font-weight: 600;
  }

  /* Cells with no photograph yet: the numeral carries the cell instead, and
     the rule across the top separates it the way the old grid did. */
  /* No photograph yet: a rule and the label, nothing more. It does NOT
     reserve a photo-sized box, because a grid of empty squares reads as
     broken rather than as pending. The cell grows when an image arrives. */
  /* The rule rides on the label, not on the cell. On the cell it would pin
     itself to the top of a stretched cell and leave the label stranded far
     below it. */
  .size-cell:not(.has-photo) .size-label {
    border-top: 1px solid var(--color-divider);
    padding: 14px 0 0;
  }
  .size-cell:not(.has-photo) .size-num {
    font-size: clamp(46px, 5.4vw, 82px);
  }

  /* Rows with no size number, currently torta bread, carry their name at the
     same weight the numerals have so the cell still reads as a product. */
  .size-name {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: clamp(15px, 1.5vw, 18px);
    line-height: 1.1;
    letter-spacing: -0.015em;
  }

  .size-num {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: clamp(20px, 2vw, 25px);
    line-height: 1;
    letter-spacing: -0.03em;
    /* Lining, tabular figures so every numeral is the same width and the
       column of numbers reads as one run. */
    font-variant-numeric: lining-nums tabular-nums;
  }

  /* The hash is grammar, not content: smaller, set back, and out of the
     accessibility tree so a screen reader says "16" and not "hash 16". */
  .size-hash {
    font-size: 0.55em;
    vertical-align: 0.35em;
    margin-right: 0.06em;
    color: var(--color-accent);
    letter-spacing: 0;
  }

  .size-pack {
    font-size: 14px;
    line-height: 18px;
    font-weight: 700;
    color: var(--color-text);
    font-variant-numeric: lining-nums tabular-nums;
  }

  .size-note {
    font-size: 11px;
    line-height: 16px;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--color-accent-700);
  }

  .size-other {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 14px;
    margin: 26px 0 0;
    padding: 18px 0 0;
    border-top: 1px solid var(--color-divider);
    font-size: 17px;
  }

  .size-other-label {
    font-size: 12px;
    line-height: 16px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--color-accent-700);
  }

  /* ── corn: the families ─────────────────────────────────────────────────
     Family name in the left column at display size, its variants listed
     against it on the right. Corn has no numbering to lead on, so the family
     names carry the scale instead. */

  .fam-set {
    display: grid;
    gap: 0;
  }

  .fam {
    padding: 26px 0 28px;
    border-top: 1px solid var(--color-divider);
  }
  .fam .size-grid { margin-top: 18px; }

  .fam-title {
    font-size: clamp(22px, 2.4vw, 30px);
    line-height: 1.06;
    letter-spacing: -0.025em;
    margin: 0;
    text-wrap: balance;
  }

  .fam-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .fam-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 7px 0;
    font-size: 16px;
    line-height: 25px;
  }
  .fam-row + .fam-row {
    border-top: 1px solid color-mix(in srgb, var(--color-text) 7%, transparent);
  }

  .fam-variant { min-width: 0; }

  .fam-pack {
    white-space: nowrap;
    color: color-mix(in srgb, var(--color-text) 65%, transparent);
    font-variant-numeric: lining-nums tabular-nums;
  }

  .cross-link {
    margin: 0;
    font-size: 16px;
  }
  .cross-link a {
    font-weight: 600;
    text-decoration: none;
  }
  .cross-link a:hover { text-decoration: underline; }


  @media (max-width: 760px) {
    .cat-row { grid-template-columns: minmax(0, 1fr); }
    .fam { grid-template-columns: minmax(0, 1fr); }
    .fam-title { margin-bottom: 6px; }
  }

/* ===========================================================================
   10. Wholesale: numbered steps
   =========================================================================== */

.wholesale-intro { max-width: 58ch; }

  .steps {
    display: grid;
    gap: 36px;
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: step;
  }

  .step {
    display: grid;
    grid-template-columns: 76px minmax(0, 340px) minmax(0, 1fr);
    gap: 12px 40px;
    align-items: start;
  }

  /* Was a 64px filled disc. The circle went; the numeral stays, since the
     steps still need numbering. Set large and in the accent so it reads as a
     step marker rather than as body copy. */
  .step-n {
    display: block;
    font-family: var(--font-heading);
    font-weight: var(--font-heading-weight);
    font-size: 40px;
    line-height: 1;
    color: var(--color-accent);
    font-variant-numeric: tabular-nums;
  }

  .step-title {
    font-size: 26px;
    line-height: 32px;
    margin: 12px 0 0;
  }

  .step-body {
    font-size: 16px;
    line-height: 28px;
    margin: 12px 0 0;
    max-width: 52ch;
    color: color-mix(in srgb, var(--color-text) 78%, transparent);
  }

  /* Three columns need roughly 900px before the body column starts crushing.
     Below that the numeral sits beside the title and the body drops under. */
  @media (max-width: 900px) {
    .step {
      grid-template-columns: 76px minmax(0, 1fr);
      gap: 0 24px;
    }
    .step-title { margin-top: 14px; }
    .step-body { grid-column: 2; }
  }

  @media (max-width: 480px) {
    .step {
      grid-template-columns: minmax(0, 1fr);
      gap: 0;
    }
    .step-title { margin-top: 16px; }
    .step-body { grid-column: 1; }
  }

/* ===========================================================================
   11. Pricing request form
   =========================================================================== */

.form-title {
    font-size: clamp(25px, 2.8vw, 34px);
    line-height: 1.18;
    margin: 0 0 14px;
  }

  .form-lede {
    font-size: 16px;
    line-height: 28px;
    max-width: 54ch;
    margin: 0 0 32px;
    color: color-mix(in srgb, var(--color-text) 78%, transparent);
  }

  .fields-grid {
    display: grid;
    /* 280px, not 240px, since 28 Sep 2026: at the full 760px width that fits
       two columns, so the four fields sit two by two. At 240px it fit three,
       and City sat alone on a second row. Below ~580px, one column. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
    gap: 20px;
    max-width: 760px;
  }

  .field-wide {
    display: block;
    max-width: 760px;
    margin-top: 20px;
  }

  .req {
    color: var(--color-accent-700);
    margin-left: 2px;
  }

  /* `.input` is a pill sized for one line. A multi-line field needs a real
     corner radius, room to grow, and the body font it does not inherit. */
  .textarea {
    height: auto;
    min-height: 112px;
    padding-block: 12px;
    border-radius: var(--radius-md, 12px);
    font: inherit;
    line-height: 24px;
    resize: vertical;
  }

  .field-error {
    margin: 6px 0 0;
    padding-inline: 14px;
    font-size: 13px;
    line-height: 18px;
    color: var(--color-accent-800);
  }

  /* The system's .input focus ring is the accent; an invalid field needs to
     read as wrong without relying on colour alone, hence the message. */
  .input[aria-invalid='true'] {
    border-color: var(--color-accent-700);
    background: color-mix(in srgb, var(--color-accent-200) 55%, var(--color-surface));
  }

  .form-error {
    max-width: 760px;
    margin: 24px 0 0;
    font-size: 15px;
    line-height: 24px;
    color: var(--color-accent-800);
  }
  .form-error a { color: inherit; }

  .form-actions { margin-top: 28px; }

  .form-privacy {
    font-size: 14px;
    line-height: 22px;
    margin: 14px 0 0;
    color: color-mix(in srgb, var(--color-text) 78%, transparent);
  }

  /* Off-screen rather than display:none, so bots that skip hidden inputs
     still fill it. Never tabbable, never announced. */
  .hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
  }

  .success-title {
    font-size: clamp(25px, 2.8vw, 34px);
    line-height: 1.18;
    margin: 0 0 12px;
  }

  .success-body {
    font-size: 16px;
    line-height: 28px;
    max-width: 52ch;
    margin: 0;
    color: color-mix(in srgb, var(--color-text) 78%, transparent);
  }

  .form-success:focus-visible { outline: none; }

/* ===========================================================================
   12. Our Story
   =========================================================================== */

.story-hero {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 40px clamp(24px, 5vw, 88px);
    align-items: center;
    padding: 72px 0 56px;
  }

  .story-title {
    font-size: clamp(34px, 4.4vw, 56px);
    line-height: 1.1;
    margin: 0 0 24px;
    margin-left: -0.028em;
    max-width: 18ch;
  }

  .story-p {
    font-size: 18px;
    line-height: 31px;
    max-width: 52ch;
    margin: 0 0 18px;
  }
  .story-p-last { margin-bottom: 0; }

  .story-photo {
    width: min(420px, 100%);
    justify-self: end;
  }

  .states-kicker { margin-bottom: 20px; }

  .states-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    list-style: none;
    margin: 0;
    padding: 0;
  }


  @media (max-width: 860px) {
    .story-hero { grid-template-columns: minmax(0, 1fr); }
    .story-photo { justify-self: start; }
  }

/* ===========================================================================
   13. FAQ
   =========================================================================== */

.faq-section { padding-bottom: 44px; }

  .faq-section-title {
    font-size: clamp(24px, 2.6vw, 32px);
    line-height: 1.18;
    margin: 0 0 24px;
  }

  .faq-list {
    display: grid;
    gap: 28px;
    margin: 0;
    max-width: 68ch;
  }

  .faq-item {
    display: grid;
    gap: 8px;
  }

  .faq-q {
    font-family: var(--font-heading);
    font-weight: var(--font-heading-weight);
    font-size: 19px;
    line-height: 1.32;
    letter-spacing: -0.015em;
  }

  .faq-a {
    margin: 0;
    font-size: 16px;
    line-height: 28px;
    max-width: 62ch;
    color: color-mix(in srgb, var(--color-text) 78%, transparent);
  }

  /* Deliberately loud. This is scaffolding, not a design element, and it
     should be impossible to mistake for finished copy. */
  .faq-todo {
    display: inline-block;
    padding: 4px 12px;
    border-radius: var(--radius-sm);
    background: var(--color-accent-200);
    color: var(--color-accent-800);
    font-size: 14px;
    line-height: 22px;
  }
  .faq-todo strong { letter-spacing: 0.06em; }

  .faq-cta-title {
    font-size: clamp(25px, 2.8vw, 34px);
    line-height: 1.18;
    margin: 0 0 12px;
  }

/* ===========================================================================
   14. Footer
   =========================================================================== */

.site-footer {
    font-size: 15px;
    line-height: 26px;
    color: color-mix(in srgb, var(--color-text) 70%, transparent);
  }

  .footer-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 28px 40px;
    padding-block: 8px 72px;
  }

  .footer-brand {
    font-family: var(--font-heading);
    font-weight: var(--font-heading-weight);
    font-size: 20px;
    line-height: 26px;
    margin: 0 0 8px;
    color: var(--color-text);
  }

  .footer-tag { margin: 0; }

  .footer-address {
    font-style: normal;
    margin: 0;
  }

  @media (max-width: 560px) {
    .footer-grid { grid-template-columns: minmax(0, 1fr); }
  }
