/* =========================================================================
   AULA PREMIUM — sistema de diseño v2 (TANDA 22-SEP-P1 · P1.1)
   Portado de `rediseno_premium/html/gg.css` (fuente de verdad del prototipo)
   con prefijo `--ap-` en los tokens y `.ap-` en los componentes para no
   chocar con los de `style.css`. Se encola SOLO en el frente, después de
   `style.css`. Envuelve cada pantalla nueva en `.ap` (equivalente al `.gg`
   del prototipo).
   ========================================================================= */

@font-face {
  font-family: 'Sora';
  src: url('../fuentes/sora-variable-latino.woff2') format('woff2-variations'),
       url('../fuentes/sora-variable-latino.woff2') format('woff2');
  font-weight: 600 800;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ---- Neutros (base cálida, no gris frío) ---- */
  --ap-ground: #F5F3EC;
  --ap-surface: #FFFFFF;
  --ap-surface-2: #FBFAF6;
  --ap-line: #E7E3D8;
  --ap-line-2: #EFECE3;
  --ap-ink-900: #0F1F1D;
  --ap-ink-700: #2A3A38;
  --ap-ink-500: #55635F;
  --ap-ink-400: #5F6B68;   /* P23 Q2c1: 5.5:1 sobre blanco, antes 4.4:1 (bajo el 4.5 AA, ver comentario más abajo) */
  --ap-ink-300: #A7B1AE;

  /* ---- Marca ---- */
  --ap-teal-950: #042F2C;
  --ap-teal-900: #073C38;
  --ap-teal-800: #0A4A45;
  --ap-teal-700: #0E5B55;
  --ap-teal-600: #11706A;
  --ap-teal-500: #14766E;
  --ap-teal-400: #2E9589;
  --ap-teal-300: #5FB3A9;
  --ap-teal-100: #DCEDEA;
  --ap-teal-50:  #EEF6F4;

  /* ---- Logro (oro del certificado) ---- */
  --ap-gold-700: #8A5A0E;
  --ap-gold-600: #A87C34;
  --ap-gold-500: #D9A031;
  --ap-gold-400: #F1C04E;
  --ap-gold-100: #FBEFD2;
  --ap-gold-50:  #FDF7E8;

  /* ---- Urgencia / estado ---- */
  --ap-coral-700: #9E3525;
  --ap-coral-600: #B8432F;
  --ap-coral-100: #FBE4DF;
  --ap-ok-700: #1F6B3A;  --ap-ok-100: #E2F2E7;
  --ap-info-700: #1D5A94; --ap-info-100: #E3EEF9;
  --ap-live: #E5484D;

  /* ---- Color por curso (portadas, chips, acentos de curso) ---- */
  --ap-c-excel: #1E7B4F;   --ap-c-excel-soft: #E4F2EA;
  --ap-c-pbi: #B07A06;     --ap-c-pbi-soft: #FCF1D6;
  --ap-c-canva: #6A3FD0;   --ap-c-canva-2: #16A3C4; --ap-c-canva-soft: #EEE8FB;
  --ap-c-gemini: #3456E0;  --ap-c-gemini-2: #8B5CF6; --ap-c-gemini-soft: #EAEEFD;
  --ap-c-sap: #0A5FB4;     --ap-c-sap-soft: #E4EEF9;
  --ap-c-ia: #7C3AED;      --ap-c-ia-soft: #F0E9FE;
  --ap-c-code: #D9480F;    --ap-c-code-soft: #FDEBE3;

  /* ---- Tipografía ---- */
  --ap-font-display: 'Sora', 'Nunito', system-ui, sans-serif;
  --ap-font-body: 'Nunito', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --ap-fs-d1: 44px;  --ap-lh-d1: 52px;
  --ap-fs-h1: 34px;  --ap-lh-h1: 42px;
  --ap-fs-h2: 24px;  --ap-lh-h2: 32px;
  --ap-fs-h3: 19px;  --ap-lh-h3: 26px;
  --ap-fs-body: 16px; --ap-lh-body: 26px;
  --ap-fs-sm: 14px;  --ap-lh-sm: 22px;
  --ap-fs-xs: 12.5px; --ap-lh-xs: 18px;

  /* ---- Geometría ---- */
  --ap-r-xl: 28px; --ap-r-lg: 22px; --ap-r-md: 16px; --ap-r-sm: 12px; --ap-r-xs: 8px; --ap-r-pill: 999px;
  --ap-sp-1: 4px; --ap-sp-2: 8px; --ap-sp-3: 12px; --ap-sp-4: 16px; --ap-sp-5: 20px; --ap-sp-6: 24px;
  --ap-sp-7: 32px; --ap-sp-8: 40px; --ap-sp-9: 56px; --ap-sp-10: 72px;
  --ap-shadow-1: 0 1px 2px rgb(15 31 29 / .05), 0 1px 1px rgb(15 31 29 / .03);
  --ap-shadow-2: 0 1px 2px rgb(15 31 29 / .04), 0 6px 18px -6px rgb(15 31 29 / .10);
  --ap-shadow-3: 0 2px 4px rgb(15 31 29 / .05), 0 18px 40px -12px rgb(15 31 29 / .18);
  --ap-ring: 0 0 0 2px #fff, 0 0 0 4px var(--ap-teal-700, #0E5B55);
  --ap-touch: 44px;
  --ap-nav-h: var(--navbar-h);
  --ap-content: 1200px;
}

/* ======================= Base ======================= */
.ap { font-family: var(--ap-font-body); color: var(--ap-ink-900); background: var(--ap-ground);
  font-size: var(--ap-fs-body); line-height: var(--ap-lh-body); -webkit-font-smoothing: antialiased;
  word-spacing: normal; }
.ap *, .ap *::before, .ap *::after { box-sizing: border-box; }
/* R2 (TANDA 22-SEP-P2R): títulos de más de una palabra con Sora — sin letter-spacing negativo,
   que en algunos renderizadores pega la última letra de una palabra con la primera de la
   siguiente. */
.ap h1, .ap h2, .ap h3, .ap h4 { font-family: var(--ap-font-display); margin: 0; letter-spacing: normal; color: var(--ap-ink-900); }
.ap h1 { font-size: var(--ap-fs-h1); line-height: var(--ap-lh-h1); font-weight: 700; }
.ap h2 { font-size: var(--ap-fs-h2); line-height: var(--ap-lh-h2); font-weight: 700; }
.ap h3 { font-size: var(--ap-fs-h3); line-height: var(--ap-lh-h3); font-weight: 600; }
.ap p { margin: 0; }
.ap a:not(.btn-pri) { color: var(--ap-teal-700); text-decoration: none; } /* P109 P0k: los botones de la casa conservan su propio color */
.ap a.btn-pri { text-decoration: none; }
/*
 * P8.0 · B2 (VEREDICTO_SUPERVISOR_23SEP.md) — el conmutador «Mi aula / Mi grupo» es
 * `.gta-navbar__conmutador` de `style.css` (v4-J, pastilla teal con el enlace activo en blanco),
 * reusado tal cual dentro de la barra nueva (header.php). Su regla `color:#fff` para el enlace
 * NO activo tiene la MISMA especificidad que `.ap a` de aquí arriba, y esta hoja se encola
 * DESPUÉS de `style.css`: gana `.ap a`, el enlace queda teal sobre teal y «Mi aula» se ve como
 * una pastilla en blanco sin texto. Specificidad más alta, sólo dentro de la barra nueva.
 */
.ap .ap-nav .gta-navbar__conmutador a { color: #fff; }
.ap .ap-nav .gta-navbar__conmutador a.activo { color: var(--ap-teal-700); }
.ap .ap-num { font-variant-numeric: tabular-nums; }
.ap .ap-muted { color: var(--ap-ink-500); }
/* P2.4 · `--ap-ink-400` sobre blanco da 4.41:1 — bajo el 4.5 que AA exige a 14px (Lighthouse
   `color-contrast`, medido en «1 de 83 lecciones», «1/16 insignias» y el resto de `.ap-meta`).
   `--ap-ink-500` da 6.29:1 y es el mismo tono más oscuro que ya usa `.ap-muted` al lado. */
.ap .ap-meta { color: var(--ap-ink-500); font-size: var(--ap-fs-sm); line-height: var(--ap-lh-sm); }
.ap .ap-eyebrow { font-size: 12px; line-height: 16px; letter-spacing: .08em; text-transform: uppercase; font-weight: 800; color: var(--ap-teal-600); }
/* R8 (TANDA 22-SEP-P2R): `.gta-main` (style.css) trae su propio `max-width:1080px` +
   padding lateral de la barra vieja; sin anularlo aquí, toda pantalla `.ap` queda encogida a
   ~1048px de contenido en vez de los 1120px (1200 - 2×40) del prototipo (medido en `/` y
   `/cursos/` a 1440 con becado 446: `.ap-page` medía 1048px pese a `max-width:1200px`). El
   ancho de `.ap-page` lo decide esta hoja, no la barra vieja que ya no se pinta detrás de ella. */
.gta-main:has(> .ap) { max-width: none; padding: 0; }
.ap .ap-page { max-width: var(--ap-content); margin: 0 auto; padding: 36px 40px 72px; }
.ap .ap-row { display: flex; gap: var(--ap-sp-6); }
.ap .ap-stack { display: flex; flex-direction: column; }
.ap .ap-ico { width: 20px; height: 20px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.ap .ap-ico-sm { width: 16px; height: 16px; }
.ap .ap-ico-lg { width: 24px; height: 24px; }

/* ======================= Navegación ======================= */
/*
 * P2R · R1 — `padding` y `gap` bajan de 28/16 a 24/12: con dirección/administración (que suman
 * el conmutador «Mi colegio»/«Secretaría» a la barra del becado, `gta-navbar__conmutador--escritorio`)
 * el contenido pedía 1458px, 18px más que un escritorio de 1440. Medido con Playwright
 * (`arreglos/verificar-r1-perfiles.mjs`): con este recorte cabe en los tres roles sin perder
 * ningún enlace ni encimarse.
 */
.ap .ap-nav { height: var(--ap-nav-h); white-space: nowrap; background: var(--ap-surface); border-bottom: 1px solid var(--ap-line);
  display: flex; align-items: center; padding: 0 24px; gap: 12px; position: relative; z-index: 40; }
/* obs 16 · la cabecera se queda fija: el que se pega es el envoltorio (header.php), porque un sticky no sale de su padre y el <nav> es su único hijo */
.ap.ap-cab { position: sticky; top: var(--gta-offset-superior); z-index: 60; }
.ap .ap-brand { display: flex; align-items: center; gap: 10px; white-space: nowrap; flex: none; font-family: var(--ap-font-display); font-weight: 800; font-size: 19px; color: var(--ap-ink-900); }
.ap .ap-brand-mark { width: 40px; height: 40px; border-radius: 12px; background: var(--ap-gold-50); display: grid; place-items: center; border: 1px solid var(--ap-gold-100); }
.ap .ap-brand small { display: block; font-family: var(--ap-font-body); font-weight: 700; font-size: 11px; letter-spacing: .06em; color: var(--ap-ink-400); text-transform: uppercase; line-height: 12px; }
.ap .ap-nav-links { display: flex; gap: 2px; margin-left: 8px; }
/* P113B C2 · la barra cabe de 1025 a 1920 px: lo que no cabe cede en este orden —los enlaces recortan su
   rótulo (queda el icono y el nombre sigue entero para el lector de pantalla) y después el nombre de la
   cuenta se recorta con puntos suspensivos—; los controles (marca, racha, campana, foto) no se encogen. */
.ap .ap-nav-links { flex: 0 1 auto; min-width: 0; }
.ap .ap-nav-link { flex: 0 1 auto; min-width: 0; overflow: hidden; }
.ap .ap-nav-link .ap-ico { flex: none; }
.ap .ap-nav-link__txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ap .ap-nav .gta-navbar__cuenta { flex-shrink: 1; min-width: 0; }
.ap .ap-nav .gta-navbar__cuenta-boton { max-width: 100%; }
.ap .ap-nav .gta-navbar__cuenta-nombre { flex: 0 1 auto; min-width: 0; }
.ap .ap-nav-link { display: inline-flex; align-items: center; gap: 8px; height: 42px; padding: 0 11px; border-radius: var(--ap-r-pill);
  font-weight: 700; font-size: 15px; color: var(--ap-ink-700); white-space: nowrap; position: relative; }
.ap .ap-nav-link .ap-pill { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; background: var(--ap-coral-600); color: #fff; font-size: 11.5px; font-weight: 800; line-height: 20px; text-align: center; }
.ap .ap-nav-link .ap-ico { width: 18px; height: 18px; color: var(--ap-ink-400); }
.ap .ap-nav-link.is-active { background: var(--ap-teal-50); color: var(--ap-teal-800); box-shadow: inset 0 0 0 1px var(--ap-teal-100); }
.ap .ap-nav-link.is-active .ap-ico { color: var(--ap-teal-600); }
.ap .ap-nav-spacer { flex: 1; }
.ap .ap-nav-chip { flex: none; display: inline-flex; align-items: center; gap: 8px; height: 40px; padding: 0 14px 0 10px; border-radius: var(--ap-r-pill);
  background: var(--ap-surface-2); border: 1px solid var(--ap-line); font-weight: 800; font-size: 15px; }
.ap .ap-nav-chip .ap-dot { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; }
.ap .ap-icon-btn { flex: none; width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center; background: var(--ap-surface-2);
  border: 1px solid var(--ap-line); color: var(--ap-ink-700); position: relative; }
.ap .ap-badge-dot { position: absolute; top: 6px; right: 7px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--ap-coral-600); color: #fff; font-size: 11px; font-weight: 800; line-height: 18px; text-align: center; border: 2px solid #fff; }
.ap .ap-avatar-btn { flex: none; display: inline-flex; align-items: center; gap: 10px; height: 44px; padding: 0 12px 0 4px; border-radius: var(--ap-r-pill);
  border: 1px solid var(--ap-line); background: var(--ap-surface); font-weight: 700; font-size: 15px; color: var(--ap-ink-900); }
.ap .ap-avatar { width: 36px; height: 36px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ap-gold-50); flex: none; }
/*
 * P2R · R1 — el nombre de cuenta sin tope de ancho estiraba el botón hasta 197px con un nombre
 * largo («Miguel Rodríguez») y esos 18px de más eran justo los que le faltaban a la barra de
 * dirección para caber en 1440 (medido con Playwright: 1458 de contenido contra 1440 de
 * viewport). El nombre se recorta con puntos suspensivos; sigue entero para quien lo lee con
 * lector de pantalla, porque es texto, no lo esconde una clase de accesibilidad.
 */
.ap .gta-navbar__cuenta-nombre { display: inline-block; max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
.ap .ap-menu { position: absolute; right: 32px; top: 64px; width: 280px; background: var(--ap-surface); border: 1px solid var(--ap-line);
  border-radius: var(--ap-r-md); box-shadow: var(--ap-shadow-3); padding: 8px; z-index: 60; }
.ap .ap-menu-head { display: flex; gap: 12px; align-items: center; padding: 10px 10px 14px; border-bottom: 1px solid var(--ap-line-2); margin-bottom: 6px; }
.ap .ap-menu-item { display: flex; align-items: center; gap: 12px; height: 44px; padding: 0 10px; border-radius: 10px; color: var(--ap-ink-700); font-weight: 700; font-size: 15px; }
.ap .ap-menu-item:hover { background: var(--ap-teal-50); }
.ap .ap-menu-item.danger { color: var(--ap-coral-700); }
.ap .ap-menu-sep { height: 1px; background: var(--ap-line-2); margin: 6px 4px; }

/* ======================= Tabbar móvil (P1.2 chunk 2) ======================= */
/* Mismo esqueleto que .gta-tabbar (style.css): fijo abajo, oculto desde 1025px, alto mínimo
   táctil de 44px, borde de seguridad del notch. Sólo cambian los tokens y que el icono es el
   SVG de gta_icono() (trazo, ESTÁNDAR §3) en vez del emoji viejo.
   P2R · R1 — el corte era 641px hasta que se midió la barra a 768/1024: sin la tabbar ahí, esos
   anchos se quedaban sin ninguna forma de llegar a Inicio/Mis cursos/Biblioteca/Logros (ver el
   @media de la barra, más abajo, que ahora colapsa hasta 1024px por la misma razón). */
.ap-tabbar { position: fixed; bottom: 0; left: 0; right: 0; z-index: 50; display: flex;
  background: var(--ap-surface); border-top: 1px solid var(--ap-line);
  padding-bottom: env(safe-area-inset-bottom); }
@media (min-width: 1025px) { .ap-tabbar { display: none; } }
/*
 * P2.4 (TANDA 22-SEP-P2) · `min-width: 0` — sin él, un `flex:1` no encoge por debajo del ancho
 * mínimo de SU contenido (la palabra «Biblioteca» sin partir), y los cinco ítems sumaban más de
 * 390px: «Más» quedaba empujado FUERA del viewport entero (medido con Lighthouse, `target-size`:
 * su `summary` aterrizaba en left:390, ya fuera de la pantalla). `overflow-wrap` deja partir esa
 * palabra en dos líneas en vez de desbordar.
 */
.ap-tabbar a, .ap-tabbar .ap-tabbar__mas > summary { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center;
  gap: 4px; text-decoration: none; color: var(--ap-ink-400); font-family: var(--ap-font-body);
  font-size: 11.5px; font-weight: 800; padding: 10px 2px 12px; min-height: 44px; cursor: pointer; list-style: none;
  text-align: center; overflow-wrap: anywhere; }
.ap-tabbar .ap-tabbar__mas > summary::-webkit-details-marker { display: none; }
.ap-tabbar a.is-active, .ap-tabbar .ap-tabbar__mas[open] > summary, .ap-tabbar .ap-tabbar__mas > summary.is-active { color: var(--ap-teal-700); }
.ap-tabbar .ap-ico { width: 22px; height: 22px; }
.ap-tabbar__icono { position: relative; display: inline-flex; }
.ap-tabbar__num { position: absolute; top: -6px; right: -10px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--ap-coral-600); color: #fff; font-size: 10px; font-weight: 800; line-height: 16px; text-align: center; }
.ap-tabbar__mas { position: relative; }
.ap-tabbar__mas-menu { position: absolute; right: 6px; bottom: 100%; margin-bottom: 8px; min-width: 190px;
  background: var(--ap-surface); border: 1px solid var(--ap-line); border-radius: var(--ap-r-md); box-shadow: var(--ap-shadow-3); padding: 8px; }
.ap-tabbar__mas-menu a { flex-direction: row; align-items: center; gap: 10px; height: 44px; padding: 0 10px; font-size: 15px; color: var(--ap-ink-700); }
.ap-tabbar__mas-menu a.is-active { color: var(--ap-teal-800); }
.ap-tabbar__mas-menu .ap-tabbar__num { position: static; margin-left: auto; }

/* ======================= Botones ======================= */
.ap .ap-btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 48px; padding: 0 22px; border-radius: var(--ap-r-pill);
  font-family: var(--ap-font-body); font-weight: 800; font-size: 16px; border: 0; cursor: pointer; white-space: nowrap; }
.ap .ap-btn-primary { background: var(--ap-teal-700); color: #fff; box-shadow: 0 1px 0 rgb(255 255 255 / .12) inset, 0 6px 16px -6px rgb(14 91 85 / .6); }
.ap .ap-btn-primary:hover { background: var(--ap-teal-800); }
.ap .ap-btn-gold { background: var(--ap-gold-400); color: var(--ap-ink-900); box-shadow: 0 6px 16px -8px rgb(169 124 52 / .8); }
.ap .ap-btn-light { background: #fff; color: var(--ap-teal-800); }
.ap .ap-btn-ghost { background: transparent; color: var(--ap-teal-700); box-shadow: inset 0 0 0 1.5px var(--ap-teal-100); }
.ap .ap-btn-soft { background: var(--ap-teal-50); color: var(--ap-teal-800); }
.ap .ap-btn-sm { height: 38px; padding: 0 16px; font-size: 14px; }
.ap .ap-btn-lg { height: 56px; padding: 0 28px; font-size: 17px; }
.ap .ap-btn-block { width: 100%; }
.ap .ap-btn[disabled], .ap .ap-btn.is-disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

/* ======================= Tarjetas y chips ======================= */
.ap .ap-card { background: var(--ap-surface); border: 1px solid var(--ap-line); border-radius: var(--ap-r-lg); box-shadow: var(--ap-shadow-1); }
.ap .ap-card-pad { padding: 24px; }
/*
 * P2R · R3 — sin `min-width:0` un hijo flex no encoge por debajo del ancho de SU contenido
 * (el título «Recomendado para ti en la Biblioteca» no cabía junto a «Ver todo» a 390px) y el
 * navegador terminaba partiendo «Ver todo» letra por letra para hacerle sitio. `flex-wrap:wrap`
 * deja que el enlace baje debajo del título cuando no cabe en la misma fila; `flex:none` +
 * `white-space:nowrap` en el enlace evitan que ÉL sea el que se parta.
 */
.ap .ap-card-title { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; margin-bottom: 16px; }
.ap .ap-card-title h3 { display: flex; align-items: center; gap: 10px; min-width: 0; }
.ap .ap-link-more { display: inline-flex; align-items: center; gap: 6px; flex: none; white-space: nowrap; font-weight: 800; font-size: 14px; color: var(--ap-teal-700); }
.ap .ap-chip { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 12px; border-radius: var(--ap-r-pill);
  font-size: 13px; font-weight: 800; background: var(--ap-teal-50); color: var(--ap-teal-800); white-space: nowrap; }
.ap .ap-chip .ap-ico { width: 14px; height: 14px; }
.ap .ap-chip-gold { background: var(--ap-gold-100); color: var(--ap-gold-700); }
.ap .ap-chip-coral { background: var(--ap-coral-100); color: var(--ap-coral-700); }
.ap .ap-chip-ok { background: var(--ap-ok-100); color: var(--ap-ok-700); }
.ap .ap-chip-info { background: var(--ap-info-100); color: var(--ap-info-700); }
.ap .ap-chip-line { background: transparent; box-shadow: inset 0 0 0 1px var(--ap-line); color: var(--ap-ink-700); }
.ap .ap-chip-live { background: #FDECEC; color: #B4232A; }
/* H9 chunk 1/N (TANDA 23-SEP-P4H) · chips-pestaña de Biblioteca (`.gta-biblio2__tab`, JS
   propio que sólo hace `classList.toggle('is-activo', ...)`) — el prototipo `Biblioteca.html`
   pinta la pestaña activa con `background: var(--teal-700); color:#fff` a mano sobre `.chip`;
   aquí es una regla, no un estilo en línea repetido por cada botón. */
.ap .ap-chip.is-activo { background: var(--ap-teal-700); color: #fff; box-shadow: none; }
/* H7 chunk 4/N (TANDA 22-SEP-P4G/23-SEP-P4H) · el chip de estado del certificado (cabecera y
   columna de la lección, `header.php`/`sidebar.php`) lleva una frase, no una etiqueta corta
   como el resto de `.ap-chip`: en la columna angosta de la lección (~220px) el `white-space:
   nowrap` de base lo desborda y lo corta. `ap-chip-wrap` deja que ese chip en concreto rompa
   línea y crezca de alto en vez de desbordar. */
.ap .ap-chip-wrap { white-space: normal; height: auto; min-height: 28px; text-align: left; line-height: 1.3; }
/*
 * P2R · R8 — `png/Main.png` pinta cada logro como un círculo de 56px con su emoji encima y el
 * nombre centrado debajo, 3 por fila; la ganada a color, la pendiente en gris con un candado.
 */
.ap .ap-logro-grid { display: grid; grid-template-columns: repeat( 3, 1fr ); gap: 16px 8px; margin-top: 12px; }
.ap .ap-logro { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.ap .ap-logro-ico { width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center;
  font-size: 26px; flex: none; }
.ap .ap-logro-label { font-size: 12px; font-weight: 700; color: var(--ap-ink-700); line-height: 1.3; }
/* H4 (TANDA 23-SEP-P4H) · `ops/rediseno_premium/html/Main.html` pinta el círculo ganado con un
 * degradado radial (no plano) y borde real de 2px, ícono en `--gold-700`; el pendiente lleva el
 * mismo borde de 2px en `--line`, sin el `box-shadow` de 1px que usábamos antes. */
.ap .ap-logro-ok .ap-logro-ico { background: radial-gradient( circle at 30% 30%, #FFE7A3, var(--ap-gold-400) ); border: 2px solid var(--ap-gold-500); color: var(--ap-gold-700); }
.ap .ap-logro-line .ap-logro-ico { background: var(--ap-surface-2); color: var(--ap-ink-300); border: 2px solid var(--ap-line); }
.ap .ap-logro-line .ap-logro-label { color: var(--ap-ink-400); }
/*
 * P4E · E3(b) — `png/Main.png` pinta la racha como un calendario de 14 llamitas, una por día:
 * la de un día que SÍ contó (`valido = 1` del motor) a color, las demás en línea gris; la de
 * hoy lleva un contorno para ubicarla sin contar columnas.
 * H4 (TANDA 23-SEP-P4H) · `Main.html` no usa círculo sino casilla de esquina redondeada (30px,
 * radio 10px) con fondo plano `--gold-400`/borde `--gold-500`/ícono en `--ink-900` para el día
 * que sí contó; casilla en `--surface-2`/borde `--line`/`--ink-300` para el resto.
 */
.ap .ap-racha-cal { display: grid; grid-template-columns: repeat(14, minmax(0,1fr)); gap: 3px; margin-top: 12px; }
.ap .ap-racha-dia { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.ap .ap-racha-dia__ico { width: 100%; max-width: 30px; aspect-ratio: 1; border-radius: 10px; display: grid; place-items: center;
  background: var(--ap-surface-2); color: var(--ap-ink-300); border: 1px solid var(--ap-line); }
.ap .ap-racha-dia--on .ap-racha-dia__ico { background: var(--ap-gold-400); color: var(--ap-ink-900); border-color: var(--ap-gold-500); }
.ap .ap-racha-dia--hoy .ap-racha-dia__ico { box-shadow: 0 0 0 2px var(--ap-ok-700); }
/*
 * P4E · E3(e) — «Avisos de tu aula» pasa a llevar el avatar (iniciales) de quien publicó junto
 * al título, y «hace X h» a la derecha en vez de la fecha suelta sobre el título.
 */
.ap .ap-avatar--iniciales { background: var(--ap-teal-700); color: #fff; font-weight: 800; font-size: 14px; }
.ap .ap-aviso-fila { display: flex; align-items: flex-start; gap: 12px; }
.ap .ap-aviso-texto { flex: 1; min-width: 0; }
.ap .ap-aviso-cabecera { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ap .ap-aviso-titulo { font-size: 16px; margin: 0; }
.ap .ap-aviso-hace { flex: none; font-size: 12px; font-weight: 700; color: var(--ap-ink-400); white-space: nowrap; }
.ap .ap-chip-live::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--ap-live); box-shadow: 0 0 0 4px rgb(229 72 77 / .18); }
.ap .ap-seg { display: inline-flex; gap: 4px; padding: 4px; background: var(--ap-surface); border: 1px solid var(--ap-line); border-radius: var(--ap-r-pill); }
.ap .ap-seg a { height: 38px; padding: 0 16px; border-radius: var(--ap-r-pill); display: inline-flex; align-items: center; gap: 8px; font-weight: 800; font-size: 14px; color: var(--ap-ink-500); }
.ap .ap-seg a.is-active { background: var(--ap-teal-700); color: #fff; }
.ap .ap-seg .ap-count { font-size: 12px; padding: 0 7px; border-radius: 10px; background: rgb(15 31 29 / .07); line-height: 20px; }
.ap .ap-seg a.is-active .ap-count { background: rgb(255 255 255 / .18); }

/* ======================= Progreso ======================= */
.ap .ap-bar { height: 8px; background: var(--ap-teal-100); border-radius: 8px; overflow: hidden; }
.ap .ap-bar > span { display: block; height: 100%; border-radius: 8px; background: var(--ap-teal-500); }
.ap .ap-bar.gold > span { background: linear-gradient(90deg, var(--ap-gold-500), var(--ap-gold-400)); }
.ap .ap-bar-lg { height: 12px; }
.ap .ap-bar-pct { font-weight: 700; color: var(--ap-teal-700); margin-bottom: 4px; }

/* H7 chunk 3/N (TANDA 22-SEP-P4G/23-SEP-P4H) · migas de la lección, portadas de
   `.gta-migas--leccion` (area-estudio.css) al sistema `.ap`. D10 se conserva tal cual: las dos
   migas son las DOS salidas de la lección en el teléfono («Mis cursos» y el curso), así que
   cada enlace mide --ap-touch (44px) de alto y no el texto suelto de `.ap-meta`. */
.ap .gta-migas-leccion { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding: var(--ap-sp-6) var(--ap-sp-6) 0; min-width: 0; }
.ap .gta-migas-leccion a { display: inline-flex; align-items: center; min-height: var(--ap-touch); }
.ap .gta-migas-leccion__curso,
.ap .gta-migas-leccion__actual { max-width: min(38ch, 100%); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* En móvil la cabecera de Tutor ya nombra la lección: la miga final (y su separador) sobra
   y quitarla deja las dos salidas reales en una sola línea. */
@media (max-width: 600px) {
  .ap .gta-migas-leccion__actual,
  .ap .gta-migas-leccion__sep-final { display: none; }
}
/*
 * H7 chunk 5/N (TANDA 22-SEP-P4G/23-SEP-P4H) · «reproductor + tarjeta dorada» de
 * `Leccion.html`. El reproductor de verdad NO es el bloque de video de Tutor (los cursos de
 * la demo no llevan `video_info` de Tutor: el iframe de Bunny viaja como shortcode
 * `[gta_player]` dentro del cuerpo de la lección — GTA_Player::render(), mu-plugins/
 * gta-becas-core/class-gta-player.php) y su marco ya vive en `style.css`
 * (`.gta-player-frame`, `--r-md`). Aquí sólo se redondea a los 22px del prototipo: el
 * esqueleto de carga, el iframe y el aviso de error (`player-heartbeat.css`) no se tocan.
 *
 * La tarjeta dorada SÍ es nueva y es el mismo `.gta-vista` de `gta_candado_marcar_vista()`
 * (functions.php) — la puerta REAL del «Marcar como vista» (MASTER P14, ≥50 % del video) —
 * con las clases `.ap` puestas encima; ni la condición, ni el texto (`gta_puerta_texto()`),
 * ni el candado del `<button name="complete_lesson_btn">` se reescriben aquí. El botón real
 * de Tutor se restila por selector descendiente (sin tocar su marcado) para que se vea como
 * el «Completar lección» del prototipo en sus tres estados (candado, listo, completada).
 * `.esta-lista` es la clase que YA añadía `player-heartbeat.js` al abrirse la puerta en vivo
 * (antes sin ninguna regla): aquí se le da lectura visual, sin acuñar clase nueva.
 */
.ap .ap-gate-video,
.gta-vista.ap-gate-video { display: flex; align-items: center; gap: var(--ap-sp-5); padding: var(--ap-sp-4) var(--ap-sp-5);
  border-color: var(--ap-gold-100); background: var(--ap-gold-50); }
.ap-gate-video__ico { flex: none; width: 44px; height: 44px; border-radius: var(--ap-r-sm); background: #fff;
  color: var(--ap-gold-700); display: grid; place-items: center; }
.ap-gate-video__texto { flex: 1; min-width: 0; }
.ap-gate-video__texto b { font-size: 15px; }
.ap-gate-video__texto .gta-vista__motivo { margin: 2px 0 0; }
.ap-gate-video__barra { margin-top: var(--ap-sp-2); max-width: 520px; }
/* Lista (puerta abierta, aún sin completar): el acento pasa de dorado a teal, mismo patrón
   que el resto de `.ap` para «lo pendiente» → «lo listo». */
.ap-gate-video.esta-lista { border-color: var(--ap-teal-100); background: var(--ap-teal-50); }
.ap-gate-video.esta-lista .ap-gate-video__ico { color: var(--ap-teal-700); }
/* El botón real de Tutor (`.tutor-mark-as-complete-button`), sin tocar su marcado ni su JS:
   sólo el aspecto, para que combine con `.ap-btn`. */
.ap-gate-video .tutor-mark-as-complete-button { flex: none; display: inline-flex; align-items: center; gap: 8px;
  height: 38px; padding: 0 16px; border-radius: var(--ap-r-pill); background: #fff; color: var(--ap-ink-400);
  box-shadow: inset 0 0 0 1.5px var(--ap-line); font-weight: 800; font-size: 14px; border: 0; cursor: not-allowed; }
.ap-gate-video .tutor-mark-as-complete-button svg { width: 18px; height: 18px; }
.ap-gate-video .tutor-mark-as-complete-button:not([disabled]) { color: var(--ap-ink-900); box-shadow: none;
  background: var(--ap-gold-400); cursor: pointer; }
.ap-gate-video .tutor-mark-as-complete-button.completed { background: var(--ap-ok-100); color: var(--ap-ok-700);
  box-shadow: none; cursor: default; }
.ap-gate-video .tutor-mark-as-complete-button.completed svg { width: 22px; height: 22px; }
/* Medido en vivo a 390px: Tutor fija `.tutor-learning-area-footer` al fondo de la pantalla
   bajo 576px (tutor-learning-area.min.css) con cada `<form>` a 50% de ancho — pensado para un
   botón de una línea, no para esta tarjeta (icono + frase + barra). Con la tarjeta dentro, ese
   50% la aplastaba contra «Anterior»/«Siguiente» y la barra fija tapaba el contenido de debajo
   al hacer scroll. `:has()` acota el arreglo a la única fila que lleva `.ap-gate-video`: el
   resto de lecciones (sin puerta de video) conservan el pie fijo de Tutor tal cual.
 *
 * AVISO 24-sep punto 3 · el mismo aplastamiento pasa en escritorio: Tutor pone
 * `position:sticky;bottom:0` en `.tutor-learning-area-footer[data-lesson]` SIN media query
 * (tutor-learning-area.min.css) — pensado para un pie delgado que cabe entero, no para esta
 * tarjeta de 300px de alto. Medido en vivo a 1440px con «Mis apuntes» activa: el pie se
 * queda pegado sobre «Tus apuntes de este curso» al no caber sin recorte. La regla de abajo
 * ya no depende del ancho: `position: static` a cualquier tamaño para la única fila que
 * lleva `.ap-gate-video`. */
.tutor-learning-area-footer:has(.ap-gate-video) { position: static; }
@media (max-width: 576px) {
  .tutor-learning-area-footer:has(.ap-gate-video) { flex-direction: column; align-items: stretch; }
  .tutor-learning-area-footer:has(.ap-gate-video) form { width: 100%; }
}

/* H7 chunk 7/N (TANDA 23-SEP-P4H) · «Anterior»/«Siguiente» del pie de la lección
   (templates/learning-area/lesson/footer.php, botones de Tutor sin plantilla propia: no hay
   filtro para ellos como en `tutor_learning_area_lesson_mark_as_complete`, así que se restilan
   por selector descendiente, mismo patrón que `.tutor-mark-as-complete-button` arriba) pasan
   del `.tutor-btn` de fábrica al `.ap-btn-ghost.ap-btn-sm` del prototipo (`Leccion.html`), para
   no quedar como los dos únicos botones ingleses-de-forma en una pantalla ya portada al `.ap`. */
.tutor-learning-area-footer a.tutor-btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  height: 38px; padding: 0 16px; border-radius: var(--ap-r-pill); background: transparent; color: var(--ap-teal-700);
  box-shadow: inset 0 0 0 1.5px var(--ap-teal-100); font-family: var(--ap-font-body); font-weight: 800; font-size: 14px;
  border: 0; white-space: nowrap; }
.tutor-learning-area-footer a.tutor-btn:hover { background: var(--ap-teal-50); }
.tutor-learning-area-footer a.tutor-btn svg { width: 18px; height: 18px; }
.tutor-learning-area-footer a.tutor-btn.disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

.ap .ap-ring { position: relative; display: grid; place-items: center; flex: none; }
.ap .ap-ring svg { transform: rotate(-90deg); }
.ap .ap-ring .ap-ring-val { position: absolute; text-align: center; font-family: var(--ap-font-display); font-weight: 800; line-height: 1; }
.ap .ap-ring .ap-ring-val small { display: block; font-family: var(--ap-font-body); font-weight: 700; font-size: 11px; color: var(--ap-ink-400); margin-top: 4px; letter-spacing: .04em; }
.ap .ap-ring .ap-ring-val { font-size: 13px; }

/* ======================= Portadas de curso ======================= */
.ap .ap-cover { position: relative; border-radius: var(--ap-r-md); overflow: hidden; aspect-ratio: 16 / 9; }
.ap .ap-cover svg { display: block; width: 100%; height: 100%; }

/*
 * P2R · R8 — «Tus cursos» del hoy (`png/Main.png`): título suelto sobre el fondo (no dentro de
 * una `.ap-card`, a diferencia de «Recomendado…»/«Avisos» de abajo) + tarjetas compactas en fila.
 */
.ap .ap-section-title { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; margin: var(--ap-sp-8) 0 var(--ap-sp-4); }
.ap .ap-section-title h2 { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: 20px; }
.ap .ap-cover-mini { position: relative; width: 56px; height: 56px; flex: none; border-radius: var(--ap-r-sm); background: var(--ap-teal-50); overflow: hidden; }
.ap .ap-cover-mini svg { display: block; width: 100%; height: 100%; object-fit: cover; }
.ap .ap-curso-compacto { display: block; color: inherit; }
.ap .ap-curso-compacto__texto { flex: 1; min-width: 0; }
.ap .ap-curso-compacto__texto h3 { font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/*
 * ======================= Piezas de Biblioteca (R8(a), TANDA 22-SEP-P4F) =======================
 * `png/Main.png` las pinta como FILAS compactas (icono de formato + título + una línea de
 * metadatos + flecha), no como la tarjeta horizontal con portada 3:4 de la entrega anterior.
 */
.ap .ap-biblio-filas { display: flex; flex-direction: column; gap: var(--ap-sp-2); }
.ap .ap-biblio-fila { display: flex; align-items: center; gap: var(--ap-sp-3); padding: 10px var(--ap-sp-2); border-radius: var(--ap-r-sm); color: inherit; }
.ap .ap-biblio-fila:hover { background: var(--ap-teal-50); }
.ap .ap-biblio-fila__ico { display: grid; place-items: center; width: 36px; height: 36px; flex: none; border-radius: var(--ap-r-sm); background: var(--ap-teal-50); color: var(--ap-teal-700); }
.ap .ap-biblio-fila__portada { flex: none; width: 36px; height: 48px; object-fit: cover; border-radius: 4px; border: 1px solid var(--ap-ink-100, #e5e7eb); background: var(--ap-teal-50); }
.ap .ap-biblio-pags { display: flex; align-items: center; justify-content: center; gap: var(--ap-sp-3); margin-top: var(--ap-sp-4, 16px); flex-wrap: wrap; }
.ap .ap-biblio-modulo { margin: var(--ap-sp-4, 16px) 0 var(--ap-sp-2, 8px); font-weight: 700; color: var(--ap-ink-700, inherit); }
.ap .ap-biblio-fila__texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ap .ap-biblio-fila__titulo { font-weight: 700; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ap .ap-biblio-fila__chev { flex: none; color: var(--ap-ink-400); }

/* ======================= Formularios ======================= */
.ap .ap-field { display: flex; flex-direction: column; gap: 8px; }
.ap .ap-label { font-weight: 800; font-size: 14px; color: var(--ap-ink-700); }
.ap .ap-input { height: 48px; border-radius: 14px; border: 1px solid var(--ap-line); background: var(--ap-surface); padding: 0 16px; font: inherit; color: var(--ap-ink-900); display: flex; align-items: center; gap: 10px; }
.ap .ap-input.search { height: 54px; border-radius: var(--ap-r-pill); padding: 0 20px; box-shadow: var(--ap-shadow-1); }
.ap .ap-input .ap-ph { color: var(--ap-ink-400); }
.ap textarea.ap-input { height: 120px; padding: 14px 16px; resize: none; }

/* ======================= Utilidades ======================= */
.ap .ap-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ap-sp-6); }
.ap .ap-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ap-sp-6); }
.ap .ap-grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--ap-sp-5); }
.ap .ap-divider { height: 1px; background: var(--ap-line); }
.ap .ap-kbd { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; padding: 2px 6px; border-radius: 6px; background: var(--ap-surface-2); border: 1px solid var(--ap-line); }
.ap .ap-note { font-size: 13px; line-height: 20px; color: var(--ap-ink-400); display: flex; gap: 8px; align-items: flex-start; }
.ap .ap-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
/* H4 (TANDA 23-SEP-P4H) · cajita de fecha del Bloque 3 «Próxima sesión en vivo» (`Main.html` línea 65): día/número/mes, ~72x80px. */
.ap .ap-fecha-chip { flex: none; width: 72px; height: 80px; border-radius: var(--ap-r-md); background: var(--ap-teal-50); border: 1px solid var(--ap-teal-100);
	display: flex; flex-direction: column; align-items: center; justify-content: center; }
.ap .ap-fecha-chip__dia { font-size: 12px; font-weight: 800; color: var(--ap-teal-600); letter-spacing: .08em; }
.ap .ap-fecha-chip__num { font-family: var(--ap-font-display); font-weight: 800; font-size: 28px; line-height: 34px; color: var(--ap-ink-900); }
.ap .ap-fecha-chip__mes { font-size: 12px; font-weight: 800; color: var(--ap-ink-400); }

.ap a.ap-card { color: inherit; }
.ap .gta-ruta__cabecera .ap-meta.ap-num { white-space: nowrap; }
.ap a.ap-card:hover { box-shadow: var(--ap-shadow-2); }

/* P8.2 (TANDA 22-SEP-P8) · `/en-vivo/`: el reproductor incrustado (16:9, sin recorte) y las
   tarjetas del banco de grabaciones — miniatura con el icono de play centrado (no hay archivo
   de miniatura real por grabación, así que se pinta un color sólido en vez de una imagen rota)
   y el badge «Vista» cuando `ha_asistido()` ya es true para ese becario. */
.ap .ap-ev-player { position: relative; width: 100%; aspect-ratio: 16/9; border-radius: var(--ap-r-md); overflow: hidden; background: var(--ap-ink-900); }
.ap .ap-ev-player iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.ap .ap-ev-grabacion { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.ap .ap-ev-grabacion__miniatura { position: relative; aspect-ratio: 16/9; display: grid; place-items: center; background: var(--ap-teal-700); color: #fff; }
.ap .ap-ev-grabacion__vista { position: absolute; left: 10px; top: 10px; }
.ap .ap-ev-pregunta--destacada { box-shadow: inset 0 0 0 2px var(--ap-gold-700); }
#gta-ev-preguntas-form textarea { width: 100%; min-height: 44px; border-radius: var(--ap-r-md); border: 1px solid var(--ap-line); padding: 10px 12px; font: inherit; resize: vertical; }

/* H9 chunk 2/N (TANDA 23-SEP-P4H) · tarjeta de «Todos los recursos» de la Biblioteca
   (`Biblioteca.html` grid-4): portada cuadrada con el color de su familia, insignia de tipo
   en la esquina, chips de familia/fuente y acciones al pie — mismo patrón que las tarjetas del
   prototipo, sin inventar un dato por curso que la consulta de biblioteca no trae. */
.ap .ap-biblio-card { padding: 14px; display: flex; flex-direction: column; gap: 12px; }
/* S0 (TANDA 28-SEP-P46) · José: «las portadas tienen que previsualizarse, no quedar ocultas con
   esa imagen tan genérica» — con 4/3 + object-fit:cover una portada vertical de libro (los
   ficheros reales del almacén son 600×800, comprobado en `_portadas/`) se recortaba a lo ancho
   y perdía casi todo el diseño. Vertical real: la portada se ve casi completa, sin el recorte
   fuerte de antes. */
.ap .ap-biblio-portada { aspect-ratio: 600/800; border-radius: var(--ap-r-md); position: relative; overflow: hidden;
  display: grid; place-items: center; }
.ap .ap-biblio-portada .ap-ico { width: 34px; height: 34px; color: #fff; }
/* B1 (VEREDICTO_SUPERVISOR_23SEP.md, TANDA 22-SEP-P8 · P8.0) · la portada real siempre
   carga (confirmado: los 308 ficheros del almacén existen y `portada_url()` sirve 200 en
   todos), pero `loading="lazy"` no la trae hasta que la tarjeta entra al viewport — con
   `background: var(--ap-surface-2)` fijo eso se leía como «no cargó», no como «está
   cargando». El degradado animado + el `<img>` en opacidad 0 hasta `onload`/`onerror` (ver
   `views/biblioteca.php`) hacen que se vea un estado de carga, nunca un rectángulo vacío. */
.ap .ap-biblio-portada--img { padding: 0;
  background: linear-gradient(100deg, var(--ap-surface-2) 30%, #eef2f1 45%, var(--ap-surface-2) 60%);
  background-size: 250% 100%; animation: ap-biblio-shimmer 1.3s ease-in-out infinite; }
.ap .ap-biblio-portada--img.is-cargada { animation: none; background: var(--ap-surface-2); }
.ap .ap-biblio-portada--img img { width: 100%; height: 100%; object-fit: cover; display: block;
  opacity: 0; transition: opacity .2s ease; }
.ap .ap-biblio-portada--img.is-cargada img { opacity: 1; }
/* B1 remate 1 (CUARTA REVISIÓN, VEREDICTO_SUPERVISOR_23SEP.md): si la portada real da 404,
   `onerror` (ver `views/biblioteca.php`) marca la imagen con esta clase — nunca mostrar el
   icono de imagen rota ni el texto alternativo, sólo el fondo neutro ya cargado. */
.ap .ap-biblio-portada--img img.ap-biblio-portada__img-rota { opacity: 0 !important; }
/* B1 remate 2 (VEREDICTO_SUPERVISOR_23SEP.md): «cae a la genérica», no sólo se oculta. El
   div guarda su color de familia en `--ap-biblio-soft` (siempre, tenga o no portada real);
   si `onerror` añade `.ap-biblio-portada--rota`, se apaga la animación, vuelve el fondo del
   color de familia y aparece el icono gemelo que ya se pinta cuando no hay portada — mismo
   aspecto final que una pieza sin portada, nunca un rectángulo vacío. */
.ap .ap-biblio-portada--img.ap-biblio-portada--rota { animation: none; background: var(--ap-biblio-soft, var(--ap-surface-2)); }
.ap .ap-biblio-portada__generica { display: none; position: absolute; inset: 0; align-items: center; justify-content: center; }
.ap .ap-biblio-portada--rota .ap-biblio-portada__generica { display: flex; }
/* P46 S0 · «portada de marca»: sin imagen real, el rectángulo de color muestra el TÍTULO de la
   pieza (como el lomo de un libro), nunca sólo el ícono genérico de formato. */
.ap .ap-biblio-portada__marca { display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 10px; padding: 18px; text-align: center; }
.ap .ap-biblio-portada__marca-ico { opacity: .85; }
.ap .ap-biblio-portada__marca-titulo { font-size: 15px; font-weight: 800; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
@keyframes ap-biblio-shimmer { 0% { background-position: 200% 0; } 100% { background-position: 0 0; } }
.ap .ap-biblio-badge { position: absolute; right: 10px; top: 10px; font-size: 11px; font-weight: 800;
  letter-spacing: .06em; color: var(--ap-ink-900); background: #fff; border-radius: 8px; padding: 2px 8px; }
.ap .ap-biblio-card b { font-size: 16px; line-height: 22px; }
.ap .ap-biblio-card .ap-meta { margin-top: -6px; }
.ap .ap-biblio-card__acciones { display: flex; gap: 8px; margin-top: auto; }

/* R8 (TANDA 22-SEP-P2R) · las tres cifras del hero (racha/bekis/insignias) de `png/Main.png`,
   a la derecha del saludo en escritorio. `margin-left: auto` las empuja al borde cuando
   `.ap-hero__texto` no llena el ancho; con `.ap-row { flex-wrap: wrap }` (móvil, regla ya
   existente) caen en su propia fila debajo del saludo sin CSS adicional. */
.ap .ap-hero__stats { display: flex; gap: var(--ap-sp-3); margin-left: auto; flex: none; }
.ap .ap-hero__stat {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 92px; padding: var(--ap-sp-3) var(--ap-sp-4);
  background: var(--ap-gold-50); border: 1px solid var(--ap-gold-100); border-radius: var(--ap-r-lg);
  color: var(--ap-gold-700);
}
.ap .ap-hero__stat-num { font-family: var(--ap-font-display); font-size: 22px; font-weight: 800; color: var(--ap-ink-900); }
.ap .ap-hero__stat-label { font-size: 12px; color: var(--ap-ink-500); text-align: center; line-height: 1.2; }

/* R8 chunk 2 (TANDA 22-SEP-P2R) · `png/Main.png` (`--teal-800`, fecha en `--gold-400`, cifras
   sobre tarjetas translúcidas) — mismos tokens `--ap-*` que ya usa el resto del sistema, ningún
   color a mano nuevo. `.ap-hero--oscuro` es un modificador sobre `.ap-hero`, no un componente
   aparte: el resto de reglas de `.ap-hero` (alto en móvil, etc.) le siguen aplicando igual. */
.ap .ap-hero--oscuro { background: var(--ap-teal-800); border-color: transparent; position: relative; overflow: hidden; }
/* H4 chunk 2/N (TANDA 22-SEP-P4G/P4H) · `Main.html` línea 21: círculos decorativos tras el
   saludo, sólo en el hero oscuro. `pointer-events:none` para que no roben clics del contenido
   que va encima (`.ap-hero--oscuro .ap-row` ya queda por delante al ser el siguiente hermano
   en el flujo normal, sin necesitar z-index). */
.ap .ap-hero__deco { position: absolute; right: -60px; top: -40px; opacity: .5; pointer-events: none; }
/* H4 chunk 3/N (TANDA 22-SEP-P4G/23-SEP-P4H) · `Main.html` línea 45 no mete a Beki en el flujo
   bajo las cifras (eso empujaba la tarjeta más alta que el prototipo): lo cuelga ABSOLUTO del
   borde inferior del hero (`bottom:-12px`, recortado por el `overflow:hidden` de la tarjeta),
   a la derecha, bajo la rejilla de cifras. Mismo patrón aquí. */
.ap .ap-hero__beki { position: absolute; right: var(--ap-sp-6); bottom: -12px; pointer-events: none; }
.ap .ap-hero--oscuro .ap-hero__fecha { color: var(--ap-gold-400); }
.ap .ap-hero--oscuro h1 { color: #fff; }
.ap .ap-hero--oscuro .ap-hero__sub { color: #D7ECE8; }
.ap .ap-hero--oscuro .ap-hero__stat {
  background: rgb(255 255 255 / .08); border-color: rgb(255 255 255 / .14); color: #BFDAD5;
}
.ap .ap-hero--oscuro .ap-hero__stat-num { color: #fff; }
.ap .ap-hero--oscuro .ap-hero__stat-label { color: #BFDAD5; }
.ap .ap-btn-ghost-claro { background: rgb(255 255 255 / .1); color: #fff; box-shadow: inset 0 0 0 1.5px rgb(255 255 255 / .25); }
.ap .ap-btn-ghost-claro:hover { background: rgb(255 255 255 / .16); }

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

.ap .ap-btn:focus-visible,
.ap .ap-nav-link:focus-visible,
.ap .ap-icon-btn:focus-visible,
.ap .ap-avatar-btn:focus-visible,
.ap .ap-menu-item:focus-visible,
.ap .ap-seg a:focus-visible,
.ap a:focus-visible {
  outline: none;
  box-shadow: var(--ap-ring);
}
/* K2 · sobre banda teal (hero oscuro, ruta) el aro exterior teal se pierde (1,27:1): aro exterior claro, hueco oscuro */
.ap .ap-hero--oscuro :is(a, button):focus-visible,
.ap .ap-ruta :is(a, button):focus-visible {
  box-shadow: 0 0 0 2px var(--ap-teal-900), 0 0 0 4px #fff;
}
/* P34 lente 5: los buscadores y cuadros de mensaje llevan el `outline:0` en el campo interior;
   sin esto el teclado no veía dónde escribía (WCAG 2.4.7). El aro sale en la caja que lo envuelve. */
.ap .ap-input:focus-within {
  border-color: var(--ap-teal-600, var(--ap-line));
  box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--ap-teal-600, #11706a);
}

/* ======================= Móvil (P2.4, TANDA 22-SEP-P2) =======================
   `.ap-nav` no llevaba NINGÚN @media: a 390 px la marca, los 6 enlaces de escritorio, el chip
   de racha, la campana y el avatar se apretaban en una sola fila de 72 px de alto y desbordaban
   el viewport (medido: 640px de contenido para 390 de pantalla). Se apagan aquí los enlaces de
   escritorio y el nombre de cuenta porque `.ap-tabbar` (arriba) YA lleva la misma navegación al
   pulgar desde P1.2 chunk 2 — no es una pérdida de función, es la misma ruta por otra barra.
   Este bloque va AL FINAL del fichero a propósito: `.ap-grid-2/3/4` y `.ap-page` se declaran en
   «Utilidades» más arriba con la MISMA especificidad, y en CSS gana quien viene DESPUÉS en la
   hoja — puesto antes (como en el primer intento de este chunk), el `@media` perdía siempre
   contra la regla de escritorio sin que ninguna herramienta lo avisara. */
@media (max-width: 640px) {
  .ap .ap-nav { padding: 0 var(--ap-sp-3); gap: var(--ap-sp-2); }
  .ap .ap-nav-links,
  .ap .ap-nav .gta-navbar__conmutador--escritorio,
  .ap .ap-brand small { display: none; }
  /*
   * NO `display:none` AQUÍ. Ese botón no lleva `aria-label`: su avatar es decorativo y este
   * texto es su ÚNICO nombre accesible (Lighthouse `button-name` lo cazó a la primera —el botón
   * pasaba a no tener ninguno). Se oculta a la vista con el mismo recorte de `.ap-sr`, no de la
   * accesibilidad.
   */
  .ap .gta-navbar__cuenta-nombre {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  }
  /*
   * P2R · R1 — `.ap-menu` (el panel de «Mi perfil / Cerrar sesión») nunca se había visto a este
   * ancho: hasta este chunk, `.ap .ap-menu` no matcheaba nada (el mismo defecto de la barra) y el
   * panel salía sin ningún estilo, así que su `width:280px; right:32px` de escritorio quedaba
   * dormido. Al despertar la regla de la barra, este chunk lo despertó también, y a 390px ese
   * ancho fijo corre el panel FUERA del viewport (medido: el documento se iba a 612px). Mismo
   * panel, ancho fluido.
   */
  /*
   * `position: fixed` y no `absolute`: el padre posicionado real es `.gta-navbar__cuenta`
   * (64px de ancho, del botón), no la barra — `left`/`right` en `absolute` se miden contra ÉL y
   * el panel salía angosto de 40px en vez de ancho. `fixed` lo mide contra el viewport, que es
   * lo que hace falta para que quepa.
   */
  .ap .ap-menu { position: fixed; top: calc(var(--gta-cab-top) + 12px); right: var(--ap-sp-3); left: var(--ap-sp-3); width: auto; }

  /* Las tarjetas anchas (`ap-row` con portada fija de 180px + texto al lado, Bloque 2/3) caben
     en 1200px de escritorio pero no en 390: se apilan en columna, y la portada deja de ser
     `flex:none` para no quedarse angosta cuando su ancho fijo no cabe en el viewport. Las
     rejillas de 2/3/4 columnas (Logros/Racha, Tus cursos) bajan a 1 columna — `png/MovilMiBeca.png`
     pinta cada tarjeta a lo ancho, apiladas, nunca en rejilla. La Biblioteca (Bloque 8, R8(a)
     TANDA 22-SEP-P4F) ya son filas compactas de ancho completo: no necesitan override aparte. */
  .ap .ap-page { padding: var(--ap-sp-5) var(--ap-sp-4) var(--ap-sp-7); }
  .ap .ap-row { flex-wrap: wrap; }
  .ap .ap-row > .ap-cover { width: 100% !important; flex: none !important; }
  .ap .ap-grid-2, .ap .ap-grid-3, .ap .ap-grid-4 { grid-template-columns: minmax(0, 1fr); }

  /* R5 (TANDA 22-SEP-P2R) · el saludo (Bloque 1) es la tarjeta con la que arranca la pantalla:
     con Beki a 64-88px y el h1 al tamaño de escritorio (34/42px), el título de dos palabras
     partía en dos líneas y la tarjeta pasaba de 220px de alto en 390px de ancho — «Continúa
     donde te quedaste» (Bloque 2) quedaba fuera de los 844px del viewport sin scroll (medido con
     `verificar-r4-burbuja-beki.mjs` como base). Beki más chico, h1 en una línea y padding menor:
     mismo contenido, menos alto. `!important` sólo en el SVG porque su tamaño llega por atributo
     `width`/`height` inline (`gta_beki_svg()`), no por una regla de CSS que esta pueda ganar. */
  .ap .ap-hero { padding: var(--ap-sp-4); gap: var(--ap-sp-3) !important; }
  .ap .ap-hero .gta-beki { width: 48px !important; height: 44px !important; }
  .ap .ap-hero h1 { font-size: 22px; line-height: 28px; }
  .ap .ap-hero__sub { font-size: var(--ap-fs-sm); line-height: var(--ap-lh-sm); }
  .ap .ap-hero__stats { width: 100%; margin-left: 0; }
  .ap .ap-hero__stat { flex: 1; min-width: 0; padding: var(--ap-sp-2) var(--ap-sp-2); }
  .ap .ap-hero__stat-num { font-size: 18px; }

  /*
   * H5 (TANDA 22-SEP-P4G/23-SEP-P4H) · `.ap-seg` (segmentado de «Mis cursos») no traía ningún
   * recorte a 390px: dentro de un `.ap-row` con `flex-wrap:wrap` sus botones se apretaban hasta
   * partir «En curso»/«Completados» letra por letra (medido con
   * `verificar-h5-miscursos.mjs`, captura `h5-miscursos-390.png`, texto ilegible tipo «d 4 / En
   * / Comp…»). Mismo patrón que ya usaba `.gta-chips` para este caso: ancho completo, riel con
   * scroll horizontal y texto en una sola línea por botón — nada se oculta, se desliza.
   */
  .ap .ap-seg { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .ap .ap-seg a { flex: none; white-space: nowrap; }

  /*
   * H6 chunk 1/N (TANDA 22-SEP-P4G/23-SEP-P4H) · la tarjeta de avance del hero de «Curso»
   * (`cabecera-curso.php`) trae `flex:none; width:270px` inline (mismo patrón que el resto
   * de anchos fijos de este bloque, arriba): sin `!important` el ancho fijo gana a esta
   * regla y la tarjeta queda angosta con hueco vacío al lado en vez de a lo ancho.
   */
  .ap .gta-hero-curso__anillo { width: 100% !important; max-width: none !important; }

  /*
   * H6 chunk 3/N (TANDA 22-SEP-P4G/23-SEP-P4H) · la cabecera de cada módulo de «Ruta del
   * curso» (`ruta-del-curso.php`) mete insignia + título + meta + chip + flecha en una sola
   * fila sin `flex-wrap`: a 390px el conteo de lecciones («N lecciones · Xh Ym») se apretaba
   * contra el chip. Mismo patrón que `.gta-ruta__meta` de la versión anterior: la meta baja
   * de línea, con el margen del ancho de la insignia (46px + 16px de gap) para alinear bajo
   * el título en vez de bajo la insignia.
   */
  .ap .gta-ruta__cabecera { flex-wrap: wrap; }
  .ap .gta-ruta__cabecera .ap-meta.ap-num,
  .ap .gta-ruta__cabecera .ap-chip,
  .ap .gta-ruta__cabecera > span:last-child { order: 3; }
  .ap .gta-ruta__cabecera .ap-meta.ap-num { flex: 1 1 100%; margin-left: 62px; margin-right: 0 !important; white-space: normal; }
  /* P107 P0g · la sección de cada módulo puede encogerse al ancho del contenedor (en columna flex su mínimo era el contenido, 304 px a 320). */
  .ap .gta-ruta > .ap-card { min-width: 0; }
}

/*
 * H10 (TANDA 23-SEP-P4H) · Certificados — porta `Certificados.html` (tarjeta-mérito con la
 * imagen del certificado a la izquierda y el nombre/código superpuestos, datos y botones a la
 * derecha; la rejilla «En camino» reusa `.ap-grid-2` con una portada gris + candado). La
 * plantilla oficial del PDF sólo existe hoy para `excelencia` (`GTA_Cert_Plantillas`); el resto
 * cae al icono genérico `award`, así que el nombre/código sólo se superponen cuando hay foto
 * real — pintarlos sobre el icono inventaría una imagen que no está.
 */
.ap .ap-cert-hero {
  display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: var(--ap-sp-6); align-items: center; padding: 28px;
  background: linear-gradient(180deg, #fff, var(--ap-gold-50)); border-color: var(--ap-gold-100);
}
.ap .ap-cert-hero--horas { background: var(--ap-surface); border-color: var(--ap-line); }
.ap .ap-cert-hero__imagen {
  position: relative; border-radius: var(--ap-r-lg); overflow: hidden; aspect-ratio: 1.293;
  box-shadow: var(--ap-shadow-2, 0 10px 30px -14px rgb(0 0 0 / .3));
  background: var(--ap-teal-50); color: var(--ap-teal-500); display: grid; place-items: center;
}
.ap .ap-cert-hero__imagen img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ap .ap-cert-hero__nombre {
  position: absolute; left: 0; right: 0; top: 53.5%; text-align: center;
  font-family: var(--ap-font-display); font-weight: 700; font-size: 30px;
  letter-spacing: .01em; color: #1C2330;
}
.ap .ap-cert-hero__codigo {
  position: absolute; left: 0; right: 0; bottom: 2.2%; text-align: center;
  font-size: 11px; font-weight: 800; letter-spacing: .06em; color: #4A5160;
}
.ap .ap-cert-hero__meta { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ap .ap-cert-hero__dato { background: #fff; border: 1px solid var(--ap-line); border-radius: var(--ap-r-md); padding: 12px 14px; }
.ap .ap-cert-hero__dato--ancho { grid-column: span 2; }
.ap .ap-cert-hero__dato .ap-meta { display: block; }
.ap .ap-cert-camino__imagen {
  width: 190px; flex: none; position: relative; border-radius: var(--ap-r-md); overflow: hidden;
  aspect-ratio: 1.29; background: #111; color: #fff; display: grid; place-items: center;
}
.ap .ap-cert-camino__imagen img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) blur(1px); opacity: .55; }
.ap .ap-cert-camino__candado {
  position: absolute; inset: 0; margin: auto; width: 44px; height: 44px; display: grid; place-items: center;
  background: #fff; color: #1C2330; border-radius: var(--ap-r-pill);
  box-shadow: var(--ap-shadow-1, 0 4px 10px rgb(0 0 0 / .18));
}
/* La tarjeta-mérito es 2 columnas a 1440 (portada + datos) y `.ap-cert-camino__imagen` lleva
   un ancho fijo de 190px; ninguna de las dos cabe en 390. Este bloque va DESPUÉS de la regla
   de escritorio de arriba a propósito: puesto dentro del `@media (max-width:640px)` de la
   cabecera (antes en el fichero), la regla de escritorio sin condición que viene después en
   la hoja la ganaba siempre, en cualquier ancho — misma cascada que ya explica el comentario
   de la barra en tableta, unas líneas más abajo. */
@media (max-width: 640px) {
  .ap .ap-cert-hero { grid-template-columns: 1fr; }
  .ap .ap-cert-camino__imagen { width: 100%; }
}

/* ======================= Barra en tableta (P2R, TANDA 22-SEP-P2R, R1) =======================
   Medido con Playwright a 768 y 1024: la marca + 6 enlaces con texto + el chip de racha + la
   campana + el botón de cuenta CON el nombre visible piden 1246px — más que el propio 1024, así
   que el documento entero se corría en horizontal y el resto de la barra quedaba fuera de
   pantalla sin aviso. No hay prototipo de tableta (`rediseno_premium/png/` sólo trae 1440 y 390):
   se reutiliza el MISMO colapso del móvil, sólo para la barra (el contenido de la página sigue
   con su propio corte en 640px, arriba) — la tabbar del pie, ahora visible hasta 1024px, ocupa el
   lugar de los enlaces. */
@media (min-width: 641px) and (max-width: 1024px) {
  .ap .ap-nav-links,
  .ap .ap-nav .gta-navbar__conmutador--escritorio,
  .ap .ap-brand small { display: none; }
  .ap .gta-navbar__cuenta-nombre {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  }
}

/*
 * TANDA 23-SEP-P4H, H11 · «Bandeja del aula» (`views/mi-grupo-aula-mensajes.php`) — las tres
 * columnas de `BandejaDocente.html` (filtros · lista · conversación) no caben ni a 390 ni en el
 * ancho real de `.ap-page` de este portal (`--ap-content:1200px`, no los 1440 del prototipo:
 * ver el comentario de `.ap-page` arriba). Mismo corte de 640px que el resto de la hoja: por
 * debajo, la rejilla pasa a una sola columna y sólo se ve UNA cosa a la vez — la lista (con sus
 * filtros) si no hay hilo abierto, la conversación (con «← Bandeja del aula») si lo hay — mismo
 * criterio de «una pantalla, una tarea» que ya usa `.ap-mensajes` del lado del alumno.
 */
.ap .ap-mam-grid { display: grid; grid-template-columns: 200px 320px minmax(0, 1fr); }
.ap .ap-mam-volver { display: none; }
@media (max-width: 640px) {
  /* `!important`: los tres hijos de la rejilla traen su propio `display:flex` en línea (layout
     de escritorio, mismo criterio que el resto de `.ap-*` de este fichero) y una regla externa
     sin `!important` nunca gana a un estilo en línea, por especificidad — no es adorno. */
  .ap .ap-mam-grid { grid-template-columns: 1fr; min-height: 0 !important; }
  .ap .ap-mam-grid > .ap-mam-conversacion { display: none !important; }
  .ap .ap-mam-grid.ap-mam-grid--abierto > .ap-mam-filtros,
  .ap .ap-mam-grid.ap-mam-grid--abierto > .ap-mam-lista { display: none !important; }
  .ap .ap-mam-grid.ap-mam-grid--abierto > .ap-mam-conversacion { display: flex !important; }
  .ap .ap-mam-volver { display: block; }
}

/*
 * N13 chunk 1/2 (TANDA 22-SEP-P9) · `AlumnoPrimaria` — letra y botones grandes, y sobre todo:
 * el avance se dice con PUNTOS, nunca con un número de `%`. `.ap8-punto` porta `puntos()` del
 * generador Python (círculos rellenos = misión hecha, borde grueso = la actual, vacío = por
 * hacer) tal cual, sin barra ni anillo.
 */
.ap .ap8 h1, .ap .ap8 h2, .ap .ap8 h3 { font-family: var(--ap-font-display); }
.ap .ap8-h1 { font-size: 40px; line-height: 1.15; color: #fff; }
.ap .ap8-h2 { font-size: 24px; line-height: 1.3; }
.ap .ap8-hero__sub { font-size: 17px; line-height: 1.5; color: #D7ECE8; max-width: 44ch; margin: 0; }
.ap .ap8-stat { background: rgb(255 255 255 / .08); border: 1px solid rgb(255 255 255 / .14); border-radius: 18px;
  padding: 14px 18px; text-align: center; min-width: 100px; color: #fff; }
.ap .ap8-stat__num { display: block; font-family: var(--ap-font-display); font-weight: 800; font-size: 28px; line-height: 1.2; margin-top: 4px; }
.ap .ap8-stat__label { font-size: 13px; color: #BFDAD5; font-weight: 700; }

.ap .ap8-puntos { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.ap .ap8-punto { display: inline-grid; place-items: center; flex: none; border-radius: 50%; border: 2px solid var(--ap-line);
  background: var(--ap-surface-2); color: var(--ap-ink-300); }
.ap .ap8-punto--hecha { background: var(--ap-gold-400); border-color: var(--ap-gold-500); color: var(--ap-ink-900); }
.ap .ap8-punto--actual { background: var(--ap-surface); border-color: var(--ap-teal-700); border-width: 3px; color: var(--ap-teal-700); }
.ap .ap8-puntos__resto { font-size: 14px; font-weight: 800; color: var(--ap-ink-400); align-self: center; }

.ap .ap8-aventura { display: flex; flex-direction: column; gap: 0; padding: 0; overflow: hidden; text-decoration: none; }
.ap .ap8-aventura__cov { display: block; }
.ap .ap8-aventura__cuerpo { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 10px; }
.ap .ap8-aventura__titulo { font-family: var(--ap-font-display); font-weight: 700; font-size: 19px; line-height: 1.25; color: var(--ap-ink-900); }

.ap .ap8-dia { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.ap .ap8-dia__letra { font-size: 13px; font-weight: 800; color: var(--ap-ink-400); }
.ap .ap8-dia__marca { width: 100%; aspect-ratio: 1; max-width: 48px; border-radius: 16px; border: 2px solid var(--ap-line);
  background: var(--ap-surface-2); display: grid; place-items: center; color: var(--ap-ink-300); }
.ap .ap8-dia__marca--ok { background: var(--ap-gold-400); border-color: var(--ap-gold-500); color: var(--ap-ink-900); }

.ap .ap8-premio { display: flex; flex-direction: column; align-items: center; gap: 8px; width: 96px; text-align: center; }
.ap .ap8-premio__ico { width: 68px; height: 68px; border-radius: 50%; display: grid; place-items: center;
  background: var(--ap-surface-2); border: 3px solid var(--ap-line); color: var(--ap-ink-300); }
.ap .ap8-premio--ok .ap8-premio__ico { background: radial-gradient(circle at 30% 30%, #FFE7A3, var(--ap-gold-400)); border-color: var(--ap-gold-500); color: var(--ap-gold-700); }
.ap .ap8-premio__nombre { font-size: 12.5px; line-height: 1.3; font-weight: 800; color: var(--ap-ink-400); }

/* P45 W3 · «Arma tu ruta» (GTA_Ruta_Sugerida), a la altura del prototipo de
   /mnt/d/GTA/01_Becas-GG/ops/prototipos/ruta_sugerida/: tarjeta teal con Beki y contador
   «N de 3 respondidas», preguntas con opciones grandes en vez de <select>. */
.ap .ap-ruta { background: linear-gradient(135deg, var(--ap-teal-800), var(--ap-teal-900)); color: #fff;
  border-radius: var(--ap-r-lg); padding: 28px 30px; position: relative; overflow: hidden; }
.ap .ap-ruta__cab { display: flex; align-items: flex-start; gap: 16px; justify-content: space-between; flex-wrap: wrap; }
.ap .ap-ruta__beki { flex: none; width: 56px; height: 56px; border-radius: 50%; background: rgb(255 255 255 / .12);
  display: grid; place-items: center; border: 2px solid rgb(255 255 255 / .35); overflow: hidden; }
.ap .ap-ruta__beki .gta-beki { width: 44px; height: auto; }
.ap .ap-ruta__titulo { font-family: var(--ap-font-display); font-weight: 800; font-size: 22px; margin: 0; color: #fff; }
.ap .ap-ruta__sub { color: rgb(255 255 255 / .78); margin: 2px 0 0; font-size: 14px; }
.ap .ap-ruta__contador { font-size: 13px; font-weight: 800; color: rgb(255 255 255 / .85); white-space: nowrap; }
.ap .ap-ruta__pregunta { margin-top: 22px; }
.ap .ap-ruta__pregunta-cab { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.ap .ap-ruta__num { flex: none; width: 24px; height: 24px; border-radius: 50%; background: var(--ap-gold-400);
  color: var(--ap-ink-900); font-weight: 800; font-size: 13px; display: grid; place-items: center; }
.ap .ap-ruta__pregunta-txt { font-weight: 700; font-size: 15.5px; margin: 0; }
.ap .ap-ruta__opciones { display: flex; flex-wrap: wrap; gap: 10px; }
.ap .ap-ruta__opcion { position: relative; }
.ap .ap-ruta__opcion input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ap .ap-ruta__opcion label { display: flex; align-items: center; gap: 10px; min-height: 56px; padding: 10px 16px;
  border-radius: 14px; background: rgb(255 255 255 / .08); border: 1.5px solid rgb(255 255 255 / .18);
  cursor: pointer; transition: background .15s, border-color .15s; }
.ap .ap-ruta__opcion label:hover { background: rgb(255 255 255 / .14); }
.ap .ap-ruta__opcion input:checked + label { background: #fff; border-color: #fff; color: var(--ap-ink-900); }
.ap .ap-ruta__opcion input:focus-visible + label { box-shadow: var(--ap-ring); }
.ap .ap-ruta__opcion-ico { flex: none; display: grid; place-items: center; width: 22px; height: 22px; }
.ap .ap-ruta__opcion-t { font-weight: 800; font-size: 14.5px; line-height: 1.2; }
.ap .ap-ruta__opcion-s { font-weight: 600; font-size: 12.5px; line-height: 1.2; color: rgb(255 255 255 / .7); }
.ap .ap-ruta__opcion input:checked + label .ap-ruta__opcion-s { color: var(--ap-ink-500); }
.ap .ap-ruta__acciones { display: flex; align-items: center; gap: 18px; margin-top: 24px; flex-wrap: wrap; }
.ap .ap-ruta__acciones a { color: #fff; text-decoration: underline; font-weight: 700; font-size: 14.5px; }
.ap .ap8-premio--ok .ap8-premio__nombre { color: var(--ap-ink-700); }

/* P45 W3 · «Tu ruta sugerida» (Estado 2 de GTA_Ruta_Sugerida), a la altura del prototipo:
   camino con pasos numerados unidos por una línea punteada ámbar (horizontal en escritorio,
   vertical en celular — mismo truco del prototipo: mover la línea de `top` a `left`). */
.ap .ap-ruta2__cab { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.ap .ap-ruta2__titulo { font-family: var(--ap-font-display); font-weight: 800; font-size: 21px; margin: 4px 0 6px; }
.ap .ap-ruta2__resumen { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.ap .ap-ruta2__camino { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin: 22px 0 0; padding: 0; list-style: none; position: relative; }
.ap .ap-ruta2__camino::before { content: ""; position: absolute; left: 8%; right: 8%; top: 21px; border-top: 2.5px dashed var(--ap-gold-500); z-index: 0; }
.ap .ap-ruta2__paso { position: relative; z-index: 1; }
.ap .ap-ruta2__num { width: 42px; height: 42px; border-radius: 50%; background: var(--ap-teal-600); color: #fff;
  font-family: var(--ap-font-display); font-weight: 800; font-size: 16px; display: grid; place-items: center;
  margin: 0 auto 12px; box-shadow: 0 0 0 6px var(--ap-surface); }
.ap .ap-ruta2__paso.is-hecho .ap-ruta2__num { background: var(--ap-ok-700); }
.ap .ap-ruta2__paso.is-hecho .ap-ruta2__num svg { width: 16px; height: 16px; }
.ap .ap-ruta2__card { background: var(--ap-surface); border: 1px solid var(--ap-line-2); border-radius: var(--ap-r-md); overflow: hidden; box-shadow: var(--ap-shadow-1); }
.ap .ap-ruta2__portada { border-radius: 0; }
.ap .ap-ruta2__cuerpo { padding: 14px 15px 15px; }
.ap .ap-ruta2__cuerpo h3 { font-family: var(--ap-font-display); font-weight: 700; font-size: 15px; margin: 0 0 6px; line-height: 1.3; }
.ap .ap-ruta2__porque { font-size: 12.5px; color: var(--ap-ink-700); background: var(--ap-gold-50); border-radius: 10px; padding: 8px 10px; margin: 0 0 12px; }
.ap .ap-ruta2__fila { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.ap .ap-ruta2__mover { display: flex; gap: 6px; }
.ap .ap-ruta2__mover button { width: 32px; height: 32px; border-radius: 10px; border: 1px solid var(--ap-line-2); background: var(--ap-surface); color: var(--ap-teal-600); font-weight: 900; cursor: pointer; }
.ap .ap-ruta2__pie { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 18px; font-size: 13px; color: var(--ap-ink-500); }
@media (max-width: 640px) {
  .ap .ap-ruta2__camino { grid-template-columns: 1fr; gap: 14px; }
  .ap .ap-ruta2__camino::before { left: 20px; right: auto; top: 10px; bottom: 10px; border-top: 0; border-left: 2.5px dashed var(--ap-gold-500); }
  .ap .ap-ruta2__paso { display: grid; grid-template-columns: 42px 1fr; gap: 12px; align-items: start; }
  .ap .ap-ruta2__num { margin: 0; }
  .ap .ap-ruta2__pie { flex-direction: column; align-items: stretch; }
}

/* P47 S0 (TANDA 28-SEP-P47) · VISTA GENERAL DE LA BIBLIOTECA, como el prototipo
   `ops/prototipos/biblioteca_v2/`: hero con abanico de portadas, carriles de portadas verticales
   COMPLETAS (600×850, `contain`: ni un recorte), colecciones por curso con tres portadas en
   abanico, plantillas con su vista apaisada y la rejilla de «Todos los recursos» a 5 columnas. */
.ap .gta-vg-hero { display: grid; grid-template-columns: 1.25fr 1fr; gap: 24px; align-items: center;
  background: linear-gradient(135deg, #0E5B55, #127A6E); color: #fff; border-radius: 28px; padding: 36px 40px; overflow: hidden; }
.ap .gta-vg-hero__ceja { margin: 0 0 8px; font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: #FFC24B; }
.ap .gta-vg-hero h1 { margin: 0; font-size: 44px; line-height: 1.05; color: #fff; }
.ap .gta-vg-hero__bajada { max-width: 560px; color: #D7E9E6; font-size: 17px; line-height: 1.55; margin: 14px 0 0; }
.ap .gta-vg-hero__cifras { display: flex; gap: 10px; flex-wrap: wrap; list-style: none; padding: 0; margin: 18px 0 0; }
.ap .gta-vg-hero__cifras li { background: rgba(255,255,255,.12); padding: 8px 14px; border-radius: 999px; font-size: 14px; }
.ap .gta-vg-hero__cifras strong { color: #FFC24B; }
.ap .gta-vg-hero__abanico { position: relative; height: 300px; }
.ap .gta-vg-hero__abanico img { position: absolute; width: 170px; aspect-ratio: 600/850; object-fit: cover; border-radius: 12px; box-shadow: 0 18px 36px rgba(0,0,0,.35); top: 30px; background: #fff; }
.ap .gta-vg-hero__p1 { left: 10px; transform: rotate(-10deg); }
.ap .gta-vg-hero__p2 { left: 120px; transform: rotate(-3deg); top: 10px !important; }
.ap .gta-vg-hero__p3 { left: 230px; transform: rotate(4deg); top: 20px !important; }
.ap .gta-vg-hero__p4 { left: 330px; transform: rotate(11deg); top: 45px !important; }
.ap .gta-vg-fila { margin-top: 40px; min-width: 0; max-width: 100%; }
.ap .gta-vg-carril, .ap .gta-biblio2__tabs { position: relative; min-width: 0; max-width: 100%; }
.ap .gta-vg-cab { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.ap .gta-vg-cab h2 { margin: 0; font-size: 24px; }
.ap .gta-vg-cab h2 span { font-size: 15px; font-weight: 600; color: var(--ap-ink-500, #5F6B69); margin-left: 8px; }
.ap .gta-vg-flechas button { width: 36px; height: 36px; border-radius: 50%; background: #fff; border: 1px solid var(--ap-line); font-size: 22px; line-height: 1; margin-left: 6px; cursor: pointer; }
.ap .gta-vg-ver { background: none; border: 0; font: inherit; font-weight: 700; color: var(--ap-teal-700, #0E5B55); cursor: pointer; white-space: nowrap; }
.ap .gta-vg-carril { display: grid; grid-auto-flow: column; grid-auto-columns: calc((100% - 5 * 18px) / 6); gap: 18px;
  overflow-x: auto; scroll-snap-type: x mandatory; padding: 4px 2px 8px; }
.ap .gta-vg-libro { scroll-snap-align: start; display: flex; flex-direction: column; }
.ap .gta-vg-portada { position: relative; aspect-ratio: 600/850; border-radius: 12px; overflow: hidden;
  background: var(--ap-surface-2, #EEF4F3); box-shadow: 0 10px 22px rgba(30,43,41,.16); transition: transform .2s; }
.ap .gta-vg-libro:hover .gta-vg-portada { transform: translateY(-4px); }
.ap .gta-vg-portada img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ap .gta-vg-tipo { position: absolute; left: 8px; bottom: 8px; background: rgba(255,255,255,.94); color: #0E5B55;
  font-size: 11px; font-weight: 800; padding: 3px 8px; border-radius: 999px; }
.ap .gta-vg-tipo--sol { background: #FFC24B; color: #1E2B29; }
.ap .gta-vg-info { padding: 10px 2px 0; display: flex; flex-direction: column; flex: 1; }
.ap .gta-vg-curso { margin: 0; font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #8A5A0F; }
.ap .gta-vg-info h3, .ap .gta-vg-coleccion h3 { margin: 4px 0; font-size: 15px; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ap .gta-vg-meta { margin: 0; font-size: 13px; color: var(--ap-ink-500, #5F6B69); }
.ap .gta-vg-acciones { display: flex; gap: 6px; margin-top: auto; padding-top: 10px; flex-wrap: nowrap; }
.ap .gta-vg-acciones .ap-btn { padding-left: 12px; padding-right: 12px; white-space: nowrap; }
.ap .gta-vg-colecciones, .ap .gta-vg-plantillas { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.ap .gta-vg-coleccion, .ap .gta-vg-plantilla { background: #fff; border-radius: 18px; overflow: hidden; box-shadow: 0 8px 22px rgba(30,43,41,.08); display: flex; flex-direction: column; }
.ap .gta-vg-abanico { position: relative; height: 210px; background: var(--gta-vg-c, #0E5B55); overflow: hidden; }
.ap .gta-vg-abanico img { position: absolute; width: 104px; aspect-ratio: 600/850; object-fit: cover; bottom: 14px; border-radius: 8px; box-shadow: 0 10px 20px rgba(0,0,0,.3); background: #fff; }
.ap .gta-vg-abanico__f1 { left: calc(50% - 130px); transform: rotate(-8deg); }
.ap .gta-vg-abanico__f2 { left: calc(50% - 52px); bottom: 24px !important; z-index: 2; }
.ap .gta-vg-abanico__f3 { left: calc(50% + 26px); transform: rotate(8deg); }
.ap .gta-vg-coleccion__info { padding: 18px; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.ap .gta-vg-coleccion__info .ap-btn { margin-top: 12px; }
.ap .gta-vg-plantilla .gta-vg-portada { aspect-ratio: 560/380; border-radius: 0; box-shadow: none; border-bottom: 1px solid var(--ap-line); }
.ap .gta-vg-plantilla .gta-vg-portada img { object-fit: cover; object-position: top; }
.ap .gta-vg-plantilla .gta-vg-portada--vertical img { object-fit: contain; object-position: center; }
.ap .gta-vg-plantilla .gta-vg-tipo { top: 10px; bottom: auto; }
.ap .gta-vg-plantilla .gta-vg-info { padding: 14px 16px 16px; }
.ap .gta-vg-rejilla { grid-template-columns: repeat(5, 1fr); }
.ap .gta-vg-rejilla .ap-biblio-portada { aspect-ratio: 600/850; }
.ap .gta-vg-rejilla .ap-biblio-portada--img img { object-fit: contain; }
@media (max-width: 1100px) { .ap .gta-vg-rejilla { grid-template-columns: repeat(3, 1fr); } .ap .gta-vg-colecciones, .ap .gta-vg-plantillas { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px) {
  .ap .gta-vg-hero { grid-template-columns: 1fr; padding: 24px 20px; border-radius: 22px; }
  .ap .gta-vg-hero h1 { font-size: 30px; }
  .ap .gta-vg-hero__bajada { font-size: 15px; }
  .ap .gta-vg-hero__abanico { height: 180px; }
  .ap .gta-vg-hero__abanico img { width: 104px; }
  .ap .gta-vg-hero__p1 { left: 0; } .ap .gta-vg-hero__p2 { left: 70px; } .ap .gta-vg-hero__p3 { left: 140px; } .ap .gta-vg-hero__p4 { left: 205px; }
  .ap .gta-biblio2__tabs { flex-wrap: nowrap !important; overflow-x: auto; padding-bottom: 6px; }
  .ap .gta-biblio2__tabs > * { white-space: nowrap; flex: none; }
  .ap .gta-vg-carril { grid-auto-columns: 42%; }
  .ap .gta-vg-colecciones, .ap .gta-vg-plantillas { grid-template-columns: 1fr; }
  .ap .gta-vg-rejilla { grid-template-columns: repeat(2, 1fr); }
  .ap .gta-vg-cab h2 { font-size: 20px; }
  .ap .gta-vg-cab h2 span { display: block; margin: 2px 0 0; }
}
.ap .gta-vg-estantes { margin-top: 40px; background: #fff; border: 1px solid var(--ap-line); border-radius: 18px; padding: 14px 18px; }
.ap .gta-vg-estantes > summary { cursor: pointer; font-weight: 800; font-size: 17px; color: var(--ap-teal-700, #0E5B55); }

/* A7 · H4 · a ≤389 px (390 queda igual) la cabecera pedía 380 px (marca con rótulo + racha + campana + cuenta) y la página se corría en horizontal a 375, 360 y 320. Se queda la marca (enlace al Inicio) y el rótulo pasa a texto solo para lectores de pantalla: el enlace conserva su nombre accesible. */
@media (max-width: 389px) {
  .ap .ap-brand > span:not(.ap-brand-mark) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
}
