/* ══════════════════════════════════════════════════
   RUTA EDUCATIVA — SISTEMA DE DISEÑO COMPARTIDO

   Única fuente de verdad para las 15 páginas: tokens, base,
   tipografía, header, footer, FAQ y componentes comunes.
   Las secciones exclusivas de la portada viven en home.css.

   MOBILE FIRST, igual que home.css: las reglas sin @media son el
   layout de móvil, y cada @media (min-width) SUMA columnas, barras
   laterales o espacio según cabe el aire. Ningún componente de aquí
   parte de un layout de escritorio para luego restarle cosas.
══════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════
   TIPOGRAFÍAS AUTO-ALOJADAS

   Servidas desde el propio dominio: el sitio no hace ninguna
   petición a terceros, y se ahorran dos handshakes TLS en la
   ruta crítica.

   Instrument Sans es variable: un solo archivo cubre 400-600.
   El unicode-range es el original de Google, así que el navegador
   sigue bajando latin-ext solo si la página lo necesita.

   Ambas familias están bajo SIL Open Font License 1.1.
   Para regenerarlas: scratchpad/selfhost.py
══════════════════════════════════════════════════ */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-400-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;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-400-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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-500-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;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-500-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: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("fonts/instrument-sans-400-600-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;
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("fonts/instrument-sans-400-600-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;
}

:root {
  color-scheme: light dark;

  /* ── superficies ── */
  --bg:        light-dark(oklch(0.98 0.004 260), oklch(0.17 0.014 260));
  --surface:   light-dark(#fff,                  oklch(0.215 0.016 260));
  --surface-2: light-dark(oklch(0.98 0.004 260), oklch(0.245 0.016 260));
  /* "Liquid glass": vidrio traslúcido con blur + saturación, compartido
     por el navbar, botones fantasma y tarjetas flotantes. Más claro que
     la superficie normal (no solo transparente) para que el panel se
     perciba como cristal incluso sin un resplandor de color detrás; el
     borde lleva tinte de marca (--glass-line) y arriba un filo claro
     que simula el brillo del cristal (--glass-sheen). */
  --pill-bg:     light-dark(oklch(1 0 0 / 0.5),   oklch(0.34 0.03 262 / 0.55));
  --glass-sheen: light-dark(oklch(1 0 0 / 0.75),  oklch(1 0 0 / 0.16));
  --glass-line:  light-dark(oklch(0.8 0.03 262 / 0.9), oklch(0.56 0.06 262 / 0.5));
  --glass-blur:  blur(22px) saturate(190%);
  /* Variante para bloques oscuros en ambos temas (.roles-dark): un vidrio
     claro fijo, no light-dark(), porque el fondo detrás no cambia. */
  --dark-glass-bg:    oklch(0.45 0.03 262 / 0.5);
  --dark-glass-sheen: oklch(1 0 0 / 0.14);
  --dark-glass-line:  oklch(0.58 0.07 262 / 0.55);
  /* Un poco más presente que --brand-halo, para secciones claras/oscuras
     nuevas donde el vidrio necesita algo de color detrás que desenfocar.
     Nunca tan fuerte como para competir con el texto: son manchas en las
     esquinas, no una capa pareja sobre todo el bloque. */
  --glass-halo:   light-dark(oklch(0.94 0.05 262 / 0.75), oklch(0.3 0.1 262 / 0.5));
  --glass-halo-2: light-dark(oklch(0.94 0.06 160 / 0.55), oklch(0.32 0.09 160 / 0.32));

  /* ── texto ── */
  --ink:       light-dark(oklch(0.22 0.02 260), oklch(0.96 0.005 260));
  --ink-2:     light-dark(oklch(0.28 0.02 260), oklch(0.90 0.008 260));
  --ink-3:     light-dark(oklch(0.25 0.02 260), oklch(0.93 0.008 260));
  --muted:     light-dark(oklch(0.45 0.02 260), oklch(0.72 0.012 260));
  --muted-2:   light-dark(oklch(0.5 0.02 260),  oklch(0.68 0.012 260));
  /* muted-3 y muted-4 son los grises del texto MÁS pequeño (.label 10px).
     En claro se oscurecieron hasta pasar 4.5:1 sobre --bg y sobre #fff;
     en oscuro ya pasaban y se dejan como estaban. */
  --muted-3:   light-dark(oklch(0.525 0.02 260), oklch(0.645 0.012 260));
  --muted-4:   light-dark(oklch(0.545 0.02 260), oklch(0.625 0.012 260));

  /* ── marca ── */
  --brand:      light-dark(oklch(0.52 0.16 262), oklch(0.70 0.15 262));
  --brand-dark: light-dark(oklch(0.44 0.16 262), oklch(0.80 0.12 262));
  --brand-soft: light-dark(oklch(0.94 0.02 262), oklch(0.30 0.05 262));
  --brand-halo: light-dark(oklch(0.96 0.03 262), oklch(0.24 0.045 262));
  --brand-ink:  light-dark(oklch(0.42 0.12 262), oklch(0.84 0.10 262));
  --on-brand:   light-dark(#fff, oklch(0.16 0.04 262));

  /* ── líneas ── */
  --line:           light-dark(oklch(0.91 0.008 260), oklch(0.315 0.014 260));
  --line-2:         light-dark(oklch(0.94 0.006 260), oklch(0.275 0.014 260));
  --line-3:         light-dark(oklch(0.96 0.004 260), oklch(0.25 0.012 260));
  --line-4:         light-dark(oklch(0.93 0.006 260), oklch(0.295 0.014 260));
  --line-section:   light-dark(oklch(0.92 0.008 260), oklch(0.27 0.014 260));
  --line-dash:      light-dark(oklch(0.78 0.02 260),  oklch(0.40 0.02 260));
  --line-brand:     light-dark(oklch(0.88 0.03 262),  oklch(0.44 0.07 262));
  --line-brand-on:  light-dark(oklch(0.72 0.1 262),   oklch(0.52 0.11 262));
  --line-on-brand:  light-dark(oklch(0.62 0.13 262),  oklch(0.58 0.12 262));
  --btn-line:       light-dark(oklch(0.89 0.008 260), oklch(0.34 0.014 260));
  --btn-line-hover: light-dark(oklch(0.70 0.02 260),  oklch(0.52 0.02 260));
  --dot:            light-dark(oklch(0.85 0.01 260),  oklch(0.36 0.014 260));

  /* ── estado ── */
  --ok:      light-dark(oklch(0.52 0.11 160), oklch(0.74 0.13 160));
  --ok-soft: light-dark(oklch(0.72 0.13 160), oklch(0.78 0.14 160));
  --ok-bg:   light-dark(oklch(0.93 0.05 160), oklch(0.30 0.06 160));
  --ok-ink:  light-dark(oklch(0.42 0.11 160), oklch(0.84 0.12 160));
  --on-ok:   light-dark(#fff, oklch(0.16 0.03 160));
  --warn:    light-dark(oklch(0.55 0.14 40),  oklch(0.75 0.15 45));
  /* Escala de desempeño tal como la pinta el producto:
     Bajo (rojo) · Básico (ámbar) · Alto (azul de marca) · Superior (verde).
     Cada par ink/bg pasa 4.5:1 en los dos temas. */
  --warn-bg: light-dark(oklch(0.94 0.05 80),  oklch(0.33 0.07 70));
  --warn-ink:light-dark(oklch(0.44 0.13 70),  oklch(0.87 0.10 80));
  --bad:     light-dark(oklch(0.50 0.19 27),  oklch(0.70 0.17 27));
  --bad-bg:  light-dark(oklch(0.94 0.04 27),  oklch(0.32 0.09 27));
  --bad-ink: light-dark(oklch(0.44 0.17 27),  oklch(0.86 0.10 27));

  /* ── bloques de alto contraste (oscuros en ambos temas) ── */
  --dark:        light-dark(oklch(0.22 0.02 260), oklch(0.115 0.012 260));
  --dark-card:   light-dark(oklch(0.27 0.02 260), oklch(0.185 0.014 260));
  --dark-line:   light-dark(oklch(0.34 0.02 260), oklch(0.30 0.02 260));
  --dark-line-2: light-dark(oklch(0.32 0.02 260), oklch(0.26 0.02 260));
  --dark-text:   oklch(0.78 0.01 260);
  --rail-fill:   light-dark(oklch(0.22 0.02 260), oklch(0.90 0.008 260));

  /* ── sombras ── */
  --sh-c:       light-dark(oklch(0.4 0.06 262 / 0.6),  oklch(0.02 0.01 260 / 0.75));
  --sh-c-brand: light-dark(oklch(0.45 0.16 262 / 0.7), oklch(0.30 0.14 262 / 0.6));
  --sh-c-dark:  light-dark(oklch(0.3 0.06 262 / 0.7),  oklch(0.02 0.01 260 / 0.85));

  --sh-sm: 0 20px 40px -30px var(--sh-c);
  --sh-md: 0 30px 55px -40px var(--sh-c);
  --sh-lg: 0 40px 70px -44px var(--sh-c);
  --sh-xl: 0 50px 80px -50px var(--sh-c);
  --sh-dark: 0 30px 60px -34px var(--sh-c-dark);
}

:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

/* ══════════════════════════════════════════════════
   BASE
══════════════════════════════════════════════════ */
* { box-sizing: border-box; }
html { overflow-x: clip; }
/* El desplazamiento suave es una animación: solo para quien no pide lo contrario. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Instrument Sans", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
  overflow-x: clip;
}
a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-dark); }
h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.03em; }
p { margin: 0; }
/* min-height:44px es el mínimo táctil (WCAG 2.5.5) y es la base
   mobile-first; a partir de min-width:640px un mouse apunta con más
   precisión y ya no hace falta forzarlo (@media más abajo). */
button { font: inherit; min-height: 44px; }

.page { position: relative; max-width: 100%; overflow-x: clip; }
.wrap { max-width: 1240px; margin: 0 auto; }
.mono { font-family: 'IBM Plex Mono', monospace; }

/* Microetiqueta de las tarjetas y de las capturas de producto.
   Vive aquí y no en home.css porque la usan las 15 páginas. */
.label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-3);
}

.h2 {
  font-size: clamp(30px, 4vw, 50px);
  line-height: 1.05;
  letter-spacing: -0.03em;
}
.lead {
  font-size: 17px;
  line-height: 1.6;
  color: var(--muted);
}

section { padding: clamp(70px, 12vh, 140px) clamp(18px, 4vw, 40px); }

.btn {
  display: inline-block;
  font-size: 15px;
  font-weight: 500;
  padding: 15px 24px;
  border-radius: 12px;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.btn--primary { background: var(--brand); color: var(--on-brand); border: 1px solid var(--brand); }
.btn--primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); color: var(--on-brand); }
.btn--ghost {
  background: var(--pill-bg);
  color: var(--ink-2);
  border: 1px solid var(--glass-line);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-sheen);
}
.btn--ghost:hover { border-color: var(--btn-line-hover); color: var(--ink-2); }

/* Variantes para .final y .article-cta: bloques que ya no son oscuros en
   ambos temas (siguen el tema como cualquier otro), pero conservan su
   propia superficie con acento en vez de la superficie normal del
   sitio. En oscuro se ven exactamente igual que antes (botón blanco
   sólido / fantasma con borde claro); en claro pasan a la pareja
   habitual del sitio para "botón sólido de marca" — el mismo look que
   ya usa .btn--primary, solo con otro nombre porque vive sobre un
   fondo que también le pertenece a este componente, no al normal. */
.btn--on-dark {
  background: light-dark(var(--brand), #fff);
  color: light-dark(var(--on-brand), var(--dark));
  border: 1px solid light-dark(var(--brand), #fff);
}
.btn--on-dark:hover {
  background: light-dark(var(--brand-dark), oklch(0.92 0.01 260));
  border-color: light-dark(var(--brand-dark), oklch(0.92 0.01 260));
  color: light-dark(var(--on-brand), var(--dark));
}
/* Borde a 0.55 y no más bajo en oscuro: por debajo de ~0.51 el contorno
   del botón cae por debajo de 3:1 sobre --dark y falla WCAG 1.4.11
   (contraste no textual). En claro usa --line-brand-on, ya pensado
   para un borde con tinte de marca sobre superficie clara. */
.btn--on-dark-ghost {
  background: transparent;
  color: light-dark(var(--ink), #fff);
  border: 1px solid light-dark(var(--line-brand-on), oklch(0.55 0.02 260));
}
.btn--on-dark-ghost:hover { border-color: light-dark(var(--brand), oklch(0.72 0.02 260)); color: light-dark(var(--ink), #fff); }
.btn--on-dark:focus-visible,
.btn--on-dark-ghost:focus-visible { outline: 2px solid light-dark(var(--brand), #fff); outline-offset: 3px; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
}

::selection { background: var(--brand-soft); color: var(--ink); }

@media (prefers-reduced-motion: reduce) { * { animation: none !important; } }

:root.theme-switching,
:root.theme-switching *,
:root.theme-switching *::before,
:root.theme-switching *::after {
  transition: background-color .28s ease, border-color .28s ease,
              color .28s ease, box-shadow .28s ease, fill .28s ease,
              opacity .28s ease, filter .28s ease !important;
}
@media (prefers-reduced-motion: reduce) {
  :root.theme-switching, :root.theme-switching * { transition: none !important; }
}

/* ══════════════════════════════════════════════════
   SALTAR AL CONTENIDO
   Primer elemento enfocable de la página. Fuera de la
   pantalla hasta que recibe el foco por teclado.
══════════════════════════════════════════════════ */
/* fixed, no absolute: absolute lo ancla al documento y, con la página
   desplazada, el enlace aparece por encima del viewport y no se ve. */
.skip-link {
  position: fixed;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 13px 20px;
  border-radius: 0 0 12px 0;
  background: var(--brand);
  color: var(--on-brand);
  font-size: 15px;
  font-weight: 500;
}
.skip-link:focus {
  left: 0;
  color: var(--on-brand);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* El ancla del skip link recibe el foco por programa: sin anillo visible,
   porque el usuario ya sabe dónde aterrizó. */
main:focus { outline: none; }

/* ══════════════════════════════════════════════════
   HEADER

   Las 15 páginas comparten un único componente de navegación: el
   dock flotante de más abajo. .theme-btn se queda aquí porque es la
   base que .dock .theme-btn reutiliza (el dock solo le quita la caja
   cuadrada con borde); el resto del header clásico —barra sticky,
   .site-nav, el menú de hamburguesa— ya no lo usa ninguna página y se
   retiró con la unificación de navegación.
══════════════════════════════════════════════════ */
.theme-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 44px;
  padding: 0;
  border-radius: 12px;
  border: 1px solid var(--btn-line);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.theme-btn:hover { border-color: var(--btn-line-hover); color: var(--ink); }
.theme-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.theme-btn svg { width: 18px; height: 18px; display: block; }
.theme-btn .i-sun { display: none; }
:root[data-scheme="dark"] .theme-btn .i-sun  { display: block; }
:root[data-scheme="dark"] .theme-btn .i-moon { display: none; }

/* ══════════════════════════════════════════════════
   NAVEGACIÓN INFERIOR (.dock)

   Píldora flotante anclada abajo. Cada destino se ve siempre como
   icono; el nombre solo lo muestra el que se está viendo, y crece
   con una transición en vez de aparecer de golpe.

   El truco del ancho: el nombre vive en una rejilla que pasa de 0fr
   a 1fr. Eso sí se puede animar, mientras que ir de width:0 a
   width:auto no. El hijo lleva overflow:hidden para que el texto se
   recorte mientras tanto en vez de desbordar.

   Se pone en site.css, y no en home.css, porque es chrome del sitio:
   cualquier página puede montarla copiando el bloque de <nav>.
══════════════════════════════════════════════════ */
.dock {
  position: fixed;
  z-index: 60;
  /* Centrada con left/right 0 + margen automático, no con left:50%: con
     left:50% el ancho disponible de un elemento fijo es solo la mitad
     derecha de la pantalla, y en móvil eso aplastaba la etiqueta del
     ítem activo hasta dejarla en cero. */
  left: 0;
  right: 0;
  width: fit-content;
  margin-inline: auto;
  top: max(12px, env(safe-area-inset-top));
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 6px;
  border-radius: 999px;
  /* Más opaca que --pill-bg (el vidrio del header): esta barra pasa por
     encima de bloques claros y oscuros, y a media transparencia se
     ensuciaba sobre el pie. */
  background: light-dark(oklch(1 0 0 / 0.88), oklch(0.245 0.018 260 / 0.9));
  border: 1px solid var(--glass-line);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: 0 18px 40px -20px var(--sh-c), inset 0 1px 0 var(--glass-sheen);
  max-width: calc(100vw - 20px);
}
/* La barra flota (no ocupa sitio en el flujo), así que el hueco de
   arriba lo pone el contenido. El scroll-margin hace que al saltar a una
   sección su título quede debajo de la barra y no detrás. */
.page--dock main { padding-top: clamp(76px, 9vh, 94px); }
.page--dock main [id] { scroll-margin-top: clamp(84px, 10vh, 102px); }
/* El breadcrumb de las páginas de artículo vive FUERA de <main> (es
   hermano, no hijo), así que necesita su propio despeje bajo la
   píldora flotante — si no, el primer renglón quedaría tapado. */
.page--dock .breadcrumb { padding-top: clamp(76px, 9vh, 94px); }

.dock__item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  height: 44px;
  min-width: 44px;
  padding: 0 11px;
  border-radius: 999px;
  color: var(--muted);
  transition: color .2s ease, background-color .3s ease, gap .38s cubic-bezier(.2, .7, .3, 1);
}
.dock__item:hover { color: var(--ink); background: var(--surface-2); }
.dock__item:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.dock__item svg { width: 20px; height: 20px; display: block; flex: 0 0 auto; }

.dock__item.is-on {
  color: var(--brand-ink);
  background: var(--brand-soft);
}
.dock__item.is-on:hover { color: var(--brand-ink); background: var(--brand-soft); }

.dock__label {
  display: grid;
  grid-template-columns: 0fr;
  opacity: 0;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.01em;
  transition: grid-template-columns .38s cubic-bezier(.2, .7, .3, 1), opacity .24s ease;
}
.dock__label > span { overflow: hidden; white-space: nowrap; min-width: 0; }
/* En móvil el ítem activo solo se ilumina (color + fondo, arriba): la
   barra ya va justa de ancho contra el borde de la pantalla, así que
   expandir una etiqueta ahí la desbordaba o apretaba al resto de
   iconos. La etiqueta que nombra la sección solo se abre desde
   tablet/escritorio, donde sobra aire para crecer sin empujar nada. */
@media (min-width: 640px) {
  .dock__item.is-on { gap: 8px; }
  .dock__item.is-on .dock__label { grid-template-columns: 1fr; opacity: 1; }
}

.dock__sep {
  width: 1px;
  height: 22px;
  margin: 0 4px;
  background: var(--glass-line);
  flex: 0 0 auto;
}

/* Marca. Entra como máscara y no como <img> para que tome el color de
   la tinta: el trazo del logo no lleva color propio, así que en oscuro
   se ve claro sin necesidad de un segundo archivo ni de invertirlo. */
.dock__brand {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  border-radius: 999px;
  color: var(--ink);
  transition: background-color .3s ease;
}
.dock__brand:hover { background: var(--surface-2); }
.dock__brand:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.dock__logo {
  width: 25px;
  height: 25px;
  display: block;
  background: currentColor;
  -webkit-mask: url("images/logo.svg") no-repeat center / contain;
  mask: url("images/logo.svg") no-repeat center / contain;
}

/* El interruptor de tema reaprovecha .theme-btn por el cambio de icono
   (claro/oscuro), pero aquí es un ítem más de la barra: se le quita la
   caja cuadrada con borde que lleva en el header. */
.dock .theme-btn {
  width: auto;
  border: 0;
  background: transparent;
  border-radius: 999px;
}
.dock .theme-btn:hover { background: var(--surface-2); border: 0; }

@media (max-width: 400px) {
  .dock { gap: 0; padding: 5px; }
  .dock__item { padding: 0 9px; min-width: 42px; }
  .dock__label { font-size: 13px; }
  .dock__brand { width: 40px; }
  .dock__sep { display: none; }
}

/* La regla global de reduced-motion solo apaga animaciones; estas son
   transiciones y hay que apagarlas aparte. */
@media (prefers-reduced-motion: reduce) {
  .dock__item,
  .dock__label { transition: none; }
}

/* ══════════════════════════════════════════════════
   MIGA DE PAN
══════════════════════════════════════════════════ */
.breadcrumb {
  max-width: 1240px;
  margin: 0 auto;
  padding: 20px clamp(18px, 4vw, 40px) 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--muted-3);
}
.breadcrumb a { color: var(--muted-3); }
.breadcrumb a:hover { color: var(--brand); }
.breadcrumb span[aria-current] { color: var(--muted); }

/* ══════════════════════════════════════════════════
   ARTÍCULO / GUÍA — encabezado
══════════════════════════════════════════════════ */
.article-hero { padding-top: clamp(30px, 6vh, 60px); padding-bottom: clamp(40px, 7vh, 76px); }
.article-hero__inner { max-width: 780px; margin: 0 auto; }
/* Variante centrada: solo la usa 404. */
.article-hero--center { text-align: center; }
.article-hero--center .lead { margin-inline: auto; }
.article-hero h1 {
  font-size: clamp(32px, 5vw, 52px);
  line-height: 1.06;
  letter-spacing: -0.03em;
  margin: 16px 0 18px;
  text-wrap: balance;
}
.article-hero .lead { font-size: clamp(17px, 1.6vw, 19px); max-width: 62ch; }
.article-meta { display: flex; flex-wrap: wrap; gap: 10px 18px; margin-top: 22px; font-size: 13px; color: var(--muted-3); }

/* ══════════════════════════════════════════════════
   ARTÍCULO / GUÍA — cuerpo (prosa)
══════════════════════════════════════════════════ */
.article-body { padding-top: 0; padding-bottom: clamp(40px, 7vh, 70px); }
/* Mobile-first: una columna es la base; la prosa con la barra lateral
   angosta a la derecha es el añadido de escritorio (@media min-width
   más abajo, junto al de .article-aside). */
.article-body__inner {
  max-width: 1240px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(30px, 5vw, 64px);
  align-items: start;
}
.prose { max-width: 68ch; }
.prose > * + * { margin-top: 18px; }
.prose h2 {
  font-size: clamp(22px, 2.6vw, 30px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin-top: 48px;
  padding-top: 28px;
  border-top: 1px solid var(--line-section);
}
.prose > h2:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.prose h3 { font-size: 18px; letter-spacing: -0.015em; margin-top: 30px; }
.prose p { font-size: 16px; line-height: 1.7; color: var(--ink-2); }
.prose ul, .prose ol { margin: 0; padding-left: 22px; display: grid; gap: 10px; }
.prose li { font-size: 16px; line-height: 1.6; color: var(--ink-2); }
.prose li::marker { color: var(--muted-3); }
.prose strong { color: var(--ink); font-weight: 600; }
.prose a { text-decoration: underline; text-decoration-color: var(--line-brand-on); text-underline-offset: 3px; }
/* Un botón dentro del texto sigue siendo un botón: el subrayado de los
   enlaces de prosa no debe alcanzarlo. */
.prose a.btn { text-decoration: none; }

.callout {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 22px 24px;
}
.callout .label { margin-bottom: 8px; }
.callout p { color: var(--ink-2); }

.criteria-list { display: grid; gap: 14px; }
.criteria-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 18px 20px;
}
.criteria-item .name { font-size: 15px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
.criteria-item p { font-size: 14px; line-height: 1.6; color: var(--muted); margin: 0; }

/* Ya no es oscuro en los dos temas: en claro pasa a --brand-halo, en
   oscuro se ve idéntico a como se veía (--dark + #fff), igual que .final
   en home.css (mismo patrón, misma razón). */
.article-cta {
  background: light-dark(var(--brand-halo), var(--dark));
  color: light-dark(var(--ink), #fff);
  border-radius: 20px;
  padding: 32px 30px;
  margin-top: 40px;
}
.article-cta h3 { font-size: clamp(20px, 2.4vw, 26px); letter-spacing: -0.02em; margin: 0 0 10px; color: light-dark(var(--ink), #fff); }
.article-cta p { color: light-dark(var(--muted), var(--dark-text)); font-size: 14px; line-height: 1.6; margin-bottom: 18px; }

/* ── Barra lateral ── */
/* En móvil las tarjetas de la barra lateral no son una barra lateral:
   son una fila de tarjetas que se ajustan las que quepan (auto-fit).
   Vuelven a ser una sola columna fija (@media min-width más abajo). */
.article-aside {
  display: grid;
  gap: 20px;
  align-content: start;
  position: static;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.aside-card { background: var(--surface); border: 1px solid var(--line); border-radius: 16px; padding: 20px; }
.aside-card .label { margin-bottom: 12px; }
.aside-card nav { display: grid; gap: 9px; }
.aside-card nav a { font-size: 13px; color: var(--muted-2); line-height: 1.4; }
.aside-card nav a:hover { color: var(--brand); }
.related-list { display: grid; gap: 14px; }
.related-list a { display: block; font-size: 13.5px; font-weight: 500; color: var(--ink-2); line-height: 1.4; }
.related-list a:hover { color: var(--brand); }
.related-list p { font-size: 12.5px; color: var(--muted-3); margin-top: 4px; font-weight: 400; }

/* Reutiliza el componente de acordeón del FAQ del home.
   Mobile-first: una columna y el intro sin fijar es la base; las dos
   columnas con el intro pegado al hacer scroll son el añadido de
   escritorio (@media min-width más abajo), no al revés. */
.faq .wrap {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(28px, 5vw, 72px);
  align-items: start;
}
.faq__intro { max-width: 620px; position: static; margin-bottom: clamp(22px, 4vh, 38px); }
.faq__intro h2 { margin: 18px 0 12px; }
.faq__groups { display: grid; gap: 30px; }
.faq__group-title {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-3);
  margin-bottom: 14px;
}
.faq__list { display: grid; gap: 12px; }

.faq-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.faq-item:hover { border-color: var(--btn-line-hover); }
.faq-item[open] { border-color: var(--line-brand); box-shadow: var(--sh-sm); }
.faq-item summary {
  list-style: none;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 15px 16px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.45;
  color: var(--ink-2);
  cursor: pointer;
  border-radius: 16px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--ink); }
.faq-item summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.faq-item__icon {
  order: -1;
  position: relative;
  width: 28px;
  height: 28px;
  margin-top: -2px;
  border-radius: 50%;
  background: var(--brand-soft);
  flex: 0 0 auto;
  transition: background .2s ease;
}
.faq-item__icon::before, .faq-item__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--brand);
  translate: -50% -50%;
  transition: rotate .2s ease, opacity .2s ease, background .2s ease;
}
.faq-item__icon::before { width: 11px; height: 1.6px; }
.faq-item__icon::after  { width: 1.6px; height: 11px; }
.faq-item[open] summary { color: var(--ink); }
.faq-item[open] .faq-item__icon { background: var(--brand); }
.faq-item[open] .faq-item__icon::before { background: var(--on-brand); }
.faq-item[open] .faq-item__icon::after { rotate: 90deg; opacity: 0; }
.faq-item__body { padding: 0 16px 16px 56px; }
/* Mientras se cierra, el icono y el borde vuelven a su sitio desde el
   primer momento: el atributo [open] no se quita hasta que termina la
   animación de altura, así que este estado cubre ese intervalo. */
.faq-item.is-closing { border-color: var(--line); box-shadow: none; }
.faq-item.is-closing .faq-item__icon { background: var(--brand-soft); }
.faq-item.is-closing .faq-item__icon::before { background: var(--brand); }
.faq-item.is-closing .faq-item__icon::after { rotate: 0deg; opacity: 1; }
.faq-item__body p { font-size: 14px; line-height: 1.6; color: var(--muted); max-width: 60ch; }

/* ── Cierre de la sección ── */
.faq__more {
  background: var(--brand-halo);
  border: 1px solid var(--line-brand);
  border-radius: 16px;
  padding: 26px 24px;
  text-align: center;
}
.faq__more .name { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); }
.faq__more p { margin-top: 8px; font-size: 14px; line-height: 1.6; color: var(--muted); }
.faq__more-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 18px; }
.faq__more-actions .btn { font-size: 14px; padding: 12px 20px; }

@media (min-width: 640px) {
  .faq-item summary { padding: 17px 20px; gap: 14px; font-size: 15.5px; }
  .faq-item__body { padding: 0 20px 18px 62px; }
}
@media (min-width: 900px) {
  .faq .wrap { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.6fr); }
  .faq__intro { position: sticky; top: 100px; margin-bottom: 0; }
}

/* ══════════════════════════════════════════════════
   FOOTER
══════════════════════════════════════════════════ */
/* ══════════════════════════════════════════════════
   FOOTER
   Bloque de alto contraste: oscuro en AMBOS temas, por lo
   que sus colores internos son literales a propósito.
══════════════════════════════════════════════════ */
.site-footer {
  padding: clamp(46px, 6vw, 72px) clamp(18px, 4vw, 40px) 26px;
  background: light-dark(var(--surface-2), var(--dark));
  color: light-dark(var(--muted), oklch(0.72 0.01 260));
  border-top: 1px solid light-dark(var(--line), oklch(0.3 0.02 260));
}
.site-footer__inner { max-width: 1240px; margin: 0 auto; }
:where(.site-footer) a { color: inherit; }
.site-footer a:focus-visible { outline: 2px solid light-dark(var(--brand), #fff); outline-offset: 3px; border-radius: 8px; }

/* ── Columnas ── */
/* Mobile-first: dos columnas con la marca ocupando la fila entera es
   la base; cuatro columnas y luego las cinco (marca + 4 navs) en su
   propia franja son el añadido de tablet/escritorio más abajo. */
.footer-main {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 30px 18px;
  padding: 0 0 clamp(30px, 4vw, 42px);
}
.footer-brand { grid-column: 1 / -1; max-width: 560px; }
.footer-brand .brandline {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: light-dark(var(--ink), #fff);
  font-weight: 600;
  font-size: 15.5px;
  letter-spacing: -0.01em;
}
/* El logo es un SVG de trazo negro: en oscuro se invierte a blanco con
   filter (light-dark() no vale para filter, solo para <color>), así
   que el volteo va condicionado a data-scheme, la misma marca que ya
   usa el botón de tema para su propio icono sol/luna. En claro no
   necesita filtro: el trazo negro ya se lee sobre la superficie clara. */
.footer-brand .brandline img { width: 24px; height: 24px; opacity: .9; }
:root[data-scheme="dark"] .footer-brand .brandline img { filter: brightness(0) invert(1); }
.footer-brand p { margin-top: 14px; font-size: 13.5px; line-height: 1.6; color: light-dark(var(--muted-2), oklch(0.68 0.012 260)); }

.footer-social { display: flex; gap: 10px; margin: 22px 0 0; padding: 0; list-style: none; }
.footer-social a {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 11px;
  border: 1px solid light-dark(var(--line), oklch(0.34 0.02 260));
  color: light-dark(var(--muted), oklch(0.78 0.01 260));
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.footer-social a:hover { background: light-dark(var(--surface), oklch(0.3 0.02 260)); border-color: light-dark(var(--btn-line-hover), oklch(0.48 0.02 260)); color: light-dark(var(--ink), #fff); }
.footer-social svg { width: 17px; height: 17px; }

.footer-col__title {
  margin: 0 0 15px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: light-dark(var(--muted-3), oklch(0.6 0.012 260));
}
.footer-col ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 11px; }
.footer-col li { font-size: 13.5px; line-height: 1.45; }
.footer-col a { color: light-dark(var(--muted-2), oklch(0.78 0.01 260)); }
.footer-col a:hover { color: light-dark(var(--ink), #fff); }
.footer-col--contacto .muted { color: light-dark(var(--muted-3), oklch(0.6 0.012 260)); }

/* ── Barra inferior ── */
.footer-bottom {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px 24px;
  padding-top: 24px;
  border-top: 1px solid light-dark(var(--line), oklch(0.3 0.02 260));
  font-size: 12.5px;
  color: light-dark(var(--muted-3), oklch(0.62 0.012 260));
}
.footer-bottom .by { display: inline-flex; align-items: center; gap: 8px; }
.footer-bottom .by img { height: 15px; opacity: .5; }
:root[data-scheme="dark"] .footer-bottom .by img { filter: brightness(0) invert(1); }
.footer-bottom .legal-links { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.footer-bottom .legal-links a {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: light-dark(var(--line-dash), oklch(0.4 0.02 260));
}
.footer-bottom .legal-links a:hover { color: light-dark(var(--ink), #fff); text-decoration-color: currentColor; }

@media (min-width: 640px) {
  .footer-main { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(28px, 3vw, 40px); }
  .footer-social a { width: 40px; height: 40px; }
  .footer-bottom { flex-direction: row; align-items: center; }
}
@media (min-width: 1100px) {
  .footer-main { grid-template-columns: minmax(230px, 1.35fr) repeat(4, minmax(120px, 1fr)); }
  .footer-brand { grid-column: auto; max-width: 330px; }
}

/* ══════════════════════════════════════════════════
   GUÍAS (tarjetas de enlace — home y 404)
══════════════════════════════════════════════════ */
.guias__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 16px;
}
.guia-card {
  display: block;
  background: var(--pill-bg);
  border: 1px solid var(--glass-line);
  border-radius: 16px;
  padding: 22px;
  color: var(--ink);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-sheen);
  transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.guia-card:hover {
  border-color: var(--btn-line-hover);
  color: var(--ink);
  transform: translateY(-2px);
  box-shadow: var(--sh-sm), inset 0 1px 0 var(--glass-sheen);
}
.guia-card .name { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 6px; }
.guia-card p { font-size: 13.5px; color: var(--muted-2); line-height: 1.5; }

/* Variante de los índices (hubs): la tarjeta lleva etiqueta de categoría
   encima y el título pesa más. Sustituye a los style="" que repetían
   font-size:17px y margin-bottom:8px en cada tarjeta. */
.guia-card--labeled .label { margin-bottom: 8px; }
.guia-card--labeled .name { font-size: 17px; }

/* ══════════════════════════════════════════════════
   MARQUEE DE ESCUDOS (prueba social)

   Tira infinita de logos inspirada en el componente "marquee" de
   21st.dev. La idea del bucle sin costura: la pista se escribe UNA vez
   en el HTML y el JS la clona; cada copia mide al menos el ancho del
   contenedor (min-width:100%) y las dos se desplazan un -100% de su
   propio ancho, así que cuando la primera termina de salir la segunda
   está justo donde arrancó la primera y el ciclo empalma.

   Los bordes se difuminan con una máscara, no con un degradado encima:
   la máscara no necesita saber de qué color es el fondo, así que la
   misma regla sirve en claro y en oscuro y sobre cualquier sección.

   Vive en site.css (y no en home.css) porque es un bloque que puede
   montar cualquier página copiando el <section class="clientes">.
══════════════════════════════════════════════════ */
.clientes {
  /* El padding lateral lo pone la .wrap del título: la tira tiene que
     llegar de borde a borde para que los escudos entren y salgan de la
     pantalla, no de una caja centrada. */
  padding-inline: 0;
  padding-block: clamp(44px, 7vh, 80px);
}
.clientes > .wrap { padding-inline: clamp(18px, 4vw, 40px); }
/* Título de la tira de escudos: no es una etiqueta sobre un titular
   (no hay ningún h2 debajo, esto ES el título), así que lleva su
   propia tipografía discreta en vez de la de .eyebrow. */
.clientes__titulo {
  text-align: center;
  margin-bottom: clamp(20px, 3vh, 32px);
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
}

.marquee {
  /* Velocidad en píxeles por segundo, no en duración: así la tira avanza
     igual de rápido con 6 escudos que con 26. El JS traduce esta cifra a
     --marquee-duration midiendo la pista; el valor de abajo es el respaldo
     por si el script no corre. */
  --marquee-speed: 48;
  --marquee-duration: 46s;
  --marquee-gap: clamp(34px, 6vw, 78px);
  display: flex;
  overflow: hidden;
  /* El difuminado de los extremos. El 12% es el ancho de la caída: lo
     justo para que un escudo no aparezca de golpe en el filo. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee__track {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  min-width: 100%;
  gap: var(--marquee-gap);
  /* space-around reparte el sobrante cuando hay pocos escudos: con
     flex-start se apilarían todos a la izquierda y quedaría un hueco
     girando por la pantalla. */
  justify-content: space-around;
  margin: 0;
  padding: 0 calc(var(--marquee-gap) / 2);
  list-style: none;
}
/* La animación se enciende solo cuando el JS ya clonó la pista: con una
   sola copia el desplazamiento dejaría un vacío del ancho de la tira. */
.marquee.is-live .marquee__track {
  animation: marquee-scroll var(--marquee-duration) linear infinite;
}
/* Detener al pasar el cursor deja leer un escudo concreto. El :focus-within
   hace lo mismo para quien recorre la página con el teclado. */
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }

.marquee__item { display: flex; align-items: center; flex: 0 0 auto; }
.marquee__logo {
  height: clamp(46px, 6vw, 64px);
  width: auto;
  max-width: 170px;
  object-fit: contain;
  display: block;
  /* Los escudos llegan con colores muy distintos entre colegios; bajarles
     un poco el contraste los deja convivir como una sola fila y devuelve
     el color entero al pasar por encima. */
  opacity: .82;
  filter: saturate(.35);
  transition: opacity .25s ease, filter .25s ease;
}
.marquee:hover .marquee__logo,
.marquee__logo:hover { opacity: 1; filter: none; }

@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}

/* La regla global de reduced-motion ya apaga la animación (animation:none),
   así que la tira se queda quieta con la primera copia llenando el ancho;
   solo hay que apagar aparte las transiciones y el gris. */
@media (prefers-reduced-motion: reduce) {
  .marquee__logo { transition: none; opacity: 1; filter: none; }
}

/* ══════════════════════════════════════════════════
   RESPONSIVE
══════════════════════════════════════════════════ */
@media (min-width: 640px) {
  .theme-btn { width: 40px; height: 40px; }
  button { min-height: 0; }
}

@media (min-width: 1000px) {
  .article-body__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 260px); }
  .article-aside { position: sticky; top: 90px; grid-template-columns: 1fr; }
}
