/* =============================================================================
   empleos.css — sistema visual de Litsea Empleos
   -----------------------------------------------------------------------------
   Tokens y medidas portados de Litsea-Empleos/docs/auth-panel-design.md y de
   los design tokens de docs/01-arquitectura.md, para que la versión PHP se vea
   igual que la de Next.js.

   Un solo archivo a propósito: son ~30 componentes en total, y repartirlos en
   parciales obligaría a un compilador que aquí no existe.
   ========================================================================== */

:root {
	--litsea-primary:       #2fb7a4;
	--litsea-primary-dark:  #239688;
	--litsea-accent-gold:   #c9a24d;

	--text-main:    #4a4a4a;
	--text-dark:    #1a1a1a;
	--text-muted:   #8a8a8a;

	--input-border: #e5e7eb;
	--input-bg:     #f9fafb;

	/*
	 * Superficies del panel.
	 *
	 * Existen para que el modo oscuro sea UN bloque de tokens (css/tema.css) y
	 * no 25 anulaciones repartidas por esta hoja. En claro valen exactamente el
	 * `#fff` y el `#f4f5f6` que estaban escritos a pelo, así que introducirlos
	 * no cambió un píxel — se puede comprobar con el `.bak` del commit.
	 *
	 * ⚠️ `--superficie` es «el fondo de una pieza», no «blanco». Los 26
	 * `color: #fff` de la hoja NO se tocaron y no deben tocarse: ésos van sobre
	 * un relleno de color —botón teal, héroe, pie oscuro— y ahí el blanco sigue
	 * siendo correcto en los dos temas. Confundir las dos cosas es cómo un botón
	 * acaba con texto casi invisible en oscuro.
	 */
	--superficie:   #fff;      /* tarjetas, tablas, campos, carril, barra */
	--fondo:        #f4f5f6;   /* el gris de detrás de la tarjeta */

	/*
	 *  🔴 Los tres `--*-bg` son restos: el 20/8/2026 se quitaron las cajas
	 * pastel de toda la interfaz por decisión del cliente (ver el comentario de
	 * `.alert`). El único que sigue vivo es `--error-bg` en el hover de salir,
	 * que es un realce de ratón y no un aviso. **No reintroducirlos como fondo
	 * de un mensaje**: el estado se dice con color de texto, punto o regla.
	 */
	--error-bg:     #fff2f2;
	--error-border: #fecaca;
	--error-text:   #b91c1c;

	--ok-bg:        #f0fdf9;
	--ok-border:    #a7f3d0;
	--ok-text:      #0f766e;

	/*
	 * Ancho de la barra del menú lateral. Se usa en dos sitios que tienen que
	 * decir lo mismo: el `::-webkit-scrollbar` que la dibuja y el respaldo de
	 * `scrollbar-gutter` para navegadores que no lo soportan. Separarlos era
	 * pedir que un día dejaran de cuadrar.
	 */
	--emp-scroll: 8px;

	--warn-bg:      #fffbeb;
	--warn-border:  #fde68a;
	--warn-text:    #92400e;

	--radius-panel: 20px;
	--panel-gap:    16px;
}

*, *::before, *::after {
	font-family: Poppins, system-ui, -apple-system, sans-serif;
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}

html, body { height: 100%; background: var(--superficie); color: var(--text-main); }

/* ── Armazón de dos paneles ──────────────────────────────────────────────── */

.login-wrapper {
	display: flex;
	min-height: 100vh;
	padding: var(--panel-gap);
	gap: var(--panel-gap);
	align-items: stretch;
}

.panel-left {
	position: relative;
	width: 70%;
	border-radius: var(--radius-panel);
	overflow: hidden;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	flex-shrink: 0;
	background: #071210;   /* por si el vídeo tarda o no carga */
}

@media (max-width: 1480px) { .panel-left { width: 65%; } }
@media (max-width: 1280px) { .panel-left { width: 60%; } }
@media (max-width: 1180px) { .panel-left { width: 55%; } }

.panel-left video,
.panel-left img.fondo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * Velo de legibilidad sobre el vídeo. Plano, NO degradado: la regla del
 * proyecto es cero gradientes. Un tinte uniforme al 62% deja el texto blanco
 * legible en cualquier fotograma, que es lo que el degradado hacía solo en la
 * franja inferior.
 */
.panel-left::after {
	content: '';
	position: absolute;
	inset: 0;
	background: rgba(0,0,0,.62);
}

.panel-left-logo { position: absolute; z-index: 2; top: 28px; left: 32px; }
.panel-left-logo img { height: 40px; width: auto; }

.panel-left-content { position: relative; z-index: 2; padding: 40px 36px; }

.badge-sep {
	display: inline-flex; align-items: center; gap: 8px;
	background: rgba(47,183,164,.18);
	border: 1px solid rgba(47,183,164,.40);
	border-radius: 100px; padding: 5px 14px; margin-bottom: 18px;
}
.badge-sep .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--litsea-primary); }
.badge-sep span { font-size: 11px; font-weight: 600; color: var(--litsea-primary);
	letter-spacing: .07em; text-transform: uppercase; }

.panel-left-content h1 {
	font-size: clamp(24px, 2.6vw, 36px);
	font-weight: 700; color: #fff; line-height: 1.25; margin-bottom: 12px;
}
/* <strong> es lo que usa el login de la escuela; <em> se conserva por si
   alguna pantalla ya lo trae. Los dos pintan igual.
 *
 * En blanco, no en teal (9/8/2026). Es la tercera regla dura de D16: el teal
 * marca el ítem activo y el avatar, no es el color del armazón. Sobre el vídeo
 * oscuro, además, el teal a 36px pierde contraste; el blanco lo tiene entero.
 * La segunda línea se distingue por el salto y el peso, que ya bastan. */
.panel-left-content h1 strong,
.panel-left-content h1 em { font-style: normal; font-weight: 700; color: #fff; }
.panel-left-content p { font-size: 13.5px; color: #fff; line-height: 1.7; max-width: 360px; }

.panel-right {
	width: 50%;
	display: flex; align-items: center; justify-content: center;
	background: var(--superficie); border-radius: var(--radius-panel); padding: 40px 24px;
}

.login-card { width: 100%; max-width: 400px; }

/* Variante ancha, sólo para el alta de terapeuta (20/8/2026). Ahí se piden los
   siete datos obligatorios antes de crear la cuenta —decisión del cliente— y
   en 400px las casillas de especialidades y zonas salen en una columna que no
   se acaba nunca.

   ⚠️ El sitio lo cede el panel IZQUIERDO, y por eso la clase va en
   `.login-wrapper` y no en `.panel-right`. El reparto real no es mitad y mitad:
   `.panel-left` mide 70% con `flex-shrink: 0` y el derecho se queda con lo que
   sobra. Ensanchar el derecho no habría hecho nada, y CSS no puede seleccionar
   un hermano anterior. El izquierdo es decorativo —un vídeo— y las consultas de
   móvil de más abajo ya lo esconden entero. */
.login-wrapper--ancho .panel-left { width: 42%; }
.login-wrapper--ancho .login-card { max-width: 620px; }

@media (max-width: 1280px) { .login-wrapper--ancho .panel-left { width: 34%; } }
@media (max-width: 1100px) { .login-wrapper--ancho .panel-left { display: none; } }
.login-card-header { margin-bottom: 28px; }

.eyebrow {
	font-size: 11px; font-weight: 600; letter-spacing: .1em;
	text-transform: uppercase; color: var(--litsea-primary); margin-bottom: 6px;
}
.login-card-header h2 { font-size: 26px; font-weight: 700; color: var(--text-main); margin-bottom: 6px; }
.login-card-header p  { font-size: 13.5px; color: var(--text-muted); line-height: 1.55; }

.mobile-logo { display: none; justify-content: center; margin-bottom: 28px; }
.mobile-logo img { height: 38px; width: auto; }

/* ── Avisos ──────────────────────────────────────────────────────────────── */

/* 🔴 `display:flex` aquí es para `emp_alerta()`, que emite DOS hijos: el icono y
   un <div> con el texto. Si escribes una alerta a mano, su contenido tiene que ir
   igualmente dentro de UN solo elemento.

   El motivo no es de estilo: en un contenedor flex, **cada nodo de texto suelto se
   convierte en un ítem anónimo**. Un aviso escrito así —

       <div class="alert alert-warning">
           ¿Estudiaste en Litsea? <a href="…">entra aquí</a> y activa tu perfil.
       </div>

   — tiene TRES hijos (texto, <a>, texto) y se pinta en tres columnas estrechas,
   cada una partiendo palabras por su cuenta. Pasó en `registro-terapeuta.php` y en
   `terapeuta/vacantes.php`; corregido el 19/8/2026 envolviendo el contenido, y de
   paso se le dio la misma forma a las otras cuatro alertas escritas a mano, que
   funcionaban sólo porque tenían un único hijo. */
/* 🔴 SIN FONDO DE COLOR, A PROPÓSITO (20/8/2026)

   Hasta hoy cada alerta era una tarjeta pastel: fondo tintado, borde de 1px y
   `border-radius`. El cliente lo rechazó viéndolo en pantalla —«no me gusta
   nada ese estilo, nada AI made»— y pidió quitarlo de toda la app, de Empleos,
   del sitio y de los correos.

   No es sólo gusto. Es el mismo camino que tomó el sitio de marketing el 17/8:
   fuera sombras, fuera degradados, tarjetas sólo con un borde de 1px. Y la
   caja pastel además compite con la tarjeta que la contiene: dos rectángulos
   redondeados, uno dentro del otro, cada uno con su relleno.

   Lo que queda: una regla vertical de 2px con el color del estado, el icono en
   ese mismo color y el título en negrita. La severidad se lee igual —son tres
   colores distintos en el borde y en el título— sin pintar el fondo.

   El detalle va en `--text-main` y no en el color del estado: es texto para
   leer, y el rojo o el ámbar sobre blanco cansan en un párrafo. El color se
   reserva para lo que tiene que saltar. */
.alert {
	border-left: 2px solid var(--input-border);
	padding: 1px 0 1px 12px; margin-bottom: 20px;
	font-size: 13px; line-height: 1.5; color: var(--text-main);
	display: flex; align-items: flex-start; gap: 10px;
}
.alert svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 2px; }
.alert-danger  svg { stroke: var(--error-text); }
.alert-warning svg { stroke: var(--warn-text); }
.alert-ok      svg { stroke: var(--ok-text); }
.alert-danger  strong { color: var(--error-text); }
.alert-warning strong { color: var(--warn-text); }
.alert-ok      strong { color: var(--ok-text); }
.alert-danger  { border-left-color: var(--error-text); }
.alert-warning { border-left-color: var(--warn-text); }
.alert-ok      { border-left-color: var(--ok-text); }

/* ── Formularios ─────────────────────────────────────────────────────────── */

.form-group { margin-bottom: 14px; }
.form-group label {
	display: block; font-size: 13px; font-weight: 500;
	color: var(--text-main); margin-bottom: 6px;
}

.input-wrap { position: relative; }

/* Icono a la izquierda del campo. El hueco lo abre el selector de hermano de
   abajo, así los campos sin icono conservan su padding normal. */
.input-wrap .icon {
	position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
	display: flex; align-items: center; pointer-events: none;
}
.input-wrap .icon svg { width: 16px; height: 16px; stroke: #c0c0c0; }
.input-wrap .icon ~ .form-control { padding-left: 40px; }

.form-control {
	width: 100%;
	padding: 11px 14px;
	border: 1.5px solid var(--input-border);
	border-radius: 10px;
	background: var(--input-bg);
	font-size: 13.5px; color: var(--text-main);
	transition: border-color .2s, box-shadow .2s, background .2s;
	outline: none;
}
.form-control::placeholder { color: #c0c0c0; }
.form-control:focus {
	border-color: var(--litsea-primary);
	box-shadow: 0 0 0 3px rgba(47,183,164,.15);
	background: var(--superficie);
}

.toggle-pass {
	position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
	background: none; border: none; cursor: pointer; padding: 4px;
	display: flex; align-items: center;
}
.toggle-pass svg { width: 16px; height: 16px; stroke: #c0c0c0; transition: stroke .2s; }
.toggle-pass:hover svg { stroke: var(--litsea-primary); }

.row-check {
	display: flex; align-items: center; justify-content: space-between;
	gap: 12px; margin: 6px 0 20px;
}
.forgot-link {
	font-size: 12.5px; font-weight: 500;
	color: var(--litsea-primary); text-decoration: none; white-space: nowrap;
}
.forgot-link:hover { text-decoration: underline; }

.btn-submit {
	width: 100%; padding: 12px;
	background: var(--litsea-primary); color: #fff;
	font-size: 14px; font-weight: 600; letter-spacing: .02em;
	border: none; border-radius: 10px; cursor: pointer;
	transition: background .2s, box-shadow .2s, transform .1s;
	display: flex; align-items: center; justify-content: center; gap: 8px;
}
.btn-submit svg { width: 16px; height: 16px; stroke: #fff; }
.btn-submit:hover  { background: var(--litsea-primary-dark); box-shadow: 0 6px 18px rgba(47,183,164,.30); }
.btn-submit:active { transform: scale(.98); }
.btn-submit:disabled { opacity: .6; cursor: not-allowed; transform: none; box-shadow: none; }

.btn-secundario {
	display: inline-block; width: 100%; text-align: center;
	padding: 11px; margin-top: 10px;
	background: var(--superficie); color: var(--text-main);
	border: 1.5px solid var(--input-border); border-radius: 10px;
	font-size: 13.5px; text-decoration: none; cursor: pointer;
}
.btn-secundario:hover { border-color: var(--litsea-primary); color: var(--litsea-primary); }

.ayuda { font-size: 12px; color: var(--text-muted); margin-top: 6px; line-height: 1.5; }

/* Medidor de fuerza de la contraseña */
.fuerza { height: 4px; border-radius: 4px; background: #eee; margin-top: 8px; overflow: hidden; }
.fuerza span { display: block; height: 100%; width: 0; transition: width .25s, background .25s; }
.fuerza-txt { font-size: 11.5px; color: var(--text-muted); margin-top: 5px; }

/* ── Recuperación de contraseña ──────────────────────────────────────────── */

/* Barra de tres pasos. Decorativa (aria-hidden): el paso también va escrito. */
.pasos { display: flex; align-items: center; gap: 6px; margin-bottom: 22px; }
.paso-pill { height: 4px; flex: 1; border-radius: 99px; background: var(--input-border); }
.paso-pill.on { background: var(--litsea-primary); }

/*
 * Un solo campo para el código, no seis casillas: las casillas se rompen al
 * pegar desde el correo y los gestores de contraseñas no saben rellenarlas.
 * Con autocomplete="one-time-code" el móvil lo ofrece solo.
 */
.otp-input {
	width: 100%; height: 64px;
	text-align: center;
	font-size: 28px; font-weight: 600;
	letter-spacing: 12px;
	/* El espaciado se aplica también DETRÁS del último dígito; sin esta
	   sangría el texto se ve descentrado hacia la izquierda. */
	text-indent: 12px;
	color: var(--text-main);
	border: 1.5px solid var(--input-border); border-radius: 12px;
	background: var(--input-bg); outline: none;
	transition: border-color .2s, box-shadow .2s, background .2s;
}
.otp-input::placeholder { color: #dbe0e6; font-weight: 500; letter-spacing: 12px; }
.otp-input:focus {
	border-color: var(--litsea-primary);
	box-shadow: 0 0 0 3px rgba(47,183,164,.15);
	background: var(--superficie);
}

.reenviar-row {
	display: flex; justify-content: space-between; align-items: center;
	gap: 12px; margin: 14px 0 20px;
	font-size: 12.5px; color: var(--text-muted);
}
.reenviar-row button {
	background: none; border: none; padding: 0; cursor: pointer;
	font-size: 12.5px; font-weight: 600; color: var(--litsea-primary);
	white-space: nowrap;
}
.reenviar-row button[disabled] { color: #c0c0c0; cursor: default; }

/* ── Pie de las tarjetas ─────────────────────────────────────────────────── */

.divider {
	display: flex; align-items: center; gap: 10px;
	margin: 18px 0; color: #d1d5db; font-size: 12px;
}
.divider::before, .divider::after {
	content: ''; flex: 1; height: 1px; background: var(--input-border);
}

.back-link {
	display: flex; align-items: center; justify-content: center; gap: 6px;
	font-size: 13px; color: var(--text-muted); text-decoration: none;
	transition: color .2s;
}
.back-link svg { width: 14px; height: 14px; stroke: var(--text-muted); transition: stroke .2s; }
.back-link:hover { color: var(--litsea-primary); }
.back-link:hover svg { stroke: var(--litsea-primary); }

.register-row {
	text-align: center; margin-top: 14px;
	font-size: 13px; color: var(--text-muted); line-height: 2;
}
.register-row a { color: var(--litsea-primary); font-weight: 600; text-decoration: none; }
.register-row a:hover { text-decoration: underline; }


/* ── Móvil ───────────────────────────────────────────────────────────────── */

@media (max-width: 768px) {
	.login-wrapper { padding: 0; gap: 0; }
	.panel-left    { display: none; }
	.panel-right {
		width: 100%; min-height: 100vh; border-radius: 0;
		align-items: flex-start; padding-top: 52px; padding-bottom: 40px;
	}
	.mobile-logo { display: flex; justify-content: flex-start; }
}

/* =============================================================================
   ARMAZÓN DE LOS PANELES (pantallas con sesión)
   -----------------------------------------------------------------------------
   Las de acceso usan dos paneles a pantalla completa; estas no: barra arriba,
   contenido centrado y pie. Comparten los tokens de :root, así que el salto de
   una a otra no cambia de color ni de tipografía.
   ========================================================================== */

/*
 * Armazón replicado de la app Next.js (components/layout/DashboardShell.tsx):
 * superficie exterior gris neutra, menú lateral plegable, y el contenido en una
 * tarjeta blanca enmarcada con scroll propio.
 *
 * El teal NO es el color del armazón: sólo marca el ítem activo y el avatar.
 * El resto es blanco y gris — es cromo, no marca.
 */
body.app {
	background: var(--fondo);
	min-height: 100vh;
}

.app-shell { display: flex; height: 100vh; overflow: hidden; }

/* ── Menú lateral ────────────────────────────────────────────────────────── */

.sidebar {
	width: 248px; flex-shrink: 0;
	display: flex; flex-direction: column;
	background: var(--superficie);
	border-right: 1px solid var(--input-border);
	transition: width .2s ease-in-out;
	/*
	 * Recorta el carril. Plegado, los rótulos siguen ocupando su ancho real
	 * —sólo están a opacity 0— así que el contenido mide 248px dentro de una
	 * caja de 68px. Sin esto aparece una barra de scroll horizontal.
	 * Se puede recortar sin miedo porque los globos del carril son `title`
	 * nativo, no un ::after que hubiera que dejar salir.
	 */
	overflow: hidden;
}

/* Los rótulos se desvanecen y se desplazan 4px; NO se anima el ancho de cada
   uno, sólo el del carril. Animar anchos por texto da tirones. */
.rotulo {
	white-space: nowrap;
	transition: opacity .15s ease-in-out, transform .15s ease-in-out;
}

.sidebar-cab {
	display: flex; align-items: center; gap: 8px;
	height: 62px; padding: 0 10px 0 14px; flex-shrink: 0;
	border-bottom: 1px solid var(--input-border);
}
.sidebar-marca {
	display: flex; align-items: center; gap: 10px;
	text-decoration: none; flex: 1; min-width: 0;
}
.sidebar-marca img { height: 28px; width: auto; flex-shrink: 0; }
.sidebar-marca .rotulo { font-size: 14px; font-weight: 700; color: var(--text-dark); }

.sidebar-plegar {
	display: flex; align-items: center; justify-content: center;
	width: 28px; height: 28px; flex-shrink: 0;
	background: none; border: none; border-radius: 8px; cursor: pointer;
	color: var(--text-muted);
	transition: background .15s, color .15s;
}
.sidebar-plegar:hover { background: var(--input-bg); color: var(--text-main); }
.sidebar-plegar svg { width: 16px; height: 16px; transition: transform .2s ease-in-out; }

/*
 * La ÚNICA zona que hace scroll. La cabecera (con el botón de plegar) y el pie
 * (avatar y salir) quedan fuera a propósito: son `flex-shrink: 0` y no se
 * mueven por mucho que crezca la lista.
 *
 * `min-height: 0` no es decorativo: sin él un hijo flex no encoge por debajo de
 * su contenido y el overflow nunca llega a activarse.
 *
 * `overflow-x: hidden` explícito porque al fijar sólo un eje, la especificación
 * calcula el otro como `auto` y vuelve a salir la barra horizontal.
 *
 * `scrollbar-gutter: stable both-edges` es lo que mantiene los iconos
 * centrados: reserva el hueco de la barra en los DOS lados y siempre, haya
 * desbordamiento o no. Sin esto, la barra se come el lado derecho sólo cuando
 * la lista es larga —le pasa al admin, que tiene más ítems— y el carril plegado
 * centra sobre un ancho distinto: la fila entera se ve torcida a la izquierda.
 * Con el hueco reservado a los dos lados, los cuatro estados —plegado y
 * desplegado, con y sin desbordamiento— quedan idénticos.
 */
.sidebar-nav {
	flex: 1 1 auto; min-height: 0;
	overflow-y: auto; overflow-x: hidden;
	padding: 6px 0;
	scrollbar-gutter: stable both-edges;
	scrollbar-width: thin;
	scrollbar-color: transparent transparent;   /* Firefox: aparece al pasar */
}

/*
 * Respaldo para quien no soporta `scrollbar-gutter` (Safari por debajo de 18.2).
 * Ahí la barra sí roba ancho, así que se compensa con el mismo hueco a los dos
 * lados — la misma cifra que dibuja `::-webkit-scrollbar`, tomada de la variable
 * para que no puedan discrepar.
 *
 * Va en @supports y no suelto: donde `scrollbar-gutter` funciona, este padding
 * sumaría al hueco ya reservado y estrecharía el carril de más.
 */
@supports not (scrollbar-gutter: stable) {
	.sidebar-nav { padding-left: var(--emp-scroll); padding-right: var(--emp-scroll); }
}

/* La barra, discreta: sólo se ve cuando el ratón está en el menú. Una barra
   gruesa y gris permanente en un carril de 68px se lee como un borde raro. */
.sidebar-nav::-webkit-scrollbar { width: var(--emp-scroll); }
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }
.sidebar-nav::-webkit-scrollbar-thumb {
	background: transparent; border-radius: 100px;
	transition: background .15s ease-in-out;
}
.sidebar:hover .sidebar-nav::-webkit-scrollbar-thumb { background: #d7dbe0; }
.sidebar:hover .sidebar-nav::-webkit-scrollbar-thumb:hover { background: #c2c8ce; }
.sidebar:hover .sidebar-nav { scrollbar-color: #d7dbe0 transparent; }

.sidebar-sec { padding: 4px 0; }
.sidebar-sec + .sidebar-sec { border-top: 1px solid #f1f3f5; margin-top: 4px; }
.sidebar-sec-tit {
	font-size: 10.5px; font-weight: 600; letter-spacing: .08em;
	text-transform: uppercase; color: #aab0b7;
	padding: 8px 16px 4px;
}

/* Caja de icono de 40px fija: mantiene cada glifo centrado en los dos estados
   del carril, plegado y desplegado. */
.glifo {
	display: flex; align-items: center; justify-content: center;
	width: 40px; height: 40px; flex-shrink: 0;
}

.sidebar-item {
	position: relative;
	display: flex; align-items: center; gap: 2px;
	height: 40px; margin: 1px 10px; padding-right: 12px;
	border-radius: 10px;
	font-size: 13.5px; font-weight: 500; color: var(--text-muted);
	text-decoration: none;
	transition: background .15s, color .15s;
}
.sidebar-item svg { width: 18px; height: 18px; stroke: currentColor; }
.sidebar-item:hover { background: var(--input-bg); color: var(--text-main); }

.sidebar-item.activo {
	background: rgba(47,183,164,.10);
	color: var(--litsea-primary-dark); font-weight: 600;
}
/* Indicador fino pegado al borde del carril, no un bloque de color. */
.sidebar-item.activo::before {
	content: ''; position: absolute; left: -10px; top: 9px; bottom: 9px;
	width: 3px; border-radius: 0 3px 3px 0; background: var(--litsea-primary);
}

/* Pantalla que aún no existe: se ve, no se pulsa. */
.sidebar-item.off,
.sidebar-item.off:hover { color: #c9ced4; background: none; cursor: default; }

/* Globo de mensajes sin leer en el ítem del menú. */
.menu-n {
	margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px;
	display: inline-flex; align-items: center; justify-content: center;
	background: var(--litsea-primary); color: #fff; border-radius: 9px;
	font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
	flex-shrink: 0;
}

.sidebar-pie {
	margin-top: auto; flex-shrink: 0;
	border-top: 1px solid var(--input-border); padding: 10px;
}
.sidebar-yo { display: flex; align-items: center; gap: 10px; padding: 6px; min-width: 0; }
.avatar {
	display: flex; align-items: center; justify-content: center;
	width: 32px; height: 32px; flex-shrink: 0; border-radius: 50%;
	background: rgba(47,183,164,.14); color: var(--litsea-primary-dark);
	font-size: 13px; font-weight: 700;
	overflow: hidden;   /* la foto hereda el círculo en vez de traer el suyo */
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.sidebar-yo-txt { display: flex; flex-direction: column; min-width: 0; }
.sidebar-yo-txt .nombre,
.sidebar-yo-txt .correo { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-yo-txt .nombre { font-size: 12.5px; font-weight: 600; color: var(--text-dark); }
.sidebar-yo-txt .correo { font-size: 11px; color: var(--text-muted); }

/* Es un <button> dentro de un <form>, no un enlace — ver plantillas.php.
   De ahí background y font-family explícitos: sin ellos hereda los del
   navegador y sale gris con la tipografía del sistema. */
.sidebar-salir {
	display: flex; align-items: center; gap: 2px;
	width: 100%; height: 40px; padding-right: 12px;
	background: none; border: none; border-radius: 10px; cursor: pointer;
	font-family: inherit; font-size: 13.5px; font-weight: 500;
	color: var(--text-muted); text-align: left;
	transition: background .15s, color .15s;
}
.sidebar-salir svg { width: 18px; height: 18px; stroke: currentColor; }
.sidebar-salir:hover { background: var(--error-bg); color: var(--error-text); }

/* ── Contenido ───────────────────────────────────────────────────────────── */

/*
 * ⚠️ `.app-main` NO scrollea, y no es un descuido.
 *
 * Es una columna flex: la barra superior arriba, fija, y `.app-contenido`
 * debajo llevándose el scroll. El overflow tiene que estar en el hijo porque la
 * barra lleva dos desplegables que se salen de su caja —los resultados del
 * buscador y el menú del perfil— y un contenedor con `overflow` los recorta en
 * cuanto pasan del borde. Volver a poner `overflow-y: auto` aquí los corta.
 */
.app-main {
	flex: 1; min-width: 0; min-height: 0;
	margin: 8px;
	display: flex; flex-direction: column;
	background: var(--superficie);
	border: 1px solid var(--input-border);
	border-radius: 16px;
}

.app-contenido {
	flex: 1; min-height: 0;
	padding: 28px 30px 48px;
	overflow-y: auto;
	/* Sólo abajo: arriba lo tapa la barra, y redondear ahí recortaría su
	   borde inferior contra la esquina de la tarjeta. */
	border-radius: 0 0 15px 15px;
}

/* Flechas en línea de los enlaces de texto del panel («Ver vacantes →»).
   Hijo directo a propósito: así no alcanza a los iconos que van dentro de otra
   pieza, como las estrellas de una valoración enlazada. */
.app-contenido a > svg { width: 14px; height: 14px; vertical-align: -2px; }

/* ── Barra superior ──────────────────────────────────────────────────────────
 * Título, buscador, tema y perfil. Portada del armazón de la app escolar
 * (`Litseacc-App/css/topbar.css`) con los tokens de aquí. El marcado lo pinta
 * php/plantillas_topbar.php y el comportamiento vive en js/topbar.js.
 * ------------------------------------------------------------------------- */

.tb {
	display: flex; align-items: center; gap: 16px;
	flex-shrink: 0;
	min-height: 64px;
	padding: 10px 20px;
	border-bottom: 1px solid var(--input-border);
}

.tb-tit { min-width: 0; flex-shrink: 1; }
.tb-tit-h {
	margin: 0;
	font-size: 19px; font-weight: 700; line-height: 1.25;
	color: var(--text-dark);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-tit-sub {
	margin: 2px 0 0;
	font-size: 12.5px; color: var(--text-muted);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* El buscador cede antes que el título o el perfil: entre los tres es el único
   que puede encogerse sin perder información — sigue siendo un campo. */
.tb-buscar { position: relative; flex: 1 1 auto; min-width: 0; max-width: 460px; margin-left: auto; }

.tb-campo { position: relative; display: flex; align-items: center; }
.tb-campo-icono {
	position: absolute; left: 11px; display: flex;
	color: var(--text-muted); pointer-events: none;
}
.tb-campo-icono svg { width: 16px; height: 16px; }

.tb-campo-input {
	width: 100%;
	padding: 9px 58px 9px 34px;
	font-family: inherit; font-size: 13.5px;
	color: var(--text-main);
	background: var(--input-bg);
	border: 1px solid var(--input-border); border-radius: 10px;
	transition: border-color .2s, box-shadow .2s, background .2s;
}
.tb-campo-input:focus {
	outline: none;
	background: var(--superficie);
	border-color: var(--litsea-primary);
	box-shadow: 0 0 0 3px rgba(47,183,164,.15);
}
/* La X nativa de `type=search` en WebKit trae su propio icono gris que no
   sigue al tema. Se quita y se deja el vaciado por Escape, que ya está. */
.tb-campo-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.tb-atajo {
	position: absolute; right: 9px;
	padding: 2px 6px;
	font-family: inherit; font-size: 10.5px; font-weight: 600;
	color: var(--text-muted);
	background: var(--superficie);
	border: 1px solid var(--input-border); border-radius: 5px;
	pointer-events: none;
}

/* ── El panel de resultados ─────────────────────────────────────────────── */

.tb-panel {
	position: absolute; top: calc(100% + 6px); left: 0; right: 0;
	z-index: 40;
	background: var(--superficie);
	border: 1px solid var(--input-border); border-radius: 12px;
	box-shadow: 0 10px 30px rgba(0,0,0,.10);
	overflow: hidden;
}
.tb-resultados { max-height: 60vh; overflow-y: auto; padding: 6px; }

.tb-grupo-tit {
	padding: 8px 10px 4px;
	font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
	color: var(--text-muted);
}

.tb-res {
	display: flex; align-items: center; gap: 10px;
	padding: 8px 10px; border-radius: 9px;
	color: var(--text-main); text-decoration: none;
}
/* Una sola clase para ratón y teclado: la pone el JS al pasar por encima y al
   moverse con las flechas, así Enter hace siempre lo que se está mirando. */
.tb-res--sel { background: var(--input-bg); }
.tb-res--dato { cursor: default; }

.tb-res-glifo { display: flex; flex-shrink: 0; color: var(--text-muted); }
.tb-res-glifo svg { width: 16px; height: 16px; }

.tb-res-txt { min-width: 0; display: flex; flex-direction: column; }
.tb-res-t {
	font-size: 13.5px; font-weight: 500; color: var(--text-dark);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-res-s {
	font-size: 11.5px; color: var(--text-muted);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Estado de una fila del buscador: punto de color y texto, sin píldora — el
   mismo criterio que `.badge`, ver el comentario largo de ahí. */
.tb-marca {
	margin-left: auto; flex-shrink: 0;
	display: inline-flex; align-items: center; gap: 5px;
	font-size: 10.5px; font-weight: 600; white-space: nowrap;
}
.tb-marca::before {
	content: ""; width: 5px; height: 5px; border-radius: 50%;
	background: currentColor; flex-shrink: 0;
}
.tb-marca--bien    { color: var(--ok-text); }
.tb-marca--aviso   { color: var(--warn-text); }
.tb-marca--mal     { color: var(--error-text); }
.tb-marca--apagado { color: var(--text-muted); }

.tb-vacio, .tb-cargando {
	padding: 18px 12px; text-align: center;
	font-size: 13px; color: var(--text-muted);
}

/* ── Acciones: tema y perfil ────────────────────────────────────────────── */

.tb-acciones { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

.tb-icono {
	display: flex; align-items: center; justify-content: center;
	width: 36px; height: 36px;
	color: var(--text-muted);
	background: none; border: none; border-radius: 9px; cursor: pointer;
	transition: background .15s, color .15s;
}
.tb-icono:hover { background: var(--input-bg); color: var(--text-main); }
.tb-icono svg   { width: 18px; height: 18px; }

.tb-yo { position: relative; }
.tb-yo-btn {
	display: flex; align-items: center; gap: 9px;
	padding: 5px 8px 5px 5px;
	background: none; border: none; border-radius: 10px; cursor: pointer;
	font-family: inherit;
	transition: background .15s;
}
.tb-yo-btn:hover { background: var(--input-bg); }

.tb-avatar {
	position: relative; overflow: hidden;
	display: flex; align-items: center; justify-content: center;
	width: 32px; height: 32px; flex-shrink: 0;
	border-radius: 50%;
	background: var(--litsea-primary); color: #fff;
	font-size: 13px; font-weight: 600;
}
.tb-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.tb-yo-txt { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.tb-yo-nombre {
	font-size: 13px; font-weight: 600; color: var(--text-dark);
	max-width: 150px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-yo-rol { font-size: 11px; color: var(--text-muted); }
.tb-yo-flecha { display: flex; color: var(--text-muted); }
.tb-yo-flecha svg { width: 14px; height: 14px; }

.tb-menu {
	position: absolute; top: calc(100% + 6px); right: 0;
	z-index: 40; min-width: 232px;
	padding: 6px;
	background: var(--superficie);
	border: 1px solid var(--input-border); border-radius: 12px;
	box-shadow: 0 10px 30px rgba(0,0,0,.10);
}
.tb-menu-cab {
	display: flex; flex-direction: column;
	padding: 8px 10px 10px; margin-bottom: 4px;
	border-bottom: 1px solid var(--input-border);
}
.tb-menu-nombre { font-size: 13px; font-weight: 600; color: var(--text-dark); }
.tb-menu-correo {
	font-size: 11.5px; color: var(--text-muted);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.tb-menu-item {
	display: flex; align-items: center; gap: 9px; width: 100%;
	padding: 9px 10px; border-radius: 9px;
	font-family: inherit; font-size: 13px; text-align: left;
	color: var(--text-main); text-decoration: none;
	background: none; border: none; cursor: pointer;
	transition: background .15s, color .15s;
}
.tb-menu-item:hover { background: var(--input-bg); color: var(--text-dark); }
.tb-menu-item svg   { width: 16px; height: 16px; flex-shrink: 0; }
.tb-menu-salir:hover { color: var(--error-text); }

/* ── Estrecho ───────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
	/* El nombre y el rol se van antes que el buscador: son el dato que menos
	   falta hace de los tres —quien está dentro ya sabe quién es— y el avatar
	   por sí solo sigue abriendo el menú, donde los dos vuelven a estar. */
	.tb-yo-txt, .tb-yo-flecha { display: none; }
	.tb-atajo { display: none; }
	.tb          { gap: 10px; padding: 10px 14px; }
	.tb-campo-input { padding-right: 12px; }
}

@media (max-width: 620px) {
	/* Aquí ya no caben las dos cosas. Gana el título: dice dónde estás, y el
	   buscador tiene su atajo y su sitio en cuanto haya un dedo de ancho más. */
	.tb-buscar { display: none; }
}

/* ── Carril plegado (sólo escritorio) ────────────────────────────────────── */
/*
 * Acotado a escritorio a propósito: en móvil el menú es un cajón deslizante y
 * el estado "plegado" no tiene sentido. Con un @media de mínimo, el móvil ni
 * siquiera ve estas reglas y no hay que deshacerlas una por una.
 */
@media (min-width: 901px) {
	body.menu-plegado .sidebar { width: 68px; }

	body.menu-plegado .rotulo {
		opacity: 0; transform: translateX(-4px); pointer-events: none;
	}
	body.menu-plegado .sidebar-sec-tit { height: 0; padding: 0; overflow: hidden; }

	body.menu-plegado .sidebar-cab { padding: 0; justify-content: center; }
	body.menu-plegado .sidebar-marca { display: none; }
	body.menu-plegado .sidebar-plegar svg { transform: rotate(180deg); }

	/* La rayita del activo señala el borde del carril; con el carril encogido
	   queda pegada al icono y parece un resto de pintura. Fuera. */
	body.menu-plegado .sidebar-item.activo::before { display: none; }

	/* Plegado, cada ítem se reduce a su caja de icono: 40×40 (1:1) y centrada
	   en el carril — también la píldora del activo y el hover. El rótulo
	   invisible sobresale de la caja, pero a opacity 0 no pinta nada y el
	   overflow del carril lo recorta. */
	body.menu-plegado .sidebar-item  { width: 40px; margin: 1px auto; padding-right: 0; }

	/*
	 * El centrado con la barra de scroll de por medio ya está resuelto arriba,
	 * en `.sidebar-nav`, con `scrollbar-gutter: stable both-edges`. Aquí no
	 * hace falta compensar nada: el hueco está reservado a los dos lados
	 * siempre, así que `margin: auto` centra sobre el mismo ancho haya o no
	 * desbordamiento.
	 */

	/* Plegado, el globo se vuelve un punto sobre el icono: el número no cabe. */
	body.menu-plegado .menu-n {
		position: absolute; top: 5px; right: 5px; margin: 0;
		width: 8px; min-width: 8px; height: 8px; padding: 0;
		overflow: hidden; color: transparent; border-radius: 50%;
	}
	body.menu-plegado .sidebar-salir { width: 40px; margin: 0 auto;  padding-right: 0; }

	body.menu-plegado .sidebar-yo    { justify-content: center; padding: 6px 0; }
	/* El texto del perfil se OCULTA, no solo se desvanece: como `rotulo` solo
	   baja la opacidad, seguía ocupando su ancho y `justify-content: center`
	   centraba [avatar + texto invisible], dejando el avatar 8px a la izquierda
	   del carril. Con display:none el avatar queda solo y cae en el centro (34),
	   igual que los iconos y el botón de salir. */
	body.menu-plegado .sidebar-yo-txt { display: none; }
}

/* ── Móvil: barra superior + cajón ───────────────────────────────────────── */

.movil-bar   { display: none; }
.sidebar-velo { display: none; }

@media (max-width: 900px) {
	.movil-bar {
		display: flex; align-items: center; gap: 12px;
		height: 56px; padding: 0 14px; flex-shrink: 0;
		background: var(--superficie); border-bottom: 1px solid var(--input-border);
	}
	.movil-menu {
		display: flex; align-items: center; justify-content: center;
		width: 36px; height: 36px; flex-shrink: 0;
		background: none; border: none; border-radius: 9px; cursor: pointer;
		color: var(--text-main);
	}
	.movil-menu:hover { background: var(--input-bg); }
	.movil-menu svg { width: 20px; height: 20px; }
	.movil-marca { display: flex; align-items: center; gap: 9px; text-decoration: none; min-width: 0; }
	.movil-marca img  { height: 26px; width: auto; }
	.movil-marca span {
		font-size: 14px; font-weight: 700; color: var(--text-dark);
		overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	}

	.app-shell { height: calc(100vh - 56px); }

	.sidebar {
		position: fixed; top: 0; left: 0; bottom: 0; z-index: 50;
		width: 268px;
		transform: translateX(-100%);
		transition: transform .2s ease-in-out;
	}
	body.menu-abierto .sidebar { transform: translateX(0); }

	/*
	 * ⚠️ El velo se apagaba con el atributo `hidden` del HTML, y este
	 * `display: block` se lo comía: una clase gana al `display:none` que el
	 * navegador aplica a `[hidden]`. Resultado: en móvil el velo estaba SIEMPRE
	 * puesto —la pantalla se veía atenuada con el menú cerrado y se tragaba
	 * todos los taps—, y el cajón parecía roto sin estarlo.
	 *
	 * Ahora el estado lo lleva la clase del body, que es la misma que mueve el
	 * cajón, así que no pueden discrepar. Y se apaga con las tres, no con una:
	 * `opacity` sola deja la capa capturando taps, y `visibility` sola corta la
	 * transición de golpe.
	 */
	.sidebar-velo {
		display: block; position: fixed; inset: 0; z-index: 40;
		background: rgba(0,0,0,.42);
		opacity: 0;
		visibility: hidden;
		pointer-events: none;
		transition: opacity .22s ease-out, visibility .22s ease-out;
	}
	body.menu-abierto .sidebar-velo {
		opacity: 1;
		visibility: visible;
		pointer-events: auto;
	}
	.sidebar-plegar { display: none; }

	.app-main      { margin: 8px; }
	.app-contenido { padding: 22px 18px 40px; }

	/*
	 * Cuerpo bloqueado mientras el cajón está abierto. `position: fixed` y no
	 * `overflow: hidden` a secas porque en iOS el segundo no frena el scroll
	 * de la página de debajo. El `top` negativo lo pone el JS con la posición
	 * en la que estaba, y al cerrar la devuelve: sin eso, abrir el menú manda
	 * la página al principio.
	 */
	body.cuerpo-fijo {
		position: fixed;
		width: 100%;
		overflow: hidden;
	}

	/* El cajón respeta la barra de gestos del teléfono. */
	.sidebar { padding-bottom: env(safe-area-inset-bottom, 0); }
	.movil-bar { padding-top: env(safe-area-inset-top, 0); }

	/*
	 * Zonas de toque de 44px. El botón se ve de 36 —el tamaño visual no
	 * cambia— pero el área que responde al dedo llega a 44 por el pseudo
	 * elemento, que es la forma de crecer sin descuadrar la barra.
	 */
	.movil-menu { position: relative; }
	.movil-menu::after {
		content: ''; position: absolute;
		top: 50%; left: 50%; transform: translate(-50%, -50%);
		width: 44px; height: 44px;
	}

	/* Los ítems del menú ya miden 40; en el cajón suben a 44. */
	.sidebar-item, .sidebar-salir { height: 44px; }
}

/*
 * Sin animaciones para quien las ha desactivado en su sistema. El cajón sigue
 * abriendo y cerrando: lo que se quita es el desplazamiento, no la función.
 */
@media (prefers-reduced-motion: reduce) {
	.sidebar, .sidebar-velo { transition: none; }
}

.seccion { margin-bottom: 30px; }
.seccion > h2 {
	font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
	color: var(--text-muted); margin-bottom: 12px;
}

.tarjeta {
	background: var(--superficie); border: 1px solid var(--input-border);
	border-radius: 14px; padding: 20px 22px;
}
.tarjeta + .tarjeta { margin-top: 12px; }
.tarjeta h3 { font-size: 15px; font-weight: 600; color: var(--text-dark); margin-bottom: 6px; }
.tarjeta p  { font-size: 13.5px; line-height: 1.65; color: var(--text-main); }

/* ── Cifras ──────────────────────────────────────────────────────────────── */

.metricas {
	display: grid; gap: 12px;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	margin-bottom: 30px;
}
.metrica {
	display: flex; flex-direction: column; gap: 4px;
	background: var(--superficie); border: 1px solid var(--input-border);
	border-radius: 14px; padding: 18px 20px;
	text-decoration: none; transition: border-color .2s, box-shadow .2s;
}
a.metrica:hover { border-color: var(--litsea-primary); box-shadow: 0 4px 14px rgba(47,183,164,.13); }
.metrica-valor    { font-size: 27px; font-weight: 700; color: var(--text-dark); line-height: 1.1; }
.metrica-etiqueta { font-size: 12.5px; color: var(--text-muted); line-height: 1.4; }

/* ── Distintivos de estado ───────────────────────────────────────────────── */

/* 🔴 PUNTO Y TEXTO, NO PÍLDORA DE COLOR (20/8/2026)

   Una ficha de terapeuta puede llevar cuatro marcas a la vez —«Pendiente de
   aprobación», «Egresada», «Destacada», «Desde la escuela»—. Con píldoras
   pastel eso era una hilera de cápsulas ámbar, verde, dorada y gris que pesaba
   más que el nombre de la persona, que es lo que de verdad se va a leer. El
   cliente lo señaló así, con esa pantalla delante.

   Un punto de 6px y la palabra al lado dicen lo mismo ocupando la mitad, y
   dejan que el orden de lectura de la tarjeta sea el correcto: nombre, correo,
   estado. `currentColor` en el punto ata su color al del texto, así que añadir
   una marca nueva es una línea con un `color` y nada más.

   Los tres colores ya pasaban AA sobre blanco cuando eran texto sobre su
   propio tinte, así que sirven igual sobre el blanco de la tarjeta. El dorado
   no: `--litsea-accent-gold` (#c9a24d) da 2,2:1 y sólo valía porque iba sobre
   #fdf7e7. Sin fondo hay que bajarlo — ver `.badge-destacada`. */
.badge {
	display: inline-flex; align-items: center; gap: 6px;
	font-size: 12px; font-weight: 500; white-space: nowrap;
	color: var(--text-muted);
}
.badge::before {
	content: ""; width: 6px; height: 6px; border-radius: 50%;
	background: currentColor; flex-shrink: 0;
}
.badge-pendiente { color: var(--warn-text); }
.badge-aprobado  { color: var(--ok-text); }
.badge-rechazado { color: var(--error-text); }

/* ── Estado vacío ────────────────────────────────────────────────────────── */

.vacio {
	background: var(--superficie); border: 1px dashed var(--input-border); border-radius: 14px;
	padding: 34px 22px; text-align: center;
	font-size: 13.5px; color: var(--text-muted);
}

/* ── Tablas ──────────────────────────────────────────────────────────────── */

.tabla-envoltura {
	background: var(--superficie); border: 1px solid var(--input-border);
	border-radius: 14px; overflow-x: auto;
}
table.tabla { width: 100%; border-collapse: collapse; font-size: 13px; }
table.tabla th {
	text-align: left; padding: 12px 16px;
	font-size: 11.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
	color: var(--text-muted); border-bottom: 1px solid var(--input-border); white-space: nowrap;
}
table.tabla td { padding: 13px 16px; border-bottom: 1px solid #f2f4f5; color: var(--text-main); }
table.tabla tr:last-child td { border-bottom: none; }
table.tabla tbody tr:hover { background: #fafbfb; }
table.tabla a { color: var(--litsea-primary-dark); text-decoration: none; font-weight: 500; }
table.tabla a:hover { text-decoration: underline; }

/* ── Desplazamiento con inercia y entradas (sólo parte pública) ──────────── */
/*
 * Lo que pide Lenis para funcionar. Sin `height:auto` en <html> y <body> el
 * cálculo del alto se queda corto y el desplazamiento se atasca al final.
 */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: clip; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/*
 * Entradas al hacer scroll.
 *
 * ⚠️ El estado oculto cuelga de `html.con-revelado`, y esa clase la pone
 * js/publico.js DESPUÉS de comprobar que puede revelarlos. Es la diferencia
 * entre una animación y una página en blanco: si el script no llega a
 * ejecutarse —error de red, JS desactivado, navegador viejo—, esta regla nunca
 * se aplica y el contenido se ve entero, sin animar. Escrito al revés (ocultar
 * en el CSS y confiar en que el JS lo arregle) un fallo de 14 KB dejaría la
 * portada vacía.
 *
 * 18px y no 40: el desplazamiento se nota sin que el bloque «venga de fuera».
 * A esta escala se lee como que el contenido se asienta, no como que viaja.
 */
html.con-revelado .revelar {
	opacity: 0;
	transform: translateY(18px);
	transition: opacity .55s ease-out, transform .55s ease-out;
	will-change: opacity, transform;
}
html.con-revelado .revelar.visible {
	opacity: 1;
	transform: none;
	will-change: auto;   /* se suelta al acabar: mantenerlo cuesta memoria */
}

/* Cinturón: aunque el JS ya no arranca con quietud pedida, si esa clase quedara
   puesta de una sesión anterior el contenido se ve igual. */
@media (prefers-reduced-motion: reduce) {
	html.con-revelado .revelar {
		opacity: 1; transform: none; transition: none;
	}
}

/* ── Tablas en móvil: cada fila, una tarjeta ─────────────────────────────── */
/*
 * A 360px, una tabla de cinco columnas o hace scroll horizontal o parte cada
 * celda en tres líneas. Las dos son malas de la misma forma: las columnas de la
 * derecha —estado y acciones, justo lo que se viene a mirar— quedan fuera de
 * vista y nada indica que existan.
 *
 * Cada fila pasa a ser una tarjeta y cada celda una línea de «etiqueta: valor».
 * La etiqueta sale del `data-label` que pone el PHP con la MISMA clave i18n que
 * el encabezado, así que se traduce sola y no hay una segunda lista de nombres
 * de columna que mantener.
 *
 * El corte es 767 y no 900 —que es el del cajón— a propósito: son dos problemas
 * distintos. En una tablet de 800px la tabla cabe entera y se lee mejor como
 * tabla; lo que ya no cabe ahí es el menú fijo.
 */
@media (max-width: 767px) {
	/*
	 * 16px en los campos, y no por estética: Safari de iOS hace zoom al enfocar
	 * cualquier campo de menos de 16px, y al salir no lo deshace. La página se
	 * queda ampliada y descuadrada, y la persona tiene que arreglarlo a mano —
	 * pasa en el login, que es la primera pantalla que ve.
	 */
	.form-control, select.form-control, textarea.form-control { font-size: 16px; }

	.tabla-envoltura { border: none; background: none; overflow: visible; }

	table.tabla thead { display: none; }
	table.tabla, table.tabla tbody { display: block; width: 100%; }

	table.tabla tr {
		display: block;
		border: 1px solid var(--input-border);
		border-radius: 12px;
		padding: 6px 12px;
		margin-bottom: 12px;
		background: var(--superficie);
	}
	table.tabla tbody tr:hover { background: var(--superficie); }   /* el hover es de ratón */

	table.tabla td {
		display: flex; justify-content: space-between; align-items: baseline;
		gap: 12px;
		padding: 7px 0;
		border-bottom: 1px solid #f4f6f7;
		/* Los correos largos no tienen espacios donde partirse: sin esto
		   desbordan la tarjeta y devuelven el scroll horizontal que veníamos
		   a quitar. */
		overflow-wrap: anywhere;
		text-align: right;
		white-space: normal !important;   /* varias celdas traen nowrap en línea */
	}
	table.tabla tr td:last-child { border-bottom: none; }

	table.tabla td::before {
		content: attr(data-label);
		font-weight: 600; color: var(--text-muted);
		flex-shrink: 0; text-align: left;
	}

	/* La columna de acciones no tiene etiqueta: ocupa la fila entera y se
	   alinea a la izquierda, como una barra de botones al pie de la tarjeta. */
	table.tabla td:not([data-label]) { justify-content: flex-start; text-align: left; }
	table.tabla td:not([data-label])::before { content: none; }

	/* Una celda vacía dentro de una tarjeta es una línea con una etiqueta y
	   nada al lado; se deja, porque «sin dato» también es información. */
	table.tabla .col-detalle span { text-align: right; }
}

/* ── Vacantes ────────────────────────────────────────────────────────────── */

.vac-lista { display: flex; flex-direction: column; gap: 12px; }

.vac {
	background: var(--superficie); border: 1px solid var(--input-border);
	border-radius: 14px; padding: 18px 20px;
	transition: border-color .2s, box-shadow .2s;
}
.vac:hover { border-color: #d6dade; box-shadow: 0 3px 12px rgba(0,0,0,.04); }

.vac-cab { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.vac-titulo { font-size: 15.5px; font-weight: 600; color: var(--text-dark); flex: 1; min-width: 220px; }
.vac-titulo a { color: inherit; text-decoration: none; }
.vac-titulo a:hover { color: var(--litsea-primary-dark); }

/* 16px en horizontal y no 6: sin la píldora que las encerraba, dos marcas
   seguidas con 6px de aire se leen como una sola frase. */
.vac-marcas { display: flex; gap: 6px 16px; flex-wrap: wrap; }

.vac-meta { font-size: 12.5px; color: var(--text-muted); margin-top: 5px; }
.vac-meta .sep, .sep { opacity: .5; margin: 0 2px; }

.vac-desc { font-size: 13px; color: var(--text-main); line-height: 1.6; margin-top: 10px; }

/* Descripción completa de la ficha: respeta los saltos que escribió la empresa. */
.vac-cuerpo { font-size: 13.5px; color: var(--text-main); line-height: 1.75; }

.vac-pie {
	display: flex; align-items: center; justify-content: space-between;
	gap: 12px; flex-wrap: wrap;
	margin-top: 14px; padding-top: 12px;
	border-top: 1px solid #f2f4f5;
	font-size: 12px; color: var(--text-muted);
}
.vac-pie-acciones { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }

/* El dorado de marca (#c9a24d) da 2,2:1 sobre blanco: valía dentro de su
   píldora #fdf7e7 y sin ella no. Éste da 4,8:1 y se sigue leyendo como oro. */
.badge-destacada { color: #a16207; }

/* ── Botones pequeños ────────────────────────────────────────────────────── */

/* Cada acción es su propio <form> (POST + testigo), así que hay que impedir
   que el display:block por defecto los ponga uno debajo de otro. */
.form-inline { display: inline; }

.btn-mini {
	/* inline-flex y no inline-block: con un icono dentro, el SVG se alineaba
	   por línea base y quedaba caído respecto al texto. */
	display: inline-flex; align-items: center; justify-content: center; gap: 6px;
	padding: 6px 12px;
	background: var(--superficie); color: var(--text-main);
	border: 1.5px solid var(--input-border); border-radius: 8px;
	font-size: 12.5px; font-weight: 500; line-height: 1.3;
	text-decoration: none; cursor: pointer; white-space: nowrap;
	transition: border-color .2s, color .2s, background .2s;
}
.btn-mini svg { width: 14px; height: 14px; flex-shrink: 0; }
.btn-mini:hover { border-color: var(--litsea-primary); color: var(--litsea-primary-dark); }

.btn-mini-primario {
	background: var(--litsea-primary); border-color: var(--litsea-primary); color: #fff;
}
.btn-mini-primario:hover {
	background: var(--litsea-primary-dark); border-color: var(--litsea-primary-dark); color: #fff;
}

.btn-mini-peligro { border-color: var(--error-border); color: var(--error-text); }
.btn-mini-peligro:hover { background: var(--error-text); border-color: var(--error-text); color: #fff; }

/* Acción que existe pero no está disponible ahora mismo — hoy, «Aprobar» con el
   perfil de la terapeuta a medias (2026-08-20).

   Es un <span>, no un <button disabled>: un botón deshabilitado no recibe foco
   ni eventos de ratón, así que en táctil no hay forma de leer su `title` y quien
   lo pulsa se queda sin saber por qué no pasa nada. El motivo va escrito encima,
   en el aviso de la ficha; esto solo tiene que verse apagado y no invitar al clic.

   `cursor: not-allowed` y no `default` porque el elemento ocupa el sitio donde
   antes había un botón: sin esa señal, el primer impulso es volver a pulsarlo.

   ⚠️ Sin `:hover` a propósito. Hereda el de `.btn-mini`, que tiñe de teal, y eso
   lo haría parecer pulsable justo al pasar por encima. */
.btn-mini-inerte {
	background: var(--fondo);
	border-color: var(--input-border);
	color: var(--text-muted);
	cursor: not-allowed;
	opacity: .7;
}
.btn-mini-inerte:hover {
	border-color: var(--input-border);
	color: var(--text-muted);
}

.acciones-fila { display: flex; gap: 6px; flex-wrap: wrap; }

.acciones-form {
	display: flex; align-items: center; gap: 12px;
	margin-top: 16px; flex-wrap: wrap;
}
.acciones-form .btn-submit { width: auto; padding-left: 28px; padding-right: 28px; }

/* Cuando el botón es la ÚNICA acción de la pantalla —el alta y completar.php—
   vuelve a ocupar el ancho del formulario.

   El `width: auto` de arriba existe para que el botón quepa al lado de
   «Cancelar»; sin cancelar no hay nada al lado y se queda un botón corto y
   suelto debajo de un formulario ancho. Reportado el 20/8 en las dos pantallas.

   Va como clase y no quitando el `.acciones-form`: ese contenedor también pone
   la separación de arriba, y duplicarla en dos sitios es cómo se descuadran. */
.acciones-form--sola .btn-submit { width: 100%; padding-left: 12px; padding-right: 12px; }

/* ── Filtros ─────────────────────────────────────────────────────────────── */

.filtros {
	display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end;
	background: var(--superficie); border: 1px solid var(--input-border);
	border-radius: 14px; padding: 16px 18px; margin-bottom: 16px;
}
.filtro-campo { flex: 1 1 150px; min-width: 140px; }
.filtro-ancho { flex: 2 1 240px; }
.filtro-campo label {
	display: block; font-size: 12px; font-weight: 500;
	color: var(--text-muted); margin-bottom: 5px;
}
.filtro-campo .form-control { padding: 9px 12px; font-size: 13px; }
.filtro-botones { display: flex; gap: 8px; align-items: center; padding-bottom: 1px; }

/* ── Casillas de catálogo ────────────────────────────────────────────────── */

.casillas { display: flex; flex-wrap: wrap; gap: 8px; }

.casilla {
	display: inline-flex; align-items: flex-start; gap: 7px;
	padding: 7px 12px; cursor: pointer;
	background: var(--input-bg); border: 1.5px solid var(--input-border);
	border-radius: 100px; font-size: 12.5px; color: var(--text-main);
	transition: border-color .15s, background .15s;
}
.casilla:hover { border-color: var(--litsea-primary); }
.casilla input { accent-color: var(--litsea-primary); cursor: pointer; margin-top: 1px; }
/* :has() para teñir la píldora entera al marcarla. Donde no exista, la casilla
   marcada se sigue viendo — solo se pierde el fondo. */
.casilla:has(input:checked) { background: rgba(47,183,164,.10); border-color: var(--litsea-primary); }

.casilla-sola {
	border-radius: 12px; align-items: flex-start;
	padding: 14px 16px; width: 100%; line-height: 1.5;
}
.casilla-sola .ayuda { margin-top: 3px; }

/* ── Etiquetas (especialidades de una ficha) ─────────────────────────────── */

.etiquetas { display: flex; flex-wrap: wrap; gap: 6px; }
.etiqueta {
	display: inline-block; padding: 4px 11px;
	background: rgba(47,183,164,.10); border: 1px solid rgba(47,183,164,.30);
	border-radius: 100px; font-size: 12px; color: var(--litsea-primary-dark);
}

/* ── Rejilla y pestañas ──────────────────────────────────────────────────── */

.rejilla-3 { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

.pestanias {
	display: flex; gap: 4px; flex-wrap: wrap;
	border-bottom: 1px solid var(--input-border); margin-bottom: 18px;
}
.pestania {
	padding: 9px 15px; margin-bottom: -1px;
	border-bottom: 2px solid transparent;
	font-size: 13px; color: var(--text-muted); text-decoration: none;
	transition: color .15s, border-color .15s;
}
.pestania:hover  { color: var(--text-main); }
.pestania.activa { color: var(--litsea-primary-dark); border-bottom-color: var(--litsea-primary); font-weight: 600; }

/* ── Zona de borrado ─────────────────────────────────────────────────────── */

/* Separada y con marco rojo a propósito: lo de aquí no se deshace, y no debe
   quedar a un clic de distancia del botón de guardar. */
.zona-peligro {
	margin-top: 34px; padding: 20px 0 0;
	border-top: 1px solid var(--error-border);
}
.zona-peligro h3 { font-size: 14.5px; font-weight: 600; color: var(--error-text); margin-bottom: 8px; }
.zona-peligro p  { font-size: 13px; color: var(--error-text); line-height: 1.6; opacity: .92; }

.aviso-incoherente {
	margin-top: 4px; font-size: 11.5px; line-height: 1.4;
	color: var(--warn-text); max-width: 220px;
}

textarea.form-control { resize: vertical; min-height: 120px; line-height: 1.6; font-family: inherit; }

/* ── Perfil ──────────────────────────────────────────────────────────────── */

.perfil-estado {
	display: flex; align-items: flex-start; justify-content: space-between;
	gap: 14px; flex-wrap: wrap;
}

.perfil-foto { display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap; }
.perfil-foto-campo { flex: 1; min-width: 220px; }
.perfil-foto-campo label {
	display: block; font-size: 13px; font-weight: 500;
	color: var(--text-main); margin-bottom: 6px;
}

.avatar-actual {
	width: 84px; height: 84px; flex-shrink: 0;
	border-radius: 50%; overflow: hidden;
	background: var(--input-bg); border: 1.5px solid var(--input-border);
	display: flex; align-items: center; justify-content: center;
}
/* El logotipo de una empresa no se recorta en círculo: se le comen las
   esquinas y muchos son cuadrados con el nombre dentro. */
.avatar-cuadrado { border-radius: 12px; }
.avatar-actual img { width: 100%; height: 100%; object-fit: cover; }
.avatar-vacio {
	font-size: 30px; font-weight: 600; color: var(--litsea-primary);
	text-transform: uppercase; line-height: 1;
}

/* input[type=file] no acepta padding como los demás: sin esto queda más alto
   que el resto de campos de la misma fila. */
input[type="file"].form-control { padding: 8px 10px; font-size: 12.5px; cursor: pointer; }

/* Un campo que se enseña y no se edita — el correo. Se ve distinto a un input
   deshabilitado a propósito: deshabilitado sugiere "ahora no"; esto es "no
   desde aquí", y la ayuda de al lado dice por dónde. */
.campo-fijo {
	padding: 11px 14px;
	border: 1.5px dashed var(--input-border); border-radius: 10px;
	background: var(--input-bg);
	font-size: 13.5px; color: var(--text-muted);
	overflow-wrap: anywhere;
}

/* ── Barra de progreso y lista de comprobación ───────────────────────────── */

.progreso-cab {
	display: flex; justify-content: space-between; align-items: baseline;
	font-size: 12.5px; color: var(--text-muted); margin-bottom: 6px;
}
.progreso-cab strong { font-size: 15px; color: var(--text-dark); }

.progreso-barra {
	height: 6px; border-radius: 99px; background: var(--input-border); overflow: hidden;
}
.progreso-barra span {
	display: block; height: 100%; background: var(--litsea-primary);
	transition: width .3s;
}

.lista-check { list-style: none; margin: 12px 0 0; padding: 0; }
.lista-check li {
	display: flex; align-items: center; gap: 8px;
	font-size: 13px; line-height: 1.9;
}
.lista-marca { display: inline-flex; align-items: center; justify-content: center; width: 16px; }
.lista-marca svg { width: 15px; height: 15px; }
.lista-hecha { color: var(--ok-text); }
.lista-falta { color: var(--text-muted); }

/* ── Fichas de revisión (admin) ──────────────────────────────────────────── */

.ficha-cab { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.ficha-datos { flex: 1; min-width: 220px; }

.avatar-mini { width: 46px; height: 46px; }
.avatar-mini .avatar-vacio { font-size: 18px; }

/* Al llegar desde el panel con #t12, el navegador deja la tarjeta pegada al
   borde superior y debajo de la barra fija. Con esto queda a la vista. */
.ficha { scroll-margin-top: 80px; }

.ficha-cifras {
	display: flex; flex-wrap: wrap; gap: 6px 18px;
	margin-top: 12px; padding-top: 12px;
	border-top: 1px solid #f2f4f5;
	font-size: 12.5px; color: var(--text-muted);
}
.ficha-cifras strong { color: var(--text-dark); font-weight: 600; }

/* Texto suelto, no recuadro: va DENTRO de la ficha, y una caja ámbar dentro
   de una tarjeta blanca es justo el apilamiento que el cliente rechazó.

   La línea entera va en ámbar y no sólo su etiqueta: las otras dos cosas que
   usan esta clase —«no ha puesto sitio web», «no ha escrito descripción»—
   son frases sin etiqueta que colorear, y en gris quedaban indistinguibles del
   correo de arriba. Es una línea corta: el ámbar oscuro se lee sin cansar. */
.aviso-falta {
	margin-top: 10px;
	font-size: 12.5px; color: var(--warn-text); line-height: 1.5;
}

.pestania-n {
	display: inline-block; min-width: 18px; padding: 0 5px;
	border-radius: 100px; background: var(--input-border);
	font-size: 11px; font-weight: 600; text-align: center;
}
.pestania.activa .pestania-n { background: var(--litsea-primary); color: #fff; }

.btn-mini-ok { border-color: var(--ok-border); color: var(--ok-text); }
.btn-mini-ok:hover { background: var(--ok-text); border-color: var(--ok-text); color: #fff; }

/* ── Desplegable de rechazo ──────────────────────────────────────────────── */

/* <details> nativo: el motivo se puede escribir aunque el JavaScript falle. */
.desplegable { display: inline-block; position: relative; }
.desplegable > summary { list-style: none; user-select: none; }
.desplegable > summary::-webkit-details-marker { display: none; }

.desplegable-cuerpo {
	position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
	width: 320px; max-width: 88vw; padding: 14px;
	background: var(--superficie); border: 1px solid var(--input-border); border-radius: 12px;
	box-shadow: 0 10px 30px rgba(0,0,0,.12);
	text-align: left;
}
.desplegable-cuerpo textarea { font-size: 13px; min-height: 76px; }
.desplegable-cuerpo .btn-mini { margin-top: 8px; }

.etiqueta-mini {
	display: block; font-size: 12px; font-weight: 500;
	color: var(--text-main); margin-bottom: 5px;
}

/* ── Opiniones ───────────────────────────────────────────────────────────── */

.cita {
	margin: 12px 0 0; padding: 12px 16px;
	border-left: 3px solid var(--litsea-primary);
	background: var(--input-bg); border-radius: 0 8px 8px 0;
	font-size: 13.5px; line-height: 1.7; color: var(--text-main);
}

/* La estrella dada va rellena y la vacía sólo con contorno: con dos tonos del
   mismo dorado y sin relleno, a 14px no se distingue cuál es cuál. */
.estrellas { display: inline-flex; align-items: center; gap: 1px; margin-left: 6px; vertical-align: -2px; }
.estrellas svg { width: 14px; height: 14px; }
.estrellas .estrella-on  { color: var(--litsea-accent-gold); fill: var(--litsea-accent-gold); stroke: var(--litsea-accent-gold); }
.estrellas .estrella-off { color: var(--input-border); fill: none; stroke: var(--input-border); }

/* ── Pie ─────────────────────────────────────────────────────────────────── */

.pie {
	padding: 18px 28px; border-top: 1px solid var(--input-border);
	background: var(--superficie); text-align: center;
	font-size: 12px; color: var(--text-muted);
}

@media (max-width: 860px) {
	.topbar { flex-wrap: wrap; height: auto; padding: 12px 18px; gap: 12px; }
	.topbar-nav { order: 3; width: 100%; flex: none; }
	.topbar-yo  { margin-left: auto; }
	.topbar-nombre { max-width: 120px; }
	.contenido { padding: 22px 16px 44px; }
}

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

/* ── Candidaturas ────────────────────────────────────────────────────────── */

.flecha { display: inline-flex; align-items: center; color: var(--text-muted); margin: 0 4px; vertical-align: -3px; }
.flecha svg { width: 15px; height: 15px; }

/* Icono de enlace externo, alineado con el texto que lo precede. */
.vac-meta a svg { width: 13px; height: 13px; vertical-align: -2px; }

.form-aplicacion {
	margin-top: 12px; padding-top: 12px;
	border-top: 1px solid #f2f4f5;
}
.form-aplicacion textarea { font-size: 13px; min-height: 56px; }


/* ── Chat ────────────────────────────────────────────────────────────────── */
/*
 * Dos paneles: conversaciones a la izquierda, hilo a la derecha. Cada uno con
 * su propio scroll — el hilo se desplaza sin llevarse la lista, que es lo que
 * permite saltar de una conversación a otra sin perder el sitio.
 */

.sr-solo {
	position: absolute; width: 1px; height: 1px;
	padding: 0; margin: -1px; overflow: hidden;
	clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.chat {
	display: grid;
	grid-template-columns: 290px minmax(0, 1fr);
	gap: 14px;
	/* Altura de la ventana menos el armazón: márgenes de .app-main, su padding
	   y el título de la página. Con min-height para que en pantallas bajas no
	   se quede en una franja inservible. */
	height: calc(100vh - 178px);
	min-height: 420px;
}

/* Volver a la lista: solo existe en móvil, donde la lista no está al lado. */
.chat-volver { display: none; }

/*
 * Móvil: UNA columna. Se enseña la lista O la conversación, decidido por la
 * clase `chat-abierto` que pone el servidor — sin JS. `.chat-col` es el
 * envoltorio del panel en la pantalla del admin.
 */
@media (max-width: 760px) {
	.chat { grid-template-columns: 1fr; height: calc(100vh - 230px); }

	.chat.chat-abierto > .chat-lista { display: none; }
	.chat:not(.chat-abierto) > .chat-panel,
	.chat:not(.chat-abierto) > .chat-col { display: none; }

	.chat-volver {
		display: inline-flex; align-items: center; justify-content: center;
		width: 34px; height: 34px; flex-shrink: 0; border-radius: 9px;
		color: var(--text-muted);
	}
	.chat-volver:hover { background: var(--input-bg); color: var(--text-main); }
	.chat-volver svg { width: 18px; height: 18px; }
}

/* ── Lista de conversaciones ─────────────────────────────────────────────── */

.chat-lista {
	overflow-y: auto;
	border: 1px solid var(--input-border);
	border-radius: 14px;
	background: var(--superficie);
	padding: 6px;
}
.chat-lista-vacia { padding: 16px 12px; font-size: 13px; color: var(--text-muted); line-height: 1.6; }

.chat-item {
	display: flex; flex-direction: column; gap: 3px;
	padding: 10px 11px; margin-bottom: 2px;
	border-radius: 10px; text-decoration: none;
	transition: background .15s;
}
.chat-item:hover  { background: var(--input-bg); }
.chat-item.activo { background: rgba(47,183,164,.10); }

.chat-item-cab { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.chat-item-quien {
	font-size: 13px; font-weight: 600; color: var(--text-dark);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-item-vacante,
.chat-item-ultimo {
	font-size: 11.5px; color: var(--text-muted);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-item-ultimo { color: #a6acb3; }
.chat-item-cerrada {
	align-self: flex-start; margin-top: 2px;
	font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
	color: var(--text-muted);
}

.chat-sin-leer {
	flex-shrink: 0; min-width: 18px; height: 18px; padding: 0 5px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 99px; background: var(--litsea-primary); color: #fff;
	font-size: 10.5px; font-weight: 700;
}

/* ── Hilo ────────────────────────────────────────────────────────────────── */

.chat-col   { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.chat-col .chat-panel { flex: 1; min-height: 0; }

.chat-panel {
	display: flex; flex-direction: column; min-height: 0;
	border: 1px solid var(--input-border);
	border-radius: 14px; background: var(--superficie);
	overflow: hidden;
}
.chat-panel-vacio {
	align-items: center; justify-content: center;
	color: var(--text-muted); font-size: 13.5px;
}

.chat-cab {
	display: flex; align-items: center; justify-content: space-between; gap: 12px;
	padding: 13px 16px; flex-shrink: 0;
	border-bottom: 1px solid var(--input-border);
}
/* El título se queda con el espacio: con el botón de volver delante,
   space-between lo mandaría al centro. */
.chat-cab > div { flex: 1; min-width: 0; }
.chat-cab h2 { font-size: 15px; font-weight: 600; color: var(--text-dark); }
.chat-cab p  { font-size: 12px; color: var(--text-muted); margin-top: 2px; }

.chat-hilo {
	flex: 1; min-height: 0; overflow-y: auto;
	padding: 16px; display: flex; flex-direction: column; gap: 10px;
	background: #fafbfc;
}
.chat-hilo-vacio { margin: auto; font-size: 13px; color: var(--text-muted); }

.chat-burbuja {
	max-width: 74%; align-self: flex-start;
	padding: 8px 12px 6px;
	border: 1px solid var(--input-border);
	border-radius: 12px 12px 12px 4px;
	background: var(--superficie);
}
/* La propia va a la derecha y con el acento al 10%: suficiente para separar de
   un vistazo quién dijo qué, sin convertir el hilo en dos bloques de color. */
.chat-burbuja.mia {
	align-self: flex-end;
	border-radius: 12px 12px 4px 12px;
	background: rgba(47,183,164,.10);
	border-color: rgba(47,183,164,.22);
}

.chat-quien { display: block; font-size: 11px; font-weight: 600; color: var(--litsea-primary-dark); margin-bottom: 2px; }
/* pre-line: respeta los saltos de línea que escribió la persona sin permitir
   marcado — el cuerpo se inserta con textContent, nunca con innerHTML. */
.chat-cuerpo { font-size: 13.5px; line-height: 1.55; color: var(--text-main); white-space: pre-line; }
.chat-hora   { display: block; text-align: right; font-size: 10.5px; color: #b0b6bc; margin-top: 3px; }

.chat-aviso {
	flex-shrink: 0; padding: 12px 16px;
	border-top: 1px solid var(--input-border);
	font-size: 12.5px; color: var(--text-muted); line-height: 1.55;
	background: var(--superficie);
}

/* ── Redactor ────────────────────────────────────────────────────────────── */

.chat-redactor {
	flex-shrink: 0; display: flex; align-items: flex-end; gap: 8px;
	padding: 10px; border-top: 1px solid var(--input-border); background: var(--superficie);
}
.chat-redactor textarea {
	flex: 1; resize: none;
	padding: 9px 12px;
	border: 1.5px solid var(--input-border); border-radius: 10px;
	background: var(--input-bg);
	font-family: inherit; font-size: 13.5px; line-height: 1.5; color: var(--text-main);
	outline: none;
	transition: border-color .2s, box-shadow .2s, background .2s;
}
.chat-redactor textarea:focus {
	border-color: var(--litsea-primary);
	box-shadow: 0 0 0 3px rgba(47,183,164,.15);
	background: var(--superficie);
}

.btn-enviar {
	flex-shrink: 0;
	display: flex; align-items: center; justify-content: center;
	width: 38px; height: 38px;
	border: none; border-radius: 10px; cursor: pointer;
	background: var(--litsea-primary); color: #fff;
	transition: background .2s;
}
.btn-enviar svg { width: 17px; height: 17px; stroke: #fff; }
.btn-enviar:hover    { background: var(--litsea-primary-dark); }
.btn-enviar:disabled { opacity: .55; cursor: not-allowed; }

@media (max-width: 900px) {
	/* Apilado. La lista se acota para que el hilo siga siendo lo que se ve al
	   entrar; mostrar una sola de las dos columnas queda como mejora. */
	.chat { grid-template-columns: 1fr; height: auto; min-height: 0; }
	.chat-lista { max-height: 232px; }
	.chat-panel { height: 62vh; min-height: 380px; }
	.chat-burbuja { max-width: 88%; }
}

/* ── Bitácora ────────────────────────────────────────────────────────────── */

.auditoria-cuenta { font-size: 12.5px; color: var(--text-muted); margin-bottom: 10px; }

/* Dato presente pero secundario: un id, un correo, un «sin admin». Gris en vez
   de oculto — la fila se sigue leyendo sin que el ruido compita con el resto. */
.apagado { color: #b0b6bc; }

.col-fecha   { white-space: nowrap; font-variant-numeric: tabular-nums; }
.col-detalle { max-width: 320px; }

.paginacion {
	display: flex; align-items: center; justify-content: center; gap: 14px;
	margin-top: 16px;
}
.paginacion .btn-mini { display: inline-flex; align-items: center; gap: 4px; }
.paginacion .btn-mini svg { width: 14px; height: 14px; }
.paginacion-pos { font-size: 12.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ═══════════════════════════════════════════════════════════════════════════
   PARTE PÚBLICA — el sitio sin sesión
   ═══════════════════════════════════════════════════════════════════════════
   Mismo lenguaje que el resto (D16): Poppins, iconos Lucide, cero degradados,
   el teal como acento. El armazón es blanco y gris neutro. */

body.publico { background: #fff; }

.pub-ancho { max-width: 1080px; margin: 0 auto; padding: 0 20px; }

/* ── Cabecera ─────────────────────────────────────────────────────────────
   Portada de `css/layout/styles.css` del sitio de marketing (`.navbar`): alto
   de 80px, fija arriba, y sobre el héroe transparente hasta que se baja.

   Es FIJA y no pegajosa porque la variante transparente tiene que montarse
   ENCIMA del vídeo; una cabecera pegajosa empuja el contenido hacia abajo y el
   héroe dejaría de empezar en el borde de la pantalla. A cambio hay que
   devolverle el hueco al resto de páginas — lo hace `.pub-cuerpo`. */

.pub-cab {
	position: fixed; top: 0; left: 0; right: 0; z-index: 60;
	background: rgba(255,255,255,.94); backdrop-filter: blur(6px);
	border-bottom: 1px solid var(--input-border);
	transition: background .3s, border-color .3s, box-shadow .3s;
}
.pub-cab-fila { display: flex; align-items: center; gap: 18px; height: 80px; }

/* Las páginas sin héroe recuperan el alto que la cabecera fija les quitó. La
   que sí lo tiene arranca pegada arriba: el vídeo empieza en el píxel 0. */
.pub-cuerpo       { padding-top: 80px; }
.pub-cuerpo-heroe { padding-top: 0; }

.pub-marca { display: flex; align-items: center; gap: 10px; text-decoration: none; flex-shrink: 0; }
.pub-marca img { height: 44px; width: auto; transition: filter .3s; }
.pub-marca span { font-size: 14.5px; font-weight: 700; color: var(--text-dark); white-space: nowrap; }

.pub-nav { display: flex; gap: 4px; flex: 1; justify-content: center; flex-wrap: wrap; }
.pub-nav-item {
	padding: 7px 12px; border-radius: 9px;
	font-size: 13.5px; font-weight: 500; color: var(--text-muted);
	text-decoration: none; transition: background .15s, color .15s;
}
.pub-nav-item:hover  { background: var(--input-bg); color: var(--text-main); }
.pub-nav-item.activo { color: var(--litsea-primary-dark); font-weight: 600; }

.pub-cab-acciones { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.pub-idioma {
	font-size: 12px; font-weight: 700; letter-spacing: .04em;
	color: var(--text-muted); text-decoration: none; padding: 6px 8px; border-radius: 8px;
}
.pub-idioma:hover { background: var(--input-bg); color: var(--text-main); }

/* ── Cabecera sobre el héroe ──────────────────────────────────────────────
   Mientras está arriba del todo no tiene fondo ni línea: el vídeo pasa por
   detrás. Al bajar 24px (lo pone `cabecera.js`) recupera el blanco de siempre,
   así que el estado por defecto de arriba es también el estado final. */

.pub-cab-heroe {
	background: transparent; border-bottom-color: transparent;
	backdrop-filter: none; box-shadow: none;
}
/* El logo es de color; sobre el vídeo se apaga a blanco puro. Es el mismo
   recurso del sitio: una sola imagen y una regla, en vez de un segundo archivo
   que haya que recordar cambiar cuando cambie la marca. */
.pub-cab-heroe .pub-marca img { filter: brightness(0) invert(1); }
.pub-cab-heroe .pub-nav-item        { color: rgba(255,255,255,.85); }
.pub-cab-heroe .pub-nav-item:hover  { background: rgba(255,255,255,.14); color: #fff; }
.pub-cab-heroe .pub-nav-item.activo { color: #fff; font-weight: 600; }
.pub-cab-heroe .pub-cab-menu        { color: #fff; }
/* El CTA NO cambia sobre el héroe: es teal con texto blanco en los dos estados.
   Hacerlo transparente encima del vídeo lo dejaba a merced de lo que hubiera
   detrás, y es la única acción de la barra. */

.pub-cab-heroe.es-scroll {
	background: rgba(255,255,255,.94); backdrop-filter: blur(6px);
	border-bottom-color: var(--input-border);
	box-shadow: 0 2px 12px rgba(0,0,0,.06);
}
.pub-cab-heroe.es-scroll .pub-marca img { filter: none; }
.pub-cab-heroe.es-scroll .pub-nav-item        { color: var(--text-muted); }
.pub-cab-heroe.es-scroll .pub-nav-item:hover  { background: var(--input-bg); color: var(--text-main); }
.pub-cab-heroe.es-scroll .pub-nav-item.activo { color: var(--litsea-primary-dark); }
.pub-cab-heroe.es-scroll .pub-cab-menu        { color: var(--litsea-primary); }
/* ── El único botón de la cabecera ────────────────────────────────────────
   Calcado del `.navbar-btn` del sitio de marketing: `padding: .6rem 1.4rem`,
   `border-radius: .5rem`, peso 500 y el teal de la casa con texto blanco.

   Va con clase propia y NO con `.btn-mini` a propósito: los `.btn-mini` de la
   cabecera cambiaban de color según el estado del héroe, y éste tiene que
   verse igual siempre. Con clase aparte no hay reglas que pelear. */
.pub-cab-cta {
	display: inline-flex; align-items: center; justify-content: center;
	padding: .6rem 1.4rem;
	background: var(--litsea-primary);
	color: #fff;
	border: 0; border-radius: .5rem;
	font-size: .85rem; font-weight: 500; line-height: 1.3;
	text-decoration: none; white-space: nowrap; cursor: pointer;
	transition: background .3s, transform .2s;
}
.pub-cab-cta:hover {
	background: var(--litsea-primary-dark);
	color: #fff;
	transform: translateY(-1px);
}

/* ── El cajón de móvil ────────────────────────────────────────────────────
   Mismo patrón que el menú lateral con sesión (09 §3-ter): el estado lo lleva
   una clase en <html> y no el atributo `hidden`, para que el velo, el cajón y
   el bloqueo del scroll no puedan discrepar entre sí. Y las tres propiedades
   —`opacity`, `visibility` y `pointer-events`—, que es lo que faltaba cuando el
   velo se tragaba todos los toques con el menú cerrado. */

.pub-cab-menu {
	display: none;
	align-items: center; justify-content: center;
	width: 42px; height: 42px; margin-left: auto;
	background: none; border: 0; border-radius: 10px; cursor: pointer;
	color: var(--litsea-primary); transition: background .2s, color .3s;
}
.pub-cab-menu:hover { background: rgba(47,183,164,.1); }
.pub-cab-menu svg   { width: 26px; height: 26px; }

.pub-velo {
	position: fixed; inset: 0; z-index: 70;
	background: rgba(0,0,0,.45);
	opacity: 0; visibility: hidden; pointer-events: none;
	transition: opacity .3s, visibility .3s;
}

.pub-cajon {
	position: fixed; top: 0; right: 0; bottom: 0; z-index: 80;
	width: min(360px, 100%);
	background: #fff;
	display: flex; flex-direction: column;
	transform: translateX(100%);
	visibility: hidden;
	transition: transform .3s ease, visibility .3s;
	overflow-y: auto;
	box-shadow: -10px 0 30px rgba(0,0,0,.08);
}
.pub-cajon-cab {
	display: flex; align-items: center; justify-content: space-between;
	padding: 18px 20px; border-bottom: 1px solid var(--input-border);
}
.pub-cajon-cerrar {
	display: flex; align-items: center; justify-content: center;
	width: 40px; height: 40px;
	background: none; border: 0; border-radius: 10px; cursor: pointer;
	color: var(--litsea-primary); transition: background .2s;
}
.pub-cajon-cerrar:hover { background: rgba(47,183,164,.1); }
.pub-cajon-cerrar svg   { width: 22px; height: 22px; }

.pub-cajon-nav { display: flex; flex-direction: column; }
.pub-cajon-item {
	/* 56px de alto real: por debajo de 44 el dedo falla, y este menú se usa
	   exactamente con el dedo. */
	display: flex; align-items: center; min-height: 56px; padding: 0 20px;
	font-size: 16px; font-weight: 500; color: var(--text-main);
	text-decoration: none; border-bottom: 1px solid var(--input-border);
	transition: background .2s, color .2s;
}
.pub-cajon-item:hover  { background: #f2fbf9; color: var(--litsea-primary); }
.pub-cajon-item.activo {
	color: var(--litsea-primary-dark); font-weight: 600;
	border-left: 3px solid var(--litsea-primary); padding-left: 17px;
}
.pub-cajon-acciones { display: flex; flex-direction: column; gap: 10px; padding: 20px; }
/* En el cajón el botón ocupa el ancho: es la única acción y hay sitio de sobra.
   Alto de 48px, por encima de los 44 que hacen falta para acertar con el dedo. */
.pub-cajon-acciones .pub-cab-cta { padding: 14px 20px; font-size: 15px; }

/* Abierto */
.pub-cajon-abierto .pub-velo {
	opacity: 1; visibility: visible; pointer-events: auto;
}
.pub-cajon-abierto .pub-cajon { transform: translateX(0); visibility: visible; }

@media (max-width: 899px) {
	.pub-cab-fila     { height: 68px; }
	.pub-cuerpo       { padding-top: 68px; }
	.pub-cuerpo-heroe { padding-top: 0; }
	.pub-marca img    { height: 38px; }
	.pub-nav, .pub-cab-acciones { display: none; }
	.pub-cab-menu     { display: flex; }
}
@media (min-width: 900px) {
	/* Ni existen en escritorio: así el tabulador tampoco los encuentra. */
	.pub-cajon, .pub-velo { display: none; }
}

/* Botón de marca: el único lleno de teal en todo el cromo. */
.btn-mini-marca {
	background: var(--litsea-primary); border-color: var(--litsea-primary); color: #fff;
}
.btn-mini-marca:hover {
	background: var(--litsea-primary-dark); border-color: var(--litsea-primary-dark); color: #fff;
}

/* ── Escala de la parte pública ──────────────────────────────────────────── */
/*
 * La portada juega en otra liga que el panel, y a propósito.
 *
 * El panel es una herramienta: densidad alta, 13px, todo a la vista. La portada
 * es un escaparate, y a la escala del panel se leía como una pantalla interna
 * con el menú quitado. Lo que la referencia (Serenique) hace distinto no son
 * sus colores —marrón y crema— sino tres cosas que sí se traen:
 *
 *   1. Una serif de display SOLO en los títulos grandes. Es lo que más cambia.
 *   2. Escala grande de verdad: su H1 son 82px, no 46.
 *   3. Aire: secciones de 100–140px de alto en vez de 54.
 *
 * Lo que NO se trae es la paleta: el teal es la marca de Litsea y no se cambia
 * por parecerse a una plantilla de spa. Lo que sí se templa es el gris: el
 * fondo alterno pasa de un gris frío a un crema (--pub-crema), que es lo que da
 * la calidez de la referencia sin tocar el acento.
 *
 * Todo esto vive bajo `.publico`: los paneles no ven ni una de estas reglas.
 */
:root {
	--pub-serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;

	/* Crema en vez del gris frío para las bandas alternas. */
	--pub-crema:  #faf7f1;
	--pub-borde:  #ece7dd;

	/* Aire de sección. En móvil se reduce con su propio media. */
	--pub-aire:   clamp(64px, 9vw, 118px);
}

.publico .pub-sec-gris { background: var(--pub-crema); }

/*
 * Bordes templados SOLO en público.
 *
 * Las tarjetas usan `--input-border` (#e5e7eb), un gris azulado que junto al
 * crema se ve gris de verdad, casi sucio. Aquí pasan a `--pub-borde`, que es el
 * mismo tono pero cálido. Va acotado a `.publico` porque `.vac` y `.tarjeta`
 * también se usan en los paneles, y allí el gris frío es el correcto: el fondo
 * es blanco y gris, no crema.
 */
.publico .vac,
.publico .tarjeta,
.publico .pub-terapeuta { border-color: var(--pub-borde); }

/* Y la cabecera pegajosa, con la misma línea cálida. */
/* La línea cálida va en la cabecera normal, y en la del héroe SÓLO cuando ya
   recuperó el fondo blanco. Transparente sobre el vídeo tiene que ser
   transparente del todo: esta regla lleva `.publico` delante y por eso le ganaba
   por especificidad a `.pub-cab-heroe`, dejando una línea cruzando el vídeo. */
.publico .pub-cab:not(.pub-cab-heroe),
.publico .pub-cab-heroe.es-scroll { border-bottom-color: var(--pub-borde); }

/* ── Héroe y secciones ───────────────────────────────────────────────────── */

/* ── Héroe a pantalla completa ────────────────────────────────────────────
   Portado del `#inicio` del sitio de marketing: vídeo a sangre, velo encima y
   el texto a la izquierda, ocupando el alto de la ventana.

   `100dvh` DESPUÉS de `100vh` y no en vez de: en móvil, `vh` cuenta la ventana
   con la barra de direcciones desplegada, así que el héroe queda más alto que
   la pantalla y el primer gesto de la persona es corregirlo. `dvh` mide lo que
   de verdad se ve; el `vh` de arriba queda de respaldo para quien no lo tenga. */

.pub-heroe {
	position: relative;
	min-height: 100vh;
	min-height: 100dvh;
	display: flex; align-items: center;
	overflow: hidden;
	background: #101314;   /* mientras carga el póster, negro y no blanco */
}

/* Vídeo e imagen ocupan el mismo hueco: en cada tamaño se ve uno de los dos. */
.pub-heroe-video,
.pub-heroe-img {
	position: absolute; inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
	z-index: 0;
}
/* En escritorio manda el vídeo, así que la imagen sobra: si se dejara visible
   se vería un instante por debajo mientras el vídeo arranca. */
.pub-heroe-img { display: none; }

.pub-heroe-velo {
	position: absolute; inset: 0; z-index: 1;
	/*
	 * DEGRADADO, y es una excepción consciente a D16 regla 2 (decisión del
	 * cliente, 9/8/2026 — anotada en `00-INDICE-Y-DECISIONES.md`).
	 *
	 * Son dos capas y cada una hace un trabajo distinto:
	 *  · la vertical oscurece la franja de arriba —donde va la cabecera
	 *    transparente, que si no se pierde sobre un plano claro del vídeo— y la
	 *    de abajo, que es donde el ojo busca el borde de la sección;
	 *  · la horizontal carga el lado izquierdo, que es donde está el texto.
	 *
	 * El sitio de marketing resuelve esto con un `rgba(0,0,0,.8)` plano. Se ve
	 * bien, pero apaga el vídeo entero para proteger un texto que sólo ocupa el
	 * tercio izquierdo. Aquí el vídeo se ve donde no estorba.
	 */
	background:
		linear-gradient(180deg,
			rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 22%,
			rgba(0,0,0,0) 62%,  rgba(0,0,0,.62) 100%),
		linear-gradient(90deg,
			rgba(0,0,0,.82) 0%, rgba(0,0,0,.46) 52%, rgba(0,0,0,.24) 100%);
}

.pub-heroe-contenido {
	position: relative; z-index: 2;
	width: 100%;
	padding-top: 96px;    /* el hueco de la cabecera fija, que aquí va encima */
	padding-bottom: 48px;
	text-align: left;
}

.pub-heroe h1 {
	font-family: var(--pub-serif);
	/* Hasta 78px: la referencia usa 82 sobre un lienzo más ancho. Con la serif
	   el mismo tamaño «pesa» menos que en Poppins, así que sube sin gritar. */
	font-size: clamp(34px, 6.4vw, 78px);
	font-weight: 400;          /* la serif ya tiene cuerpo; en 700 se emborrona */
	color: #fff;
	letter-spacing: -.015em;
	line-height: 1.06;
	max-width: 15ch;           /* dos o tres líneas: un titular de una sola línea larga no se lee, se barre */
	margin: 0;
}
.pub-heroe p {
	margin: 22px 0 0; max-width: 46ch;
	font-size: clamp(15px, 1.5vw, 18px); line-height: 1.65;
	color: rgba(255,255,255,.88);
}
.pub-heroe-cta {
	display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 26px;
}
.pub-heroe .pub-heroe-cta { justify-content: flex-start; margin-top: 32px; }
.pub-heroe-cta .btn-mini {
	padding: 13px 26px; font-size: 14.5px; border-radius: 999px;
}

/* Botón claro sobre fondo oscuro: el contrapunto del de marca. Vive aquí y no
   junto a `.btn-mini` porque sólo tiene sentido sobre una imagen. */
.btn-mini-claro {
	background: #fff; border-color: #fff; color: var(--text-dark);
}
.btn-mini-claro:hover { background: rgba(255,255,255,.88); border-color: rgba(255,255,255,.88); }

/* El corte del vídeo es 768px: **teléfono** abajo, **tablet y PC** arriba.
   Antes estaba en 720, que dejaba fuera del vídeo a algún teléfono grande en
   apaisado pero también quedaba a 48px de la frontera real entre teléfono y
   tablet. 768 es el mismo umbral que usa el sitio de marketing en su pie, así
   que las dos propiedades cortan por el mismo sitio.

   ⚠️ Este número está DUPLICADO en `js/cabecera.js` (`min-width: 768px`), que
   es lo que decide si se pide el archivo. Si cambia aquí, cambia allí: si se
   descuadran, o se descarga un vídeo que no se ve, o se ve un hueco negro. */
@media (max-width: 767px) {
	/* Se cambia el vídeo por la imagen. `cabecera.js` además no llega a pedir
	   el archivo, así que en teléfono no se descargan los 24 MB. */
	.pub-heroe-video { display: none; }
	.pub-heroe-img   { display: block; }

	.pub-heroe-contenido { padding-top: 84px; padding-bottom: 40px; }
	/* Centrado: con el ancho de un móvil, el texto a la izquierda deja un
	   margen derecho que parece un error de maquetación. */
	.pub-heroe-contenido,
	.pub-heroe h1 { text-align: center; }
	.pub-heroe h1 { max-width: none; }
	.pub-heroe p  { margin-left: auto; margin-right: auto; }
	.pub-heroe .pub-heroe-cta { justify-content: center; }
	.pub-heroe-velo {
		/* Sin el texto a un lado, la capa horizontal ya no pinta nada: se deja
		   sólo la vertical, algo más cargada porque el texto va centrado. */
		background: linear-gradient(180deg,
			rgba(0,0,0,.62) 0%, rgba(0,0,0,.45) 30%,
			rgba(0,0,0,.5) 62%, rgba(0,0,0,.78) 100%);
	}
}

.pub-sec      { padding: var(--pub-aire) 0; }
.pub-sec-gris { background: #f4f5f6; }

/*
 * Hueco para la cabecera cuando se llega por un ancla del menú.
 *
 * ⚠️ Esto NO es redundante con el `offset: -70` de Lenis, y conviene tenerlo
 * claro antes de borrarlo por duplicado. `publico.js` se corta ENTERO en su
 * línea 32 con `prefers-reduced-motion`, así que para esas personas —y para
 * quien tenga el JS caído o desactivado— el salto lo hace el navegador, sin
 * Lenis y sin offset. Sin este margen, el título de la sección aterriza DEBAJO
 * de la cabecera fija y parece que el enlace llevó al sitio equivocado.
 *
 * El valor sigue al alto real de la cabecera (80px, 68 por debajo de 900) más
 * un respiro para que la etiqueta de sección no quede pegada al borde.
 */
.pub-heroe[id], .pub-sec[id] { scroll-margin-top: 96px; }
@media (max-width: 899px) {
	.pub-heroe[id], .pub-sec[id] { scroll-margin-top: 84px; }
}

/*
 * La etiqueta de sección. Es lo único que se trae del sistema del Next.js tal
 * cual: teal, mayúsculas, muy espaciada y pequeña, encima del titular.
 *
 * No es decoración. Los títulos son serif de hasta 52px y, al bajar por la
 * página, sin nada delante el ojo no distingue dónde termina un bloque y empieza
 * el siguiente — todos arrancan igual. La etiqueta le da un punto de anclaje que
 * se lee antes que el titular por contraste de color, no de tamaño.
 */
.pub-sec-eti {
	margin-bottom: 14px;
	font-size: 11px; font-weight: 700;
	letter-spacing: .25em; text-transform: uppercase;
	color: var(--litsea-primary);
}
.pub-sec-cab h2 {
	font-family: var(--pub-serif);
	font-size: clamp(28px, 4.2vw, 52px); font-weight: 400;
	color: var(--text-dark); letter-spacing: -.012em; line-height: 1.1;
	max-width: 20ch;
}
.pub-sec-sub {
	margin-top: 12px; max-width: 56ch;
	font-size: clamp(14px, 1.2vw, 16.5px); line-height: 1.65; color: var(--text-muted);
}
.pub-sec-cab    { margin-bottom: clamp(26px, 3.5vw, 48px); }
.pub-sec-mas    { margin-top: clamp(24px, 3vw, 44px); text-align: center; }
/*
 * Los cierres de sección («ver todas las vacantes», «deja tu opinión») eran
 * texto subrayado suelto: a la escala nueva quedaban como una errata al pie
 * de un bloque grande, y en móvil el área que se toca eran tres palabras.
 * Ahora son botón de contorno, con la misma píldora que el héroe.
 */
.pub-sec-mas a {
	display: inline-flex; align-items: center; gap: 8px;
	min-height: 44px; padding: 0 26px;
	border: 1px solid var(--pub-borde); border-radius: 999px;
	font-size: 14px; font-weight: 600;
	color: var(--litsea-primary-dark); text-decoration: none;
	background: #fff;
	transition: border-color .15s ease-in-out, background .15s ease-in-out;
}
.pub-sec-mas a:hover {
	border-color: var(--litsea-primary); background: rgba(47,183,164,.06);
	text-decoration: none;
}
/* Sobre el crema el botón blanco desaparece; ahí se invierte. */
.pub-sec-gris .pub-sec-mas a { background: #fff; }

/*
 * La excepción: el CTA de «Para hoteles y spas» va RELLENO, no de contorno. Es
 * la única llamada de la portada dirigida al empleador y tiene que sostener un
 * bloque entero que le habla a la terapeuta.
 *
 * ⚠️ Hay que declararlo aquí, y no basta con ponerle `.btn-mini-marca` en el
 * HTML, por especificidad — que además producía un fallo de los que no se ven
 * leyendo el marcado:
 *
 *   ·  En reposo, `.pub-sec-mas a` (0,1,1) le ganaba a `.btn-mini-marca`
 *      (0,1,0), así que el relleno teal no llegaba a aplicarse nunca.
 *   ·  En `:hover` la cosa empeoraba. `.pub-sec-mas a:hover` (0,2,1) ponía el
 *      fondo —un teal al 6%, casi blanco— pero NO declara `color`, así que el
 *      texto lo seguía decidiendo `.btn-mini-marca:hover` (0,2,0) con su
 *      `#fff`. Resultado: texto blanco sobre fondo casi blanco. El botón se
 *      borraba al pasar el ratón.
 *
 * Va DESPUÉS de `.pub-sec-gris .pub-sec-mas a` a propósito: las dos valen
 * (0,2,1) y ahí decide el orden de aparición. Moverla más arriba devuelve el
 * fondo blanco a la sección de hoteles, que es `pub-sec-gris`.
 */
.pub-sec-mas a.btn-mini-marca {
	background: var(--litsea-primary);
	border-color: var(--litsea-primary);
	color: #fff;
}
.pub-sec-mas a.btn-mini-marca:hover {
	background: var(--litsea-primary-dark);
	border-color: var(--litsea-primary-dark);
	color: #fff;
}

/* ── Terapeutas ──────────────────────────────────────────────────────────── */

.pub-terapeutas {
	display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px;
}
.pub-terapeuta {
	display: flex; flex-direction: column; align-items: center; gap: 8px;
	padding: 22px 16px; text-align: center; text-decoration: none;
	background: #fff; border: 1px solid var(--input-border); border-radius: 14px;
	transition: border-color .15s, box-shadow .15s;
}
.pub-terapeuta:hover { border-color: var(--litsea-primary); box-shadow: 0 4px 14px rgba(0,0,0,.05); }
.pub-terapeuta-nombre { font-size: 14.5px; font-weight: 600; color: var(--text-dark); }
.pub-terapeuta-marcas { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; }
.pub-terapeuta-dato   { font-size: 12.5px; color: var(--text-muted); }

.avatar-grande { width: 96px; height: 96px; }
.avatar-grande .avatar-vacio { font-size: 34px; }

/* ── Cómo funciona / hoteles ─────────────────────────────────────────────── */

/* ── Cómo funciona: acordeón ─────────────────────────────────────────────
 *
 * Cuatro pasos, un texto abierto. Antes eran cuatro columnas con sus cuatro
 * párrafos a la vez: cuatro bloques compitiendo justo donde se explica un
 * proceso, que es lo contrario de lo que la sección quiere contar.
 *
 * Sin JavaScript los cuatro quedan abiertos —el `[data-acordeon]` del script es
 * quien cierra los tres inactivos al arrancar—, así que el contenido está
 * siempre completo para el buscador y para quien navegue sin scripts.
 * ─────────────────────────────────────────────────────────────────────── */

/*
 * En pantalla ancha, título a la izquierda y pasos a la derecha. El acordeón es
 * una columna estrecha —una lista quiere serlo—, y sola en un ancho de 1440
 * dejaba media pantalla vacía a la derecha. Es la misma estructura de dos
 * columnas del Next.js, sin la ilustración: poner un dibujo de relleno para
 * tapar el hueco habría sido peor que el hueco.
 */
@media (min-width: 1000px) {
	.pub-sec-como .pub-ancho {
		display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
		gap: clamp(32px, 5vw, 80px); align-items: start;
	}
	/* Sin `position: sticky`: la sección mide unos 300px, así que el título nunca
	   llegaría a despegarse, y a cambio se desalinea del primer paso. */
	.pub-sec-como .pub-sec-cab { margin-bottom: 0; }
}

.pub-pasos { list-style: none; margin: 0; padding: 0; max-width: 760px; }

.pub-paso {
	border-top: 1px solid var(--pub-borde);
	transition: background .25s ease;
}
.pub-paso:last-child { border-bottom: 1px solid var(--pub-borde); }
.pub-paso.es-activo  { background: #fff; }

/* Botón, no div: se llega con Tab y se abre con Enter o Espacio de fábrica. */
.pub-paso-cab {
	display: flex; align-items: baseline; gap: 16px; width: 100%;
	padding: clamp(18px, 2vw, 24px) clamp(14px, 1.6vw, 20px);
	background: none; border: 0; text-align: left; cursor: pointer;
	font: inherit; color: inherit;
}
.pub-paso-cab:focus-visible {
	outline: 2px solid var(--litsea-primary); outline-offset: -2px; border-radius: 10px;
}
.pub-paso-n {
	flex: none;
	font-size: 12px; font-weight: 700; line-height: 1;
	font-variant-numeric: tabular-nums;
	color: var(--pub-borde-fuerte, #d4d4d4);
	transition: color .3s ease;
}
.pub-paso-tit {
	font-family: var(--pub-serif);
	font-size: clamp(18px, 1.8vw, 24px); font-weight: 400; line-height: 1.25;
	color: var(--text-muted);
	transition: color .3s ease;
}
.pub-paso.es-activo .pub-paso-n   { color: var(--litsea-primary); }
.pub-paso.es-activo .pub-paso-tit { color: var(--text-dark); }

/*
 * `grid-template-rows: 0fr → 1fr` en vez de animar `height`. Es la única forma
 * de que la transición sea suave SIN saber la altura de antemano: `height: auto`
 * no es animable, y medirla en JavaScript se rompe cuando la fuente termina de
 * cargar y el texto se reajusta.
 */
.pub-paso-cuerpo {
	display: grid; grid-template-rows: 0fr;
	transition: grid-template-rows .3s ease;
}
.pub-paso.es-activo .pub-paso-cuerpo { grid-template-rows: 1fr; }
.pub-paso-cuerpo > p {
	overflow: hidden;
	margin: 0; padding: 0 clamp(14px, 1.6vw, 20px);
	font-size: clamp(13.5px, 1.1vw, 15.5px); line-height: 1.7; color: var(--text-muted);
	opacity: 0; transition: opacity .25s ease .05s, padding-bottom .3s ease;
}
.pub-paso.es-activo .pub-paso-cuerpo > p {
	opacity: 1; padding-bottom: clamp(18px, 2vw, 24px);
}

/* Sin JS no hay clase `es-activo` en nadie: se abren todos y nada se pierde. */
.pub-pasos:not([data-listo]) .pub-paso-cuerpo     { grid-template-rows: 1fr; }
.pub-pasos:not([data-listo]) .pub-paso-cuerpo > p { opacity: 1; padding-bottom: 20px; }

/* ── Para hoteles: tres ventajas en tarjeta, alineadas a la izquierda ─────
 *
 * Centrado, un bloque de tres obliga al ojo a buscar el arranque de cada línea
 * en un sitio distinto. A la izquierda hay un solo eje y se leen en diagonal.
 * ─────────────────────────────────────────────────────────────────────── */

.pub-ventajas {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: clamp(14px, 1.8vw, 20px);
}
.pub-ventaja {
	display: flex; flex-direction: column; align-items: flex-start;
	padding: clamp(22px, 2.4vw, 30px);
	background: #fff;
	border: 1px solid var(--pub-borde); border-radius: 18px;
	transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.pub-ventaja:hover {
	border-color: var(--litsea-primary);
	box-shadow: 0 6px 20px rgba(0,0,0,.05);
	transform: translateY(-2px);
}
/* El icono en su propia caja: así el título arranca a la misma altura en las
   tres aunque uno ocupe dos líneas. */
.pub-ventaja-ico {
	display: inline-flex; align-items: center; justify-content: center;
	width: 44px; height: 44px; margin-bottom: 18px;
	border-radius: 12px;
	background: rgba(47,183,164,.1); color: var(--litsea-primary-dark);
}
.pub-ventaja-ico svg { width: 22px; height: 22px; }
.pub-ventaja h3 {
	font-family: var(--pub-serif);
	font-size: clamp(18px, 1.7vw, 23px); font-weight: 400; line-height: 1.25;
	color: var(--text-dark);
}
.pub-ventaja p {
	margin-top: 10px;
	font-size: clamp(13.5px, 1.1vw, 15px); line-height: 1.7; color: var(--text-muted);
}

/* ── Opiniones ───────────────────────────────────────────────────────────── */

.pub-sec-opiniones { background: #fdfaf5; }

/* Título a la izquierda y el botón de opinar a la derecha, alineados abajo.
   El «deja tu opinión» estaba al pie de la sección: quien acaba de leer diez
   reseñas ya ha decidido, y para actuar tenía que llegar al final del bloque. */
.pub-opiniones-cab {
	display: flex; flex-direction: column; gap: 20px;
	margin-bottom: clamp(26px, 3.5vw, 48px);
}
.pub-opiniones-cab .pub-sec-cab { margin-bottom: 0; }
.pub-opiniones-cta { align-self: flex-start; flex: none; }
@media (min-width: 700px) {
	.pub-opiniones-cab { flex-direction: row; align-items: flex-end; justify-content: space-between; }
	/* Hay que repetirlo: el `align-self: flex-start` de arriba —que en móvil
	   impide que el botón se estire a lo ancho— gana sobre el `align-items` del
	   contenedor, y el botón se quedaba pegado arriba en vez de a la línea base
	   del subtítulo. */
	.pub-opiniones-cta { align-self: flex-end; }
}

/*
 * Columnas fijas por tramo, no `auto-fill`. La paginación reparte 9 / 6 / 3 por
 * página justo para llenar tres filas de 3, 2 y 1 columna; con `auto-fill` el
 * número de columnas lo decide el ancho disponible y deja de cuadrar con el
 * número de tarjetas, así que la última fila queda coja en anchos intermedios.
 */
.pub-opiniones { display: grid; grid-template-columns: 1fr; gap: 14px; }
@media (min-width: 768px)  { .pub-opiniones { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .pub-opiniones { grid-template-columns: repeat(3, 1fr); } }

.pub-opinion {
	display: flex; flex-direction: column;
	margin: 0; padding: clamp(22px, 2.4vw, 30px);
	background: #fff;
	border: 1px solid var(--pub-borde); border-radius: 18px;
	transition: border-color .2s ease, box-shadow .2s ease;
}
.pub-opinion:hover { border-color: rgba(47,183,164,.4); box-shadow: 0 4px 16px rgba(0,0,0,.04); }
.pub-opinion .estrellas { margin-left: 0; }
/* La cita, en serif y con cuerpo: es la voz de una persona, no un dato. */
.pub-opinion blockquote {
	margin: 14px 0 0; flex: 1;
	font-family: var(--pub-serif);
	font-size: clamp(15.5px, 1.4vw, 19px); font-weight: 400; line-height: 1.45;
	color: var(--text-dark);
}
/* Recorte a cuatro líneas. `-webkit-line-clamp` sigue siendo la única forma con
   soporte real; sin él la tarjeta crece y rompe la rejilla de tres filas. */
.pub-opinion.es-largo blockquote {
	display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
	overflow: hidden;
}
.pub-opinion.es-abierta blockquote { display: block; -webkit-line-clamp: none; overflow: visible; }
.pub-opinion-mas {
	align-self: flex-start; margin-top: 8px; padding: 0;
	background: none; border: 0; cursor: pointer;
	font: inherit; font-size: 12.5px; font-weight: 600;
	color: var(--litsea-primary-dark);
}
.pub-opinion-mas:hover { text-decoration: underline; }
.pub-opinion figcaption { margin-top: 16px; display: flex; flex-direction: column; }
.pub-opinion figcaption strong { font-size: 13px; color: var(--text-dark); }
.pub-opinion figcaption span   { font-size: 12px; color: var(--text-muted); }

/* Lo que la paginación esconde. Es `display:none` y no `visibility` para que las
   tarjetas ocultas no ocupen celda en la rejilla. */
.pub-opinion[hidden] { display: none; }

/* ── Paginación ──────────────────────────────────────────────────────────── */

.pub-pag {
	display: flex; align-items: center; justify-content: center; gap: 6px;
	flex-wrap: wrap; margin-top: clamp(28px, 3vw, 40px);
}
.pub-pag button {
	min-width: 40px; height: 40px; padding: 0 12px;
	display: inline-flex; align-items: center; justify-content: center;
	background: #fff; color: var(--text-main);
	border: 1px solid var(--pub-borde); border-radius: 10px;
	font: inherit; font-size: 13.5px; font-weight: 600;
	font-variant-numeric: tabular-nums;
	cursor: pointer;
	transition: border-color .15s, background .15s, color .15s;
}
.pub-pag button:hover:not(:disabled) { border-color: var(--litsea-primary); color: var(--litsea-primary-dark); }
.pub-pag button[aria-current="page"] {
	background: var(--litsea-primary); border-color: var(--litsea-primary); color: #fff;
}
/* Deshabilitado y no escondido: si los extremos desaparecen, el resto de los
   números se desplaza al cambiar de página y hay que volver a apuntar. */
.pub-pag button:disabled { opacity: .35; cursor: default; }
.pub-pag-salto { padding: 0 4px; color: var(--text-muted); font-size: 13.5px; }

/* El selector de calificación: pastillas por radio, sin JS. */
/* ── Especialidades ──────────────────────────────────────────────────────
   Cuatro grupos, cada uno con sus fichas. `auto-fit` y no un número fijo de
   columnas: los grupos son de tamaños muy distintos (Masajes tiene 15 y
   Cosmetología 3), así que dejar que se acomoden solos evita huecos raros. */

/* Columnas CSS y no `grid`. Con `grid` los cuatro grupos son celdas de la misma
   fila: «Masajes» tiene 15 fichas y «Cosmetología» tres, así que la fila crecía
   a la altura de la más larga y el cuarto grupo caía a una segunda fila con un
   hueco enorme al lado. Con `columns` el contenido FLUYE y se reparte solo,
   funcione con cuatro grupos o con seis el día que el catálogo cambie.

   `break-inside: avoid` es lo que impide que un grupo se parta por la mitad
   entre dos columnas, que es el fallo clásico de este enfoque. */
.pub-esp-grupos {
	columns: 3 280px;
	column-gap: clamp(14px, 1.8vw, 20px);
}
/*
 * Ahora cada grupo es una TARJETA, no una columna de texto entre otras. Antes,
 * las treinta especialidades se leían como una lista corrida —«Cosmetología,
 * Faciales, Corporales, Aparatología, Estilismo…»— sin que se viera dónde acaba
 * una familia y empieza la siguiente. Con fondo y borde el agrupamiento es un
 * hecho visual y no algo que el lector tiene que deducir.
 */
.pub-esp-grupo {
	break-inside: avoid;
	-webkit-column-break-inside: avoid;   /* Safari viejo */
	margin-bottom: clamp(14px, 1.8vw, 20px);
	padding: clamp(18px, 2vw, 24px);
	background: #fff;
	border: 1px solid var(--pub-borde); border-radius: 18px;
}
.pub-esp-grupo-cab {
	display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
	padding-bottom: 14px; margin-bottom: 14px;
	border-bottom: 1px solid var(--pub-borde);
}
.pub-esp-grupo-tit {
	font-family: var(--pub-serif);
	font-size: clamp(17px, 1.5vw, 21px); font-weight: 400; line-height: 1.2;
	color: var(--text-dark);
}
/* El contador: «Masajes» con catorce y «Otros» con dos pesan distinto, y
   decirlo antes ahorra contarlas. */
.pub-esp-grupo-n {
	flex: none;
	font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
	color: var(--litsea-primary-dark);
	font-variant-numeric: tabular-nums;
}
.pub-esp-fichas { display: flex; flex-wrap: wrap; gap: 8px; }
.pub-esp-ficha {
	display: inline-flex; align-items: center;
	padding: 8px 14px;
	background: #fff; color: var(--text-main);
	border: 1px solid var(--pub-borde); border-radius: 999px;
	font-size: 13px; font-weight: 500; line-height: 1.3;
	text-decoration: none;
	transition: border-color .2s, color .2s, background .2s;
}
.pub-esp-ficha:hover {
	border-color: var(--litsea-primary);
	color: var(--litsea-primary-dark);
	background: #f2fbf9;
}
/* Sobre la banda gris, la ficha blanca se vería como un botón; al revés se lee
   como parte del fondo. */
.pub-sec-gris .pub-esp-ficha { background: transparent; }
.pub-sec-gris .pub-esp-ficha:hover { background: #fff; }

/* ── Respaldo (logos de instituciones) ───────────────────────────────────
   En gris y al 65%: son marcas de terceros. A todo color compiten con el teal
   de la casa y se llevan la sección, que va de Litsea y no de ellas. */

/* `grid` y no `flex`: los cinco logos tienen anchos naturales muy distintos
   —el de la SEP es cuatro veces más ancho que el de IMA— y con `flex` la fila
   se desbordaba por el más ancho, mandando el quinto a una segunda fila él
   solo. En celdas iguales entran los cinco y cada uno se ajusta dentro. */
.pub-respaldo-logos {
	display: grid; align-items: center; justify-items: center;
	gap: clamp(24px, 4vw, 44px);
	grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}
.pub-respaldo-logos img {
	height: clamp(38px, 5vw, 56px); width: auto;
	object-fit: contain;
	filter: grayscale(1); opacity: .65;
	transition: filter .3s, opacity .3s;
}
.pub-respaldo-logos img:hover { filter: none; opacity: 1; }

/* ── Preguntas frecuentes ────────────────────────────────────────────────
   `<details>` nativo. El único trabajo del CSS es que no parezca el widget por
   defecto del navegador: fuera el triángulo, y el chevron de Lucide gira. */

/* 780px es el ancho de lectura, pero SIN centrarse: va dentro de `.pub-ancho`,
   así que arranca en el mismo margen izquierdo que los títulos de las demás
   secciones. Centrado (que es lo que pasaba al poner las dos clases en el mismo
   div) el bloque quedaba desplazado a la derecha respecto a todo lo de arriba y
   se leía como un descuido. */
/* ── Preguntas frecuentes: preguntas a la izquierda, foto a la derecha ───────
 * La sección era una columna de texto sola contra todo el ancho, y con seis
 * desplegables cerrados quedaba una franja de aire a la derecha más alta que el
 * propio bloque. La foto la ocupa y da el respiro visual antes del cierre.
 * ------------------------------------------------------------------------- */

.pub-faq-fila {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, .78fr);
	gap: clamp(28px, 4vw, 64px);
	align-items: stretch;
}

/* Dentro de la columna sobra el tope de 780px: lo pone ya la rejilla, y con los
   dos a la vez el texto se quedaría corto contra el borde de la foto. */
.pub-faq-fila .pub-faq { max-width: none; }

/*
 * ⚠️ `display: flex` y no una imagen suelta, y esto es lo que hace que
 * «estirada» funcione sin números mágicos.
 *
 * La celda mide lo que mide la fila, y la fila la marca la columna de las
 * preguntas —que crece al abrir un desplegable—. Al ser contenedor flex, la
 * imagen toma por defecto el alto de la caja (`align-items: stretch`), así que
 * la foto sigue a las preguntas sin altura fija, sin `position: absolute` y sin
 * que nadie tenga que recalcular nada al abrir o cerrar una pregunta.
 */
.pub-faq-foto {
	display: flex;
	border-radius: 18px;
	overflow: hidden;
	/* El crema de las bandas: si la imagen tarda o falla, el hueco sigue siendo
	   un bloque de la página y no un rectángulo blanco roto. */
	background: var(--pub-crema);
}
.pub-faq-foto img {
	width: 100%;
	min-height: 0;          /* sin esto puede desbordar la caja al encoger */
	object-fit: cover;      /* recorta, nunca deforma */
	object-position: center;
	display: block;
}

@media (max-width: 900px) {
	/* Mismo corte que el cajón del menú y que el resto de la portada. */
	.pub-faq-fila { grid-template-columns: 1fr; gap: 28px; }
	/*
	 * Apiladas, la celda ya no hereda altura de nadie: sin esto la foto se
	 * quedaría en la que le diera la imagen y el `cover` no recortaría nada.
	 * La proporción se la damos aquí.
	 */
	.pub-faq-foto { aspect-ratio: 16 / 10; }
}

.pub-faq { max-width: 780px; }
.pub-faq-item {
	border-bottom: 1px solid var(--pub-borde);
}
.pub-faq-item summary {
	display: flex; align-items: center; justify-content: space-between; gap: 16px;
	padding: 20px 0;
	font-size: 15.5px; font-weight: 500; color: var(--text-dark);
	cursor: pointer; list-style: none;
}
/* Los dos: WebKit usa el pseudo-elemento y el resto la propiedad. */
.pub-faq-item summary::-webkit-details-marker { display: none; }
.pub-faq-item summary::marker { content: ''; }
.pub-faq-item summary:hover { color: var(--litsea-primary-dark); }
.pub-faq-item summary svg {
	width: 18px; height: 18px; flex-shrink: 0;
	color: var(--text-muted); transition: transform .25s;
}
.pub-faq-item[open] summary svg { transform: rotate(180deg); }
.pub-faq-item p {
	padding: 0 34px 22px 0;
	font-size: 14.5px; line-height: 1.75; color: var(--text-main);
}

.pub-rating { display: flex; gap: 6px; flex-wrap: wrap; }
.pub-rating-op input { position: absolute; opacity: 0; pointer-events: none; }
.pub-rating-op span {
	display: inline-flex; align-items: center; gap: 4px;
	padding: 7px 11px; border: 1px solid var(--input-border); border-radius: 9px;
	font-size: 13px; color: var(--text-muted); cursor: pointer;
}
.pub-rating-op span svg { width: 14px; height: 14px; }
.pub-rating-op input:checked + span {
	border-color: var(--litsea-primary); color: var(--litsea-primary-dark);
	background: rgba(47,183,164,.08); font-weight: 600;
}

/* ── Filtros públicos, perfil, chips ─────────────────────────────────────── */

.pub-filtros { display: flex; gap: 8px; flex-wrap: wrap; }
.pub-filtros .form-control { max-width: 220px; }

.pub-perfil     { max-width: 760px; }
.pub-perfil-cab { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.pub-perfil-cab h1 { font-size: 26px; font-weight: 700; color: var(--text-dark); }

.pub-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }

/* ── Cierre ──────────────────────────────────────────────────────────────── */

.pub-cierre { padding: clamp(72px, 10vw, 132px) 0; background: #101314; text-align: center; }
.pub-cierre h2 {
	font-family: var(--pub-serif);
	font-size: clamp(28px, 4.4vw, 56px); font-weight: 400;
	color: #fff; letter-spacing: -.012em; line-height: 1.1;
	max-width: 18ch; margin: 0 auto;
}
.pub-cierre .pub-heroe-cta { margin-top: 22px; }
.pub-cierre .btn-mini { background: transparent; border-color: #3a4144; color: #d7dcde; }
.pub-cierre .btn-mini:hover { background: #1c2123; color: #fff; }
.pub-cierre .btn-mini-marca { border-color: var(--litsea-primary); color: #fff; }
.pub-cierre .btn-mini-marca:hover { background: var(--litsea-primary-dark); }

/* ── Legales ─────────────────────────────────────────────────────────────── */

.pub-legal { max-width: 760px; }
.pub-legal h1 { font-size: 28px; font-weight: 700; color: var(--text-dark); }
.pub-legal-fecha { margin-top: 6px; font-size: 12.5px; color: var(--text-muted); }
.pub-legal h2 { margin-top: 28px; font-size: 16px; font-weight: 600; color: var(--text-dark); }
.pub-legal p  { margin-top: 10px; font-size: 14px; color: var(--text-main); line-height: 1.75; }

/* ── Pie ─────────────────────────────────────────────────────────────────── */

.pub-pie { background: #101314; padding: clamp(48px, 6vw, 76px) 0 30px; }
/* Estructura del pie de `litseacc.edu.mx` (`.footer-grid` / `.footer-nav`).
   Son DOS bloques, no cuatro columnas: la marca y la navegación. Cada uno
   reparte por dentro, y por eso ninguna columna se queda huérfana al estrechar.

   Antes era `1.7fr repeat(auto-fit, minmax(150px, 1fr))` sobre las cuatro
   sueltas: en tablet el `auto-fit` metía dos por fila y dejaba «Acceso» solo en
   la tercera, con un hueco al lado. */
.pub-pie-fila {
	display: grid; gap: clamp(22px, 3vw, 40px);
	grid-template-columns: 1fr;   /* móvil: uno debajo del otro */
}
.pub-pie-nav {
	display: grid; gap: clamp(20px, 3vw, 32px);
	/* Dos columnas en móvil: tres no caben sin partir los rótulos. Es lo que
	   hace el sitio (`@media (max-width: 767px)` → `repeat(2, 1fr)`). */
	grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 768px) {
	/* La marca pesa menos que el bloque de navegación, que lleva tres columnas.
	   1.4 / 2 son las proporciones del sitio. */
	.pub-pie-fila { grid-template-columns: 1.4fr 2fr; align-items: start; }
	.pub-pie-nav  { grid-template-columns: repeat(3, 1fr); }
}
.pub-pie-logo { width: 64px; height: 64px; object-fit: contain; margin-bottom: 14px; display: block; }

.pub-pie-contacto { margin-top: 14px; display: flex; flex-direction: column; gap: 6px; }
.pub-pie-contacto .pub-pie-txt {
	margin-top: 0; display: flex; align-items: center; gap: 10px; line-height: 1.5;
}
.pub-pie-contacto a { color: #d7dbdd; }
/* El icono en teal, como en el sitio: es el único color del pie aparte del logo. */
.pub-pie-contacto svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--litsea-primary); }

.pub-pie-mapa {
	margin: clamp(28px, 4vw, 44px) 0 0;
	height: 16rem; border-radius: 12px; overflow: hidden;
}
.pub-pie-mapa iframe { width: 100%; height: 100%; border: 0; display: block; }

.pub-pie-marca { font-size: 14px; font-weight: 700; color: #fff; }
.pub-pie-tit   { font-size: 12px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: #8b9498; }
.pub-pie-txt   { margin-top: 8px; font-size: 13px; color: #b9c0c3; line-height: 1.9; }
.pub-pie-txt a { color: #b9c0c3; text-decoration: none; }
.pub-pie-txt a:hover { color: #fff; }
/* Igual que `.footer-bottom` del sitio: apilado y centrado en móvil, en una fila
   con los legales a la derecha desde 768px. Centrar en móvil no es cosmética —
   en columna, «© 2026 Litsea…» alineado a la izquierda y los tres legales
   debajo también a la izquierda se leen como una lista rota. */
.pub-pie-cierre {
	display: flex; flex-wrap: wrap; gap: 10px 24px;
	flex-direction: column; align-items: center; text-align: center;
	margin-top: 38px; padding-top: 20px; border-top: 1px solid #23292b;
}
.pub-pie-copy  { font-size: 12px; color: #8b9498; margin: 0; }
.pub-pie-legal {
	display: flex; flex-wrap: wrap; gap: 18px; margin: 0; font-size: 12px;
	justify-content: center;
}
.pub-pie-legal a { color: #8b9498; }
.pub-pie-legal a:hover { color: #d7dbdd; }

/* ⚠️ Este media query va DESPUÉS de las reglas base a propósito. `.pub-pie-legal`
   y `.pub-pie-cierre` tienen la misma especificidad aquí y ahí (una clase), así
   que decide el orden en el archivo: puesto antes, el `justify-content: center`
   de arriba le ganaba y los legales seguían centrados en escritorio. */
@media (min-width: 768px) {
	.pub-pie-cierre {
		flex-direction: row; align-items: center;
		justify-content: space-between; text-align: left;
	}
	.pub-pie-legal { justify-content: flex-end; }
}

/* 🗑️ Aquí vivía un bloque `@media (max-width: 720px)` del diseño ANTERIOR, de
   cuando la cabecera no tenía cajón y el menú se envolvía en una segunda fila:

       .pub-cab-fila { flex-wrap: wrap; height: auto; padding: 10px 0; … }
       .pub-nav      { order: 3; width: 100%; … }
       .pub-heroe    { padding: 48px 0 40px; }

   Se retira entero, y las tres líneas estorbaban:

   · `padding: 10px 0` ponía los lados a CERO y se comía los 20px de
     `.pub-ancho`. Es por lo que el logo y el botón del menú salían pegados al
     borde de la pantalla en móvil.
   · `.pub-nav` ya no se envuelve: por debajo de 900px es `display: none` y su
     sitio lo ocupa el cajón.
   · El `padding` del héroe peleaba con el nuevo, que va en
     `.pub-heroe-contenido` — aquél es ahora un contenedor a pantalla completa. */

/* ── Revelado al entrar en pantalla ──────────────────────────────────────────
 *
 * Las tarjetas suben 16px y aparecen, escalonadas. Lo dispara `landing.js` con
 * IntersectionObserver poniéndole `data-visible` al contenedor; el retraso de
 * cada hija sale de `--i`, que también lo pone el script.
 *
 * ⚠️ TODO cuelga de `html[data-anim]`, y ese atributo lo pone el script justo
 *    antes de empezar a observar. Es lo único que impide el desastre clásico de
 *    este patrón: ocultar con CSS y revelar con JavaScript deja la página EN
 *    BLANCO el día que el script no carga, falla o llega tarde. Aquí, sin script
 *    no hay `data-anim`, no hay regla que oculte, y se ve todo.
 *
 *    Se descubrió porque un pantallazo de página completa salió con dos secciones
 *    vacías: el observador solo dispara para lo que está en pantalla, y lo de
 *    abajo seguía en opacidad cero. Ese mismo hueco es lo que vería alguien con
 *    el JavaScript bloqueado.
 *
 * Y con `prefers-reduced-motion` no se mueve nada: el contenido aparece y ya.
 * No es una preferencia estética — hay gente a la que el movimiento le provoca
 * náuseas.
 * ─────────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: no-preference) {
	[data-anim] [data-revelar]:not([data-visible]) > * {
		opacity: 0;
		transform: translateY(16px);
	}
	[data-anim] [data-revelar] > * {
		transition: opacity .5s cubic-bezier(.22, 1, .36, 1) calc(var(--i, 0) * 70ms),
		            transform .5s cubic-bezier(.22, 1, .36, 1) calc(var(--i, 0) * 70ms);
	}
}
