/* core-app/assets/css/site.css — sistema de diseño de TODO core-app: las
   páginas públicas/alumno (inicio, cursos, curso, cuenta) Y el panel de
   administración de la academia (admin/*). Paleta CLARA a propósito —
   deliberadamente distinta del tema oscuro de la homepage de SimpleAula y
   de master_panel (esas sí deben verse como "la marca SaaS"; tanto el
   sitio público como el panel admin de una academia son el negocio del
   cliente, no un anexo del panel interno de SimpleAula — por eso el admin
   de la academia también va en claro, aunque sea un "dashboard"). Mismo
   verde de acento para que se note que es la misma familia de producto,
   recalibrado para fondo blanco.

   Modo oscuro (solo panel admin): ver el bloque
   ".admin-shell[data-theme=dark]" más abajo — es una preferencia PERSONAL
   del admin que inicia sesión (cookie, no config de marca), y solo repinta
   dentro de .admin-shell. El sitio público del alumno nunca tiene ese
   ancestro, así que queda intacto siempre. */

:root {
    --bg: #f8fafc;
    --bg-alt: #ffffff;
    --panel: #ffffff;
    --panel-2: #f1f5f9;
    --border: #e2e8f0;
    --text: #0f172a;
    --muted: #64748b;
    --accent: #16a34a;
    --accent-2: #0891b2;
    --accent-3: #7c3aed;
    --accent-rgb: 22,163,74;
    --accent-2-rgb: 8,145,178;
    --accent-3-rgb: 124,58,237;
    --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    --danger: #dc2626;
    --danger-rgb: 220,38,38;
    --danger-bg: #fef2f2;
    --danger-border: #fecaca;
    --warn: #a16207;
    --warn-bg: #fef9c3;
    --radius: 16px;
    --radius-sm: 10px;
    --shadow-sm: 0 1px 2px rgba(15,23,42,.04);
    --shadow-md: 0 14px 32px rgba(15,23,42,.08);
}

/* ---------- Modo oscuro del panel admin (preferencia personal, ver arriba) ----------
   Redefine los mismos nombres de token dentro de .admin-shell[data-theme="dark"]:
   como las custom properties de CSS heredan por el DOM, esto repinta automáticamente
   cualquier componente ya existente que use var(--bg)/var(--panel)/etc. sin tocar su
   HTML — el mecanismo es el mismo para el shell (sidebar/topbar) y para el contenido
   de cada página admin ya construida. Paleta deliberadamente distinta del neón
   #4cf817 de master_panel (esa es la marca interna de SimpleAula; el panel de una
   academia sigue siendo "el negocio del cliente", solo que ahora también en oscuro). */
.admin-shell[data-theme="dark"] {
    --bg: #0b1220;
    --bg-alt: #101a2c;
    --panel: #131d30;
    --panel-2: #1a2740;
    --border: #2a3752;
    --text: #e7edf7;
    --muted: #8ea0bd;
    /* Mismo azul del wordmark que en claro (ya tiene contraste de sobra sobre
       fondo oscuro, 5.25:1); --accent-2 sí sube al extremo más cian del
       degradado del ícono (el que en claro quedaba con muy poco contraste
       sobre blanco, acá brilla mejor y es más fiel al logo). */
    --accent: #2885ff;
    --accent-2: #14acff;
    --accent-3: #a78bfa;
    --accent-rgb: 40,133,255;
    --accent-2-rgb: 20,172,255;
    --accent-3-rgb: 167,139,250;
    --danger: #f87171;
    --danger-rgb: 248,113,113;
    --danger-bg: rgba(248,113,113,.14);
    --danger-border: rgba(248,113,113,.35);
    --warn: #fbbf24;
    --warn-bg: rgba(251,191,36,.16);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.3);
    --shadow-md: 0 18px 40px rgba(0,0,0,.5);
}
/* Transición suave de colores al alternar el tema — acotada a las superficies
   principales (no ".admin-shell *", por rendimiento). */
.admin-shell, .admin-sidebar, .admin-topbar, .admin-main, .content-card, .form-section,
.stat, .table-wrap, .modulo-card, .leccion-card, .metodo-card, .plan-card, .feature-card {
    transition: background-color .25s ease, color .25s ease, border-color .25s ease;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-family);
    line-height: 1.55;
    overflow-x: hidden;
}
a { color: inherit; }
img { max-width: 100%; display: block; }
p { margin: 0; }
.wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }

/* ---------- Header ---------- */
.site-header {
    position: sticky; top: 0; z-index: 50;
    background: rgba(255,255,255,0.82); backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--border);
}
/* padding-top/bottom, NUNCA el shorthand "padding": estos elementos llevan
   la clase .wrap (padding: 0 24px lateral) además de .bar — un "padding: Xpx 0"
   acá pisaría ESE lateral por completo (misma propiedad, mayor especificidad),
   dejando el logo/hamburguesa pegados al borde de la pantalla en mobile. Mismo
   criterio aplicado a .bar-dividida-top/.nav-dividida-abajo/.header-minimalista
   .bar/.bar-destacada-top/.bar-destacada-bottom/.bar-compacta más abajo. */
.site-header .bar { display: flex; align-items: center; justify-content: space-between; padding-top: 16px; padding-bottom: 16px; gap: 20px; }
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; font-weight: 800; font-size: 16px; min-width: 0; color: var(--text); }
.brand .dot { width: 10px; height: 10px; border-radius: 3px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); flex-shrink: 0; }
.brand .brand-logo-img { height: 28px; width: auto; max-width: 160px; object-fit: contain; flex-shrink: 0; }
.brand span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.nav-desktop { display: flex; align-items: center; gap: 28px; }
.nav-desktop a.navlink { color: var(--muted); text-decoration: none; font-size: 14px; font-weight: 600; }
.nav-desktop a.navlink:hover { color: var(--text); }
.header-actions { display: flex; align-items: center; gap: 12px; }
.header-actions .navlink { color: var(--muted); text-decoration: none; font-size: 14px; font-weight: 600; }
.header-actions .navlink:hover { color: var(--text); }

/* min-width/min-height (no solo padding): asegura un target táctil de ~44px,
   el mínimo recomendado, sin depender de que el ícono interno mida lo
   suficiente por sí solo. */
.menu-toggle {
    display: none; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px; background: none; border: 1px solid var(--border);
    color: var(--text); border-radius: 10px; padding: 8px; cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}
.menu-toggle:hover { background: var(--panel-2); border-color: rgba(var(--accent-rgb),.35); }

/* ---------- Drawer de navegación móvil (site_header.php) — panel fijo que
   entra deslizando desde la derecha, mismo mecanismo ya probado en
   .admin-sidebar/.panel-sidebar/.lesson-sidebar (position:fixed + transform +
   overlay independiente), no el viejo truco de grid-rows que "empujaba" el
   contenido de la página. Reemplaza a .mobile-panel/.mobile-panel-inner. */
.site-nav-overlay { display: none; }
.site-nav-drawer {
    position: fixed; top: 0; right: 0; bottom: 0; width: min(320px, 85vw);
    background: var(--panel); z-index: 60; display: flex; flex-direction: column;
    transform: translateX(100%); transition: transform .3s var(--ease-spring, cubic-bezier(.4,0,.2,1));
    box-shadow: -20px 0 60px rgba(0,0,0,.16);
}
.site-nav-drawer.abierto { transform: translateX(0); }
.site-nav-drawer-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 18px 18px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.site-nav-drawer-brand { display: flex; align-items: center; gap: 10px; min-width: 0; overflow: hidden; }
.site-nav-drawer-brand .brand-logo-img { height: 26px; width: auto; max-width: 150px; object-fit: contain; }
.site-nav-drawer-brand .brand-nombre { font-weight: 800; font-size: 15px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.site-nav-close {
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 38px; height: 38px; border-radius: 10px; border: 1px solid var(--border);
    background: none; color: var(--text); cursor: pointer; transition: background .15s ease, border-color .15s ease;
}
.site-nav-close:hover { background: var(--panel-2); border-color: rgba(var(--accent-rgb),.35); }
.site-nav-drawer-links { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 2px; }
.site-nav-drawer-link {
    display: flex; align-items: center; gap: 14px; padding: 12px; border-radius: 12px;
    color: var(--text); text-decoration: none; font-size: 15px; font-weight: 600;
    transition: background .15s ease;
}
.site-nav-drawer-link:hover, .site-nav-drawer-link:active { background: var(--panel-2); }
.site-nav-drawer-foot {
    padding: 16px 18px 22px; border-top: 1px solid var(--border);
    display: flex; flex-direction: column; gap: 10px; flex-shrink: 0;
}

@media (max-width: 720px) {
    .nav-desktop, .header-actions, .header-actions-izq, .header-actions-der, .nav-dividida-abajo { display: none; }
    .menu-toggle { display: flex; }
    /* Dividida usa grid en desktop (ver abajo) — en mobile solo deben quedar
       visibles la marca y el botón hamburguesa, en una sola fila simple. */
    .bar-dividida-top { display: flex; justify-content: space-between; align-items: center; padding-top: 16px; padding-bottom: 16px; }
    .site-nav-overlay.visible { display: block; position: fixed; inset: 0; background: rgba(15,23,42,.4); z-index: 55; }
}
/* Red de seguridad: el drawer/overlay solo tiene sentido bajo el breakpoint de
   arriba (es lo que abre .menu-toggle, que ya está oculto en desktop) — si la
   clase ".abierto"/".visible" quedó pegada de una visita móvil anterior y la
   ventana se agranda (o cambia de tamaño sin recargar), esto evita que el
   drawer se quede visible flotando sobre el sitio de escritorio. */
@media (min-width: 721px) {
    .site-nav-drawer, .site-nav-overlay { display: none !important; }
}

/* ---------- Estructuras de sitio (admin/temas.php) — menú -----------------
   Solo importan en desktop: bajo 720px el header ya colapsa siempre al mismo
   hamburger+drawer sin importar la estructura elegida (ver arriba), así que
   estas reglas van scopeadas a ese mismo breakpoint para no interferir. */
@media (min-width: 721px) {
    /* Clásica: logo solo a la izquierda; menú + acciones (Ingresar/Regístrate)
       agrupados juntos a la derecha (antes el menú quedaba "flotando" en el
       medio del header, sin agrupar con nada de los dos lados). */
    .header-group-der { display: flex; align-items: center; gap: 28px; min-width: 0; }

    /* Dividida: 2 filas. Arriba, 3 columnas reales vía CSS grid — acción
       izquierda (Ingresar/Mis cursos, como botón) | logo centrado | acción
       derecha (Regístrate gratis). Abajo, el menú centrado en su propia fila. */
    .bar-dividida-top { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; padding-top: 16px; padding-bottom: 16px; gap: 14px; }
    .header-actions-izq { justify-self: start; }
    .header-actions-der { justify-self: end; }
    .nav-dividida-abajo { justify-content: center; padding-bottom: 16px; }

    /* Minimalista: más liviano — sin blur ni línea inferior marcada, más aire.
       Ingresar y Regístrate ahora son botones reales (antes uno se mostraba
       como link con flecha) diferenciados por color: Ingresar usa
       .btn-secondary (blanco/borde), Regístrate usa .btn-primary (verde). */
    .header-minimalista { background: #fff; backdrop-filter: none; border-bottom: 1px solid transparent; }
    .header-minimalista .bar { padding-top: 24px; padding-bottom: 24px; }
    .header-minimalista .nav-desktop a.navlink { font-weight: 500; }
}

/* ---------- Estructuras de sitio — header "destacada" (marca sola arriba,
   nav+acciones en una franja propia debajo) ---------- */
.bar-destacada-top { display: flex; align-items: center; justify-content: center; position: relative; padding-top: 20px; padding-bottom: 20px; }
.bar-destacada-top .menu-toggle { position: absolute; right: 24px; top: 50%; transform: translateY(-50%); }
.header-destacada-bottom { background: var(--panel-2); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.bar-destacada-bottom { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding-top: 10px; padding-bottom: 10px; }
@media (max-width: 720px) { .header-destacada-bottom { display: none; } }

/* ---------- Estructuras de sitio — header "compacta" (nav en píldora) ---------- */
.bar-compacta { padding-top: 12px; padding-bottom: 12px; }
.nav-pill { background: var(--panel-2); border-radius: 999px; padding: 5px 6px; gap: 2px; }
.nav-pill a.navlink { padding: 7px 14px; border-radius: 999px; transition: background .15s ease, color .15s ease; }
.nav-pill a.navlink:hover { background: var(--panel); color: var(--text); }

/* ---------- Estructuras de sitio — header "editorial" (franja de anuncio
   arriba de la fila clásica, reutilizada tal cual) ---------- */
.header-anuncio-strip { background: var(--accent); color: #fff; text-align: center; font-size: 12.5px; font-weight: 600; padding: 7px 16px; }
@media (max-width: 480px) { .header-anuncio-strip { font-size: 11.5px; padding: 6px 12px; } }

/* ---------- Botones ---------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 12px 22px; border-radius: 10px; border: none;
    font-weight: 700; font-size: 14px; cursor: pointer; text-decoration: none;
    transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.btn:active { transform: scale(.97); }
/* Segundo color del degradado vía var(--accent-boton2, ...) con fallback —
   así sitios sin personalizar (o sin "Acento secundario" cargado) se ven
   exactamente igual que antes, y una zona/color global que sí lo define
   controla AMBOS colores del botón, no solo el primero. */
.btn-primary { background: linear-gradient(135deg, var(--accent), var(--accent-boton2, #22c55e)); color: #ffffff; }
.btn-primary:hover { box-shadow: 0 10px 24px rgba(var(--accent-rgb),.28); }
.btn-secondary { background: #ffffff; color: var(--text); border: 1px solid var(--border); }
.btn-secondary:hover { background: var(--panel-2); }
/* El fondo de .btn-secondary está fijo en blanco (pensado para el sitio
   claro) pero su texto usa var(--text) — en el admin en tema oscuro
   var(--text) es claro, así que sin este override queda texto claro
   sobre fondo blanco (invisible). Repinta con los mismos tokens ya
   usados por el resto de superficies oscuras del panel. */
.admin-shell[data-theme="dark"] .btn-secondary { background: var(--panel-2); border-color: var(--border); }
.admin-shell[data-theme="dark"] .btn-secondary:hover { background: var(--border); }
.btn-sm { padding: 9px 16px; font-size: 13px; }
.btn-block { width: 100%; }
/* ---------- Reseñas: fila de 5 estrellas SVG (sa_estrellas_html() en
   resenas_helpers.php), reutilizada en las tarjetas de curso y en la
   presentación del curso. */
.resena-linea { display: flex; align-items: center; gap: 4px; }
.resena-estrellas { display: inline-flex; align-items: center; gap: 1px; color: #f59e0b; }
.resena-estrellas svg { flex-shrink: 0; }
.resena-estrellas.sin-resenas { color: var(--muted); font-size: 12px; font-weight: 600; }
.resena-numero { font-size: 12.5px; color: var(--muted); font-weight: 600; }

/* ---------- Banner de rating promedio (admin/resenas.php) + fila
   persona con avatar-inicial (reutilizable en cualquier tabla que
   muestre un alumno por fila) + texto de feedback en la tabla ---------- */
.resenas-rating-banner { display: flex; align-items: center; padding: 10px 16px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow-sm); }
.fila-persona { display: flex; align-items: center; gap: 10px; font-weight: 600; color: var(--text); }
.avatar-fila {
    width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; font-size: 12.5px; font-weight: 800; color: #fff;
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    display: flex; align-items: center; justify-content: center;
}
.feedback-texto { margin: 0 0 6px; font-size: 13.5px; color: var(--text); line-height: 1.6; }

/* Selector de calificación interactivo (formulario de "Danos tu opinión") —
   truco clásico 100% CSS: los inputs van en orden DESCENDENTE (5..1) en el
   DOM, el contenedor está en row-reverse (así se VEN de 1 a 5 de izquierda
   a derecha), y ":checked ~ label"/"label:hover ~ label" pinta el
   seleccionado/hovereado y todo lo que le sigue en el DOM — que
   visualmente son las estrellas anteriores. Funciona sin JS y es
   accesible por teclado (son radios reales). */
.star-rating-input { display: inline-flex; flex-direction: row-reverse; justify-content: flex-end; gap: 2px; }
.star-rating-input input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.star-rating-input label { font-size: 30px; line-height: 1; color: var(--border); cursor: pointer; transition: color .12s ease; }
.star-rating-input label:hover,
.star-rating-input label:hover ~ label,
.star-rating-input input:checked ~ label { color: #f59e0b; }
.star-rating-input input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.wishlist-btn { gap: 8px; }
.wishlist-btn.activo { background: rgba(225,29,72,.1); border-color: rgba(225,29,72,.3); color: #e11d48; }
.wishlist-btn.activo:hover { background: rgba(225,29,72,.16); }

/* ---------- Fondo decorativo compartido (grid + orbes).
   Vive en su propio div vacío, absoluto y detrás del contenido — el mask-image
   afecta TODO lo que se pinta dentro del elemento al que se aplica, así que
   nunca debe compartir elemento con texto real (si no, el texto se desvanece
   junto con el patrón de grid). */
.fondo-decorado {
    position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background-image:
        linear-gradient(rgba(15,23,42,0.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(15,23,42,0.05) 1px, transparent 1px);
    background-size: 42px 42px;
    mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 40%, transparent 100%);
}
.orbe { position: absolute; border-radius: 50%; filter: blur(80px); pointer-events: none; z-index: 0; }

/* ---------- Hero ---------- */
.hero { padding: 76px 0 60px; text-align: center; position: relative; overflow: hidden; }
.hero .wrap { position: relative; z-index: 1; }
.eyebrow {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px;
    padding: 6px 14px; font-size: 12.5px; color: var(--muted); font-weight: 600; margin-bottom: 22px;
}
.eyebrow .dot-sm { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.hero h1 { font-size: 46px; font-weight: 800; margin: 0 0 18px; letter-spacing: -0.5px; color: var(--text); }
.hero h1 span { background: linear-gradient(135deg, var(--accent), var(--accent-2)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.hero .lead { max-width: 560px; margin: 0 auto 32px; color: var(--muted); font-size: 17px; }
.hero-ctas { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }

/* Imagen de portada del hero (admin/temas.php, sección "Hero de inicio") — solo en las
   estructuras clásica/minimalista (dividida ya tiene su propia columna de imagen, ver
   .hero-dividida-imagen más abajo). Mismo criterio ya establecido para .fondo-decorado:
   vive en su propio div vacío detrás del contenido, nunca comparte elemento con el texto
   real. Este bloque va DESPUÉS de ".hero h1"/".hero .lead" a propósito: misma especificidad
   (una clase + un elemento) que esas reglas, así que el orden en el archivo decide cuál
   gana — puesto antes, ".hero h1 { color: var(--text) }" le ganaba y el texto quedaba
   oscuro sobre un fondo oscuro, casi ilegible. */
.hero-portada-imagen { position: absolute; inset: 0; z-index: 0; background-size: cover; background-position: center; }
.hero-portada-overlay { position: absolute; inset: 0; z-index: 0; background: linear-gradient(180deg, rgba(15,23,42,.5), rgba(15,23,42,.72)); }

/* Texto claro cuando el hero tiene imagen de portada (siempre necesita contraste sobre la
   superposición oscura de arriba) — nunca se aplica en la estructura dividida, cuyo texto
   vive en su propia columna, separada de la imagen. */
.hero-texto-claro .eyebrow { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.28); color: #fff; }
.hero-texto-claro h1 { color: #fff; }
.hero-texto-claro h1 span { -webkit-text-fill-color: initial; background: none; color: var(--accent-2); }
.hero-texto-claro .lead { color: rgba(255,255,255,.88); }
.hero-texto-claro.hero-minimalista .btn-primary { color: #fff; border-color: #fff; }
.hero-texto-claro.hero-minimalista .btn-secondary { color: rgba(255,255,255,.75); }

@media (max-width: 640px) {
    .hero { padding: 52px 0 40px; }
    .hero h1 { font-size: 32px; }
    .hero .lead { font-size: 15.5px; }
}

/* ---------- Estructuras de sitio — hero "dividida" (texto + imagen en 2 columnas) ---------- */
.hero-dividida { padding: 60px 0; text-align: left; }
.hero-dividida-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 48px; align-items: center; }
.hero-dividida-texto .eyebrow { margin-bottom: 18px; }
.hero-dividida-texto h1 { font-size: 40px; font-weight: 800; margin: 0 0 16px; letter-spacing: -.5px; color: var(--text); }
.hero-dividida-texto h1 span { background: linear-gradient(135deg, var(--accent), var(--accent-2)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.hero-dividida-texto .lead { max-width: 460px; margin: 0 0 28px; color: var(--muted); font-size: 16.5px; }
.hero-dividida-texto .hero-ctas { justify-content: flex-start; }
.hero-dividida-imagen { aspect-ratio: 4/3; border-radius: var(--radius); overflow: hidden; background: linear-gradient(135deg, rgba(var(--accent-rgb),.14), rgba(var(--accent-2-rgb),.14)); background-size: cover; background-position: center; display: flex; align-items: center; justify-content: center; }
.hero-dividida-imagen img { width: 100%; height: 100%; object-fit: cover; }
.hero-dividida-imagen-fallback { width: 64px; height: 64px; border-radius: 18px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); }
@media (max-width: 860px) {
    .hero-dividida-grid { grid-template-columns: 1fr; text-align: center; }
    .hero-dividida-texto .lead { margin-left: auto; margin-right: auto; }
    .hero-dividida-texto .hero-ctas { justify-content: center; }
    .hero-dividida-imagen { max-width: 420px; margin: 0 auto; }
}

/* ---------- Estructuras de sitio — hero "minimalista" (sin imagen, solo tipografía) ---------- */
.hero-minimalista { padding: 100px 0 76px; text-align: center; }
.hero-minimalista .eyebrow { display: none; }
.hero-minimalista h1 { font-size: 40px; font-weight: 700; margin: 0 0 20px; letter-spacing: -.3px; color: var(--text); }
.hero-minimalista h1 span { color: var(--accent); }
.hero-minimalista .lead { max-width: 480px; margin: 0 auto 34px; color: var(--muted); font-size: 16px; }
.hero-minimalista .btn-primary { background: none; color: var(--text); border-bottom: 2px solid var(--accent); border-radius: 0; padding: 4px 2px; }
.hero-minimalista .btn-primary:hover { box-shadow: none; }
.hero-minimalista .btn-secondary { border: none; color: var(--muted); }
@media (max-width: 640px) {
    .hero-minimalista { padding: 64px 0 48px; }
    .hero-minimalista h1 { font-size: 30px; }
}

/* ---------- Estructuras de sitio — hero "editorial" (mismo hero de "clásica",
   alineado a la izquierda en vez de centrado) ---------- */
.hero-editorial { text-align: left; }
.hero-editorial .lead { margin-left: 0; margin-right: auto; }
.hero-editorial .hero-ctas { justify-content: flex-start; }
@media (max-width: 640px) {
    .hero-editorial { text-align: center; }
    .hero-editorial .lead { margin-left: auto; margin-right: auto; }
    .hero-editorial .hero-ctas { justify-content: center; }
}

/* Barra de estadísticas del hero "editorial" (cursos/lecciones/rating,
   calculados en vivo desde la BD en inicio.php — nunca datos inventados). */
.hero-stats-bar { display: flex; gap: 30px; margin-top: 30px; flex-wrap: wrap; }
.hero-stat { display: flex; flex-direction: column; gap: 2px; }
.hero-stat strong { font-size: 24px; font-weight: 800; color: var(--text); line-height: 1; }
.hero-stat span { font-size: 12.5px; color: var(--muted); font-weight: 600; }
@media (max-width: 640px) { .hero-stats-bar { justify-content: center; gap: 24px; } }

/* ---------- Secciones ---------- */
.section { padding: 60px 0; }
.section-head { text-align: center; max-width: 560px; margin: 0 auto 40px; }
.section-head h2 { font-size: 28px; margin: 0 0 10px; color: var(--text); }
.section-head p { color: var(--muted); font-size: 15px; }

/* ---------- Cursos ---------- */
.cursos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 22px; }
.curso-card-wrap { display: flex; flex-direction: column; gap: 10px; }
.curso-card-wrap .curso-card { flex: 1; }
/* .curso-card dejó de ser el <a> completo (para poder tener, además del
   link a la presentación, un botón de wishlist y un botón de CTA que NO
   deben quedar anidados dentro de otro <a> — HTML inválido y clicks
   ambiguos) — ahora es el contenedor; ".curso-card-link" es el <a> que
   envuelve la miniatura + el cuerpo (todo lo que sigue siendo "un solo
   click lleva al curso"), y el botón de wishlist/el CTA final son
   hermanos suyos dentro de ".curso-card". */
.curso-card {
    background: var(--tarjeta-fondo, var(--panel)); border: 1px solid var(--border); border-radius: var(--radius);
    overflow: hidden; box-shadow: var(--shadow-sm); position: relative;
    display: flex; flex-direction: column; text-decoration: none; color: inherit;
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
/* text-decoration/color de arriba quedan por compatibilidad con usos que
   TODAVÍA ponen esta clase directo en un <a> (ej. alumno/mis-cursos.php,
   que muestra "mis" cursos con progreso — deliberadamente NO usa
   curso_card.php: ahí no aplican wishlist/CTA de compra, ya son del
   alumno). El catálogo público (curso_card.php) usa el patrón nuevo:
   .curso-card es un <div>, .curso-card-link es el <a> real de adentro. */
.curso-card:hover { transform: translateY(-4px); border-color: rgba(var(--accent-rgb),.35); box-shadow: var(--shadow-md); }
.curso-card-link { text-decoration: none; color: inherit; display: flex; flex-direction: column; flex: 1; min-width: 0; }
.curso-thumb {
    aspect-ratio: 16 / 9; position: relative; display: flex; align-items: center; justify-content: center;
    background: var(--curso-grad, linear-gradient(135deg, var(--accent), var(--accent-2)));
}
.curso-thumb img { width: 100%; height: 100%; object-fit: cover; }
.curso-thumb .letra { font-size: 44px; font-weight: 800; color: rgba(255,255,255,.55); }
.curso-thumb .precio-pill {
    position: absolute; top: 12px; right: 12px; padding: 4px 11px; border-radius: 999px;
    font-size: 12px; font-weight: 700; background: rgba(255,255,255,.94); backdrop-filter: blur(6px);
}
.precio-pill.gratis { color: var(--accent); }
.precio-pill.pago { color: var(--accent-2); }

/* ---------- Botón circular de wishlist, arriba a la derecha de la
   miniatura — vive FUERA de .curso-card-link (ver comentario arriba). */
.curso-card-wishlist-form { position: absolute; top: 10px; right: 10px; z-index: 2; }
.curso-card-wishlist {
    width: 34px; height: 34px; border-radius: 50%; border: none; padding: 0;
    background: rgba(255,255,255,.92); backdrop-filter: blur(6px);
    display: flex; align-items: center; justify-content: center; cursor: pointer;
    color: #64748b; box-shadow: 0 2px 8px rgba(15,23,42,.18);
    transition: transform .15s var(--ease-spring, ease), color .15s ease;
}
.curso-card-wishlist:hover { transform: scale(1.1); }
.curso-card-wishlist.activo { color: #e11d48; }
.curso-card-wishlist svg { width: 17px; height: 17px; }

.curso-body { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.curso-body h3 { font-size: 16.5px; margin: 0; color: var(--tarjeta-texto, var(--text)); }
.curso-body .excerpt { color: var(--tarjeta-descripcion, var(--muted)); font-size: 13.5px; flex: 1; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.curso-meta { display: flex; align-items: center; justify-content: space-between; font-size: 12px; color: var(--tarjeta-meta, var(--muted)); margin-top: 4px; padding-top: 12px; border-top: 1px solid var(--border); }
.curso-meta .ver { color: var(--accent); font-weight: 700; }

/* ---------- Chips de categoría/etiqueta (color propio por entidad, elegido
   por el dueño al crearla) — mismo componente para las dos, reutilizado en
   tarjetas y en la presentación del curso. sa_chip_html() manda el color de
   ESA entidad puntual como custom properties inline (--chip-fondo/--chip-texto,
   ver categorias_helpers.php) en vez de background/color directos — así, si
   admin/temas.php → "Tarjetas" define un color global de etiqueta, ese var()
   (declarado más arriba en la cascada, en :root) le gana; si no se definió
   ninguno, cada chip cae de nuevo a su propio color individual. */
.taxonomia-chips-row { display: flex; flex-wrap: wrap; gap: 6px; }
.taxonomia-chip {
    display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px;
    font-size: 11px; font-weight: 700; text-decoration: none; white-space: nowrap; line-height: 1.6;
    background: var(--tarjeta-etiqueta-fondo, var(--chip-fondo, rgba(100,116,139,.14)));
    color: var(--tarjeta-etiqueta-texto, var(--chip-texto, #64748b));
}
a.taxonomia-chip { transition: filter .15s ease; }
a.taxonomia-chip:hover { filter: brightness(1.08); }

/* ---------- Fila de filtro por categoría (catálogo público) ---------- */
.categorias-filtro-row { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin: 0 0 32px; }
.categoria-filtro-pill {
    display: inline-flex; align-items: center; padding: 7px 16px; border-radius: 999px;
    border: 1px solid var(--border); background: var(--panel); color: var(--text);
    font-size: 13px; font-weight: 600; text-decoration: none;
    transition: border-color .15s ease, transform .15s ease;
}
.categoria-filtro-pill:hover { transform: translateY(-1px); border-color: rgba(var(--accent-rgb),.4); }
.categoria-filtro-pill.activa { border-color: var(--accent); background: rgba(var(--accent-rgb),.1); color: var(--accent); font-weight: 700; }

/* ---------- Checklist de etiquetas (admin/cursos/form.php) ---------- */
.etiquetas-checklist { display: flex; flex-wrap: wrap; gap: 10px; }
.etiqueta-check { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.etiqueta-check input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }

/* ---------- Selector de ícono de categoría (admin/categorias.php) — un
   <select> nativo ("celda de selección") + preview en vivo, mismo criterio
   ya usado para el selector de red social de Ajustes (un <option> no puede
   contener un SVG, así que el ícono real vive afuera, en un badge hermano
   que el JS actualiza al cambiar de opción). El badge reutiliza
   .leccion-tipo-icon (30px, ya usada para el mismo propósito en Membresías/
   Métodos de pago) en vez de una clase nueva. */
.icono-select-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.icono-select-row > * { min-width: 0; }
.icono-select-row select { flex: 1; padding: 11px 13px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 13.5px; }
.icono-select-row select:focus { outline: none; border-color: var(--accent); }
.icono-select-row p { flex: 1; }

/* ---------- Franja del profesor (avatar + nombre) al pie del cuerpo — vive
   FUERA de .curso-card-link (ver comentario en curso_card.php): el nombre
   del profesor es un link a su perfil público, y un <a> no puede anidar
   otro <a>. */
.curso-card-profesor { display: flex; align-items: center; gap: 8px; padding: 12px 20px 16px; border-top: 1px solid var(--border); }
.curso-card-profesor-link { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; text-decoration: none; color: inherit; }
.curso-card-profesor-link:hover .nombre { text-decoration: underline; }
.curso-card-profesor .avatar { width: 24px; height: 24px; border-radius: 50%; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 10.5px; font-weight: 800; flex-shrink: 0; }
.curso-card-profesor .nombre { flex: 1; font-size: 12.5px; color: var(--muted); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.curso-card-categoria-texto { flex-shrink: 0; font-size: 12px; color: var(--tarjeta-meta, var(--muted)); font-weight: 600; }

/* ---------- Botón de CTA con precio, al final de la tarjeta — hermano de
   .curso-card-link, con su propio <a> (dos links seguidos al mismo curso,
   nunca anidados). El color viene de var(--tarjeta-boton*) — admin/temas.php →
   pestaña "Tarjetas" — con fallback al acento de la zona si no se personalizó,
   así un sitio sin tocar esa pestaña se ve igual que antes. Solo la variante
   "gratis" (esta regla base); .pago sigue con el acento secundario de la zona
   a propósito, para no perder la distinción visual gratis/pago. */
.curso-card-cta {
    display: flex; align-items: center; justify-content: center; gap: 6px;
    margin: 0 20px 18px; padding: 10px 14px; border-radius: var(--radius-sm);
    color: var(--tarjeta-boton-texto, #fff); font-size: 13.5px; font-weight: 700; text-decoration: none; text-align: center;
    background: linear-gradient(135deg, var(--tarjeta-boton, var(--accent)), var(--tarjeta-boton-2, var(--accent-boton2, #22c55e)));
    transition: box-shadow .15s ease, transform .15s ease;
}
.curso-card-cta:hover { box-shadow: 0 10px 20px rgba(var(--accent-rgb),.3); transform: translateY(-1px); }
.curso-card-cta.pago { background: linear-gradient(135deg, var(--accent-2), var(--accent-boton2, #0e7490)); }
.curso-card-cta.pago:hover { box-shadow: 0 10px 20px rgba(var(--accent-2-rgb),.3); }

/* ---------- Estructuras de sitio — contenido "dividida" (filas horizontales) ---------- */
.cursos-fila { display: flex; flex-direction: column; gap: 14px; }
.curso-card-fila {
    display: flex; align-items: center; gap: 20px; background: var(--panel); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 14px; text-decoration: none; color: inherit;
    transition: border-color .18s ease, box-shadow .18s ease;
}
.curso-card-fila:hover { border-color: rgba(var(--accent-rgb),.35); box-shadow: var(--shadow-md); }
.curso-card-fila .curso-thumb { width: 160px; flex-shrink: 0; border-radius: var(--radius-sm); aspect-ratio: 16/10; }
.curso-card-fila .curso-body { padding: 0; flex: 1; min-width: 0; }
.curso-card-fila .curso-body .excerpt { -webkit-line-clamp: 1; }
.curso-card-fila .curso-meta { border-top: none; padding-top: 0; margin-top: 6px; }
@media (max-width: 620px) {
    .curso-card-fila { flex-direction: column; align-items: stretch; }
    .curso-card-fila .curso-thumb { width: 100%; }
}

/* ---------- Estructuras de sitio — contenido "minimalista" (lista compacta CON miniatura chica) ---------- */
.cursos-lista { display: flex; flex-direction: column; border-top: 1px solid var(--border); }
.curso-card-lista {
    display: flex; align-items: center; gap: 14px;
    padding: 14px 4px; text-decoration: none; color: inherit; border-bottom: 1px solid var(--border);
    transition: padding-left .15s ease;
}
.curso-card-lista:hover { padding-left: 10px; }
.curso-thumb-mini {
    width: 52px; height: 52px; flex-shrink: 0; border-radius: var(--radius-sm); overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    background: var(--curso-grad, linear-gradient(135deg, var(--accent), var(--accent-2)));
}
.curso-thumb-mini img { width: 100%; height: 100%; object-fit: cover; }
.curso-thumb-mini .letra { font-size: 18px; font-weight: 800; color: rgba(255,255,255,.65); }
.curso-card-lista .info { flex: 1; min-width: 0; }
.curso-card-lista .info h3 { font-size: 15.5px; margin: 0 0 4px; color: var(--text); font-weight: 700; }
.curso-card-lista .info .curso-meta-lista { font-size: 12px; color: var(--tarjeta-meta, var(--muted)); }
.curso-card-lista .precio-lista { font-size: 13px; font-weight: 700; color: var(--accent); white-space: nowrap; flex-shrink: 0; }
.curso-card-lista .precio-lista.pago { color: var(--accent-2); }

/* ---------- Estructuras de sitio — contenido "destacada" (slider de 3
   columnas con flechas) — scroll-snap nativo, sin librería. Ver
   initCursosSlider() en site.js (solo mueve el scroll; el navegador hace el
   snap). ---------- */
.cursos-slider-wrap { display: flex; align-items: center; gap: 12px; }
.cursos-slider {
    display: flex; gap: 22px; flex: 1; min-width: 0; overflow-x: auto;
    scroll-snap-type: x mandatory; scroll-behavior: smooth; padding-bottom: 4px;
    scrollbar-width: none;
}
.cursos-slider::-webkit-scrollbar { display: none; }
.cursos-slider .curso-card { flex: 0 0 calc((100% - 44px) / 3); scroll-snap-align: start; min-width: 0; }
.slider-flecha {
    flex-shrink: 0; width: 42px; height: 42px; border-radius: 50%; border: 1px solid var(--border);
    background: var(--panel); color: var(--text); display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: border-color .15s ease, opacity .15s ease;
}
.slider-flecha:hover { border-color: rgba(var(--accent-rgb),.4); }
.slider-flecha:disabled { opacity: .35; cursor: default; }
@media (max-width: 900px) { .cursos-slider .curso-card { flex-basis: calc((100% - 22px) / 2); } }
@media (max-width: 620px) {
    .cursos-slider .curso-card { flex-basis: 82%; }
    .slider-flecha { width: 36px; height: 36px; }
}

/* ---------- Estructuras de sitio — contenido "compacta" (grilla más densa,
   misma tarjeta .curso-card, solo cambia el tamaño de columna) ---------- */
.cursos-grid-compacta { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 16px; }

/* ---------- Estructuras de sitio — contenido "editorial" (lista numerada +
   barra de estadísticas en el hero, ver .hero-stats-bar más abajo) ---------- */
.cursos-numerada { display: flex; flex-direction: column; }
.curso-numerada-fila {
    display: flex; align-items: center; gap: 18px; padding: 18px 4px;
    text-decoration: none; color: inherit; border-bottom: 1px solid var(--border);
    transition: padding-left .15s ease;
}
.curso-numerada-fila:first-child { border-top: 1px solid var(--border); }
.curso-numerada-fila:hover { padding-left: 8px; }
.curso-numerada-numero { font-size: 26px; font-weight: 800; color: rgba(var(--accent-rgb),.3); flex-shrink: 0; width: 46px; }
.curso-numerada-thumb {
    width: 84px; height: 84px; border-radius: var(--radius-sm); overflow: hidden; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: var(--curso-grad, linear-gradient(135deg, var(--accent), var(--accent-2)));
}
.curso-numerada-thumb img { width: 100%; height: 100%; object-fit: cover; }
.curso-numerada-thumb .letra { font-size: 24px; font-weight: 800; color: rgba(255,255,255,.6); }
.curso-numerada-info { flex: 1; min-width: 0; }
.curso-numerada-info h3 { font-size: 16px; margin: 0 0 4px; color: var(--text); }
.curso-numerada-info .excerpt { color: var(--muted); font-size: 13px; margin: 4px 0; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.curso-numerada-info .curso-meta { font-size: 12px; color: var(--tarjeta-meta, var(--muted)); border: none; padding: 0; margin: 0; }
.curso-numerada-precio { flex-shrink: 0; font-size: 14px; font-weight: 700; color: var(--accent); white-space: nowrap; }
.curso-numerada-precio.pago { color: var(--accent-2); }
@media (max-width: 620px) {
    .curso-numerada-fila { flex-wrap: wrap; gap: 10px 14px; }
    .curso-numerada-numero { width: auto; font-size: 20px; }
    .curso-numerada-precio { margin-left: auto; }
}

.empty-state { text-align: center; padding: 60px 20px; color: var(--muted); background: var(--panel-2); border: 1px dashed var(--border); border-radius: var(--radius); }

/* ---------- Features / valores ---------- */
.features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; }
.feature-card { background: var(--tarjeta-fondo, var(--panel)); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; box-shadow: var(--shadow-sm); }
.feature-card .ico {
    width: 40px; height: 40px; border-radius: 11px; display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, rgba(var(--accent-rgb),.14), rgba(var(--accent-2-rgb),.10)); margin-bottom: 14px;
}
.feature-card .ico svg { width: 20px; height: 20px; color: var(--tarjeta-icono, var(--accent)); }
.feature-card h3 { font-size: 15px; margin: 0 0 6px; color: var(--tarjeta-texto, var(--text)); }
.feature-card p { color: var(--tarjeta-descripcion, var(--muted)); font-size: 13.5px; }

/* ---------- "Quiénes somos" (inicio.php, nueva) — 2 columnas: imagen +
   texto. Sin imagen (campo opcional), el texto queda solo, a todo el ancho
   pero con el mismo max-width legible que el resto del sitio. ---------- */
.quienesomos-grid { display: grid; grid-template-columns: 1fr 1.2fr; gap: 48px; align-items: center; }
.quienesomos-grid.sin-imagen { grid-template-columns: 1fr; max-width: 720px; margin: 0 auto; text-align: center; }
.quienesomos-imagen-wrap { border-radius: var(--radius); overflow: hidden; aspect-ratio: 4/3; box-shadow: var(--shadow-md); }
.quienesomos-imagen-wrap img { width: 100%; height: 100%; object-fit: cover; display: block; }
.quienesomos-texto .eyebrow { margin-bottom: 16px; }
.quienesomos-texto p { color: var(--text); font-size: 16px; line-height: 1.7; white-space: pre-line; }
@media (max-width: 780px) {
    .quienesomos-grid { grid-template-columns: 1fr; gap: 24px; }
    .quienesomos-imagen-wrap { max-width: 420px; margin: 0 auto; }
}

/* ---------- "Explora por categoría" (inicio.php, nueva) — grilla de íconos
   con el color propio de cada categoría (ver sa_categoria_icono_svg()). ---------- */
.categorias-iconos-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 16px; }
.categoria-icono-card {
    display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center;
    padding: 26px 14px; background: var(--tarjeta-fondo, var(--panel)); border: 1px solid var(--border); border-radius: var(--radius);
    text-decoration: none; color: var(--tarjeta-texto, var(--text)); transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.categoria-icono-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: rgba(var(--accent-rgb),.35); }
/* Mismo mecanismo que .taxonomia-chip (ver comentario arriba): --chip-fondo/
   --chip-texto los manda inicio.php inline con el color propio de ESA
   categoría; el override global de "Tarjetas" (si está definido) le gana. */
.categoria-icono-badge {
    width: 52px; height: 52px; border-radius: 16px; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    background: var(--tarjeta-etiqueta-fondo, var(--chip-fondo, rgba(100,116,139,.14)));
    color: var(--tarjeta-etiqueta-texto, var(--chip-texto, #64748b));
}
.categoria-icono-badge svg { width: 24px; height: 24px; }
.categoria-icono-card .nombre { font-size: 13.5px; font-weight: 700; }

/* ---------- Preguntas frecuentes (inicio.php, nueva) — HTML de confianza
   (mismo criterio que paginas_fijas.contenido), <details> nativos estilo
   acordeón, igual patrón que la homepage de marketing de SimpleAula. ---------- */
.faq-contenido { max-width: 760px; margin: 0 auto; display: flex; flex-direction: column; gap: 10px; }
.faq-contenido details {
    background: var(--tarjeta-fondo, var(--panel)); border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: 16px 20px;
}
.faq-contenido summary { cursor: pointer; font-weight: 700; font-size: 14.5px; color: var(--tarjeta-texto, var(--text)); list-style: none; }
.faq-contenido summary::-webkit-details-marker { display: none; }
.faq-contenido summary::before { content: '+'; display: inline-block; width: 18px; color: var(--tarjeta-icono, var(--accent)); font-weight: 800; }
.faq-contenido details[open] summary::before { content: '−'; }
.faq-contenido details p { margin: 10px 0 0 18px; color: var(--tarjeta-descripcion, var(--muted)); font-size: 13.5px; line-height: 1.6; }

/* ---------- CTA final ---------- */
.cta-panel {
    text-align: center; padding: 60px 32px; border-radius: 24px;
    background: radial-gradient(circle at 50% 0%, rgba(var(--accent-rgb),.10), transparent 60%), var(--panel-2);
    border: 1px solid var(--border);
}
.cta-panel h2 { font-size: 26px; margin: 0 0 12px; color: var(--text); }
.cta-panel p { color: var(--muted); margin: 0 0 26px; }

/* ---------- Página de curso (detalle) ---------- */
.back-link { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); text-decoration: none; font-size: 13.5px; font-weight: 600; }
.back-link:hover { color: var(--text); }

.breadcrumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); margin-bottom: 18px; }
.breadcrumbs a { color: var(--muted); text-decoration: none; }
.breadcrumbs a:hover { color: var(--accent); text-decoration: underline; }
.breadcrumbs .sep { color: var(--border); }
.breadcrumbs .actual { color: var(--text); font-weight: 600; }

.content-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px 26px; box-shadow: var(--shadow-sm); }

.pill { display: inline-flex; align-items: center; padding: 5px 13px; border-radius: 999px; font-size: 13px; font-weight: 700; white-space: nowrap; }
.pill-gratis { background: rgba(var(--accent-rgb),.1); color: var(--accent); }
.pill-pago { background: rgba(var(--accent-2-rgb),.1); color: var(--accent-2); }
.curso-desc { color: var(--text); line-height: 1.7; margin: 0; }

.modulos-list { display: flex; flex-direction: column; gap: 12px; }
.modulo-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 16px 20px; box-shadow: var(--shadow-sm); }
.modulo-card h3 { font-size: 14.5px; margin: 0 0 4px; color: var(--text); }
.modulo-card ul { margin: 0; padding: 0; list-style: none; }
.modulo-card li { padding: 9px 0; border-top: 1px solid var(--border); color: var(--muted); font-size: 13.5px; }
.modulo-card li:first-child { border-top: none; }

.aviso-cta { color: var(--muted); font-size: 13px; margin-top: 14px; }
.aviso-cta a { color: var(--accent); font-weight: 600; text-decoration: none; }
.aviso-cta a:hover { text-decoration: underline; }

/* ══════════════════════════════════════════════════════════════════════
   Detalle de curso estilo TutorLMS — hero + layout de 2 columnas con
   sidebar sticky (precio/CTA/"este curso incluye") + currículum en
   acordeón. Ver core-app/src/pages/curso.php.
   ══════════════════════════════════════════════════════════════════════ */
.curso-tutor-hero { margin: 20px 0 24px; }
.curso-tutor-hero h1 { font-size: 30px; margin: 0 0 10px; color: var(--text); }
.curso-tutor-meta-row { display: flex; flex-wrap: wrap; gap: 6px 18px; color: var(--muted); font-size: 14px; }

.curso-tutor-grid { display: grid; grid-template-columns: 1fr 360px; gap: 28px; align-items: start; }
.curso-tutor-main { min-width: 0; }
.curso-tutor-section { margin-bottom: 20px; }
.curso-tutor-hero-img { display: block; width: 100%; aspect-ratio: 16/9; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--border); margin-bottom: 20px; }
.curso-tutor-hero-media.video-wrap { margin-bottom: 20px; }
.curso-tutor-section h2 { font-size: 19px; margin: 0 0 14px; color: var(--text); }

.aprenderas-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px 20px; }
.aprenderas-item { display: flex; align-items: flex-start; gap: 10px; font-size: 14px; color: var(--text); line-height: 1.5; }
.aprenderas-item svg { flex-shrink: 0; color: var(--accent); margin-top: 2px; }

.curriculum-resumen { color: var(--muted); font-size: 13.5px; margin: -6px 0 14px; }
.curriculum-acordeon { display: flex; flex-direction: column; gap: 10px; }
.curriculum-modulo { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.curriculum-modulo-head {
    display: flex; align-items: center; gap: 10px; width: 100%; padding: 14px 16px;
    background: var(--panel-2); border: none; cursor: pointer; text-align: left; font: inherit;
}
.curriculum-modulo-head .chevron { flex-shrink: 0; color: var(--muted); transition: transform .15s ease; }
.curriculum-modulo.expandido .curriculum-modulo-head .chevron { transform: rotate(180deg); }
.curriculum-modulo-titulo { flex: 1; min-width: 0; font-weight: 700; font-size: 14.5px; color: var(--text); }
.curriculum-modulo-conteo { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.curriculum-lecciones { display: none; }
.curriculum-modulo.expandido .curriculum-lecciones { display: block; }
.curriculum-leccion { display: flex; align-items: center; gap: 10px; padding: 11px 16px; border-top: 1px solid var(--border); font-size: 13.5px; color: var(--muted); }
.curriculum-leccion svg:first-child { flex-shrink: 0; }
.curriculum-leccion span { flex: 1; min-width: 0; }
.curriculum-leccion .candado { flex-shrink: 0; color: var(--muted); opacity: .7; }

.simple-list { margin: 0; padding: 0; list-style: none; }
.simple-list li { position: relative; padding: 7px 0 7px 22px; color: var(--text); font-size: 14px; line-height: 1.5; }
.simple-list li::before { content: '—'; position: absolute; left: 0; color: var(--accent); font-weight: 700; }

.instructor-card { display: flex; align-items: center; gap: 14px; text-decoration: none; transition: border-color .15s ease, box-shadow .15s ease; }
.instructor-card:hover { border-color: rgba(var(--accent-rgb),.35); box-shadow: var(--shadow-md); }
.instructor-avatar { width: 52px; height: 52px; border-radius: 50%; background: var(--curso-grad); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 700; flex-shrink: 0; }
.instructor-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; font-weight: 700; }
.instructor-nombre { font-size: 16px; font-weight: 700; color: var(--text); }

.curso-tutor-sidebar { position: sticky; top: 90px; }
.curso-tutor-sidebar-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.curso-tutor-media { display: block; width: 100%; aspect-ratio: 16/9; object-fit: cover; margin: 0; border-radius: 0; }
.curso-tutor-sidebar-body { padding: 22px; }
.curso-tutor-precio { margin-bottom: 16px; }
.curso-tutor-precio .pill { font-size: 20px; padding: 6px 16px; }
.curso-tutor-incluye { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--border); }
.curso-tutor-incluye h4 { font-size: 13px; margin: 0 0 12px; color: var(--text); }
.curso-tutor-incluye ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.curso-tutor-incluye li { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--muted); }
.curso-tutor-incluye li svg { flex-shrink: 0; color: var(--accent); }

.curso-tutor-taxonomia-card { margin-top: 18px; padding: 18px 22px; }
.taxonomia-grupo + .taxonomia-grupo { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
.taxonomia-grupo h4 { font-size: 13px; margin: 0 0 10px; color: var(--text); }

@media (max-width: 960px) {
    .curso-tutor-grid { grid-template-columns: 1fr; }
    .curso-tutor-sidebar { position: static; order: -1; }
}

/* ---------- Footer ---------- */
.site-footer { border-top: 1px solid var(--border); padding: 34px 0; margin-top: 0px; }
.site-footer .bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; font-size: 13px; color: var(--muted); }
.site-footer a { color: var(--muted); text-decoration: none; }
.site-footer a:hover { color: var(--text); }
.site-footer .credit { color: #94a3b8; }

/* ---------- Redes sociales del footer (admin/ajustes.php → Generales) ---------- */
.footer-social { display: inline-flex; align-items: center; gap: 10px; }
.footer-social-link {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--border);
    color: var(--muted); flex-shrink: 0; transition: color .15s ease, border-color .15s ease;
}
.footer-social-link:hover { color: var(--accent); border-color: var(--accent); }
.footer-social-link svg { width: 15px; height: 15px; }
/* .site-footer-dividida-col a fuerza display:block/margin-bottom a CUALQUIER <a>
   descendiente (para los links de texto apilados) — los íconos sociales necesitan
   quedar en fila, no apilados, así que se sobreescribe puntualmente acá. */
.site-footer-dividida-col .footer-social a { display: inline-flex; margin-bottom: 0; }

/* ---------- Estructuras de sitio — footer "dividida" (3 columnas) ---------- */
.site-footer-dividida { padding: 48px 0 24px; }
.site-footer-dividida-grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr 1fr; gap: 32px; padding-bottom: 30px; }
.site-footer-dividida-col h4 { font-size: 13px; margin: 0 0 14px; color: var(--text); text-transform: uppercase; letter-spacing: .04em; }
.site-footer-dividida-col p { color: var(--muted); font-size: 13.5px; line-height: 1.6; margin: 0; }
.site-footer-dividida-col a { display: block; color: var(--muted); text-decoration: none; font-size: 13.5px; margin-bottom: 9px; }
.site-footer-dividida-col a:hover { color: var(--text); }
.site-footer-dividida-bottom { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding-top: 22px; border-top: 1px solid var(--border); font-size: 12.5px; color: var(--muted); }
@media (max-width: 720px) {
    .site-footer-dividida-grid { grid-template-columns: 1fr; gap: 24px; }
}

/* ---------- Estructuras de sitio — footer "minimalista" (una sola línea centrada) ---------- */
.site-footer-minimalista { padding: 26px 0; }
.site-footer-minimalista .bar { justify-content: center; text-align: center; flex-direction: column; gap: 6px; font-size: 12.5px; }

/* ---------- Estructuras de sitio — footer "destacada" (franja de CTA arriba +
   la misma línea de "clásica" debajo) ---------- */
/* Sin "tiene-cta-band" (alumno con sesión: no se muestra la franja) el footer
   conserva el border-top/padding-top de siempre, para no perder la separación
   visual con el contenido de arriba. */
.site-footer-destacada.tiene-cta-band { border-top: none; padding-top: 0; }
.footer-cta-band { background: linear-gradient(135deg, rgba(var(--accent-rgb),.12), rgba(var(--accent-2-rgb),.08)); border-bottom: 1px solid var(--border); padding: 26px 0; margin-bottom: 24px; }
.footer-cta-band-inner { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.footer-cta-band-inner strong { display: block; font-size: 15.5px; color: var(--text); margin-bottom: 3px; }
.footer-cta-band-inner p { margin: 0; color: var(--muted); font-size: 13.5px; }

/* ---------- Estructuras de sitio — footer "compacta" (2 columnas asimétricas) ---------- */
.site-footer-compacta-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 40px; padding: 4px 0 24px; }
.site-footer-compacta-brand h4 { font-size: 15px; margin: 0 0 8px; color: var(--text); }
.site-footer-compacta-brand p { color: var(--muted); font-size: 13.5px; line-height: 1.6; margin: 0 0 14px; max-width: 380px; }
.site-footer-compacta-links { display: flex; flex-direction: column; gap: 10px; }
.site-footer-compacta-links a { color: var(--muted); text-decoration: none; font-size: 13.5px; }
.site-footer-compacta-links a:hover { color: var(--text); }
.site-footer-compacta-bottom { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding-top: 20px; border-top: 1px solid var(--border); font-size: 12.5px; color: var(--muted); }
@media (max-width: 720px) {
    .site-footer-compacta-grid { grid-template-columns: 1fr; gap: 24px; }
}

/* ---------- Estructuras de sitio — footer "editorial" (todo centrado, apilado
   vertical, estilo "linktree") ---------- */
.site-footer-editorial-inner { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 40px 0; text-align: center; font-size: 13px; color: var(--muted); }
.site-footer-editorial-nombre { font-size: 15.5px; color: var(--text); }
.site-footer-editorial-nav { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; }
.site-footer-editorial-nav a { color: var(--muted); text-decoration: none; font-size: 13.5px; }
.site-footer-editorial-nav a:hover { color: var(--text); }
.site-footer-editorial-nav .dot-sep { color: var(--border); }

/* ---------- Formularios ---------- */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 6px; font-weight: 600; }
.field input[type=text], .field input[type=email], .field input[type=password], .field input[type=number], .field input[type=tel], .field input[type=datetime-local], .field input[type=file], .field select {
    width: 100%; padding: 11px 13px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 14px;
    transition: border-color .15s ease;
}
.field input[type=file] { padding: 8px 10px; }
.field input:focus, .field select:focus { outline: none; border-color: var(--accent); }
/* Sin esto, el ícono nativo de calendario/reloj queda oscuro sobre fondo
   oscuro (casi invisible) — el navegador solo lo ajusta si se le avisa. */
.admin-shell[data-theme="dark"] .field input[type=datetime-local] { color-scheme: dark; }
.field textarea {
    width: 100%; min-height: 100px; resize: vertical; padding: 11px 13px;
    background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm);
    color: var(--text); font-size: 14px; font-family: inherit;
}
.field textarea:focus { outline: none; border-color: var(--accent); }

/* ---------- Grilla de campos responsiva (formularios anchos: curso, etc.) ---------- */
.field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; }
.field-grid > * { min-width: 0; } /* si no, un <input type=number> puede negarse a encogerse y desborda la columna */
.field-grid-tight { grid-template-columns: 1fr 110px; }
@media (max-width: 480px) { .field-grid-tight { grid-template-columns: 1fr; } }
/* Exactamente 2 columnas fijas (no auto-fit) — Datos personales de Ajustes,
   donde 5 campos en auto-fit terminaban en una sola fila apretada en
   pantallas anchas. */
.field-grid-2col { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 640px) { .field-grid-2col { grid-template-columns: 1fr; } }

/* Fila de 2 inputs lado a lado (campo/valor de un método de pago) — mismo motivo que
   .field-grid > *: sin min-width:0 un <input> se niega a encogerse y desborda en móvil. */
.campo-datos-row { display: flex; gap: 10px; }
.campo-datos-row > * { min-width: 0; } /* mismo motivo que .field-grid > * — sin esto un input/select se niega a encogerse y desborda */
@media (max-width: 480px) { .campo-datos-row { flex-direction: column; gap: 6px; } }
/* Excepción puntual: la fila bandera+teléfono debe seguir en una sola
   línea aun en mobile (la bandera es angosta y fija, nunca necesitó
   apilarse como sí lo necesitan 2 inputs de texto completos). Doble clase
   para ganarle en especificidad a la regla de apilado de arriba. */
.campo-datos-row.campo-datos-row-telefono { flex-direction: row; gap: 8px; }
.campo-datos-row .field-icon-wrap { flex: 1; }
.campo-datos-row select { flex-shrink: 0; width: auto; padding: 11px 30px 11px 13px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 13.5px; }

/* Selector de código de país — picker propio, NO un <select> nativo: un
   <option> solo puede tener texto, y el pedido explícito fue "solo
   banderas, no números" tanto en el trigger cerrado como en la lista al
   buscar — ningún <select> nativo puede mostrar un SVG por fila. El
   trigger es un <button> (sin caja de texto, solo la bandera) que abre
   .campo-pais-lista (un panel propio posicionado absoluto, con
   bandera + NOMBRE del país por fila, nunca el código numérico). El
   valor real viaja en un <input type=hidden> sincronizado por JS
   (elegirPais(), en _mi_cuenta_perfil.php). */
.campo-pais-picker { position: relative; align-self: stretch; }
.campo-pais-bandera-wrap {
    display: flex; align-items: center; justify-content: center;
    width: 46px; height: 100%; padding: 0; border-radius: var(--radius-sm);
    background: var(--panel); border: 1px solid var(--border); cursor: pointer; transition: border-color .15s ease;
}
.campo-pais-bandera-wrap:hover, .campo-pais-bandera-wrap[aria-expanded="true"] { border-color: var(--accent); }
.campo-pais-bandera { width: 24px; height: 17px; border-radius: 3px; overflow: hidden; box-shadow: 0 0 0 1px rgba(15,23,42,.12); display: flex; flex-shrink: 0; }
.campo-pais-bandera svg { width: 100%; height: 100%; display: block; }

.campo-pais-lista {
    position: absolute; top: calc(100% + 6px); left: 0; z-index: 20; width: 230px; max-height: 280px; overflow-y: auto;
    background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 6px;
}
.campo-pais-lista.hidden { display: none; }
.campo-pais-opcion {
    display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; border-radius: var(--radius-sm);
    background: none; border: none; text-align: left; cursor: pointer; font-size: 13.5px; color: var(--text);
}
.campo-pais-opcion:hover { background: var(--panel-2); }
.campo-pais-opcion.seleccionada { background: rgba(var(--accent-rgb),.1); color: var(--accent); font-weight: 700; }
.campo-pais-opcion-bandera { width: 22px; height: 15px; border-radius: 3px; overflow: hidden; box-shadow: 0 0 0 1px rgba(15,23,42,.12); flex-shrink: 0; display: flex; }
.campo-pais-opcion-bandera svg { width: 100%; height: 100%; display: block; }
.campo-pais-opcion-texto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 480px) { .campo-pais-lista { width: 200px; } }

/* ══════════════════════════════════════════════════════════════════════
   Editor de contenido "estilo LMS" — formularios de curso/módulo/lección.
   Layout de dos columnas (formulario + preview en vivo sticky) con
   secciones tipo tarjeta, dropzone de archivos y controles segmentados
   en vez de <select> nativos, para sentirse como un editor de curso
   moderno (Teachable/Thinkific/Kajabi) en vez de un formulario CRUD plano.
   ══════════════════════════════════════════════════════════════════════ */
.editor-layout { display: grid; grid-template-columns: 1.7fr 1fr; gap: 24px; align-items: start; }
@media (max-width: 960px) { .editor-layout { grid-template-columns: 1fr; } }
/* Regla general, mismo patrón ya aplicado antes en .field-grid: un ítem de
   grid tiene min-width:auto implícito — si algo adentro (ej. una descripción
   larga en .form-section-head, ver admin/temas.php → "Explora por
   categoría"/"Preguntas frecuentes") no puede encogerse por debajo de su
   ancho de contenido, empuja toda la columna más ancha que su 1.7fr/1fr real,
   y en mobile (1 columna) directamente más ancha que el propio viewport —
   el min-width:0 en .form-section-head ya no alcanzaba si el problema
   arrancaba un nivel más arriba, en el propio ítem de grid. */
.editor-layout > * { min-width: 0; }

/* admin/temas.php: el botón "Guardar" es un 3er hijo directo de .editor-layout
   (hermano del formulario y de .preview-sidebar, no anidado adentro del
   primero) — en escritorio queda pegado debajo de la columna del formulario
   (grid-column:1, cae solo en la fila siguiente por el auto-placement de
   grid). En mobile (1 columna) se reordena para quedar DESPUÉS del preview —
   pedido explícito del usuario, mismo mecanismo `order` ya usado para
   .pass-editor-layout más abajo. En una sola columna cada ítem ocupa su
   propia fila (a diferencia de escritorio con 2 columnas), así que acá
   `order` no arrastra ningún problema de altura compartida entre columnas. */
.temas-guardar-fila { grid-column: 1; margin-top: 4px; }
/* El botón (.btn-block-mobile) llena el 100% de ESTE contenedor — en mobile
   se le da padding propio para que quede con aire respecto de los bordes de
   la pantalla, en vez de tocarlos directo (pedido explícito del usuario:
   "necesita un margen mucho más amplio"). */
@media (max-width: 640px) { .temas-guardar-fila { padding: 0 14px; } }
@media (max-width: 960px) {
    .editor-layout > div:first-child { order: 0; }
    .editor-layout > .preview-sidebar { order: 1; }
    .editor-layout > .temas-guardar-fila { order: 2; }
}

/* Ajustes → Contraseña: en mobile (apilado a 1 columna) los "Consejos de
   seguridad" deben leerse ANTES que el formulario de cambio — pero en
   escritorio .preview-sidebar sigue angosta a la derecha como en el resto
   del proyecto (cursos/form.php, admin/temas.php, certificado.php...), así
   que el reorden se limita a esta clase puntual y al mismo breakpoint
   donde .editor-layout ya colapsa a 1 columna: fuera de ese ancho, `order`
   en un grid con 2 columnas reales movería la tarjeta angosta a la columna
   ancha (invertiría las proporciones 1.7fr/1fr), efecto no buscado.
   `position:sticky` (heredado de .preview-sidebar, pensado para quedar
   pegada al lado de una columna más alta en escritorio) queda sin sentido
   apilada arriba de todo en mobile — sin desactivarla, "Consejos" quedaba
   fija tapando el inicio del formulario al hacer scroll, exactamente lo
   que reportó el usuario ("los consejos se mantienen y las celdas se
   cortan"). Se fuerza position:static solo acá. */
@media (max-width: 960px) {
    .pass-editor-layout .preview-sidebar { order: -1; position: static; top: auto; }
}

.form-section { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px 26px; box-shadow: var(--shadow-sm); margin-bottom: 20px; }
.form-section-head { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.form-section-head .ico {
    width: 36px; height: 36px; border-radius: 10px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, rgba(var(--accent-rgb),.14), rgba(var(--accent-2-rgb),.10)); color: var(--accent);
}
.form-section-head .ico svg { width: 18px; height: 18px; }
.form-section-head h3 { font-size: 15px; margin: 0; color: var(--text); }
/* overflow-wrap: aunque el contenedor pueda encogerse (ver .form-section-head
   > div:last-child y .editor-layout > * más arriba), eso no alcanza si el
   texto tiene un solo "token" sin espacios más ancho que el espacio
   disponible (ej. una etiqueta de código larga) — sin espacios el navegador
   no tiene dónde cortar la línea por default y el texto se sale igual. */
.form-section-head p { font-size: 12.5px; color: var(--muted); margin: 2px 0 0; overflow-wrap: break-word; }

/* admin/temas.php → "Preguntas frecuentes": 4 pares Pregunta/Respuesta fijos
   (no un CRUD abierto), separados por una línea fina para no confundirse
   entre sí dentro de la misma tarjeta. */
.faq-admin-item { padding-top: 16px; margin-top: 16px; border-top: 1px solid var(--border); }
.faq-admin-item:first-of-type { padding-top: 0; margin-top: 0; border-top: none; }
/* El bloque de título+descripción (segundo hijo, sin clase propia) es un ítem
   flex sin flex-basis explícito — por default tiene min-width:auto, que con una
   descripción larga (ver "Explora por categoría"/"Preguntas frecuentes" en
   admin/temas.php) lo empuja más ancho que el espacio disponible en vez de
   ajustarse y hacer wrap del texto, desbordando la tarjeta entera en mobile
   (mismo patrón de bug ya documentado varias veces en este archivo). */
.form-section-head > div:last-child { flex: 1; min-width: 0; }

/* ---------- Dropzone de archivos (portada, recursos) ---------- */
.dropzone {
    display: block; /* <label> es inline por default — sin esto, max-width/margin:auto no tienen efecto */
    position: relative; border: 2px dashed var(--border); border-radius: var(--radius); overflow: hidden;
    padding: 26px 20px; text-align: center; cursor: pointer; background: var(--panel-2);
    transition: border-color .15s ease, background .15s ease;
    max-width: 460px; margin: 0 auto;
}
.dropzone:hover, .dropzone.dragover { border-color: var(--accent); background: rgba(var(--accent-rgb),.05); }
/* input[type=file] tiene un bug/quirk real en Chromium: ni inset:0 ni width:100% lo estiran
   a ocupar el contenedor (queda como una tira angosta de ~18px pegada al borde izquierdo,
   con su tooltip nativo "Sin archivos seleccionados" asomando — el bug reportado). En vez de
   pelear con ese ancho intrínseco, se lo oculta de verdad (1×1px, clip) — el click igual
   funciona porque el <label> que lo envuelve reenvía el evento de forma nativa, y arrastrar
   un archivo funciona porque los listeners drag/drop están en .dropzone, no en el input. */
.dropzone input[type=file] { position: absolute; top: 0; left: 0; width: 1px; height: 1px; margin: 0; padding: 0; opacity: 0; overflow: hidden; clip: rect(0,0,0,0); cursor: pointer; }
.dropzone .ico { width: 34px; height: 34px; margin: 0 auto 10px; color: var(--muted); }
.dropzone .txt-main { font-size: 13.5px; font-weight: 700; color: var(--text); }
.dropzone .txt-main span { color: var(--accent); }
.dropzone .txt-sub { font-size: 12px; color: var(--muted); margin-top: 3px; }
.dropzone .preview-img { display: block; max-width: 100%; max-height: 170px; margin: 0 auto 12px; border-radius: var(--radius-sm); object-fit: cover; }

/* Variante compacta para una firma (imagen ancha y baja, no un cuadrado) —
   usada en la pestaña Perfil de Ajustes. */
.dropzone-firma { max-width: none; margin: 0; padding: 18px 20px; }
.dropzone-firma .preview-img { max-height: 84px; border-bottom: 2px solid var(--border); border-radius: 0; padding-bottom: 10px; }
.dropzone-firma .ico { width: 26px; height: 26px; margin-bottom: 6px; }

/* ---------- Firma de certificado: dropzone a la izquierda + demostración
   de ejemplo a la derecha (pedido explícito para que se entienda cómo
   subirla) ---------- */
.firma-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: stretch; }
@media (max-width: 720px) { .firma-layout { grid-template-columns: 1fr; } }
/* Los 2 hijos directos del grid (el .field de la izquierda y .firma-demo)
   ya se estiran al alto de la fila por align-items:stretch, pero eso solo
   fija la altura de la CAJA — hay que propagar esa altura hacia adentro
   (.dropzone-wrap → .dropzone-firma) para que el recuadro punteado
   realmente iguale el alto de la tarjeta de ejemplo, no solo su propio
   contenido. */
.firma-layout > .field { display: flex; flex-direction: column; height: 100%; }
.firma-layout .dropzone-wrap { flex: 1; display: flex; }
.firma-layout .dropzone-firma { flex: 1; display: flex; flex-direction: column; justify-content: center; }
.firma-demo { height: 100%; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 10px; }
.firma-demo-etiqueta { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.firma-demo-firma { width: 100%; max-width: 220px; }
.firma-demo-firma svg { width: 100%; height: 56px; color: var(--accent); }
.firma-demo-linea { width: 100%; max-width: 220px; border-top: 2px solid var(--text); margin-top: -4px; }
.firma-demo-nombre { font-size: 12.5px; font-weight: 700; color: var(--text); margin-top: 4px; }
.firma-demo-caption { font-size: 12px; color: var(--muted); max-width: 240px; line-height: 1.5; margin-top: 6px; }

/* ---------- Encabezado de perfil estilo Facebook (portada + avatar
   superpuesto) — pestaña Perfil de Ajustes (panel/mi_cuenta.php). El botón
   de subida y el de "quitar" son elementos HERMANOS, nunca anidados dentro
   del mismo <label> que el input — el click de un <button> dentro de un
   <label> con dos controles labelables es ambiguo (mismo bug ya
   documentado y corregido antes en .dropzone-wrap). */
.perfil-header-fb { position: relative; margin-bottom: 25px; }
.perfil-portada-banner {
    position: relative; width: 100%; aspect-ratio: 2.1 / 1; max-height: 300px; border-radius: var(--radius); overflow: hidden;
    background: linear-gradient(135deg, rgba(var(--accent-rgb),.16), rgba(var(--accent-2-rgb),.10));
    border: 1px solid var(--border);
}
.perfil-portada-banner .preview-img-full { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* .arrastrable solo la lleva la portada EDITABLE (panel/_mi_cuenta_perfil.php)
   — el perfil público (profesor_publico.php) reutiliza el mismo componente
   en modo solo-lectura y no debe insinuar con el cursor que se puede
   arrastrar algo ahí, donde no hay ningún JS de reposición enganchado. */
.perfil-portada-banner .preview-img-full.arrastrable { cursor: grab; user-select: none; -webkit-user-drag: none; }
.perfil-portada-banner.arrastrando .preview-img-full.arrastrable { cursor: grabbing; }
.perfil-portada-vacia { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; color: var(--muted); font-size: 12.5px; font-weight: 600; }
.perfil-portada-vacia svg { width: 26px; height: 26px; }
/* Pista de "se puede arrastrar" — visible siempre que hay foto de portada,
   se atenúa mientras se arrastra para no tapar la vista previa del encuadre. */
.perfil-portada-hint {
    position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 1;
    display: flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px;
    background: rgba(15,23,42,.55); backdrop-filter: blur(4px); color: #fff; font-size: 11.5px; font-weight: 600;
    white-space: nowrap; pointer-events: none; transition: opacity .15s ease;
}
.perfil-portada-hint svg { width: 13px; height: 13px; flex-shrink: 0; }
.perfil-portada-banner.arrastrando .perfil-portada-hint { opacity: .35; }
.perfil-portada-actions { position: absolute; top: 12px; right: 12px; display: flex; gap: 8px; z-index: 2; }
.perfil-portada-btn {
    display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px; border-radius: 999px;
    background: rgba(15,23,42,.55); backdrop-filter: blur(4px); color: #fff; font-size: 12.5px; font-weight: 700;
    border: none; cursor: pointer; white-space: nowrap;
}
.perfil-portada-btn:hover { background: rgba(15,23,42,.72); }
.perfil-portada-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
.perfil-portada-btn input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; clip: rect(0,0,0,0); }
.perfil-portada-quitar {
    display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%;
    background: rgba(15,23,42,.55); backdrop-filter: blur(4px); color: #fff; border: none; cursor: pointer; flex-shrink: 0;
}
.perfil-portada-quitar:hover { background: var(--danger); }
.perfil-portada-quitar svg { width: 15px; height: 15px; }

/* .perfil-avatar-wrap es el elemento posicionado (left/bottom, superpuesto
   a la banner) — .perfil-avatar-overlap adentro SOLO recorta la foto/letra
   a un círculo. Los botones (editar/quitar) son HERMANOS de esa parte
   recortada, no hijos: si vivieran dentro del círculo con overflow:hidden,
   quedarían cortados por la propia curva del círculo apenas se acercan a
   una esquina (el área de una esquina del cuadrado que los contiene cae
   AFUERA del círculo inscripto) — bug real ya visto una vez con la
   portada/avatar, mismo patrón acá con el botón de cámara. */
.perfil-avatar-wrap { position: absolute; left: 50px; bottom: -44px; width: 200px; height: 200px; }
.perfil-avatar-overlap {
    position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%;
    border: 5px solid var(--panel); background: linear-gradient(135deg, var(--accent), var(--accent-2));
    overflow: hidden; box-shadow: var(--shadow-md);
}
.perfil-avatar-overlap .preview-img-full { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.perfil-avatar-overlap .letra { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 56px; font-weight: 800; }
/* right/bottom en POSITIVO (no negativo) a propósito: un botón centrado
   en la esquina exacta del cuadrado que envuelve al círculo cae mayormente
   en el área que el círculo NO cubre (la esquina de un cuadrado siempre
   sobra respecto al círculo inscripto), así que quedaba "flotando" separado
   de la foto en vez de apoyado sobre ella. Con un inset positivo el botón
   se superpone de verdad al borde curvo visible del círculo. */
.perfil-avatar-edit-btn {
    position: absolute; right: 6px; bottom: 6px; width: 44px; height: 44px; border-radius: 50%;
    background: var(--panel); border: 2px solid var(--panel); box-shadow: var(--shadow-sm);
    display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--text);
}
.perfil-avatar-edit-btn:hover { color: var(--accent); }
.perfil-avatar-edit-btn svg { width: 20px; height: 20px; }
.perfil-avatar-edit-btn input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; clip: rect(0,0,0,0); }
.perfil-avatar-quitar {
    position: absolute; left: 6px; top: 6px; width: 28px; height: 28px; border-radius: 50%;
    background: var(--panel); border: 2px solid var(--panel); box-shadow: var(--shadow-sm); color: var(--danger);
    display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 13px; line-height: 1;
}
@media (max-width: 560px) {
    .perfil-avatar-wrap { width: 116px; height: 116px; left: 18px; bottom: -46px; }
    .perfil-avatar-overlap .letra { font-size: 40px; }
    .perfil-avatar-edit-btn { width: 36px; height: 36px; }
    .perfil-avatar-edit-btn svg { width: 16px; height: 16px; }
    .perfil-header-fb { margin-bottom: 66px; }
    .perfil-portada-btn span { display: none; }
}

/* ---------- Campo con ícono al inicio (Ajustes: Perfil/Contraseña/Redes) ---------- */
.field-icon-wrap { position: relative; }
.field-icon-wrap .ico-campo { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--muted); pointer-events: none; }
.field .field-icon-wrap input[type=text],
.field .field-icon-wrap input[type=email],
.field .field-icon-wrap input[type=tel],
.field .field-icon-wrap input[type=password] { padding-left: 40px; }
.field .field-icon-wrap textarea { padding-left: 40px; padding-top: 12px; }
.field-icon-wrap.wrap-textarea .ico-campo { top: 16px; transform: none; }
.field-icon-wrap .toggle-pass {
    position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 30px; height: 30px;
    border-radius: 7px; border: none; background: none; color: var(--muted); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.field-icon-wrap .toggle-pass:hover { background: var(--panel-2); color: var(--text); }
.field-icon-wrap .toggle-pass svg { width: 16px; height: 16px; }
.field .field-icon-wrap.con-toggle input { padding-right: 40px; }

/* ---------- Medidor de fuerza de contraseña ---------- */
.pass-fuerza { display: flex; gap: 4px; margin-top: 8px; }
.pass-fuerza-barra { height: 4px; flex: 1; border-radius: 999px; background: var(--border); transition: background .2s ease; }
.pass-fuerza-texto { font-size: 11.5px; color: var(--muted); margin-top: 5px; font-weight: 600; }

/* ---------- Tarjeta de consejos de seguridad, sidebar de la pestaña
   Contraseña (mismo .preview-sidebar sticky ya usado para previews de
   curso/certificado) ---------- */
.pass-tips-card { text-align: center; padding: 30px 24px; }
.pass-tips-ico { width: 52px; height: 52px; border-radius: 16px; background: rgba(var(--accent-rgb),.1); color: var(--accent); display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; }
.pass-tips-ico svg { width: 26px; height: 26px; }
.pass-tips-card h3 { font-size: 15px; margin: 0 0 14px; color: var(--text); }
.pass-tips-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; text-align: left; }
.pass-tips-list li { position: relative; padding-left: 22px; font-size: 13px; color: var(--muted); line-height: 1.5; }
.pass-tips-list li::before { content: ''; position: absolute; left: 0; top: 5px; width: 8px; height: 8px; border-radius: 50%; background: rgba(var(--accent-rgb),.35); }

/* ---------- Filas dinámicas de "Redes Sociales" (Ajustes) ---------- */
.red-fila { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.red-fila > * { min-width: 0; } /* mismo motivo que .field-grid > * */
.red-fila-icono {
    flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%; background: rgba(var(--accent-rgb),.1); color: var(--accent);
    display: flex; align-items: center; justify-content: center;
}
.red-fila-icono svg { width: 18px; height: 18px; }
.red-fila select { flex: 0 0 160px; padding: 11px 13px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 13.5px; }
.red-fila input { flex: 1; padding: 11px 13px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 14px; }
.red-fila select:focus, .red-fila input:focus { outline: none; border-color: var(--accent); }
.red-fila-quitar { flex-shrink: 0; width: 40px; height: 40px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--panel); color: var(--muted); cursor: pointer; font-size: 14px; }
.red-fila-quitar:hover { color: var(--danger); border-color: var(--danger-border); background: var(--danger-bg); }
@media (max-width: 560px) { .red-fila { flex-wrap: wrap; } .red-fila select { flex: 1 1 calc(100% - 50px); } }

/* ---------- Botón de guardado de "Ajustes" (Perfil/Contraseña/Redes
   Sociales) — grande, ícono a la DERECHA del texto (order:1 lo manda al
   final del flex sin reordenar el HTML), y SIEMPRE afuera de la tarjeta
   blanca de la sección: vive como hermano del <form> o al final de él,
   nunca anidado dentro de un .form-section. Mismo degradado de --accent
   que .btn-primary (antes tenía un azul marino fijo, deliberadamente
   distinto — el usuario pidió que volviera a seguir el diseño/color del
   tema de la academia, como el resto de los botones primarios). */
.btn-cuenta-guardar {
    display: flex; width: fit-content; margin-left: auto;
    padding: 16px 30px; font-size: 15.5px; border-radius: 12px;
    background: linear-gradient(135deg, var(--accent), var(--accent-boton2, #22c55e)); color: #fff; box-shadow: var(--shadow-md);
}
.btn-cuenta-guardar svg { width: 19px; height: 19px; order: 1; }
.btn-cuenta-guardar:hover { box-shadow: 0 10px 24px rgba(var(--accent-rgb),.28); }
@media (max-width: 640px) { .btn-cuenta-guardar { width: 100%; margin-left: 0; } }

/* ---------- Control segmentado (reemplaza <select> de pocas opciones) ---------- */
.segmented { position: relative; display: inline-flex; flex-wrap: wrap; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 3px; gap: 2px; }
.segmented input { position: absolute; opacity: 0; pointer-events: none; }
.segmented label { padding: 8px 18px; border-radius: 999px; font-size: 13px; font-weight: 700; color: var(--muted); cursor: pointer; transition: background .15s ease, color .15s ease; white-space: nowrap; }
.segmented input:checked + label { background: var(--panel); color: var(--accent); box-shadow: var(--shadow-sm); }
.segmented input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------- Selector de vista grid / lista ---------- */
.view-toggle { display: inline-flex; background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px; padding: 3px; gap: 2px; flex-shrink: 0; }
.view-toggle-btn { display: flex; align-items: center; justify-content: center; width: 34px; height: 30px; border-radius: 7px; border: none; background: none; color: var(--muted); cursor: pointer; }
.view-toggle-btn svg { width: 16px; height: 16px; }
.view-toggle-btn:hover { color: var(--text); }
.view-toggle-btn.activo { background: var(--panel); color: var(--accent); box-shadow: var(--shadow-sm); }
.curso-thumb .badge.thumb-badge { position: absolute; top: 12px; right: 12px; background: rgba(255,255,255,.94); backdrop-filter: blur(6px); white-space: nowrap; }

/* ---------- Sidebar de preview en vivo (cómo se ve la tarjeta pública) ---------- */
/* top: suma la altura del nuevo .admin-topbar (--topbar-h, definida en .admin-shell)
   para que no quede tapado por la barra sticky — con fallback 0px por si esta clase
   se usa alguna vez fuera del panel admin. */
.preview-sidebar { position: sticky; top: calc(var(--topbar-h, 0px) + 24px); }
.preview-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 0 0 10px; }
.preview-sidebar .curso-card { cursor: default; box-shadow: var(--shadow-md); }
.preview-sidebar .curso-card:hover { transform: none; }
.preview-hint { font-size: 12px; color: var(--muted); margin-top: 12px; margin-bottom: 55px; line-height: 1.5; }

/* ---------- Mockup en vivo del certificado (admin/certificado.php) ---------- */
.cert-preview { position: relative; width: 100%; aspect-ratio: 297 / 210; border-radius: var(--radius-sm); border: 1px solid var(--border); overflow: hidden; background: linear-gradient(135deg, #f8fafc, #eef2f7); box-shadow: var(--shadow-md); }
.cert-preview-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cert-preview-fallback { position: absolute; inset: 4%; display: flex; flex-direction: column; align-items: center; gap: 4px; padding-top: 6%; border: 1.5px solid #cbd5e1; border-radius: 4px; }
.cert-preview-academia { font-weight: 800; color: #64748b; white-space: nowrap; }
.cert-preview-subtitulo { color: #94a3b8; white-space: nowrap; }
.cert-preview-campo { position: absolute; left: 5%; right: 5%; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: top .12s ease, color .12s ease, font-size .12s ease, text-align 0s; }

/* ---------- Switch toggle (reemplaza checkboxes simples en formularios "de nueva generación") ---------- */
/* .switch-toggle.switch-toggle (no ".field .switch-toggle"): el switch se usa tanto
   dentro de un .field como suelto (ver admin/_ajustes_facturacion.php) — duplicar la clase
   sube la especificidad para ganarle a ".field label{display:block}" en ambos casos,
   sin depender de si hay un ancestro .field o no. */
.switch-toggle.switch-toggle { display: flex; align-items: center; gap: 12px; cursor: pointer; user-select: none; }
.switch-toggle input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.switch-track { position: relative; width: 42px; height: 24px; border-radius: 999px; background: var(--border); flex-shrink: 0; transition: background .2s ease; }
.switch-thumb { position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-sm); transition: transform .2s cubic-bezier(.4,0,.2,1); }
.switch-toggle input:checked + .switch-track { background: var(--accent); }
.switch-toggle input:checked + .switch-track .switch-thumb { transform: translateX(18px); }
.switch-toggle input:focus-visible + .switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch-label-text { font-size: 14px; color: var(--text); font-weight: 600; }

/* ---------- Slider "de nueva generación" con relleno de color + burbuja de valor ---------- */
.field-slider { margin-bottom: 4px; }
.field-slider-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.field-slider-head label { font-size: 13px; color: var(--muted); font-weight: 600; }
.field-slider-value { font-size: 12.5px; font-weight: 700; color: var(--accent); background: rgba(var(--accent-rgb),.1); padding: 2px 10px; border-radius: 999px; min-width: 40px; text-align: center; }
input[type=range].range-moderno { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: 999px; background: var(--panel-2); outline: none; cursor: pointer; }
input[type=range].range-moderno::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: #fff; border: 3px solid var(--accent); box-shadow: var(--shadow-sm); cursor: pointer; transition: transform .15s ease; }
input[type=range].range-moderno::-webkit-slider-thumb:hover { transform: scale(1.15); }
input[type=range].range-moderno::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: #fff; border: 3px solid var(--accent); box-shadow: var(--shadow-sm); cursor: pointer; transition: transform .15s ease; border: none; outline: 3px solid var(--accent); outline-offset: -3px; }
input[type=range].range-moderno::-moz-range-thumb:hover { transform: scale(1.15); }
input[type=range].range-moderno::-moz-range-track { height: 6px; border-radius: 999px; background: var(--panel-2); }

/* ---------- Selector de color circular (reemplaza el <input type=color> nativo, poco vistoso) ---------- */
.color-swatch-wrap { display: flex; align-items: center; gap: 10px; }
.color-swatch { position: relative; width: 42px; height: 42px; border-radius: 50%; flex-shrink: 0; box-shadow: 0 0 0 1px var(--border), var(--shadow-sm); cursor: pointer; overflow: hidden; transition: transform .15s ease, box-shadow .15s ease; }
.color-swatch:hover { transform: scale(1.08); box-shadow: 0 0 0 1px var(--accent), var(--shadow-md); }
.color-swatch input[type=color] { position: absolute; inset: -6px; width: calc(100% + 12px); height: calc(100% + 12px); opacity: 0; cursor: pointer; border: none; padding: 0; }
.color-hex { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .02em; }

/* ---------- Guía de tamaño de imagen + aviso de proporción ---------- */
.upload-hint-dims { font-size: 11.5px; color: var(--muted); margin-top: 4px; }
.upload-warn { display: none; align-items: flex-start; gap: 8px; font-size: 12.5px; color: var(--warn); background: var(--warn-bg); border-radius: var(--radius-sm); padding: 10px 12px; margin-top: 12px; text-align: left; line-height: 1.5; }
.upload-warn.visible { display: flex; }
.upload-warn svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; }

/* ---------- Animación de entrada de las tarjetas del editor de certificado ---------- */
#form-certificado .form-section { transition: box-shadow .2s ease, border-color .2s ease; }
#form-certificado .form-section:focus-within { border-color: rgba(var(--accent-rgb),.4); box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.08), var(--shadow-sm); }

/* ---------- Modal de curso completado ---------- */
.modal-overlay { position: fixed; inset: 0; background: rgba(15,23,42,.6); display: flex; align-items: center; justify-content: center; z-index: 300; padding: 20px; }
.modal-overlay.hidden { display: none; }
.modal-box { position: relative; background: var(--panel); border-radius: var(--radius); max-width: 420px; width: 100%; padding: 34px 28px 28px; text-align: center; box-shadow: var(--shadow-md); animation: modal-pop .18s ease; }
@keyframes modal-pop { from { transform: scale(.95); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.modal-cerrar { position: absolute; top: 14px; right: 14px; display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 8px; background: none; border: none; color: var(--muted); cursor: pointer; }
.modal-cerrar:hover { background: var(--panel-2); color: var(--text); }
.modal-icono { font-size: 42px; line-height: 1; margin-bottom: 10px; }
.modal-box h2 { font-size: 20px; margin: 0 0 4px; color: var(--text); }
.modal-curso-nombre { color: var(--muted); font-size: 14px; margin: 0 0 22px; }
.modal-fechas { display: flex; justify-content: center; gap: 28px; margin-bottom: 26px; flex-wrap: wrap; }
.modal-fecha-label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 700; margin-bottom: 3px; }
.modal-fecha-valor { display: block; font-size: 13.5px; color: var(--text); font-weight: 600; }
.modal-acciones { display: flex; flex-direction: column; gap: 10px; }
.modal-acciones .btn { justify-content: center; }
.modal-resena { padding: 16px 0 22px; margin-bottom: 4px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.modal-resena-label { margin: 0 0 8px; font-size: 13px; font-weight: 700; color: var(--text); }
.modal-resena .star-rating-input label { font-size: 26px; }
.modal-resena .mini-link { display: inline-block; margin-top: 6px; }

/* ---------- Modal de formulario (crear/ver, alineado a la izquierda —
   distinto de .modal-box, que es centrado y pensado para un mensaje corto) ---------- */
.modal-box-form { position: relative; background: var(--panel); border-radius: var(--radius); max-width: 480px; width: 100%; box-shadow: var(--shadow-md); animation: modal-pop .18s ease; text-align: left; overflow: hidden; }
.modal-form-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--border); }
.modal-form-head h2 { font-size: 16.5px; margin: 0; color: var(--text); }
.modal-form-head .modal-cerrar { position: static; }
.modal-form-body { padding: 22px; max-height: 74vh; overflow-y: auto; }
.modal-form-body .msg { margin: 0 0 16px; }
.modal-form-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--border); }
.modal-form-foot .btn { justify-content: center; }

/* ---------- Barra de filtros (listados admin: Anuncios, y reutilizable
   para futuros listados con curso/fecha/búsqueda) ---------- */
.filtros-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px; margin-bottom: 18px; }
.campo-filtro { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.campo-filtro label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.campo-filtro select, .campo-filtro input[type=date] {
    padding: 9px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 13.5px;
}
.campo-filtro select:focus, .campo-filtro input:focus { outline: none; border-color: var(--accent); }
.campo-filtro-busqueda { flex: 1 1 180px; max-width: 280px; }
.busqueda-input-wrap { display: flex; align-items: center; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0 4px 0 12px; }
.busqueda-input-wrap:focus-within { border-color: var(--accent); }
.busqueda-input-wrap input[type=search] { flex: 1; min-width: 0; border: none; background: none; padding: 9px 6px 9px 0; font-size: 13.5px; color: var(--text); }
.busqueda-input-wrap input[type=search]:focus { outline: none; }
.busqueda-input-wrap button { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 7px; border: none; background: none; color: var(--muted); cursor: pointer; flex-shrink: 0; }
.busqueda-input-wrap button:hover { background: var(--panel-2); color: var(--accent); }
.filtros-reset { align-self: center; font-size: 13px; color: var(--muted); text-decoration: none; font-weight: 600; padding: 9px 2px; }
.filtros-reset:hover { color: var(--text); text-decoration: underline; }

/* ---------- Campo compuesto select+botón dentro de .filtros-bar (acción masiva) ---------- */
.campo-accion-masiva { display: flex; gap: 8px; }
.campo-accion-masiva select {
    flex: 1; min-width: 0; padding: 9px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 13.5px;
}
.campo-accion-masiva select:focus { outline: none; border-color: var(--accent); }

/* ---------- Botón "Filtros" que colapsa .filtros-bar en mobile (oculto en
   escritorio, donde la barra ya se ve siempre completa en una fila) ---------- */
.filtros-toggle-btn {
    display: none; align-items: center; gap: 8px; width: 100%; margin-bottom: 14px; padding: 11px 16px;
    background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm);
    color: var(--text); font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.filtros-toggle-btn .chevron { margin-left: auto; transition: transform .15s ease; }
.filtros-toggle-btn.activo .chevron { transform: rotate(180deg); }
.filtros-badge {
    display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 999px; background: var(--accent); color: #fff; font-size: 11px; font-weight: 800;
}

@media (max-width: 640px) {
    .filtros-toggle-btn { display: flex; }
    .filtros-bar { display: none; flex-direction: column; align-items: stretch; }
    .filtros-bar.mostrar-mobile { display: flex; }
    .campo-filtro-busqueda { flex: 1 1 auto; max-width: none; }
}

/* ---------- Mensajes ---------- */
.msg { padding: 12px 16px; border-radius: var(--radius-sm); margin-bottom: 18px; font-size: 13.5px; }
.msg-ok { background: rgba(var(--accent-rgb),.1); color: var(--accent); }
.msg-error { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); }
.msg-warn { background: var(--warn-bg); color: var(--warn); }

/* ---------- Auth standalone (login / registro) ---------- */
.auth-page {
    min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px;
    background:
        radial-gradient(circle at 15% 15%, rgba(var(--accent-rgb),.08), transparent 45%),
        radial-gradient(circle at 85% 85%, rgba(var(--accent-2-rgb),.08), transparent 45%),
        var(--bg);
}
.auth-box { width: 100%; max-width: 380px; }
.auth-box .brand { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 24px; text-decoration: none; color: var(--text); font-weight: 800; font-size: 16px; }
.auth-box .brand .dot { width: 11px; height: 11px; border-radius: 3px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); flex-shrink: 0; }
.auth-box h1 { font-size: 19px; margin: 0 0 4px; text-align: center; color: var(--text); }
.auth-box .sub { text-align: center; color: var(--muted); font-size: 13px; margin: 0 0 20px; }
.auth-foot { text-align: center; margin-top: 18px; font-size: 13.5px; color: var(--muted); }
.auth-foot a { color: var(--accent); font-weight: 600; text-decoration: none; }
.auth-foot a:hover { text-decoration: underline; }

/* ---------- Registro/ingreso del alumno (alumno/registro.php, panel/login.php)
   — "aurora glass": un solo fondo animado a pantalla completa (sin costura
   dura entre 2 mitades de color) con textura de puntos + orbes flotantes +
   fichas flotantes tipo "screenshot de producto", y el formulario como una
   tarjeta de vidrio esmerilado (backdrop-filter) flotando encima. Clases
   NUEVAS y propias, deliberadamente separadas de .auth-page/.auth-box/
   .auth-foot de arriba — esas 2 siguen siendo las de admin/login.php (login
   del dueño), que no formaba parte de este rediseño y no debía verse afectado. */
.auth-split {
    /* SIN overflow:hidden acá a propósito: .auth-split es el <body>, y
       overflow:hidden en body bloquea el scroll VERTICAL entero de la
       página, no solo el horizontal de los orbes — eso fue justo el bug
       reportado ("en mobile no scrollea"), invisible en un screenshot
       fullPage de Playwright porque ese modo ignora el scroll real del
       viewport. El recorte horizontal de los orbes ya lo resuelve
       .auth-orbe-layer con su propio overflow:hidden más abajo, y el
       overflow-x:hidden global de "body" (ver arriba) cubre cualquier otro
       desborde lateral — no hace falta repetirlo acá. */
    min-height: 100vh; display: flex; position: relative;
    background: linear-gradient(125deg, var(--accent) 0%, var(--accent-2) 45%, var(--accent) 100%);
    background-size: 220% 220%;
    animation: auth-gradient-shift 16s ease infinite;
}
@keyframes auth-gradient-shift {
    0%, 100% { background-position: 0% 30%; }
    50% { background-position: 100% 70%; }
}
/* Textura de puntos, recortada con mask-image para que se difumine hacia
   los bordes en vez de cortar en seco (mismo criterio ya usado en
   .fondo-decorado del resto del sitio). */
.auth-split::before {
    content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background-image: radial-gradient(rgba(255,255,255,.20) 1.5px, transparent 1.5px);
    background-size: 30px 30px;
    mask-image: radial-gradient(ellipse 85% 75% at 30% 35%, #000 30%, transparent 75%);
}
/* Caja de recorte explícita para los orbes — están calculados en px/%
   pensados para el ancho de escritorio, así que en mobile se salen del
   viewport por decenas de píxeles. Confiar en "overflow:hidden" del body
   para taparlos es fràgil (el body ya tenía overflow-x:hidden desde el
   inicio del proyecto y aun así el scrollWidth del documento crecía) —
   con esta capa propia, position:absolute + overflow:hidden + inset:0
   recorta de forma inequívoca sin depender de cómo cada navegador
   propaga el overflow de body/html. */
.auth-orbe-layer { position: absolute; inset: 0; overflow: hidden; z-index: 0; pointer-events: none; }
/* .orbe (definida arriba) ya da position/border-radius/blur/z-index — acá
   solo se suma la animación de flotado lento. */
.auth-orbe { animation: auth-orbe-flotar 12s ease-in-out infinite; }
@keyframes auth-orbe-flotar {
    0%, 100% { transform: translate(0,0) scale(1); }
    50% { transform: translate(26px,-30px) scale(1.08); }
}

.auth-brand-panel {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    position: relative; z-index: 1; padding: 56px 48px; color: #fff; text-align: center;
}
.auth-brand-logo-chip {
    position: relative; z-index: 1; background: #fff; border-radius: 20px; padding: 16px 26px;
    display: inline-flex; margin-bottom: 30px; box-shadow: 0 20px 50px rgba(15,23,42,.3);
}
/* Halo suave detrás de la ficha del logo — separado en su propio pseudo-
   elemento (mismo criterio ya establecido en el proyecto: un fondo
   decorativo nunca comparte elemento con contenido real, así el blur no
   se lleva puesto el logo). */
.auth-brand-logo-chip::before {
    content: ''; position: absolute; inset: -16px; z-index: -1; border-radius: 30px;
    background: rgba(255,255,255,.35); filter: blur(22px);
}
/* .brand (de config_helpers.php) trae color:var(--text) — perfecto sobre
   esta ficha blanca, así que sa_render_brand() se reutiliza tal cual acá,
   sin ningún override de color. */
.auth-brand-panel h2 { position: relative; z-index: 1; font-size: 28px; font-weight: 800; margin: 0 0 14px; line-height: 1.25; text-shadow: 0 2px 20px rgba(15,23,42,.15); }
.auth-brand-panel > p { position: relative; z-index: 1; font-size: 15px; opacity: .92; max-width: 380px; margin: 0; line-height: 1.65; }
.auth-brand-features { position: relative; z-index: 1; margin-top: 34px; display: flex; flex-direction: column; gap: 14px; text-align: left; }
.auth-brand-features div { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; }
.auth-brand-features svg { flex-shrink: 0; width: 19px; height: 19px; }

/* Fichas flotantes tipo "screenshot de producto" — dan la sensación de estar
   viendo la app real detrás del formulario, no solo un fondo decorativo. */
.auth-float-chip {
    position: absolute; z-index: 1; display: flex; align-items: center; gap: 8px;
    background: rgba(255,255,255,.97); padding: 10px 16px; border-radius: 14px;
    box-shadow: 0 16px 36px rgba(15,23,42,.25); font-size: 12.5px; font-weight: 800; color: var(--text);
    animation: auth-chip-flotar 7s ease-in-out infinite;
    animation-delay: var(--auth-chip-delay, 0s);
}
.auth-float-chip .ico-chip {
    width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
    background: rgba(var(--accent-rgb),.14); color: var(--accent);
}
.auth-float-chip .ico-chip svg { width: 14px; height: 14px; }
@keyframes auth-chip-flotar {
    0%, 100% { transform: translateY(0) rotate(var(--auth-chip-rot, 0deg)); }
    50% { transform: translateY(-12px) rotate(var(--auth-chip-rot, 0deg)); }
}

.auth-form-panel {
    flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 32px;
    position: relative; z-index: 1;
}
.auth-form-inner {
    width: 100%; max-width: 410px;
    background: rgba(255,255,255,.94);
    backdrop-filter: blur(28px); -webkit-backdrop-filter: blur(28px);
    border: 1px solid rgba(255,255,255,.65);
    border-radius: 26px; padding: 40px 34px;
    box-shadow: 0 40px 90px -18px rgba(15,23,42,.4), 0 0 0 1px rgba(255,255,255,.4) inset;
}
.auth-form-brand { display: none; align-items: center; justify-content: center; gap: 10px; margin-bottom: 26px; text-decoration: none; color: var(--text); font-weight: 800; font-size: 16px; }
.auth-form-inner h1 { font-size: 22px; margin: 0 0 6px; text-align: center; color: var(--text); }
.auth-form-inner .sub { text-align: center; color: var(--muted); font-size: 13.5px; margin: 0 0 26px; }

.auth-divider { display: flex; align-items: center; gap: 12px; margin: 22px 0; color: var(--muted); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; }
.auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.social-btns { display: flex; flex-direction: column; gap: 10px; }
.social-btn {
    display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
    padding: 12px 18px; border-radius: 10px; border: 1px solid var(--border); background: #fff;
    color: var(--text); font-weight: 700; font-size: 14px; cursor: pointer; text-decoration: none;
    transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.social-btn:hover { background: var(--panel-2); border-color: rgba(var(--accent-rgb),.35); }
.social-btn:active { transform: scale(.98); }
.social-btn svg { flex-shrink: 0; }

@media (max-width: 899px) {
    .auth-brand-panel { display: none; }
    .auth-form-brand { display: flex; }
    .auth-form-inner { max-width: 440px; border-radius: 22px; padding: 32px 24px; }
}
@media (prefers-reduced-motion: reduce) {
    .auth-split, .auth-orbe, .auth-float-chip { animation: none; }
}

/* ---------- Registro en 2 pasos (alumno/registro.php) — "Tus datos" /
   "Seguridad", con indicador de progreso arriba del formulario. Los pasos
   son puramente visuales (JS show/hide): los 2 <div> conviven SIEMPRE
   dentro del mismo <form>, así que ocultar el paso 1 con display:none no le
   saca sus valores del POST al enviar desde el paso 2 — el servidor sigue
   validando todo junto, como si fuera un solo formulario (que lo es). */
.reg-stepper { display: flex; align-items: center; margin-bottom: 28px; }
.reg-stepper-item { display: flex; flex-direction: column; align-items: center; gap: 6px; flex-shrink: 0; }
.reg-stepper-num {
    width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    background: var(--panel-2); color: var(--muted); font-weight: 800; font-size: 13px;
    border: 2px solid var(--border); transition: background .25s ease, border-color .25s ease, color .25s ease;
}
.reg-stepper-item.activo .reg-stepper-num { background: var(--accent); border-color: var(--accent); color: #fff; }
.reg-stepper-item.completado .reg-stepper-num { background: rgba(var(--accent-rgb),.14); border-color: var(--accent); color: var(--accent); }
.reg-stepper-label { font-size: 11px; font-weight: 700; color: var(--muted); white-space: nowrap; }
.reg-stepper-item.activo .reg-stepper-label { color: var(--text); }
.reg-stepper-track { flex: 1; height: 2px; background: var(--border); margin: 0 10px 20px; position: relative; overflow: hidden; }
.reg-stepper-fill { position: absolute; inset: 0; width: 0; background: var(--accent); transition: width .3s ease; }

.reg-step { animation: reg-step-in .25s ease; }
@keyframes reg-step-in { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: translateX(0); } }
.reg-step-intro { font-size: 13px; color: var(--muted); margin: -6px 0 18px; line-height: 1.5; }
.reg-field-hint { font-size: 12px; color: var(--muted); margin-top: 6px; line-height: 1.45; }
.reg-step-actions { display: flex; gap: 10px; }
.reg-step-actions .btn-secondary { flex: 0 0 auto; }
.reg-step-actions .btn-primary { flex: 1; }

.reg-match-hint { font-size: 12px; margin-top: 6px; font-weight: 600; display: none; align-items: center; gap: 5px; }
.reg-match-hint.visible { display: flex; }
.reg-match-hint.ok { color: var(--accent); }
.reg-match-hint.error { color: var(--danger); }
.reg-match-hint svg { width: 13px; height: 13px; flex-shrink: 0; }

.reg-privacy-check { display: flex; align-items: flex-start; gap: 10px; margin: 18px 0; cursor: pointer; }
.reg-privacy-check input { width: 17px; height: 17px; margin: 1px 0 0; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.reg-privacy-check span { font-size: 13px; color: var(--muted); line-height: 1.5; }
.reg-privacy-check a { color: var(--accent); font-weight: 600; text-decoration: none; }
.reg-privacy-check a:hover { text-decoration: underline; }

.reg-trust-note { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 16px; font-size: 11.5px; color: var(--muted); }
.reg-trust-note svg { width: 13px; height: 13px; flex-shrink: 0; }

/* ---------- Encabezado de página (dashboards del alumno) ---------- */
.page-head { margin-bottom: 32px; display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.page-head h1 { font-size: 26px; margin: 0 0 6px; color: var(--text); }
.page-head p { color: var(--muted); font-size: 14px; margin: 0; }

/* ---------- Pestañas (admin/ajustes.php, panel/mi_cuenta.php) ---------- */
.ajustes-tabs { display: inline-flex; flex-wrap: wrap; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 3px; gap: 2px; margin-bottom: 24px; }
/* border:none/background:none/font/cursor: el componente nació pensado para
   <a> (sin estilos nativos que pisar) — admin/temas.php lo reutiliza sobre
   <button> para poder cambiar de pestaña sin recargar la página, y un
   <button> sin este reset trae su propio borde/fondo nativo del navegador
   por encima (bug real: cada pestaña aparecía con un recuadro oscuro propio
   en vez de la píldora limpia de siempre). */
.ajustes-tab { padding: 9px 20px; border-radius: 999px; font-size: 13.5px; font-weight: 700; color: var(--muted); text-decoration: none; transition: background .15s ease, color .15s ease; white-space: nowrap; border: none; background: none; font-family: inherit; cursor: pointer; }
.ajustes-tab:hover { color: var(--text); }
.ajustes-tab.activo { background: var(--panel); color: var(--accent); box-shadow: var(--shadow-sm); }
/* En mobile, con 4 pestañas (mi_cuenta.php: Perfil/Contraseña/Retiros/Redes
   Sociales) el texto no entra en una sola línea y flex-wrap las partía en 2
   renglones — dentro de una píldora de border-radius:999px eso se ve
   descuadrado (el radio se calcula sobre una caja ahora más alta, y el
   segundo renglón queda con el mismo padding pensado para una sola línea).
   En vez de apilar en 2 líneas, se vuelve una tira de scroll horizontal de
   una sola línea — mismo patrón "pill" pero deslizable. */
@media (max-width: 640px) {
    .ajustes-tabs { display: flex; flex-wrap: nowrap; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .ajustes-tabs::-webkit-scrollbar { display: none; }
}

/* ---------- Barra de progreso ---------- */
.progreso-bar { background: var(--panel-2); border-radius: 999px; height: 9px; overflow: hidden; }
.progreso-bar > div { background: linear-gradient(90deg, var(--accent), var(--accent-2)); height: 100%; border-radius: 999px; transition: width .3s ease; }
.progreso-pct { font-size: 12px; color: var(--muted); margin-top: 8px; font-weight: 600; }

/* ---------- Datos de pago (checkout) ---------- */
.datos-pago-box { background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 12px; font-size: 12px; color: var(--muted); margin-top: 8px; white-space: pre-wrap; }

/* ---------- Planes de membresía ---------- */
.planes-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; }
.plan-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; }
.plan-card h2 { font-size: 17px; margin: 0 0 8px; color: var(--text); }
.plan-card .precio { color: var(--accent); font-weight: 700; margin-bottom: 12px; font-size: 15px; }
.plan-card p { color: var(--muted); font-size: 13.5px; margin-bottom: 18px; flex: 1; }

/* ---------- Reproductor de lección (shell propio, sin header/footer del sitio) ---------- */
.lesson-shell { display: flex; min-height: 100vh; background: var(--bg); }
.lesson-sidebar {
    width: 280px; flex-shrink: 0; background: #fff; border-right: 1px solid var(--border);
    padding: 22px 18px; position: fixed; top: 0; bottom: 0; left: 0; overflow-y: auto;
    transform: translateX(0); transition: transform .25s ease; z-index: 40;
}
.lesson-sidebar .back-link { display: inline-flex; margin-bottom: 16px; }
.lesson-main { flex: 1; min-width: 0; margin-left: 280px; padding: 36px 40px 60px; }
.lesson-main .wrap { max-width: 720px; }
.lesson-overlay { display: none; }
.lesson-topbar-mobile { display: none; }

.lesson-modulo-titulo { color: var(--muted); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; margin: 18px 0 6px; }
.lesson-link { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px; border-radius: 12px; color: var(--text); text-decoration: none; font-size: 13.5px; margin-bottom: 2px; transition: background .15s ease, transform .15s ease; }
.lesson-link:hover { background: var(--panel-2); transform: translateX(2px); }
/* Píldora sólida (mismo lenguaje que .panel-nav-link de la sidebar del
   panel) en vez del tinte sutil que usa el admin — a propósito, para que el
   reproductor también se sienta parte del panel educativo, no del admin. */
.lesson-link.activa { background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff; font-weight: 700; box-shadow: 0 6px 16px -4px rgba(var(--accent-rgb),.45); }
.lesson-link.bloqueada { color: var(--muted); }
.lesson-link.activa.bloqueada { background: var(--panel-2); color: var(--muted); box-shadow: none; }
.lesson-link.bloqueada svg { flex-shrink: 0; opacity: .6; }

/* ---------- Clases en vivo de este curso, dentro del sidebar del reproductor ---------- */
.lesson-clases-vivo { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.lesson-clase-vivo-item {
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
    background: none; border: none; padding: 8px 10px; border-radius: var(--radius-sm);
    text-align: left; cursor: pointer; font: inherit; margin-bottom: 2px;
}
.lesson-clase-vivo-item:hover { background: var(--panel-2); }
.lesson-clase-vivo-item .titulo { font-size: 13.5px; font-weight: 600; color: var(--text); }
.lesson-clase-vivo-item .fecha { font-size: 12px; color: var(--muted); }

/* ---------- "Próxima clase" en la tarjeta de Mis cursos ---------- */
.curso-proxima-clase { font-size: 12.5px; font-weight: 600; color: var(--accent); background: rgba(var(--accent-rgb),.08); border-radius: 8px; padding: 6px 10px; }

.lesson-title { font-size: 22px; margin: 0 0 20px; color: var(--text); }
.video-wrap { position: relative; padding-bottom: 56.25%; height: 0; margin-bottom: 24px; background: #000; border-radius: var(--radius); overflow: hidden; }
.video-wrap iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; }
.lesson-content { color: var(--text); line-height: 1.7; margin-bottom: 26px; }

.recursos-list { margin-bottom: 26px; display: flex; flex-direction: column; gap: 8px; }
.recurso-link { display: flex; align-items: center; gap: 8px; color: var(--accent); text-decoration: none; font-size: 14px; font-weight: 600; }
.recurso-link:hover { text-decoration: underline; }
.recurso-link svg { width: 16px; height: 16px; flex-shrink: 0; }

.completada-chip { display: inline-flex; align-items: center; gap: 6px; color: var(--accent); font-size: 13.5px; font-weight: 700; }
.completada-chip svg { width: 16px; height: 16px; }

.lesson-footnav { display: flex; justify-content: space-between; gap: 16px; margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--border); }
.lesson-footnav a { color: var(--muted); text-decoration: none; font-size: 13.5px; font-weight: 600; max-width: 45%; }
.lesson-footnav a:hover { color: var(--text); }
.lesson-footnav .siguiente { text-align: right; margin-left: auto; }
.lesson-footnav .oculto { visibility: hidden; }

@media (max-width: 900px) {
    .lesson-sidebar { transform: translateX(-100%); box-shadow: 20px 0 60px rgba(0,0,0,.12); }
    .lesson-sidebar.abierto { transform: translateX(0); }
    .lesson-main { margin-left: 0; padding: 24px 18px 50px; }
    .lesson-shell { flex-direction: column; }
    .lesson-topbar-mobile {
        display: flex; align-items: center; justify-content: space-between;
        padding: 14px 18px; border-bottom: 1px solid var(--border);
        background: rgba(255,255,255,.9); backdrop-filter: blur(10px);
        position: sticky; top: 0; z-index: 30;
    }
    /* Barra fina de avance del curso pegada al borde inferior del header
       móvil — mismo criterio "professional" que un reader de app (YouTube/
       Medium): el alumno ve cuánto le falta sin tener que abrir el drawer. */
    .lesson-topbar-progress { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--panel-2); }
    .lesson-topbar-progress > div { height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); }
    .lesson-overlay.visible { display: block; position: fixed; inset: 0; background: rgba(15,23,42,.35); z-index: 35; }
}

/* ══════════════════════════════════════════════════════════════════════
   Panel de administración de la academia (admin/*) — mismo shell fijo +
   drawer que el reproductor de lección, pero para el dashboard de staff.
   ══════════════════════════════════════════════════════════════════════ */
.admin-shell {
    /* 16px de inset del topbar + ~64px de alto + 24px de margen inferior — usado
       por .preview-sidebar (cursos/form.php, leccion_form.php, certificado.php,
       temas.php) para no quedar tapado por la barra flotante sticky. */
    --topbar-h: 104px;
    /* Easing con resorte (overshoot suave) vía la función nativa linear() — sin
       ninguna librería de animación. Usado puntualmente: colapso de sidebar,
       apertura de dropdowns, hover de nav-link y las entradas escalonadas. */
    --ease-spring: linear(0, 0.5 55%, 0.92 75%, 1.03 88%, 0.99 95%, 1);
    /* Neutros "tinta" con un matiz apenas perceptible, en vez de gris
       Tailwind-slate genérico — SOLO acá dentro de .admin-shell, nunca en
       :root, para no afectar el sitio público del alumno. */
    --bg: #f5f8f6;
    --panel-2: #edf2ef;
    --border: #dde5e0;
    /* Paleta azul/cian del logo de SimpleAula (colores tomados por píxel
       directo de los archivos reales, no a ojo — ver core-app/assets/img/),
       SOLO dentro del panel admin (el resto del producto sigue en verde,
       decisión explícita del usuario). --accent = el azul del wordmark
       "Aula" del logo; --accent-2 = un punto intermedio del degradado
       cian→azul del ícono, elegido por contraste (el extremo más cian del
       degradado, ~2.5:1 sobre blanco, no alcanza el piso ~3.3:1 que ya
       tenía el verde/cian anteriores como texto). --accent-3 (violeta) NO
       viene del logo — se mantiene solo como tercer color funcional para
       distinguir tipos de badge (quiz/tarea/venta), el logo no trae un
       tercer matiz. */
    --accent: #2885ff;
    --accent-2: #1884ff;
    --accent-rgb: 40,133,255;
    --accent-2-rgb: 24,132,255;
    display: flex; min-height: 100vh;
    background:
        radial-gradient(circle at 12% 8%, rgba(var(--accent-rgb),.07), transparent 40%),
        radial-gradient(circle at 88% 92%, rgba(var(--accent-2-rgb),.06), transparent 40%),
        var(--bg);
}
.admin-sidebar {
    width: 240px; flex-shrink: 0; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
    display: flex; flex-direction: column; padding: 22px 16px;
    position: fixed; top: 16px; bottom: 16px; left: 16px; overflow-y: auto;
    box-shadow: var(--shadow-md);
    transform: translateX(0); transition: transform .25s ease, width .25s var(--ease-spring, cubic-bezier(.4,0,.2,1)); z-index: 40;
    view-transition-name: admin-sidebar; /* persiste/funde entre navegaciones (ver meta view-transition en admin_header.php) */
    /* Scrollbar fina y a tono, en vez de la barra gris nativa del navegador
       (se nota en monitores/ventanas más bajos, donde el nav con el logo
       grande + muchas secciones no entra sin scroll). Firefox vía
       scrollbar-width/-color; Chrome/Edge/Safari vía ::-webkit-scrollbar. */
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}
.admin-sidebar::-webkit-scrollbar { width: 6px; }
.admin-sidebar::-webkit-scrollbar-track { background: transparent; }
.admin-sidebar::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
.admin-sidebar::-webkit-scrollbar-thumb:hover { background: var(--muted); }
.admin-sidebar .brand { display: flex; align-items: center; padding: 0 4px 26px; text-decoration: none; }

/* ---------- Logo de SimpleAula (admin_sidebar.php) — 4 variantes (completo/
   ícono × claro/oscuro), alternadas por CSS según data-theme y .colapsada.
   Por defecto: completo + claro. Tamaño 60px (probado y confirmado por el
   usuario directo en el inspector del navegador) para que se note como
   marca principal del sidebar. */
.brand-logo { display: none; animation: stagger-in .4s var(--ease-spring, ease) both; }
.brand-logo-full.brand-logo-light { display: block; height: 60px; width: auto; }
.admin-shell[data-theme="dark"] .brand-logo-full.brand-logo-light { display: none; }
.admin-shell[data-theme="dark"] .brand-logo-full.brand-logo-dark { display: block; height: 60px; width: auto; }

.admin-nav-group { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.admin-nav-section { display: flex; flex-direction: column; gap: 2px; }
.admin-nav-section + .admin-nav-section { margin-top: 18px; }
.admin-nav-section-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); padding: 0 12px; margin-bottom: 4px; opacity: .75; }
.admin-nav-link {
    display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--radius-sm);
    color: var(--muted); text-decoration: none; font-size: 14px; font-weight: 600;
    position: relative; transition: background .15s ease, color .15s ease, transform .15s var(--ease-spring, ease);
    animation: stagger-in .35s var(--ease-spring, ease) both;
}
.admin-nav-link svg { width: 18px; height: 18px; flex-shrink: 0; opacity: .8; }
.admin-nav-link:hover { background: var(--panel-2); color: var(--text); transform: translateX(2px); }
.admin-nav-link.activo { background: rgba(var(--accent-rgb),.1); color: var(--accent); box-shadow: 0 0 0 1px rgba(var(--accent-rgb),.12), 0 2px 10px rgba(var(--accent-rgb),.15); }
.admin-nav-link.activo svg { opacity: 1; }

/* ---------- Íconos de color por sección (sidebar + tabbar móvil) — cada
   sección tiene un color propio y fijo dentro de una "chip" redondeada, en
   vez de depender solo de currentColor/opacity — el pedido explícito fue
   que se vean "más llamativos". El estado activo/hover se sigue notando en
   la FILA (fondo, barra de acento, color del texto), no en el ícono: acá el
   color es de identidad de categoría, no de estado. .nav-ico-sm es el
   tamaño compacto para .admin-tab (la barra de tabs móvil). ---------- */
.nav-ico {
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 30px; height: 30px; border-radius: 9px;
    transition: transform .15s var(--ease-spring, ease);
}
.nav-ico svg { width: 17px; height: 17px; opacity: 1; }
.admin-nav-link:hover .nav-ico { transform: scale(1.08) rotate(-4deg); }
.nav-ico-sm { width: 24px; height: 24px; border-radius: 7px; }
/* .admin-tab .nav-ico-sm svg (no ".nav-ico-sm svg"): así le gana en
   especificidad a ".admin-tab svg" (que sigue existiendo para el ícono
   suelto de "Más", el único tab sin chip de color) sin importar el orden
   en el archivo. */
.admin-tab .nav-ico-sm svg { width: 14px; height: 14px; }

.nav-ico-blue    { background: rgba(40,133,255,.12); color: #2885ff; }
.nav-ico-green   { background: rgba(16,185,129,.12); color: #10b981; }
.nav-ico-amber   { background: rgba(217,119,6,.12); color: #d97706; }
.nav-ico-violet  { background: rgba(124,58,237,.12); color: #7c3aed; }
.nav-ico-rose    { background: rgba(225,29,72,.12); color: #e11d48; }
.nav-ico-orange  { background: rgba(234,88,12,.12); color: #ea580c; }
.nav-ico-red     { background: rgba(220,38,38,.12); color: #dc2626; }
.nav-ico-indigo  { background: rgba(79,70,229,.12); color: #4f46e5; }
.nav-ico-cyan    { background: rgba(8,145,178,.12); color: #0891b2; }
.nav-ico-fuchsia { background: rgba(192,38,211,.12); color: #c026d3; }

/* Variantes oscuras — mismo matiz, más brillo/opacidad para que resalten
   sobre el panel oscuro (mismo criterio que --accent/--warn/--danger). */
.admin-shell[data-theme="dark"] .nav-ico-blue    { background: rgba(90,169,255,.18); color: #5aa9ff; }
.admin-shell[data-theme="dark"] .nav-ico-green   { background: rgba(52,211,153,.18); color: #34d399; }
.admin-shell[data-theme="dark"] .nav-ico-amber   { background: rgba(251,191,36,.18); color: #fbbf24; }
.admin-shell[data-theme="dark"] .nav-ico-violet  { background: rgba(167,139,250,.18); color: #a78bfa; }
.admin-shell[data-theme="dark"] .nav-ico-rose    { background: rgba(251,113,133,.18); color: #fb7185; }
.admin-shell[data-theme="dark"] .nav-ico-orange  { background: rgba(251,146,60,.18); color: #fb923c; }
.admin-shell[data-theme="dark"] .nav-ico-red     { background: rgba(248,113,113,.18); color: #f87171; }
.admin-shell[data-theme="dark"] .nav-ico-indigo  { background: rgba(129,140,248,.18); color: #818cf8; }
.admin-shell[data-theme="dark"] .nav-ico-cyan    { background: rgba(34,211,238,.18); color: #22d3ee; }
.admin-shell[data-theme="dark"] .nav-ico-fuchsia { background: rgba(232,121,249,.18); color: #e879f9; }
/* Barra de acento a la izquierda del ítem activo, con una pequeña animación de
   "crecimiento" al entrar (feedback visual de cuál sección está activa). */
.admin-nav-link.activo::before {
    content: ''; position: absolute; left: -16px; top: 50%; width: 3px; height: 0;
    background: var(--accent); border-radius: 0 3px 3px 0; transform: translateY(-50%);
    animation: nav-accent-in .2s ease forwards .05s;
}
@keyframes nav-accent-in { to { height: 60%; } }

/* ---------- Entradas escalonadas (stagger) — sidebar, stat-grid y dropdowns.
   Sin tocar ningún PHP: el orden lo da la posición real en el DOM vía
   nth-of-type/nth-child, con un tope de 8 ítems (alcanza para cualquier
   sección de sidebar, el stat-grid del escritorio y los 3 dropdowns). ---------- */
@keyframes stagger-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
.stat-grid > .stat { animation: stagger-in .35s var(--ease-spring, ease) both; }
.topbar-dropdown-panel.abierto .topbar-dropdown-item { animation: stagger-in .22s var(--ease-spring, ease) both; }

.admin-nav-link:nth-of-type(1), .stat-grid > .stat:nth-child(1), .topbar-dropdown-panel.abierto .topbar-dropdown-item:nth-of-type(1) { animation-delay: 0ms; }
.admin-nav-link:nth-of-type(2), .stat-grid > .stat:nth-child(2), .topbar-dropdown-panel.abierto .topbar-dropdown-item:nth-of-type(2) { animation-delay: 40ms; }
.admin-nav-link:nth-of-type(3), .stat-grid > .stat:nth-child(3), .topbar-dropdown-panel.abierto .topbar-dropdown-item:nth-of-type(3) { animation-delay: 80ms; }
.admin-nav-link:nth-of-type(4), .stat-grid > .stat:nth-child(4), .topbar-dropdown-panel.abierto .topbar-dropdown-item:nth-of-type(4) { animation-delay: 120ms; }
.admin-nav-link:nth-of-type(5), .stat-grid > .stat:nth-child(5), .topbar-dropdown-panel.abierto .topbar-dropdown-item:nth-of-type(5) { animation-delay: 160ms; }
.admin-nav-link:nth-of-type(6), .stat-grid > .stat:nth-child(6), .topbar-dropdown-panel.abierto .topbar-dropdown-item:nth-of-type(6) { animation-delay: 200ms; }
.admin-nav-link:nth-of-type(7), .stat-grid > .stat:nth-child(7) { animation-delay: 240ms; }
.admin-nav-link:nth-of-type(8), .stat-grid > .stat:nth-child(8) { animation-delay: 280ms; }

/* ---------- Pie de la sidebar: solo el botón de colapsar/expandir (el perfil
   de usuario se mudó al topbar, ver .admin-profile más abajo). ---------- */
.admin-sidebar-foot { border-top: 1px solid var(--border); padding-top: 14px; margin-top: 14px; }
.admin-collapse-btn {
    display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px;
    border-radius: var(--radius-sm); border: none; background: none; color: var(--muted);
    font-size: 13px; font-weight: 600; cursor: pointer; transition: background .15s ease, color .15s ease;
}
.admin-collapse-btn:hover { background: var(--panel-2); color: var(--text); }
.admin-collapse-btn svg { width: 17px; height: 17px; flex-shrink: 0; transition: transform .25s cubic-bezier(.4,0,.2,1); }
.admin-sidebar.colapsada .admin-collapse-btn svg { transform: rotate(180deg); }

.admin-main { flex: 1; min-width: 0; margin-left: 272px; padding: 24px 28px 48px; transition: margin-left .25s var(--ease-spring, cubic-bezier(.4,0,.2,1)); }
.admin-overlay { display: none; }
.admin-tabbar { display: none; } /* la navegación en escritorio ya vive en la sidebar */

/* ---------- Sidebar colapsada a riel de íconos (desktop únicamente — el drawer
   móvil de abajo no se ve afectado por esta clase). Los textos se ocultan y cada
   link muestra su título nativo del navegador como tooltip. ---------- */
.admin-sidebar.colapsada { width: 76px; }
.admin-sidebar.colapsada ~ .admin-main { margin-left: 108px; }
/* Los links de nav no envuelven su texto en <span> (es un nodo de texto suelto
   junto al <svg>) — en vez de tocar el markup de admin_sidebar.php, se oculta
   con font-size:0 (el ícono no se ve afectado: su ancho/alto son px fijos, no
   relativos a la fuente). */
.admin-sidebar.colapsada .admin-nav-section-label,
.admin-sidebar.colapsada .admin-collapse-btn span { display: none; }
/* gap:0 — el "gap" del flex de .admin-nav-link (12px) sigue reservando
   espacio entre el ícono y el texto aunque el texto quede en font-size:0
   (el gap no depende del tamaño de fuente); sin esto, el ícono queda pegado
   al borde izquierdo con 12px de aire fantasma a la derecha, y el fondo de
   hover/activo (que es toda la fila) se ve visiblemente descuadrado
   respecto al ícono en vez de centrado. */
.admin-sidebar.colapsada .admin-nav-link { justify-content: center; font-size: 0; gap: 0; }
.admin-sidebar.colapsada .admin-nav-link.activo::before { left: -16px; }
.admin-sidebar.colapsada .brand { justify-content: center; padding: 0 0 22px; }
.admin-sidebar.colapsada .admin-collapse-btn { justify-content: center; }
/* Colapsada: el logo completo (ancho, 3:1) no entra en el riel de 76px —
   se muestra solo el ícono cuadrado (favicon-*.png), mismo criterio de
   tema claro/oscuro que el logo completo. */
.admin-sidebar.colapsada .brand-logo-full { display: none; }
/* La regla de arriba (especificidad 2 clases) pierde contra
   ".admin-shell[data-theme=dark] .brand-logo-full.brand-logo-dark" (4 clases/
   atributos) que muestra el logo oscuro — sin este refuerzo, colapsar en modo
   oscuro dejaba el logo ANCHO visible en vez del ícono cuadrado. */
.admin-shell[data-theme="dark"] .admin-sidebar.colapsada .brand-logo-full { display: none; }
.admin-sidebar.colapsada .brand-logo-icon.brand-logo-light { display: block; height: 32px; width: 32px; }
.admin-shell[data-theme="dark"] .admin-sidebar.colapsada .brand-logo-icon.brand-logo-light { display: none; }
.admin-shell[data-theme="dark"] .admin-sidebar.colapsada .brand-logo-icon.brand-logo-dark { display: block; height: 32px; width: 32px; }

@media (max-width: 900px) {
    .admin-shell { flex-direction: column; }
    /* El drawer móvil pasa a ser un "bottom sheet" (estilo app: sube desde
       abajo) en vez de un panel que entra desde la izquierda — mismo
       elemento/mismo contenido/mismo initDrawer() de siempre, solo cambia el
       eje de la animación y la forma. Una "manija" decorativa arriba (sin
       gesto de arrastre real: cerrar sigue siendo por overlay o por tocar
       un link, igual que antes). */
    .admin-sidebar {
        top: auto; bottom: 0; left: 0; right: 0; width: auto; max-height: 80vh;
        border-radius: var(--radius) var(--radius) 0 0;
        border: none; border-top: 1px solid var(--border); box-shadow: none;
        background: var(--panel);
        padding-top: 28px;
        transform: translateY(100%);
        transition: transform .3s var(--ease-spring, ease);
    }
    .admin-sidebar::before {
        content: ''; position: absolute; top: 10px; left: 50%; width: 36px; height: 4px;
        background: var(--border); border-radius: 999px; transform: translateX(-50%);
    }
    .admin-sidebar.abierto { transform: translateY(0); box-shadow: 0 -20px 60px rgba(0,0,0,.16); }
    .admin-sidebar-foot { display: none; } /* "Colapsar menú" es un concepto de escritorio, no aplica en el bottom sheet */
    /* En el bottom sheet el logo se ve grande y centrado (en vez de chico y a
       la izquierda como en escritorio) — mismo <a class="brand"> e imágenes,
       solo cambia tamaño/alineación por CSS. */
    .admin-sidebar .brand { justify-content: center; padding: 4px 20px 22px; }
    .brand-logo-full.brand-logo-light, .admin-shell[data-theme="dark"] .brand-logo-full.brand-logo-dark { height: 68px; }
    .admin-sidebar.colapsada { width: auto; } /* el colapso es un concepto de escritorio; en el bottom sheet siempre se ve completo */
    /* El colapso no aplica en móvil: aunque la cookie diga "colapsada" (arrastrada
       de una sesión de escritorio), acá siempre se ve el logo completo centrado.
       El segundo selector (con [data-theme=dark]) es necesario para ganarle en
       especificidad a ".admin-shell[data-theme=dark] .admin-sidebar.colapsada
       .brand-logo-full" (la reinforzada arriba para el caso de escritorio). */
    /* Bug real: la versión anterior de esta regla forzaba display:block sobre
       CUALQUIER .brand-logo-full (sin distinguir claro/oscuro), así que con
       la cookie "colapsada" arrastrada de una sesión de escritorio, el bottom
       sheet mostraba el logo claro Y el oscuro al mismo tiempo, uno al lado
       del otro. Ahora respeta el tema, igual que la regla base (línea ~753). */
    .admin-sidebar.colapsada .brand-logo-full.brand-logo-light { display: block; }
    .admin-shell[data-theme="dark"] .admin-sidebar.colapsada .brand-logo-full.brand-logo-light { display: none; }
    .admin-shell[data-theme="dark"] .admin-sidebar.colapsada .brand-logo-full.brand-logo-dark { display: block; }
    /* Mismo cuidado de especificidad que arriba: ".brand-logo-icon" a secas
       (0,3,0) no le ganaba a ".admin-shell[data-theme=dark]
       .admin-sidebar.colapsada .brand-logo-icon.brand-logo-dark" (0,6,0) —
       el ícono cuadrado de escritorio-colapsado quedaba visible A LA VEZ que
       el logo completo en el bottom sheet. Se repite el selector con la
       misma especificidad exacta para poder ganarle en los dos temas. */
    .admin-sidebar.colapsada .brand-logo-icon.brand-logo-light,
    .admin-shell[data-theme="dark"] .admin-sidebar.colapsada .brand-logo-icon.brand-logo-light,
    .admin-shell[data-theme="dark"] .admin-sidebar.colapsada .brand-logo-icon.brand-logo-dark { display: none; }
    .admin-sidebar.colapsada .brand { justify-content: center; }
    .admin-sidebar.colapsada .admin-nav-section-label,
    .admin-sidebar.colapsada .admin-collapse-btn span { display: initial; }
    .admin-sidebar.colapsada .admin-nav-link { font-size: 14px; }
    .admin-sidebar.colapsada .admin-nav-link, .admin-sidebar.colapsada .admin-collapse-btn { justify-content: flex-start; }
    /* padding-bottom deja lugar a .admin-tabbar (fija abajo) + su propio
       espacio de safe-area, para que el contenido nunca quede tapado. */
    .admin-main, .admin-sidebar.colapsada ~ .admin-main { margin-left: 0; padding: 24px 18px calc(78px + env(safe-area-inset-bottom, 0px)); }
    .admin-overlay.visible { display: block; position: fixed; inset: 0; background: rgba(15,23,42,.35); z-index: 35; }

    /* ---------- Barra de tabs fija abajo (admin_bottom_nav.php) — el drawer
       de la sidebar de arriba sigue existiendo tal cual, "Más" solo cambia
       QUIÉN lo abre (ver admin_bottom_nav.php: misma clase admin-menu-btn
       que ya engancha initDrawer() en site.js). ---------- */
    .admin-tabbar {
        display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
        background: var(--panel);
        border-top: 1px solid var(--border);
        padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
        box-shadow: 0 -4px 20px rgba(0,0,0,.06);
        view-transition-name: admin-tabbar;
    }
    .admin-tab {
        flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
        padding: 6px 2px; border: none; background: none; color: var(--muted);
        text-decoration: none; font-size: 10.5px; font-weight: 600; cursor: pointer; font-family: inherit;
        border-radius: var(--radius-sm); transition: color .15s ease, transform .15s var(--ease-spring, ease);
    }
    .admin-tab svg { width: 21px; height: 21px; }
    .admin-tab:active { transform: scale(.92); }
    .admin-tab.activo { color: var(--accent); }
}

/* ══════════════════════════════════════════════════════════════════════
   Barra superior del panel admin (admin_topbar.php) — título de la página
   (reutiliza $titulo_pagina, ya lo define cada página) + campana de
   notificaciones, chip de plan/membresía (solo dueño), toggle claro/oscuro
   y el perfil de usuario (mudado acá desde el pie de la sidebar).
   ══════════════════════════════════════════════════════════════════════ */
.admin-topbar {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    min-height: 64px;
    margin: 0 0 24px; padding: 13px 24px;
    background: var(--panel);
    border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm);
    position: sticky; top: 16px; z-index: 25;
    view-transition-name: admin-topbar;
}
.admin-topbar-title { font-size: 15px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.admin-topbar-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.topbar-actions-right { display: flex; align-items: center; gap: 8px; }

/* Logo (ícono, mismo favicon-light/dark.png que usan el sidebar y la pestaña
   del navegador) — solo existe en móvil, ocupando el lugar donde antes
   quedaba el avatar de perfil; ver .admin-topbar-logo-mobile más abajo. */
.admin-topbar-logo-mobile { display: none; align-items: center; }
.admin-topbar-logo-mobile img { height: 38px; width: 38px; display: block; }
.admin-topbar-logo-mobile .logo-dark { display: none; }
.admin-shell[data-theme="dark"] .admin-topbar-logo-mobile .logo-light { display: none; }
.admin-shell[data-theme="dark"] .admin-topbar-logo-mobile .logo-dark { display: block; }

@media (max-width: 900px) {
    /* Única barra superior en móvil (ya no compite con una segunda barra de
       marca+hamburguesa, esa se eliminó) — por eso ahora sí puede quedar
       sticky. El logo ocupa el extremo izquierdo (lugar del título, oculto
       en móvil); a la derecha, en este orden: campana, tema y el avatar de
       perfil (sin nombre) al final, pegado al borde derecho. */
    .admin-topbar { position: sticky; top: 8px; margin: 8px 8px 16px; padding: 10px 14px; border-radius: var(--radius); }
    .admin-topbar-title { display: none; } /* el nombre de la academia ya se ve al abrir "Más" */
    .admin-topbar-logo-mobile { display: flex; }
    .admin-profile-dropdown { order: 1; } /* dentro de .admin-topbar-actions: al final, después de .topbar-actions-right */
    .admin-profile-trigger { border: none; padding: 0 6px 0 0; background: none; }
    .admin-profile-trigger .chev { display: none; }
    .admin-profile-trigger .nombre { display: none; }
}

/* ---------- Botón circular genérico (campana, toggle de tema) ---------- */
.topbar-icon-btn {
    position: relative; display: flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 50%; border: none; background: none;
    color: var(--muted); cursor: pointer; flex-shrink: 0;
    transition: background .15s ease, color .15s ease;
}
.topbar-icon-btn:hover { background: var(--panel-2); color: var(--text); }
.topbar-icon-btn svg { width: 19px; height: 19px; }

/* Badge de conteo sobre la campana — entrada tipo "pop" única (no parpadea sin parar). */
.topbar-badge {
    position: absolute; top: 4px; right: 4px; min-width: 16px; height: 16px; padding: 0 4px;
    border-radius: 999px; background: var(--danger); color: #fff; font-size: 10px; font-weight: 800;
    display: flex; align-items: center; justify-content: center; line-height: 1;
    animation: badge-pop .3s cubic-bezier(.34,1.56,.64,1);
}
@keyframes badge-pop { from { transform: scale(0); } to { transform: scale(1); } }

/* Ícono de tema: sol y luna superpuestos, cross-fade + rotación al alternar. */
.theme-toggle-btn { position: relative; overflow: hidden; }
.theme-toggle-btn svg { position: absolute; transition: transform .35s cubic-bezier(.4,0,.2,1), opacity .25s ease; }
.theme-toggle-btn .ico-sun { opacity: 1; transform: rotate(0deg) scale(1); }
.theme-toggle-btn .ico-moon { opacity: 0; transform: rotate(-90deg) scale(.5); }
.admin-shell[data-theme="dark"] .theme-toggle-btn .ico-sun { opacity: 0; transform: rotate(90deg) scale(.5); }
.admin-shell[data-theme="dark"] .theme-toggle-btn .ico-moon { opacity: 1; transform: rotate(0deg) scale(1); }

/* ---------- Dropdown genérico (campana / perfil / chip de plan) ---------- */
.topbar-dropdown { position: relative; }
.topbar-dropdown-panel {
    position: absolute; top: calc(100% + 10px); right: 0; z-index: 60;
    width: max-content; min-width: 270px; max-width: 320px;
    background: var(--panel);
    border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow-md); padding: 8px;
    opacity: 0; visibility: hidden; transform: translateY(-6px) scale(.98); transform-origin: top right;
    transition: opacity .16s var(--ease-spring, ease), transform .16s var(--ease-spring, ease), visibility 0s linear .16s;
}
.topbar-dropdown-panel.abierto { opacity: 1; visibility: visible; transform: translateY(0) scale(1); transition: opacity .16s var(--ease-spring, ease), transform .16s var(--ease-spring, ease); }
.topbar-dropdown-head { padding: 10px 12px 8px; font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.topbar-dropdown-item {
    display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--radius-sm);
    color: var(--text); text-decoration: none; font-size: 13.5px; transition: background .15s ease;
}
.topbar-dropdown-item svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--muted); }
.topbar-dropdown-item:hover { background: var(--panel-2); }
.topbar-dropdown-item .n { margin-left: auto; font-weight: 800; color: var(--accent); background: rgba(var(--accent-rgb),.1); border-radius: 999px; padding: 1px 8px; font-size: 12px; flex-shrink: 0; }
.topbar-dropdown-item .info { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.topbar-dropdown-item .info .sub { font-size: 11.5px; color: var(--muted); font-weight: 400; }
.topbar-dropdown-empty { padding: 26px 14px; text-align: center; color: var(--muted); font-size: 13px; }
.topbar-dropdown-divider { height: 1px; background: var(--border); margin: 6px 4px; }
.topbar-dropdown-item.salir { color: var(--danger); }
.topbar-dropdown-item.salir svg { color: var(--danger); }
.topbar-dropdown-item.salir:hover { background: var(--danger-bg); }

/* ---------- Comunicado de academia sin leer (campanita del profesor,
   panel_topbar.php) — punto rojo + título en negrita, mismo criterio visual
   que un "no leído" de bandeja de entrada. ---------- */
.topbar-dropdown-item.no-leida .info span:first-child { font-weight: 700; color: var(--text); }
.punto-no-leido { width: 8px; height: 8px; border-radius: 50%; background: var(--danger); flex-shrink: 0; margin-left: auto; }
@media (max-width: 480px) {
    .topbar-dropdown-panel { position: fixed; left: 14px; right: 14px; top: 62px; width: auto; max-width: none; }
}

/* ---------- Perfil de usuario (mudado del pie de la sidebar) ---------- */
.admin-profile-trigger {
    display: flex; align-items: center; gap: 8px; padding: 4px 10px 4px 4px; border-radius: 999px;
    border: 1px solid var(--border); background: none; cursor: pointer; color: var(--text); flex-shrink: 0;
    transition: background .15s ease;
}
.admin-profile-trigger:hover { background: var(--panel-2); }
.admin-profile-trigger .avatar { width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: flex; align-items: center; justify-content: center; font-weight: 800; color: #fff; font-size: 12.5px; flex-shrink: 0; }
.admin-profile-trigger .nombre { font-size: 13px; font-weight: 700; max-width: 110px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.admin-profile-trigger .chev { width: 13px; height: 13px; color: var(--muted); flex-shrink: 0; transition: transform .2s ease; }
.admin-profile-trigger[aria-expanded="true"] .chev { transform: rotate(180deg); }

.admin-profile-card { display: flex; align-items: center; gap: 12px; padding: 8px 10px 14px; }
.admin-profile-card .avatar { width: 42px; height: 42px; border-radius: 12px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: flex; align-items: center; justify-content: center; font-weight: 800; color: #fff; font-size: 16px; flex-shrink: 0; }
.admin-profile-card .info { min-width: 0; }
.admin-profile-card .u { font-size: 14px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.admin-profile-card .r { font-size: 12px; color: var(--muted); text-transform: capitalize; }

/* ══════════════════════════════════════════════════════════════════════
   Panel del cliente (profesor + alumno) — panel_header.php/panel_footer.php.
   Mismo esqueleto de layout que el panel admin (sidebar fija con drawer
   móvil, topbar sticky, tabbar) pero SIN la identidad azul/oscura de
   .admin-shell — sigue en verde, la marca de la propia academia, no la de
   SimpleAula, y sin modo oscuro real. Los componentes de navegación en sí
   (.admin-nav-link, .admin-nav-section, .admin-collapse-btn, .admin-tab,
   .nav-ico-*) se REUTILIZAN tal cual dentro de este shell — nunca estuvieron
   scopeados a .admin-shell como ancestro, así que ya heredan el verde
   automáticamente acá; solo el armazón (sidebar/main/topbar/tabbar/overlay/
   perfil) necesita su propia clase porque .admin-shell sí trae su propio
   --topbar-h y la sidebar de escritorio/alto fijo que no queremos duplicar
   con reglas condicionales de tema oscuro.

   Look "panel educativo" (pedido explícito del usuario): fondo gris-azulado
   más oscuro que el blanco casi puro de :root, para que las tarjetas
   blancas (.content-card/.stat/.curso-card/.table-wrap, todas ya usan
   var(--border) y var(--shadow-*)) floten con más contraste — sin tocar
   :root, así que el sitio público (site_header.php) no se ve afectado.
   Mismo truco de redefinir tokens ya usado por .admin-shell[data-theme=dark]:
   como todos los componentes ya leen var(--border)/var(--shadow-*) en vez
   de un color fijo, alcanza con estos 3 overrides para que TODA la UI del
   panel (sidebar, topbar, cards, tablas, tarjetas de curso) se actualice
   sola, sin tocar cada componente por separado. */
.panel-shell {
    display: flex; min-height: 100vh;
    --bg: #e8edf4;
    --border: #ccd6e3;
    --shadow-sm: 0 2px 6px rgba(15,23,42,.07), 0 1px 2px rgba(15,23,42,.05);
    --shadow-md: 0 18px 40px rgba(15,23,42,.12);
    background: var(--bg);
}

.panel-sidebar {
    width: 240px; flex-shrink: 0; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
    display: flex; flex-direction: column; padding: 22px 16px;
    position: fixed; top: 16px; bottom: 16px; left: 16px; overflow-y: auto;
    box-shadow: var(--shadow-md);
    transform: translateX(0); transition: transform .25s ease, width .25s var(--ease-spring, cubic-bezier(.4,0,.2,1)); z-index: 40;
    scrollbar-width: thin; scrollbar-color: var(--border) transparent;
}
.panel-sidebar::-webkit-scrollbar { width: 6px; }
.panel-sidebar::-webkit-scrollbar-track { background: transparent; }
.panel-sidebar::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
.panel-sidebar .brand { display: flex; align-items: center; gap: 10px; padding: 4px 4px 26px; text-decoration: none; }
.panel-sidebar .brand img { height: 63px; width: auto; max-width: 100%; border-radius: 8px; display: block; }
.panel-sidebar .brand .dot { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.panel-sidebar .brand .brand-nombre { font-size: 16px; font-weight: 800; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Expandida: logo completo (o punto+nombre). Colapsada: favicon/ícono
   cuadrado — un logo ancho (wordmark) se ve aplastado en el riel de 76px,
   por eso son DOS elementos distintos (no el mismo logo encogido), igual
   criterio que ya usaba el viejo sistema de brand-logo-full/icon.
   object-fit:contain (no cover) porque el archivo subido no siempre es
   cuadrado — así se ve completo dentro del cuadro, nunca recortado. */
.panel-sidebar .brand-full { display: flex; align-items: center; gap: 10px; }
.panel-sidebar .brand-compact { display: none; align-items: center; justify-content: center; }
.panel-sidebar .brand-compact img { height: 40px; width: 40px; border-radius: 7px; object-fit: contain; display: block; }
.panel-sidebar .brand-compact .dot { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); }

/* ---------- Tarjeta de perfil (avatar + nombre + rol), pedida explícitamente
   para que el panel del cliente se lea como un panel EDUCATIVO propio (tipo
   TutorLMS) y no como una copia recoloreada del admin — el admin nunca tuvo
   esto en su sidebar (su perfil vive solo en el topbar). */
.panel-profile-card-side {
    display: flex; align-items: center; gap: 12px; padding: 12px; margin: 0 0 18px;
    background: var(--panel-2); border-radius: 16px;
}
.panel-profile-card-side .avatar {
    width: 40px; height: 40px; border-radius: 12px; flex-shrink: 0;
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 800; font-size: 15px;
}
.panel-profile-card-side .info { min-width: 0; }
.panel-profile-card-side .nombre { font-size: 13.5px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.panel-profile-card-side .rol-chip {
    display: inline-flex; margin-top: 3px; padding: 2px 9px; border-radius: 999px;
    background: rgba(var(--accent-rgb),.14); color: var(--accent); font-size: 10.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .03em;
}

/* ---------- Navegación en "pills" — a propósito muy distinta del
   .admin-nav-link del panel de dueños (barra fina de acento + tinte sutil):
   acá el ítem activo es una píldora sólida con degradado y sombra de color,
   el lenguaje visual de una app de estudio, no el de un dashboard de negocio. */
.panel-nav-section-label { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); padding: 0 12px; margin-bottom: 6px; opacity: .7; }
.panel-nav-link {
    display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 14px;
    color: var(--muted); text-decoration: none; font-size: 14px; font-weight: 600;
    position: relative; transition: background .18s ease, color .18s ease, transform .15s var(--ease-spring, ease), box-shadow .18s ease;
    animation: stagger-in .35s var(--ease-spring, ease) both;
}
.panel-nav-link:hover { background: var(--panel-2); color: var(--text); transform: translateX(2px); }
.panel-nav-link .nav-ico { transition: background .18s ease, color .18s ease, transform .15s var(--ease-spring, ease); }
.panel-nav-link:hover .nav-ico { transform: scale(1.08) rotate(-4deg); }
.panel-nav-link.activo {
    background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff;
    box-shadow: 0 10px 22px -6px rgba(var(--accent-rgb),.5);
}
.panel-nav-link.activo .nav-ico { background: rgba(255,255,255,.22); color: #fff; }
.panel-nav-link.activo:hover { transform: none; }
.panel-nav-link:nth-of-type(1) { animation-delay: 0ms; }
.panel-nav-link:nth-of-type(2) { animation-delay: 40ms; }
.panel-nav-link:nth-of-type(3) { animation-delay: 80ms; }
.panel-nav-link:nth-of-type(4) { animation-delay: 120ms; }
.panel-nav-link:nth-of-type(5) { animation-delay: 160ms; }
.panel-nav-link:nth-of-type(6) { animation-delay: 200ms; }

.panel-sidebar.colapsada { width: 76px; }
.panel-sidebar.colapsada ~ .panel-main { margin-left: 108px; }
.panel-sidebar.colapsada .panel-nav-section-label,
.panel-sidebar.colapsada .panel-profile-card-side .info,
.panel-sidebar.colapsada .admin-collapse-btn span { display: none; }
.panel-sidebar.colapsada .panel-profile-card-side { justify-content: center; padding: 8px; }
.panel-sidebar.colapsada .brand-full { display: none; }
.panel-sidebar.colapsada .brand-compact { display: flex; }
.panel-sidebar.colapsada .panel-nav-link { justify-content: center; font-size: 0; gap: 0; }
.panel-sidebar.colapsada .brand { justify-content: center; padding: 0 0 22px; }
.panel-sidebar.colapsada .admin-collapse-btn { justify-content: center; }

.panel-main { flex: 1; min-width: 0; margin-left: 272px; padding: 24px 28px 48px; transition: margin-left .25s var(--ease-spring, cubic-bezier(.4,0,.2,1)); }
.panel-overlay { display: none; }
.panel-tabbar { display: none; } /* la navegación en escritorio ya vive en la sidebar — solo se activa dentro del media query móvil de abajo */

@media (max-width: 900px) {
    .panel-shell { flex-direction: column; }
    .panel-sidebar {
        top: auto; bottom: 0; left: 0; right: 0; width: auto; max-height: 80vh;
        border-radius: var(--radius) var(--radius) 0 0;
        border: none; border-top: 1px solid var(--border); box-shadow: none;
        background: var(--panel); padding-top: 28px;
        transform: translateY(100%); transition: transform .3s var(--ease-spring, ease);
    }
    .panel-sidebar::before {
        content: ''; position: absolute; top: 10px; left: 50%; width: 36px; height: 4px;
        background: var(--border); border-radius: 999px; transform: translateX(-50%);
    }
    .panel-sidebar.abierto { transform: translateY(0); box-shadow: 0 -20px 60px rgba(0,0,0,.16); }
    .panel-sidebar-foot { display: none; }
    /* Nombre/logo de la academia se ocultan en el drawer móvil — ya se
       muestran en el topbar (panel_topbar.php), repetirlos acá era
       redundante con el título de la página apenas se abre el menú. */
    .panel-sidebar .brand { display: none; }
    .panel-sidebar.colapsada { width: auto; }
    .panel-sidebar.colapsada .panel-nav-section-label,
    .panel-sidebar.colapsada .panel-profile-card-side .info,
    .panel-sidebar.colapsada .admin-collapse-btn span { display: initial; }
    .panel-sidebar.colapsada .panel-profile-card-side { justify-content: flex-start; padding: 12px; }
    .panel-sidebar.colapsada .panel-nav-link { font-size: 14px; justify-content: flex-start; gap: 12px; }
    .panel-main, .panel-sidebar.colapsada ~ .panel-main { margin-left: 0; padding: 20px 16px calc(96px + env(safe-area-inset-bottom, 0px)); }
    .panel-overlay.visible { display: block; position: fixed; inset: 0; background: rgba(15,23,42,.35); z-index: 35; }

    /* ---------- Tabbar flotante del panel del cliente (panel_bottom_nav.php)
       — deliberadamente NO reutiliza .admin-tabbar/.admin-tab (esa es la
       barra plana, borde-a-borde, del panel de dueños): acá es una "isla"
       flotante con esquinas redondeadas y el tab activo levanta su ícono
       sobre una píldora de color, mismo lenguaje que .panel-nav-link de la
       sidebar — pedido explícito: que en el teléfono se sienta como una app
       de estudio (Duolingo/Udemy), no como una tabla de administración. */
    .panel-tabbar {
        display: flex; align-items: stretch; gap: 2px;
        position: fixed; left: 12px; right: 12px; bottom: calc(10px + env(safe-area-inset-bottom, 0px)); z-index: 20;
        background: var(--panel); border: 1px solid var(--border); border-radius: 22px;
        padding: 7px 6px; box-shadow: 0 16px 36px rgba(15,23,42,.16);
        view-transition-name: panel-tabbar;
    }
    .panel-tab {
        flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
        padding: 5px 2px; border: none; background: none; color: var(--muted);
        text-decoration: none; font-size: 10.5px; font-weight: 700; cursor: pointer; font-family: inherit;
        border-radius: 16px; transition: color .15s ease;
    }
    .panel-tab .ico-wrap {
        width: 34px; height: 26px; display: flex; align-items: center; justify-content: center;
        border-radius: 12px; transition: background .18s var(--ease-spring, ease), transform .18s var(--ease-spring, ease), box-shadow .18s ease;
    }
    .panel-tab svg { width: 20px; height: 20px; }
    .panel-tab:active .ico-wrap { transform: scale(.9); }
    .panel-tab.activo { color: var(--accent); }
    .panel-tab.activo .ico-wrap {
        background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff;
        transform: translateY(-3px); box-shadow: 0 8px 18px -4px rgba(var(--accent-rgb),.55);
    }
}

/* Header oscuro con degradado de marca — a diferencia del resto del panel
   (claro), acá se justifica un contraste fuerte porque es una sola barra
   angosta, no una superficie grande de lectura; mismo patrón que ya usan
   Notion/Linear/Vercel para distinguir la "barra de comando" del contenido.
   El degradado usa los 3 acentos DE LA ACADEMIA (--accent/--accent-2/
   --accent-3, personalizables desde Temas) — antes usaba a propósito los
   colores fijos del logo de SimpleAula (#0f172a/#2885ff/#14acff), que es
   justo la marca que este panel NO debería llevar (esa es la identidad de
   .admin-shell en oscuro, el panel interno del SaaS): si una academia
   cambia su color de acento en Temas, esta barra debe seguirlo, no quedar
   pegada al azul de otra empresa. Los hijos (título, campana, perfil)
   necesitan su propio override de color abajo porque por defecto leen
   var(--text)/var(--muted), pensados para fondo claro. */
.panel-topbar {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    min-height: 64px; margin: 0 0 24px; padding: 13px 24px;
    background: linear-gradient(120deg, var(--accent) 0%, var(--accent-2) 65%, var(--accent-3) 100%);
    border: 1px solid rgba(255,255,255,.12); border-radius: var(--radius); box-shadow: 0 12px 28px rgba(var(--accent-rgb),.28);
    position: sticky; top: 16px; z-index: 25;
}
.panel-topbar-title { font-size: 15px; font-weight: 700; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.panel-topbar-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.panel-topbar .topbar-icon-btn { color: rgba(255,255,255,.75); }
.panel-topbar .topbar-icon-btn:hover { background: rgba(255,255,255,.12); color: #fff; }
.panel-topbar .panel-profile-trigger { border-color: rgba(255,255,255,.18); color: #fff; }
.panel-topbar .panel-profile-trigger:hover { background: rgba(255,255,255,.1); }
.panel-topbar .panel-profile-trigger .chev { color: rgba(255,255,255,.7); }
.panel-topbar-logo-mobile { display: none; align-items: center; }
/* object-fit:contain (no cover) porque el archivo subido como favicon/logo
   no siempre es cuadrado — contain garantiza que se vea COMPLETO dentro
   del cuadro en vez de recortado, sin importar su proporción real. */
.panel-topbar-logo-mobile img { height: 42px; width: 42px; border-radius: 7px; object-fit: contain; display: block; }
.panel-topbar-logo-mobile .dot { width: 18px; height: 18px; border-radius: 50%; background: var(--accent); }

@media (max-width: 900px) {
    .panel-topbar { position: sticky; top: 8px; margin: 8px 8px 16px; padding: 10px 14px; border-radius: var(--radius); }
    .panel-topbar-title { display: none; }
    .panel-topbar-logo-mobile { display: flex; }
    .panel-profile-dropdown { order: 1; }
    .panel-profile-trigger { border: none; padding: 0 6px 0 0; background: none; }
    .panel-profile-trigger .chev, .panel-profile-trigger .nombre { display: none; }
}

.panel-profile-trigger {
    display: flex; align-items: center; gap: 8px; padding: 4px 10px 4px 4px; border-radius: 999px;
    border: 1px solid var(--border); background: none; cursor: pointer; color: var(--text); flex-shrink: 0;
    transition: background .15s ease;
}
.panel-profile-trigger:hover { background: var(--panel-2); }
.panel-profile-trigger .avatar { width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: flex; align-items: center; justify-content: center; font-weight: 800; color: #fff; font-size: 12.5px; flex-shrink: 0; }
.panel-profile-trigger .nombre { font-size: 13px; font-weight: 700; max-width: 110px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.panel-profile-trigger .chev { width: 13px; height: 13px; color: var(--muted); flex-shrink: 0; transition: transform .2s ease; }
.panel-profile-trigger[aria-expanded="true"] .chev { transform: rotate(180deg); }
.panel-profile-card { display: flex; align-items: center; gap: 12px; padding: 8px 10px 14px; }
.panel-profile-card .avatar { width: 42px; height: 42px; border-radius: 12px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: flex; align-items: center; justify-content: center; font-weight: 800; color: #fff; font-size: 16px; flex-shrink: 0; }
.panel-profile-card .info { min-width: 0; }
.panel-profile-card .u { font-size: 14px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.panel-profile-card .r { font-size: 12px; color: var(--muted); }

/* Tarjeta destacada del dashboard ("Continuar aprendiendo") — degradado
   sólido + círculos decorativos, mismo espíritu "banner" que usan las apps
   educativas (TutorLMS, Udemy) para la tarjeta de "seguir donde lo dejaste".
   Antes era un tinte muy sutil (casi un .content-card con acento); ahora es
   la pieza más vistosa del dashboard, a propósito, porque es la única
   acción que un alumno necesita ver primero al entrar. */
.panel-hero-card {
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    border: none; border-radius: 22px; padding: 26px 28px; box-shadow: 0 16px 36px -8px rgba(var(--accent-rgb),.45);
    display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap;
    position: relative; overflow: hidden;
}
.panel-hero-card::before { content: ''; position: absolute; top: -50px; right: -30px; width: 170px; height: 170px; border-radius: 50%; background: rgba(255,255,255,.10); }
.panel-hero-card::after { content: ''; position: absolute; bottom: -60px; right: 90px; width: 120px; height: 120px; border-radius: 50%; background: rgba(255,255,255,.08); }
.panel-hero-card > * { position: relative; z-index: 1; }
/* .eyebrow ya existe como componente genérico (ver arriba, hero del sitio
   público) con fondo var(--panel-2) — acá hay que pisar TAMBIÉN fondo/borde,
   no solo el color de texto, si no el texto queda casi blanco sobre un
   fondo casi blanco (invisible). Mismo tratamiento translúcido que ya usa
   .hero-texto-claro .eyebrow para el mismo problema de contraste. */
.panel-hero-card .eyebrow {
    display: inline-flex; background: rgba(255,255,255,.18); border: 1px solid rgba(255,255,255,.3);
    padding: 4px 12px; border-radius: 999px; font-size: 11px; font-weight: 800;
    text-transform: uppercase; letter-spacing: .07em; color: #fff; margin: 0 0 10px;
}
.panel-hero-card h2 { margin: 0 0 8px; font-size: 19px; color: #fff; }
.panel-hero-card p { margin: 0; color: rgba(255,255,255,.88); font-size: 14px; }
.panel-hero-card .progreso-bar { max-width: 260px; margin-top: 12px; background: rgba(255,255,255,.28); }
.panel-hero-card .progreso-bar > div { background: #fff; }
.panel-hero-card .btn-primary { background: #fff; color: var(--accent); box-shadow: 0 8px 18px rgba(15,23,42,.18); }
.panel-hero-card .btn-primary:hover { box-shadow: 0 10px 22px rgba(15,23,42,.22); }
@media (max-width: 560px) { .panel-hero-card { padding: 22px 20px; } .panel-hero-card .btn-primary { width: 100%; } }

/* ---------- Tarjetas de estadísticas del dashboard del panel del cliente —
   deliberadamente NO reutilizan .stat (la del panel admin: barra de color
   arriba, número grande, nada más). Acá cada tarjeta lleva su propio ícono
   en una "chip" redondeada, mismo lenguaje que .panel-nav-link, y en
   móvil se vuelven una fila de scroll horizontal con snap — pensado para
   pulgar, no para mouse, ya que los alumnos entran sobre todo desde el
   teléfono (pedido explícito del usuario). */
.panel-stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; }
.panel-stat-card {
    background: var(--panel); border: 1px solid var(--border); border-radius: 18px; padding: 18px 18px 16px;
    box-shadow: var(--shadow-sm); transition: transform .18s ease, box-shadow .18s ease;
}
.panel-stat-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.panel-stat-card .ico {
    width: 38px; height: 38px; border-radius: 12px; display: flex; align-items: center; justify-content: center;
    background: rgba(var(--accent-rgb),.14); color: var(--stat-color, var(--accent)); margin-bottom: 12px;
}
.panel-stat-card .ico svg { width: 19px; height: 19px; }
.panel-stat-card .n { font-size: 25px; font-weight: 800; color: var(--text); line-height: 1; }
.panel-stat-card .label { color: var(--muted); font-size: 12.5px; margin-top: 6px; }
/* Siempre son exactamente 3 tarjetas (cursos/tareas/ensayos según el rol) —
   en vez de un carrusel de scroll horizontal con "peek" (la 3ª tarjeta se
   veía cortada de golpe, sin ninguna señal de que se podía deslizar, y se
   leía como algo roto en vez de adaptado), en móvil las 3 se achican y
   entran completas en una sola fila, sin recortes ni scroll. */
@media (max-width: 680px) {
    .panel-stat-row { grid-template-columns: repeat(3, 1fr); gap: 8px; }
    .panel-stat-card { padding: 12px 8px 10px; border-radius: 14px; text-align: center; }
    .panel-stat-card .ico { width: 28px; height: 28px; border-radius: 9px; margin: 0 auto 8px; }
    .panel-stat-card .ico svg { width: 14px; height: 14px; }
    .panel-stat-card .n { font-size: 19px; }
    .panel-stat-card .label { font-size: 10.5px; margin-top: 4px; line-height: 1.3; }
    .panel-stat-card:hover { transform: none; }
}

/* ---------- Lista de "Próximas clases" en formato agenda/timeline (fecha en
   una placa propia a la izquierda) — reemplaza a .eventos-list/.evento-item
   SOLO en las páginas del panel del cliente (inicio, clases en vivo); el
   dashboard del dueño (admin/escritorio.php) sigue usando el componente
   viejo tal cual, sin tocarlo. */
.panel-schedule-list { display: flex; flex-direction: column; gap: 10px; }
.panel-schedule-item {
    display: flex; align-items: center; gap: 14px; padding: 12px 14px;
    background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-sm);
    width: 100%; text-align: left; font: inherit; cursor: pointer; color: inherit; text-decoration: none;
    transition: border-color .15s ease, transform .15s ease;
}
.panel-schedule-item:hover { border-color: rgba(var(--accent-rgb),.35); transform: translateX(2px); }
.panel-schedule-date {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    width: 46px; height: 46px; border-radius: 13px; flex-shrink: 0;
    background: rgba(var(--accent-rgb),.12); color: var(--accent);
}
.panel-schedule-item.tipo-webinar .panel-schedule-date { background: rgba(var(--accent-2-rgb),.12); color: var(--accent-2); }
.panel-schedule-date .dia { font-size: 15px; font-weight: 800; line-height: 1.1; }
.panel-schedule-date .mes { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; }
.panel-schedule-item .info { flex: 1; min-width: 0; }
.panel-schedule-item .titulo-linea { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.panel-schedule-item .titulo { font-size: 14px; font-weight: 700; color: var(--text); }
.panel-schedule-item .meta { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.panel-schedule-item .chev { color: var(--muted); flex-shrink: 0; width: 16px; height: 16px; }
/* Variante con acción propia (ej. "Unirse ahora" en Clases en vivo): el
   ítem deja de ser él mismo el disparador y pasa a envolver un botón
   interno (.panel-schedule-trigger, abre el popover de preview) + una
   acción aparte que no debe activar ese popover al tocarla. */
.panel-schedule-trigger { display: flex; align-items: center; gap: 14px; flex: 1; min-width: 0; background: none; border: none; padding: 0; margin: 0; cursor: pointer; font: inherit; color: inherit; text-align: left; }
.panel-schedule-item .acciones { flex-shrink: 0; margin-left: 10px; }
/* Fila propia (bajo el título) cuando no entra "Unirse ahora" al lado del
   texto — mismo criterio que ya usa .activity-item para su columna .meta. */
@media (max-width: 480px) {
    .panel-schedule-item { flex-wrap: wrap; }
    .panel-schedule-trigger { flex-basis: 100%; }
    .panel-schedule-item .acciones { margin-left: 60px; }
}

/* ---------- Chip de plan/membresía SaaS (solo dueño) ---------- */
.plan-chip {
    display: flex; align-items: center; gap: 8px; padding: 7px 14px 7px 11px; border-radius: 999px;
    border: 1px solid var(--border); background: var(--panel-2); cursor: pointer; color: var(--text);
    font-size: 12.5px; font-weight: 700; white-space: nowrap; flex-shrink: 0;
    box-shadow: 0 2px 8px rgba(var(--accent-rgb),.10);
    transition: border-color .15s ease;
}
.plan-chip:hover { border-color: rgba(var(--accent-rgb),.4); }
.plan-chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.plan-chip.plan-warn .dot { background: var(--warn); }
.plan-chip.plan-danger .dot { background: var(--danger); animation: plan-pulse 1.8s ease-in-out infinite; }
@keyframes plan-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(var(--danger-rgb),.4); }
    50% { box-shadow: 0 0 0 5px rgba(var(--danger-rgb),0); }
}
.plan-chip .dias { color: var(--muted); font-weight: 600; }
@media (max-width: 720px) { .plan-chip .dias { display: none; } }
/* Se oculta el WRAPPER completo (.plan-chip-wrap), no solo el botón interno
   — si no, el <div> vacío seguía ocupando un lugar en el flex de
   .admin-topbar-actions (con su gap de ambos lados), dejando un hueco
   invisible entre el avatar y la campana. */
@media (max-width: 560px) { .plan-chip-wrap { display: none; } }

.plan-popover-body { padding: 4px 12px 12px; }
.plan-popover-body .fecha { font-size: 13px; color: var(--text); margin: 8px 0 12px; line-height: 1.5; }
.plan-popover-body a.soporte { display: inline-flex; align-items: center; gap: 6px; color: var(--accent); font-weight: 700; font-size: 13px; text-decoration: none; }
.plan-popover-body a.soporte:hover { text-decoration: underline; }

/* ---------- Encabezado de página + estados de contenido (badges) ---------- */
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 11px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.badge-publicado { background: rgba(var(--accent-rgb),.1); color: var(--accent); }
.badge-borrador { background: var(--warn-bg); color: var(--warn); }
.badge-archivado { background: var(--panel-2); color: var(--muted); }
.badge-rol { background: var(--panel-2); color: var(--muted); text-transform: capitalize; }
.badge-quiz { background: rgba(var(--accent-3-rgb),.1); color: var(--accent-3); }
.badge-tarea { background: rgba(var(--accent-2-rgb),.1); color: var(--accent-2); }
.badge-aprobado { background: rgba(var(--accent-rgb),.1); color: var(--accent); }
.badge-pendiente { background: var(--warn-bg); color: var(--warn); }
.badge-rechazado { background: var(--danger-bg); color: var(--danger); }
.badge-profesores { background: rgba(var(--accent-3-rgb),.1); color: var(--accent-3); }
.badge-alumnos { background: rgba(var(--accent-2-rgb),.1); color: var(--accent-2); }
.badge-ambos { background: rgba(var(--accent-rgb),.1); color: var(--accent); }

/* ---------- Revelado de contraseña generada (Ajustes → Equipo y alumnos) —
   una sola vez, en el modal de alta/restablecer, ver _ajustes_equipo.php ---------- */
.password-reveal-box {
    display: flex; align-items: center; gap: 10px; margin-top: 14px; padding: 12px 14px;
    background: var(--panel-2); border: 1px dashed var(--border); border-radius: var(--radius-sm);
}
.password-reveal-box code {
    flex: 1; font-family: 'Courier New', monospace; font-size: 16px; font-weight: 700;
    color: var(--text); letter-spacing: .04em; word-break: break-all;
}

/* ---------- Stat tiles (escritorio) ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; }
.stat { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px 22px; position: relative; overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .18s ease, box-shadow .18s ease; }
.stat:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.stat::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--stat-color, var(--accent)); }
.stat .n { font-size: 30px; font-weight: 800; color: var(--text); line-height: 1.1; }
.stat .label { color: var(--muted); font-size: 13px; margin-top: 6px; }
.stat-delta { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 700; margin-top: 8px; padding: 2px 9px; border-radius: 999px; }
.stat-delta.up { background: rgba(var(--accent-rgb),.12); color: var(--accent); }
.stat-delta.down { background: var(--danger-bg); color: var(--danger); }
.stat-delta.flat { background: var(--panel-2); color: var(--muted); }

/* En vez de colapsar a 1 sola columna (una tarjeta angosta ocupando todo el
   ancho, una abajo de la otra — lo que se veía "pobre" en móvil, mismo
   síntoma que .panel-stat-row ya había resuelto forzando N columnas en vez
   de dejar que el auto-fit colapse), .stat-grid fuerza una grilla de 2
   columnas real en móvil, con cada tarjeta compactada (menos padding, texto
   más chico) para que quepan cómodas — mismo criterio, tamaños propios
   porque .stat tiene números más largos (montos con moneda, ej. "USD
   44.90") que .panel-stat-card (solo conteos cortos). */
@media (max-width: 640px) {
    .stat-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .stat { padding: 14px 15px 13px; border-radius: 14px; }
    .stat:hover { transform: none; }
    .stat .n { font-size: 19px; }
    .stat .label { font-size: 11px; margin-top: 4px; line-height: 1.3; }
    .stat-delta { font-size: 10.5px; padding: 1px 8px; margin-top: 6px; }
}

/* ---------- Facturación: tarjetas de gráfica, línea de ingresos, donut,
   split cursos/membresías, paginación de la tabla de transacciones ----------
   Paleta categórica propia (NO reutiliza --accent/--accent-2/--accent-3, que
   cambian de tono entre tema claro/oscuro a propósito como identidad de
   marca) — estos 5 tonos + "Otros" se validaron con el validador de paletas
   del skill de dataviz (6 checks: banda de luminosidad, piso de croma,
   separación CVD adyacente ≥8, piso de visión normal ≥15, contraste ≥3:1) en
   AMBOS modos con los MISMOS valores — por eso no hace falta un bloque dark
   aparte para estas variables. */
:root {
    --fc-cat-1: #16a34a; --fc-cat-2: #0891b2; --fc-cat-3: #d97706;
    --fc-cat-4: #e11d48; --fc-cat-5: #7c3aed; --fc-cat-otros: #94a3b8;
}
.admin-shell[data-theme="dark"] { --fc-cat-5: #8b5cf6; }
.fc-export-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.chart-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px 24px; box-shadow: var(--shadow-sm); }
.chart-card-hero { margin-bottom: 20px; }
.chart-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 18px; flex-wrap: wrap; }
.chart-card-head h3 { margin: 0; font-size: 15px; color: var(--text); }
.chart-card-head p { margin: 2px 0 0; font-size: 12.5px; color: var(--muted); }
.chart-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 20px; margin-bottom: 24px; }

.fc-line-wrap { position: relative; }
.fc-svg { width: 100%; height: auto; display: block; overflow: visible; }
.fc-grid { stroke: var(--border); stroke-width: 1; }
.fc-axis-label { fill: var(--muted); font-size: 11px; }
.fc-crosshair { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
.fc-punto { fill: var(--panel); stroke: var(--accent); stroke-width: 2.5; pointer-events: none; }
.fc-overlay { cursor: crosshair; }
.fc-tooltip {
    position: absolute; top: 0; transform: translate(-50%, -6px); background: var(--text); color: var(--panel);
    padding: 6px 11px; border-radius: 8px; font-size: 12px; pointer-events: none; opacity: 0; transition: opacity .12s ease;
    white-space: nowrap; display: flex; flex-direction: column; gap: 1px; z-index: 5; box-shadow: var(--shadow-md);
}
.fc-tooltip strong { font-size: 13px; }
.fc-tooltip span { opacity: .75; font-size: 11px; }
.fc-tabla-detalle { margin-top: 14px; }
.fc-tabla-detalle summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--accent); }

.donut-wrap { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.donut-svg-wrap { position: relative; width: 152px; height: 152px; flex-shrink: 0; }
.donut-svg { width: 100%; height: 100%; }
.donut-seg { transition: stroke-width .15s ease; }
.donut-seg:hover { stroke-width: 27; }
.donut-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; pointer-events: none; }
.donut-center-n { font-size: 10.5px; color: var(--muted); font-weight: 700; letter-spacing: .03em; }
.donut-center-v { font-size: 17px; color: var(--text); font-weight: 800; }
.donut-legend { flex: 1; min-width: 190px; display: flex; flex-direction: column; gap: 11px; }
.donut-legend-row { display: flex; align-items: center; gap: 9px; font-size: 13.5px; }
.donut-legend-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; background: currentColor; }
.donut-legend-label { flex: 1; min-width: 0; color: var(--text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.donut-legend-value { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 12px; white-space: nowrap; }

.fc-cat-1 { color: var(--fc-cat-1); stroke: var(--fc-cat-1); background: var(--fc-cat-1); }
.fc-cat-2 { color: var(--fc-cat-2); stroke: var(--fc-cat-2); background: var(--fc-cat-2); }
.fc-cat-3 { color: var(--fc-cat-3); stroke: var(--fc-cat-3); background: var(--fc-cat-3); }
.fc-cat-4 { color: var(--fc-cat-4); stroke: var(--fc-cat-4); background: var(--fc-cat-4); }
.fc-cat-5 { color: var(--fc-cat-5); stroke: var(--fc-cat-5); background: var(--fc-cat-5); }
.fc-cat-otros { color: var(--fc-cat-otros); stroke: var(--fc-cat-otros); background: var(--fc-cat-otros); }

.split-bar { display: flex; height: 15px; border-radius: 999px; overflow: hidden; background: var(--panel-2); }
.split-bar > span { height: 100%; }
.split-legend { display: flex; gap: 18px; margin-top: 14px; flex-wrap: wrap; font-size: 13px; color: var(--text); }
.split-legend-item { display: flex; align-items: center; gap: 7px; }
.split-legend-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }

.fc-pagination { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 20px; }
.fc-pagination a { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 38px; padding: 0 14px; border-radius: var(--radius-sm); border: 1px solid var(--border); color: var(--text); text-decoration: none; font-size: 13.5px; font-weight: 600; }
.fc-pagination a:hover { background: var(--panel-2); border-color: rgba(var(--accent-rgb),.35); }
.fc-pagination a.deshabilitada { opacity: .4; pointer-events: none; }
.fc-pagination-info { font-size: 13px; color: var(--muted); }

@media (max-width: 640px) {
    .donut-wrap { justify-content: center; text-align: center; }
    .donut-legend-row { justify-content: center; }
}

/* Texto secundario para estados vacíos ("todavía no hay X") — ya se usaba
   en 11 archivos (facturacion.php, solicitudes.php, tareas.php, etc.) pero
   nunca se había definido; quedaba renderizando como texto normal sin la
   variante "muted/chica" que el nombre de la clase promete. */
.muted-sm { color: var(--muted); font-size: 13.5px; }

/* ---------- Escritorio: accesos rápidos, actividad reciente, ranking
   (admin/escritorio.php) ---------- */
.dashboard-section { margin-top: 28px; }
.dashboard-section-title { font-size: 13px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; margin: 0 0 12px; }

.quick-actions-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.quick-action-card {
    display: flex; align-items: center; gap: 14px; padding: 16px 18px; position: relative;
    background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow-sm); text-decoration: none; color: inherit;
    transition: transform .18s var(--ease-spring, ease), box-shadow .18s ease, border-color .18s ease;
}
.quick-action-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: rgba(var(--accent-rgb),.3); }
.quick-action-card .nav-ico { width: 42px; height: 42px; border-radius: 12px; }
.quick-action-card .nav-ico svg { width: 22px; height: 22px; }
.quick-action-card .txt { min-width: 0; }
.quick-action-card .titulo { font-size: 14.5px; font-weight: 700; color: var(--text); }
.quick-action-card .sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.quick-action-card .badge-count {
    position: absolute; top: 12px; right: 14px; min-width: 22px; height: 22px; padding: 0 6px;
    border-radius: 999px; background: var(--danger); color: #fff; font-size: 12px; font-weight: 800;
    display: flex; align-items: center; justify-content: center;
}

/* Dos columnas (actividad/pendientes + ranking/mis cursos), mismo patrón que .editor-layout */
.dashboard-split { display: grid; grid-template-columns: 1.6fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 960px) { .dashboard-split { grid-template-columns: 1fr; } }

.activity-list { display: flex; flex-direction: column; }
.activity-item { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-top: 1px solid var(--border); }
.activity-item:first-child { border-top: none; padding-top: 0; }
.activity-item .nav-ico { width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0; }
.activity-item .nav-ico svg { width: 17px; height: 17px; }
.activity-item .txt { flex: 1; min-width: 0; }
.activity-item .txt strong { color: var(--text); font-weight: 700; }
.activity-item .detalle { font-size: 13px; color: var(--muted); margin-top: 1px; }
.activity-item .meta { flex-shrink: 0; text-align: right; }
.activity-item .cuando { font-size: 12px; color: var(--muted); white-space: nowrap; }
@media (max-width: 480px) {
    .activity-item { flex-wrap: wrap; }
    .activity-item .meta { margin-left: 46px; text-align: left; }
}

/* ---------- Botones pequeños ok / no (aprobar / rechazar) ---------- */
.btn-ok { background: rgba(var(--accent-rgb),.1); color: var(--accent); }
.btn-ok:hover { background: rgba(var(--accent-rgb),.18); }
.btn-no { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); }
.btn-no:hover { background: var(--danger-bg); }

/* ---------- Tabla (→ tarjetas en móvil), igual patrón que master_panel ---------- */
.table-wrap { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); }
.table-wrap table { border-collapse: collapse; width: 100%; }
.table-wrap th, .table-wrap td { text-align: left; padding: 13px 18px; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.table-wrap thead th { color: var(--muted); font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; background: var(--panel-2); }
.table-wrap tbody tr:last-child td { border-bottom: none; }
.table-wrap tbody tr:hover { background: var(--panel-2); }

@media (max-width: 720px) {
    .table-wrap { overflow: visible; }
    .table-wrap table, .table-wrap thead, .table-wrap tbody, .table-wrap th, .table-wrap td, .table-wrap tr { display: block; }
    .table-wrap thead { display: none; }
    .table-wrap tbody tr { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 14px; padding: 4px 4px; }
    .table-wrap tbody tr:hover { background: var(--panel); }
    .table-wrap td { border-bottom: 1px solid var(--border); padding: 10px 14px; word-break: break-word; }
    .table-wrap tbody tr td:last-child { border-bottom: none; }
    .table-wrap td::before { content: attr(data-label); display: block; color: var(--muted); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; margin-bottom: 4px; }
    .table-wrap td[data-label=""]::before { content: none; margin: 0; }
}

/* ---------- Alternativa a tabla→tarjetas para listados con contenido
   "de post" (reseñas, anuncios): el patrón label+valor de arriba es
   perfecto para datos cortos (fechas, nombres, precios), pero se ve
   burocrático para una tarjeta con avatar/estrellas/párrafo de texto —
   ahí conviene una tarjeta de verdad en vez de una fila de tabla
   reetiquetada. `.table-wrap.con-tarjetas-movil` se oculta bajo el mismo
   breakpoint que ya usa `.table-wrap`, y `.tarjetas-movil` (mismos datos,
   HTML propio, `.content-card` de siempre) ocupa su lugar. ---------- */
.tarjetas-movil { display: none; flex-direction: column; gap: 14px; }
@media (max-width: 720px) {
    .table-wrap.con-tarjetas-movil { display: none; }
    .tarjetas-movil { display: flex; }
}

.anuncio-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.anuncio-card-top input[type=checkbox] { margin-top: 2px; flex-shrink: 0; }
.anuncio-card-titulo { margin: 8px 0 0; font-size: 15px; color: var(--text); }
.anuncio-card-acciones { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); text-align: right; }

.resena-card-header { display: flex; align-items: center; gap: 10px; }
.resena-card-header strong { display: block; font-size: 14px; color: var(--text); }
.resena-card-header .muted-sm { display: block; margin-top: 1px; }

/* ---------- Utilidad genérica ---------- */
.hidden { display: none !important; }

/* ---------- Árbol de contenido (módulos → lecciones) ---------- */
.mini-link { color: var(--accent); text-decoration: none; font-size: 13px; font-weight: 600; background: none; border: none; cursor: pointer; padding: 0; font-family: inherit; }
.mini-link:hover { text-decoration: underline; }
.mini-danger { background: none; border: none; color: var(--danger); cursor: pointer; font-size: 13px; font-weight: 600; padding: 0; }
.mini-danger:hover { text-decoration: underline; }

.curriculum { display: flex; flex-direction: column; gap: 20px; }

.modulo-card { padding: 22px 24px; }
.modulo-header { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.modulo-numero { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; background: rgba(var(--accent-rgb),.1); color: var(--accent); font-weight: 800; font-size: 14px; flex-shrink: 0; }
.modulo-titulo-wrap { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 160px; user-select: none; }
.modulo-titulo-wrap h2 { font-size: 16px; margin: 0; color: var(--text); }
.modulo-meta { font-size: 12px; color: var(--muted); background: var(--panel-2); border-radius: 999px; padding: 4px 12px; flex-shrink: 0; white-space: nowrap; }
.modulo-acciones { display: flex; align-items: center; gap: 14px; flex-shrink: 0; margin-left: auto; }

.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 7px; border: none; background: none; color: var(--muted); cursor: pointer; flex-shrink: 0; }
.icon-btn:hover { background: var(--panel-2); color: var(--accent); }
.icon-btn svg { width: 14px; height: 14px; }

.modulo-chevron svg { transition: transform .15s ease; }
.modulo-chevron.rotado svg { transform: rotate(-90deg); }

.inline-edit-row { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 220px; flex-wrap: wrap; }
.inline-edit-row input[type=text] { flex: 1; min-width: 160px; padding: 8px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-size: 14px; }
.inline-edit-hint { flex-basis: 100%; font-size: 12px; color: var(--muted); margin: 2px 0 0; }

/* Lista vertical: cada lección es una fila horizontal completa, una abajo de la otra (no grid de tarjetas). */
.lecciones-grid { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.leccion-card { background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px 16px; }
.leccion-card-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.leccion-tipo-icon { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 7px; flex-shrink: 0; background: var(--panel); color: var(--muted); }
.leccion-tipo-icon svg { width: 15px; height: 15px; }
.leccion-tipo-icon.tipo-quiz { background: rgba(var(--accent-3-rgb),.1); color: var(--accent-3); }
.leccion-tipo-icon.tipo-tarea { background: rgba(var(--accent-2-rgb),.1); color: var(--accent-2); }
.leccion-card .info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 160px; }
.leccion-card .titulo-linea { display: flex; align-items: center; gap: 6px; }
.leccion-card .titulo { font-size: 13.5px; font-weight: 700; color: var(--text); line-height: 1.4; }
.leccion-card .tipo-video { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.leccion-card .acciones { display: flex; align-items: center; gap: 14px; flex-shrink: 0; margin-left: auto; }
.leccion-card .inline-edit-row { min-width: 0; }
.leccion-card .inline-edit-row input[type=text] { font-size: 13px; padding: 7px 10px; }
@media (max-width: 640px) {
    .leccion-card .acciones { margin-left: 0; width: 100%; padding-top: 10px; border-top: 1px solid var(--border); }
}

.quick-add-row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.quick-add-btn { display: inline-flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 999px; border: 1px dashed var(--border); background: var(--panel); color: var(--text); font-size: 13px; font-weight: 600; text-decoration: none; }
.quick-add-btn:hover { border-color: var(--accent); color: var(--accent); background: rgba(var(--accent-rgb),.05); }

/* ---------- Monetización: grid 2 columnas arriba (modelo + PayPal) + tarjetas de métodos de pago ---------- */
.monetizacion-layout { display: flex; flex-direction: column; gap: 20px; }
.monetizacion-top-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 900px) { .monetizacion-top-grid { grid-template-columns: 1fr; } }

.metodos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; align-items: start; }
.metodo-card { background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.metodo-card.expandida { grid-column: 1 / -1; }
.metodo-card-vista { display: flex; flex-direction: column; gap: 12px; flex: 1; }
.metodo-card-head { display: flex; align-items: center; gap: 10px; }
.metodo-card-head .titulo-linea { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.metodo-card-head .titulo { font-size: 13.5px; font-weight: 700; color: var(--text); line-height: 1.4; }
.metodo-card-meta { font-size: 12px; color: var(--muted); line-height: 1.5; flex: 1; }
.metodo-card-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-top: 12px; border-top: 1px solid var(--border); margin-top: auto; }
.metodo-card-form { display: flex; flex-direction: column; gap: 10px; }
.metodo-card-form .campo-datos-row input { font-size: 13px; padding: 8px 10px; }

.metodo-card-add { border: 1.5px dashed var(--border); background: transparent; box-shadow: none; }
.metodo-card-add-teaser { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; min-height: 108px; cursor: pointer; color: var(--muted); font-weight: 600; font-size: 13.5px; text-align: center; background: none; border: none; width: 100%; padding: 0; font-family: inherit; }
.metodo-card-add-teaser:hover { color: var(--accent); }
.metodo-card-add-teaser svg { width: 22px; height: 22px; }
.metodo-card-add.expandida { border-style: solid; }

/* ---------- "Próximamente" (Clases en vivo, Ajustes) — placeholder honesto, sin funcionalidad real todavía ---------- */
/* Teaser compacto de "próximamente" para incrustar DENTRO de un dashboard
   (a diferencia de .proximamente-card, pensada para una página entera) —
   borde punteado para que se lea como "todavía no está activo", mismo
   criterio que ya usan .quick-add-btn/.metodo-card-add. */
.dashboard-teaser { display: flex; align-items: center; gap: 18px; padding: 20px 22px; background: var(--panel); border: 1.5px dashed var(--border); border-radius: var(--radius); }
.dashboard-teaser .nav-ico { width: 46px; height: 46px; border-radius: 14px; flex-shrink: 0; }
.dashboard-teaser .nav-ico svg { width: 23px; height: 23px; }
.dashboard-teaser .txt { flex: 1; min-width: 0; }
.dashboard-teaser .titulo-linea { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 3px; }
.dashboard-teaser .titulo { font-size: 15px; font-weight: 700; color: var(--text); }
.dashboard-teaser .sub { font-size: 13px; color: var(--muted); line-height: 1.5; }
@media (max-width: 560px) { .dashboard-teaser { flex-direction: column; text-align: center; } }

.proximamente-card { text-align: center; padding: 60px 30px; max-width: 480px; margin: 40px auto 0; }
.proximamente-ico { width: 56px; height: 56px; border-radius: 16px; background: rgba(var(--accent-rgb),.1); color: var(--accent); display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; }
.proximamente-ico svg { width: 26px; height: 26px; }
.proximamente-card h2 { font-size: 19px; margin: 0 0 10px; color: var(--text); }
.proximamente-card p { color: var(--muted); font-size: 14px; line-height: 1.6; margin: 0; }

/* ---------- Reportes: filas de barra horizontal (ventas por método de pago) ---------- */
.kpi-bar-row { display: flex; flex-direction: column; gap: 6px; }
.kpi-bar-row + .kpi-bar-row { margin-top: 14px; }
.kpi-bar-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 13.5px; }
.kpi-bar-head .nombre { font-weight: 700; color: var(--text); }
.kpi-bar-head .valor { color: var(--muted); font-variant-numeric: tabular-nums; }
.kpi-bar-track { height: 8px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
.kpi-bar-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--accent), var(--accent-2)); }

/* ---------- Clases en vivo: calendario mensual (admin) ---------- */
.calendario-nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.calendario-nav .nav-links { display: flex; align-items: center; gap: 8px; }
.calendario-nav .mes-actual { font-size: 17px; font-weight: 700; text-transform: capitalize; min-width: 160px; text-align: center; }
/* En móvil "← Anterior"/"Siguiente →" con su texto no entran en una sola
   fila junto a "Hoy" y el mes — se deja solo la flecha para que las 3
   piezas quepan sin envolver a una segunda línea. */
@media (max-width: 480px) {
    .btn-nav-mes .nav-mes-label { display: none; }
    .calendario-nav .mes-actual { min-width: 0; font-size: 15px; }
}

.calendario-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin-bottom: 8px; }
.calendario-dow { text-align: center; font-size: 12px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; padding-bottom: 4px; }
.calendario-dia { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 8px; min-height: 96px; display: flex; flex-direction: column; gap: 4px; min-width: 0; } /* si no, un evento con título largo fuerza esa columna del grid a ensancharse (mismo motivo que .field-grid > *) */
.calendario-dia.fuera-mes { opacity: .45; }
.calendario-dia.hoy { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.calendario-dia .num-dia { font-size: 13px; font-weight: 700; color: var(--text); }
.calendario-dia.fuera-mes .num-dia { color: var(--muted); font-weight: 500; }
.pills-dia { display: flex; flex-direction: column; gap: 3px; }

.evento-pill { display: block; font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-decoration: none; }
a.evento-pill:hover { filter: brightness(0.92); }
.evento-pill.tipo-clase { background: rgba(220,38,38,.12); color: #dc2626; }
.evento-pill.tipo-webinar { background: rgba(8,145,178,.12); color: #0891b2; }
.evento-pill.cancelado { opacity: .55; text-decoration: line-through; }
.evento-pill-mas { font-size: 11px; color: var(--muted); font-weight: 600; padding: 2px 4px; }
.admin-shell[data-theme="dark"] .evento-pill.tipo-clase { background: rgba(248,113,113,.18); color: #f87171; }
.admin-shell[data-theme="dark"] .evento-pill.tipo-webinar { background: rgba(34,211,238,.18); color: #22d3ee; }

.dots-dia { display: none; }
/* El punto en sí es chico (7px) para no saturar la celda, pero el botón
   que lo envuelve tiene relleno propio — así el área tocable real es más
   grande que el punto visible (importa en móvil, donde el punto es el
   ÚNICO disparador visible del popover, ya que .pills-dia se oculta). */
.evento-dot-btn { background: none; border: none; padding: 5px; margin: 0; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.evento-dot { width: 7px; height: 7px; border-radius: 50%; }
.evento-dot.tipo-clase { background: #dc2626; }
.evento-dot.tipo-webinar { background: #0891b2; }
.admin-shell[data-theme="dark"] .evento-dot.tipo-clase { background: #f87171; }
.admin-shell[data-theme="dark"] .evento-dot.tipo-webinar { background: #22d3ee; }

@media (max-width: 640px) {
    .calendario-grid { gap: 4px; }
    .calendario-dia { min-height: 48px; padding: 6px 3px; align-items: center; }
    .calendario-dia .num-dia { font-size: 12px; }
    .pills-dia { display: none; }
    .dots-dia { display: flex; gap: 3px; flex-wrap: wrap; justify-content: center; margin-top: 2px; }
}

/* ---------- Clases en vivo: lista de eventos (admin + alumno) ---------- */
.eventos-list { display: flex; flex-direction: column; gap: 10px; }
.evento-item { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel); flex-wrap: wrap; }
.evento-item.cancelado { opacity: .6; }
.evento-item .info { flex: 1; min-width: 160px; }
.evento-item .titulo-linea { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 2px; }
.evento-item .titulo { font-weight: 700; font-size: 14.5px; color: var(--text); }
.evento-item .meta { font-size: 13px; color: var(--muted); }
.evento-item .acciones { display: flex; align-items: center; gap: 12px; margin-left: auto; flex-wrap: wrap; }

/* Botón (pill del calendario o fila del alumno) que dispara el popover de
   preview — reset de los estilos nativos de <button>, el resto de la
   apariencia la heredan de .evento-pill / .evento-item .info ya existentes. */
button.evento-pill { border: none; width: 100%; text-align: left; cursor: pointer; font-family: inherit; }
.evento-item-trigger {
    display: flex; align-items: flex-start; gap: 12px; flex: 1; min-width: 160px;
    background: none; border: none; padding: 0; margin: 0; font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.evento-item-trigger .info { flex: 1; min-width: 0; }

/* ---------- Clases en vivo: popover de preview (imagen/video + datos) al
   pasar el mouse (desktop) o tocar (mobile) un evento — mismo componente
   reutilizado en el calendario del admin y en la lista del alumno.
   Posicionado por JS (site.js) cerca del disparador, dentro del viewport. ---------- */
.evento-popover {
    display: none; position: fixed; z-index: 200; width: 300px; max-width: calc(100vw - 20px);
    background: var(--panel); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-lg, 0 20px 45px rgba(0,0,0,.18));
    overflow: hidden;
}
.evento-popover.visible { display: block; }
.evento-popover-cerrar {
    position: absolute; top: 8px; right: 8px; z-index: 1; width: 26px; height: 26px; border-radius: 50%;
    background: rgba(15,23,42,.55); color: #fff; border: none; font-size: 13px; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.evento-popover-media { position: relative; width: 100%; aspect-ratio: 16 / 9; background: var(--panel-2); overflow: hidden; }
.evento-popover-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.evento-popover-media-generico { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--accent), var(--accent-2)); }
.evento-popover-play {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 46px; height: 46px; border-radius: 50%; background: rgba(15,23,42,.55); color: #fff;
    display: flex; align-items: center; justify-content: center;
}
.evento-popover-play svg { width: 20px; height: 20px; }
.evento-popover-body { display: flex; align-items: flex-start; gap: 10px; padding: 14px; }
.evento-popover-info { flex: 1; min-width: 0; }
.evento-popover-titulo { font-weight: 700; font-size: 14.5px; color: var(--text); margin-bottom: 2px; }
.evento-popover-meta { font-size: 12.5px; color: var(--muted); }
.evento-popover-desc { font-size: 13px; color: var(--text); margin: 8px 0 0; line-height: 1.5; }
.evento-popover-acciones { margin-top: 10px; }

/* ---------- Clases en vivo: form de alta/edición en grid de 2 columnas
   (en vez de un formulario angosto de 640px con mucho espacio vacío al
   costado) — "Tipo de evento"/"Curso" van lado a lado (fila 1), el resto
   de tarjetas ocupan todo el ancho con .full. ---------- */
.evento-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.evento-form-grid .form-section { margin-bottom: 0; } /* el gap del grid ya separa las tarjetas */
.evento-form-grid .full { grid-column: 1 / -1; }
.evento-form-grid button[type=submit] { grid-column: 1 / -1; justify-self: start; }
@media (max-width: 900px) {
    .evento-form-grid { grid-template-columns: 1fr; }
    .evento-form-grid button[type=submit] { justify-self: stretch; }
}

/* Utilidad puntual: un botón de acción principal que en móvil debe verse
   a todo el ancho (nunca cortado por el borde de la pantalla). */
@media (max-width: 640px) { .btn-block-mobile { width: 100%; } }
/* .btn-block-mobile por sí solo no alcanza si el botón vive dentro de un
   <form> (ítem flex de .page-head): un flex item no se estira a todo el
   ancho de su fila por default, así que el width:100% del botón solo
   terminaba llenando el ancho ya angosto del form. Este wrapper fuerza al
   propio form a ocupar toda la fila en móvil (admin/temas.php → botón
   "Restablecer valores por defecto"). */
@media (max-width: 640px) { .btn-block-mobile-wrap { width: 100%; } }

/* ---------- Página personalizada (contenido HTML básico escrito por el dueño) ---------- */
.pagina-contenido { color: var(--text); font-size: 15.5px; line-height: 1.75; }
.pagina-contenido p { margin: 0 0 16px; }
.pagina-contenido h2 { font-size: 22px; margin: 32px 0 14px; color: var(--text); }
.pagina-contenido h3 { font-size: 18px; margin: 26px 0 12px; color: var(--text); }
.pagina-contenido ul, .pagina-contenido ol { margin: 0 0 16px; padding-left: 22px; }
.pagina-contenido li { margin-bottom: 6px; }
.pagina-contenido a { color: var(--accent); }
.pagina-contenido strong { color: var(--text); }

/* ---------- Preview en vivo de admin/temas.php ---------- */
/* Preview real de admin/temas.php — un <iframe> del sitio de verdad (no un mockup
   dibujado a mano) escalado con transform:scale(), truco clásico de "thumbnail de
   página web": el iframe se renderiza a un ancho de escritorio real (title=333%) y
   se encoge visualmente a como si midiera 100% del panel. Así el preview siempre es
   pixel-exacto — no hay que mantener una segunda copia de las reglas de header/hero/
   footer solo para la vista previa. */
.tema-preview-frame { position: relative; width: 100%; aspect-ratio: 3 / 4; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: #fff; box-shadow: var(--shadow-md); margin: 0 auto; }
/* El ancho/alto/escala reales del iframe los calcula JS (ajustarEscalaPreview() en
   temas.php) según el ancho REAL del contenedor — no hay forma de hacer "ancho del
   contenedor ÷ ancho del dispositivo" en CSS puro. Los valores de acá son solo el
   fallback antes de que corra el JS (equivalen al dispositivo "desktop" por default). */
.tema-preview-frame iframe { position: absolute; top: 0; left: 0; width: 333.34%; height: 333.34%; border: none; transform: scale(.3); transform-origin: top left; }
.tema-preview-frame[data-device="tablet"] { max-width: 340px; }
.tema-preview-frame[data-device="mobile"] { aspect-ratio: 9 / 17; max-width: 220px; }
.tema-preview-frame.cargando::after {
    content: 'Actualizando...'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    background: rgba(255,255,255,.85); color: var(--muted); font-size: 12.5px; font-weight: 600;
}

/* ---------- Selector de dispositivo del preview (admin/temas.php) ---------- */
.preview-device-picker { display: flex; gap: 4px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 3px; margin-bottom: 10px; }
.preview-device-btn {
    flex: 1; display: flex; align-items: center; justify-content: center; gap: 5px;
    padding: 7px 4px; border: none; background: none; border-radius: 999px;
    color: var(--muted); font-size: 12px; font-weight: 700; cursor: pointer;
    transition: background .15s ease, color .15s ease;
}
.preview-device-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
.preview-device-btn:hover { color: var(--text); }
.preview-device-btn.activo { background: var(--panel); color: var(--text); box-shadow: var(--shadow-sm); }
@media (max-width: 480px) {
    .preview-device-btn span { display: none; } /* solo el ícono si el sidebar queda muy angosto */
}

/* .dropzone-wrap envuelve el <label class="dropzone"> Y el botón "Quitar" como HERMANOS,
   a propósito — un <label> con dos elementos "labelable" adentro (un <button> y el
   <input type=file> de la dropzone) es un caso ambiguo del spec de HTML: en Chrome, clicks
   dentro del label a veces terminan dirigidos al <button> en vez de abrir el selector de
   archivos, sin ningún error visible (bug real encontrado con Playwright — un click "de
   verdad", no `setInputFiles()`, nunca disparaba el diálogo nativo). Sacar el botón del
   label y reposicionarlo como hermano absoluto lo resuelve de raíz. */
.dropzone-wrap { position: relative; max-width: 460px; margin: 0 auto; }
.dropzone-wrap .dropzone { max-width: none; margin: 0; }
.dropzone-remove {
    position: absolute; top: 10px; right: 10px; z-index: 2;
    display: inline-flex; align-items: center; gap: 4px; padding: 5px 11px; border-radius: 999px;
    border: 1px solid var(--danger-border); background: var(--panel); color: var(--danger);
    font-size: 12px; font-weight: 700; cursor: pointer; box-shadow: var(--shadow-sm);
}
.dropzone-remove:hover { background: var(--danger-bg); }

/* ---------- Selector de "Estructura del sitio" (admin/temas.php) ---------- */
.estructura-picker { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; }
.estructura-opcion {
    position: relative; border: 2px solid var(--border); border-radius: var(--radius-sm); padding: 14px;
    cursor: pointer; display: flex; flex-direction: column; gap: 12px;
    transition: border-color .15s ease, background .15s ease;
}
.estructura-opcion input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.estructura-opcion.seleccionada { border-color: var(--accent); background: rgba(var(--accent-rgb),.05); }
.estructura-opcion:hover { border-color: rgba(var(--accent-rgb),.4); }

.estructura-mockup { background: var(--panel-2); border-radius: 8px; padding: 9px; display: flex; flex-direction: column; gap: 6px; height: 90px; }
.mm-bar { display: flex; align-items: center; gap: 5px; height: 7px; }
.mm-logo { width: 10px; height: 7px; border-radius: 2px; background: var(--accent); flex-shrink: 0; }
.mm-nav { height: 4px; border-radius: 2px; background: var(--border); margin-left: auto; width: 26px; }
.mm-nav-mini { width: 16px; height: 4px; border-radius: 2px; background: var(--border); }

.mm-hero { height: 28px; border-radius: 5px; background: linear-gradient(135deg, rgba(var(--accent-rgb),.28), rgba(var(--accent-2-rgb),.24)); }
.mm-grid { display: flex; gap: 4px; flex: 1; }
.mm-grid span { flex: 1; border-radius: 4px; background: #fff; border: 1px solid var(--border); }
.mm-foot { height: 5px; border-radius: 2px; background: var(--border); width: 40%; }

.mm-bar-dividida { justify-content: space-between; }
.mm-hero-split { display: flex; gap: 4px; height: 28px; }
.mm-hero-split span { flex: 1; border-radius: 5px; }
.mm-hero-split span:first-child { background: var(--panel); border: 1px dashed var(--border); }
.mm-hero-split span:last-child { background: linear-gradient(135deg, rgba(var(--accent-rgb),.28), rgba(var(--accent-2-rgb),.24)); }
.mm-filas { display: flex; flex-direction: column; gap: 4px; flex: 1; }
.mm-filas span { border-radius: 4px; background: #fff; border: 1px solid var(--border); }
.mm-foot-ancho { width: 100%; height: 9px; }

.mm-hero-min { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; height: 28px; }
.mm-hero-min span { height: 4px; border-radius: 2px; background: var(--border); }
.mm-hero-min span:first-child { width: 55%; background: var(--accent); opacity: .55; }
.mm-hero-min span:last-child { width: 32%; }
.mm-lista { display: flex; flex-direction: column; gap: 6px; flex: 1; justify-content: center; }
.mm-lista-fila { display: flex; align-items: center; gap: 5px; }
.mm-lista-thumb { width: 9px; height: 9px; border-radius: 2px; flex-shrink: 0; background: linear-gradient(135deg, var(--accent), var(--accent-2)); }
.mm-lista-linea { height: 3px; border-radius: 2px; background: var(--border); flex: 1; }
.mm-foot-centro { width: 30%; margin: 0 auto; }

.estructura-info strong { display: block; font-size: 13.5px; color: var(--text); margin-bottom: 3px; }
.estructura-info p { font-size: 11.5px; color: var(--muted); margin: 0; line-height: 1.4; }

/* Pickers de Header/Footer por separado (a diferencia de "Contenido", que sí necesita
   mostrar hero+grid juntos): mockup más bajo, solo la franja relevante de esa zona. */
.estructura-mockup-chico { height: 40px; justify-content: center; }
.mm-bar-min { justify-content: flex-start; }
.mm-foot-columnas { display: flex; gap: 6px; flex: 1; align-items: flex-end; }
.mm-foot-columnas span { flex: 1; border-radius: 3px; background: var(--border); }
.mm-foot-columnas span:nth-child(1) { height: 16px; }
.mm-foot-columnas span:nth-child(2) { height: 24px; }
.mm-foot-columnas span:nth-child(3) { height: 20px; }
.quick-add-btn svg { width: 14px; height: 14px; }

/* ---------- Miniaturas de las 3 estructuras NUEVAS por zona (admin/temas.php) ---------- */
/* Header "destacada": logo solo arriba + franja de nav debajo */
.mm-bar-strip { background: var(--panel); border-radius: 3px; padding: 2px 6px; justify-content: center; gap: 6px; }
/* Header "compacta": nav en píldora */
.mm-pill { display: inline-flex; gap: 3px; background: var(--panel); border-radius: 999px; padding: 3px 6px; }
.mm-pill span { width: 5px; height: 4px; border-radius: 2px; background: var(--border); }
/* Header "editorial": franja de anuncio arriba de la barra */
.mm-strip-anuncio { height: 5px; border-radius: 2px; background: var(--accent); opacity: .7; width: 100%; }

/* Contenido "destacada": slider de 3 columnas con flechas */
.mm-slider { display: flex; align-items: stretch; gap: 4px; flex: 1; }
.mm-slider-flecha { display: flex; align-items: center; font-size: 11px; color: var(--muted); flex-shrink: 0; }
.mm-slider > span:not(.mm-slider-flecha) { flex: 1; border-radius: 4px; background: #fff; border: 1px solid var(--border); }
/* Contenido "editorial": barra de estadísticas + lista numerada */
.mm-stats-bar { display: flex; gap: 8px; height: 28px; align-items: center; }
.mm-stats-bar span { flex: 1; height: 6px; border-radius: 2px; background: var(--border); }
.mm-numerada { display: flex; flex-direction: column; gap: 6px; flex: 1; justify-content: center; }
.mm-numerada-fila { display: flex; align-items: center; gap: 6px; }
.mm-numerada-fila i { font-style: normal; font-size: 9px; font-weight: 800; color: rgba(var(--accent-rgb),.5); width: 13px; flex-shrink: 0; }
.mm-numerada-fila b { flex: 1; height: 5px; border-radius: 2px; background: var(--border); font-weight: normal; }

/* Footer "destacada": franja de CTA arriba de la línea */
.mm-foot-cta { height: 10px; border-radius: 3px; width: 90%; margin: 0 auto; background: linear-gradient(135deg, rgba(var(--accent-rgb),.35), rgba(var(--accent-2-rgb),.22)); }
/* Footer "compacta": 2 columnas asimétricas */
.mm-foot-compacta { display: flex; gap: 6px; flex: 1; align-items: flex-end; }
.mm-foot-compacta span { border-radius: 3px; background: var(--border); height: 18px; }
.mm-foot-compacta .col-grande { flex: 1.6; }
.mm-foot-compacta .col-chica { flex: 1; }
/* Footer "editorial": todo centrado, apilado */
.mm-foot-editorial { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 1; justify-content: center; }
.mm-foot-editorial span:first-child { width: 34%; height: 5px; border-radius: 2px; background: var(--border); }
.mm-foot-editorial span:last-child { width: 50%; height: 4px; border-radius: 2px; background: var(--border); opacity: .6; }

/* ---------- "Temas" (presets rápidos, admin/temas.php) ---------- */
.tema-preset-picker { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; }
.tema-preset-opcion {
    border: 2px solid var(--border); border-radius: var(--radius-sm); padding: 14px;
    display: flex; flex-direction: column; gap: 12px; transition: border-color .15s ease, background .15s ease;
}
.tema-preset-opcion.seleccionada { border-color: var(--accent); background: rgba(var(--accent-rgb),.05); }
.tema-preset-mockup { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; height: 96px; display: flex; flex-direction: column; }
.tpm-header { height: 20px; flex-shrink: 0; display: flex; align-items: center; padding: 0 8px; border-bottom: 2px solid; }
.tpm-header span { width: 16px; height: 5px; border-radius: 2px; }
.tpm-hero { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; }
.tpm-hero span:first-child { width: 50%; height: 5px; border-radius: 2px; }
.tpm-hero span:last-child { width: 28%; height: 8px; border-radius: 4px; }
.tpm-footer { height: 14px; flex-shrink: 0; }
.tema-preset-opcion .btn { width: 100%; }

/* ---------- Colores por zona (admin/temas.php, dentro de _temas_color_zona.php):
   4 swatches (fondo/texto/acento/borde) bajo un solo switch por zona. ---------- */
.zona-colores-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 14px; margin-top: 12px; }
.zona-color-campo-label { display: block; font-size: 12px; font-weight: 700; color: var(--muted); margin-bottom: 6px; }

/* ---------- Recurso descargable (formulario de lección) ---------- */
.recurso-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; font-size: 13.5px; padding: 8px 0; border-top: 1px solid var(--border); flex-wrap: wrap; }

/* ---------- Página de error standalone (403 / 409) ---------- */
.error-page { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--bg); }
.error-page .content-card { text-align: center; max-width: 420px; }
.error-page h1 { color: var(--danger); font-size: 20px; margin: 0 0 10px; }
.error-page p { color: var(--muted); font-size: 14px; margin-bottom: 16px; }
