/* =============================================================================
   instilab.css — Sistema de diseño compartido de INSTILAB
   Tokens + base + componentes de armazón (breadcrumb, back-btn, page-hero, footer).
   Cárgalo en TODAS las páginas internas:  <link rel="stylesheet" href="/css/instilab.css">
   Cada página solo define su acento de sección con una línea, p. ej.:
       <style>:root{ --accent: var(--accent-4); }</style>   (cian para 1º ESO índice)
   Si no se define, el acento por defecto es el teal de ESO (--primary).
   La cabecera (logo + sesión/avatar) NO va aquí: se inyecta desde /js/auth.js.
   TEMA: oscuro por defecto (tokens de :root). El tema claro se activa con
   <html data-theme="light"> y vive al final del archivo (sección TEMA CLARO).
   Regla: ningún color literal en las reglas; todo pasa por un token.
   ============================================================================= */

:root {
  --primary: #66ffd1;
  --primary-dim: color-mix(in srgb, var(--primary) 10%, transparent);
  --primary-soft: color-mix(in srgb, var(--primary) 18%, transparent);
  --bg: #0a192f;
  --bg-soft: #0e2240;
  --card: #112240;
  --card-hover: #1a2f52;
  --text: #8892b0;
  --text-bright: #a8b2d1;
  --white: #e6f1ff;
  --accent-2: #ffb86c;
  --accent-3: #ff79c6;
  --accent-4: #8be9fd;
  --border: rgba(136,146,176,0.15);
  --radius: 10px;
  --radius-lg: 14px;

  /* Tokens añadidos para el tema claro (en oscuro valen EXACTAMENTE lo que
     antes estaba escrito a mano en cada regla: el aspecto oscuro no cambia). */
  --ok: #50fa7b;                        /* verde semántico de acierto / ejercicio */
  /* *** COLORES FIJOS CON NOMBRE, NO ACENTOS. ***
     Donde antes había un ámbar, un rosa o un verde escritos a mano, ahora hay
     estos tokens, y NO --accent-2/--accent-3/--ok. Esos los redefine la paleta
     de cada bloque: en 1º BACH --accent-2 es lila, y las notas importantes y las
     cajas de fórmulas pasaban de ámbar a lila en modo noche. Medido. */
  --ambar: #ffb86c;
  --rosa: #ff79c6;
  --verde: #50fa7b;
  --on-accent: #04132a;                 /* texto sobre un botón/insignia de acento */
  --overlay: rgba(4,10,24,.66);         /* velo de los modales */
  --shadow-modal: 0 20px 60px rgba(0,0,0,.5);
  --shadow-pop: 0 4px 16px rgba(0,0,0,.35);

  /* Acento de la sección. Cada página puede sobreescribirlo. */
  --accent: var(--primary);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg); color: var(--white);
  margin: 0; line-height: 1.7; -webkit-font-smoothing: antialiased;
}
.container { max-width: 1200px; width: 92%; margin: 0 auto; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }

/* ---- Breadcrumb ---- */
.breadcrumb { padding: 24px 0 8px; font-size: 0.85rem; color: var(--text); }
.breadcrumb a { color: var(--text-bright); transition: 0.15s; }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb .sep { margin: 0 8px; opacity: 0.6; }
.breadcrumb .current { color: var(--accent); font-weight: 600; }

/* ---- Botón volver ---- */
.back-btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 18px; border-radius: var(--radius);
  background: transparent; color: var(--text-bright);
  font-size: 0.88rem; font-weight: 600;
  border: 1px solid var(--border); transition: 0.2s; margin-bottom: 20px;
}
.back-btn:hover { color: var(--accent); border-color: var(--accent); }

/* ---- Cabecera de página (hero) ---- */
.page-hero { padding: 20px 0 50px; border-bottom: 1px solid var(--border); margin-bottom: 50px; }
.page-hero .eyebrow {
  display: inline-block; padding: 4px 12px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  border-radius: 20px; font-size: 0.75rem; font-weight: 700;
  letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 18px;
}
.page-hero h1 {
  font-size: clamp(1.8rem, 4.5vw, 3rem); font-weight: 800;
  line-height: 1.15; margin: 0 0 16px; letter-spacing: -1px;
}
.page-hero h1 .hl { color: var(--accent); }
.page-hero .lead { font-size: 1.1rem; color: var(--text-bright); max-width: 720px; margin: 0; }

/* ---- Footer ---- */
.site-footer { border-top: 1px solid var(--border); padding: 40px 0; margin-top: 40px; text-align: center; color: var(--text); font-size: 0.85rem; }
.site-footer nav { margin-bottom: 18px; display: flex; gap: 22px; justify-content: center; flex-wrap: wrap; }
.site-footer nav a { color: var(--text-bright); }
.site-footer nav a:hover { color: var(--accent); }

@media (max-width: 600px) {
  .page-hero { padding: 10px 0 30px; margin-bottom: 30px; }
}

/* =============================================================================
   PROBLEMAS ANCLADOS Y FIGURAS  ·  (render dinámico de /js/problemas.js)
   Añadido INSTILAB: tematiza las figuras line-art y estiliza el bloque de
   problemas, aviso de libro y modal. Todo con los tokens de arriba.
   ============================================================================= */

/* ---- Contenedor de un grupo de problemas anclado a su teoría ---- */
.problemas-ancla { margin: 1.4rem 0 .4rem; }
.problemas-ancla > .ancla-tit {
  font: 600 .8rem/1.2 'JetBrains Mono', ui-monospace, monospace;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--primary); opacity: .85; margin: .2rem 0 .6rem;
}

/* ---- Figuras: tarjeta oscura con rejilla + recolor automático del line-art ----
   Los SVG generados usan solo #111 (líneas/textos) y white (fondo); se
   recolorean por atributo sin regenerar nada. Aplica también sin login. */
.fig-problema, .fig-dsl, .fig-teoria {
  --fw-line: var(--accent-4);
  --fw-soft: #7fb0c9;
  background:
    linear-gradient(var(--primary-dim) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(90deg, var(--primary-dim) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(180deg, var(--card), var(--bg-soft));
  border: 1px solid var(--primary-soft);
  border-radius: var(--radius-lg);
  padding: .7rem; margin: 1rem auto; max-width: 440px; text-align: center;
}
.fig-problema svg, .fig-dsl svg, .fig-teoria svg,
.fig-problema img, .fig-dsl img {
  max-width: 100%; max-height: 240px; height: auto; width: auto;
  display: block; margin: 0 auto;
  filter: drop-shadow(0 0 2.5px color-mix(in srgb, var(--accent-4) 45%, transparent));
}
.fig-problema figcaption, .fig-dsl figcaption, .fig-teoria figcaption {
  font-style: italic; font-size: .8rem; opacity: .7; margin-top: .3rem; color: var(--text-bright);
}
.fig-problema svg [fill="white"], .fig-dsl svg [fill="white"], .fig-teoria svg [fill="white"] { fill: transparent; }
.fig-problema svg [stroke="#111"], .fig-dsl svg [stroke="#111"], .fig-teoria svg [stroke="#111"] { stroke: var(--fw-line); }
.fig-problema svg [fill="#111"], .fig-dsl svg [fill="#111"], .fig-teoria svg [fill="#111"] { fill: var(--fw-line); }
.fig-problema svg [fill="#555"], .fig-dsl svg [fill="#555"], .fig-teoria svg [fill="#555"] { fill: var(--fw-soft); }

/* ---- Aviso "haz los ejercicios del libro" + botón ---- */
.grupo-libro { margin: .6rem 0; }
.libro-resultados { margin-top: .6rem; }
.aviso-libro {
  border-left: 3px solid var(--primary); padding: .7rem .9rem;
  background: var(--primary-dim); border-radius: 0 6px 6px 0;
  display: flex; flex-wrap: wrap; gap: .6rem .9rem; align-items: center; justify-content: space-between;
}
.btn-ver-resultados {
  border: 1px solid var(--primary); background: transparent; color: var(--primary);
  border-radius: 6px; padding: .35rem .8rem; font: inherit; font-size: .85rem; transition: .15s;
}
.btn-ver-resultados:hover { background: var(--primary-dim); }

/* ---- Modal de confirmación (problemas de libro) ---- */
.ilab-modal-ov {
  position: fixed; inset: 0; z-index: 9999; padding: 1rem;
  background: var(--overlay);
  display: flex; align-items: center; justify-content: center;
}
.ilab-modal {
  max-width: 420px; width: 100%; padding: 1.4rem;
  background: var(--card); color: var(--white);
  border: 1px solid var(--primary-soft); border-radius: 12px;
  box-shadow: var(--shadow-modal);
}
.ilab-modal h3 { margin: 0 0 .6rem; font-size: 1.05rem; color: var(--primary); }
.ilab-modal p  { margin: 0 0 1.2rem; line-height: 1.5; font-size: .95rem; }
.ilab-modal .acciones { display: flex; gap: .6rem; justify-content: flex-end; }
.ilab-modal button { border-radius: 6px; padding: .45rem .9rem; font: inherit; }
.ilab-modal .m-no { border: 1px solid var(--border); background: transparent; color: inherit; }
.ilab-modal .m-si { border: 0; background: var(--primary); color: var(--on-accent); font-weight: 600; }
#ilab-reserva-problemas h2 { margin-top: 2rem; }

/* ---- Conmutador de idioma ES/VA ---- */
.ilab-lang-toggle{ position:fixed; top:12px; right:14px; z-index:1000;
  display:inline-flex; gap:2px; padding:3px; border-radius:999px;
  background:var(--bg-soft); border:1px solid var(--primary-soft); box-shadow:var(--shadow-pop); }
.ilab-lang-toggle button{ border:0; background:transparent; color:var(--text);
  font:600 .78rem/1 'JetBrains Mono', ui-monospace, monospace; letter-spacing:.05em;
  padding:.32rem .62rem; border-radius:999px; cursor:pointer; transition:.15s; }
.ilab-lang-toggle button:hover{ color:var(--primary); }
.ilab-lang-toggle button.on{ background:var(--primary); color:var(--on-accent); }

/* =============================================================================
   TARJETA DE PROBLEMA (render de problemas.js) — movida de los HTML de los
   bloques 1-3 a global, para que TODOS los bloques la pinten igual.
   Verde semántico --ok (#50fa7b en oscuro; el token --accent-3 es rosa: no se toca).
   ============================================================================= */
.ejercicio {
    background: color-mix(in srgb, var(--verde) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--verde) 25%, transparent);
    border-radius: var(--radius);
    margin: 26px 0;
    overflow: hidden;
}
.ejercicio-header {
    background: color-mix(in srgb, var(--verde) 10%, transparent);
    padding: 12px 20px;
    border-bottom: 1px solid color-mix(in srgb, var(--verde) 20%, transparent);
    display: flex; justify-content: space-between; align-items: center; gap: 12px;
    flex-wrap: wrap;
}
.ejercicio-header .ej-num {
    color: var(--verde);
    font-weight: 800;
    font-size: 0.95rem;
    letter-spacing: 0.5px;
    font-style: italic;
}
.ejercicio-header .ej-source {
    color: var(--text);
    font-size: 0.78rem;
    font-style: italic;
}
.ejercicio-body {
    padding: 18px 22px;
    color: var(--white);
}
.ejercicio-body p { color: var(--white); }
.ejercicio-body ol { color: var(--white); }
.ejercicio-body ul { color: var(--white); }
.ejercicio details {
    margin-top: 16px;
    border-top: 1px dashed color-mix(in srgb, var(--verde) 25%, transparent);
    padding-top: 14px;
}
.ejercicio details summary {
    cursor: pointer;
    color: var(--verde);
    font-weight: 700;
    font-size: 0.85rem;
    letter-spacing: 1px;
    text-transform: uppercase;
    list-style: none;
    user-select: none;
    display: inline-flex; align-items: center; gap: 8px;
}
.ejercicio details summary::-webkit-details-marker { display: none; }
.ejercicio details summary::before {
    content: '▶';
    font-size: 0.7em;
    transition: transform 0.2s;
}
.ejercicio details[open] summary::before { transform: rotate(90deg); }
.ejercicio details .solucion {
    padding: 12px 0 0;
    color: var(--text-bright);
}
.ejercicio details .solucion .paso {
    margin-bottom: 14px;
}
.ejercicio details .solucion .paso-titulo {
    color: var(--verde);
    font-weight: 700;
    font-size: 0.9rem;
    margin-bottom: 4px;
}

/* =============================================================================
   TEORÍA · contenido de bloque headless (inyectado por /js/teoria.js)
   Portado desde los bloques 1–3 a global para unificar la estructura web.
   Se tematiza con --accent-4/--accent-2/--accent-3 (semánticos) y el tope de
   tamaño de imagen + marco de "figura pendiente" viven aquí (antes se perdían
   al pasar el bloque a headless).
   ============================================================================= */
.section-intro { font-size: 1rem; color: var(--text-bright); padding: 0 0 18px; border-bottom: 1px solid var(--border); margin-bottom: 24px; }

/* ---- Cajas de definición / nota / pendiente ---- */
.definicion { background: var(--card); border: 1px solid var(--border); border-left: 3px solid var(--accent-4); border-radius: var(--radius); padding: 18px 22px; margin: 18px 0; }
.definicion .label { display: inline-block; font-size: .7rem; font-weight: 700; color: var(--accent-4); letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 6px; }
.definicion p:last-child { margin-bottom: 0; }
.nota-importante { background: color-mix(in srgb, var(--ambar) 6%, transparent); border: 1px solid color-mix(in srgb, var(--ambar) 30%, transparent); border-left: 3px solid var(--accent-2); border-radius: var(--radius); padding: 14px 18px; margin: 18px 0; font-size: .93rem; }
.nota-importante .label { display: inline-block; font-size: .7rem; font-weight: 700; color: var(--accent-2); letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 4px; }
.nota-importante p { color: var(--white); }
.nota-importante p:last-child { margin-bottom: 0; }
.pendiente-revision { background: color-mix(in srgb, var(--rosa) 6%, transparent); border: 1px dashed var(--accent-3); border-radius: var(--radius); padding: 12px 16px; margin: 16px 0; font-size: .88rem; color: var(--text-bright); }
.pendiente-revision .label { display: inline-block; font-size: .7rem; font-weight: 700; color: var(--accent-3); letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 4px; }
.pendiente-revision code { background: color-mix(in srgb, var(--rosa) 10%, transparent); color: var(--accent-3); }

/* ---- Caja de fórmulas (ámbar, estilo del PDF) ---- */
.formula-box { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0; margin: 18px 0; border: 1px solid color-mix(in srgb, var(--ambar) 40%, transparent); border-radius: var(--radius); overflow: hidden; background: color-mix(in srgb, var(--ambar) 4%, transparent); }
.formula-box .formula-cell { padding: 12px 16px; border-right: 1px solid color-mix(in srgb, var(--ambar) 25%, transparent); background: color-mix(in srgb, var(--ambar) 5%, transparent); }
.formula-box .formula-cell:last-child { border-right: none; }
.formula-box .formula-cell .ftitle { display: block; font-size: .72rem; font-weight: 700; color: var(--accent-2); letter-spacing: 1px; text-transform: uppercase; margin-bottom: 8px; text-align: center; }
.formula-box .formula-cell .feq { text-align: center; color: var(--white); font-size: 1.05rem; }

/* ---- Tablas ---- */
.table-wrapper { overflow-x: auto; margin: 18px 0; border-radius: var(--radius); border: 1px solid var(--border); }
table.data { width: 100%; border-collapse: collapse; font-size: .92rem; background: var(--card); }
table.data thead th { background: var(--bg-soft); color: var(--accent-4); text-align: left; padding: 12px 16px; font-weight: 700; font-size: .82rem; text-transform: uppercase; letter-spacing: 1px; border-bottom: 1px solid var(--border); }
table.data tbody td { padding: 11px 16px; border-bottom: 1px solid var(--border); color: var(--text-bright); }
table.data tbody tr:last-child td { border-bottom: none; }
table.data tbody tr:hover { background: var(--card-hover); }
table.data tbody td strong { color: var(--white); }

/* ---- Figuras (imagen real acotada) · tamaño de referencia INSTILAB (ajustado +33%) ---- */
.figura { margin: 22px auto; max-width: min(61%, 585px); background: rgba(255,255,255,.015); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; text-align: center; transition: border-color .2s ease, background .2s ease; }
.figura.wide  { max-width: min(90%, 850px); }
.figura.full  { max-width: 100%; }
.figura.small { max-width: min(72%, 690px); display: flex; align-items: center; gap: 18px; padding: 14px 16px; text-align: left; }
.figura.small img { flex: 0 0 170px; max-width: 170px; margin: 0; }
.figura.small figcaption, .figura.small figcaption strong { flex: 1; margin-top: 0; text-align: left; }
.figura:hover { border-color: color-mix(in srgb, var(--accent) 30%, transparent); background: color-mix(in srgb, var(--accent) 4%, transparent); }
.figura img { display: block; margin: 0 auto; max-width: 100%; max-height: 400px; width: auto; height: auto; border-radius: 6px; background: #fff; }
.figura figcaption { margin-top: 12px; font-size: .85rem; color: var(--text-bright); line-height: 1.5; text-align: center; }
.figura figcaption strong { display: block; color: var(--accent-4); font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 1.4px; margin-bottom: 6px; }
.figura figcaption .cap-desc { color: var(--text); font-size: .85rem; }

/* ---- Fallback: imagen que aún no está en el servidor (JS añade .img-missing) ---- */
.figura.img-missing { background: color-mix(in srgb, var(--rosa) 6%, transparent); border: 2px dashed var(--accent-3); min-height: 96px; display: flex; flex-direction: column; justify-content: center; }
.figura.img-missing img { display: none; }
.figura.img-missing::before { content: '🖼  Figura pendiente de subir · ' attr(data-src); display: block; color: var(--accent-3); font-size: .82rem; font-family: 'JetBrains Mono', ui-monospace, monospace; margin-bottom: 8px; padding: 10px 12px; background: color-mix(in srgb, var(--rosa) 8%, transparent); border-radius: 6px; }

/* ---- Figura embebida (grid imagen + texto) ---- */
.figura-inline { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: center; margin: 22px 0; }
.figura-inline .figura { margin: 0; max-width: none; }

@media (max-width: 768px) {
  .figura, .figura.small, .figura.wide { max-width: 100%; }
  .figura.small { display: block; text-align: center; padding: 14px; }
  .figura.small img { flex: none; max-width: 100%; margin: 0 auto; }
  .figura.small figcaption, .figura.small figcaption strong { text-align: center; margin-top: 12px; }
  .formula-box { grid-template-columns: 1fr; }
  .formula-box .formula-cell { border-right: none; border-bottom: 1px solid color-mix(in srgb, var(--ambar) 25%, transparent); }
  .formula-box .formula-cell:last-child { border-bottom: none; }
  .figura-inline { grid-template-columns: 1fr; }
}

/* =============================================================================
   ÍNDICE · subapartados de primer nivel (h3) — generados por teoria.js.
   Alta especificidad para NO heredar el contador numérico del índice base.
   ============================================================================= */
.toc ol .toc-sub { list-style: none; margin: 2px 0 6px; padding: 0 0 0 22px; }
.toc ol .toc-sub li { counter-increment: none; }
.toc ol .toc-sub a { display: block; padding: 5px 9px; font-size: .78rem; line-height: 1.35;
  color: var(--soft, #7d97b8); border-left: 2px solid transparent; border-radius: 8px; }
.toc ol .toc-sub a::before { content: none; }
.toc ol .toc-sub a:hover { color: var(--text-bright, #a8b2d1); background: var(--card-2, #16294a); text-decoration: none; }
.toc ol .toc-sub a.active { color: var(--accent); border-left-color: var(--accent); }

/* Mismo tratamiento en el índice del overlay móvil */
.mobile-toc-panel ol .toc-sub { list-style: none; margin: 2px 0 8px; padding: 0 0 0 20px; }
.mobile-toc-panel ol .toc-sub li { counter-increment: none; }
.mobile-toc-panel ol .toc-sub a { display: block; padding: 8px 10px; font-size: .84rem;
  color: var(--soft, #7d97b8); border-bottom: 1px solid var(--line, rgba(136,146,176,.12)); }
.mobile-toc-panel ol .toc-sub a::before { content: none; }
.mobile-toc-panel ol .toc-sub a.active { color: var(--accent); }

/* =============================================================================
   CONTENCIÓN DE DESBORDAMIENTO HORIZONTAL (móvil)
   Fórmulas KaTeX anchas y tablas grandes desbordaban a lo ancho; en iOS eso
   ensancha el layout viewport y empuja el header fijo (avatar) fuera de pantalla.
   Se hace que el contenido ancho haga scroll INTERNO en vez de desbordar la página.
   ============================================================================= */
#contenido-bloque { max-width: 100%; overflow-wrap: break-word; }
.feq, .formula-cell { max-width: 100%; overflow-x: auto; overflow-y: hidden; }
.katex-display { max-width: 100%; overflow-x: auto; overflow-y: hidden; }
#contenido-bloque p[style*="center"] { max-width: 100%; overflow-x: auto; overflow-y: hidden; }
/* Red de seguridad definitiva: en móvil (donde la barra lateral sticky está
   oculta) se impide el scroll horizontal a nivel de página. Así el layout
   viewport = viewport visible y el header fijo deja de salirse por la derecha.
   El contenido ancho (fórmulas/tablas) hace scroll interno, no se recorta. */
@media (max-width: 980px){ html, body { overflow-x: hidden; max-width: 100%; } }

/* CAUSA RAÍZ del header desplazado en B01: las actividades classify (.cls-wrap)
   y link (.link-row) usan rejillas de 2 columnas que solo se renderizan en los
   bloques con esas actividades. En móvil no encogen bajo su contenido y desbordan
   a lo ancho → ensanchan el viewport → empujan el header fijo. Se apilan a 1
   columna en pantallas estrechas. !important para vencer al <style> inline del shell. */
@media (max-width: 720px){
  .cls-wrap, .link-row { grid-template-columns: 1fr !important; }
}

/* =============================================================================
   FIN DE BLOQUE · felicitación + navegación entre bloques (genera teoria.js)
   ============================================================================= */
.bloque-fin { margin: 44px 0 18px; padding: 26px 22px; text-align: center;
  background: color-mix(in srgb, var(--accent) 8%, var(--card));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: var(--radius-lg); }
.bloque-fin .bf-badge { width: 46px; height: 46px; margin: 0 auto 12px; border-radius: 50%;
  display: grid; place-items: center; font-size: 1.35rem; font-weight: 800;
  background: var(--accent); color: var(--on-accent); }
.bloque-fin h3 { margin: 0 0 6px; font-size: 1.2rem; color: var(--white); }
.bloque-fin p { margin: 0 auto; max-width: 560px; color: var(--text-bright); font-size: .95rem; }

.block-nav { display: flex; flex-wrap: wrap; gap: 12px; margin: 8px 0 52px; }
.block-nav a { flex: 1 1 180px; display: flex; flex-direction: column; gap: 4px;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card); transition: border-color .2s ease, background .2s ease, transform .2s ease; }
.block-nav a:hover { border-color: var(--accent); background: var(--card-hover); transform: translateY(-2px); }
.block-nav a small { font-size: .72rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--accent); }
.block-nav a span { font-size: .9rem; font-weight: 600; color: var(--white); line-height: 1.3; }
.block-nav .bn-hub  { flex: 0 1 170px; text-align: center; align-items: center; }
.block-nav .bn-next { text-align: right; align-items: flex-end; }
@media (max-width: 720px){
  .block-nav { flex-direction: column; }
  .block-nav a, .block-nav .bn-hub, .block-nav .bn-next, .block-nav .bn-prev {
    text-align: center; align-items: center; justify-content: center; min-height: 64px; }
}

/* =============================================================================
   ACTIVIDADES link / order (global; el shell headless ya no las lleva).
   Usan tokens del shell (--line, --card-2, --bg-soft, --mono, --accent…).
   ============================================================================= */
.link-wrap{display:flex;flex-direction:column;gap:9px;margin-top:6px}
.link-row{display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:stretch}
.link-left{display:flex;align-items:center;padding:9px 12px;border:1px solid var(--line);border-radius:10px;background:var(--card-2);font-size:.9rem;font-weight:600}
.link-drop{min-height:44px;display:flex;align-items:center;flex-wrap:wrap;gap:6px}
.order-list{list-style:none;counter-reset:o;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:8px}
.order-item{counter-increment:o;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 13px;border:1px solid var(--line);border-radius:10px;background:var(--bg-soft)}
.order-item::before{content:counter(o);font-family:var(--mono);font-size:.78rem;color:var(--accent);flex:none;width:1.4em}
.order-txt{flex:1;font-size:.92rem}
.order-ctrls{display:flex;flex-direction:column;gap:3px;flex:none}
.ord-btn{font-size:.7rem;line-height:1;border:1px solid var(--line-strong);background:var(--card-2);color:var(--muted);border-radius:6px;padding:3px 7px;cursor:pointer}
.ord-btn:disabled{opacity:.3;cursor:default}

/* =============================================================================
   ÍNDICE PERMANENTE EN MÓVIL (patrón de B02): la barra lateral no se oculta,
   se muestra ARRIBA (debajo del hero/vídeo) como bloque estático, además de la
   píldora flotante. !important para vencer al display:none del shell.
   ============================================================================= */
@media (max-width: 980px){
  aside.toc { display: block !important; position: static !important; max-height: none !important; overflow: visible !important; margin-bottom: 8px; }
  aside.toc .toc-inner { max-height: none; }
  aside.toc .toc-sub { display: none; }          /* en el índice permanente móvil, solo secciones */
  .toc-show { display: none !important; }         /* en móvil no hay colapso lateral */
  body.toc-collapsed aside.toc { display: block !important; }
}

/* =============================================================================
   CONTENCIÓN EN EL ORIGEN (fix definitivo del header en móvil).
   El overflow-x:hidden en <body> NO siempre constriñe un position:fixed en móvil
   (iOS/Android calculan el header fijo sobre el ancho del contenido, no del body).
   Solución: recortar el desbordamiento horizontal en los PROPIOS contenedores
   donde teoria.js/problemas.js inyectan. Así nada del contenido puede ensanchar
   el viewport y empujar el header. 'clip' no crea scroll-container (no rompe nada).
   ============================================================================= */
@media (max-width: 980px){
  #hero-bloque, #contenido-bloque { overflow-x: clip; overflow-y: visible; }
}

/* =============================================================================
   FÓRMULAS KaTeX EN LÍNEA DENTRO DE PROSA (definiciones, notas, párrafos).
   Al renderizarse pueden superar el ancho de la columna en móvil VERTICAL
   (caben en horizontal, no en vertical) y desbordar la página, empujando el
   header fijo. Se hace que el párrafo portador haga scroll horizontal interno.
   Esto cubre lo que .feq / párrafos centrados no cubrían. ============================================================================= */
#contenido-bloque p, #contenido-bloque li { overflow-x: auto; }
#contenido-bloque .katex-display { overflow-x: auto; overflow-y: hidden; }

/* =============================================================================
   HEADER FIJO — eliminar promoción a capa GPU en REPOSO (fix del header ancho).
   auth.js promociona .ilab-bar con will-change:transform + transform:translateZ(0).
   En móvil, esa capa compuesta NO recalcula su geometría (ancho left:0/right:0)
   tras el reflow que provoca el render de KaTeX, y la barra queda más ancha que
   el viewport aunque NADA más lo sea. Se anula la promoción en reposo. La animación
   de auto-ocultar sigue intacta: .ilab-bar.ocultar aplica su transform con más
   especificidad e !important, así que gana cuando la barra se oculta al bajar. =============================================================================*/
#ilab-header .ilab-bar { transform: none !important; will-change: auto !important; }

/* =============================================================================
   CONTENEDOR DE FÓRMULA ANCHA (lo genera teoria.js → contenerFormulas).
   Acota la fórmula al ancho disponible y le da scroll horizontal propio, de modo
   que ni un frame desborde la pantalla (raíz del zoom-out del viewport en móvil).
   Solo se aplica a fórmulas más anchas que el viewport; las estrechas no se tocan. =============================================================================*/
.katex-fit { display: inline-block; max-width: 100%; overflow-x: auto; overflow-y: hidden; vertical-align: middle; }
.katex-fit::-webkit-scrollbar { height: 4px; }

/* =============================================================================
   CONTRASTE EN MODO NOCHE · dos textos que se quedaban cortos
   Medidos con prueba_tema.js el 22/09/2026: los datos de la franja de los hubs
   (4,43:1) y el pie del póster de vídeo de los bloques (4,3:1), por debajo de
   AA (4,5:1). Vivían en el <style> en línea de cada página; se corrigen aquí.
   El `body` delante es solo para ganar a la regla de la página, que va después.
   ============================================================================= */
body .info-strip .item { color: var(--text-bright); }
body .video-poster small { color: var(--muted, var(--text-bright)); }

/* =============================================================================
   TEMA CLARO  ·  <html data-theme="light">
   Motivo: en la pizarra digital/proyector el fondo oscuro refleja ventanas y
   fluorescentes y el negro proyectado se "lava"; el fondo claro se lee mejor.
   Criterios de la paleta (verificados por cálculo WCAG 2.x):
     · Texto principal ≥ 14:1 y secundario ≥ 6:1 sobre cualquier fondo del tema
       (holgura por encima de AA 4.5:1 para absorber la pérdida de contraste
       del proyector).
     · Acentos (teal, cian, ámbar, rosa, verde) ≥ 4.5:1 sobre todos los fondos:
       son los mismos tonos del tema oscuro, oscurecidos, no colores nuevos.
     · Fondo base gris-azulado, no blanco puro: menos deslumbramiento en
       proyección; las tarjetas sí son blancas para separarse del fondo.
   Especificidad: :root[data-theme="light"] (0,2,0) vence al :root{} (0,1,0)
   que cada shell define en su <style> en línea, sin necesidad de !important.
   ============================================================================= */
:root[data-theme="light"] {
  color-scheme: light;

  --primary: #006b58;
  /* *** MENOS LUZ, Y MÁS DIFERENCIA ENTRE UN BLANCO Y OTRO. ***
   * El blanco puro de las tarjetas sobre un fondo casi blanco deslumbraba en
   * pantalla y, peor, apenas se distinguían entre sí: las tarjetas no parecían
   * levantarse del fondo. Ahora el fondo baja un par de tonos y la tarjeta es un
   * blanco roto, no un blanco de papel: menos luz y más contraste entre ellos.
   * Las proporciones de contraste con el texto siguen igual de holgadas, porque
   * el texto no se toca. */
  --bg: #dde4ee;
  --bg-soft: #d0d9e6;
  --card: #eef2f8;
  --card-hover: #e2e9f3;
  --text: #4a5770;
  --text-bright: #334155;
  --white: #0f1b2d;          /* el token se llama "white" pero es el texto principal */
  /* --accent-2/3/4 NO se fijan aquí: se recalculan más abajo desde el valor de
     cada página. Fijarlos pisaba la paleta de cada bloque (en 1º BACH, B01,
     --accent-2 es lila y salía ámbar). */
  /* Un poco más marcado: con los fondos más próximos entre sí, la línea es lo
   * que separa una caja de otra. */
  --border: rgba(15,27,45,.20);

  --ok: #0f642f;
  --ambar: #8c4400;
  --rosa: #a3134f;
  --verde: #0f642f;
  --on-accent: #ffffff;
  --overlay: rgba(15,23,42,.45);
  --shadow-modal: 0 20px 50px rgba(15,23,42,.22);
  --shadow-pop: 0 4px 14px rgba(15,23,42,.14);

  /* Tokens que definen los shells en línea (y que este archivo ya consume) */
  --card-2: #e9eef5;
  --soft: #4f5f78;
  --muted: #4f5f78;
  --line: rgba(15,27,45,.12);
  --line-strong: rgba(15,27,45,.26);
  --warn: #a3134f;

  /* Tokens de las paletas de bloque (armazón clonado de cada curso) que no
     son acentos sino texto o fondo: se fijan, no se recalculan. */
  --ink: #0f1b2d;            /* texto principal en los armazones que lo usan */
  --ink-soft: #4a5770;
  --card2: #e9eef5;
  --navy-2: #e9eef5;
  --glow: rgba(0,107,88,.16);
  --shadow: 0 10px 28px rgba(15,23,42,.10);
}

/* *** EN LOS BLOQUES, --text ES EL TEXTO PRINCIPAL. ***
   En este archivo --text es el texto ATENUADO; en el armazón de los bloques
   headless (su <style> en línea) es el de LECTURA. Como el :root de arriba gana
   al del armazón, el cuerpo de todos los bloques salía gris medio en vez de
   casi negro: se lee, pero en el proyector es justo lo que hay que evitar.
   Se reconoce la página de bloque por #contenido-bloque, que solo existe ahí.
   Sin :has (navegadores muy viejos) se queda en gris medio: legible igual. */
:root[data-theme="light"]:has(#contenido-bloque) { --text: #0f1b2d; }

/* ---- Acentos heredados de la página, recalculados ----
   Cada armazón y cada hub fija sus acentos con hex neón literales, y cada curso
   trae su paleta (--tool, --c, --amber, --purple, --teal…). No se pueden
   reescribir sobre el mismo elemento sin crear un ciclo, así que se capturan en
   <body> y se recalculan en sus hijos: mismo tono (h) y croma (c), luminosidad
   fija 0.43, y la transparencia que tuvieran (los tintes siguen siendo tintes).
   Un token que la página no define queda sin definir, igual que antes: no
   aparece de la nada ningún color.
   Navegadores sin sintaxis relativa: color-mix hacia negro (algo menos fiel). */
:root[data-theme="light"] body {
  --accent-src: var(--accent);     --accent-2-src: var(--accent-2);
  --accent-3-src: var(--accent-3); --accent-4-src: var(--accent-4);
  --accent-5-src: var(--accent-5); --accent-warn-src: var(--accent-warn);
  --tool-src: var(--tool);         --tool-dim-src: var(--tool-dim);
  --c-src: var(--c);               --code-src: var(--code);
  --red-src: var(--red);           --cyan-src: var(--cyan);
  --teal-src: var(--teal);         --no-src: var(--no);
  --amber-src: var(--amber);       --purple-src: var(--purple);
  --green-src: var(--green);       --pink-src: var(--pink);
  --yellow-src: var(--yellow);     --line2-src: var(--line2);
  --primary-dim-src: var(--primary-dim); --primary-soft-src: var(--primary-soft);
  --accent-bach1-src: var(--accent-bach1); --accent-bach2-src: var(--accent-bach2);
}
:root[data-theme="light"] body > * {
  --accent: color-mix(in oklab, var(--accent-src) 52%, #000);
  --accent-2: color-mix(in oklab, var(--accent-2-src) 52%, #000);
  --accent-3: color-mix(in oklab, var(--accent-3-src) 52%, #000);
  --accent-4: color-mix(in oklab, var(--accent-4-src) 52%, #000);
  --accent-5: color-mix(in oklab, var(--accent-5-src) 52%, #000);
  --accent-warn: color-mix(in oklab, var(--accent-warn-src) 52%, #000);
  --tool: color-mix(in oklab, var(--tool-src) 52%, #000);
  --c: color-mix(in oklab, var(--c-src) 52%, #000);
  --code: color-mix(in oklab, var(--code-src) 52%, #000);
  --red: color-mix(in oklab, var(--red-src) 52%, #000);
  --cyan: color-mix(in oklab, var(--cyan-src) 52%, #000);
  --teal: color-mix(in oklab, var(--teal-src) 52%, #000);
  --no: color-mix(in oklab, var(--no-src) 52%, #000);
  --amber: color-mix(in oklab, var(--amber-src) 52%, #000);
  --purple: color-mix(in oklab, var(--purple-src) 52%, #000);
  --green: color-mix(in oklab, var(--green-src) 52%, #000);
  --pink: color-mix(in oklab, var(--pink-src) 52%, #000);
  --yellow: color-mix(in oklab, var(--yellow-src) 52%, #000);
  --accent-bach1: color-mix(in oklab, var(--accent-bach1-src) 52%, #000);
  --accent-bach2: color-mix(in oklab, var(--accent-bach2-src) 52%, #000);
}
@supports (color: oklch(from red l c h)) {
  :root[data-theme="light"] body > * {
    --accent: oklch(from var(--accent-src) 0.43 c h / alpha);
    --accent-2: oklch(from var(--accent-2-src) 0.43 c h / alpha);
    --accent-3: oklch(from var(--accent-3-src) 0.43 c h / alpha);
    --accent-4: oklch(from var(--accent-4-src) 0.43 c h / alpha);
    --accent-5: oklch(from var(--accent-5-src) 0.43 c h / alpha);
    --accent-warn: oklch(from var(--accent-warn-src) 0.43 c h / alpha);
    --tool: oklch(from var(--tool-src) 0.43 c h / alpha);
    --tool-dim: oklch(from var(--tool-dim-src) 0.43 c h / alpha);
    --c: oklch(from var(--c-src) 0.43 c h / alpha);
    --code: oklch(from var(--code-src) 0.43 c h / alpha);
    --red: oklch(from var(--red-src) 0.43 c h / alpha);
    --cyan: oklch(from var(--cyan-src) 0.43 c h / alpha);
    --teal: oklch(from var(--teal-src) 0.43 c h / alpha);
    --no: oklch(from var(--no-src) 0.43 c h / alpha);
    --amber: oklch(from var(--amber-src) 0.43 c h / alpha);
    --purple: oklch(from var(--purple-src) 0.43 c h / alpha);
    --green: oklch(from var(--green-src) 0.43 c h / alpha);
    --pink: oklch(from var(--pink-src) 0.43 c h / alpha);
    --yellow: oklch(from var(--yellow-src) 0.43 c h / alpha);
    --line2: oklch(from var(--line2-src) 0.43 c h / alpha);
    --primary-dim: oklch(from var(--primary-dim-src) 0.43 c h / alpha);
    --primary-soft: oklch(from var(--primary-soft-src) 0.43 c h / alpha);
    --accent-bach1: oklch(from var(--accent-bach1-src) 0.43 c h / alpha);
    --accent-bach2: oklch(from var(--accent-bach2-src) 0.43 c h / alpha);
  }
}

/* ---- Colores de acento escritos en el propio elemento (style="--acc:…") ----
   Las tarjetas de los hubs llevan su color en línea, una por bloque, y así
   escapan al recálculo de arriba: el acento en claro salía a 1,2:1. Se captura
   en la tarjeta y se recalcula en sus hijos, con la misma regla. La raya
   superior y el borde, que pinta la propia tarjeta, se quedan con el neón:
   son decoración. */
:root[data-theme="light"] [style*="--acc:"] { --acc-src: var(--acc); }
:root[data-theme="light"] [style*="--acc:"] > * { --acc: color-mix(in oklab, var(--acc-src) 52%, #000); }
@supports (color: oklch(from red l c h)) {
  :root[data-theme="light"] [style*="--acc:"] > * { --acc: oklch(from var(--acc-src) 0.43 c h / alpha); }
}

/* ---- Figuras line-art: en claro vuelven a trazo oscuro sobre rejilla suave,
   que es lo más nítido proyectado. Se quita el halo (en claro emborrona). ---- */
:root[data-theme="light"] .fig-problema,
:root[data-theme="light"] .fig-dsl,
:root[data-theme="light"] .fig-teoria {
  --fw-line: var(--white);
  --fw-soft: #4d6576;
}
:root[data-theme="light"] .fig-problema svg, :root[data-theme="light"] .fig-dsl svg,
:root[data-theme="light"] .fig-teoria svg, :root[data-theme="light"] .fig-problema img,
:root[data-theme="light"] .fig-dsl img { filter: none; }

/* ---- Figura con imagen real: en claro se le da tarjeta blanca ---- */
:root[data-theme="light"] .figura { background: var(--card); }

/* =============================================================================
   TEMA CLARO · LA PLANTILLA DE LOS BLOQUES HEADLESS
   -----------------------------------------------------------------------------
   Los bloques se pintan con el <style> en línea de su propio index.html, que es
   la MISMA plantilla en todos los cursos (comprobado en 1º ESO, 1º BACH y
   2º BACH). Ahí hay colores escritos a mano que no pasan por ningún token. Se
   corrigen aquí, en un solo sitio, en vez de tocar los 56 armazones: con el
   prefijo :root[data-theme="light"] estas reglas ganan a las del armazón sin
   necesidad de !important.
   ============================================================================= */

/* *** LAS NEGRITAS. *** El armazón dice `strong,b{color:#fff}`: en claro, todo
   el texto en negrita de todos los bloques quedaba blanco sobre blanco. */
:root[data-theme="light"] strong,
:root[data-theme="light"] b,
:root[data-theme="light"] table.data tr.hot td { color: var(--white); }

/* Texto oscuro sobre un botón o una ficha de acento: en claro el acento es
   oscuro, así que el texto va blanco. */
:root[data-theme="light"] .pill.active,
:root[data-theme="light"] .tf-btns button.sel-ok,
:root[data-theme="light"] .tf-btns button.sel-no,
:root[data-theme="light"] .chip.sel,
:root[data-theme="light"] .btn:not(.ghost) { color: var(--on-accent); }

/* Las filas alternas de las tablas se aclaraban con blanco: sobre blanco no se
   ven. Se oscurecen un pelo. */
:root[data-theme="light"] table.data tbody tr:nth-child(odd) { background: rgba(15,27,45,.03); }

/* Las líneas de fórmula tenían un fondo casi negro fijo, con el texto en el
   verde de acierto: en claro, verde oscuro sobre casi negro. */
:root[data-theme="light"] .eq { background: var(--card-2); }

/* El resplandor neón del título: en claro emborrona. */
:root[data-theme="light"] .hero h1 .glow { text-shadow: none; }

/* La píldora del índice en móvil: fondo azul noche fijo con el texto en blanco. */
:root[data-theme="light"] .mtoc-pill { background: rgba(255,255,255,.96); }
:root[data-theme="light"] .mtoc-text { color: var(--white); }

/* *** LOS SIMULADORES Y EL VÍDEO SE QUEDAN OSCUROS, COMO UNA PANTALLA. ***
   Los laboratorios dibujan en <canvas> con sus propios colores y sus mandos
   (interruptores, lámparas, bits, puertas, lecturas) llevan fondos casi negros
   fijos. Pasarlos a claro a medias dejaría piezas ilegibles. Se les devuelven
   los tokens del tema oscuro: por dentro son exactamente lo que eran, como un
   instrumento con su propia pantalla. Cuando se revisen los labs uno a uno, se
   podrán pasar a claro quitando esta regla. */
:root[data-theme="light"] .lab,
:root[data-theme="light"] .video-wrap,
:root[data-theme="light"] .ilab-isla {
  color-scheme: dark;
  --bg: #0a192f; --bg-soft: #0d1f3a; --card: #112240; --card-2: #16294a;
  --card-hover: #1a2f52; --primary: #66ffd1; --accent: var(--accent-src);
  --ok: #50fa7b; --warn: #ff79c6; --text: #e6f1ff; --muted: #9fb6d4;
  --soft: #7d97b8; --white: #e6f1ff; --text-bright: #a8b2d1; --ink: #e6f1ff;
  --ink-soft: #9fb3d1; --code: var(--code-src); --tool: var(--tool-src);
  --c: var(--c-src); --accent-2: var(--accent-2-src); --accent-3: var(--accent-3-src);
  --accent-4: var(--accent-4-src); --accent-5: var(--accent-5-src);
  --line: rgba(102,255,209,.16); --line-strong: rgba(102,255,209,.32);
  --border: rgba(136,146,176,.15); --on-accent: #04132a;
}
:root[data-theme="light"] .lab,
:root[data-theme="light"] .video-wrap { color: var(--text); }

/* *** LA RED DE SEGURIDAD (auth.js, revisarLegibilidad). ***
   `.ilab-isla` la pone auth.js en cualquier caja con fondo casi negro que haya
   en pantalla, venga de donde venga: recibe los tokens oscuros de arriba. Y si
   un texto sigue sin leerse (< 3:1), recibe uno de estos dos colores. El
   !important es a propósito: es el último recurso contra un texto invisible, y
   tiene que ganar a cualquier regla de cualquier página. */
:root[data-theme="light"] .ilab-legible-claro { color: #e6f1ff !important; }
:root[data-theme="light"] .ilab-legible-oscuro { color: #0f1b2d !important; }

/* =============================================================================
   TEMA CLARO · HUBS DE ETAPA Y DE CURSO
   Algún hub escribe el lila de PIAR II a mano (#bd93f9), también dentro de un
   atributo style. En claro es 2,3:1 sobre blanco. El !important es solo para
   poder alcanzar el color escrito en el atributo.
   ============================================================================= */
:root[data-theme="light"] [style*="color:#bd93f9"] { color: #6a3fb0 !important; }
:root[data-theme="light"] .c5::before { background: #6a3fb0 !important; }
:root[data-theme="light"] .c5:hover, :root[data-theme="light"] .c5:focus-visible,
:root[data-theme="light"] .c5.in-view { border-color: #6a3fb0 !important; }
:root[data-theme="light"] .c5 .curso-link { color: #6a3fb0; }
:root[data-theme="light"] .c5:hover .curso-link, :root[data-theme="light"] .c5:focus-visible .curso-link,
:root[data-theme="light"] .c5.in-view .curso-link { background: #6a3fb0; color: #fff; }

/* =============================================================================
   TEMA CLARO · LA PIZARRA Y EL MARCAPÁGINAS (gestion-bloque.js)
   El panel y sus ventanas se quedan oscuros: son una herramienta flotante,
   no contenido. La flecha ámbar se lee igual en los dos temas; lo que en claro
   se perdía es la raya discontinua y el resaltado del destino.
   ============================================================================= */
:root[data-theme="light"] .ilab-marca-linea { border-top-color: rgba(140,68,0,.55); }
:root[data-theme="light"] .pzm-destino { outline-color: #8c4400; }

/* =============================================================================
 * LA PANTALLA DE CARGA · INSTILAB
 * -----------------------------------------------------------------------------
 * Para pegar al final de instilab.css. No hay que tocar ninguna página.
 *
 * *** POR QUÉ EN CSS Y NO EN JAVASCRIPT. ***
 * Si la pintara un script, el día que un módulo falle al cargar la pantalla se
 * quedaría puesta para siempre y nadie sabría por qué. Aquí vive de una clase
 * que ya existe: mientras el documento no tenga `auth-ready` —la que pone
 * guard.js cuando ya sabe quién entra—, se ve; en cuanto la tiene, desaparece.
 * Si el CSS no cargara, tampoco pasaría nada: simplemente no habría animación.
 *
 * *** Y POR QUÉ HACE FALTA. ***
 * Las páginas internas esconden el cuerpo hasta saber quién eres. Eso evita que
 * se vea un instante lo que no toca, pero deja una pantalla en blanco de uno o
 * dos segundos —más en la red del instituto— donde no se distingue «cargando»
 * de «colgado». La gente recarga, y recargar durante un inicio de sesión es la
 * forma más rápida de acabar sin sesión.
 * ========================================================================== */

/* El velo: va en el <html>, no en el <body>, porque el cuerpo está oculto. */
html:not(.auth-ready)::before,
html.ilab-cargando::before {
  content: 'INSTILAB';
  position: fixed;
  inset: 0;
  z-index: 99999;

  display: flex;
  align-items: center;
  justify-content: center;

  background: #0a192f;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: clamp(1.8rem, 7vw, 3.4rem);
  font-weight: 800;
  letter-spacing: 0.08em;

  /* *** EL TEXTO SE RELLENA, NO PARPADEA. ***
   * Un parpadeo se lee como un error; algo que avanza se lee como que falta
   * poco. El relleno recorre la palabra de izquierda a derecha, en el turquesa
   * de la marca sobre el azul del fondo. */
  color: transparent;
  background-image: linear-gradient(
    100deg,
    rgba(100, 255, 218, 0.18) 0%,
    rgba(100, 255, 218, 0.18) 38%,
    #64ffda 50%,
    rgba(100, 255, 218, 0.18) 62%,
    rgba(100, 255, 218, 0.18) 100%);
  background-size: 300% 100%;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  animation: ilabCargando 1.5s linear infinite;
}

@keyframes ilabCargando {
  to { background-position: -100% 0; }
}

/* *** SI TARDA DE VERDAD, SE DICE. ***
 * Más de cinco segundos ya no es «un momento»: es una red lenta o algo que no
 * va. Decirlo evita que se recargue la página en mitad de un inicio de sesión,
 * que es como se acaba sin sesión. */
html:not(.auth-ready)::after,
html.ilab-cargando::after {
  content: 'Esto está tardando más de lo normal. No recargues: suele terminar solo.';
  position: fixed;
  left: 0;
  right: 0;
  bottom: 18%;
  z-index: 100000;

  text-align: center;
  padding: 0 24px;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 0.86rem;
  color: #8892b0;

  opacity: 0;
  animation: ilabTarda 0.4s linear 5s forwards;
}

html[lang^='ca']:not(.auth-ready)::after,
html[lang^='ca'].ilab-cargando::after {
  content: 'Això està tardant més del normal. No recarregues: sol acabar a soles.';
}

@keyframes ilabTarda {
  to { opacity: 1; }
}

/* *** QUIEN HAYA PEDIDO MENOS MOVIMIENTO, NO VE NINGUNO. ***
 * Sigue viendo la palabra y el fondo: lo que se quita es el barrido. */
@media (prefers-reduced-motion: reduce) {
  html:not(.auth-ready)::before,
  html.ilab-cargando::before {
    animation: none;
    color: #64ffda;
    background-image: none;
  }
  html:not(.auth-ready)::after,
  html.ilab-cargando::after { animation: none; opacity: 1; }
}

/* -----------------------------------------------------------------------------
 * PARA LO QUE NO ES LA CARGA INICIAL
 * -----------------------------------------------------------------------------
 * La clase `ilab-cargando` en el <html> enseña lo mismo en cualquier otro
 * momento: mientras se inicia sesión, mientras se canjea una tarjeta o mientras
 * se guarda algo que tarda. Se pone y se quita desde el script que espera:
 *
 *   document.documentElement.classList.add('ilab-cargando');
 *   try { ... } finally { document.documentElement.classList.remove('ilab-cargando'); }
 *
 * *** SIEMPRE EN UN `finally`. ***
 * Si la operación falla y nadie quita la clase, la pantalla se queda puesta y el
 * fallo se convierte en una página colgada.
 * ========================================================================== */
