/* ===========================================================================
   Rakko · landing
   ---------------------------------------------------------------------------
   Los colores, la tipografía y las formas **no se eligen aquí**: se copian de
   `frontend/src/styles/tokens/*.css`, que es el sistema bloqueado de la app.
   Esta página y el producto tienen que leerse como el mismo objeto — es lo
   único que hace que la captura de la mitad de la página no parezca de otro
   programa.

   Lo que sí es propio de esta superficie, y va marcado donde aparece:

   - **Una escala de display más alta.** La app tope en 33px porque se lee bajo
     presión a un metro de distancia; un titular de portada a 33px es tímido.
     Los tamaños grandes son `clamp()` y solo existen aquí.
   - **Motion.** `design.md` lo prohíbe en la app y tiene razón: el KDS remonta
     tarjetas con cada evento y animar la llegada deja una pantalla de trabajo
     que nunca se queda quieta. Aquí hay **un solo momento con autor**: la
     presentación de marca al abrir (§18). Lo demás es la ola del pie (§19),
     que se mueve tan despacio que solo se nota si uno se queda mirándola, y
     las transiciones de estado de los controles. Hubo además una entrada al
     aparecer en cada sección y se quitó: la misma subida repetida doce veces
     no es un gesto, es una muletilla, y le robaba a la presentación el ser el
     único momento en que la página se mueve.

   Lo demás es el sistema tal cual, incluida la prohibición de card-in-card y
   el presupuesto de acento (≤5% del viewport).
   =========================================================================== */

/* --- Tipografía autohospedada, los mismos archivos que sirve la app. ------
   No se carga de Google Fonts por lo mismo que allá: una petición a un tercero
   que dice qué se abre y cuándo, y una página que se cae a la fuente del
   sistema si ese tercero falla. Es una fuente variable, así que son dos
   archivos por estilo y no doce. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('assets/fonts/plus-jakarta-sans-normal-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('assets/fonts/plus-jakarta-sans-normal-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ===========================================================================
   1 · Tokens
   =========================================================================== */

:root {
  /* — Superficies. Ancla cálida hue 85: la crema es de la marca. — */
  --paper: oklch(97.4% 0.009 85);
  --panel: oklch(99.3% 0.006 85);
  --sunken: oklch(95% 0.011 85);

  /* — Filetes. — */
  --rule: oklch(89.5% 0.009 85);
  --rule-strong: oklch(78% 0.012 85);

  /* — Tinta. Ancla fría hue 255: la tensión crema/navy es la identidad. — */
  --ink: oklch(22% 0.022 255);
  --ink-2: oklch(38% 0.02 255);
  --muted: oklch(50% 0.018 255);

  /* Tinta para rellenos cálidos claros (coral, ámbar). NO se invierte con el
     tema: coral y ámbar se quedan claros en los dos, así que su texto tiene que
     ser oscuro en los dos. */
  --on-warm: oklch(22% 0.022 255);

  /* — Chrome: el navy de la marca. — */
  --chrome: oklch(17.5% 0.045 258);
  --chrome-2: oklch(24% 0.042 258);
  /* Las dos capas de atrás de la ola del pie; la de delante es `--chrome`.
     Son tokens propios porque cada tema pide otra cosa: en oscuro no pueden
     ser `--chrome-2` —el papel y el chrome están a cuatro puntos y la ola
     desaparecía— y en claro no pueden ser navy: tres capas oscuras saliendo
     de golpe del crema eran el elemento más contrastado de la página, más que
     el titular que tienen encima. Aquí el agua **aclara hacia atrás** y se
     oscurece al acercarse, así que la orilla pasa del papel al navy en tres
     escalones en vez de en uno. */
  --ola-cresta: oklch(86% 0.03 245);
  --ola-medio: oklch(66% 0.04 248);

  /* El marco del teléfono. En claro es el navy de la marca, que a 17.5% ya se
     lee como negro; en oscuro se separa (ver allí). Sin canto: sobre el papel
     claro el contorno lo dibuja la sombra. */
  --marco-movil: var(--chrome);
  --marco-canto: transparent;

  /* El destello de la charola, en la presentación de marca. **No se invierte
     con el tema** y es el único que no lo hace: cae sobre el navy del dibujo,
     que tampoco cambia, así que aclararlo u oscurecerlo con el tema lo dejaría
     apagado sobre su propio fondo. */
  --destello: oklch(94% 0.012 200);
  /* El teal de la ola del logotipo, para el mar de la presentación. */
  --ola-intro: oklch(54.9% 0.094 209.1);
  /* La placa de la marca en oscuro, y por la misma razón tampoco cambia: es el
     papel **claro** para el que el logotipo está dibujado. Con el `--paper` del
     tema se volvería oscura justo cuando hace falta. */
  --placa-marca: oklch(97.4% 0.009 85);
  --on-chrome: oklch(96% 0.008 85);
  --on-chrome-dim: oklch(74% 0.02 255);

  /* — Acción: el teal del logo. — */
  --action: oklch(54.9% 0.094 209.1);
  --action-ink: oklch(100% 0 0);
  --action-hover: oklch(48.9% 0.08 209.1);
  --focus: oklch(54.9% 0.0947 209.1);
  /* El teal como **texto chico**. El de la marca da 4.35:1 sobre el papel y
     4.05 sobre el hundido de la portada, y la etiqueta de arriba del titular
     son 13 px: no llega a 4.5. Este da 5.25 sobre el hundido. En los titulares
     grandes sigue el de la marca, que ahí basta con 3:1. */
  --action-texto: oklch(48.9% 0.08 209.1);

  /* — Acento: el coral de marca como relleno sólido, con tinta blanca. — */
  --accent: oklch(56% 0.16 42);
  --accent-ink: oklch(100% 0 0);
  --accent-hover: oklch(50% 0.15 42);

  /* — Semánticos. — */
  --green: oklch(70% 0.15 152);
  --green-surface: oklch(95.5% 0.035 152);
  --green-ink: oklch(43% 0.113 152);

  --coral: oklch(76% 0.13 45);
  --coral-surface: oklch(95.5% 0.025 50);
  --coral-ink: oklch(47% 0.13 42);

  --amber: oklch(79% 0.14 75);
  --amber-surface: oklch(95.5% 0.045 85);
  --amber-ink: oklch(47% 0.105 65);

  /* — Elevación, tintada con la tinta y nunca gris neutro. — */
  --shadow-card: 0 1px 2px oklch(22% 0.022 255 / 0.04), 0 4px 14px oklch(22% 0.022 255 / 0.06);
  --shadow-float: 0 8px 24px oklch(22% 0.022 255 / 0.1);
  --shadow-overlay: 0 16px 40px oklch(22% 0.022 255 / 0.16);
  /* Propia de esta página: una captura de 1440px flotando necesita más caída
     que un modal de la app, o se lee pegada al papel. */
  --shadow-hero: 0 2px 6px oklch(22% 0.022 255 / 0.06), 0 24px 60px oklch(22% 0.022 255 / 0.16);
  --scrim: oklch(22% 0.022 255 / 0.5);

  /* — Forma: los tres radios de la app. Ni uno más. — */
  --radius-panel: 20px;
  --radius-control: 14px;
  --radius-indicator: 999px;

  /* — Espaciado: la escala de 4pt de la app, sin el multiplicador de densidad
       (aquí no hay modo `pass` ni `counter`). — */
  --space-3xs: 4px;
  --space-2xs: 8px;
  --space-xs: 12px;
  --space-sm: 16px;
  --space-md: 24px;
  --space-lg: 32px;
  --space-xl: 48px;
  --space-2xl: 64px;
  --space-3xl: 96px;
  --space-4xl: 128px;

  /* — Tipografía. Hasta `--text-hero` son los tamaños de la app; de ahí para
       arriba es escala de portada y solo existe en esta página. — */
  --font: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --text-micro: 0.694rem;
  --text-label: 0.833rem;
  --text-body: 1rem;
  --text-lead: 1.2rem;
  --text-title: 1.44rem;
  --text-display: 1.728rem;
  --text-hero: 2.074rem;
  --text-portada: clamp(2.4rem, 1.4rem + 3.6vw, 4.2rem);
  --text-seccion: clamp(1.75rem, 1.2rem + 1.9vw, 2.6rem);

  --weight-body: 400;
  --weight-medium: 500;
  --weight-semibold: 700;
  --tracking-display: -0.01em;
  --tracking-label: 0.06em;

  /* — Motion: los easings y duraciones de la app. — */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 120ms;
  --dur-normal: 200ms;
  --dur-slow: 560ms;

  --ancho: 1200px;
  /* El alto de la barra fija: lo usan ella y el ancla de las secciones, que
     tiene que caer justo por debajo. */
  --alto-barra: 72px;

  color-scheme: light;
}

/* **El tema es oscuro por defecto**, y el interruptor de la barra lo cambia a
   claro. Quien resuelve cuál toca es `tema-init.js`, antes del primer pintado,
   y lo deja siempre escrito en `data-theme`: por eso aquí hay un solo bloque de
   tokens oscuros y ninguno bajo `@media (prefers-color-scheme: dark)`. Los
   tokens de arriba son los claros porque son lo que ve quien no tiene el guion:
   sin él la página sale en claro, entera, que se lee. */

:root[data-theme='dark'] {
  color-scheme: dark;

  --paper: oklch(15% 0.018 258);
  --panel: oklch(20% 0.018 258);
  --sunken: oklch(24.5% 0.018 258);

  --rule: oklch(30% 0.016 258);
  --rule-strong: oklch(38% 0.016 258);

  --ink: oklch(94% 0.008 85);
  --ink-2: oklch(84% 0.012 255);
  --muted: oklch(70% 0.016 255);

  /* El navy de la marca en oscuro. Estuvo en 11% con 0.03 de croma: **más
     oscuro que el propio papel** (15%) y casi gris, así que las superficies
     que lo usan —«El dinero», la tarjeta de precios y el pie— se leían como
     huecos negros en vez de como la franja navy que son en claro. Ahora queda
     por encima del papel y con el croma suficiente para que se lea el tono,
     que es lo que las distingue. */
  --chrome: oklch(20% 0.05 258);
  --chrome-2: oklch(26% 0.05 258);
  --ola-cresta: oklch(27% 0.055 258);
  /* El punto medio entre la cresta y `--chrome`, escrito y no con
     `color-mix`: en claro la capa de en medio ya no es la mezcla de las otras
     dos, así que el token tiene que existir en los dos temas. */
  --ola-medio: oklch(23.5% 0.0525 258);

  /* El marco del teléfono **no** sigue al navy en oscuro. Subir `--chrome`
     para que las franjas navy se leyeran como tales lo dejó en un azul con
     croma, y en un marco eso deja de ser un teléfono: un teléfono es negro.
     Negro sobre el papel oscuro se separa por luminosidad (8% contra 15%), y
     el canto —un filete de un píxel, como el borde de metal de uno real— es
     lo que dibuja el contorno donde la sombra ya no se ve. */
  --marco-movil: oklch(8% 0.004 258);
  --marco-canto: oklch(30% 0.008 258);

  --action: oklch(74% 0.11 209.1);
  --action-ink: oklch(15% 0.018 258);
  --action-hover: oklch(80% 0.11 209.1);
  --focus: oklch(74% 0.11 209.1);
  --action-texto: oklch(74% 0.11 209.1);

  --accent: oklch(78% 0.12 45);
  --accent-ink: oklch(15% 0.018 258);
  --accent-hover: oklch(84% 0.1 50);

  --green: oklch(74% 0.145 152);
  --green-surface: oklch(30% 0.06 152);
  --green-ink: oklch(83% 0.13 152);

  --coral: oklch(78% 0.12 45);
  --coral-surface: oklch(32% 0.06 45);
  --coral-ink: oklch(84% 0.1 50);

  --amber: oklch(82% 0.13 78);
  --amber-surface: oklch(32% 0.055 78);
  --amber-ink: oklch(87% 0.12 85);

  /* El mar de la presentación, más claro: con el teal de la marca y esas
     opacidades, sobre el lienzo oscuro la franja se leía como una mancha. */
  --ola-intro: oklch(70% 0.1 209.1);

  --shadow-card: none;
  --shadow-float: 0 8px 24px oklch(0% 0 0 / 0.55);
  --shadow-overlay: 0 16px 40px oklch(0% 0 0 / 0.65);
  --shadow-hero: 0 20px 56px oklch(0% 0 0 / 0.6);
  --scrim: oklch(0% 0 0 / 0.6);
}

/* ===========================================================================
   2 · Base
   =========================================================================== */

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

html {
  scroll-behavior: smooth;
  /* Cada sección se ancla por debajo de la barra fija; sin esto el enlace de
     navegación deja el título tapado por ella. Justo el alto de la barra: el
     aire hasta el título lo pone la sección (`.seccion`), no este número. */
  scroll-padding-top: var(--alto-barra);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--text-body);
  font-weight: var(--weight-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
svg {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-display);
  line-height: 1.15;
  text-wrap: balance;
}

p {
  margin: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* El anillo de foco nunca se anima y nunca se quita: aparece instantáneo,
   igual que en la app. */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: 6px;
}

.rk-num {
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold);
}

/* Salto al contenido: lo primero que recibe el foco con teclado. */
.saltar {
  position: absolute;
  top: var(--space-2xs);
  left: var(--space-2xs);
  z-index: 100;
  padding: var(--space-2xs) var(--space-sm);
  background: var(--action);
  color: var(--action-ink);
  border-radius: var(--radius-control);
  font-weight: var(--weight-semibold);
  transform: translateY(-200%);
}
.saltar:focus-visible {
  transform: none;
}

.wrap {
  width: min(100% - 2 * var(--space-md), var(--ancho));
  margin-inline: auto;
}

/* ===========================================================================
   3 · Controles
   =========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  /* 48px de alto: objetivo táctil de la app en modo `counter`, y esta página
     se abre desde un teléfono la mitad de las veces. */
  min-height: 48px;
  padding: 0 var(--space-md);
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  font: inherit;
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.btn svg {
  width: 18px;
  height: 18px;
  flex: none;
}
.btn:active {
  transform: translateY(1px);
}

/* Primario: el coral de marca. En la app el primario es teal y el acento
   coral; aquí se invierte a propósito y es la única inversión — el teal es
   «acción dentro del producto» y quien mira esta página todavía no está
   dentro. El presupuesto de acento se respeta igual: son dos botones. */
.btn-accent {
  background: var(--accent);
  color: var(--accent-ink);
}
@media (hover: hover) {
  .btn-accent:hover {
    background: var(--accent-hover);
  }
}

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}
@media (hover: hover) {
  .btn-ghost:hover {
    background: var(--sunken);
    border-color: var(--ink-2);
  }
}

.btn-sm {
  min-height: 40px;
  padding: 0 var(--space-sm);
  font-size: var(--text-label);
}

/* ===========================================================================
   4 · Piezas compartidas
   =========================================================================== */

.marca {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
}
.marca-simbolo {
  width: 38px;
  height: 38px;
  flex: none;
  /* El PNG del logotipo viene con fondo blanco —es el mismo archivo que sirve
     la app—, así que se presenta como una placa deliberada en vez de dejar un
     cuadro blanco suelto sobre el navy. */
  background: oklch(100% 0 0);
  border-radius: var(--radius-control);
  padding: 3px;
  object-fit: contain;
}
/* Mientras corre la presentación, el símbolo de la barra no está: la marca de
   la presentación vuela a ocupar su sitio (`intro.js`) y lo enciende al
   llegar. Con los dos a la vista, el vuelo se leería como un duplicado. */
.con-intro .nav .marca-simbolo {
  opacity: 0;
  transition: opacity 160ms var(--ease-out);
}
.marca-nombre {
  font-size: var(--text-lead);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.02em;
}

/* Una sola en la página, sobre el titular de la portada: dice qué es el
   producto antes de que el titular diga qué hace. Hubo una encima de cada
   sección, y una etiqueta en todas partes deja de ser un sistema y pasa a ser
   una muletilla; los titulares de sección se sostienen solos. */
.kicker {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--action-texto);
}
.kicker::before {
  content: '';
  width: 22px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
}

.seccion {
  --seccion-aire: clamp(var(--space-2xl), 7vw, var(--space-4xl));
  padding-block: var(--seccion-aire);
  /* Al llegar desde la barra, el título queda a un respiro de ella y no a
     todo el acolchado de la sección. Ese acolchado es la separación **entre**
     secciones leyendo de corrido; sumado al ancla, dejaba más de 200 px vacíos
     encima del título en una pantalla ancha, y en «El dinero» una franja de
     navy sin nada. El margen negativo recorta el blanco del objetivo de
     desplazamiento sin tocar la maqueta. */
  scroll-margin-top: calc(var(--space-lg) - var(--seccion-aire));
}
.seccion-encabezado {
  max-width: 62ch;
  display: flex;
  flex-direction: column;
  /* Más aire encima de un título que debajo. */
  gap: var(--space-xs);
  margin-bottom: var(--space-xl);
}
.seccion-encabezado h2 {
  font-size: var(--text-seccion);
}
.seccion-encabezado p {
  color: var(--muted);
  font-size: var(--text-lead);
  line-height: 1.5;
  max-width: 58ch;
}

/* Etiqueta de estado. `--radius-indicator` está reservado a esto — nunca a un
   botón. */
.etiqueta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--radius-indicator);
  font-size: var(--text-micro);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.etiqueta-nucleo {
  background: var(--coral-surface);
  color: var(--coral-ink);
}

/* ===========================================================================
   5 · Barra de navegación
   =========================================================================== */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: oklch(from var(--paper) l c h / 0.86);
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-normal) var(--ease-out),
    background-color var(--dur-normal) var(--ease-out);
}
.nav.pegada {
  border-bottom-color: var(--rule);
}
.nav-interior {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  min-height: var(--alto-barra);
}
.nav-enlaces {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-left: auto;
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  color: var(--ink-2);
}
.nav-enlaces a {
  position: relative;
  padding-block: var(--space-2xs);
}
.nav-enlaces a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--action);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-normal) var(--ease-out);
}
@media (hover: hover) {
  .nav-enlaces a:hover::after {
    transform: scaleX(1);
  }
}
/* La sección en la que se está (`main.js`, el mismo cálculo que marca el
   cajón): el subrayado del cursor se queda puesto. */
.nav-enlaces a[aria-current] {
  color: var(--ink);
}
.nav-enlaces a[aria-current]::after {
  transform: scaleX(1);
}
.nav-acciones {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}

/* El botón del cajón. Mismo marco que el interruptor de tema, que es su
   vecino de barra; solo aparece donde los enlaces dejan de caber. */
.menu {
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}
.menu svg {
  width: 22px;
  height: 22px;
}
@media (hover: hover) {
  .menu:hover {
    background: var(--sunken);
    border-color: var(--rule-strong);
  }
}

@media (max-width: 1000px) {
  .nav-enlaces {
    display: none;
  }
  .nav-acciones {
    margin-left: auto;
  }
  .menu {
    display: inline-grid;
  }
}
@media (max-width: 560px) {
  .nav-interior {
    gap: var(--space-xs);
  }
  .nav-acciones .btn-ghost {
    display: none;
  }
  /* Menú, marca, tema y «Contactar» no caben en 327 px. El tema se muda al
     cajón, donde además cabe con su nombre. */
  :root[data-theme] .nav-acciones .tema {
    display: none;
  }
}

/* El interruptor solo existe si `tema-init.js` corrió —es quien escribe
   `data-theme`—: sin él sería un botón que no hace nada. */
.tema {
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}
:root[data-theme] .tema {
  display: inline-grid;
}
.tema svg {
  width: 19px;
  height: 19px;
}
@media (hover: hover) {
  .tema:hover {
    background: var(--sunken);
    border-color: var(--rule-strong);
  }
}
/* El sol con el tema claro puesto, la luna con el oscuro: el icono dice en
   qué tema se está. */
.tema .luna {
  display: none;
}
:root[data-theme='dark'] .tema .luna {
  display: block;
}
:root[data-theme='dark'] .tema .sol {
  display: none;
}

/* ===========================================================================
   6 · Marcos de dispositivo
   ---------------------------------------------------------------------------
   Una captura suelta sobre el papel se lee como una imagen de stock; dentro de
   un marco se lee como «esto es una pantalla». El marco es mínimo a propósito
   —sin reflejos, sin perspectiva, sin sombra de cristal—: lo que tiene que
   mirarse es la interfaz.
   =========================================================================== */

.ventana {
  border-radius: var(--radius-panel);
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-hero);
}
.ventana-barra {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: 10px var(--space-sm);
  background: var(--sunken);
  border-bottom: 1px solid var(--rule);
}
.ventana-puntos {
  display: flex;
  gap: 6px;
}
.ventana-puntos i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--rule-strong);
}
.ventana-url {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-inline: auto;
  padding: 3px 12px;
  border-radius: var(--radius-indicator);
  background: var(--panel);
  border: 1px solid var(--rule);
  color: var(--muted);
  font-size: var(--text-micro);
  letter-spacing: 0.01em;
}
.ventana-url svg {
  width: 11px;
  height: 11px;
}
.ventana img {
  width: 100%;
  height: auto;
}

.telefono {
  width: 260px;
  padding: 9px;
  border-radius: 38px;
  background: var(--marco-movil);
  box-shadow:
    0 0 0 1px var(--marco-canto),
    var(--shadow-hero);
  /* Sin barra de estado inventada: la app ya decidió que un dato falso en una
     pantalla que existe para enseñar datos verdaderos no se dibuja. */
}
.telefono img {
  width: 100%;
  height: auto;
  border-radius: 30px;
  background: var(--paper);
}

/* ===========================================================================
   7 · Portada
   =========================================================================== */

.portada {
  position: relative;
  padding-top: clamp(var(--space-xl), 6vw, var(--space-3xl));
  /* El relleno de abajo deja sitio al teléfono, que cuelga ~104px por debajo
     de la ventana. Sin ese margen el `overflow` de la portada lo cortaría. */
  padding-bottom: clamp(var(--space-2xl), 10vw, 160px);
  overflow: hidden;
}
/* La única forma decorativa de la página, y es geométrica: una banda de crema
   hundida que separa la portada del resto. No hay blobs — la app los prohíbe
   y esta página no es la excepción. */
/* La banda de detrás de la portada se desvanece en vez de terminar en un
   filete. Terminaba en seco al 68% del alto, y a esa altura la columna de texto
   todavía no ha acabado: la línea cruzaba el párrafo por la mitad («sin
   recargar y sin papelitos» quedaba partido entre dos fondos). En claro apenas
   se notaba; en oscuro, con cuatro veces más salto entre papel y hundido, era
   lo primero que se veía. */
.portada::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 68%;
  background: linear-gradient(to bottom, var(--sunken) 55%, transparent);
  z-index: -1;
}
.portada-rejilla {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: clamp(var(--space-xl), 5vw, var(--space-3xl));
  align-items: center;
}
.portada-texto {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-sm);
}
.portada h1 {
  font-size: var(--text-portada);
  line-height: 1.04;
  letter-spacing: -0.025em;
  margin-top: var(--space-2xs);
}
.portada-entrada {
  font-size: var(--text-lead);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 46ch;
}
.portada-botones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin-top: var(--space-2xs);
}

.portada-figura {
  position: relative;
  /* La ventana se sale del contenedor por la derecha en pantallas anchas: es
     lo que hace que se lea como una pantalla de verdad y no como una lámina
     recortada. */
  margin-right: clamp(-160px, -6vw, 0px);
}
/* Cuelga **por debajo** de la esquina inferior izquierda de la ventana, no
   encima de ella. Las dos posiciones obvias fallan y las dos se probaron:
   metido hacia dentro tapa el mapa del salón —la mitad de lo que esa captura
   vino a enseñar— y sacado hacia la izquierda se mete en la columna del texto
   y corta la frase de entrada. Saliendo hacia abajo no pisa ninguna de las
   dos, y el aire que necesita lo paga el relleno de la sección. */
.portada-telefono {
  position: absolute;
  left: -34px;
  bottom: -104px;
  width: 186px;
  z-index: 2;
}
@media (max-width: 1080px) {
  .portada-rejilla {
    grid-template-columns: 1fr;
  }
  .portada-figura {
    margin-right: 0;
  }
  .portada-telefono {
    left: auto;
    right: -12px;
    bottom: -32px;
    width: 148px;
  }
}
@media (max-width: 600px) {
  .portada-telefono {
    display: none;
  }
}

/* ===========================================================================
   7b · El video
   ---------------------------------------------------------------------------
   Un marco sin barra de navegador: el video ya trae sus propios dispositivos
   dentro, y meterlo en una «ventana» sería un marco dentro de otro. El fondo
   es el navy del propio video, para que las bandas de una pantalla con otra
   proporción —o el instante antes de que llegue el primer cuadro— no se lean
   como un hueco blanco.
   =========================================================================== */

.video-marco {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-panel);
  overflow: hidden;
  background: oklch(17.5% 0.045 258);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-hero);
}
.video-marco video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* La portada es un botón entero: el póster y la pastilla son un solo objetivo,
   porque en un teléfono nadie apunta a un triángulo de 40 px. */
.video-portada {
  position: absolute;
  inset: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.video-portada[hidden] {
  display: none;
}
.video-portada img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Abajo a la izquierda y no al centro: el póster es el cuadro que dice «Todo
   tu restaurante, en una sola app.», y un círculo en medio lo taparía. */
.video-boton {
  position: absolute;
  left: clamp(var(--space-sm), 3vw, var(--space-xl));
  bottom: clamp(var(--space-sm), 3vw, var(--space-xl));
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 10px var(--space-md) 10px 10px;
  border-radius: var(--radius-indicator);
  background: oklch(100% 0 0 / 0.96);
  color: oklch(22% 0.022 255);
  box-shadow: var(--shadow-overlay);
  transition: transform var(--dur-fast) var(--ease-out);
}
.video-boton-icono {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
}
.video-boton-icono svg {
  width: 22px;
  height: 22px;
  margin-left: 3px; /* el triángulo se ve centrado, no medido */
}
.video-boton-texto {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  line-height: 1.25;
}
.video-duracion {
  font-size: var(--text-label);
  font-weight: var(--weight-body);
  color: oklch(50% 0.018 255);
}
@media (hover: hover) {
  .video-portada:hover .video-boton {
    transform: translateY(-2px);
  }
}
.video-portada:focus-visible {
  outline: 3px solid var(--action);
  outline-offset: -3px;
}

/* En un teléfono en vertical se sirve el video vertical (el `media` de su
   `source` es esta misma condición), así que el marco toma su forma. El alto
   se topa para que el video y su botón quepan en la pantalla sin desplazar. */
@media (max-width: 700px) and (orientation: portrait) {
  .video-marco {
    aspect-ratio: 9 / 16;
    width: min(100%, calc(80svh * 9 / 16));
    margin-inline: auto;
  }
}

/* ===========================================================================
   9 · Un día en el restaurante
   =========================================================================== */

.dia {
  background: var(--panel);
  border-block: 1px solid var(--rule);
}
.dia-rejilla {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(var(--space-lg), 4vw, var(--space-2xl));
  align-items: start;
}
.pasos {
  display: flex;
  flex-direction: column;
}
.paso {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-sm);
  align-items: start;
  width: 100%;
  padding: var(--space-md) var(--space-sm);
  background: transparent;
  border: 0;
  border-radius: var(--radius-control);
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  position: relative;
  transition: background-color var(--dur-normal) var(--ease-out);
}
.paso + .paso {
  border-top: 1px solid var(--rule);
}
/* La barra vertical dice cuál está activo y cuánto falta: es indicador de
   estado, no decoración, y por eso puede llevar color. */
.paso::before {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 3px;
  background: var(--action);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform var(--dur-normal) var(--ease-out);
}
.paso[aria-selected='true']::before {
  transform: scaleY(1);
}
.paso[aria-selected='true'] {
  background: var(--sunken);
}
@media (hover: hover) {
  .paso:not([aria-selected='true']):hover {
    background: var(--sunken);
  }
}
.paso-numero {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-indicator);
  border: 1px solid var(--rule-strong);
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  transition: background-color var(--dur-normal) var(--ease-out),
    color var(--dur-normal) var(--ease-out), border-color var(--dur-normal) var(--ease-out);
}
.paso[aria-selected='true'] .paso-numero {
  background: var(--action);
  border-color: var(--action);
  color: var(--action-ink);
}
.paso-rol {
  display: block;
  font-size: var(--text-micro);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--muted);
}
.paso h3 {
  font-size: var(--text-lead);
  margin-top: 2px;
}
.paso p {
  color: var(--muted);
  font-size: var(--text-label);
  line-height: 1.5;
  margin-top: var(--space-3xs);
}

/* Las cuatro escenas se apilan en la misma celda y **todas cuentan para la
   altura**: la del mesero es un teléfono de 607px y la de caja una ventana de
   500px, así que sacando de la maqueta la que no se ve, el panel daba un salto
   de cien píxeles en cada paso — y como el recorrido avanza solo, el salto
   ocurre sin que nadie lo haya pedido. Las inactivas se ocultan con
   `visibility` (que conserva el sitio) y se sacan del foco con `inert`. */
.escenario {
  display: grid;
  place-items: center;
}
.escena {
  grid-area: 1 / 1;
  width: 100%;
  display: flex;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity var(--dur-normal) var(--ease-out),
    transform var(--dur-normal) var(--ease-out), visibility var(--dur-normal);
}
.escena[data-activa='true'] {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.escena .telefono {
  width: 290px;
}
@media (max-width: 900px) {
  .dia-rejilla {
    grid-template-columns: 1fr;
  }
  .escenario {
    min-height: 0;
  }
}

/* ===========================================================================
   10 · Las pantallas (carrusel)
   =========================================================================== */

.carrete {
  display: flex;
  /* Alineadas arriba: por defecto se estirarían al alto del carril y el marco
     de la más baja crecería con la imagen anclada arriba. */
  align-items: flex-start;
  gap: var(--space-md);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* Sangra fuera del contenedor para que la primera y la última no queden
     pegadas al borde y se vea que hay más a los lados. */
  padding-inline: max(var(--space-md), calc((100vw - var(--ancho)) / 2));
  margin-inline: calc(50% - 50vw);
  padding-bottom: var(--space-md);
  scrollbar-width: thin;
  scrollbar-color: var(--rule-strong) transparent;
}
.pantalla {
  flex: 0 0 auto;
  width: min(560px, 82vw);
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  background: transparent;
  border: 0;
  /* `figure` trae margen propio (1em 40px): sin anularlo el carril queda con
     separaciones que nadie eligió y que no casan con el `gap`. */
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: zoom-in;
}

/* La captura de la carta es de un teléfono (390×844) entre capturas de monitor
   (1440×900), y el carril mide lo que mida su elemento más alto: basta con que
   una se pase para que **todas las demás** queden con el hueco debajo. Dentro
   de una tarjeta de 560px esa captura se estira a 1 212px de alto y abre un
   socavón de casi mil píxeles.

   Se intentó estrecharle la tarjeta hasta cuadrar las alturas, y el arreglo
   duró hasta el teléfono: a 105px de ancho la que se pasa ya no es la imagen
   sino el **pie de texto**, que en esa columna se parte en diez renglones. La
   salida es no tocarle el ancho a la tarjeta —así el pie se lee igual que en
   las demás— y poner el teléfono sobre una plataforma con la misma altura que
   una ventana, que además se lee como lo que es: una pantalla chica al lado de
   unas grandes. */
.pantalla-movil .plataforma {
  display: grid;
  place-items: center;
  /* Los 1440×900 de la captura más los ~39px de la barra de la ventana. */
  aspect-ratio: 1440 / 939;
  background: var(--sunken);
  border: 1px solid var(--rule);
  border-radius: var(--radius-panel);
  overflow: hidden;
}
.pantalla-movil .telefono {
  width: auto;
  height: 86%;
  padding: 5px;
  border-radius: 22px;
}
.pantalla-movil .telefono img {
  width: auto;
  height: 100%;
  border-radius: 18px;
}
.pantalla .ventana,
.pantalla .plataforma {
  transition: transform var(--dur-normal) var(--ease-out);
}
@media (hover: hover) {
  .pantalla:hover .ventana,
  .pantalla:hover .plataforma {
    transform: translateY(-4px);
  }
}
.pantalla figcaption {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.pantalla b {
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
}
.pantalla span {
  font-size: var(--text-label);
  color: var(--muted);
  line-height: 1.45;
}
.carrete-ayuda {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: var(--space-sm);
  font-size: var(--text-label);
  color: var(--muted);
}
.carrete-ayuda svg {
  width: 16px;
  height: 16px;
}

/* Ampliada: es un diálogo porque mirar una captura al detalle sí necesita el
   foco protegido — y porque «atrás» y Escape tienen que cerrarla. */
.lupa {
  width: min(96vw, 1400px);
  max-height: 92vh;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius-panel);
  background: var(--panel);
  color: var(--ink);
  overflow: hidden;
  box-shadow: var(--shadow-overlay);
}
.lupa::backdrop {
  background: var(--scrim);
  backdrop-filter: blur(3px);
}
.lupa img {
  width: 100%;
  height: auto;
  display: block;
}
.lupa-pie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
  border-top: 1px solid var(--rule);
  font-size: var(--text-label);
  color: var(--muted);
}
.lupa-cerrar {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
}
.lupa-cerrar svg {
  width: 18px;
  height: 18px;
}

/* ===========================================================================
   11 · Módulos
   ---------------------------------------------------------------------------
   Lista con reglas y no once tarjetas: es lo que la app hace en Configuración
   («Long Document»), y once cajas iguales no son una estructura, son la falta
   de una.
   =========================================================================== */

.modulos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr));
  gap: 0 var(--space-2xl);
}
/* Sin icono. Once cuadros teal a la izquierda de once nombres no decían nada
   que el nombre no dijera, y pesaban más que él: la lista se leía como una
   rejilla de iconos. Lo que distingue a unos de otros es la etiqueta
   «Núcleo», y esa sí se queda. */
.modulo {
  padding-block: var(--space-md);
  border-top: 1px solid var(--rule);
}
.modulo h3 {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  flex-wrap: wrap;
  font-size: var(--text-body);
}
.modulo p {
  color: var(--muted);
  font-size: var(--text-label);
  line-height: 1.5;
  margin-top: var(--space-3xs);
}

/* ===========================================================================
   12 · El dinero
   =========================================================================== */

.dinero {
  background: var(--chrome);
  color: var(--on-chrome);
}
.dinero .seccion-encabezado h2,
.dinero h3 {
  color: var(--on-chrome);
}
/* Sobre el navy el texto secundario se tiñe del propio tono, nunca gris. */
.dinero .seccion-encabezado p,
.dinero .garantia p {
  color: var(--on-chrome-dim);
}
/* Un poco menos de aire que el resto de encabezados: las garantías de debajo
   son parte del mismo argumento. Vivía en un `style` en el marcado, que el
   CSP (`style-src 'self'`) descartaba en producción sin avisar. */
.dinero .seccion-encabezado {
  margin-bottom: var(--space-lg);
}
.dinero-rejilla {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(var(--space-xl), 5vw, var(--space-3xl));
  align-items: center;
}
.garantias {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
/* Sin icono: los tres cuadros teal sobre el navy eran la plantilla de «icono
   en recuadro sobre título», y no decían nada que el título no dijera. */
.garantia {
  padding-top: var(--space-md);
  border-top: 1px solid oklch(96% 0.008 85 / 0.16);
}
.garantia:first-child {
  border-top: 0;
  padding-top: 0;
}
.garantia h3 {
  font-size: var(--text-lead);
}
.garantia p {
  margin-top: var(--space-3xs);
  line-height: 1.55;
}
.dinero .ventana {
  border-color: oklch(96% 0.008 85 / 0.14);
}
.dinero-pie {
  margin-top: var(--space-md);
  font-size: var(--text-label);
  color: var(--on-chrome-dim);
}
@media (max-width: 900px) {
  .dinero-rejilla {
    grid-template-columns: 1fr;
  }
}

/* ===========================================================================
   13 · Lo que lo distingue
   =========================================================================== */

/* Misma gramática que los módulos: filete y aire, sin icono. Ocho iconos en
   cuadro sobre ocho títulos son la plantilla de «rejilla de funciones» que la
   página evita en todo lo demás. */
.distingue {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--space-lg) var(--space-xl);
}
.rasgo {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--rule);
}
.rasgo h3 {
  font-size: var(--text-body);
}
.rasgo p {
  color: var(--muted);
  font-size: var(--text-label);
  line-height: 1.55;
}

/* ===========================================================================
   14 · Precios
   ---------------------------------------------------------------------------
   Tres tarjetas, dos renglones de descuentos y el panel de lo que no cabe en un
   plan. El plan del centro va marcado con el teal de «acción» y no con el
   coral, que en esta página es el de los botones de contacto: dos rellenos de
   acento compitiendo en la misma vista dejan de decir cuál se pulsa.
   =========================================================================== */

.planes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-md);
  align-items: stretch;
}
.plan {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: clamp(var(--space-md), 3vw, var(--space-lg));
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-card);
}
.plan-destacado {
  border-color: var(--action);
  box-shadow: 0 0 0 1px var(--action), var(--shadow-float);
}
.plan-etiqueta {
  position: absolute;
  top: 0;
  left: clamp(var(--space-md), 3vw, var(--space-lg));
  transform: translateY(-50%);
  padding: 4px 12px;
  border-radius: var(--radius-indicator);
  background: var(--action);
  color: var(--action-ink);
  font-size: var(--text-micro);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.plan h3 {
  font-size: 1.35rem;
}
.plan-para {
  color: var(--muted);
  font-size: var(--text-label);
  line-height: 1.45;
  min-height: 2.9em; /* dos renglones: alinea los precios de las tres */
}
.plan-precio {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 6px;
  margin-top: var(--space-2xs);
}
.plan-moneda {
  font-size: var(--text-lead);
  font-weight: var(--weight-semibold);
  align-self: flex-start;
  margin-top: 0.35em;
}
.plan-cifra {
  font-size: clamp(2.6rem, 2rem + 2vw, 3.4rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
}
.plan-periodo {
  color: var(--muted);
  font-size: var(--text-label);
}
.plan-primer {
  align-self: flex-start;
  padding: 4px 12px;
  border-radius: var(--radius-indicator);
  background: var(--coral-surface);
  color: var(--coral-ink);
  font-size: var(--text-label);
}
.plan-base {
  margin-top: var(--space-xs);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--rule);
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
}
/* Básico no lleva «Todo lo de…»: su lista es la que empieza, y sin la línea
   de arriba quedaría pegada al precio. */
.plan-primer + .plan-incluye {
  margin-top: var(--space-xs);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--rule);
}
.plan-incluye {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  margin-bottom: var(--space-md);
}
.plan-incluye li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2xs);
  align-items: start;
  font-size: var(--text-label);
  line-height: 1.45;
}
.plan-incluye svg {
  width: 17px;
  height: 17px;
  margin-top: 2px;
  color: var(--action-texto);
}
/* El botón se queda al pie aunque las listas midan distinto: las tres
   tarjetas terminan en la misma línea. */
.plan .btn {
  margin-top: auto;
  justify-content: center;
}

/* Los descuentos son una nota al pie de los planes, no una sección: dos
   renglones con el mismo chip que el «Primer mes» de cada tarjeta. Fueron tres
   columnas con cifras de titular y filete encima, y competían con los precios
   —que es lo que se viene a leer— para decir algo secundario. El caso «a la
   medida» no va aquí: ya lo cuenta el panel de cotización de abajo. */
.descuentos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-xs) var(--space-xl);
  margin-block: var(--space-lg) var(--space-xl);
}
.descuento {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
}
.descuento-cifra {
  flex-shrink: 0;
  padding: 4px 12px;
  border-radius: var(--radius-indicator);
  background: var(--coral-surface);
  color: var(--coral-ink);
  font-size: var(--text-label);
  font-weight: 700;
  white-space: nowrap;
}
.descuento-texto {
  color: var(--muted);
  font-size: var(--text-body);
  line-height: 1.5;
}
.descuento-texto strong {
  color: var(--ink);
}
/* Los dos descuentos no duran lo mismo, y el color lo dice antes que el
   texto: el coral es el mismo chip del «Primer mes» de cada tarjeta —una
   promoción que se acaba— y el verde es el de lo que se queda, el descuento
   por sucursal que se cobra así todos los meses. Con el mismo chip los dos se
   leían como promociones, y el dueño de tres locales calculaba su segundo mes
   creyendo que el 25 % también vencía. */
.descuento--siempre .descuento-cifra {
  background: var(--green-surface);
  color: var(--green-ink);
}

.precio {
  background: var(--chrome);
  color: var(--on-chrome);
  border-radius: var(--radius-panel);
  padding: clamp(var(--space-lg), 5vw, var(--space-2xl));
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(var(--space-lg), 4vw, var(--space-2xl));
  align-items: center;
}
.precio-titulo {
  font-size: clamp(1.4rem, 1.1rem + 1vw, 1.9rem);
  color: var(--on-chrome);
}
.precio-entrada {
  margin-top: var(--space-sm);
  color: var(--on-chrome-dim);
  line-height: 1.55;
  max-width: 52ch;
}
.precio ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
.precio li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2xs);
  align-items: start;
  color: var(--on-chrome-dim);
  line-height: 1.5;
}
.precio li svg {
  width: 19px;
  height: 19px;
  color: oklch(74% 0.145 152);
  margin-top: 3px;
  flex: none;
}
.precio-botones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin-top: var(--space-lg);
}
@media (max-width: 880px) {
  .precio {
    grid-template-columns: 1fr;
  }
}
/* Los planes se deslizan de lado. Apilados eran tres tarjetas de ~700 px cada
   una y quien venía a comparar precios tenía que bajar dos pantallas para ver
   el tercero; puestos en un carril, el vecino asoma por los dos lados —que es
   lo que dice que hay más— y la comparación es un gesto.

   - **Cada tarjeta se centra al soltar** (`scroll-snap`) y el relleno de los
     extremos es lo que deja centrar también la primera y la última.
   - **El carril sangra hasta el borde de la pantalla**, como el de las
     pantallas (`.carrete`): así lo que asoma se corta por la pantalla y no
     por el margen.
   - **Arranca en el plan recomendado** (`main.js`), no en el primero: con el
     del centro a la vista se ven los otros dos a los lados.
   - Con `overflow-x` el eje vertical también recorta, y el rótulo «Recomendado»
     sobresale por arriba y la sombra de la tarjeta por abajo. De ahí el relleno
     con margen negativo: deja sitio a las dos cosas sin mover nada de lo que
     tiene alrededor.
   - La línea de «para quién es» recupera su alto de dos renglones: ahora las
     tres tarjetas vuelven a estar lado a lado y los precios tienen que caer en
     la misma línea. */
@media (max-width: 900px) {
  .planes {
    --ancho-plan: min(80vw, 360px);
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: var(--ancho-plan);
    gap: var(--space-sm);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    margin-inline: calc(50% - 50vw);
    padding-inline: calc((100vw - var(--ancho-plan)) / 2);
    padding-block: var(--space-md) 36px;
    margin-block: calc(-1 * var(--space-md)) -36px;
    scrollbar-width: none;
  }
  .planes::-webkit-scrollbar {
    display: none;
  }
  .plan {
    scroll-snap-align: center;
  }
  .descuentos {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ===========================================================================
   15 · Preguntas
   =========================================================================== */

/* Dos columnas como mucho. A `minmax(340px)` el contenedor de 1200 resuelve
   tres, y ocho preguntas de un renglón repartidas en tres columnas se leen
   como una rejilla de etiquetas, no como una lista que se abre. */
.preguntas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(440px, 100%), 1fr));
  gap: 0 var(--space-2xl);
}
.pregunta {
  border-top: 1px solid var(--rule);
}
.pregunta summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-block: var(--space-md);
  cursor: pointer;
  list-style: none;
  font-weight: var(--weight-semibold);
  /* Toda la fila es el objetivo: una flecha de 16px al final de la línea es la
     que se falla con el dedo. */
  min-height: 48px;
}
.pregunta summary::-webkit-details-marker {
  display: none;
}
.pregunta .mas {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: var(--radius-indicator);
  border: 1px solid var(--rule-strong);
  color: var(--muted);
  transition: transform var(--dur-normal) var(--ease-out),
    background-color var(--dur-normal) var(--ease-out), color var(--dur-normal) var(--ease-out);
}
.pregunta .mas svg {
  width: 14px;
  height: 14px;
}
.pregunta[open] .mas {
  transform: rotate(45deg);
  background: var(--action);
  border-color: var(--action);
  color: var(--action-ink);
}
.pregunta .respuesta {
  padding-bottom: var(--space-md);
  color: var(--muted);
  line-height: 1.6;
  max-width: 62ch;
}
.pregunta .respuesta a {
  color: var(--action-texto);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ===========================================================================
   16 · Contacto y pie
   =========================================================================== */

.contacto {
  text-align: center;
}
.contacto .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}
.contacto h2 {
  font-size: var(--text-seccion);
}
.contacto > .wrap > p {
  color: var(--muted);
  font-size: var(--text-lead);
  max-width: 54ch;
  line-height: 1.5;
}
.contacto-botones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2xs);
  margin-top: var(--space-2xs);
}

.pie {
  position: relative;
  background: var(--chrome);
  color: var(--on-chrome-dim);
  padding-block: var(--space-xl);
  font-size: var(--text-label);
  /* La ola se dibuja encima del borde superior y **cabe dentro del acolchado
     de la sección anterior**, que ahí es aire. Reservarle su alto entero en
     margen dejaba doscientos píxeles de crema vacía antes del navy. Este
     margen es solo la holgura para que la cresta no toque el último renglón. */
  margin-top: clamp(20px, 1.4vw, 24px);
}
.pie .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
}
.pie .marca {
  color: var(--on-chrome);
}
.pie nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  margin-left: auto;
}
.pie .copia {
  width: 100%;
  padding-top: var(--space-md);
  border-top: 1px solid oklch(96% 0.008 85 / 0.14);
  color: var(--on-chrome-dim);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2xs) var(--space-md);
}
/* Quién hizo Rakko: una firma, no un anuncio. Mismo tono apagado que el
   copyright y en su mismo renglón; el logotipo trae fondo negro propio, así que
   va como un ícono con esquinas en vez de flotar sobre el navy. */
.pie .autoria {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.pie .autoria img {
  border-radius: 5px;
}
/* Los documentos legales viven en la app, que es donde se aceptan al activar
   una cuenta: copiarlos aquí daría dos textos que divergen al primer cambio.
   Van en el renglón del copyright y no en la navegación de arriba, que lleva
   a secciones de esta página. */
.pie .legal {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-md);
}
.pie .legal a:hover {
  color: var(--on-chrome);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.pie a.autoria {
  color: inherit;
  text-decoration: none;
}
.pie a.autoria:hover {
  color: var(--on-chrome);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ===========================================================================
   17 · Menos movimiento
   ---------------------------------------------------------------------------
   Con `prefers-reduced-motion` la presentación no se monta (`tema-init.js`) y
   la ola del pie no se mueve (§19). Aquí se apaga lo que **desplaza**: el
   salto suave a las secciones y los pocos píxeles que suben la escena del
   recorrido y las capturas bajo el cursor. Los cambios de color y de opacidad
   se quedan: no marean a nadie y son lo que dice que un control respondió. Un
   `0.01ms` global se llevaba también esa respuesta.
   =========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .escena {
    transform: none;
  }
  .pantalla:hover .ventana,
  .pantalla:hover .plataforma {
    transform: none;
  }
}

/* ===========================================================================
   18 · Presentación de marca
   ---------------------------------------------------------------------------
   Sube un poco de mar al pie de la pantalla, **Rakko sale de él de un
   impulso** —rompe la superficie, salpica, se pasa un poco y vuelve—, se mece,
   la charola destella, la palabra se escribe, la marea se retira y la marca
   **vuela a su sitio en la barra** mientras el telón se levanta.

   Es un `loading`, no un corto: esta capa **tapa la portada mientras llega**,
   así que cada segundo que dura lo paga quien vino a leer. El relevo empieza a
   los 2.6 s y a los 3.2 s ya no queda nada. Lo que la hace más viva que su
   versión anterior no es durar más sino **tener física**: antes la marca subía
   flotando como en un ascensor y el telón se fundía; ahora sale con impulso,
   levanta agua y se va a alguna parte. Hubo también una versión con una ola
   rompiendo que cruzaba la pantalla, y se quitó por ser una película con el mar
   de protagonista: el mar tiene **un solo trabajo, explicar de dónde sale
   Rakko**, y por eso es una franja al pie que solo dura lo que dura la subida.

   **El reloj es uno.** Todas las animaciones cuelgan de `data-corriendo`, que
   pone `intro.js` en el mismo fotograma en que arranca su `REPOSO`: si
   arrancaran al montarse la capa, una carga lenta desfasaría el relevo de la
   escena. Los tiempos, de un vistazo:

       0 ms     sube el mar (450)
     320 ms     Rakko sale del agua (900) · a los ~400 salpica
    1150 ms     destello · 1250 ms se escribe la palabra (600)
    1220 ms     se mece y flota, sin fin
    2150 ms     baja el mar (420)
    2600 ms     relevo: vuelo a la barra (640) — `REPOSO` en `intro.js`

   El lienzo es **el papel de la página** (`.intro-telon`), no un panel con
   borde: el telón no descubre otra superficie, descubre la portada, que ya
   estaba debajo.
   =========================================================================== */

.intro {
  display: none;
}

.con-intro .intro {
  display: grid;
  place-items: center;
  position: fixed;
  inset: 0;
  z-index: 100;
  cursor: pointer;
  /* Tres medidas de las que cuelga el resto: el ancho del lockup, el del disco
     dentro de él —de ahí salen el tamaño y el alcance de las gotas— y el alto
     del mar, del que sale también el ancho de sus olas. */
  --escena: min(320px, 58vw);
  --disco: calc(var(--escena) * 0.645);
  --mar: clamp(170px, 30vh, 320px);
}
@supports (height: 1dvh) {
  .con-intro .intro {
    --mar: clamp(170px, 30dvh, 320px);
  }
}

.intro-telon {
  position: absolute;
  inset: 0;
  background: var(--paper);
}

/* La escena es el rectángulo del lockup: el disco arriba, la palabra debajo y
   el hueco que los separa, en las proporciones del archivo original (858/995
   del PNG). El ancho lo fija la palabra, que es la pieza más ancha. */
.intro-escena {
  position: relative;
  width: var(--escena);
  aspect-ratio: 995 / 858;
}

/* --- Las dos piezas de la marca ---------------------------------------- */

/* `.intro-marca` solo existe para el vuelo final, que le pone `intro.js`; todo
   lo demás se mueve dentro, en `.intro-flota`. Separados porque los dos
   necesitan `transform` y en un mismo elemento uno pisaría al otro. */
.intro-marca {
  position: absolute;
  top: 0;
  left: 17.75%;
  width: 64.5%;
}

/* Tres movimientos sobre **tres propiedades distintas** —`transform` la
   salida, `rotate` el balanceo, `translate` la flotación—, y eso no es un
   detalle: una animación infinita no puede seguir a una finita sobre la misma
   propiedad. Balancearse y flotar en períodos distintos es lo que hace que
   nunca repita la misma pose: es lo único que dice que la pantalla está viva
   y no colgada, que es el trabajo de un `loading`.

   `isolation` porque en oscuro la placa va detrás del dibujo con
   `z-index: -1`, y sin un contexto de apilamiento propio se iría detrás del
   telón. */
.intro-flota {
  isolation: isolate;
  opacity: 0;
}
.intro[data-corriendo='true'] .intro-flota {
  animation:
    intro-emerger 900ms 320ms both,
    intro-mecerse 2400ms 1220ms var(--ease-in-out) infinite alternate both,
    intro-flotar 1800ms 1220ms var(--ease-in-out) infinite alternate both;
}
.intro-disco {
  display: block;
  width: 100%;
  height: auto;
}

/* Se escribe de izquierda a derecha —«Rakk» y luego la «o»—, no aparece
   fundida: una palabra que se dibuja se lee como una firma. */
.intro-palabra {
  position: absolute;
  left: 0;
  bottom: 0;
  display: block;
  width: 100%;
  height: auto;
  clip-path: inset(0 100% 0 0);
}
.intro[data-corriendo='true'] .intro-palabra {
  animation: intro-escribir 600ms 1250ms var(--ease-out) both;
}
.intro-palabra--oscuro {
  display: none;
}

/* --- En oscuro: la marca sobre su placa --------------------------------- */

/* El logotipo está dibujado para el papel: el disco es navy y la cara de la
   nutria es **transparencia**, así que sobre el lienzo oscuro el disco se
   hundía y a Rakko se le iba la cara. Invertirlo —el atajo— da una nutria con
   la cara negra y los ojos encendidos. Lo que se hace es lo que la cabecera ya
   hace con su marca: ponerla sobre una placa clara, así que el dibujo se ve
   **exactamente** como en claro. Y cuadra con el vuelo: la placa aterriza
   sobre la placa blanca del símbolo de la barra.

   Se sale del disco por los cuatro lados para quedar casi cuadrada —el disco
   es más ancho que alto—, y la palabra baja lo que la placa ocupa por debajo,
   o la tocaría. */
:root[data-theme='dark'] .intro-flota::before {
  content: '';
  position: absolute;
  inset: -12% -9%;
  z-index: -1;
  background: var(--placa-marca);
  border-radius: 26%;
}
:root[data-theme='dark'] .intro-palabra {
  translate: 0 36%;
}
:root[data-theme='dark'] .intro-palabra--claro {
  display: none;
}
:root[data-theme='dark'] .intro-palabra--oscuro {
  display: block;
}

/* Sale **del agua**, no de la nada: arranca metido en el mar, al pie de la
   pantalla —se le ve teñido a través de las capas translúcidas— y sube hasta
   el centro **con impulso**: arranca rápido y frena arriba, que es lo que
   hace un cuerpo que sale a flote, no un ascensor. Sale ladeado hacia atrás y
   se endereza pasándose un poco; se pasa de largo **una vez** y vuelve. Un
   segundo rebote ya sería un muelle, y lo que se está contando es agua.

   El desplazamiento es media pantalla más un poco: deja el disco dentro de la
   franja de mar en cualquier alto. Aparece fundiéndose en el primer tramo
   porque a esa altura todavía está bajo el agua; sin el fundido se le vería el
   borde entrar en seco por debajo de la ola. */
@keyframes intro-emerger {
  from {
    opacity: 0;
    transform: translateY(calc(50vh + 90px)) rotate(-9deg) scale(0.94);
    animation-timing-function: cubic-bezier(0.2, 0.75, 0.3, 1);
  }
  14% {
    opacity: 1;
  }
  60% {
    transform: translateY(-8%) rotate(2.5deg) scale(1.02);
    animation-timing-function: cubic-bezier(0.45, 0, 0.4, 1);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Arranca inclinado y el relleno `both` lo aplica **desde el primer
   fotograma**, así que sigue el balanceo sin dar un tirón al llegar su turno.
   El ángulo es pequeño porque la palabra no se mece: con más grados el lockup
   deja de leerse como una sola pieza. */
@keyframes intro-mecerse {
  from {
    rotate: -1.8deg;
  }
  to {
    rotate: 1.8deg;
  }
}

/* La flotación arranca en cero —donde terminó la salida— y solo sube: bajar
   la metería otra vez en el hueco de la palabra. */
@keyframes intro-flotar {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 -5px;
  }
}

@keyframes intro-escribir {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

/* --- El destello de la charola ----------------------------------------- */

/* El gesto de Rakko. Cae sobre la cúpula de la charola, y la posición sale de
   **medir el PNG**: en el logotipo original (1080²) la cúpula está centrada en
   (735, 260) y el disco ocupa x 219–861, y 140–725 — o sea (80.4%, 20.5%) del
   disco. Las cifras son **del disco** y no de la escena porque el destello vive
   dentro de él. Puesto a ojo caía sobre el papel crema, y ahí un destello casi
   blanco no se ve; sobre el navy de la charola, sí. Crece, gira un cuarto de
   vuelta y se va: un brillo que se queda deja de ser un destello y pasa a ser
   una estrella pegada al logotipo. */
.intro-destello {
  position: absolute;
  left: 72.6%;
  top: 12%;
  width: 15.5%;
  aspect-ratio: 1;
  display: block;
  pointer-events: none;
  opacity: 0;
}
.intro[data-corriendo='true'] .intro-destello {
  animation: intro-destello 800ms 1150ms var(--ease-out) both;
}
.intro-destello svg {
  width: 100%;
  height: 100%;
  display: block;
  fill: var(--destello);
}

@keyframes intro-destello {
  from {
    opacity: 0;
    transform: scale(0.2) rotate(-60deg);
  }
  45% {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
  to {
    opacity: 0;
    transform: scale(0.55) rotate(35deg);
  }
}

/* --- Las gotas --------------------------------------------------------- */

/* Lo que convierte «sube» en «sale del agua». Seis gotas del teal de la ola
   que saltan **de los bordes del disco** —por donde escurre el agua al romper
   la superficie, no del centro, donde las taparía él mismo—, suben frenando y
   caen acelerando, que es lo que hace que un arco se lea como gravedad.

   Todo va en fracciones del ancho del disco (`--disco`) y no en píxeles: en un
   teléfono la marca mide dos tercios que en escritorio, y unas gotas del mismo
   tamaño serían proporcionalmente piedras. Cada una lleva su origen (`--x0`),
   su deriva (`--x`), su altura (`--y`), su tamaño (`--t`) y su retardo
   (`--d`); van aquí y no en el marcado porque el CSP no deja pasar un `style`
   en línea. */
.intro-gotas {
  position: absolute;
  left: 50%;
  bottom: calc(var(--mar) * 0.62);
  width: 0;
  height: 0;
  pointer-events: none;
}
.intro-gotas i {
  position: absolute;
  top: 0;
  left: 0;
  width: max(4px, calc(var(--disco) * var(--t)));
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: var(--ola-intro);
  opacity: 0;
}
.intro[data-corriendo='true'] .intro-gotas i {
  animation: intro-gota 560ms calc(340ms + var(--d)) both;
}
.intro-gotas i:nth-child(1) { --x0: -0.46; --x: -0.26; --y: 0.42; --t: 0.062; --d: 0ms; }
.intro-gotas i:nth-child(2) { --x0: -0.36; --x: -0.12; --y: 0.66; --t: 0.05; --d: 40ms; }
.intro-gotas i:nth-child(3) { --x0: -0.28; --x: -0.3; --y: 0.3; --t: 0.042; --d: 20ms; }
.intro-gotas i:nth-child(4) { --x0: 0.28; --x: 0.28; --y: 0.34; --t: 0.046; --d: 30ms; }
.intro-gotas i:nth-child(5) { --x0: 0.36; --x: 0.14; --y: 0.62; --t: 0.056; --d: 10ms; }
.intro-gotas i:nth-child(6) { --x0: 0.46; --x: 0.24; --y: 0.46; --t: 0.068; --d: 50ms; }

/* Terminan **por debajo** de donde salieron: vuelven al agua, y como el mar
   va después en el marcado, la ola de delante se las traga en vez de que se
   apaguen en el aire, que es lo que las hacía leerse como polvo flotando. Se
   apagan igual en el último tramo, ya dentro del agua: cuando el mar se
   retira, se quedarían al descubierto en el papel. */
@keyframes intro-gota {
  0% {
    opacity: 0;
    transform: translate(calc(var(--disco) * var(--x0)), 0) scale(0.5);
    animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1);
  }
  12% {
    opacity: 1;
  }
  45% {
    transform: translate(calc(var(--disco) * (var(--x0) + var(--x) * 0.5)), calc(var(--disco) * var(--y) * -1))
      scale(1);
    animation-timing-function: cubic-bezier(0.6, 0, 0.9, 0.4);
  }
  85% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate(calc(var(--disco) * (var(--x0) + var(--x))), calc(var(--disco) * 0.3)) scale(0.8);
  }
}

/* --- El mar ------------------------------------------------------------ */

/* Una franja de agua al pie de la pantalla, no una escena: sube, se queda
   mientras Rakko sale y se retira por debajo antes del relevo, así que lo
   último que se ve es la marca sola sobre el papel. **Cae, no se desvanece**:
   el agua baja, no se evapora.

   Son las tres capas del login (`frontend/src/styles/wave.css`) en el teal de
   la ola del logotipo, a opacidades que crecen hacia el frente: donde se
   cruzan se oscurecen solas, que es el fondo que da el agua. Va **después**
   de la escena en el marcado, así que Rakko sube por detrás y se ve teñido
   mientras la cruza. */
.intro-olas {
  position: absolute;
  inset: auto 0 0 0;
  height: var(--mar);
  overflow: hidden;
  pointer-events: none;
  transform: translateY(100%);
}
.intro[data-corriendo='true'] .intro-olas {
  animation:
    intro-mar-sube 450ms cubic-bezier(0.22, 0.8, 0.3, 1) both,
    intro-mar-baja 420ms 2150ms cubic-bezier(0.55, 0, 0.8, 0.4) forwards;
}

/* **El ancho de una ola sale del alto del mar, no de la pantalla.** Cada
   pista lleva dos copias de la curva y cada copia medía lo que la pantalla:
   en un teléfono eso metía las mismas crestas de un monitor de 1440 en 375 px
   con el mar casi igual de alto, y el agua salía en picos apretados. Ahora
   cada copia mide al menos cinco veces el alto del mar —la proporción que
   tiene en escritorio— y en un teléfono simplemente se ve un trozo de ella. */
.intro-ola {
  position: absolute;
  top: 0;
  left: 0;
  /* Por abajo se estira más allá del contenedor: el vaivén baja la capa y sin
     esto asomaría el papel bajo la curva. */
  bottom: -14px;
  display: flex;
  width: max(200%, calc(var(--mar) * 10));
}
.intro-ola > svg {
  flex: 0 0 50%;
  width: 50%;
  height: 100%;
  display: block;
  fill: var(--ola-intro);
}
.intro-ola--fondo {
  opacity: 0.18;
  --vaiven: 6px;
  animation:
    ola-deriva 9s -3s linear infinite,
    ola-vaiven 3.4s -1.1s ease-in-out infinite;
}
.intro-ola--medio {
  opacity: 0.28;
  --vaiven: 9px;
  animation:
    ola-deriva 7s -5s linear infinite reverse,
    ola-vaiven 2.7s -0.4s ease-in-out infinite;
}
.intro-ola--frente {
  opacity: 0.4;
  --vaiven: 12px;
  animation:
    ola-deriva 5s -1s linear infinite,
    ola-vaiven 2.1s -1.6s ease-in-out infinite;
}

@keyframes intro-mar-sube {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}
@keyframes intro-mar-baja {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(100%);
  }
}

/* --- Salir ------------------------------------------------------------- */

/* Aparece cuando la escena ya arrancó, para no pedir que se salte algo que
   todavía no empezó. `tabindex="-1"`: el foco no tiene que caer aquí, porque
   cualquier tecla cierra igual. */
.intro-saltar {
  position: fixed;
  right: var(--space-md);
  bottom: var(--space-md);
  padding: 8px 16px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-indicator);
  background: var(--panel);
  color: var(--muted);
  font: inherit;
  font-size: var(--text-label);
  cursor: pointer;
  opacity: 0;
  z-index: 2;
  transition: opacity var(--dur-normal) var(--ease-out), color var(--dur-fast) linear;
}
.intro[data-corriendo='true'] .intro-saltar {
  opacity: 1;
}
@media (hover: hover) {
  .intro-saltar:hover {
    color: var(--ink);
  }
}

/* El relevo. Con vuelo (`intro.js` mide la barra y mueve la marca), el telón
   se funde **mientras** la marca viaja, así que llega a una página que ya se
   ve; lo demás —palabra, agua, gotas, el botón— se va antes, rápido, para que
   lo único en movimiento sea la marca. Sin vuelo (no hay barra que medir, o el
   navegador no anima desde el guion) se funde la capa entera y ya. */
.intro[data-saliendo] {
  pointer-events: none;
}
.intro[data-saliendo] .intro-palabra,
.intro[data-saliendo] .intro-olas,
.intro[data-saliendo] .intro-gotas,
.intro[data-saliendo] .intro-saltar {
  opacity: 0;
  transition: opacity 180ms var(--ease-out);
}
.intro[data-saliendo='vuelo'] .intro-telon {
  opacity: 0;
  transition: opacity 520ms var(--ease-in-out);
}
.intro[data-saliendo='fundido'] {
  opacity: 0;
  transition: opacity 420ms var(--ease-out);
}

/* ===========================================================================
   19 · La orilla del pie
   ---------------------------------------------------------------------------
   La página entra en el navy por el agua y no por una línea recta, con el mismo
   oleaje que la pantalla de entrada de la app (`frontend/src/styles/wave.css`):
   tres capas con las mismas curvas, cada una en una pista con dos copias
   idénticas. Como la curva es periódica dentro de su viewBox, la
   segunda copia entra por la derecha exactamente donde la primera sale por la
   izquierda y el bucle no tiene costura.

   **Dos movimientos por capa, y no uno.** El desplazamiento lateral solo se lee
   como una cinta transportadora: el perfil no cambia y el ojo deja de mirarlo.
   El vaivén vertical es lo que lo vuelve agua, y como va en otro período que el
   lateral las dos nunca vuelven a la misma pose. Son `translate` y `transform`,
   propiedades distintas, así que se animan por separado en el mismo elemento.

   **El vaivén solo baja.** La capa de delante es del color exacto del pie y
   tiene que fundirse con él; si subiera, abriría una franja de papel entre la
   ola y el pie. Bajando, lo que se sale queda debajo del borde y el contenedor
   lo recorta.

   Aquí va más despacio que en el login: allá es el fondo de una pantalla vacía,
   aquí es el borde de una página que se está leyendo, y un pie que se mueve
   rápido tira del ojo lejos del último botón.
   =========================================================================== */

.pie-olas {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  /* El alto incluye el aire de encima de la cresta más alta (un tercio del
     viewBox), que es transparente: cabe en el acolchado de la sección anterior
     sin tapar ni un renglón. En un teléfono no baja de 96 px: a 72 la orilla
     era una franja de ondas de diez píxeles, más costura que agua. */
  --alto: clamp(96px, 10vw, 140px);
  height: var(--alto);
  overflow: hidden;
  pointer-events: none;
}

/* **El ancho de una ola sale de su alto, no de la pantalla** —la misma regla
   que el mar de la presentación—. Cada copia de la curva medía el ancho de la
   pantalla, así que en un teléfono las cinco crestas de la capa de delante
   cabían en 375 px y la orilla salía aplastada en picos. Ahora cada copia
   mide al menos ocho veces el alto —en un monitor de 1440 la proporción es
   diez, y ahí manda el ancho de la pantalla— y el teléfono ve un trozo de la
   misma ola, con una cresta entera a la vista. */
.pie-ola {
  position: absolute;
  inset: 0 auto 0 0;
  display: flex;
  width: max(200%, calc(var(--alto) * 16));
}
.pie-ola > svg {
  flex: 0 0 50%;
  width: 50%;
  height: 100%;
  display: block;
}

/* De atrás hacia delante se oscurece hasta el color del pie: el agua gana
   fondo al acercarse. Los tres tonos salen de tokens (ver `--ola-cresta`),
   porque en claro la capa de atrás es pálida y en oscuro es navy. */
.pie-ola--fondo > svg {
  fill: var(--ola-cresta);
}
.pie-ola--medio > svg {
  fill: var(--ola-medio);
}
.pie-ola--frente > svg {
  fill: var(--chrome);
}

@media (prefers-reduced-motion: no-preference) {
  .pie-ola {
    will-change: translate, transform;
  }
  /* La amplitud crece hacia el frente, que es el mismo paralaje que dan las
     tres velocidades: sin eso las tres subirían y bajarían como un bloque, y
     eso delata que son tres dibujos y no agua. */
  .pie-ola--fondo {
    --vaiven: 5px;
    animation:
      ola-deriva 34s linear infinite,
      ola-vaiven 15s ease-in-out infinite;
  }
  .pie-ola--medio {
    --vaiven: 7px;
    animation:
      ola-deriva 23s linear infinite reverse,
      ola-vaiven 11s ease-in-out infinite;
  }
  .pie-ola--frente {
    --vaiven: 9px;
    animation:
      ola-deriva 16s linear infinite,
      ola-vaiven 8s ease-in-out infinite;
  }
}

/* Compartidas con la presentación de marca, que usa el mismo oleaje. */
@keyframes ola-deriva {
  from {
    translate: 0 0;
  }
  to {
    translate: -50% 0;
  }
}

@keyframes ola-vaiven {
  0%,
  100% {
    transform: translate3d(0, 0, 0);
  }
  50% {
    transform: translate3d(0, var(--vaiven, 8px), 0);
  }
}

/* ===========================================================================
   20 · El cajón de secciones
   ---------------------------------------------------------------------------
   El índice de la página en un teléfono: sale por la izquierda, marca la
   sección en la que se está y lleva las dos salidas de siempre. Al pie, el
   mismo mar del pie de la página —tres capas, en su misma gama— con **Rakko
   flotando en él**: sale del agua al abrir y desde ahí se mece. Es lo que hace
   que este menú no sea el de cualquier otra página, y es la marca haciendo lo
   que el logotipo dice que hace, que es flotar.

   Es un `<dialog>` modal, así que el fondo queda inerte y el foco atrapado.
   La entrada y la salida son CSS (`@starting-style` y `allow-discrete`): donde
   el navegador no lo sabe animar, el cajón aparece y se va sin más.
   =========================================================================== */

.cajon {
  position: fixed;
  inset: 0 auto 0 0;
  width: min(86vw, 340px);
  height: 100vh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  border-right: 1px solid var(--rule);
  border-radius: 0 var(--radius-panel) var(--radius-panel) 0;
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow-overlay);
  overflow: hidden;
  flex-direction: column;
  /* Cerrado —y camino de cerrarse—: fuera de la pantalla por la izquierda. */
  transform: translateX(-100%);
}
@supports (height: 1dvh) {
  .cajon {
    height: 100dvh;
  }
}
.cajon[open] {
  display: flex;
  transform: none;
}
.cajon::backdrop {
  background: var(--scrim);
  backdrop-filter: blur(3px);
  opacity: 0;
}
.cajon[open]::backdrop {
  opacity: 1;
}

/* Con el cajón abierto la página de detrás no se desplaza: el dedo que
   arrastra dentro del cajón y llega al final seguiría moviendo el contenido. */
:root:has(.cajon[open]) {
  overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  /* Sale rápido y frena (abrir), se va acelerando y más corto (cerrar): la
     transición que manda es la del estado de destino. */
  .cajon {
    transition:
      transform 220ms cubic-bezier(0.55, 0, 0.8, 0.4),
      overlay 220ms allow-discrete,
      display 220ms allow-discrete;
  }
  .cajon[open] {
    transition:
      transform 380ms var(--ease-out),
      overlay 380ms allow-discrete,
      display 380ms allow-discrete;
  }
  .cajon::backdrop {
    transition:
      opacity 220ms var(--ease-out),
      overlay 220ms allow-discrete,
      display 220ms allow-discrete;
  }
  @starting-style {
    .cajon[open] {
      transform: translateX(-100%);
    }
    .cajon[open]::backdrop {
      opacity: 0;
    }
  }
}

.cajon-cabeza {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  min-height: var(--alto-barra);
  padding: 0 var(--space-sm) 0 var(--space-md);
  border-bottom: 1px solid var(--rule);
}
.cajon-cerrar {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.cajon-cerrar svg {
  width: 20px;
  height: 20px;
}
@media (hover: hover) {
  .cajon-cerrar:hover {
    background: var(--sunken);
  }
}

/* Lo que se desplaza si el teléfono es bajo. El mar se queda fuera, fijo al
   pie: si se fuera con la lista, en un teléfono chico no se vería nunca. */
.cajon-cuerpo {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-strong) transparent;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-xs) var(--space-md);
}

.cajon-secciones {
  display: flex;
  flex-direction: column;
}
.cajon-secciones a {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 44px;
  padding: 0 var(--space-xs);
  border-radius: var(--radius-control);
  font-weight: var(--weight-medium);
  color: var(--ink-2);
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
@media (hover: hover) {
  .cajon-secciones a:hover {
    background: var(--sunken);
    color: var(--ink);
  }
}
/* La ola ocupa su sitio aunque esté apagada: si apareciera empujando el texto,
   la lista entera bailaría al pasar de una sección a otra. */
.cajon-ola {
  width: 20px;
  height: 10px;
  flex: none;
  fill: none;
  stroke: var(--action);
  stroke-width: 2.2;
  stroke-linecap: round;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity var(--dur-normal) var(--ease-out), transform var(--dur-normal) var(--ease-out);
}
.cajon-secciones a[aria-current] {
  background: var(--sunken);
  color: var(--ink);
  font-weight: var(--weight-semibold);
}
.cajon-secciones a[aria-current] .cajon-ola {
  opacity: 1;
  transform: none;
}

.cajon-acciones {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding-inline: var(--space-xs);
}
.cajon-acciones .btn {
  justify-content: center;
}
.cajon-fila {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
}
.cajon-fila > * {
  flex: 1 1 auto;
}

/* Como el de la barra, solo existe si `tema-init.js` corrió. El icono y la
   etiqueta dicen **a qué** tema se cambia: aquí hay sitio para decirlo. */
.cajon-tema {
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  min-height: 48px;
  padding: 0 var(--space-sm);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
:root[data-theme] .cajon-tema {
  display: inline-flex;
}
.cajon-tema svg {
  width: 18px;
  height: 18px;
  flex: none;
}
.cajon-tema .sol,
.cajon-tema .a-claro,
:root[data-theme='dark'] .cajon-tema .luna,
:root[data-theme='dark'] .cajon-tema .a-oscuro {
  display: none;
}
:root[data-theme='dark'] .cajon-tema .sol,
:root[data-theme='dark'] .cajon-tema .a-claro {
  display: inline;
}
@media (hover: hover) {
  .cajon-tema:hover {
    background: var(--sunken);
  }
}

/* --- El mar del cajón -------------------------------------------------- */

/* Las capas miden `--ola` y se apoyan en el fondo; el mar mide un poco más,
   y ese aire de arriba es donde asoma Rakko. Los colores son los del pie de
   la página (`--ola-cresta`, `--ola-medio`, `--chrome`): el cajón y la página
   terminan en la misma orilla. */
.cajon-mar {
  --ola: 132px;
  flex: none;
  position: relative;
  height: 152px;
  overflow: hidden;
  pointer-events: none;
}
.cajon-capa {
  position: absolute;
  left: 0;
  bottom: -14px;
  height: calc(var(--ola) + 14px);
  display: flex;
  /* Mismo criterio que la orilla del pie: el ancho de una ola sale de su
     alto, así que el cajón ve un trozo de la misma ola que la página. */
  width: max(200%, calc(var(--ola) * 8));
}
.cajon-capa > svg {
  flex: 0 0 50%;
  width: 50%;
  height: 100%;
  display: block;
}
.cajon-capa--fondo > svg {
  fill: var(--ola-cresta);
}
.cajon-capa--medio > svg {
  fill: var(--ola-medio);
}
.cajon-capa--frente > svg {
  fill: var(--chrome);
}

/* Rakko va entre la capa de en medio y la de delante, con el vientre por
   debajo de la cresta de delante: lo que está bajo el agua lo tapa el agua.
   Dos envoltorios por lo mismo que en la presentación: uno sale del agua
   (`transform`) y el otro se mece y flota (`rotate`, `translate`). */
.cajon-nutria {
  position: absolute;
  left: calc(62% - 46px);
  bottom: 16px;
  width: 92px;
}
.cajon-nutria-flota {
  position: relative;
  isolation: isolate;
}
.cajon-nutria img {
  display: block;
  width: 100%;
  height: auto;
}
/* En oscuro, la placa clara del logotipo: el disco es navy y la cara es
   transparencia, así que sobre el mar oscuro Rakko se quedaría sin cara. Es
   la misma placa que lleva en la presentación y en la barra. */
:root[data-theme='dark'] .cajon-nutria-flota::before {
  content: '';
  position: absolute;
  inset: -12% -9%;
  z-index: -1;
  background: var(--placa-marca);
  border-radius: 26%;
}

@media (prefers-reduced-motion: no-preference) {
  /* Más vivo que el pie de la página: allá es el borde de algo que se está
     leyendo, aquí es lo único que se mueve mientras se elige a dónde ir. */
  .cajon[open] .cajon-capa--fondo {
    --vaiven: 5px;
    animation:
      ola-deriva 16s linear infinite,
      ola-vaiven 4.6s ease-in-out infinite;
  }
  .cajon[open] .cajon-capa--medio {
    --vaiven: 7px;
    animation:
      ola-deriva 11s linear infinite reverse,
      ola-vaiven 3.7s -1.2s ease-in-out infinite;
  }
  .cajon[open] .cajon-capa--frente {
    --vaiven: 9px;
    animation:
      ola-deriva 8s linear infinite,
      ola-vaiven 2.9s -0.6s ease-in-out infinite;
  }
  .cajon[open] .cajon-nutria {
    animation: cajon-emerger 820ms 160ms both;
  }
  /* Flota al ritmo de la capa de delante (2.9 s): sube y baja con el agua que
     la tapa, y por eso el vientre nunca asoma ni se hunde de más. */
  .cajon[open] .cajon-nutria-flota {
    animation:
      cajon-mecerse 3.4s var(--ease-in-out) infinite alternate both,
      cajon-flotar 1.45s -0.6s var(--ease-in-out) infinite alternate both;
  }
}

/* Sale del agua con impulso, se pasa un poco y vuelve — la misma física que
   la presentación, en pequeño. Arranca bajo la capa de delante, así que no
   hace falta fundirla: el agua la esconde. */
@keyframes cajon-emerger {
  from {
    transform: translateY(78%) rotate(-12deg);
    animation-timing-function: cubic-bezier(0.2, 0.75, 0.3, 1);
  }
  62% {
    transform: translateY(-9%) rotate(3deg);
    animation-timing-function: cubic-bezier(0.45, 0, 0.4, 1);
  }
  to {
    transform: none;
  }
}
@keyframes cajon-mecerse {
  from {
    rotate: -4deg;
  }
  to {
    rotate: 4deg;
  }
}
@keyframes cajon-flotar {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 7px;
  }
}

/* ===========================================================================
   El cajón en un teléfono bajo
   ---------------------------------------------------------------------------
   De fábrica el cajón mide 844 px —cabecera 72, lista 396, acciones 160 y mar
   152—, así que **casi ningún teléfono lo enseñaba entero**: con la barra del
   navegador a la vista un iPhone 13 tiene ~700 px y un iPhone SE ~550, y las
   últimas secciones quedaban detrás de un desplazamiento que nadie sabe que
   existe dentro de un menú. Se recorta por alto de ventana, de lo menos
   valioso a lo más:

   1. **El mar cede primero.** Es decoración: su alto es lo que sobra después de
      la lista (`--mar`), con tope en el de fábrica, y a falta de sitio queda en
      una franja de olas o desaparece. Rakko sale del agua mientras quepa
      entero; con menos de 100 px de mar se queda abajo, no en miniatura.
   2. **Los dos botones de abajo caben en una fila.** Apilados costaban 56 px:
      el tema pasa a ser un icono, como el de la barra, y su nombre se queda
      solo para el lector de pantalla.
   3. **Por debajo de ~700 px la lista pasa a dos columnas**: cinco filas en
      vez de nueve, que es lo único que cabe en un teléfono chico.

   Las alturas de la cuenta —592 px sin el mar, 412 con dos columnas— salen de
   medirlas, y de ellas depende el `--mar`. Sigue desplazándose si aun así no
   cabe (un teléfono de lado), pero deja de ser lo normal.

   El umbral de los dos primeros es generoso (1000 px) a propósito: la consulta
   de alto puede medir la ventana con la barra escondida mientras el cajón mide
   la que se ve (`dvh`), y un umbral justo dejaría sin recortar justo a los
   teléfonos más altos.
   =========================================================================== */

@media (max-height: 1000px) {
  .cajon-cabeza {
    min-height: 60px;
  }
  .cajon-cuerpo {
    gap: var(--space-xs);
    padding: var(--space-2xs) var(--space-xs) var(--space-xs);
  }

  .cajon-fila {
    flex-wrap: nowrap;
  }
  .cajon-acciones .btn {
    min-width: 0;
    padding-inline: var(--space-sm);
  }
  .cajon-tema {
    position: relative;
    flex: none;
    width: 48px;
    padding: 0;
  }
  /* El nombre del tema sigue en el árbol —es el nombre accesible del botón—
     pero deja de verse: el icono ya dice a cuál se cambia. */
  .cajon-tema span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .cajon-mar {
    --mar: clamp(0px, calc(100vh - 592px), 152px);
    --ola: calc(var(--mar) * 0.87);
    height: var(--mar);
    container: cajon-mar / size;
  }
  .cajon-nutria {
    width: calc(var(--mar) * 0.6);
    bottom: calc(var(--mar) * 0.105);
    left: calc(62% - var(--mar) * 0.3);
  }
}
@supports (height: 1dvh) {
  @media (max-height: 1000px) {
    .cajon-mar {
      --mar: clamp(0px, calc(100dvh - 592px), 152px);
    }
  }
}
@container cajon-mar (max-height: 99px) {
  .cajon-nutria {
    display: none;
  }
}

@media (max-height: 700px) {
  .cajon-cabeza {
    min-height: 56px;
  }
  .cajon-secciones {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-3xs);
  }
  .cajon-secciones a {
    padding: 0 var(--space-2xs);
    font-size: 0.9rem;
    line-height: 1.25;
  }
  /* Sin la ola de cada renglón —ya no hay sitio para ella—, la sección en la
     que se está se marca con el color de acción además del fondo. */
  .cajon-ola {
    display: none;
  }
  .cajon-secciones a[aria-current] {
    color: var(--action-texto);
  }
  .cajon-mar {
    --mar: clamp(0px, calc(100vh - 412px), 152px);
  }
}
@supports (height: 1dvh) {
  @media (max-height: 700px) {
    .cajon-mar {
      --mar: clamp(0px, calc(100dvh - 412px), 152px);
    }
  }
}

/* ===========================================================================
   21 · El teléfono: menos desplazamiento
   ---------------------------------------------------------------------------
   En 375 px la página medía ~11 500 px, catorce pantallas. No sobraba ninguna
   sección; sobraba **cómo se apilaban**: listas de once renglones de una sola
   columna, cuatro pasos a pantalla completa y 128 px de aire entre secciones
   que en un monitor separan y en un teléfono solo alejan.

   Lo que se hace, en orden de lo que más ahorra:

   - **Módulos y «También» van en dos columnas.** Son entradas cortas —un
     nombre y una frase— y en una columna cada una gastaba una fila entera con
     la mitad del ancho vacío a la derecha del nombre.
   - **El recorrido son cuatro pestañas en 2×2** y la descripción del paso
     vigente debajo (`main.js` la escribe; sin guion se quedan las cuatro
     descripciones, como antes). El teléfono de la escena se encoge un poco:
     era la pieza más alta de la página.
   - **Menos aire entre secciones**: 48 px por lado en vez de 64.
   =========================================================================== */

@media (max-width: 900px) {
  .dia-rejilla {
    gap: var(--space-md);
  }
  .pasos--compactos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2xs);
  }
  .pasos--compactos .paso {
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: var(--space-2xs);
    padding: var(--space-xs);
    border: 1px solid var(--rule);
    min-height: 64px;
  }
  .pasos--compactos .paso + .paso {
    border-top: 1px solid var(--rule);
  }
  /* En una pestaña con marco, lo seleccionado lo dice el marco y el número
     encendido; la barra lateral del escritorio sobra. */
  .pasos--compactos .paso::before {
    display: none;
  }
  .pasos--compactos .paso[aria-selected='true'] {
    border-color: var(--action);
  }
  .pasos--compactos .paso p,
  .pasos--compactos .paso .paso-rol {
    display: none;
  }
  .pasos--compactos .paso h3 {
    margin: 0;
    font-size: var(--text-label);
    line-height: 1.3;
  }
  .pasos--compactos .paso-numero {
    width: 26px;
    height: 26px;
  }
  /* Tres renglones reservados: el recorrido avanza solo, y un párrafo que
     cambiara de alto en cada paso movería la escena de debajo sin que nadie
     lo hubiera pedido. */
  .paso-detalle {
    min-height: calc(3 * 1.5em);
    color: var(--muted);
    font-size: var(--text-label);
    line-height: 1.5;
  }
  .paso-detalle .paso-rol {
    margin-bottom: 2px;
  }
}
@media (min-width: 901px) {
  .paso-detalle {
    display: none;
  }
}

@media (max-width: 600px) {
  .seccion {
    --seccion-aire: var(--space-xl);
  }
  .seccion-encabezado {
    margin-bottom: var(--space-lg);
  }
  .seccion-encabezado p {
    font-size: var(--text-body);
  }

  .escena .telefono {
    width: min(236px, 64vw);
  }

  .modulos {
    grid-template-columns: 1fr 1fr;
    gap: 0 var(--space-sm);
  }
  .modulo {
    padding-block: var(--space-sm);
  }
  .modulo p,
  .rasgo p {
    line-height: 1.45;
  }

  .distingue {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-md) var(--space-sm);
  }
  .rasgo {
    padding-top: var(--space-xs);
  }
}
