/* =============================================================
   Ciclo — Landing-specific styles
   Section composition: Nav · Hero · Arc · Assistant · Included · Personal (attendance) · Audience · DemoCTA · FAQ · CTA · Footer.
   Loaded after tokens.css → base.css → components.css.
   ============================================================= */

/* ---------- Nav — bg follows the current section ---------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  backdrop-filter: blur(14px) saturate(1.6);
  -webkit-backdrop-filter: blur(14px) saturate(1.6);
  border-bottom: 1px solid var(--hairline);
  background: rgba(248, 248, 248, 0.82);                /* default = clean white */
  transition: background 320ms var(--ease-out),
              color 320ms var(--ease-out),
              border-color 320ms var(--ease-out);
}
.nav-bg-cream { background: rgba(248, 248, 248, 0.82); }
.nav-bg-off   { background: rgba(245, 245, 245, 0.85); }
.nav-bg-tint  { background: rgba(230, 244, 244, 0.85); }
.nav-bg-navy {
  background: rgba(14, 22, 40, 0.85);
  border-bottom-color: rgba(255, 255, 255, 0.10);
}
.nav-bg-navy .nav-logo,
.nav-bg-navy .nav-logo .accent,
.nav-bg-navy .nav-links a {
  color: #FFFFFF;
  transition: color 320ms var(--ease-out);
}
.nav-bg-navy .nav-logo .accent { color: var(--brand-soft); }
.nav-bg-navy .nav-links a:hover { color: var(--accent-soft); }
.nav-bg-navy .btn-ghost {
  color: #FFFFFF;
  border-color: rgba(255, 255, 255, 0.20);
  background: transparent;
}
.nav-bg-navy .btn-ghost:hover { border-color: rgba(255, 255, 255, 0.55); }
.nav-bg-navy .btn-ink {
  background: #FFFFFF;
  color: var(--ink);
  border-color: #FFFFFF;
}
.nav-bg-navy .btn-ink:hover { background: rgba(255, 255, 255, 0.85); }

.nav-row {
  display: flex; align-items: center; justify-content: space-between;
  height: 64px;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.nav-logo {
  font-family: var(--font-body); font-weight: 600;
  font-size: 19px; letter-spacing: -0.03em; color: var(--ink);
  display: inline-flex; align-items: center; gap: 9px;
}
.nav-logo .accent { color: var(--brand); }
.logo-ic {
  width: 27px; height: 27px; border-radius: 8px;
  background: var(--brand); color: #FFFFFF;
  display: inline-grid; place-items: center;
  flex-shrink: 0;
}
.logo-ic svg { width: 15px; height: 15px; }

.nav-links { display: none; gap: 28px; align-items: center; }
@media (min-width: 880px) { .nav-links { display: inline-flex; } }
.nav-links a { font-size: 14px; color: var(--ink); position: relative; }
.nav-links a::after {
  content: '';
  position: absolute; left: 0; bottom: -5px;
  width: 100%; height: 1.5px; border-radius: 1px;
  background: var(--brand);
  transform: scaleX(0); transform-origin: left;
  transition: transform 220ms var(--ease-out);
}
.nav-links a:hover { color: var(--brand-deep); }
.nav-links a:hover::after { transform: scaleX(1); }

.nav-cta { display: inline-flex; align-items: center; gap: 8px; }
.nav-cta .lang-toggle { display: none; }
@media (min-width: 768px) { .nav-cta .lang-toggle { display: inline-flex; } }

/* ---------- Section jump — mobile-only in-page section nav ----------
   Below 880px, .nav-links (the header's link row, above) is `display:
   none` with nothing standing in for it — small screens had a logo,
   "Acceder" and the demo CTA and no way to reach any section but the next
   one down. Deliberately NOT a JS hamburger drawer: that would add open/
   close state, focus management and an overlay to a page that has none of
   that machinery today, in a repo with no test framework to catch a
   regression in it. Instead: a plain, horizontally-scrollable row of real
   anchor links (no JS at all) that sits in normal document flow right
   after the hero — never inside the hero itself — so it can't push the
   hero further down the fold; it only enters the viewport once the
   visitor scrolls to it. Deliberately NOT sticky/pinned: stacking it under
   the already-sticky header would double the offset anchor scrolls need
   to clear, and every section's `scroll-margin-top: 65px` (below) assumes
   only the header is pinned — a second sticky bar would silently break
   that math the moment both were onscreen together. A static row avoids
   the bug outright. overflow-x is scoped to this element alone, so it can
   scroll horizontally without ever causing the page itself to. */
.section-jump {
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  white-space: nowrap;
  padding: 10px var(--gutter);
  background: var(--paper-cream);
  border-bottom: 1px solid var(--hairline);
}
@media (min-width: 880px) { .section-jump { display: none; } }
.section-jump a {
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 16px;
  margin-right: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--body);
  background: var(--bright-white);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  white-space: nowrap;
}
.section-jump a:last-child { margin-right: 0; }
.section-jump a:hover { color: var(--brand-deep); border-color: var(--brand); }

/* Anchor-scroll offset — every section the nav links to (or that
   carries its own id) needs to clear the sticky nav, or its heading
   lands underneath the bar. Nav row is 64px + its 1px border. */
.section[id] { scroll-margin-top: 65px; }

/* ---------- Section primitives ---------- */

.section {
  padding-top: var(--section-y);
  padding-bottom: var(--section-y);
  position: relative;
}

.surface-cream-bg  { background: var(--paper-cream); }
.surface-tint-bg   { background: var(--pale-cobalt); }
.surface-white-bg  { background: var(--bright-white); }
/* The page's one deliberately inverted mid-page band (#asistente) — same
   --ink background the footer already uses. Background only, like its
   light siblings above; the on-dark text-color overrides live scoped to
   #asistente itself, further down this file. */
.surface-ink-bg    { background: var(--ink); }

/* Demoted #personal: roughly half of --section-y at every breakpoint, not
   tied to the --section-y custom property so the <768px query below
   (which redeclares --section-y: 40px for every other section) doesn't
   flatten this section back to the same height as its full-weight
   neighbors. */
.section--tight {
  padding-top: clamp(32px, 4vw, 56px);
  padding-bottom: clamp(32px, 4vw, 56px);
}

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ---------- Display headlines ---------- */

.h1 {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(48px, 6.5vw, 96px); line-height: 0.98;
  letter-spacing: -0.03em;
  color: var(--ink);
  max-width: 18ch;
  margin: 0;
}

.h2 {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(36px, 4.5vw, 64px); line-height: 1.0;
  letter-spacing: -0.03em;
  color: var(--ink);
  max-width: 22ch;
  margin: 0;
}

.h3 {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(24px, 2.4vw, 32px); line-height: 1.1;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: 0;
}

.lede {
  font-size: 18px;
  line-height: 1.55;
  color: var(--body);
  max-width: 56ch;
  margin: 24px 0 0;
}

/* ---------- Hero ---------- */

.hero {
  padding-top: clamp(48px, 6vw, 84px);
  padding-bottom: clamp(40px, 5vw, 72px);
  overflow-x: clip;
  position: relative;
}
.hero .container { position: relative; }
.hero-head { text-align: center; max-width: 880px; margin: 0 auto; }
.hero .h1 { font-size: clamp(34px, 5.6vw, 72px); line-height: 1.03; max-width: 16ch; margin: 26px auto 0; }
.hero .lede { margin-left: auto; margin-right: auto; }
.hero-actions { display: flex; gap: 12px; margin-top: 32px; flex-wrap: wrap; justify-content: center; }
.hero-trust { margin: 24px 0 0; font-size: 13px; color: var(--body-muted); }

/* Entrance — one orchestrated rise, staggered top to bottom */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
.hero-head .badge { animation: rise-in 640ms var(--ease-out) both; }
.hero .h1         { animation: rise-in 680ms var(--ease-out) 70ms both; }
.hero .lede       { animation: rise-in 680ms var(--ease-out) 150ms both; }
.hero-actions     { animation: rise-in 680ms var(--ease-out) 230ms both; }
.hero-trust       { animation: rise-in 680ms var(--ease-out) 310ms both; }

/* ---------- Hero conversation — Thread + the order it produced ----------
   Stacked at mobile (thread first, then the card it caused), side by
   side from 760px up — matching .compare's breakpoint rather than
   the nav's unrelated 768px, so this branch doesn't add a second, close-
   but-different breakpoint for the same "tablet and up" two-column
   pattern. Both panels are left-aligned regardless of .hero-head's
   centering above them. No entrance animation here by design — the
   rebuild removed motion from anything meant to read as a real, static
   artifact rather than a marketing flourish. */
.hero-convo {
  margin: clamp(40px, 5vw, 64px) auto 0;
  max-width: 1080px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
  text-align: left;
}
@media (min-width: 760px) {
  .hero-convo { grid-template-columns: 1fr 1fr; align-items: start; gap: 28px; }
}

.order-card {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
  background: var(--bright-white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: clamp(20px, 4vw, 28px);
}
.order-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--hairline-soft);
}
.order-card-folio {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: var(--tracking-mono);
  color: var(--body-muted);
}
.order-card-fields {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  margin: 0;
}
@media (min-width: 460px) {
  .order-card-fields { grid-template-columns: 1fr 1fr; }
}
/* Sentence case, body font, size-differentiated from the value beneath it
   — not the page's uppercase-mono micro-label (task: micro-label
   monopoly). The `dd` already carries the visual weight; the `dt` only
   needs to read smaller and quieter, which font-size + color do without
   forcing every field name into the same caps treatment as a dozen
   unrelated labels elsewhere on the page. */
.order-card-fields dt {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--body-muted);
  margin: 0;
}
.order-card-fields dd {
  font-size: 16px;
  font-weight: 500;
  color: var(--ink);
  margin: 4px 0 0;
}
.order-card-note {
  margin: 0;
  padding-top: 16px;
  border-top: 1px solid var(--hairline-soft);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--body-muted);
}

.badge {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 500; color: var(--body-muted);
  background: var(--bright-white); border: 1px solid var(--hairline);
  border-radius: 999px; padding: 6px 14px;
  box-shadow: 0 1px 2px rgba(11, 14, 20, 0.04);
}
.badge i { width: 6px; height: 6px; border-radius: 50%; background: var(--brand); box-shadow: 0 0 0 3px var(--brand-tint); }

/* ---------- Screens — the one real screenshot on the page ----------
   `.container-wide` (base.css, 1440px max) instead of the page's usual
   1200px `.container` — the whole point of this section is that the arc's
   ~570px media columns render a 1440-wide capture at ~0.40×, illegible;
   this section exists not to repeat that. The image itself is plain CSS
   (width:100%, height:auto) inside that wider box, so it scales down
   smoothly below 1440px and reaches its native 1:1 size at 1440px+
   viewports — the `width`/`height` attributes on the <img> (2880×1800,
   the file's real intrinsic size) only reserve the aspect ratio; they
   don't set the display size. */
.screens-head { max-width: 640px; }
.screens-figure {
  margin: clamp(32px, 5vw, 48px) 0 0;
}
.screens-img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-xl);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-lg);
  background: var(--off-white); /* visible while the lazy image loads in */
}
.screens-caption {
  margin: 12px 2px 0;
  font-size: 13px;
  color: var(--body-muted);
}

/* ---------- Order models — two pricing units, one per category ----------
   Two hairline-separated spec lists (the #incluye idiom: mono uppercase
   dt, 16px dd), not cards — no border, no shadow, no stripe. No shared
   "same order" label above them: the two columns are two different
   illustrative orders (per-kilo vs. per-garment), not one order shown
   twice, so the heading and sub carry the framing instead. Single column
   and full-width at mobile so a phone reads one model's four rows, then
   the other's, without a side-by-side squeeze; a vertical hairline
   divides the pair from 760px up, matching the breakpoint the old two-up
   block used. */

.compare {
  margin-top: 20px;
  display: grid;
  grid-template-columns: 1fr;
  border-top: 1px solid var(--hairline-soft);
}
@media (min-width: 760px) {
  .compare { grid-template-columns: 1fr 1fr; column-gap: 56px; }
}
.compare-model {
  padding: 32px 0;
  border-bottom: 1px solid var(--hairline-soft);
}
.compare-model:last-child { border-bottom: 0; }
@media (min-width: 760px) {
  .compare-model { border-bottom: 0; padding: 40px 0; }
  .compare-model:first-child { border-right: 1px solid var(--hairline-soft); padding-right: 56px; }
  .compare-model:last-child { padding-left: 56px; }
}
.compare-model-name {
  font-family: var(--font-display); font-weight: 500;
  font-size: 24px; line-height: 1.15; letter-spacing: -0.025em; color: var(--ink); margin: 0;
}
.compare-rows { margin: 20px 0 0; }
.compare-row {
  display: grid; grid-template-columns: 1fr; gap: 4px;
  padding: 14px 0;
  border-top: 1px solid var(--hairline-soft);
}
.compare-row:first-child { border-top: 0; }
/* Sentence case, body font — see order-card-fields dt's comment (task:
   micro-label monopoly). */
.compare-row dt {
  font-family: var(--font-body); font-size: 13px; font-weight: 500;
  color: var(--body-muted);
  margin: 0;
}
.compare-row dd {
  font-size: 16px; line-height: 1.5; color: var(--body); margin: 2px 0 0;
}
.compare-row--total dd {
  font-size: 22px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.compare-note {
  margin: 40px 0 0;
  padding-top: 24px;
  border-top: 1px solid var(--hairline-soft);
  max-width: 56ch;
  font-size: 16px; line-height: 1.6; color: var(--body-muted);
}

/* ---------- Arc — the four-part narrative (recibe → opera → entrega → retiene) ----------
   Two-column at desktop (text | screen), stacked at mobile with the screen
   always following its text. Alternation is done with `order` on
   .is-flipped .arc-text rather than duplicating markup; the mobile
   breakpoint resets that order explicitly so reading order stays
   text-then-screen on every part, flipped or not. */

.arc-part {
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
  align-items: center;
  padding: clamp(48px, 6vw, 96px) 0;
  border-bottom: 1px solid var(--hairline-soft);
}
.arc-part:first-child { padding-top: 0; }
.arc-part:last-child { padding-bottom: 0; border-bottom: 0; }

@media (min-width: 980px) {
  .arc-part { grid-template-columns: 1fr 1fr; gap: clamp(48px, 5vw, 96px); }
  .arc-part.is-flipped .arc-text { order: 2; }
  .arc-part.is-flipped .arc-screen { order: 1; }
}
/* Explicit reset — below the breakpoint every part reads text, then screen,
   flipped or not. Don't rely on the desktop rule simply not matching. */
@media (max-width: 979px) {
  .arc-part.is-flipped .arc-text { order: 0; }
  .arc-part.is-flipped .arc-screen { order: 0; }
}

.arc-num {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.12em;
  /* --brand-deep, not --brand: --brand as text on --paper-cream is 3.70:1
     (fails AA); --brand-deep is 5.95:1. See tokens.css brand comment. */
  color: var(--brand-deep); font-weight: 500;
}
.arc-name {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(34px, 3.6vw, 52px); line-height: 1.0;
  letter-spacing: -0.035em;
  color: var(--ink); margin: 10px 0 0;
}
.arc-body {
  margin-top: 18px;
  max-width: 52ch;
  color: var(--body); font-size: 16px; line-height: 1.6;
}
.arc-feats {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin: 28px 0 0; padding: 0; list-style: none;
}
/* Sentence case, body font — the pill shape still marks these as small
   tags, but the type inside them no longer speaks in the page's
   uppercase-mono voice (task: micro-label monopoly — this was one of the
   two highest-volume offenders, 19 li across the arc and #personal). */
.arc-feats li {
  font-family: var(--font-body); font-size: 13.5px; font-weight: 500;
  color: var(--brand-deep);
  background: var(--brand-tint);
  border: 1px solid rgba(0, 143, 146, 0.16);
  border-radius: 999px;
  padding: 6px 14px;
}

.arc-screen { min-width: 0; }

/* ---------- Driver route — the page's one portrait image ----------
   assets/screens/driver-route.webp is 1170×2532 — every other image on
   the page is landscape (2880×1800). The whole point of this section is
   that silhouette contrast, so the image is never stretched to fill a
   wide column: `.driver-media img` is width-capped and lets its own
   aspect ratio set the height. The media column is `auto`-sized (not a
   fr share) so it's exactly as wide as the capped image (up to 300px)
   rather than a fixed fraction of the row that leaves empty space beside
   a narrow portrait image at desktop (task: mobile scroll length —
   flagged as dead space even though the fix targets >=760px, not the
   mobile metric itself); the text column absorbs all the remaining
   width instead. Stacked text-then-image at mobile, matching the rest of
   the page's stacking order (Arc, #personal). */

.driver-row {
  margin-top: clamp(28px, 4vw, 40px);
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
  align-items: center;
}
@media (min-width: 760px) {
  .driver-row { grid-template-columns: 1fr auto; gap: 40px; }
}
.driver-media {
  min-width: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.driver-media img {
  width: 100%;
  max-width: clamp(220px, 42vw, 300px);
  height: auto;
  border-radius: var(--radius-xl);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-lg);
  background: var(--off-white);
}
.driver-caption {
  margin: 10px 0 0;
  max-width: 300px;
  text-align: center;
  font-size: 13px;
  color: var(--body-muted);
}

/* ---------- Shared arc-media chrome ----------
   The one surviving shell for a bordered, shadowed white card — used now
   only by .panel (ZoneMap). .panel-head/.panel-label are lighter-weight
   and reused across containers that AREN'T .panel too (.board's own
   title row, .stampcard's head), because the head/label typography is
   genuinely identical chrome even where the surrounding card shell is
   not — Board and StampCard deliberately do NOT use the bordered/shadowed
   .panel shell, so the arc's four media blocks stop sharing one
   silhouette. .chip is the same consolidation for the small status pills
   that used to be redeclared per panel (retain-card-chip, board-chip,
   fee-panel-chip) — one shape, colored by modifier, using only existing
   --chip-* token pairs (see Board's and StampCard's comments in
   landing.jsx for which modifier maps to which real product state). */

.panel {
  min-width: 0;
  background: var(--bright-white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: clamp(18px, 3.6vw, 24px);
}
.panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--hairline-soft);
}
.panel-label {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--body-muted);
}
.panel-note {
  margin: 16px 0 0; padding-top: 14px;
  border-top: 1px solid var(--hairline-soft);
  font-size: 16px; line-height: 1.5; color: var(--body-muted);
}

.chip {
  display: inline-block;
  flex-shrink: 0;
  font-family: var(--font-mono); font-size: 12px; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  border-radius: 999px; padding: 5px 12px; white-space: nowrap;
}
.chip--route { color: var(--chip-route-f); background: var(--chip-route-b); }
.chip--done  { color: var(--chip-done-f);  background: var(--chip-done-b); }
.chip--proc  { color: var(--chip-proc-f);  background: var(--chip-proc-b); }
/* .chip--pick — the hero OrderCard's "Por confirmar" stage chip. Previously
   its own bespoke `.order-card-chip` rule, byte-identical to `.chip` plus
   the info-blue token pair; folded into the shared `.chip` family instead
   (task: micro-label monopoly — one sanctioned chip component, not two
   near-duplicates) using the same `--chip-pick-*` tokens Board's lane
   accents already reference. */
.chip--pick  { color: var(--chip-pick-f);  background: var(--chip-pick-b); }

/* ---------- Board — arc part 02's visual (geometry: columns) ----------
   Parallel stage-lane columns, not a card of hairline rows: the board's
   real metaphor. .board-lanes scrolls horizontally WITHIN ITSELF at
   390px (three ~168px lanes don't fit a 350px content column) — the page
   itself never scrolls, only this strip does. No enclosing bordered
   .panel shell here on purpose — each lane carries its own light
   background instead of one big white card, so this part doesn't fall
   back into the same silhouette as ZoneMap's .panel. */

.board { display: flex; flex-direction: column; gap: 14px; }

.board-unconfirmed {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border: 1px dashed var(--hairline);
  border-radius: var(--radius);
  background: var(--chip-proc-b);
}
.board-unconfirmed-folio {
  font-family: var(--font-mono); font-size: 12px;
  letter-spacing: var(--tracking-mono);
  color: var(--body-muted);
}
.board-unconfirmed-customer {
  min-width: 0; flex: 1;
  font-size: 16px; font-weight: 500; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board-unconfirmed .chip { margin-left: auto; }

.board-lanes {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
  /* Keyboard scrollability (WCAG 2.1.1): tabindex="0" on the element (set
     in landing.jsx) makes this auto-overflow strip a focusable scroll
     container, which every evergreen browser scrolls with arrow/Page keys
     once focused — no JS needed. tabindex on role="list" is a valid ARIA
     combination (tabindex is a global attribute; it doesn't change the
     exposed role), and the element already carries its own aria-label.
     Visual continuation cue: classic scroll-shadow technique (two solid
     covers + two shadow gradients, "local" vs "scroll" background
     attachment) — the edge shadow only renders when there is unscrolled
     content in that direction and fades on its own as you reach the end,
     so it never lies about content that isn't actually there. The solid
     covers match --paper-cream, this strip's only real-world parent
     surface (the "how" section is .surface-cream-bg) — a static color
     match, not a change to the section itself. */
  background-image:
    linear-gradient(to right, var(--paper-cream) 30%, rgba(248, 248, 248, 0)),
    linear-gradient(to left, var(--paper-cream) 30%, rgba(248, 248, 248, 0)),
    linear-gradient(to right, rgba(29, 41, 61, 0.16), rgba(29, 41, 61, 0)),
    linear-gradient(to left, rgba(29, 41, 61, 0.16), rgba(29, 41, 61, 0));
  background-position: left, right, left, right;
  background-repeat: no-repeat;
  background-size: 24px 100%, 24px 100%, 10px 100%, 10px 100%;
  background-attachment: local, local, scroll, scroll;
}
.board-lanes:focus-visible {
  /* --brand-deep, not --brand: this is a non-text UI indicator (WCAG
     1.4.11, >=3:1), but --brand-deep is already the page's text-safe
     brand variant and reads clearly against the cream section (5.95:1). */
  outline: 2px solid var(--brand-deep);
  outline-offset: 3px;
  border-radius: 4px;
}
.board-lane {
  flex: 0 0 168px;
  min-width: 168px;
  background: var(--off-white);
  border-radius: var(--radius);
  border-top: 3px solid var(--hairline);
  padding: 12px;
}
.board-lane--pickup     { border-top-color: var(--chip-new-f); }
.board-lane--processing { border-top-color: var(--chip-pick-f); }
.board-lane--delivery   { border-top-color: var(--chip-done-f); }
.board-lane-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-bottom: 10px;
}
/* Sentence case, body font, bolder weight — reads as a small column
   header rather than the page's uppercase-mono micro-label (task:
   micro-label monopoly). */
.board-lane-name {
  font-family: var(--font-body); font-size: 13.5px; font-weight: 600;
  color: var(--ink);
}
.board-lane-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px;
  background: var(--bright-white);
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  color: var(--body-muted);
}
.board-lane-orders { display: flex; flex-direction: column; gap: 8px; }
.board-order {
  background: var(--bright-white);
  border: 1px solid var(--hairline-soft);
  border-radius: 8px;
  padding: 8px 10px;
  display: flex; flex-direction: column; gap: 2px;
}
.board-order-folio {
  font-family: var(--font-mono); font-size: 12px;
  letter-spacing: var(--tracking-mono);
  color: var(--body-muted);
}
.board-order-customer { font-size: 16px; font-weight: 500; color: var(--ink); }

/* ---------- Zone map — arc part 03's visual (geometry: map) ----------
   Inline SVG only — no image file, no map tiles, no request. The fee
   ladder below it renders as two numbered steps joined by a connecting
   line (a ladder, literally) instead of a bare list. Uses the shared
   .panel/.panel-head/.panel-label/.panel-note shell, its only remaining
   consumer. */

.zonemap-svg {
  display: block;
  width: 100%; height: auto;
  max-width: 220px;
  margin: 16px auto 0;
  border-radius: var(--radius);
}
.zonemap-bg { fill: var(--pale-cobalt); }
.zonemap-grid line { stroke: var(--hairline-soft); stroke-width: 1; }
.zonemap-zone {
  fill: var(--brand-tint);
  stroke: var(--brand-deep);
  stroke-width: 2;
  stroke-linejoin: round;
}
.zonemap-branch { fill: var(--brand); stroke: var(--bright-white); stroke-width: 2; }
/* Sentence case, body font — small caption weight, not the page's
   uppercase-mono micro-label (task: micro-label monopoly). */
.zonemap-caption {
  margin: 10px 0 0;
  text-align: center;
  font-family: var(--font-body); font-size: 13px; font-weight: 500;
  color: var(--body-muted);
}

.zonemap-ladder {
  position: relative;
  margin: 18px 0 0;
  display: flex; flex-direction: column;
}
.zonemap-ladder::before {
  content: '';
  position: absolute; left: 11px; top: 21px; bottom: 21px;
  width: 1px; background: var(--hairline);
}
.zonemap-rule {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0;
}
.zonemap-rule-step {
  flex-shrink: 0;
  width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  background: var(--brand-tint); color: var(--brand-deep);
}
.zonemap-rule-condition {
  flex: 1; min-width: 0;
  font-size: 16px; line-height: 1.4; color: var(--body);
}
.zonemap-rule-charge {
  flex-shrink: 0;
  font-size: 16px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- Stamp card — arc part 04's visual (geometry: dots) ----------
   A grid of filled/empty stamp circles so the count reads as counting,
   not as rows. No enclosing bordered/shadowed .panel here — a plain
   off-white surface, the same family .board-lane uses but at a
   different radius, so this doesn't reproduce ZoneMap's card shell
   either. The membership state folds into one sentence beneath a single
   divider instead of a second stacked dt/dd block, so it doesn't quietly
   reintroduce the hairline-row shape this part exists to replace. */

.stampcard {
  background: var(--off-white);
  border-radius: var(--radius);
  padding: clamp(18px, 3.6vw, 24px);
}
.stampcard-dots {
  margin-top: 20px;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  max-width: 260px;
}
.stampcard-dot {
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  border: 1.5px solid var(--hairline);
  background: var(--bright-white);
}
.stampcard-dot.is-filled { background: var(--brand); border-color: var(--brand); }
.stampcard-count {
  margin: 16px 0 0;
  font-family: var(--font-display); font-weight: 600;
  font-size: 28px; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.stampcard-count-target { font-size: 16px; font-weight: 500; color: var(--body-muted); }
.stampcard-note {
  margin: 8px 0 0;
  max-width: 42ch;
  font-size: 16px; line-height: 1.5; color: var(--body-muted);
}
.stampcard-membership {
  margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--hairline-soft);
}
.stampcard-membership-head { display: flex; align-items: center; gap: 10px; }
.stampcard-membership-text {
  margin: 8px 0 0;
  font-size: 16px; line-height: 1.5; color: var(--body);
}
.stampcard-membership-text strong { color: var(--ink); font-weight: 600; }

/* ---------- Assistant — a single real screenshot, centered "moment" ----------
   Used to be a two-column thread-plus-screenshot row: a hand-built Thread
   asking a sales question beside a screenshot of a different screen
   (Reportes) answering it with different, invented numbers (task:
   assistant screenshot defect). Now a single real capture of the
   assistant itself, so the layout is the same centered recipe as
   .hero-head (heading + framing sentence) plus one figure — no more
   two-up grid, no thread-specific type overrides to carry. */

.assistant-head { text-align: center; max-width: 640px; margin: 0 auto; }
.assistant-head .lede { margin-left: auto; margin-right: auto; }

/* One centered image, capped at 1040px (the old two-up row's combined
   width) so the dense in-product tables stay legible rather than
   stretching edge-to-edge of the 1200px .container. */
.assistant-figure {
  margin: clamp(32px, 5vw, 48px) auto 0;
  max-width: 1040px;
}
.assistant-img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-xl);
  border: 1px solid var(--hairline-on-dark);
  box-shadow: var(--shadow-lg);
  background: rgba(255, 255, 255, 0.04); /* visible while the lazy image loads in */
}
.assistant-caption {
  margin: 10px 2px 0;
  font-size: 13px;
  color: var(--body-on-dark-muted);
}

/* ---------- Assistant — dark-ground overrides, scoped to #asistente only ----------
   The page's one inverted band. Every value below is an existing on-dark
   token from tokens.css (the family the footer already uses) — no new
   colors. Ratios computed via the WCAG relative-luminance formula against
   the exact hex/rgba pairs in tokens.css (not estimated):
     white(--bright-white) / --ink                          14.62:1
     --body-on-dark (flattened) / --ink                       9.44:1
   Both clear the 4.5:1 floor with room to spare. This section no longer
   renders a Thread (see the comment above), so the former
   `#asistente .thread-frame` / `#asistente .thread-msg--customer
   .thread-bubble` overrides are gone too — the unscoped `.thread-frame` /
   `.thread-msg--customer .thread-bubble` rules (components.css) continue
   to govern the hero and arc part 01 exactly as before, untouched by
   this ID-scoped block either way. */
#asistente.section { color: var(--body-on-dark); }
#asistente .h2 { color: var(--bright-white); }
#asistente .lede { color: var(--body-on-dark); }

/* ---------- Included — a multi-column index (was a single-column dl) ----------
   24 hairline rows in one ~1792px column (task: back-half variety,
   measured) — nearly two phone screens of the identical row shape
   repeated. Same 6 groups, same density, laid out as a grid instead of a
   stack: 2 columns from the smallest width up, 3 at 980px+ — a single
   mobile column was still ~1.8 screens tall (task: mobile scroll length,
   measured), a straight stack of 6 groups' worth of items with nothing
   to shrink; going 2-up at 390px halves the row count (6 groups -> 3
   rows) for the same content, same density, same item count per group.
   Item text is short (the longest, the delivery fee-rule row, is the
   only one that wraps past one line even at a ~165px mobile column), so
   readability holds. Each group is a real `<h3>` (landing.jsx) at
   body-text size/weight, not the page's uppercase-mono micro-label — see
   .spec-group-name below (task: micro-label monopoly). A plain hairline
   above each group is the only chrome; still no cards. */

.spec-grid {
  margin: 40px 0 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 32px 48px;
}
@media (min-width: 980px) { .spec-grid { grid-template-columns: repeat(3, 1fr); } }

.spec-group {
  padding-top: 18px;
  border-top: 2px solid var(--hairline);
}
/* Sentence case, bold body type at real heading weight — the group name
   IS the grouping now that groups sit side by side, so it needs to read
   as a heading, not a field-name caption (task: micro-label monopoly). */
.spec-group-name {
  margin: 0 0 10px;
  font-family: var(--font-display); font-weight: 600;
  font-size: 16px; letter-spacing: -0.01em;
  color: var(--ink);
}
.spec-items {
  display: flex;
  flex-direction: column;
}
.spec-items li {
  font-size: 15px;
  line-height: 1.5;
  color: var(--body);
  padding: 9px 0;
  border-top: 1px solid var(--hairline-soft);
}
.spec-items li:first-child { border-top: 0; }

/* ---------- Personal (#personal) — demoted, and now image-led ----------
   Was three hairline rows naming invented employees (Marisol G./Iván R./
   Paola T.) under a full .h2, then three .arc-feats pills asserting PIN
   clock-in / adjustable tolerance / a daily summary. assets/screens/
   attendance.webp shows all three of those claims directly (PIN keypad +
   live clock, each employee's schedule, each employee's En turno/Tarde/
   Falta state), so the pills are cut — the image carries the claim
   (task). Text stays a .h3 heading + .lede sentence + the literal
   late/absent note (unchanged, see daily-summary.ts), beside the image at
   760px+ (matching .hero-convo/.compare's breakpoint), stacked
   text-then-image at mobile. No roster, no cards, no invented names. */

.personal-row {
  margin-top: clamp(28px, 4vw, 40px);
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
  align-items: center;
}
@media (min-width: 760px) {
  .personal-row { grid-template-columns: 1fr 1.05fr; gap: 40px; }
}
.personal-media { min-width: 0; margin: 0; }
.personal-media img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-xl);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-md);
  background: var(--off-white);
}
.personal-caption {
  margin: 10px 2px 0;
  font-size: 13px;
  color: var(--body-muted);
}
.personal-note {
  margin: 20px 0 0;
  max-width: 60ch;
  font-size: 16px; line-height: 1.6; color: var(--body-muted);
}

/* ---------- Demo / pricing CTA — price-led, not checklist-led ----------
   The money moment used to look exactly like every other section below
   the arc: an .h2 headline first, the price a small line beneath it, a
   three-row ✓-checklist (task: back-half variety, measured — this
   section alone was 914px). Reordered so `.price-kicker` → `.price-tag`
   comes FIRST in `.demo-block-text`, ahead of the headline, and
   `.price-amount` (below) is now sized bigger than `.demo-h`, not
   smaller — the number is the headline. The checklist is gone;
   `.demo-points-prose` is one flowing paragraph instead (i18n:
   `demo.points_prose`, replacing the old `demo.points` array). */

.demo-block {
  margin-top: 48px;
  display: grid; grid-template-columns: 1fr; gap: 32px;
  background: var(--bright-white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-xl);
  padding: clamp(28px, 4vw, 56px);
  box-shadow:
    0 0 0 6px rgba(255, 255, 255, 0.45),
    0 0 0 7px rgba(11, 14, 20, 0.04),
    0 28px 64px -32px rgba(0, 107, 109, 0.28);
  align-items: center;
}
@media (min-width: 880px) { .demo-block { grid-template-columns: 1.4fr 1fr; gap: 56px; } }

/* Sentence case, body font, small — a plain lead-in caption, not the
   page's uppercase-mono micro-label (task: micro-label monopoly). */
.price-kicker {
  margin: 0;
  font-family: var(--font-body); font-size: 13px; font-weight: 600;
  color: var(--body-muted);
}
.price-tag {
  margin: 6px 0 0;
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px;
}
/* The dominant figure on the page's money moment — bigger than the .h3
   headline beneath it (was the reverse: a 30–42px price under an .h2). */
.price-amount {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(46px, 7vw, 76px); letter-spacing: -0.03em;
  color: var(--ink);
}
.price-unit {
  font-family: var(--font-body); font-weight: 600;
  font-size: 17px; color: var(--brand-deep);
}
.demo-h { margin-top: 22px; }
.demo-points-prose {
  margin: 20px 0 0;
  max-width: 48ch;
  font-size: 16px; line-height: 1.6; color: var(--body);
}
/* Sentence case, body font — see .price-kicker's comment. */
.demo-note {
  margin: 14px 0 0; text-align: center;
  font-family: var(--font-body); font-size: 13px;
  color: var(--body-muted);
}

/* ---------- FAQ — accordion ---------- */

.faq-row {
  display: grid; grid-template-columns: 1fr; gap: 32px;
  margin-top: 48px;
}
@media (min-width: 880px) { .faq-row { grid-template-columns: 1fr 1.5fr; gap: 80px; } }

.faq-side {
  color: var(--body-muted);
  font-size: 14.5px; line-height: 1.6;
}

.faq-item { border-bottom: 1px solid var(--hairline); }
.faq-item:first-child { border-top: 1px solid var(--hairline); }

.faq-list .q {
  background: transparent;
  border: none;
  padding: 18px 0;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font: inherit;
  display: flex; justify-content: space-between; align-items: center;
  gap: 16px;
  font-size: 16px; color: var(--ink);
  transition: color 160ms var(--ease-out);
}
.faq-list .q:hover { color: var(--brand-deep); }
.faq-list .q .q-toggle {
  color: var(--brand);
  font-size: 22px; font-weight: 400;
  font-family: var(--font-mono);
  flex-shrink: 0;
  width: 18px; text-align: center;
  line-height: 1;
}
.faq-list .a-wrap[hidden] { display: none; }
.faq-list .a {
  padding: 0 0 22px;
  margin: 0;
  max-width: 64ch;
  color: var(--body); font-size: 16px; line-height: 1.6;
  animation: faq-fade 240ms var(--ease-out);
}
@keyframes faq-fade {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.faq-item.is-open .q { color: var(--ink); }

/* ---------- CTA closer — flat cream surface, separates from the navy footer ---------- */

.cta-block {
  text-align: center;
  padding: clamp(96px, 11vw, 180px) 0 clamp(64px, 8vw, 120px);
  background: var(--paper-cream);
  color: var(--ink);
}
.cta-block .h1 { margin: 0 auto; max-width: 22ch; color: var(--ink); }
.cta-block .lede { margin: 24px auto 0; color: var(--body); }
.cta-block .actions {
  margin-top: 36px;
  display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;
}

/* ---------- Footer ---------- */

.footer {
  padding: clamp(64px, 7vw, 96px) 0 32px;
  background: var(--ink);
  color: rgba(255, 255, 255, 0.78);
}
.footer .container { max-width: var(--container); }
.footer-tag {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(28px, 3vw, 44px); line-height: 1.05;
  letter-spacing: -0.03em;
  color: #FFFFFF;
  margin: 0 0 36px;
  max-width: 22ch;
}
.footer-tag .accent { color: var(--brand-soft); }
.footer-links {
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
}
@media (min-width: 760px) { .footer-links { grid-template-columns: repeat(4, 1fr); } }
/* Sentence case, body font, bold — a small column header, not the page's
   uppercase-mono micro-label (task: micro-label monopoly). Color/opacity
   unchanged from before, so its contrast against --ink is unaffected. */
.footer-col h3 {
  font-family: var(--font-body); font-size: 14px;
  color: rgba(255, 255, 255, 0.55);
  margin: 0 0 14px;
  font-weight: 700;
}
.footer-col a {
  display: block; padding: 4px 0;
  color: rgba(255, 255, 255, 0.85);
  font-size: 14.5px;
  text-decoration: none;
}
.footer-col a:hover { color: #6FD3CE; }
/* Sentence case, body font — see .footer-col h3's comment. i18n content
   (footer.base_left/base_right) changed from forced ALL CAPS strings to
   real sentence case to match. */
.footer-base {
  margin-top: 44px; padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  font-family: var(--font-body); font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
}

/* Footer's copy of the language toggle — only reachable below 768px, the
   inverse of the nav's rule, so exactly one instance is on screen at once. */
.footer .lang-toggle {
  display: none;
  margin: 28px 0 0;
  border-color: var(--hairline-on-dark);
}
@media (max-width: 767px) { .footer .lang-toggle { display: inline-flex; } }
.footer .lang-toggle button {
  color: var(--body-on-dark-muted);
  min-width: 44px; min-height: 44px; padding: 0 14px;
  display: inline-flex; align-items: center; justify-content: center;
}
.footer .lang-toggle button.is-active { background: var(--hairline-on-dark); color: var(--bright-white); }

/* ---------- Language toggle — ES/EN; one copy in the nav, one in the footer ---------- */

.lang-toggle { display: inline-flex; border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; }
.lang-toggle button {
  font: 500 12px/1 var(--font-mono); letter-spacing: var(--tracking-mono);
  padding: 7px 10px; background: transparent; color: var(--body-muted);
  border: 0; cursor: pointer;
}
.lang-toggle button.is-active { background: var(--bright-white); color: var(--ink); }

/* ---------- Mono utility (used by Mono component) ---------- */

.mono {
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}
.mono-md {
  font-family: var(--font-mono); font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}
/* ---------- Mobile rhythm — tightened vertical spacing below 768px ----------
   Section padding, panel padding and inter-block margins on this page were
   all tuned reading comfortably at desktop widths; at 390px those same
   clamp() floors compound across nine stacked sections into hundreds of
   pixels nothing is using. Nothing here removes content — every row,
   panel and list item that existed above 768px still exists here, just
   closer together, which is also the stated design direction ("refined
   and dense, not decorated"). Scoped to max-width:767px so nothing above
   the nav's own breakpoint changes.

   `--section-y` is a custom property, not a class — redeclaring it on
   :root inside this query overrides the clamp() in tokens.css for every
   .section on the page (landing.css loads after tokens.css, so this wins
   at matching widths) without editing that shared token file. */
@media (max-width: 767px) {
  /* --section-y governs 7 .section elements (Screens/panel, Arc, Assistant,
     Included, Attendance's sibling OrderModels, DemoCTA, FAQ) — one more
     point of tightening here compounds across all seven (task: mobile
     scroll length). --section--tight (Attendance, DriverApp) gets its own
     explicit override just below for the same reason: it isn't tied to
     this token on purpose (see .section--tight's comment), so it doesn't
     move with this value. */
  :root { --section-y: 32px; }
  .section--tight { padding-top: 24px; padding-bottom: 24px; }

  .lede { margin-top: 16px; }

  /* Hero — six thread messages plus an order card is the tallest single
     block on the page; its content can't shrink (the thread text is a
     literal template transcript), so only whitespace comes out. */
  .hero { padding-top: 24px; padding-bottom: 20px; }
  .hero-convo { margin-top: 16px; gap: 16px; }
  .hero-actions { margin-top: 20px; }
  .hero-trust { margin-top: 14px; }
  .hero-convo .thread { gap: 9px; }
  .hero-convo .thread-frame { padding: 12px; }
  .hero-convo .thread-bubble { padding: 7px 12px; }
  .order-card { gap: 12px; padding: 14px; }
  .order-card-head { padding-bottom: 12px; }
  .order-card-fields { gap: 10px; }
  .order-card-note { padding-top: 10px; }

  .screens-figure { margin-top: 16px; }
  .screens-caption { margin-top: 6px; }

  /* Arc — same-background seam with the hero above it (both cream); the
     four parts' own internal padding is the other lever. */
  .arc-part { padding: 20px 0; gap: 16px; }
  .arc-body { margin-top: 14px; }
  .arc-feats { margin-top: 14px; }
  .board { gap: 10px; }
  .board-unconfirmed { padding: 10px 12px; }
  .board-lane { padding: 10px; }
  .zonemap-svg { margin-top: 10px; }
  .zonemap-ladder { margin-top: 10px; }
  .stampcard-dots { margin-top: 12px; }
  .stampcard-membership { margin-top: 12px; padding-top: 12px; }

  /* Driver route — the portrait image already caps its own width
     (.driver-media img, landing.css), so only the row's own gap needs
     tightening here. */
  .driver-row { margin-top: 16px; gap: 16px; }

  .assistant-figure { margin-top: 14px; }

  /* #incluye and #personal no longer share a surface (task: page rhythm —
     incluye is .surface-white-bg/off, personal is .surface-tint-bg/tint),
     so the old same-surface seam shortcut that used to live here is gone;
     #personal's own .section--tight (landing.css, near .section) already
     handles its compact padding at every width, mobile included. */
  .personal-row { margin-top: 16px; gap: 16px; }

  /* #incluye is 2-column from the smallest width up (landing.css, near
     .spec-grid) — column-gap can run tighter than the desktop 48px
     without crowding the short item text, which buys back more row
     height than the row-gap alone. */
  .spec-grid { margin-top: 20px; gap: 20px 16px; }
  .spec-items li { padding: 7px 0; }

  .compare { margin-top: 10px; }
  .compare-model { padding: 16px 0; }
  .compare-note { margin-top: 18px; padding-top: 14px; }

  .demo-block { margin-top: 20px; padding: 18px; }
  .price-tag { margin-top: 4px; }
  .demo-h { margin-top: 14px; }
  .demo-points-prose { margin-top: 14px; }

  .faq-row { margin-top: 20px; gap: 16px; }
  /* .q is a 44px+ tap target at every width the constraint applies to:
     16px text (line-height ~24px) + 12px top/bottom padding = 48px,
     still clear of the floor. */
  .faq-list .q { padding: 12px 0; }
  .faq-list .a { padding-bottom: 12px; }

  .cta-block { padding: 48px 0 32px; }
  .cta-block .actions { margin-top: 16px; }

  .footer { padding-top: 32px; }
  .footer-tag { margin-bottom: 18px; }
  .footer-links { gap: 16px; }
  .footer-base { margin-top: 24px; padding-top: 10px; }
}

/* ---------- Scroll reveal — JS adds .reveal-ready on <html>, .is-in per element ----------
   Animation (not transition) on reveal so card hover transitions stay untouched;
   `backwards` fill so styles return to natural values once the rise completes. */

.reveal-ready [data-reveal]:not(.is-in) { opacity: 0; }
.reveal-ready [data-reveal].is-in { animation: rise-in 700ms var(--ease-out) backwards; }

.reveal-ready [data-reveal='stagger']:not(.is-in) { opacity: 1; }
.reveal-ready [data-reveal='stagger']:not(.is-in) > * { opacity: 0; }
.reveal-ready [data-reveal='stagger'].is-in { animation: none; }
.reveal-ready [data-reveal='stagger'].is-in > * { animation: rise-in 640ms var(--ease-out) backwards; }
.reveal-ready [data-reveal='stagger'].is-in > *:nth-child(2) { animation-delay: 90ms; }
.reveal-ready [data-reveal='stagger'].is-in > *:nth-child(3) { animation-delay: 180ms; }
.reveal-ready [data-reveal='stagger'].is-in > *:nth-child(4) { animation-delay: 270ms; }
.reveal-ready [data-reveal='stagger'].is-in > *:nth-child(5) { animation-delay: 360ms; }

/* ---------- Reduced motion: everything lands instantly, mocks hold still ---------- */

@media (prefers-reduced-motion: reduce) {
  .hero-head .badge, .hero .h1, .hero .lede,
  .hero-actions, .hero-trust,
  .reveal-ready [data-reveal].is-in,
  .reveal-ready [data-reveal='stagger'].is-in > * { animation: none; }
  .reveal-ready [data-reveal]:not(.is-in),
  .reveal-ready [data-reveal='stagger']:not(.is-in) > * { opacity: 1; }
}
