/* Generated by _src/build.mjs — do not edit. Sources: tokens.css, base.css, components.css, pages.css */

/* ===== tokens.css ===== */
/* ==========================================================================
   tokens.css — the design token layer
   Generated from DESIGN.md v0.1.0. DESIGN.md is the source of truth; if the
   two disagree, DESIGN.md wins and this file is the bug.

   Every contrast ratio in the comments is stated with the ground it was
   measured against. A ratio without its ground is not a fact.
   ========================================================================== */

:root {
  /* --- Brand primitives — locked in BRAND.md:256-263. Never redefine. ----- */
  --c-azul-noche: #08182E;
  --c-azul-medio: #13304F;
  --c-cian:       #2FBBD6;
  --c-cian-claro: #9FE0EC;
  --c-hielo:      #EDF3F9;
  --c-abismo:     #040E1C;
  --c-blanco:     #FFFFFF;

  /* --- Inherited neutrals — NOT brand primitives. Named so they stop
         leaking in unnamed. See DESIGN.md §2. --------------------------- */
  --c-gris-linea: #E2E8F0;  /* decorative hairline ONLY */
  --c-gris-humo:  #CBD5E1;  /* decorative ONLY */
  --c-gris-medio: #94A3B8;  /* dark-ground ink only — fails on every light ground */
  --c-gris-tinta: #64748B;
  --c-tinta-2:    #475569;

  /* --- Surfaces ---------------------------------------------------------- */
  --bg-canvas:       var(--c-blanco);
  --bg-raised:       var(--c-hielo);      /* 1.12:1 on canvas — decorative; never a control's only boundary */
  --bg-inverse:      var(--c-azul-noche); /* 17.79:1 on canvas */
  --bg-inverse-deep: var(--c-abismo);     /* 19.24:1 on canvas */
  --bg-accent-soft:  var(--c-cian-claro); /* 1.46:1 on canvas — ground only, never text */

  /* --- Inks -------------------------------------------------------------- */
  --fg-primary:      var(--c-azul-noche); /* 17.79:1 on white · 15.92:1 on Hielo — AAA */
  --fg-secondary:    var(--c-tinta-2);    /*  7.58:1 on white ·  6.78:1 on Hielo — AAA */
  --fg-muted:        var(--c-gris-tinta); /*  4.75:1 on white — AA. FORBIDDEN on --bg-raised (4.25:1 fails) */
  --fg-link:         var(--c-azul-medio); /* 13.45:1 on white · 12.04:1 on Hielo — AAA */
  --fg-on-accent:    var(--c-azul-noche); /*  8.57:1 on Cian — AAA */
  --fg-on-inverse:   var(--c-hielo);      /* 15.92:1 on Azul noche — AAA */
  --fg-on-inverse-2: var(--c-gris-humo);  /* 11.92:1 on Azul noche — AAA */

  /* Cian is a DARK-GROUND ink. 2.30:1 on white — never text on light. */
  --accent:          var(--c-cian);

  /* Headings resolve through their own token so the dark ramp can give them
     Cian claro per Remedio Dark Mode.pdf (2026-07-02) without touching any
     other ink. On light there is nowhere for Cian to go — 2.30:1 — so this
     is --fg-primary and the indirection costs nothing. */
  --fg-heading:      var(--fg-primary);

  /* --- Borders — DESIGN.md §4, the rule that earns the file -------------- */
  --border-hairline:    var(--c-gris-linea); /* content separation ONLY. Never an interactive boundary. */
  --border-control:     var(--c-gris-tinta); /* 4.75:1 on white · 4.25:1 on Hielo — every input, button
                                                outline, toggle track, checkbox, card-that-is-a-link */
  --border-control-inv: rgba(237, 243, 249, 0.45); /* ~4.45:1 on Azul noche — dark-ground twin */
  --border-strong:      var(--c-azul-medio); /* 13.45:1 — selected / active boundary */

  /* --- Semantics — no new hue except red (DEC-034) ----------------------- */
  --sem-danger-fg:     #DC2626;            /* 4.84:1 on white */
  --sem-danger-bg:     #FEF2F2;
  --sem-danger-border: #DC2626;
  --sem-danger-ink:    #991B1B;            /* 7.66:1 on --sem-danger-bg */
  --sem-success-fg:    var(--c-azul-medio); /* no green. 5.60:1 on --sem-success-bg */
  --sem-success-bg:    var(--c-cian-claro);
  --sem-warning-fg:    var(--c-azul-medio);
  --sem-info-fg:       var(--c-azul-medio);

  /* --- Type — Poppins 400/500/600/700/800. Weight 900 is NOT loaded. ----- */
  --font-sans: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  --fs-display:  clamp(2.5rem, 6vw, 4.5rem);
  --fs-h1:       clamp(2rem, 4.5vw, 3.25rem);
  --fs-h2:       clamp(1.625rem, 3.2vw, 2.375rem);
  --fs-h3:       1.375rem;
  --fs-h4:       1.125rem;
  --fs-lead:     1.1875rem;
  --fs-body:     1.0625rem;   /* 17px — not 16. BRAND.md:381 older-relative test. */
  --fs-body-sm:  0.9375rem;
  --fs-caption:  0.875rem;    /* 14px — THE FLOOR for any sentence */
  --fs-overline: 0.8125rem;   /* 13px — LABELS ONLY, 1-3 words, uppercase. Never a sentence. */
  /* Index hero only — one step above --fs-display (DESIGN.md §6 v0.1.3). */
  --fs-hero: clamp(2.75rem, 8vw, 5.5rem);
  --lh-hero: 1;
  --ls-hero: -0.04em;

  --lh-display: 1.02;  --ls-display: -0.035em;
  --lh-h1:      1.08;  --ls-h1:      -0.03em;
  --lh-h2:      1.15;  --ls-h2:      -0.02em;
  --lh-h3:      1.25;  --ls-h3:      -0.015em;
  --lh-h4:      1.35;  --ls-h4:      -0.01em;
  --lh-lead:    1.55;
  --lh-body:    1.60;
  --lh-caption: 1.50;
  --lh-overline:1.40;  --ls-overline: 0.12em;

  --measure: 68ch;

  /* --- Spacing — 4px base. The app's scale is a SUBSET of this one. ------ */
  --sp-1:  0.25rem;  --sp-2:  0.5rem;   --sp-3: 0.75rem;  --sp-4:  1rem;
  --sp-5:  1.5rem;   --sp-6:  2rem;     --sp-7: 2.5rem;   --sp-8:  3rem;
  --sp-9:  4rem;     --sp-10: 5rem;     --sp-11: 6rem;    --sp-12: 8rem;

  --section-y:       var(--sp-10);
  --section-y-md:    var(--sp-11);
  --section-y-loose: var(--sp-12);
  /* The padding a section keeps on an edge where the ADJACENT section carries
     a different ground. The ground change is itself the separator, so the
     padding need not be. Named for the relationship, not the size. */
  --section-y-seam:  var(--sp-8);
  --gutter:          var(--sp-5);
  --gutter-md:       var(--sp-7);
  --container-max:   75rem;
  /* The sticky header's height. Was a bare 68px in components.css; anything
     that must clear the header — an anchor jump above all — reads it here, so
     the two consumers cannot drift apart. */
  --nav-h:           68px;

  /* --- Radii — adopted verbatim from src/theme/index.js ------------------ */
  --r-xs:   0.25rem;  /* legal stamps, tags — "document", not "app" */
  --r-sm:   0.5rem;
  --r-md:   0.75rem;  /* default card, default button */
  --r-lg:   1rem;
  --r-xl:   1.25rem;  /* large cards, screenshot masks */
  --r-2xl:  1.75rem;  /* hero card */
  --r-full: 999px;
  /* Screenshot phone frame — one value for every capture on a light ground. */
  --bezel-w: 6px;
  --bezel-r: 2rem;

  /* --- Elevation — shadow is Azul noche, not Tailwind slate ------------- */
  --elev-0: none;
  --elev-1: 0 1px 2px rgba(8, 24, 46, .04), 0 2px 8px rgba(8, 24, 46, .04);
  --elev-2: 0 1px 2px rgba(8, 24, 46, .04), 0 8px 24px rgba(8, 24, 46, .06);
  --elev-3: 0 12px 32px rgba(8, 24, 46, .10), 0 2px 6px rgba(8, 24, 46, .06);

  /* --- Motion ------------------------------------------------------------ */
  --dur-fast:  120ms;
  --dur-base:  180ms;
  --dur-slow:  320ms;
  --dur-enter: 480ms;
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --reveal-y: 12px;

  /* --- Focus — two-tone, always. The tones are 15.92:1 apart, so at least
         one clears 3:1 against ANY palette ground. A single-colour ring
         cannot: the old `outline: 2px solid` Cian was 2.30:1 on white. ---- */
  --focus-ring-w: 3px;
  --focus-ring-offset: 3px;
  --focus-inner: var(--c-azul-noche);
  --focus-outer: var(--c-hielo);
}

/* --------------------------------------------------------------------------
   Dark ramp — AUTHORED, NOT SHIPPED on the web in v1 (DESIGN.md §5).

   Deliberately gated behind an explicit [data-theme="dark"] stamp and NOT
   behind prefers-color-scheme, so it cannot activate by accident. It lives
   here so the app's dark mode becomes auditable against a written source.

   Three corrections to src/theme/index.js are baked in:
     1. Dark mode has NO third ink. --fg-muted resolves to --fg-secondary.
        The app's darkColors.textMuted #64748B fails on BOTH dark grounds
        (4.08:1 on Abismo, 2.83:1 on Azul medio).
     2. Danger splits by ground — the light red is only 2.9:1 on dark.
     3. No token is named for its lightness. `primaryDark` inverting its own
        meaning between themes is how the session-59 login collapse happened.
   -------------------------------------------------------------------------- */
:root[data-theme="dark"] {
  /* CORRECTION 4 (2026-09-11) — the canvas is Azul noche, not Abismo.
     BRAND.md:259 calls Azul noche the "Primary brand background — Mandatory",
     and Remedio Dark Mode.pdf draws the ground as Azul noche. Abismo stays as
     the deep surface. The swap costs exactly one token: --fg-secondary at
     Gris medio measures 7.55:1 on Abismo but 6.94:1 on Azul noche, which
     leaves AAA. Gris humo restores it to 11.98:1 — and it is already the ink
     the light theme uses ON Azul noche (--fg-on-inverse-2). */
  --bg-canvas:       var(--c-azul-noche);
  --bg-raised:       var(--c-azul-medio); /* only 1.32:1 above Azul noche — MUST carry --border-control-inv */
  --bg-inverse:      var(--c-hielo);
  --bg-inverse-deep: var(--c-blanco);

  --fg-primary:      var(--c-hielo);      /* 15.92:1 on Azul noche · 12.02:1 on Azul medio */
  --fg-secondary:    var(--c-gris-humo);  /* 11.98:1 on Azul noche ·  9.05:1 on Azul medio */
  --fg-muted:        var(--c-gris-humo);  /* CORRECTION 1 — no third ink in dark */
  --fg-link:         var(--c-cian);       /*  7.79:1 on Azul noche */
  --fg-heading:      var(--c-cian-claro); /* 12.15:1 on Azul noche — the July spec's
                                             "EXTRA DETAILS / Headings etc". This is the
                                             line that finally puts Cian on the page. */
  --fg-on-inverse:   var(--c-azul-noche);
  --fg-on-inverse-2: var(--c-tinta-2);

  --border-hairline: rgba(237, 243, 249, 0.14);
  --border-control:  rgba(237, 243, 249, 0.45);
  --border-strong:   var(--c-cian);

  --sem-danger-fg:   #EF4444;             /* CORRECTION 2 — 4.73:1 on Azul noche */
  --sem-danger-bg:   rgba(239, 68, 68, 0.12);
  --sem-danger-ink:  #FCA5A5;

  --focus-inner: var(--c-hielo);
  --focus-outer: var(--c-azul-noche);

  --elev-1: none;  /* on dark, elevation is surface lightness, not shadow */
  --elev-2: none;
  --elev-3: none;
}

/* ===== base.css ===== */
/* ==========================================================================
   base.css — reset, document defaults, typography, focus, motion
   Depends on tokens.css. No component styling here.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Guarded globally at the foot of this file — the current six pages set
     this unguarded while guarding only the reveal animation, so a
     vestibular-sensitive user who clicks an in-page link gets a full smooth
     scroll they asked the OS to suppress. */
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--fg-primary);
  background: var(--bg-canvas);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* --- Headings ------------------------------------------------------------ */
h1, h2, h3, h4, h5, h6 {
  margin: 0;
  font-weight: 800;
  color: var(--fg-heading);
  text-wrap: balance;
}
h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); }
h2 { font-size: var(--fs-h2); line-height: var(--lh-h2); letter-spacing: var(--ls-h2); font-weight: 700; }
h3 { font-size: var(--fs-h3); line-height: var(--lh-h3); letter-spacing: var(--ls-h3); font-weight: 700; }
h4 { font-size: var(--fs-h4); line-height: var(--lh-h4); letter-spacing: var(--ls-h4); font-weight: 600; }

.display {
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  font-weight: 800;
}

/* --- Body copy ----------------------------------------------------------- */
p, li { margin: 0; }
p { color: var(--fg-secondary); }

.lead    { font-size: var(--fs-lead); line-height: var(--lh-lead); color: var(--fg-secondary); }
.body-sm { font-size: var(--fs-body-sm); }
.caption { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--fg-muted); }

/* 13px is for LABELS — one to three words, uppercase. Never a sentence.
   This rule is what stops the clinical scope line shipping at 13px muted
   again, which is how the most load-bearing sentence on the patient page
   became its smallest and faintest text. */
.overline {
  font-size: var(--fs-overline);
  line-height: var(--lh-overline);
  letter-spacing: var(--ls-overline);
  text-transform: uppercase;
  font-weight: 700;
  color: var(--fg-muted);
}

/* Prose blocks cap at 68ch. Cards and grids may use the full container.

   .container frames the PAGE — it owns the gutter and the outer cap.
   .prose sets the READING MEASURE. They are both width primitives and must
   never sit on one element: correct authoring is .prose nested INSIDE
   .container. `class="container prose"` shipped on /nosotros and rendered at
   75rem, because both selectors are (0,1,0) and .container is declared later
   in this file — a silent 150-character line length. The guard below makes
   the combination degrade to "measure" rather than to "container" regardless
   of source order; build.mjs rejects it outright.

   margin-inline:auto is load-bearing, not cosmetic. A 68ch column
   left-aligned in a 1200px white container reads as a MISSING RIGHT COLUMN.
   The same column centred inside a full-bleed ground reads as an editorial
   measure, because the ground draws the width and the content no longer
   claims to. The block centres; the text inside stays left-aligned, because
   centred body copy destroys the return sweep. */
.prose > * + * { margin-top: var(--sp-4); }
.prose { max-width: var(--measure); margin-inline: auto; }
.container.prose { max-width: var(--measure); }

/* --- Links --------------------------------------------------------------- */
a {
  color: var(--fg-link);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--dur-fast) var(--ease-in-out);
}
a:hover { color: var(--fg-primary); }

/* --- Media --------------------------------------------------------------- */
img, svg, video { max-width: 100%; height: auto; display: block; }

/* --- Focus — two-tone ring, applied once, globally ----------------------- */
:focus { outline: none; }
:focus-visible {
  outline: none;
  border-radius: var(--r-sm);
  box-shadow:
    0 0 0 var(--focus-ring-w) var(--focus-inner),
    0 0 0 calc(var(--focus-ring-w) + 2px) var(--focus-outer);
}

/* --- Skip link — SC 2.4.1 Level A. All twelve current pages ship without
       one; this is the single element that fixes it site-wide. ------------ */
.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: var(--sp-4);
  z-index: 999;
  padding: var(--sp-3) var(--sp-4);
  background: var(--bg-inverse);
  color: var(--fg-on-inverse);
  border-radius: var(--r-md);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(calc(-100% - var(--sp-6)));
  transition: transform var(--dur-base) var(--ease-out);
}
.skip-link:focus-visible { transform: translateY(0); color: var(--fg-on-inverse); }

/* --- Layout primitives --------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* --gutter-md was declared in tokens.css and referenced by nothing, so the
   container held 24px gutters at every width up to the 1200px cap. This is
   the line that makes the token real. */
@media (min-width: 56.25rem) { .container { padding-inline: var(--gutter-md); } }

.section { padding-block: var(--section-y); }
.section--inverse {
  background: var(--bg-inverse);
  color: var(--fg-on-inverse);
  padding-block: var(--section-y-loose);
}
.section--inverse h1,
.section--inverse h2,
.section--inverse h3,
.section--inverse h4 { color: var(--fg-on-inverse); }
.section--inverse p  { color: var(--fg-on-inverse-2); }
.section--raised { background: var(--bg-raised); }

/* --fg-muted is FORBIDDEN on a raised surface — 4.25:1 fails AA.
   Anything muted inside a raised band resolves up to --fg-secondary. */
.section--raised .caption,
.section--raised .overline { color: var(--fg-secondary); }

/* Wide content scrolls in its own container; the page body never scrolls
   sideways. */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* --- Motion — CSS only. One keyframe, two uses: the index hero entrance and
       scroll reveals. Scroll reveals are progressive: with no
       animation-timeline support, or with reduced motion requested, the page
       is static. No JS, no hidden content. Selectors are limited to classes
       that /d/ does not use, so the doctor page is untouched. */
@keyframes rise { from { opacity: 0; transform: translateY(var(--reveal-y)); } }

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .split-feature__body, .split-feature__art, .how__item, .step,
    .founder__head, .founder__body, .band-accent__inner, .card--lifted {
      animation: rise linear both;
      animation-timeline: view();          /* must come AFTER the shorthand */
      animation-range: entry 0% entry 120px;
    }
  }
}

/* --- Reduced motion — ONE global block, not a per-effect opt-in ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
}

/* --- Utilities ----------------------------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.tabular { font-variant-numeric: tabular-nums; }

/* --- Spacing utilities --------------------------------------------------
   A deliberately tiny set. They exist so a page template never needs a
   style= attribute for a one-off margin — the failure mode that put five
   token systems on this site was exactly "just this once, inline". If a
   value is not on the scale, it does not belong on the page. */
.u-mt-3 { margin-top: var(--sp-3); }
.u-mt-4 { margin-top: var(--sp-4); }
.u-mt-8 { margin-top: var(--sp-8); }
.list-plain { list-style: none; margin: 0; padding: 0; }
.caption-left { text-align: left; padding-bottom: var(--sp-3); }

/* ===== components.css ===== */
/* ==========================================================================
   components.css — nav, footer, buttons, cards, forms, banners, figures
   Depends on tokens.css + base.css.

   The governing rule throughout: --border-hairline separates CONTENT.
   --border-control bounds anything a person can operate. Mixing them up is
   the defect class that shipped the app's invisible login fields and three
   web instances of the same bug.
   ========================================================================== */

/* --------------------------------------------------------------- Buttons -- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  min-height: 44px;                    /* SC 2.5.8 target size */
  border-radius: var(--r-md);
  border: 1.5px solid transparent;
  font-family: inherit;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease-in-out),
    border-color var(--dur-fast) var(--ease-in-out),
    color var(--dur-fast) var(--ease-in-out);
}

.btn--primary {
  background: var(--bg-inverse);
  color: var(--fg-on-inverse);
  border-color: var(--bg-inverse);
}
.btn--primary:hover { background: var(--c-azul-medio); border-color: var(--c-azul-medio); color: var(--fg-on-inverse); }

/* Cian is a ground here, never an ink on light. Text on it is Azul noche at
   8.57:1. */
.btn--accent {
  background: var(--accent);
  color: var(--fg-on-accent);
  border-color: var(--border-strong);   /* NOT --accent: Cian on white is 2.30:1, under the 3:1 non-text floor (SC 1.4.11). 13.45:1. */
}
.btn--accent:hover { background: var(--c-cian-claro); color: var(--fg-on-accent); }

/* The old CTAs read "Descargar la app →". The arrow is a ::after glyph rather
   than typed into the locale files: it stays out of the accessible name and
   out of the copy gate, and it does not get translated as a word. */
.hero__actions .btn::after { content: " \2192"; }

.btn--ghost {
  background: transparent;
  color: var(--fg-primary);
  border-color: var(--border-control);   /* 4.75:1 — NOT the hairline */
}
.btn--ghost:hover { border-color: var(--border-strong); color: var(--fg-primary); }

.btn--on-inverse {
  background: transparent;
  color: var(--fg-on-inverse);
  border-color: var(--border-control-inv); /* 4.45:1 on Azul noche */
}
.btn--on-inverse:hover { background: rgba(237, 243, 249, 0.10); color: var(--fg-on-inverse); }

.btn--block { width: 100%; }

/* ------------------------------------------------------------------- Nav -- */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--bg-inverse);
  border-bottom: 1px solid var(--border-hairline);  /* content separation — correct use */
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: var(--nav-h);
}
.nav__mark { display: flex; align-items: center; gap: var(--sp-2); }
.nav__mark img, .nav__mark svg { height: 30px; width: auto; }
/* The house is a thin-line drawing and the wordmark is a heavy grotesque: the
   house's stem is about a third of the R's, so no size makes the two agree on
   weight. The tile supplies mass instead — the same move the app icon makes,
   inverted for a dark bar (navy house on Cian claro rather than the reverse).
   Selector is .nav__mark .nav__icon, not .nav__icon: .nav__mark img is (0,1,1)
   and would otherwise win on height and width. */
.nav__mark .nav__icon {
  /* Sized so the HOUSE matches the R's cap height, not so its box matches the
     wordmark. casa-azul-noche-acento.svg is 53% transparent padding -- the drawing is
     only 0.467 of the box height -- which is why every earlier attempt read
     small and why a tile felt necessary. R cap = 0.860 x 30px = 25.8px, so the
     box is 25.8 / 0.467 = 55px. */
  height: 55px;
  /* The box carries 0.249/0.224 of its width as transparent margin, ~13px a
     side at this scale. Without this the optical gap to the R would be --sp-2
     plus that padding. Pull it back so the lockup spaces as drawn. */
  margin-inline: -13px -5px;
  /* Sit the house on the R's baseline. align-items:center aligns the two BOXES,
     but casa-azul-noche-acento.svg carries uneven vertical padding (0.213 top, 0.320
     bottom), so a centred box leaves the drawing riding high. Measured: the R
     baseline is +13.80px from the shared centre and the house bottom +9.72px,
     so the house drops 4px. */
  transform: translateY(4px);
}

.nav__links {
  display: none;
  align-items: center;
  gap: var(--sp-5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav__link {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg-on-inverse);
  text-decoration: none;
}
.nav__link:hover { color: var(--c-cian-claro); }

/* Section links sit in pills; .nav__actions (locale + Acceder) deliberately do
   not, so the pills read as "where you can go" and not "everything up here".
   Filled, not outlined -- founder 2026-09-11: an outline pill on Azul noche has
   an Azul noche centre, so it reads as unfilled rather than as a pill. Hielo
   ground with Azul noche ink is 15.92:1; the current page takes Cian claro at
   12.15:1, so both states are filled and the accent still marks where you are. */
.nav__links .nav__link {
  display: inline-flex;
  align-items: center;
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-full);
  background: var(--c-hielo);
  color: var(--fg-on-accent);                    /* 15.92:1 on Hielo */
  transition: background-color var(--dur-base) var(--ease-out);
}
.nav__links .nav__link:hover {
  background: var(--c-blanco);
  color: var(--fg-on-accent);
}
.nav__links .nav__link[aria-current="page"] {
  background: var(--c-cian-claro);
  color: var(--fg-on-accent);                    /* 12.15:1 on Cian claro */
  font-weight: 600;
}

.nav__actions { display: flex; align-items: center; gap: var(--sp-3); }

/* Founder 2026-09-11: the locale switch and Acceder become pills too, so the
   whole bar reads as one system. Hierarchy is carried by fill, not by shape --
   Hielo for the section links and the locale, Blanco for Acceder because it is
   the account action, Cian claro reserved for the page you are on. Acceder
   keeps .btn's 44px min-height for SC 2.5.8; the locale link is a 2-letter
   target, so it gets the same floor explicitly. */
.nav__actions .nav__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-full);
  background: var(--c-hielo);
  color: var(--fg-on-accent);                    /* 15.92:1 on Hielo */
  transition: background-color var(--dur-base) var(--ease-out);
}
.nav__actions .nav__link:hover { background: var(--c-blanco); color: var(--fg-on-accent); }

.nav .btn--on-inverse {
  background: var(--c-blanco);
  color: var(--fg-on-accent);                    /* 17.79:1 on Blanco */
  border-color: var(--c-blanco);
  border-radius: var(--r-full);
}
.nav .btn--on-inverse:hover { background: var(--c-hielo); color: var(--fg-on-accent); }

.nav__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  background: transparent;
  color: var(--fg-on-inverse);
  border: 1.5px solid var(--border-control-inv);
  border-radius: var(--r-md);
  cursor: pointer;
}

/* The panel is display:none when closed, not opacity:0 — an opacity-hidden
   panel keeps its links in the tab order, which is SC 2.4.3 Level A and is
   live on the current pages. */
.nav__panel { display: none; }
.nav__panel[data-open="true"] {
  display: block;
  padding-block: var(--sp-4) var(--sp-6);
  border-top: 1px solid var(--border-hairline);
}
.nav__panel .nav__links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-4);
}

/* 2026-10-02: on phones the bar holds the mark and the menu only — EN and Acceder are in the menu
   panel; together they overflowed a 400px bar and overlapped the wordmark. */
@media (max-width: 37.49rem) {
  .nav__actions .nav__link, .nav__actions .btn--on-inverse { display: none; }
}

@media (min-width: 56.25rem) {
  .nav__links { display: flex; }
  .nav__toggle { display: none; }
  .nav__panel { display: none !important; }
}

/* ---------------------------------------------------------------- Footer -- */
.footer {
  background: var(--bg-inverse);
  color: var(--fg-on-inverse);
  padding-block: var(--section-y) var(--sp-8);
  /* index.html ends on a .section--inverse, and the footer is the same ground:
     the two abutted into one continuous dark slab with no seam. We own exactly
     one loud seam (white to Azul noche, 17.79:1) and on that page it was being
     spent where the footer swallowed it. Abismo would not serve — the
     Abismo/Azul-noche boundary measures 1.08:1. A 3px Cian rule at 7.72:1 does.
     Harmless on the pages whose last section is light: it lands at the top of
     the dark ground, against white, where it reads as nothing. */
  border-top: 3px solid var(--c-cian);   /* recetario footer band (founder 2026-09-08 receta palette): Cian on Azul noche 7.72:1. Still the seam when the last section is also dark. */
}
/* MANDATORY, same class of defect as .showcase figcaption below. A <p> in the
   footer does not inherit .footer's colour — `p { color: var(--fg-secondary) }`
   is a matching rule and matching beats inheriting. So footer__entity and
   footer__copyright rendered --fg-secondary on an inverse ground: #475569 on
   Azul noche is 2.35:1 and has been live and failing SC 1.4.3. Routing them
   through the inverse ink resolves correctly in BOTH themes — 11.98:1 on the
   light theme's dark footer, 6.78:1 on the dark theme's light one. */
.footer p { color: var(--fg-on-inverse-2); }
.footer a { color: var(--fg-on-inverse); text-decoration-color: var(--border-control-inv); }
.footer a:hover { color: var(--accent); }
.footer__grid {
  display: grid;
  gap: var(--sp-8);
  grid-template-columns: 1fr;
}
.footer__col-title {
  font-size: var(--fs-overline);
  letter-spacing: var(--ls-overline);
  text-transform: uppercase;
  font-weight: 700;
  color: var(--fg-on-inverse-2);
  margin-bottom: var(--sp-3);
}
.footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.footer__legal {
  margin-top: var(--sp-8);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border-control-inv);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--fg-on-inverse-2);
}
@media (min-width: 37.5rem) { .footer__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 56.25rem) { .footer__grid { grid-template-columns: 2fr 1fr 1fr 1fr; } }

/* ----------------------------------------------------------------- Cards -- */
/* Not everything is a card. Border, fill, radius and shadow each say
   "separate object" — spend them by role. */
.card {
  background: var(--bg-canvas);
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-xl);
  padding: var(--sp-6);
}
.card--raised { background: var(--bg-raised); border-color: transparent; }
.card--lifted { box-shadow: var(--elev-2); border-color: transparent; }

/* A card that is itself a link is an interactive control and takes the
   control boundary, not the hairline. */
.card--link { border-color: var(--border-control); text-decoration: none; display: block; }
.card--link:hover { border-color: var(--border-strong); }

.grid { display: grid; gap: var(--sp-5); }
@media (min-width: 37.5rem) { .grid--2 { grid-template-columns: repeat(2, 1fr); } }
/* .grid sets no align-items, so stretch applies and a short card is pulled to
   its partner's height — a box with content at the top and dead space at the
   bottom, which is exactly what an unfilled slot looks like. Size to content
   instead; the rag is honest and content-shaped.
   Deliberately NOT on .grid--3: the three price tiers must stay comparable at
   a glance, and ragged tier cards obstruct that comparison. Those stay
   stretched. */
@media (min-width: 37.5rem) { .grid--2 { align-items: start; } }
@media (min-width: 56.25rem) {
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* ------------------------------------------------- Split feature + checks -- */
/* The two sections the rebuild deleted. Text one side, screen the other, and
   they alternate so the eye crosses the page instead of running down one rail. */
.split-feature { align-items: center; gap: var(--sp-8); }
.split-feature__body { display: grid; gap: var(--sp-5); justify-items: start; }
@media (min-width: 37.5rem) {
  .split-feature--reverse .split-feature__body { order: 2; }
  .split-feature--reverse .split-feature__art  { order: 1; }
}

/* The check badge. Cian claro ground with --fg-on-accent is 12.15:1, and the
   glyph is a ::before so the tick never lands in the accessible name — a
   screen reader reads the benefit, not "check mark, check mark, check mark". */
.check-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.check-list li {
  display: grid;
  grid-template-columns: 1.5rem 1fr;
  gap: var(--sp-3);
  align-items: start;
  color: var(--fg-secondary);
}
.check-list li::before {
  content: "\2713";
  content: "\2713" / "";
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem; height: 1.5rem;
  border-radius: var(--r-full);
  background: var(--bg-accent-soft);
  color: var(--fg-on-accent);
  font-size: var(--fs-caption);
  font-weight: 700;
}

/* --------------------------------------------------------- Pre-release -- */
/* Sits under the sticky nav on every page. --bg-raised with a hairline under
   it rather than a warning colour: this is standing context, not an alert, and
   --sem-danger on twelve pages would read as a site-wide fault. --fs-body-sm,
   not --fs-caption: tokens.css calls 14px THE FLOOR for any sentence and this
   is a sentence that exists to be read. 7.58:1 on Hielo. */
.prerelease {
  background: var(--bg-raised);
  border-bottom: 1px solid var(--border-hairline);
}
.prerelease p {
  padding-block: var(--sp-3);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body);
  color: var(--fg-secondary);
}

/* ------------------------------------------------------------- Hero art -- */
/* The recovered Monterrey illustration. Sized by its own 580x460 viewBox so it
   never crops — the whole complaint about the screenshots was arbitrary
   clipping, and an illustration has no safe crop either. */
.hero__art { position: relative; width: 100%; max-width: 580px; margin: var(--sp-8) auto 0; }
@media (min-width: 56.25rem) { .hero__art { margin: 0; justify-self: center; } }
.hero__illus { display: block; width: 100%; height: auto; border-radius: var(--r-2xl); }

/* ----------------------------------------------------------------- Steps -- */
/* Numbered because these ARE a sequence — the order carries information the
   reader needs. Do not reuse this pattern for a non-sequence. */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-6); counter-reset: step; }
/* 2.5rem, not 2rem: at 32px these counters read as a bullet rather than as a
   design decision. Not controls, so no target-size implication.

   Two rows now, because each step carries the screen it describes: the shot
   spans both columns on row 1, then the counter and the text sit side by side
   on row 2. The screenshot is never cropped — full 1284x2778, height auto. */
.step {
  counter-increment: step;
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  grid-template-areas: "shot shot" "num  text";
  gap: var(--sp-4);
  align-items: start;
}
.step__shot { grid-area: shot; }
.step__text { grid-area: text; }
/* One phone frame for every bare capture on a light ground. The child
   combinator is deliberate: .rx-schematic inside .step__shot has a wordmark
   <img> that must not get a bezel. The 340px cap stays: .grid--3 is one column
   below 900px, and an uncapped phone at 768px is 1,398px tall. */
.split-feature__art > img,
.step__shot > img {
  display: block;
  width: 100%;
  max-width: 340px;
  height: auto;
  margin-inline: auto;
  border: var(--bezel-w) solid var(--c-azul-noche);
  border-radius: var(--bezel-r);
  box-shadow: var(--elev-3);
}
/* On Azul noche a navy bezel is invisible, so the dark panels take the
   dark-ground twin. */
.showcase .figure__frame img {
  border: 6px solid var(--border-control-inv);
  border-radius: 30px;
}

.step::before {
  grid-area: num;
  content: counter(step);
  content: counter(step) / "";
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem; height: 2.5rem;
  border-radius: var(--r-full);
  background: var(--bg-accent-soft);
  color: var(--fg-on-accent);
  font-size: var(--fs-body);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ----------------------------------------------------------------- Forms -- */
.field { display: grid; gap: var(--sp-2); }
.field__label { font-size: var(--fs-body-sm); font-weight: 600; color: var(--fg-primary); }

.input {
  width: 100%;
  min-height: 44px;
  padding: var(--sp-3) var(--sp-4);
  font-family: inherit;
  font-size: var(--fs-body);
  color: var(--fg-primary);
  background: var(--bg-canvas);
  border: 1.5px solid var(--border-control);  /* 4.75:1 — the whole point */
  border-radius: var(--r-md);
}
.input::placeholder { color: var(--fg-muted); opacity: 1; }  /* 4.75:1, not the 3.28:1 currently live */
.input:hover { border-color: var(--border-strong); }

.input--on-inverse {
  background: rgba(237, 243, 249, 0.06);
  color: var(--fg-on-inverse);
  border-color: var(--border-control-inv);   /* 4.45:1 — replaces the live 1.44:1 */
}
.input--on-inverse::placeholder { color: var(--fg-on-inverse-2); opacity: 1; }

/* --------------------------------------------------------------- Banners -- */
.banner {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body);
}
.banner--info   { background: var(--bg-raised); color: var(--fg-secondary); }
.banner--danger {
  background: var(--sem-danger-bg);
  color: var(--sem-danger-ink);
  border: 1px solid var(--sem-danger-border);
}
.banner--danger strong { color: var(--sem-danger-ink); }

/* The 911 line. ONE rendering, site-wide — the current pages carry three
   different versions of this sentence (tú, usted, and REMEDIO in caps).
   Minimum 14px: it is a sentence, not a label. */
.emergency {
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--fg-secondary);
}
.section--inverse .emergency, .footer .emergency { color: var(--fg-on-inverse-2); }

/* ----------------------------------------------------------------- Chips -- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--r-full);
  background: var(--bg-accent-soft);
  color: var(--fg-on-accent);
  font-size: var(--fs-caption);
  font-weight: 600;
}
/* The status chip the old hero carried: a live dot plus the coverage line.
   Purely a restyle of home.kicker — the string is untouched, and the dot is a
   ::before, not typed. Cian claro ground with --fg-on-accent is 12.15:1. */
.chip--status { background: var(--c-cian-claro); color: var(--fg-on-accent); font-weight: 700; }
.chip--status::before {
  content: "";
  width: 0.5rem; height: 0.5rem;
  border-radius: var(--r-full);
  background: var(--accent);
  flex: 0 0 auto;
}

/* Audience label on the home split-features. Larger than .overline because it
   is the first thing that tells you whether the section is addressed to you,
   and it names the page its button goes to. */
.chip--audience {
  font-size: var(--fs-body-sm);
  padding: var(--sp-2) var(--sp-4);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--ls-overline);
}

.chip--outline { background: transparent; border: 1px solid var(--border-control); color: var(--fg-secondary); }

/* ----------------------------------------------------- Price / legal stamp -- */
/* --r-xs at 4px is deliberate here and nowhere else: a sharper corner does
   semantic work, reading as a document rather than an app surface.
   Treat as locked: changes to this element go through review. */
.stamp {
  display: inline-block;
  padding: var(--sp-4) var(--sp-5);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--r-xs);
  background: var(--bg-canvas);
}
.stamp__label { font-size: var(--fs-overline); letter-spacing: var(--ls-overline); text-transform: uppercase; font-weight: 700; color: var(--fg-secondary); }
.stamp__value { font-size: var(--fs-h2); font-weight: 800; color: var(--fg-primary); font-variant-numeric: tabular-nums; }
/* The total-price note is a sentence and never drops below the 14px floor. */
.stamp__note  { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--fg-secondary); }

/* --------------------------------------------------------------- Figures -- */
/* Screenshots come from `originales 6.9/`, which have no burned-in overlay.
   Overlay text baked into a PNG is text-as-image (SC 1.4.5). */
.figure { margin: 0; display: grid; gap: var(--sp-3); justify-items: center; }
.figure__frame {
  border-radius: var(--r-xl);
  overflow: hidden;
  box-shadow: var(--elev-2);
  background: var(--bg-raised);
  max-width: 320px;
}
.figure figcaption {
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--fg-secondary);
  text-align: center;
  max-width: 34ch;
}

/* ----------------------------------------------------------------- Table -- */
.table-wrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-body-sm); }
.table th, .table td { padding: var(--sp-3) var(--sp-4); text-align: left; border-bottom: 1px solid var(--border-hairline); }
.table th { font-weight: 700; color: var(--fg-primary); }
.table td { color: var(--fg-secondary); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- Accordion */
/* A real accordion as of 2026-09-11, on the founder's call. This block used to
   read "NOT an accordion, and deliberately not becoming one — the answers stay
   open, awareness beats convenience." That decision is reversed, and the reason
   it was wrong is worth keeping: eighteen permanently-open answers put 857
   words of FAQ across two pages, and the site read as long rather than as
   informative. The complaint was never word count. Nothing collapsed.

   <details>/<summary>, not a button plus JS: disclosure semantics,
   aria-expanded, keyboard operation, and the browser's own find-in-page
   expansion all come free, and js/ stays empty of accordion code. Before this,
   the block carried a full button reset wired to nothing — the affordance lied.
   Now it tells the truth.

   The <h3> stays, INSIDE the <summary>. The content model permits one heading
   element there, and it keeps all eighteen questions in the document outline —
   a screen-reader user's primary navigation on a long FAQ is the heading list
   (VoiceOver rotor, H key in NVDA/JAWS).

   The 75rem two-column row is gone with it. That rule existed to fill the empty
   right-hand rectangle beside a measure-capped answer; a closed row is one line
   of text at full width and has no such rectangle. It is also the rule that
   collapsed the question rail to 78px across the whole 900–1100 band on
   2026-09-10. Deleting it retires that defect class rather than re-tuning it. */
.accordion { border-top: 1px solid var(--border-hairline); }
.accordion__item {
  border-bottom: 1px solid var(--border-hairline);
  /* An anchor jump would otherwise land the target under the sticky header. */
  scroll-margin-top: calc(var(--nav-h) + var(--sp-5));
}

.accordion__q {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) 0;
  cursor: pointer;
  list-style: none;   /* the UA disclosure triangle, Chrome and Firefox */
}
.accordion__q::-webkit-details-marker { display: none; }   /* and Safari */
.accordion__q > h3 {
  font-size: var(--fs-h4);
  line-height: var(--lh-h4);
  letter-spacing: var(--ls-h4);
  font-weight: 600;
}
.accordion__q:hover > h3 { color: var(--fg-link); }

/* Drawn, not typed: a glyph would inherit the heading's weight and optical
   size and read as punctuation. Rotation is transitioned, and the global
   reduced-motion block already zeroes transition-duration. */
.accordion__q::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid var(--fg-secondary);
  border-bottom: 2px solid var(--fg-secondary);
  transform: translateY(-0.125rem) rotate(45deg);
  transition: transform var(--dur-base) var(--ease-out);
}
.accordion__item[open] > .accordion__q::after {
  transform: translateY(0.125rem) rotate(-135deg);
}

.accordion__a { padding-bottom: var(--sp-5); max-width: var(--measure); }
.accordion__a p + p { margin-top: var(--sp-3); }

/* ------------------------------------------------------------- Q&A index -- */
/* ------------------------------------------------- Contact bubble pair -- */
/* "2 boubles. A outer one ( Pacientes (ayuda@remedio.mx)) and a inner one.
   the inner one dark blue, outer one white. Keep it the saame format. not a
   list." — founder, 2026-09-11, after I twice restructured this block into a
   <ul> rail. It stays the four lines in .grid--2. Only the shape changes.

   Outer: Blanco on the Azul noche page, 17.79:1, so the capsule reads as an
   object. Label ink Azul noche on Blanco, 17.79:1.
   Inner: Azul noche on the Blanco outer, 17.79:1 — it reads as a distinct
   object inside the capsule. Address ink Hielo on Azul noche, 15.92:1.

   width: fit-content because a <p> is a block-level grid item and would
   otherwise stretch the capsule across its whole column.

   The inner bubble holds the 44px target rather than the outer, because the
   inner IS the link — the outer is not clickable. */
.contact-bubble {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  width: fit-content;
  max-width: 100%;
  /* wrap + a breakable inner: at 375 the container is 327px and the longest
     route (Privacidad: privacidad@remedio.mx) wants 355, so the capsule pushed
     4px past the viewport. The inner bubble is inline-flex and would not shrink
     below its content on its own. */
  flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-5);
  border-radius: var(--r-full);
  background: var(--c-blanco);
  color: var(--c-azul-noche);
  font-size: var(--fs-body-sm);
  font-weight: 700;
}
.contact-bubble a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-full);
  max-width: 100%;
  overflow-wrap: anywhere;
  background: var(--c-azul-noche);
  /* --c-hielo, NOT --fg-on-inverse. The bubble's fill is a raw primitive, so
     its ink must be one too: in the dark theme --fg-on-inverse resolves to
     Azul noche, which put dark ink on this dark bubble at 1:1 — invisible.
     Hielo on Azul noche is 15.92:1 and holds in either theme. */
  color: var(--c-hielo);
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--dur-base) var(--ease-out);
}
.contact-bubble a:hover { background: var(--c-azul-medio); }

/* Footer bits that would otherwise be inline styles. The whole point of the
   token layer is that nothing needs a style= attribute; these three exist
   because the footer has one entity line, one link-shaped button and one
   copyright line, and each was briefly inlined during the migration. */
.footer__entity    { border: 0; margin-top: var(--sp-4); padding: 0; }
.footer__copyright { margin-top: var(--sp-3); }
.footer__linkbtn {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}
.footer__linkbtn:hover { color: var(--accent); }

/* ------------------------------------------------- Internal rhythm ------- */
/* base.css resets h1–h6 and p to margin:0. That is right for a reset and
   wrong for every component that stacks a heading on a body line: .card,
   .step and .stamp all rendered their title welded to their text, line-box
   touching line-box, on twenty-one instances across twelve pages. .prose was
   the only place in the stylesheet that ever re-established the spacing the
   reset removed. One rule, not twenty-one. */
.card > * + *,
.step > div > * + * { margin-top: var(--sp-3); }

/* The stamp is a document, not a card: label and value belong together, the
   note belongs slightly apart. Specificity is deliberate — the paired
   selectors are (0,0,2,0) and outrank the (0,0,1,0) sweep above, so nothing
   here needs !important. */
.stamp > * + *                { margin-top: var(--sp-1); }
.stamp__label + .stamp__value { margin-top: var(--sp-2); }
.stamp__value + .stamp__note  { margin-top: var(--sp-3); }
.card .stamp__value           { margin-top: var(--sp-4); }

/* -------------------------------------------------------- Showcase ------- */
/* The app IS the product and these screenshots are the only real visual
   asset the site owns. Live, each renders at 320px in a frame whose only
   separation from the page is --elev-2 at 6% alpha — and they are
   light-ground images on --bg-canvas, so the frame edge is ~1.05:1 and
   effectively absent. The frame is not too small so much as ungrounded.
   .showcase gives it a dark ground: the same image separates from #08182E
   at roughly 17:1 by its own content, which is why this panel carries no
   border and no shadow. DESIGN.md §7 — on dark grounds, elevation is
   surface lightness, not shadow. */
.showcase {
  background: var(--bg-inverse);
  display: grid;
  gap: var(--sp-5);
  justify-items: center;
  /* Full-bleed below --bp-sm. The panel's padding would otherwise cost the
     frame ~50px of width on a 360px phone, i.e. the dark ground would make
     the screenshot SMALLER than it is today. Only reachable while
     .container is still a plain block — .hero--split does not become a
     grid until 56.25rem — so the negative margin cannot escape a track. */
  margin-inline: calc(var(--gutter) * -1);
  padding: var(--sp-5) var(--sp-4);
  border-radius: 0;
}

/* Frames render the whole screenshot. This used to be `aspect-ratio: 1284/1900`
   with `object-fit: cover`, which cut 22% off the bottom of every frame at
   render time — on top of whatever the PNG had already lost. It clipped the
   /preguntas-era calendar mid-row and the receta mid-word, which is what the
   founder saw on 2026-09-11.

   Founder, 2026-09-11: "look at the iphone silhouette. screenshot actually
   shows it. dont know why you removed part of it." The status bar and the
   Dynamic Island ARE the silhouette — cropping them is what made these read
   as flat rectangles that then needed a drawn bezel to look like phones.
   So: no crop at all. All fifteen derivatives are re-exported whole from
   `SET FINAL ASC/`, 1284x2778, mapped to source by pixel alignment rather
   than by filename. Every frame is the full screen. They cannot rag, and the
   phone chrome comes from the capture instead of from CSS. */
.showcase .figure       { width: 100%; }
.showcase .figure__frame {
  width: 100%;
  max-width: 420px;
  border-radius: var(--r-xl);   /* 20 — DESIGN.md §7: "screenshot masks" */
  background: transparent;
  box-shadow: none;             /* invisible on Azul noche — see above */
}
.showcase .figure__frame img {
  display: block;
  width: 100%;
  height: auto;
}

/* MANDATORY, not cosmetic. .figure figcaption is --fg-secondary #475569,
   which on --bg-inverse #08182E measures 2.35:1 and fails SC 1.4.3
   outright. --fg-on-inverse-2 #CBD5E1 on #08182E is 11.92:1 (DESIGN.md §3).
   Do not ship the panel without this line. */
.showcase figcaption { color: var(--fg-on-inverse-2); }

/* Two or three frames on one panel. */
.showcase--row { gap: var(--sp-5); }

@media (min-width: 37.5rem) {
  .showcase {
    margin-inline: 0;
    border-radius: var(--r-2xl);  /* 28 — DESIGN.md §7 defines this radius
                                     for exactly one thing: the hero card */
    padding: var(--sp-7);
  }
  /* A single frame on a full-width panel leaves a 1200px dark slab around a
     420px object. Cap it. In the hero the grid column already caps it, so
     --solo is only for doctores and any future single-frame section. */
  .showcase--solo { max-width: 34rem; margin-inline: auto; }
  .showcase--row {
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    align-items: start;
    gap: var(--sp-6);
  }
  .showcase--row .figure__frame { max-width: 300px; }
}

@media (min-width: 56.25rem) { .showcase { padding: var(--sp-8); } }

/* ------------------------------------------------------------ Band ------- */
/* Every inverse section on the site is one left-aligned column of two or
   three short lines inside --section-y-loose (8rem) spanning the full 75rem
   container. On a 1440px display the index coverage band is roughly
   1200 x 400 px carrying about 240 characters, all of it at the left edge.
   That is not a metaphor for empty. .band puts the argument on the left at
   a readable measure and one hard fact on the right, so the band holds two
   objects and earns its height. */
.band { display: grid; gap: var(--sp-7); align-items: start; }
.band__lede { max-width: 46ch; }
.band__lede .sec-head { max-width: none; margin-bottom: 0; }
.band__fact { display: grid; gap: var(--sp-3); justify-items: start; }
.band__fact-value {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  font-weight: 700;
  color: var(--fg-primary);
}

@media (min-width: 56.25rem) {
  .band { grid-template-columns: 1.1fr 0.9fr; gap: var(--sp-9); }
}

/* ------------------------------ Inverse-band ink re-assertion ------------ */
/* SYSTEMIC, and worth reading even if you skip the rest. base.css:128-132
   recolours every descendant p and h1–h4 inside .section--inverse. Those
   selectors are (0,0,1,1) and therefore outrank EVERY single-class
   component rule, which is (0,0,1,0). Any component that brings its own
   ground into an inverse band silently loses its ink to the band.
   Concretely: <p class="chip"> in an inverse band renders --fg-on-inverse-2
   #CBD5E1 on --bg-accent-soft #9FE0EC = 1.01:1 — invisible. This is not a
   hypothetical; it is what would have shipped tonight without these four
   lines. Two classes beat one class plus one element, so `.section--inverse
   .chip` is sufficient. */
.section--inverse .chip            { color: var(--fg-on-accent); }   /* #08182E on #9FE0EC = 12.15:1 */
.section--inverse .banner--info    { color: var(--fg-secondary); }   /* #475569 on #EDF3F9 = 6.78:1 */
.section--inverse .stamp p         { color: var(--fg-secondary); }
.section--inverse .stamp__value    { color: var(--fg-primary); }
.section--inverse p.band__fact-value { color: var(--fg-on-inverse); } /* #EDF3F9 on #08182E = 15.92:1 */

/* --------------------------------------------- Cards on a raised band ---- */
/* A white .card on --bg-raised is 1.12:1 by fill and its hairline is 1.10:1
   against that band — DESIGN.md §4 measures both. Four cards nobody can see
   is four cards' worth of "empty". .card--lifted already exists and is
   unused; on a Hielo band --elev-2 at 6% alpha is still marginal, so raise
   it to --elev-3 (10%) for exactly this case. --elev-3 is declared in
   tokens.css and referenced by nothing today. */
.section--raised .card--lifted { box-shadow: var(--elev-3); }

/* ------------------------------------------- Tier price in a card ------- */
/* .stamp__value is --fs-h2 (up to 38px), which is right for the single
   homepage stamp on a full-width block and wrong inside a three-up tier
   card ~230px wide. With the "desde" prefix added 2026-09-10 the string
   is "desde $1,256.55 MXN" and it wraps, stranding the word "desde"
   alone on a line above the number — seen rendered, not inferred.
   The qualifier must never read larger than, or separate from, the
   figure it qualifies. */
.card .stamp__value {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  text-wrap: nowrap;
}

/* ===== pages.css ===== */
/* ==========================================================================
   pages.css — page-specific layout only. Anything reused twice belongs in
   components.css instead.
   ========================================================================== */

/* ------------------------------------------------------------------ Hero -- */
.hero { padding-block: var(--sp-9) var(--section-y); }
.hero__kicker { margin-bottom: var(--sp-4); }
.hero__title  { margin-bottom: var(--sp-5); max-width: 18ch; }
.hero__sub    { max-width: 54ch; margin-bottom: var(--sp-4); }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-6); }

/* The attribution line sits under every hero. Treat as locked: changes here
   go through review. Never below the 14px floor. */
.hero__attribution {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border-hairline);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--fg-secondary);
  max-width: 58ch;
}

@media (min-width: 56.25rem) {
  /* 6rem bottom + the next section's 5rem top left 11rem of unbroken ground
     between the attribution line and the first <h2> on every page. The hero
     always abuts a section carrying a different ground, and the ground change
     is the separator — so the seam value, not the loose one. Applied
     unconditionally rather than via :has(+ .section--raised): one line, six
     pages, no modifier anyone can forget on a new page. */
  .hero { padding-block: var(--sp-11) var(--section-y-seam); }
  /* The right column must hold a 420px frame plus --sp-8 of panel padding on
     each side = 516px. 0.85fr of (1120 - 48) gave ~490px, which squeezed the
     frame to ~394px — index's hero screenshot was already rendering below the
     420px it was specified at. 33rem = 528px clears it. */
  .hero--split {
    display: grid;
    grid-template-columns: 1fr minmax(0, 33rem);
    gap: var(--sp-8);
    align-items: center;
  }
}

/* --------------------------------------------------------- Section header -- */
.sec-head { max-width: var(--measure); margin-bottom: var(--sp-8); }
.sec-head__kicker { margin-bottom: var(--sp-3); }
.sec-head__title  { margin-bottom: var(--sp-4); }

/* ------------------------------------------------------------ Screenshots -- */
.shots {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
  justify-items: center;
}
@media (min-width: 37.5rem) { .shots--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 56.25rem) { .shots--3 { grid-template-columns: repeat(3, 1fr); } }

/* ----------------------------------------------------------------- Price -- */
.price-block { display: grid; gap: var(--sp-5); justify-items: start; }

/* -------------------------------------------------------------- Contact ---- */
.contact { display: grid; gap: var(--sp-5); max-width: 34rem; }

/* ============================================ 2026-10-20 polish pass == */

/* Light heroes: a Hielo glow from the top right, no new hue. Inks on Hielo:
   --fg-secondary 6.78:1, --fg-primary 15.92:1. No --fg-muted text sits in a hero. */
.hero {
  background:
    radial-gradient(56rem 28rem at 100% 0%, var(--c-hielo), transparent 70%),
    var(--bg-canvas);
}

/* Index hero, dark. The markup also carries .section--inverse, which supplies
   the inverse inks for h1–h4, p and .chip. This block adds the ground, the
   scale and the entrance. The glows are palette hexes at alpha (Cian 16%,
   Azul medio 90%). Worst text case is the Cian glow peak, about #0E3249:
   Hielo 11.95:1, Gris humo 8.99:1, Cian 5.85:1. */
.hero--inverse {
  padding-block: var(--sp-9) var(--sp-11);
  background:
    radial-gradient(48rem 32rem at 85% 15%, rgba(47, 187, 214, 0.16), transparent 65%),
    radial-gradient(40rem 28rem at 0% 100%, rgba(19, 48, 79, 0.9), transparent 70%),
    var(--c-azul-noche);
}
@media (min-width: 56.25rem) { .hero--inverse { padding-block: var(--sp-11) var(--sp-12); } }

.hero--inverse .hero__title {
  font-size: var(--fs-hero);
  line-height: var(--lh-hero);
  letter-spacing: var(--ls-hero);
  max-width: 13ch;
}
/* The one Cian word (BRAND.md Core Colors: "the headline word that carries
   emotional weight"). 7.72:1 on Azul noche. DARK GROUNDS ONLY: on white it is 2.30:1. */
.hero__accent { color: var(--accent); }
.hero--inverse .hero__attribution { border-top-color: var(--border-control-inv); }
.hero--inverse .hero__illus {
  box-shadow: 0 0 0 1px var(--border-control-inv), 0 32px 80px -24px rgba(47, 187, 214, 0.35);
}

/* Entrance, staggered. The global reduced-motion block zeroes both duration and delay. */
.hero--inverse .hero__title,
.hero--inverse .hero__sub,
.hero--inverse .hero__actions,
.hero--inverse .hero__art { animation: rise var(--dur-enter) var(--ease-out) both; }
.hero--inverse .hero__sub     { animation-delay: 80ms; }
.hero--inverse .hero__actions { animation-delay: 160ms; }
.hero--inverse .hero__art     { animation-delay: 240ms; }

/* The app's own home screen over the night city. The frame's pixels carry the
   hero-subline attribution form, and the canonical line is in the text next to
   it (LEGAL.md §Mandatory attribution line, capture rule). */
.hero__phone {
  position: absolute;
  left: var(--sp-4);
  bottom: calc(var(--sp-7) * -1);
  width: 38%;
  max-width: 13rem;
  height: auto;
  border: var(--bezel-w) solid var(--c-azul-medio);
  border-radius: var(--bezel-r);
  box-shadow: 0 24px 48px rgba(4, 14, 28, 0.55);   /* Abismo */
}
@media (min-width: 56.25rem) { .hero__phone { left: calc(var(--sp-5) * -1); } }

/* «Cómo funciona» on the index. These are a sequence, so the markup is an
   <ol>; the numerals are ::before counters and stay out of the accessible
   name. Cian on Azul noche 7.72:1. A 4.45:1 rule joins the three steps. */
.how__list { display: grid; gap: var(--sp-7); counter-reset: how; }
.how__item { counter-increment: how; padding-top: var(--sp-5); border-top: 1px solid var(--border-control-inv); }
.how__item::before {
  content: counter(how, decimal-leading-zero);
  content: counter(how, decimal-leading-zero) / "";
  display: block;
  margin-bottom: var(--sp-4);
  font-size: var(--fs-display);
  font-weight: 800;
  line-height: 1;
  letter-spacing: var(--ls-display);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.how__item > * + * { margin-top: var(--sp-3); }
@media (min-width: 56.25rem) { .how__list { grid-template-columns: repeat(3, 1fr); gap: var(--sp-8); } }

/* One colour-blocked band before the footer. Ink on Cian claro is 12.15:1, and
   the Azul noche button's edge on it is 12.15:1. Two objects, so the width is composed. */
.band-accent { background: var(--c-cian-claro); padding-block: var(--sp-9); }
.band-accent__inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-5); }
.band-accent__title { max-width: 24ch; color: var(--fg-on-accent); }

/* /nosotros founder section. Works without a photo: the name is the image. */
.founder { scroll-margin-top: var(--nav-h); }
.founder__grid { display: grid; gap: var(--sp-8); }
.founder .overline { color: var(--accent); }   /* (0,2,0) beats .section--inverse p · Cian on Azul noche 7.72:1 */
.founder__name {
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  font-weight: 800;
}
.founder__name::after {   /* the recetario's Cian rule, drawn once */
  content: "";
  display: block;
  width: 4rem;
  height: 3px;
  margin-top: var(--sp-5);
  background: var(--accent);
}
.founder__role { margin-top: var(--sp-5); }
.founder__facts { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-6); }
.founder__facts li {
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--border-control-inv);   /* 4.45:1 */
  border-radius: var(--r-lg);
  color: var(--fg-on-inverse);                    /* 15.92:1 */
  font-size: var(--fs-body-sm);
  font-weight: 600;
}
.founder__body { display: grid; gap: var(--sp-4); align-content: start; max-width: var(--measure); }
.founder__body .lead { color: var(--fg-on-inverse); }   /* 15.92:1; the other paragraphs stay Gris humo 11.92:1 */
/* Photo slot. Styles are ready, so a portrait later is one <img>. */
.founder__photo {
  display: block; width: 100%; max-width: 16rem; aspect-ratio: 4 / 5; object-fit: cover;
  margin-bottom: var(--sp-6);
  border-radius: var(--r-xl);
  border: 1px solid var(--border-control-inv);
}
@media (min-width: 56.25rem) {
  .founder__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--sp-10); align-items: start; }
}

/* /pacientes step 3. A schematic of the app's receta screen, drawn from tokens
   (DESIGN.md §10.1) in the recetario palette. It replaces a capture that showed
   a prescription-drug name (BRAND.md §Art Direction, mandatory crop). Flat bars,
   never data. It has the same ratio and frame as the two screenshots next to
   it, so the step row stays level. Decorative: the step text carries the meaning. */
.rx-schematic {
  display: flex; flex-direction: column;
  /* content-box so the ratio sits inside the bezel, exactly like the <img>
     captures beside it (their intrinsic ratio is the content box). */
  box-sizing: content-box;
  width: calc(100% - 2 * var(--bezel-w)); max-width: calc(340px - 2 * var(--bezel-w)); margin-inline: auto;
  aspect-ratio: 1284 / 2778;
  background: var(--bg-raised);
  border: var(--bezel-w) solid var(--c-azul-noche);
  border-radius: var(--bezel-r);
  box-shadow: var(--elev-3);
  overflow: hidden;
}
.rx-schematic__doc { margin: 22% 6% 0; background: var(--c-blanco); border: 1px solid var(--border-hairline); border-radius: var(--r-sm); overflow: hidden; }
.rx-schematic__head { padding: var(--sp-4); background: var(--c-azul-noche); border-bottom: 3px solid var(--c-cian); }
.rx-schematic__head img { width: 6.25rem; height: auto; }   /* 100px = the wordmark's digital minimum */
.rx-schematic__bars { display: grid; gap: var(--sp-3); padding: var(--sp-5) var(--sp-4); }
.rx-schematic__bars span { display: block; height: 0.5rem; border-radius: var(--r-full); background: var(--c-gris-linea); }
.rx-schematic__bars span:nth-child(2n) { width: 62%; }
.rx-schematic__bars span.is-strong { height: 0.875rem; width: 78%; margin-top: var(--sp-3); background: var(--c-azul-medio); }
.rx-schematic__foot { height: 2rem; background: var(--c-azul-noche); border-top: 3px solid var(--c-cian); }
