/* =============================================================================
   tna.css — Estilos de la plataforma. CSS nativo, sin preprocesador.
   -----------------------------------------------------------------------------
   EL CARMESÍ NO PUEDE SER TEXTO SOBRE NEGRO

   #560216 sobre #0d0d0d da 1,31:1 de contraste; el mínimo legible es 4,5:1. En
   cuanto el fondo es negro, el color de marca deja de servir para escribir:
   quedaría un texto que en la maqueta se ve porque uno ya sabe lo que pone. Se
   usa como SUPERFICIE —botones, barras, bordes— donde encima va blanco (14,8:1)
   y como acento aclarado (--acento, 5,5:1) cuando hace falta color en un texto.

   Todos los pares de este fichero están comprobados contra WCAG AA.

   NADA DE ESTILOS EN LÍNEA EN LAS PLANTILLAS: la cabecera CSP que pone
   paginas.ts es `style-src 'self'`, así que un `style="..."` no se aplicaría.
   Es deliberado: obliga a que todo esté aquí.
   ========================================================================== */

:root {
  --fondo: #0d0d0d;
  --superficie: #141414;
  --superficie-alta: #1a1a1a;
  --borde: #2a2626;
  --borde-vivo: #3a3434;

  --carmesi: #560216;
  --carmesi-vivo: #6d0320;
  --acento: #d4667c;          /* 5,54:1 sobre el fondo — para texto */

  --texto: #efeeee;           /* 16,78:1 */
  --secundario: #9a9494;      /*  6,51:1 */
  --tenue: #8a8280;           /*  5,17:1 */

  --serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --sans: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono: 'DM Mono', ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', monospace;

  --ancho: 1080px;
  --radio: 10px;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

h1, h2, h3 { font-family: var(--serif); font-weight: 500; line-height: 1.2; margin: 0; }
p { margin: 0; }

a { color: var(--acento); }
a:hover { color: var(--texto); }

/* Foco visible SIEMPRE. Quitarlo es dejar el teclado sin brújula. */
:focus-visible { outline: 2px solid var(--acento); outline-offset: 3px; border-radius: 4px; }

.saltar {
  position: absolute; left: -9999px;
  background: var(--carmesi); color: #fff; padding: 10px 16px; z-index: 10;
}
.saltar:focus { left: 8px; top: 8px; }

.contenedor { width: 100%; max-width: var(--ancho); margin: 0 auto; padding: 0 20px; }

.oculto { display: none !important; }

/* --- Cabecera ------------------------------------------------------------ */
.cabecera { border-bottom: 1px solid var(--borde); background: var(--fondo); }
.cabecera__fila {
  display: flex; align-items: center; gap: 20px;
  flex-wrap: wrap; padding-top: 14px; padding-bottom: 14px;
}
.marca { text-decoration: none; color: inherit; display: block; margin-right: auto; }
.marca__lema {
  display: block; font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--tenue);
}
.marca__nombre { display: block; font-family: var(--serif); font-size: 20px; color: var(--texto); }

.nav { display: flex; flex-wrap: wrap; gap: 4px; }
.nav__enlace {
  color: var(--secundario); text-decoration: none; font-size: 14px;
  padding: 7px 12px; border-radius: var(--radio); border: 1px solid transparent;
}
.nav__enlace:hover { color: var(--texto); background: var(--superficie); }
.nav__enlace.es-activo { color: var(--texto); border-color: var(--carmesi); background: var(--superficie); }

.sesion { display: flex; align-items: center; gap: 12px; }
/* Era texto suelto sin caja propia: 22,4px de alto real, por debajo incluso
   del minimo absoluto de 24px de WCAG 2.5.8, y eso vale para el raton igual
   que para el dedo. Ahora es una caja con area propia, con el mismo trato
   visual que .campana para que las dos piezas de la sesion se lean iguales. */
.sesion__nombre {
  display: inline-flex; align-items: center;
  font-size: 14px; color: var(--secundario); text-decoration: none;
  padding: 7px 12px; border-radius: var(--radio); border: 1px solid transparent;
}
.sesion__nombre:hover, .sesion__nombre:focus-visible {
  color: var(--texto); border-color: var(--borde-vivo);
}
.sesion form { margin: 0; }

/* --- Botones ------------------------------------------------------------- */
.boton {
  display: inline-block; font-family: var(--sans); font-size: 15px; font-weight: 500;
  padding: 11px 20px; border-radius: var(--radio); border: 1px solid var(--borde-vivo);
  background: var(--superficie); color: var(--texto);
  text-decoration: none; cursor: pointer; text-align: center;
}
.boton:hover { background: var(--superficie-alta); color: var(--texto); }
.boton--carmesi { background: var(--carmesi); border-color: var(--carmesi); color: #ffffff; }
.boton--carmesi:hover { background: var(--carmesi-vivo); border-color: var(--carmesi-vivo); color: #ffffff; }
.boton--tenue { background: transparent; color: var(--secundario); }
.boton--ancho { width: 100%; }
.boton--grande { font-size: 17px; padding: 14px 28px; }
.boton[disabled] { opacity: .5; cursor: progress; }

/* --- Contenido ----------------------------------------------------------- */
.principal { flex: 1; padding-top: 44px; padding-bottom: 64px; }

.ojo {
  font-size: 11px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--tenue); margin-bottom: 12px;
}
.titular { font-size: clamp(30px, 5vw, 48px); max-width: 20ch; margin-bottom: 18px; }
.titulo { font-size: clamp(24px, 4vw, 32px); margin-bottom: 14px; }
.entradilla { color: var(--secundario); font-size: 17px; max-width: 56ch; margin-bottom: 28px; }
.acciones { margin-top: 24px; }

.portada { padding: 24px 0 56px; }

.rejilla {
  display: grid; gap: 16px; margin-top: 32px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.tarjeta {
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: var(--radio); padding: 22px;
}
.tarjeta--ancha { grid-column: 1 / -1; margin-top: 28px; }
.tarjeta__titulo { font-size: 19px; margin-bottom: 8px; }
.tarjeta__texto { color: var(--secundario); font-size: 15px; }
.tarjeta__fase {
  margin-top: 12px; font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--tenue);
}

/* --- Formularios --------------------------------------------------------- */
.panel-estrecho { max-width: 460px; margin: 0 auto; }
.panel-estrecho--centro { text-align: center; }

.forma { display: flex; flex-direction: column; gap: 14px; margin-top: 22px; }
.forma__ayuda { color: var(--secundario); font-size: 15px; }

.campo { display: block; }
.campo__etiqueta { display: block; font-size: 13px; color: var(--secundario); margin-bottom: 6px; }
.campo__opcional { color: var(--tenue); font-size: 12px; }
/* La pista bajo un campo: qué formatos y qué tamaño se admiten. `block`
   porque va DEBAJO del control, no pegada a su derecha. */
.campo__ayuda { display: block; margin-top: 6px; color: var(--tenue); font-size: 13px; }
/* Un `input[type=file]` con el padding de una caja de texto deja el botón
   del navegador descentrado y la caja demasiado alta. */
.campo__control[type="file"] { padding: 9px 12px; font-size: 15px; cursor: pointer; }
.campo__control {
  width: 100%; font-family: var(--sans); font-size: 16px;   /* 16px: menos hace que iOS haga zoom */
  padding: 12px 14px; border-radius: var(--radio);
  border: 1px solid var(--borde-vivo); background: var(--superficie-alta); color: var(--texto);
}
.campo__control::placeholder { color: #6f6a68; }
.campo__control:focus { border-color: var(--acento); outline: none; }
.campo__control--codigo {
  font-family: var(--mono); font-size: 28px; letter-spacing: .32em;
  text-align: center; padding: 14px;
}

.aviso {
  margin-top: 18px; padding: 12px 14px; border-radius: var(--radio);
  border: 1px solid var(--carmesi); background: #1a0509;
  color: var(--texto); font-size: 14px;
}
.aviso--suave { border-color: var(--borde-vivo); background: var(--superficie); color: var(--secundario); }

/* --- Onboarding ---------------------------------------------------------- */
.pasos { display: flex; gap: 8px; list-style: none; margin: 0 0 28px; padding: 0; }
.pasos__item {
  flex: 1; display: flex; align-items: center; gap: 8px;
  font-size: 13px; color: var(--tenue);
  padding: 9px 12px; border-radius: var(--radio);
  border: 1px solid var(--borde); background: var(--superficie);
}
.pasos__item.es-activo { color: var(--texto); border-color: var(--carmesi); }
.pasos__item.es-hecho { color: var(--secundario); }
.pasos__numero {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  background: var(--superficie-alta); font-family: var(--mono); font-size: 12px;
}
.pasos__item.es-activo .pasos__numero { background: var(--carmesi); color: #fff; }

.opciones { display: grid; gap: 12px; margin-top: 22px; }
.opcion {
  display: block; text-align: left; cursor: pointer;
  padding: 18px; border-radius: var(--radio);
  border: 1px solid var(--borde-vivo); background: var(--superficie); color: var(--texto);
  font-family: var(--sans);
}
.opcion:hover { border-color: var(--carmesi); background: var(--superficie-alta); }
.opcion__titulo { display: block; font-family: var(--serif); font-size: 19px; margin-bottom: 4px; }
.opcion__texto { display: block; color: var(--secundario); font-size: 14px; }

/* --- Paneles ------------------------------------------------------------- */
.cabecera-panel { margin-bottom: 8px; }
.pastilla {
  display: inline-block; font-size: 12px; font-family: var(--mono);
  padding: 2px 9px; margin-right: 6px; border-radius: 999px;
  border: 1px solid var(--borde-vivo); color: var(--texto);
}
.codigo-enlace {
  font-family: var(--mono); font-size: 15px; word-break: break-all;
  background: var(--superficie-alta); border: 1px solid var(--carmesi);
  border-radius: var(--radio); padding: 12px 14px; margin: 12px 0 18px;
}
.metricas { display: flex; flex-wrap: wrap; gap: 28px; margin: 0 0 16px; }
.metrica dt { font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--tenue); }
.metrica dd { margin: 4px 0 0; font-family: var(--mono); font-size: 26px; color: var(--texto); }

/* --- Fase 4 · Paneles ----------------------------------------------------- */

/* La campana. No es un icono SVG a propósito: la palabra «Avisos» la lee
   cualquiera, no depende de que un glifo cargue y no hay que mantener un
   sprite. La cuenta va en un círculo pegado, como en cualquier bandeja. */
.campana {
  position: relative; text-decoration: none; color: var(--secundario);
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  padding: 6px 10px; border-radius: var(--radio); border: 1px solid transparent;
}
.campana:hover, .campana:focus-visible { color: var(--texto); border-color: var(--borde-vivo); }
.campana.es-activo { color: var(--texto); border-color: var(--carmesi); }
.campana__cuenta {
  display: inline-block; min-width: 20px; margin-left: 6px; padding: 1px 6px;
  border-radius: 999px; background: var(--carmesi); color: #fff;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0; text-align: center;
}

/* El avatar. `object-fit: cover` para que una foto rectangular no salga
   deformada, que es lo que pasa por defecto con width y height fijos. */
.avatar-fila { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.avatar {
  width: 72px; height: 72px; border-radius: 50%; object-fit: cover;
  border: 1px solid var(--borde-vivo); flex: none;
}
.avatar--vacio {
  display: grid; place-items: center; background: var(--superficie-alta);
  font-family: var(--serif); font-size: 30px; color: var(--secundario);
}

/* El facilitador en la ficha pública del módulo.
   `--grande` es la MISMA pieza a otro tamaño y no un avatar distinto: aquí la
   foto es contenido —es a quien se le compra— y no un adorno de la cabecera.
   La inicial crece con ella para que el hueco de quien aún no tiene foto no se
   vea como un fallo de maqueta. */
.avatar--grande { width: 96px; height: 96px; }
.avatar--grande.avatar--vacio { font-size: 40px; }
/* `min-width: 0` porque un hijo de flex no encoge por debajo de su contenido
   (`min-width: auto`), y sin esto un párrafo con una palabra larga —una URL que
   alguien pegue en su biografía— empuja la caja y arrastra la página en
   horizontal a 380 px. Es exactamente lo que le pasó a `.buscador__fila`. */
.ficha__facilitador-texto { flex: 1 1 320px; min-width: 0; }
.ficha__facilitador-nombre {
  font-family: var(--serif); font-size: 22px; margin: 0 0 10px;
}
.ficha__facilitador-texto .parrafo { margin: 0 0 10px; }
.ficha__facilitador-texto .parrafo:last-child { margin-bottom: 0; }

/* Notificaciones. La barra carmesí de la izquierda marca lo no leído: el
   color solo no vale —hay quien no lo distingue— y por eso la plantilla pone
   además la pastilla «nuevo». Nunca sólo color. */
.avisos { list-style: none; margin: 20px 0 0; padding: 0; }
.avisos__item {
  border: 1px solid var(--borde); border-left: 3px solid transparent;
  border-radius: var(--radio); padding: 16px 18px; margin-bottom: 12px;
  background: var(--superficie);
}
.avisos__item.es-nuevo { border-left-color: var(--carmesi); background: var(--superficie-alta); }
.avisos__titulo { font-size: 16px; margin-bottom: 4px; }
.avisos__texto { color: var(--secundario); font-size: 15px; }
.avisos__pie {
  margin-top: 10px; display: flex; gap: 12px; align-items: center;
  flex-wrap: wrap; color: var(--tenue); font-size: 13px;
}

/* Métricas destacadas del panel de administración. */
.metrica--destacada dd { font-size: 34px; color: var(--acento); }
.metrica__grande {
  font-family: var(--mono); font-size: 34px; line-height: 1.1;
  margin: 6px 0 8px; color: var(--texto);
}
/* Lo que espera decisión y no es cero. Borde, no sólo color de fondo: sobre
   negro un tinte apenas se ve, y la tarjeta tiene que cantar. */
.tarjeta--urgente { border-color: var(--carmesi); }
.tarjeta--urgente .metrica__grande { color: var(--acento); }

/* Reparto de roles. */
.roles-actuales { margin: 12px 0 10px; min-height: 26px; }
.roles-botones { display: flex; flex-wrap: wrap; gap: 8px; }
.roles-botones .boton { font-size: 13px; padding: 6px 12px; }

.nota-pie { margin-top: 32px; color: var(--tenue); font-size: 13px; }

/* --- Pie ----------------------------------------------------------------- */
.pie { border-top: 1px solid var(--borde); padding: 26px 0; }
.pie__marca { font-family: var(--serif); font-size: 16px; }
.pie__nota { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--tenue); }
/* Tres enlaces desde LEG-02/LEG-03 (antes era uno). `flex` con `gap` y no
   separadores escritos a mano: en movil los tres miden 44 px de alto por la
   regla de `pointer: coarse`, y pegados serian tres objetivos tactiles sin
   aire entre ellos. El `wrap` los apila cuando no caben, que a 380 px es
   siempre. */
.pie__enlaces {
  margin-top: 12px; font-size: 13px;
  display: flex; flex-wrap: wrap; gap: 2px 20px;
}
.pie__enlaces a { color: var(--secundario); text-decoration: none; }
.pie__enlaces a:hover, .pie__enlaces a:focus-visible { color: var(--texto); }

@media (max-width: 620px) {
  .cabecera__fila { gap: 12px; }
  .nav { order: 3; width: 100%; }
  .pasos { flex-direction: column; }
  .metricas { gap: 20px; }
}

/* --- Areas tactiles ------------------------------------------------------ */
/* Con un dedo, 33px no es un objetivo: es una apuesta. Apple pide 44px y WCAG
   2.5.8 fija 24px como minimo absoluto.
   Se filtra por `pointer: coarse` y NO por ancho de pantalla porque lo que
   decide no es cuanto mide el viewport sino con que se toca: una tablet de
   1024px se navega con el dedo igual que un movil, y un escritorio con raton
   no necesita crecer. Asi el diseno de escritorio queda intacto.
   `min-height` + `inline-flex` en vez de subir el padding: la altura queda
   garantizada sin depender de la interlinea de cada regla, que es justo lo
   que hacia que estos seis elementos midieran seis cosas distintas. */
@media (pointer: coarse) {
  .nav__enlace,
  .campana,
  .sesion__nombre,
  /* Anadido 2026-08-31: el enlace del pie a la politica de devoluciones nacio
     con 17 px de alto —por debajo del minimo absoluto de 24 px de WCAG 2.5.8—
     y lo cazo `probar-onboarding-380.mjs` en las SEIS pantallas a la vez, que
     es la ventaja de que el pie sea comun. Entro con WP-08 y se fue con la
     primera corrida de ONB-04 posterior al despliegue. */
  .pie__enlaces a {
    display: inline-flex; align-items: center; min-height: 44px;
  }

  /* .boton es inline-block y centra con `text-align`. Al pasar a flex hay que
     centrar con `justify-content`, o `.boton--ancho` (width:100%) dejaria el
     texto pegado a la izquierda. */
  .boton {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px;
  }

  /* Corregido 2026-09-01: `.lateral__leccion` estaba en la lista de arriba y
     por eso el <li> del temario medía 44 px. Pero el <li> no se pulsa: se
     pulsa el <a> de dentro, que seguía midiendo su línea —22,4 px medidos a
     380 px por `probar-380-catalogo-paneles.mjs`—, así que 11 px por arriba y
     11 por abajo de cada lección no respondían al dedo. Agrandar el
     contenedor no agranda el objetivo, y es un fallo que sólo se ve midiendo
     el elemento que recibe el toque.
     El <li> conserva sus 44 px y el <a> se estira dentro (`stretch`): el
     temario se ve exactamente igual, lo que cambia es cuánto de él se toca. */
  .lateral__leccion {
    display: inline-flex; align-items: stretch; min-height: 44px;
  }
  .lateral__leccion a { display: flex; align-items: center; width: 100%; }
}

/* Quien pide menos movimiento, menos movimiento. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* --- Catálogo, ficha y visor (Fase 2) ------------------------------------ */
/* Las clases de aquí abajo siguen la misma regla que las de arriba: el carmesí
   es superficie o borde, nunca texto. El precio va en --acento (5,54:1). */

.portada--corta { padding-bottom: 32px; }

.enlace-limpio { color: inherit; text-decoration: none; }
.enlace-limpio:hover { color: var(--acento); }

.buscador { margin-top: 22px; max-width: 520px; }
/* `wrap` y no `nowrap`: un flex item no encoge por debajo de su contenido
   (`min-width: auto`), así que una fila de cinco campos con dos `type="date"`
   no cabe en 380 px por mucho que su `flex-basis` diga 160. Sin esto, la fila
   del filtro de /admin/comprobantes se salía 229 px del viewport y arrastraba
   la página entera en horizontal — medido el 03/09. */
.buscador__fila { display: flex; gap: 8px; flex-wrap: wrap; }
.buscador__fila .campo__control { flex: 1; }

/* LOG-07 · La barra del rechazo en lote, encima de la cola de comprobantes.
   `flex-wrap` y `campo--crece` por lo mismo que la fila del filtro de aquí
   arriba: en 380 px el motivo y el botón no caben en una línea, y un flex item
   no encoge por debajo de su contenido. Sin el salto, la barra se saldría del
   viewport y arrastraría la página en horizontal. */
.lote {
  margin: 18px 0 4px; padding: 14px;
  border: 1px solid var(--borde); border-radius: var(--radio);
  background: var(--superficie-alta);
}
.lote__fila { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }
/* La barra ya trae su propio margen; el del campo y el de `.acciones` (24 px)
   descolocarían el botón respecto al recuadro del motivo. */
.lote .campo--crece { margin-bottom: 0; }
.lote .acciones { margin-top: 0; }
.lote__accion { margin-top: 12px; }

.precio { font-family: var(--mono); font-size: 18px; color: var(--acento); }
.precio--grande { font-size: 30px; }
.precio__nota { font-size: 13px; color: var(--tenue); margin-top: 4px; }

.paquete {
  display: grid; gap: 24px; margin-top: 32px; padding: 26px;
  grid-template-columns: 1fr; align-items: start;
  border: 1px solid var(--carmesi); border-radius: var(--radio);
  background: var(--superficie);
}
.paquete__precio { border-top: 1px solid var(--borde); padding-top: 18px; }
.bonos { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 8px; }
.bonos__item {
  color: var(--secundario); font-size: 15px; padding-left: 18px; position: relative;
}
.bonos__item::before {
  content: ''; position: absolute; left: 0; top: 9px;
  width: 8px; height: 8px; border-radius: 2px; background: var(--carmesi);
}

.tarjeta--curso { display: flex; flex-direction: column; gap: 6px; }
.tarjeta__orden { font-family: var(--mono); font-size: 12px; color: var(--tenue); }
.tarjeta__pie { display: flex; align-items: baseline; gap: 14px; margin-top: auto; padding-top: 12px; }
.tarjeta__dato { font-size: 13px; color: var(--tenue); }
.tarjeta__estado { font-size: 13px; color: var(--acento); }

/* --- Ficha --------------------------------------------------------------- */
.ficha__cabecera { padding-bottom: 8px; }
.ficha__datos { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; margin-top: 8px; }
.ficha__bloque { margin-top: 36px; }
.parrafo { color: var(--secundario); max-width: 68ch; white-space: pre-line; }
.lista { color: var(--secundario); margin: 12px 0 0; padding-left: 20px; }
.lista li { margin-bottom: 6px; }

.modulo { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--borde); }
.modulo__titulo { font-size: 17px; margin-bottom: 8px; }
.lecciones { list-style: none; margin: 10px 0 0; padding: 0; counter-reset: leccion; }
.leccion-fila {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--borde); font-size: 15px;
}
.leccion-fila.es-hecha .leccion-fila__titulo,
.leccion-fila.es-hecha a { color: var(--tenue); }
.leccion-fila__marcas { display: flex; gap: 8px; align-items: baseline; flex: none; }

/* --- Visor --------------------------------------------------------------- */
.visor { display: grid; gap: 28px; grid-template-columns: 1fr; }
.visor__lateral {
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: var(--radio); padding: 18px; align-self: start;
}
.lateral__modulo { font-size: 14px; margin: 18px 0 6px; color: var(--secundario); }
.lateral__lecciones { list-style: none; margin: 0; padding: 0; }
.lateral__leccion { font-size: 14px; padding: 6px 8px; border-radius: 6px; }
.lateral__leccion.es-activa { background: var(--superficie-alta); border-left: 3px solid var(--carmesi); }
.lateral__leccion.es-hecha a { color: var(--tenue); }

.marco {
  position: relative; width: 100%; aspect-ratio: 16 / 9; margin-top: 18px;
  background: #000; border: 1px solid var(--borde); border-radius: var(--radio);
  overflow: hidden;
}
.marco__video { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.progreso {
  margin-top: 22px; padding: 16px; border-radius: var(--radio);
  border: 1px solid var(--borde); background: var(--superficie);
}
.progreso__estado { font-family: var(--mono); font-size: 14px; margin-bottom: 10px; }

/* La barra se pinta con una clase por tramo de 5 %. No es elegante y es la
   consecuencia de `style-src 'self'`: un `style="width:37%"` no se aplicaría.
   Con 21 tramos la barra se ve bien y no hace falta bajar la CSP. */
.barra {
  height: 6px; border-radius: 999px; background: var(--superficie-alta);
  overflow: hidden; margin: 10px 0 4px;
}
.barra__relleno { height: 100%; background: var(--carmesi); }
.barra__relleno--0 { width: 0%; }
.barra__relleno--5 { width: 5%; }
.barra__relleno--10 { width: 10%; }
.barra__relleno--15 { width: 15%; }
.barra__relleno--20 { width: 20%; }
.barra__relleno--25 { width: 25%; }
.barra__relleno--30 { width: 30%; }
.barra__relleno--35 { width: 35%; }
.barra__relleno--40 { width: 40%; }
.barra__relleno--45 { width: 45%; }
.barra__relleno--50 { width: 50%; }
.barra__relleno--55 { width: 55%; }
.barra__relleno--60 { width: 60%; }
.barra__relleno--65 { width: 65%; }
.barra__relleno--70 { width: 70%; }
.barra__relleno--75 { width: 75%; }
.barra__relleno--80 { width: 80%; }
.barra__relleno--85 { width: 85%; }
.barra__relleno--90 { width: 90%; }
.barra__relleno--95 { width: 95%; }
.barra__relleno--100 { width: 100%; }

.candado {
  margin-top: 18px; padding: 26px; text-align: center;
  border: 1px solid var(--carmesi); border-radius: var(--radio); background: var(--superficie);
}
.paso-a-paso { display: flex; gap: 10px; margin-top: 28px; flex-wrap: wrap; }

/* --- Buscador ------------------------------------------------------------ */
.panel-estrecho--ancho { max-width: 720px; }
.resultados__cuenta { margin-top: 22px; }
.resultados { list-style: none; margin: 12px 0 0; padding: 0; }
.resultado { padding: 12px 0; border-bottom: 1px solid var(--borde); }
.resultado__titulo { margin-left: 8px; }
.resultado__contexto { font-size: 13px; color: var(--tenue); margin-top: 4px; }

/* --- Panel de contenido -------------------------------------------------- */
/* `display: block` + `overflow-x: auto` para que las tablas anchas —alumnos,
   usuarios— se desplacen DENTRO de su caja en un móvil en vez de estirar el
   cuerpo de la página. El navegador sigue maquetándolas como tabla por dentro
   (caja de tabla anónima); lo que se pierde es el ajuste automático al ancho
   del contenedor, y por eso `width: 100%` sigue haciendo falta. */
.tabla {
  display: block; overflow-x: auto; max-width: 100%;
  width: 100%; border-collapse: collapse; margin-top: 20px; font-size: 15px;
}
.tabla th, .tabla td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--borde); }
.tabla th { font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--tenue); font-weight: 500; }
.tabla__num { font-family: var(--mono); }
.oculto-visual {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.forma--fila { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 10px; }
.campo--crece { flex: 1 1 240px; }
.campo--corto { flex: 0 1 160px; }
.campo__control--area { font-family: var(--sans); line-height: 1.5; resize: vertical; }

.modulo-edicion__cabecera { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.modulo-edicion__botones { display: flex; gap: 6px; flex-wrap: wrap; }
.lecciones-edicion { list-style: none; margin: 18px 0; padding: 0; }
.leccion-edicion { padding: 14px 0; border-top: 1px solid var(--borde); }
.leccion-edicion__marcas { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.leccion-edicion__marcas .boton { padding: 5px 10px; font-size: 13px; }

/* --- Mis cursos ---------------------------------------------------------- */
.curso-mio { display: flex; flex-direction: column; gap: 8px; }
.curso-mio__pie { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }

@media (min-width: 860px) {
  .paquete { grid-template-columns: 1fr 280px; }
  .paquete__precio { border-top: 0; border-left: 1px solid var(--borde); padding: 0 0 0 24px; }
  .visor { grid-template-columns: 280px 1fr; }
}

/* --- Fase 3 · compra y bandeja de comprobantes ---------------------------- */

/* `hidden` es un atributo del HTML y el navegador ya lo respeta… salvo cuando
   otra regla fija `display`, que es justo lo que pasa con `.aviso`. Sin esto,
   el aviso del cupón se ve vacío desde que carga la página. */
[hidden] { display: none !important; }

/* Los datos del Pago Móvil: etiqueta y valor, uno por línea y el valor en
   monoespaciada porque son números que se copian a mano a otra app. */
.datos-pago { margin: 18px 0 0; }
.datos-pago__fila {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--borde);
}
.datos-pago dt { color: var(--tenue); font-size: 14px; }
.datos-pago dd { margin: 0; font-family: var(--mono); font-size: 16px; color: var(--texto); }

/* Tarjetas apiladas de la bandeja. `.lista` no vale: es un <ul> con sangría. */
.pila { display: grid; gap: 16px; margin-top: 16px; }

/* MEDIDO EL 2026-09-10: la tarjeta de un comprobante se salía 73 px del
   viewport de 380 px (scrollWidth 453) en cuanto la bandeja tenía algo dentro.

   La causa es la misma que la de `.buscador__fila` de más arriba, con grid en
   vez de flex: un grid item tiene `min-width: auto`, así que NO encoge por
   debajo de su contenido mínimo, y el contenido mínimo de la tarjeta es un
   correo largo —`nombre.apellido@universidad.edu.ve` son 40 caracteres sin un
   solo sitio por donde partir—. La tarjeta se estira a lo que mida el correo y
   arrastra la página entera en horizontal.

   No se había visto NUNCA porque la prueba de 380 px medía /admin/comprobantes
   con la bandeja VACÍA: sin tarjetas no hay nada que desborde. Desde hoy la
   siembra (`sembrarBandeja`), y por eso apareció. */
.pila > * { min-width: 0; }
/* Y que el correo parta en vez de quedar cortado: `anywhere` y no `break-word`
   porque este último no rompe una palabra que ya está sola en su línea. */
.tarjeta__texto, .tabla td { overflow-wrap: anywhere; }

/* El texto crudo del OCR, para cuando hay que comprobar a mano qué leyó. */
.pila details { margin: 12px 0; color: var(--secundario); font-size: 14px; }
.pila summary { cursor: pointer; color: var(--tenue); }
.pila pre {
  white-space: pre-wrap; word-break: break-word; font-family: var(--mono);
  font-size: 13px; background: var(--superficie-alta); border: 1px solid var(--borde);
  border-radius: var(--radio); padding: 12px; margin-top: 10px;
}

/* --- Interruptores: /admin/ajustes y la casilla de 18+ del onboarding ----- */

/* El primer interruptor del proyecto. `.campo` es `display:block` porque todo
   lo demás son etiqueta-encima-de-recuadro; aquí la etiqueta va AL LADO, que es
   lo que hace que un checkbox se lea como un interruptor y no como un campo
   más. Y el área pulsable es la etiqueta entera, no los 13 px de la casilla:
   en un móvil, acertarle a la casilla sola es un ejercicio de puntería. */
.campo--interruptor {
  display: flex; align-items: center; gap: 10px; margin: 0 0 14px;
}
.campo--interruptor input { width: 20px; height: 20px; accent-color: var(--carmesi); flex: none; }
.campo--interruptor .campo__etiqueta { margin: 0; color: var(--texto); font-size: 15px; cursor: pointer; }

/* Corregido 2026-09-01: las seis casillas medían 20 px y WCAG 2.5.8 pide 24.
   Con el dedo, encender «Zelle» y encender «Zinli» son dos aciertos seguidos
   de 20 px, y es la pantalla desde la que la academia decide por dónde cobra.
   La etiqueta sube con la casilla porque el `for` la hace parte del objetivo:
   dejarla en su alto de línea sería mover el problema, no arreglarlo.

   VA AQUI Y NO EN EL BLOQUE DE AREAS TACTILES DE ARRIBA, a proposito: una
   media query no añade especificidad, así que la regla de `pointer: coarse`
   de la línea 328 perdería contra la de esta misma línea por ser anterior en
   el fichero. La regla que corrige a otra tiene que ir DESPUES de ella.

   Desde el 2026-09-10 esto vale también para la casilla de mayoría de edad del
   onboarding (`LEG-06`), que es la única casilla obligatoria del registro: si
   ahí no se acierta con el dedo, no se entra. */
@media (pointer: coarse) {
  .campo--interruptor input { width: 24px; height: 24px; }
  .campo--interruptor .campo__etiqueta {
    display: inline-flex; align-items: center; min-height: 24px;
  }
}

/* Los métodos apagados siguen en pantalla —hay que poder encenderlos— pero
   pierden peso: sin esto, ocho tarjetas idénticas no dicen cuáles están
   activas y hay que leer ocho casillas para saberlo. */
.tarjeta[data-metodo].esta-apagado .campo:not(.campo--interruptor),
.tarjeta[data-metodo].esta-apagado .nota-pie { opacity: .5; }

/* SEÑALES sobre un comprobante, en la bandeja (10/09).
   El color va en una BARRA LATERAL y no en el fondo, a propósito: son pistas
   junto a un veredicto que ya está tomado, y un fondo rojo a media tarjeta se
   lee como «rechazado». Aquí nada rechaza nada. */
.senales { list-style: none; margin: 10px 0; padding: 0; display: grid; gap: 6px; }
.senal {
  border-left: 3px solid var(--borde); padding: 6px 0 6px 10px;
  font-size: 14px; line-height: 1.45;
}
.senal__detalle { display: block; color: var(--suave); font-size: 13px; }
/* Los cuatro niveles. `nd` = no se ha podido comprobar, y se queda en gris a
   propósito: no es una buena noticia ni una mala, y pintarla de verde sería
   decir que algo se comprobó cuando no se comprobó nada. */
.senal--ok     { border-left-color: #2f8f4e; }
.senal--aviso  { border-left-color: #b8860b; }
.senal--alerta { border-left-color: var(--carmesi); }
.senal--nd     { border-left-color: var(--borde); }

/* Los seis bloques de «Dónde cobras tus módulos», en el panel del facilitador
   (10/09). Un `fieldset` de verdad y no un `div`: son seis grupos de campos con
   su propio encabezado, y el lector de pantalla necesita saber que «Teléfono»
   pertenece a «Pago Móvil» y no al bloque de al lado. El navegador le pone
   borde y margen propios, que es lo que se quita aquí para que se parezcan al
   resto de tarjetas del panel. */
.metodo-cobro {
  border: 1px solid var(--borde); border-radius: 10px;
  padding: 14px 16px; margin: 0 0 14px; min-width: 0;
}
/* `min-width: 0` arriba y esto: un `fieldset` trae un `min-inline-size:
   min-content` de fábrica que ignora el ancho del padre, así que a 380 px un
   `<textarea>` dentro estira la caja y saca la página del viewport. Es el
   mismo fallo que `QA-03` midió en /admin/comprobantes, con otra causa. */
.metodo-cobro > legend {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 0 6px; font-size: 15px; font-weight: 600; color: var(--texto);
}
.metodo-cobro .campo__control { max-width: 100%; box-sizing: border-box; }

/* Un bloque por método de cobro dentro del paso 1. Antes había uno solo (Pago
   Móvil) y no hacía falta separarlos; con seis, la línea de arriba es lo único
   que impide que un alumno lea el correo de Zinli creyendo que es el de Zelle. */
.metodo-pago__titulo {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0; font-size: 15px; color: var(--texto);
}
.metodo-pago--mas { margin-top: 22px; padding-top: 22px; border-top: 1px solid var(--borde); }

/* LEG-08 · El banner de cookies.
   Abajo y a lo ancho, por encima del pie. `position: fixed` para que no dependa
   de dónde esté la página, y con `padding-bottom` seguro en móviles con barra
   de gestos. */
.consentimiento {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 50;
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  align-items: center;
  justify-content: center;
  padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px));
  background: var(--fondo);
  border-top: 2px solid var(--carmesi);
}
.consentimiento__texto {
  margin: 0;
  max-width: 62ch;
  font-size: 14px;
  line-height: 1.55;
  color: var(--secundario);
}
.consentimiento__acciones {
  display: flex;
  gap: 10px;
  margin: 0;
  flex-shrink: 0;
}
/* A 380 px los dos botones tienen que caber sin pisarse y seguir siendo
   objetivos táctiles: es la anchura contra la que se mide todo en este
   proyecto (QA-03). */
@media (max-width: 480px) {
  .consentimiento { justify-content: stretch; }
  .consentimiento__acciones { width: 100%; }
  .consentimiento__acciones .boton { flex: 1; }
}

/* MEDIDO EL 2026-09-09, Y ESTO ES LO QUE APARECIÓ: el banner TAPA el pie.
   -----------------------------------------------------------------------------
   A 380 px ocupa 177 px de alto y está `fixed` abajo, así que con la página
   arrastrada hasta el final los tres enlaces legales —devoluciones, términos y
   privacidad, que son `LEG-02`, `LEG-03` y `LEG-09`— quedan DEBAJO de él y no
   se pueden pulsar. Es el defecto que no se ve en una captura de la parte de
   arriba, y el más incómodo de todos: el banner que pide permiso tapa
   justamente las páginas que explican para qué.

   Se reserva el hueco con una variable y no con un número: la altura del banner
   depende de cuánto envuelva su texto —una línea en escritorio, cuatro a 380 px—
   y cualquier constante estaría mal en la mitad de los anchos.
   `consentimiento.js` la mide y la escribe; el valor de reserva del `var()` es
   para el instante anterior a que corra el script y para el navegador sin
   JavaScript, donde generoso de más es preferible a un pie inalcanzable.

   Va DESPUÉS de la media query de arriba a propósito (trampa n.º 5: una media
   query no añade especificidad, y una regla que corrige a otra tiene que ir
   detrás). */
body:has(.consentimiento) { padding-bottom: var(--alto-consentimiento, 200px); }

/* Y lo mismo para el desplazamiento AUTOMÁTICO, que es el otro modo de acabar
   debajo del banner sin haberlo pedido: cuando el navegador trae un control a
   la vista —al recibir el foco con el tabulador, al saltar a un `#ancla`— usa
   la «región óptima» de la ventana, y sin esto esa región incluye los 177 px
   que el banner tiene tapados. Es WCAG 2.4.11 (el foco no queda oculto).

   Medido el 2026-09-09 en `/onboarding` a 380 px: los dos botones del paso 1
   («Subir» y «Ahora no») caen en la franja del banner con la página recién
   pintada. El banner se quita con un toque y el contenido se alcanza
   desplazándose —por eso esto no es un bloqueo—, pero el sitio no tiene por qué
   devolver el foco a un sitio tapado. */
html:has(.consentimiento) { scroll-padding-bottom: var(--alto-consentimiento, 200px); }

/* =============================================================================
   LAND-02..07 y LAND-11 — La portada (03/09)
   -----------------------------------------------------------------------------
   Las cinco secciones que el checklist daba por implementadas y no lo estaban:
   hero con stripe diagonal, marquee, manifiesto, grid mosaico y urgencia.

   NO SE AÑADE NINGÚN BREAKPOINT NUEVO, Y ES DELIBERADO

   El sitio tiene tres —480, 620 y 860— y `install/probar-breakpoints.mjs` mide
   sus fronteras. Un cuarto breakpoint aquí sería una frontera más que nadie
   estaría midiendo, así que el mosaico reutiliza los 860 px que ya existen y el
   resto se apaña con `clamp()` y `auto-fit`, que no tienen borde que romper.

   LOS COLORES DE LOS OCHO MÓDULOS SON PROVISIONALES — ES `LAND-08`

   ⏳ ESTADO AL 2026-09-10 (TARDE): DECIDIDA, MEDIDA Y **NO APLICADA**.

   La propietaria de la academia decidió una paleta por módulo, se aplicó, se
   miró en pantalla y **se revirtió el mismo día**: prefiere el mosaico como
   estaba, con fondo oscuro uniforme y el color sólo como acento. Lo que se ve
   hoy es, otra vez, la rampa de abajo.

   LA PALETA DECIDIDA NO SE BORRA, SE APARCA — Y CON SUS MEDIDAS

     1 Mentalidad      Carmesí profundo   #560216
     2 Setup           Negro cálido       #1a0a0d
     3 Pre-producción  Carmesí oscuro     #3d0110
     4 Producción      Negro absoluto     #0d0d0d
     5 Post-producción Carmesí medio      #7a0320
     6 Monetización    Vino tinto         #4a0d1a
     7 Comunicación    Blanco cálido      #efeeee
     8 Branding        Carmesí brillante  #a3041f

   ⚠️ SI ALGÚN DÍA SE VUELVEN A APLICAR, ESTO ES LO QUE HAY QUE SABER, y está
   escrito aquí para no volver a descubrirlo: **son colores de FONDO, no de
   tinta.** Puestos como color de texto sobre la superficie (#141414), siete de
   los ocho son ilegibles — medido: Mentalidad 1,24:1 · Setup 1,04:1 ·
   Pre-producción 1,06:1 · Producción 1,05:1 · Post-producción 1,63:1 ·
   Monetización 1,20:1 · Branding 2,28:1, todos por debajo del 4,5:1 de AA y
   tres por debajo de 1,1:1, que es invisible. Sólo Comunicación pasa.

   Como FONDO, en cambio, son excelentes: con #efeeee encima dan de 9,74:1
   (Branding) a 16,78:1 (Producción). Comunicación es la única clara y necesita
   tinta oscura (#0d0d0d). El texto secundario tendría que ser #cdc6c6 —el más
   apagado que aguanta 4,5:1 sobre Branding, el más claro de los oscuros—, y no
   el `--secundario` de siempre, que ahí da 2,71:1. Y el filo de 3 px no puede
   ser el color de la pieza: contra la página, Setup da 1,01:1 y Producción
   1,00:1, así que esas dos tarjetas se quedarían sin borde sobre un fondo de su
   mismo tono y dejarían de leerse como tarjetas.

   LA RAMPA QUE SÍ ESTÁ EN USO

   Los ocho pares están comprobados el 03/09 contra el fondo (#0d0d0d) y contra
   la superficie (#141414): el peor es 5,26:1, por encima del 4,5:1 de texto AA
   y del 3:1 de componente. Se usan como TINTA —el número de la pieza y su filo
   superior—, que es para lo que se eligieron.
   ========================================================================== */

:root {
  --pieza-1: #d4667c;   /* 5,54:1 */
  --pieza-2: #d47a66;   /* 6,27:1 */
  --pieza-3: #c98a5a;   /* 6,73:1 */
  --pieza-4: #b39a63;   /* 7,14:1 */
  --pieza-5: #8fa87e;   /* 7,47:1 */
  --pieza-6: #6fa39b;   /* 6,84:1 */
  --pieza-7: #7b8fc0;   /* 6,05:1 */
  --pieza-8: #a97ec4;   /* 5,99:1 */
}

/* La paleta de la academia, APARCADA y sin aplicar. Nada la referencia hoy: no
   pinta nada y no cuesta nada. Está aquí para que volver a intentarlo sea
   cambiar el enganche de abajo y no volver a preguntar los colores. */
:root {
  --paleta-1: #560216;  /* Mentalidad      */
  --paleta-2: #1a0a0d;  /* Setup           */
  --paleta-3: #3d0110;  /* Pre-producción  */
  --paleta-4: #0d0d0d;  /* Producción      */
  --paleta-5: #7a0320;  /* Post-producción */
  --paleta-6: #4a0d1a;  /* Monetización    */
  --paleta-7: #efeeee;  /* Comunicación    */
  --paleta-8: #a3041f;  /* Branding        */
}

/* --- El revelado al hacer scroll (LAND-11) --------------------------------
   `revelar--armado` lo pone el JAVASCRIPT, no el HTML. Si `portada.js` no
   llega, no hay ninguna regla que esconda nada y la portada se ve entera: es
   la diferencia entre un adorno y una dependencia. */
.revelar--armado { opacity: 0; transform: translateY(16px); }
.revelar--armado.es-visible {
  opacity: 1; transform: none;
  transition: opacity .55s ease-out, transform .55s ease-out;
}

/* --- LAND-02 · Hero con el stripe diagonal -------------------------------- */
.hero { position: relative; padding: 40px 0 64px; overflow: hidden; }
.hero__cuerpo { position: relative; z-index: 1; }
/* La banda: carmesí como SUPERFICIE, que es lo único que el carmesí puede ser
   sobre negro. No lleva texto encima, así que su 1,31:1 no es contraste de
   nada — es una forma. */
.hero__stripe {
  position: absolute; z-index: 0;
  top: -40%; right: -18%; width: 62%; height: 190%;
  background: linear-gradient(180deg, var(--carmesi-vivo), var(--carmesi));
  transform: rotate(18deg);
  opacity: .5;
  /* Sin `pointer-events` el stripe se comería los clics de los botones que
     tiene al lado, y el fallo sería invisible: el botón se ve, se pulsa y no
     pasa nada. */
  pointer-events: none;
}

/* --- LAND-03 · Marquee ---------------------------------------------------- */
.marquee {
  overflow: hidden; margin: 8px 0 48px;
  border-top: 1px solid var(--borde); border-bottom: 1px solid var(--borde);
  padding: 14px 0;
  /* Se difumina en los dos bordes para que las palabras no aparezcan y
     desaparezcan de golpe contra el borde de la ventana. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee__pista {
  display: flex; align-items: center; gap: 22px;
  width: max-content;
  animation: marquee 44s linear infinite;
}
.marquee__pieza {
  font-family: var(--serif); font-size: clamp(20px, 3.4vw, 30px);
  color: var(--secundario); white-space: nowrap;
}
.marquee__punto { color: var(--carmesi-vivo); font-size: 22px; }
/* De 0 a -50 % porque la lista se pinta dos veces: al llegar a la mitad, la
   segunda copia está donde empezó la primera y el salto no se ve. */
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
/* La regla global de `prefers-reduced-motion` ya deja la animación en 0,01 ms,
   pero eso la deja CONGELADA en su último fotograma —desplazada—. Aquí se
   devuelve al principio, que es la posición legible. */
@media (prefers-reduced-motion: reduce) {
  .marquee__pista { animation: none; transform: translateX(0); }
}

/* --- LAND-04 · Manifiesto ------------------------------------------------- */
.manifiesto { padding: 24px 0 8px; }
.manifiesto__cita { margin: 0 0 22px; padding: 0 0 0 20px; border-left: 3px solid var(--carmesi-vivo); }
.manifiesto__cita p {
  font-family: var(--serif); font-size: clamp(26px, 4.4vw, 40px);
  line-height: 1.15; max-width: 22ch;
}
.manifiesto__texto {
  display: grid; gap: 14px; margin-top: 18px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  color: var(--secundario); max-width: 78ch;
}

/* --- LAND-05 · Grid mosaico ----------------------------------------------- */
.mosaico-seccion { padding: 48px 0 8px; }
.mosaico {
  list-style: none; margin: 26px 0 0; padding: 0;
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.mosaico__pieza { display: flex; }
.mosaico__enlace {
  display: flex; flex-direction: column; gap: 8px;
  width: 100%; padding: 20px;
  background: var(--superficie); border: 1px solid var(--borde);
  border-top: 3px solid var(--pieza, var(--acento));
  border-radius: var(--radio);
  color: inherit; text-decoration: none;
  transition: border-color .18s ease, background .18s ease, transform .18s ease;
}
.mosaico__enlace:hover, .mosaico__enlace:focus-visible {
  background: var(--superficie-alta); border-color: var(--borde-vivo);
  border-top-color: var(--pieza, var(--acento));
  transform: translateY(-2px);
}
.mosaico__numero {
  font-family: var(--mono); font-size: 12px; letter-spacing: .1em;
  color: var(--pieza, var(--acento));
}
.mosaico__titulo { font-family: var(--serif); font-size: 20px; line-height: 1.2; }
.mosaico__texto { color: var(--secundario); font-size: 14px; }
.mosaico__pie {
  margin-top: auto; padding-top: 10px;
  display: flex; flex-wrap: wrap; gap: 4px 12px;
  font-size: 12px; color: var(--tenue);
}
.mosaico__tuyo { color: var(--acento); }

/* EL ENGANCHE, que se mantiene a propósito (decisión del 10/09 por la tarde).
   Una línea por pieza: cambiar el aspecto de los ocho módulos es cambiar a qué
   apunta `--pieza`, sin tocar la plantilla ni las reglas de arriba. Hoy apunta
   a la rampa; para volver a la paleta de la academia se apuntaría a
   `--paleta-N` — y entonces habría que leer el aviso de su cabecera, porque
   como TINTA no valen. */
.mosaico__pieza--1 { --pieza: var(--pieza-1); }
.mosaico__pieza--2 { --pieza: var(--pieza-2); }
.mosaico__pieza--3 { --pieza: var(--pieza-3); }
.mosaico__pieza--4 { --pieza: var(--pieza-4); }
.mosaico__pieza--5 { --pieza: var(--pieza-5); }
.mosaico__pieza--6 { --pieza: var(--pieza-6); }
.mosaico__pieza--7 { --pieza: var(--pieza-7); }
.mosaico__pieza--8 { --pieza: var(--pieza-8); }

/* Lo que lo hace MOSAICO y no rejilla: dos piezas anchas. Sólo a partir de los
   860 px que ya existen —el breakpoint del `.paquete` y del `.visor`—, porque
   por debajo no hay columnas que ocupar y `span 2` dejaría huecos. */
@media (min-width: 860px) {
  .mosaico { grid-template-columns: repeat(4, 1fr); }
  .mosaico__pieza--1, .mosaico__pieza--6 { grid-column: span 2; }
}

/* --- LAND-06 · Urgencia --------------------------------------------------- */
.urgencia {
  position: relative; overflow: hidden;
  margin: 56px 0 8px; padding: 40px 28px;
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: var(--radio);
}
.urgencia__cuerpo { position: relative; z-index: 1; }
.urgencia__stripe {
  position: absolute; z-index: 0;
  top: -60%; left: -12%; width: 46%; height: 220%;
  background: linear-gradient(180deg, var(--carmesi), var(--carmesi-vivo));
  transform: rotate(-16deg);
  opacity: .38;
  pointer-events: none;
}
.urgencia__titulo { font-size: clamp(24px, 3.6vw, 34px); max-width: 24ch; margin-bottom: 14px; }
.urgencia__texto { color: var(--secundario); max-width: 58ch; }

/* --- LAND-11 · El halo del cursor -----------------------------------------
   Acompaña al puntero del sistema, no lo sustituye: el porqué está escrito en
   la cabecera de `portada.js`. `pointer-events: none` es obligatorio — sin él,
   este círculo se pone entre el ratón y todos los enlaces de la página. */
.halo {
  --halo-lado: 26px;
  position: fixed; top: 0; left: 0; z-index: 9;
  width: var(--halo-lado); height: var(--halo-lado); border-radius: 50%;
  /* Centrado con MARGEN y no con `translate(-50%, -50%)` dentro de `transform`,
     por el mismo motivo que la posicion: ver el bloque de abajo. */
  margin: calc(var(--halo-lado) / -2) 0 0 calc(var(--halo-lado) / -2);
  border: 1px solid var(--acento);
  pointer-events: none; opacity: 0;
  /* MEDIDO EL 2026-09-10, Y ES EL FALLO QUE SE ARREGLA AQUI.
     La posicion va en la propiedad `translate` y NO dentro de `transform`.
     Las propiedades individuales se aplican en el orden
     `translate -> rotate -> scale -> transform`, asi que un `scale: 1.8`
     multiplica todo lo que venga DESPUES, incluida una traslacion escrita
     dentro de `transform`. Con la posicion ahi, al pasar por un enlace el halo
     saltaba a (x*1,8 , y*1,8): con el raton en (270, 38) el halo se dibujaba en
     (476, 58) —206 px de distancia—, y cuanto mas a la derecha estuviera el
     raton, mas lejos se iba, hasta salirse de la pantalla. Se veia como «el
     halo se queda pegado a un lado y no sigue al raton», y era esto.
     En `translate` la traslacion va ANTES del escalado y no le afecta. */
  translate: var(--halo-x, 0) var(--halo-y, 0) 0;
  scale: 1;
  /* Solo para que tenga capa propia. Un z de 0, escalado, sigue siendo 0. */
  transform: translateZ(0);
  transition: opacity .2s ease, scale .18s ease, border-color .18s ease;
}
.halo.es-visible { opacity: .5; }
/* Colgado de `.es-visible` A PROPOSITO, que es el segundo fallo de la misma
   tanda: suelto, su `opacity: .75` le ganaba al `opacity: 0` de `.halo` —misma
   especificidad, y esta regla va despues— en cuanto el JS quitaba `es-visible`.
   Al sacar el raton de la ventana sobre un enlace, el halo se quedaba encendido
   a .75 y agrandado, congelado en el ultimo sitio donde estuvo. */
.halo.es-visible.halo--sobre-control {
  scale: 1.8;
  border-color: var(--pieza, var(--acento));
  opacity: .75;
}
/* Con el dedo no hay puntero al que acompañar. `portada.js` ya no lo crea en
   `pointer: coarse`, y esto es el cinturón por si algún día se crea igual. */
@media (pointer: coarse) { .halo { display: none; } }

/* -----------------------------------------------------------------------------
   Calendario. Una agenda vertical y no una rejilla de meses: con dos o tres
   eventos al mes, una rejilla de 30 celdas son 27 huecos vacíos, y en el móvil
   —donde se mira— no cabe sin encogerla hasta que no se lee. La lista dice lo
   mismo y se lee igual de bien a 380 px que a 1400.
   -------------------------------------------------------------------------- */
.agenda { list-style: none; margin: 24px 0 0; padding: 0; }
.agenda__item {
  border: 1px solid var(--borde); border-left: 3px solid var(--borde-vivo);
  border-radius: var(--radio); padding: 18px 20px; margin-bottom: 14px;
  background: var(--superficie);
}
/* El tipo se distingue por el color de la barra Y por la pastilla escrita al
   lado. Nunca sólo color: hay quien no los distingue. */
.agenda__item--sesion_vivo { border-left-color: var(--carmesi); }
.agenda__item--promocion   { border-left-color: #c9a227; }
.agenda__item--lanzamiento { border-left-color: #3f7d58; }

.agenda__cuando {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  margin: 0 0 6px;
}
.agenda__fecha { font-family: var(--mono); font-size: 14px; color: var(--secundario); }
.agenda__titulo { font-family: var(--serif); font-size: 22px; margin: 0 0 8px; }
.agenda__pie {
  display: flex; gap: 12px; flex-wrap: wrap; align-items: center;
  margin: 10px 0 0;
}
