/* ══════════════════════════════════════════════════════════════════════
   EL PORTAL — entrar, rellenar la ficha y moderar
   ──────────────────────────────────────────────────────────────────────
   Las cuatro pantallas donde una escuela hace cosas: /school-login,
   /school-dashboard, /school-admin y la pública /for-flight-schools.

   ── LO QUE ESTA HOJA NO HACE ─────────────────────────────────────────
   No define colores. Ni uno. Todo sale de los tokens de
   css/liquid-glass.css (`--c-ink`, `--accent`, `--hairline`…), que ya se
   dan la vuelta solos en modo oscuro. Un `#fff` escrito aquí sería un
   punto blanco sobre negro que nadie recuerda arreglar. Por el mismo
   motivo las superficies son `.liquid-glass` en el HTML: el vidrio, el
   redondeo y la sombra ya están decididos ahí, y aquí solo se pone el
   relleno y la disposición de lo que va dentro.

   ── POR QUÉ REPITE LOS ESTILOS DEL BUSCADOR DE SITIOS ────────────────
   `.place-field`, `.place-suggestions` y `.place-option` también están en
   css/schools.css, y aquí vuelven a estar. No es un descuido: el panel NO
   carga schools.css —son 1.400 líneas de rejilla, tarjetas y mapa que esta
   página no usa— y cargarla entera para heredar un campo de búsqueda sería
   pagar todo eso por cuarenta líneas. La copia es la barata.

   ── EL ORDEN ─────────────────────────────────────────────────────────
     1. Comunes         botones, avisos, campos, cargando
     2. /school-login   los paneles de las cinco vistas
     3. /school-dashboard  la ficha: estado, bloques, mapa, fotos, barra
     4. /school-admin   la mesa de revisión
   ══════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════
   1 · COMUNES
   ══════════════════════════════════════════════════════════════════════ */

/* El portal es una columna estrecha, no la rejilla de 1400 px de la tienda:
   son formularios, y una línea de texto de 1.400 px de ancho no se lee —el
   ojo pierde el renglón al volver a la izquierda. */
.portal-body .main {
  max-width: 62rem;
  gap: clamp(1rem, 2.2vw, 1.5rem);
  padding-bottom: 5rem;
}

/* ── Botones ──────────────────────────────────────────────────────────
   `.btn-primary` y `.btn-ghost` vienen de fuera (styles.css y schools.css);
   `.btn-ghost` hay que traerlo porque el panel no carga schools.css. */

.btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem 1.05rem;
  border-radius: 2.5rem;
  color: rgb(var(--c-body));
  background: var(--pill);
  font-size: 0.79rem;
  font-weight: 700;
  white-space: nowrap;
  transition: background 0.25s var(--lg-ease), color 0.25s var(--lg-ease);
}

.btn-ghost:hover {
  color: rgb(var(--c-ink));
  background: var(--hover-soft);
}

.btn-ghost--icon {
  width: 38px;
  height: 38px;
  padding: 0;
  flex-shrink: 0;
}

.btn-ghost--icon svg {
  width: 16px;
  height: 16px;
}

/* Encendido: destacar y comprobar son interruptores, y un interruptor que
   no dice si está encendido obliga a leer el texto del botón para saberlo. */
.btn-ghost.is-on {
  color: var(--accent-on);
  background: var(--accent);
}

/* Lo que quita, echa o borra no se pinta de rojo en reposo: una fila de
   botones rojos deja de avisar de nada. Se enciende al pasar por encima,
   que es el momento en el que hace falta. */
.btn-ghost--danger:hover {
  color: #fff;
  background: #b91c1c;
}

.btn-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: flex-start;
  gap: 0.5rem;
  padding: 0.85rem 1.6rem;
  border-radius: 2.5rem;
  color: #fff;
  background: #b91c1c;
  font-size: 0.82rem;
  font-weight: 700;
  transition: background 0.25s var(--lg-ease);
}

.btn-danger:hover {
  background: #991b1b;
}

/* Un botón trabajando: apagado y sin cursor de mano. La opacidad es la
   señal de que la pulsación ya se ha registrado —sin ella se pulsa tres
   veces, y tres altas son tres correos a la misma persona. */
button.is-busy,
button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* ── Avisos y errores ─────────────────────────────────────────────────
   Tres tonos y ningún icono de color a secas: el color NO es la única
   señal —el texto dice qué pasa— porque uno de cada doce hombres no
   distingue el rojo del verde. */

.portal-flash {
  padding: 0.85rem 1.15rem;
  border-radius: 1rem;
  border: 1px solid var(--hairline);
  background: var(--pill);
  color: rgb(var(--c-body));
  font-size: 0.86rem;
}

.portal-flash[hidden] {
  display: none;
}

.portal-flash--ok {
  border-color: rgba(21, 128, 61, 0.35);
  background: rgba(21, 128, 61, 0.10);
}

.portal-flash--warn {
  border-color: rgba(180, 83, 9, 0.35);
  background: rgba(180, 83, 9, 0.10);
}

.portal-flash--error {
  border-color: rgba(185, 28, 28, 0.35);
  background: rgba(185, 28, 28, 0.10);
}

/* El error de UN campo va pegado a su campo, no arriba del formulario:
   «ese correo ya tiene cuenta» tres campos por encima del correo obliga a
   buscar a cuál se refiere. */
.portal-error {
  color: #b91c1c;
  font-size: 0.82rem;
  font-weight: 600;
  padding-left: 0.2rem;
}

.portal-error[hidden] {
  display: none;
}

@media (prefers-color-scheme: dark) {
  /* Sobre negro, el rojo oscuro de los avisos no se lee: sube a un rojo
     claro, que es lo mismo que hace el acento invertido de los tokens. */
  .portal-error,
  .form-group.is-missing > label {
    color: #fca5a5;
  }
}

/* ── Campos ───────────────────────────────────────────────────────────
   `.form-group` viene de styles.css. Aquí solo lo que le falta al panel:
   la pista de debajo, el `<select>` (que la tienda no tiene) y el marcado
   de lo que falta para publicar. */

.form-hint {
  color: rgb(var(--c-muted));
  font-size: 0.78rem;
  line-height: 1.5;
  padding-left: 0.2rem;
}

.form-hint--counter {
  align-self: flex-end;
  font-variant-numeric: tabular-nums;
}

.form-group select {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  border-radius: 2.5rem;
  padding: 0.95rem 2.6rem 0.95rem 1.25rem;
  background-color: rgb(var(--c-elevated));
  color: rgb(var(--c-ink));
  font-size: 0.95rem;
  font-family: inherit;
  box-shadow: var(--fieldgroup-shadow);
  transition: box-shadow 0.25s var(--lg-ease);
  /* La flecha, dibujada con un degradado en vez de con una imagen: son dos
     líneas y no una petición más, y hereda el color del texto en oscuro. */
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 1.25rem) 55%, calc(100% - 1rem) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.form-group select:focus {
  outline: none;
  box-shadow: var(--fieldgroup-shadow), var(--accent-ring);
}

/* Los códigos son códigos: monoespaciados, separados y en mayúsculas. Un
   OACI en la misma tipografía que el nombre de la ciudad se lee como una
   palabra rara; así se lee como lo que es. */
.input-code {
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Lo que falta para poder publicar. El aro rojo marca el campo; la lista de
   la barra de guardar dice qué es. Las dos cosas, porque el aro solo se ve
   si el campo está en pantalla. */
.is-missing input,
.is-missing select,
.is-missing textarea {
  box-shadow: var(--fieldgroup-shadow), 0 0 0 2px rgba(185, 28, 28, 0.55);
}

.form-group.is-missing > label {
  color: #b91c1c;
}

.dash-checks.is-missing,
.tag-input.is-missing,
.dash-map.is-missing {
  box-shadow: 0 0 0 2px rgba(185, 28, 28, 0.55);
}

/* El campo trampa. `display: none` no vale: hay robots que lo miran y lo
   saltan precisamente por eso. Se saca de la pantalla, que para una persona
   es lo mismo y para el robot no. */
.form-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ── Mientras se pregunta si hay sesión ───────────────────────────────
   Sin esto la página parpadea: enseña el formulario vacío y lo sustituye
   medio segundo después por el que trae los datos. */
.portal-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 40vh;
  color: rgb(var(--c-muted));
  font-size: 0.9rem;
}

.portal-loading[hidden] {
  display: none;
}

/* ══════════════════════════════════════════════════════════════════════
   2 · /school-login — las cinco vistas
   ══════════════════════════════════════════════════════════════════════ */

.portal-auth {
  max-width: 32rem;
  padding-top: clamp(1rem, 4vw, 3rem);
}

.portal-panel {
  padding: clamp(1.5rem, 4vw, 2.5rem);
}

.portal-panel[hidden] {
  display: none;
}

.portal-panel--centred {
  text-align: center;
}

.portal-panel__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  margin-bottom: 1rem;
  border-radius: 9999px;
  color: var(--accent-on);
  background: var(--accent);
  box-shadow: var(--accent-shadow);
}

.portal-panel__icon svg {
  width: 24px;
  height: 24px;
}

.portal-panel__title {
  color: rgb(var(--c-ink));
  font-size: clamp(1.5rem, 3.5vw, 2rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.15;
}

.portal-panel__subtitle {
  margin-top: 0.5rem;
  color: rgb(var(--c-muted));
  font-size: 0.92rem;
}

.portal-form {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  margin-top: 1.75rem;
}

/* El botón de un formulario ocupa el ancho: en un móvil es el destino de
   todo lo que se acaba de escribir, y un botón pequeño a la izquierda se
   busca con el pulgar. */
.portal-form .btn-primary {
  align-self: stretch;
  margin-top: 0.35rem;
}

.portal-legal {
  color: rgb(var(--c-subtle));
  font-size: 0.75rem;
  line-height: 1.5;
}

.portal-panel__alt {
  margin-top: 1.1rem;
  color: rgb(var(--c-muted));
  font-size: 0.85rem;
  text-align: center;
}

.portal-panel__alt a {
  color: rgb(var(--c-ink));
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ── Entrar con Google ────────────────────────────────────────────────
   El botón va ARRIBA del formulario, no debajo. Quien tiene la cuenta
   enlazada entra de un clic y no tiene que leerse dos campos para
   descubrir que había un atajo; quien usa contraseña se salta una línea.
   El orden de una pantalla de entrar dice cuál es el camino corto.

   Sigue la regla de la casa —aquí no se escribe ni un color— y aun así
   respeta las condiciones de la marca de Google: superficie propia, la «G»
   sin recolorear ni recortar, con su aire alrededor, y una de las frases
   permitidas. Los cuatro colores del logotipo están donde tienen que estar,
   en el `<symbol>` del HTML: son una marca registrada, no una decisión de
   diseño de esta hoja. */

.portal-oauth {
  display: flex;
  flex-direction: column;
  gap: 1.35rem;
  margin-top: 1.75rem;
}

.portal-oauth[hidden] {
  display: none;
}

.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  min-height: 3rem;
  padding: 0.9rem 1.5rem;
  border-radius: 2.5rem;
  background: rgb(var(--c-elevated));
  color: rgb(var(--c-ink));
  font-size: 0.88rem;
  font-weight: 600;
  box-shadow: var(--fieldgroup-shadow);
  transition:
    transform 0.45s var(--lg-spring),
    box-shadow 0.3s var(--lg-ease);
}

.btn-google:hover {
  transform: translateY(-2px);
}

.btn-google:active {
  transform: translateY(0) scale(0.98);
  transition: transform 0.13s var(--lg-ease);
}

.btn-google:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
}

/* 18 px es el tamaño con el que Google publica su botón, y no es
   arbitrario: por debajo, los cuatro trazos de la «G» se empastan. */
.btn-google__mark {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

/* El «o» entre las dos formas de entrar, con su raya a cada lado. Sin la
   raya, la palabra suelta parece el principio de una frase cortada. */
.portal-or {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  color: rgb(var(--c-subtle));
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.portal-or::before,
.portal-or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--hairline);
}

/* ══════════════════════════════════════════════════════════════════════
   3 · /school-dashboard — la ficha
   ══════════════════════════════════════════════════════════════════════ */

.portal-dash[hidden] {
  display: none;
}

/* ── TU CUENTA — la rejilla de lo que tienes ──────────────────────────
   Esta página enseña dos cosas distintas —la ficha de escuela, o la
   cuenta— y esta es la segunda. Aquí hubo una tarjeta centrada que
   ofrecía dar de alta una escuela y nada más; ahora hay una rejilla con
   lo que la cuenta tiene de verdad y, debajo, las puertas de lo que no.

   ── DE DÓNDE SALE EL ASPECTO ──────────────────────────────────────
   De la TIENDA, entero: `.product-grid` y `.product-card` viven en
   css/styles.css, que esta página ya carga, y traen la rejilla que se
   recoloca sola, el material de vidrio, el hueco 4/3 de la foto, la
   cejilla, el título y el pie. Nada de eso se repite aquí.

   Lo que sigue es SÓLO lo que una ficha de tienda no tiene: la chapa de
   estado encima de la foto —un avión puede estar en borrador y un
   producto no— y un pie de dos piezas donde la izquierda es un dato
   (el precio, las preguntas) y la derecha el botón. */

.dash-hub {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.dash-hub[hidden] {
  display: none;
}

.dash-hub__head {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  max-width: 60ch;
}

.dash-hub__title {
  color: rgb(var(--c-ink));
  font-size: clamp(1.4rem, 3.5vw, 2rem);
  font-weight: 900;
  letter-spacing: -0.03em;
}

.dash-hub__text {
  color: rgb(var(--c-muted));
  font-size: 0.95rem;
  line-height: 1.6;
}

.dash-hub__grid[hidden] {
  display: none;
}

/* El rótulo de «empieza algo». Va con un filete encima y no suelto: separa
   lo que YA es tuyo de lo que se te ofrece, que son dos cosas distintas
   pintadas con la misma baldosa. Sin la línea, las puertas se leen como
   una segunda tanda de lo tuyo. */
.dash-hub__more {
  margin-top: 0.6rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--hairline);
  color: rgb(var(--c-subtle));
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.dash-hub__more[hidden] {
  display: none;
}

/* La cuenta del primer día. No es un aviso —no ha fallado nada— así que no
   lleva ni icono de alerta ni color: es una caja del mismo material que
   todo lo demás, diciendo qué va a aparecer aquí. */
.dash-hub__empty {
  padding: clamp(1.4rem, 4vw, 2.2rem);
  text-align: center;
}

.dash-hub__empty[hidden] {
  display: none;
}

.dash-hub__emptyTitle {
  margin-bottom: 0.4rem;
  color: rgb(var(--c-ink));
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

.dash-hub__emptyText {
  max-width: 52ch;
  margin: 0 auto;
  color: rgb(var(--c-muted));
  font-size: 0.9rem;
  line-height: 1.6;
}

/* ── La baldosa ───────────────────────────────────────────────────────
   Casi todo lo pone `.product-card`. Aquí sólo se corrige lo que cambia
   por ser un <button> en el caso de la escuela: un botón trae la
   tipografía del sistema, se alinea al centro y no hereda el color del
   texto, y sin estas cuatro líneas la baldosa de la escuela se vería
   distinta de sus tres hermanas. */
.dash-tile {
  width: 100%;
  color: inherit;
  font-family: inherit;
  text-align: left;
}

/* La foto de un avión es apaisada y la de una experiencia también; el 4/3
   de la tienda —que está pensado para un producto de catálogo— dejaba
   franjas a los lados. El hueco vacío usa la misma proporción para que una
   rejilla con foto y sin foto no quede escalonada. */
.dash-tile__media,
.dash-tile__media.product-card__media--empty {
  aspect-ratio: 16 / 10;
}

/* La chapa de estado, arriba a la izquierda de la foto. En la misma esquina
   que la categoría de una tarjeta del mercado, y por lo mismo: es lo que
   clasifica la ficha, no lo que la anuncia. */
.dash-tile__badge {
  position: absolute;
  z-index: 2;
  top: 0.75rem;
  left: 0.75rem;
}

/* El pie: dato a la izquierda, botón a la derecha. El dato puede venir
   vacío —una experiencia sin precio, unas horas sin cifra— y entonces el
   botón se queda solo a la derecha, que es donde tiene que estar. */
.dash-tile__note {
  color: rgb(var(--c-ink));
  font-size: 0.95rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.dash-tile__cta {
  margin-left: auto;
}

/* La cifra dentro del hueco de la foto, para lo que no tiene ninguna: las
   horas. Mismo fondo que el hueco vacío de la tienda —de ahí que se apile
   sobre `.product-card__placeholder`— con la cifra centrada y grande y su
   rótulo debajo, apagado y en versales, como los pies de la casa. */
.dash-tile__figure {
  flex-direction: column;
  gap: 0.15rem;
}

.dash-tile__figureValue {
  color: rgb(var(--c-ink));
  font-size: clamp(2rem, 6vw, 2.9rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 1;
}

.dash-tile__figureLabel {
  color: rgb(var(--c-subtle));
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ── La puerta ────────────────────────────────────────────────────────
   Lo que todavía no se tiene. Mismo material y mismo botón que la baldosa
   de al lado, sin el hueco de la foto: no hay ninguna que enseñar, y el
   hueco vacío hacía que «empieza algo» ocupara el doble que los aviones de
   verdad de arriba — la página se leía al revés de lo que es.

   Rejilla propia y más estrecha que la de la tienda (260 contra 290) por lo
   mismo: sin foto, una puerta no necesita el ancho de una ficha, y cuantas
   más quepan en una fila menos parecen la parte principal de la página. */
.dash-hub__doors {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  gap: clamp(0.8rem, 1.6vw, 1.15rem);
  align-items: stretch;
}

.dash-door {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.35rem;
  width: 100%;
  padding: 1.2rem 1.25rem 1.25rem;
  color: inherit;
  font-family: inherit;
  text-align: left;
}

/* El dibujo, pequeño y en la tinta apagada. NO en el acento: el acento en
   esta página es del botón que hace la cosa, y cuatro discos encendidos
   encima de cuatro botones encendidos serían ocho llamadas de atención
   para cuatro decisiones. */
.dash-door__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin-bottom: 0.35rem;
  border-radius: 9999px;
  color: rgb(var(--c-muted));
  background: var(--pill);
}

.dash-door__icon svg {
  width: 17px;
  height: 17px;
}

.dash-door__title {
  color: rgb(var(--c-ink));
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* `flex: 1` para que los botones de las cuatro queden a la misma altura
   aunque un texto ocupe tres renglones y otro dos. */
.dash-door__text {
  flex: 1;
  color: rgb(var(--c-muted));
  font-size: 0.85rem;
  line-height: 1.55;
}

.dash-door__cta {
  margin-top: 0.9rem;
}

/* ── La cabecera de estado ────────────────────────────────────────────
   Lo primero que hay que saber al entrar. La barra de color de la
   izquierda es lo que hace que los cinco estados se distingan de un
   vistazo sin leer: verde en el mapa, ámbar en cola, rojo devuelta. */

.dash-status {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.25rem;
  padding: clamp(1.25rem, 3vw, 1.85rem);
  border-left: 4px solid rgb(var(--c-faint));
}

.dash-status[data-status='published'] { border-left-color: #15803d; }
.dash-status[data-status='pending']   { border-left-color: #b45309; }
.dash-status[data-status='rejected']  { border-left-color: #b91c1c; }
.dash-status[data-status='paused']    { border-left-color: rgb(var(--c-subtle)); }

.dash-status__main {
  flex: 1 1 22rem;
  min-width: 0;
}

.dash-status__badge {
  display: inline-block;
  margin-bottom: 0.5rem;
  padding: 0.25rem 0.7rem;
  border-radius: 9999px;
  background: var(--pill);
  color: rgb(var(--c-body));
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.dash-status__title {
  color: rgb(var(--c-ink));
  font-size: clamp(1.35rem, 3vw, 1.8rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.15;
}

.dash-status__text {
  margin-top: 0.4rem;
  color: rgb(var(--c-muted));
  font-size: 0.88rem;
}

/* La nota de revisión. Es lo único que hay que hacer cuando la ficha vuelve,
   así que se pinta como una cita y no como un párrafo más. */
.dash-status__note {
  margin-top: 0.9rem;
  padding: 0.8rem 1rem;
  border-left: 3px solid #b91c1c;
  border-radius: 0 0.75rem 0.75rem 0;
  background: rgba(185, 28, 28, 0.08);
  color: rgb(var(--c-body));
  font-size: 0.88rem;
  white-space: pre-line;
}

.dash-status__note[hidden] {
  display: none;
}

.dash-status__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.dash-status__actions .btn-primary {
  align-self: center;
  margin-top: 0;
}

/* El correo sin confirmar bloquea publicar y subir fotos: se dice arriba del
   todo y con el botón de arreglarlo al lado. */
.dash-warn {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem clamp(1rem, 2.5vw, 1.5rem);
  border-left: 4px solid #b45309;
  color: rgb(var(--c-body));
  font-size: 0.88rem;
}

.dash-warn[hidden] {
  display: none;
}

/* ── Los bloques del formulario ───────────────────────────────────── */

.dash-form {
  display: flex;
  flex-direction: column;
  gap: clamp(1rem, 2.2vw, 1.5rem);
}

/* `display: flex` GANA al atributo `hidden`, así que sin esta regla el
   formulario de la ficha —y la barra de guardar, y la cabecera de estado—
   seguirían en pantalla delante de quien no tiene escuela, que es
   exactamente lo que esta página dejó de hacer. Es el mismo remedio que ya
   tenía `.dash-warn[hidden]` unas líneas más arriba. */
.dash-form[hidden],
.dash-bar[hidden],
.dash-status[hidden] {
  display: none;
}

.dash-block {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  padding: clamp(1.25rem, 3vw, 1.85rem);
}

.dash-block__title {
  color: rgb(var(--c-ink));
  font-size: 1.1rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* La explicación de cada bloque va debajo del título y pegada a él —sin el
   hueco del `gap`— porque es parte del título, no el primer contenido. */
.dash-block__intro {
  margin-top: -0.75rem;
  color: rgb(var(--c-muted));
  font-size: 0.84rem;
  line-height: 1.6;
  max-width: 62ch;
}

.dash-grid {
  display: grid;
  gap: 1rem;
}

.dash-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dash-grid--3 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr); }

@media (max-width: 40rem) {
  /* En un móvil las tres columnas del aeródromo caben, pero el campo del
     nombre queda de doce caracteres. Una debajo de otra. */
  .dash-grid--2,
  .dash-grid--3 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── Casillas: habilitaciones e idiomas ───────────────────────────────
   Una rejilla que se acomoda, y no una lista: son catorce habilitaciones y
   treinta y siete idiomas, y en columna serían dos pantallas de nada.

   La casilla nativa se queda —se ve, se lee con lector de pantalla y
   funciona con el teclado sin una línea de JavaScript—; lo que cambia es la
   caja que la envuelve, que es lo que hace que el objetivo del dedo sea la
   etiqueta entera y no un cuadrado de 13 px. */

.dash-checks {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.5rem;
  border-radius: 1rem;
}

.dash-checks--compact {
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
}

.dash-check {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.85rem;
  border-radius: 0.85rem;
  background: var(--pill);
  cursor: pointer;
  transition: background 0.2s var(--lg-ease);
}

.dash-check:hover {
  background: var(--hover-soft);
}

.dash-check input {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.dash-check__label {
  min-width: 0;
  color: rgb(var(--c-body));
  font-size: 0.84rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-check:has(input:checked) {
  background: var(--hover-soft);
}

.dash-check:has(input:checked) .dash-check__label {
  color: rgb(var(--c-ink));
}

.dash-check:focus-within {
  box-shadow: var(--accent-ring);
}

/* ── El buscador de aeródromos ────────────────────────────────────────
   Copiado de css/schools.css a propósito; el porqué, en la cabecera. */

.place-field {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0 0.5rem 0 1.1rem;
  min-height: 56px;
  border-radius: 2.5rem;
  background: rgb(var(--c-elevated));
  box-shadow: var(--fieldgroup-shadow);
  transition: box-shadow 0.25s var(--lg-ease);
}

.place-field:focus-within {
  box-shadow: var(--fieldgroup-shadow), var(--accent-ring);
}

.place-field__icon {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
  color: rgb(var(--c-subtle));
}

.place-field__input {
  flex: 1;
  min-width: 0;
  height: 54px;
  border: none;
  background: none;
  outline: none;
  color: rgb(var(--c-ink));
  font-size: 0.98rem;
  font-weight: 500;
  font-family: inherit;
}

.place-field__input::placeholder {
  color: rgb(var(--c-subtle));
  font-weight: 400;
}

.place-field__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.place-field__clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: 9999px;
  color: rgb(var(--c-muted));
  background: var(--track);
  transition: background 0.2s var(--lg-ease), color 0.2s var(--lg-ease);
}

.place-field__clear svg {
  width: 14px;
  height: 14px;
}

.place-field__clear:hover {
  color: rgb(var(--c-ink));
  background: var(--hover-soft);
}

.place-field__clear[hidden] {
  display: none;
}

.place-suggestions {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  right: 0;
  z-index: 60;
  max-height: 22rem;
  overflow-y: auto;
  padding: 0.4rem;
  border-radius: 1.25rem;
  list-style: none;
}

.place-suggestions[hidden] {
  display: none;
}

.place-option {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.7rem;
  border-radius: 0.9rem;
  cursor: pointer;
}

.place-option.is-active,
.place-option:hover {
  background: var(--pill);
}

/* Aquí la chapa lleva el OACI y no la bandera del país: en una lista de
   aeródromos el indicativo es el dato que se estaba buscando. */
.place-option__flag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 1.75rem;
  flex-shrink: 0;
  border-radius: 0.5rem;
  border: 1px solid var(--hairline);
  background: var(--pill);
  color: rgb(var(--c-body));
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.place-option__text {
  min-width: 0;
}

.place-option__name {
  display: block;
  color: rgb(var(--c-ink));
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.place-option__admin {
  display: block;
  color: rgb(var(--c-subtle));
  font-size: 0.75rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.place-status {
  padding: 0.15rem 1.1rem 0;
  color: rgb(var(--c-muted));
  font-size: 0.78rem;
}

.place-status[hidden] {
  display: none;
}

/* ── El mapa ──────────────────────────────────────────────────────── */

.dash-map-shell {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.dash-map {
  height: clamp(15rem, 38vw, 22rem);
  border-radius: 1.25rem;
  overflow: hidden;
  background: var(--pill);
}

/* Leaflet se pinta con `z-index` altos por dentro. Sin esto, sus controles
   se cuelan por encima de la lista de aeródromos, que flota justo arriba. */
.dash-map .leaflet-pane,
.dash-map .leaflet-control {
  z-index: 1;
}

.dash-map__hint {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: rgb(var(--c-muted));
  font-size: 0.78rem;
}

.dash-map__hint svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* Las coordenadas, monoespaciadas: son números que se comparan con otros
   —los del AIP, los del GPS— y en proporcional no se alinean. */
.dash-map__coords {
  color: rgb(var(--c-subtle));
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.74rem;
}

/* ── Las pestañas de idioma de la descripción ────────────────────────
   El punto dice qué idiomas tienen texto. Sin él habría que abrir catorce
   pestañas para saber cuáles están escritas. */

.lang-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.lang-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.85rem;
  border-radius: 9999px;
  background: var(--pill);
  color: rgb(var(--c-muted));
  font-size: 0.78rem;
  font-weight: 700;
  transition: background 0.2s var(--lg-ease), color 0.2s var(--lg-ease);
}

.lang-tab:hover {
  color: rgb(var(--c-ink));
  background: var(--hover-soft);
}

.lang-tab.is-active {
  color: var(--accent-on);
  background: var(--accent);
}

.lang-tab__dot {
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: currentColor;
}

.lang-tab__req {
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  opacity: 0.7;
}

/* ── La flota: etiquetas ─────────────────────────────────────────── */

.tag-input {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  border-radius: 1rem;
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  list-style: none;
}

.tag-list:empty {
  display: none;
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.5rem 0.4rem 0.85rem;
  border-radius: 9999px;
  background: var(--pill);
  color: rgb(var(--c-ink));
  font-size: 0.82rem;
  font-weight: 600;
}

.tag__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 9999px;
  background: var(--track);
  color: rgb(var(--c-muted));
  font-size: 0.9rem;
  line-height: 1;
  transition: background 0.2s var(--lg-ease), color 0.2s var(--lg-ease);
}

.tag__remove:hover {
  background: #b91c1c;
  color: #fff;
}

.tag-add {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.tag-add input {
  flex: 1;
  min-width: 0;
  border: none;
  border-radius: 2.5rem;
  padding: 0.8rem 1.15rem;
  background: rgb(var(--c-elevated));
  color: rgb(var(--c-ink));
  font-size: 0.9rem;
  font-family: inherit;
  box-shadow: var(--fieldgroup-shadow);
  transition: box-shadow 0.25s var(--lg-ease);
}

.tag-add input:focus {
  outline: none;
  box-shadow: var(--fieldgroup-shadow), var(--accent-ring);
}

/* ── Fotos ────────────────────────────────────────────────────────── */

.photo-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 2rem 1rem;
  border: 2px dashed var(--hairline-strong);
  border-radius: 1.25rem;
  text-align: center;
  transition: border-color 0.2s var(--lg-ease), background 0.2s var(--lg-ease);
}

.photo-drop[hidden] {
  display: none;
}

/* Al arrastrar encima. Sin esta señal no se sabe si soltar aquí hará algo,
   y el archivo acaba soltado en el escritorio o abierto en otra pestaña. */
.photo-drop.is-over {
  border-color: var(--accent);
  background: var(--hover-soft);
}

.photo-drop.is-busy {
  opacity: 0.6;
  pointer-events: none;
}

.photo-drop__hint {
  color: rgb(var(--c-subtle));
  font-size: 0.78rem;
}

.photo-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: 1rem;
  list-style: none;
}

.photo-item {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.75rem;
  border-radius: 1rem;
  background: var(--pill);
}

.photo-item__media {
  position: relative;
  border-radius: 0.75rem;
  overflow: hidden;
  background: var(--track);
  aspect-ratio: 4 / 3;
}

.photo-item__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* «Portada» sobre la primera, y no un número de orden: lo que importa no es
   que sea la número uno, es que es la que sale en la lista de resultados. */
.photo-item__cover {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  padding: 0.2rem 0.6rem;
  border-radius: 9999px;
  background: var(--accent);
  color: var(--accent-on);
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.photo-item__body {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
}

.photo-item__body .form-group {
  flex: 1;
  min-width: 0;
}

.photo-item__body .form-group input {
  padding: 0.6rem 0.9rem;
  font-size: 0.82rem;
}

.photo-item__actions {
  display: flex;
  gap: 0.35rem;
  padding-bottom: 0.1rem;
}

/* ── La barra de guardar ──────────────────────────────────────────────
   Pegada abajo porque el formulario mide dos pantallas y media: un botón de
   guardar al final es un botón que no está cuando hace falta. */

.dash-bar {
  position: sticky;
  bottom: 1rem;
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1.15rem;
}

.dash-bar__state {
  min-width: 0;
  color: rgb(var(--c-muted));
  font-size: 0.82rem;
}

.dash-bar__state--ok    { color: #15803d; }
.dash-bar__state--warn  { color: #b45309; }
.dash-bar__state--error { color: #b91c1c; }

@media (prefers-color-scheme: dark) {
  .dash-bar__state--ok    { color: #86efac; }
  .dash-bar__state--warn  { color: #fcd34d; }
  .dash-bar__state--error { color: #fca5a5; }
}

.dash-bar__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
}

.dash-bar__actions .btn-primary {
  align-self: center;
  margin-top: 0;
  padding: 0.8rem 1.5rem;
}

.dash-bar__actions .btn-primary[hidden] {
  display: none;
}

/* ── Lo que falta para publicar ──────────────────────────────────── */

.dash-gaps {
  padding: 1rem 1.25rem;
  border-left: 4px solid #b91c1c;
}

.dash-gaps[hidden] {
  display: none;
}

.dash-gaps__title {
  color: rgb(var(--c-ink));
  font-size: 0.88rem;
  font-weight: 700;
}

.dash-gaps__list {
  margin: 0.5rem 0 0 1.1rem;
  color: rgb(var(--c-body));
  font-size: 0.85rem;
}

.dash-gaps__list li {
  list-style: disc;
  margin-top: 0.15rem;
}

/* ── La cuenta ────────────────────────────────────────────────────── */

.dash-account {
  margin-top: clamp(1.5rem, 4vw, 3rem);
}

.dash-account__email {
  color: rgb(var(--c-muted));
  font-size: 0.88rem;
  margin-top: -0.6rem;
}

.dash-account__warn {
  color: rgb(var(--c-muted));
  font-size: 0.82rem;
  line-height: 1.6;
  max-width: 62ch;
}

/* ── Cómo se entra ────────────────────────────────────────────────────
   Una fila: marca, qué pasa, y el gesto contrario a lo que pasa. NO va
   plegada en un `<details>` como la contraseña y el borrado, y la
   diferencia es deliberada: aquellas dos son cosas que se hacen una vez y
   esta es información —«entras con esta cuenta de Google»— que hay que
   poder leer sin abrir nada. */

.dash-provider {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
  padding: 1rem 0 1.25rem;
}

.dash-provider[hidden] {
  display: none;
}

.dash-provider__mark {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

.dash-provider__main {
  flex: 1 1 14rem;
  min-width: 0;
}

.dash-provider__title {
  color: rgb(var(--c-ink));
  font-size: 0.86rem;
  font-weight: 700;
}

/* La dirección de la cuenta de Google puede ser larga y no tiene por qué
   caber: se parte por donde haga falta antes que desbordar la tarjeta. */
.dash-provider__state {
  color: rgb(var(--c-muted));
  font-size: 0.82rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.dash-account__set {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.9rem;
  max-width: 62ch;
}

.dash-account__set[hidden],
.dash-details .portal-form[hidden] {
  display: none;
}

/* Cambiar la contraseña y borrar la cuenta van plegados: son cosas que se
   hacen una vez, y desplegadas ocuparían más que la ficha entera. El
   `<details>` nativo se abre sin JavaScript y funciona con el teclado. */
.dash-details {
  border-top: 1px solid var(--hairline);
  padding-top: 1rem;
}

.dash-details summary {
  cursor: pointer;
  color: rgb(var(--c-body));
  font-size: 0.86rem;
  font-weight: 700;
  list-style-position: inside;
}

.dash-details summary:hover {
  color: rgb(var(--c-ink));
}

.dash-details[open] summary {
  margin-bottom: 1rem;
}

.dash-details--danger summary {
  color: #b91c1c;
}

@media (prefers-color-scheme: dark) {
  .dash-details--danger summary {
    color: #fca5a5;
  }
}

.dash-details .portal-form {
  margin-top: 0;
  max-width: 26rem;
}

/* ══════════════════════════════════════════════════════════════════════
   4 · /school-admin — la mesa de revisión
   ══════════════════════════════════════════════════════════════════════ */

.desk-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.desk-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.55rem 1rem;
  border-radius: 9999px;
  background: var(--pill);
  color: rgb(var(--c-muted));
  font-size: 0.82rem;
  font-weight: 700;
  transition: background 0.2s var(--lg-ease), color 0.2s var(--lg-ease);
}

.desk-tab:hover {
  color: rgb(var(--c-ink));
  background: var(--hover-soft);
}

.desk-tab.is-active {
  color: var(--accent-on);
  background: var(--accent);
}

.desk-tab__count {
  padding: 0.05rem 0.45rem;
  border-radius: 9999px;
  background: var(--track);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
}

.desk-tab.is-active .desk-tab__count {
  background: rgb(var(--accent-on-rgb) / 0.2);
}

.desk-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.desk-list[aria-busy='true'] {
  opacity: 0.5;
}

.desk-empty {
  padding: 3rem 1rem;
  text-align: center;
  color: rgb(var(--c-subtle));
  font-size: 0.9rem;
}

.desk-empty[hidden] {
  display: none;
}

/* ── La tarjeta ───────────────────────────────────────────────────────
   Una ficha entera por tarjeta, sin nada plegado: si hubiera que abrir la
   descripción y las fotos, revisar veinte fichas serían sesenta clics y la
   decisión se acabaría tomando por el nombre. */

.desk-card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
}

.desk-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}

.desk-card__ident {
  min-width: 0;
}

/* Una matrícula, en la tarjeta de un avión de la cola del mercado. Va
   monoespaciada y separada porque no es una palabra: es lo que se copia de
   aquí y se pega en el registro del país para comprobar que el avión existe
   y que es de quien dice serlo. En la misma tipografía que el resto de la
   frase se lee como un nombre raro, y se copia peor. */
.desk-code {
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  letter-spacing: 0.12em;
}

.desk-card__name {
  color: rgb(var(--c-ink));
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

.desk-card__where {
  margin-top: 0.15rem;
  color: rgb(var(--c-muted));
  font-size: 0.82rem;
}

.desk-card__flags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.desk-flag {
  padding: 0.2rem 0.6rem;
  border-radius: 9999px;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border: 1px solid var(--hairline-strong);
  color: rgb(var(--c-body));
}

/* Destacada y comprobada se pintan DISTINTO aunque sean el mismo tipo de
   chapa: una es la posición de pago y la otra es que alguien la ha
   comprobado. Que se parezcan es el primer paso para confundirlas. */
.desk-flag--featured {
  border-color: rgba(180, 83, 9, 0.5);
  background: rgba(180, 83, 9, 0.12);
}

.desk-flag--verified {
  border-color: rgba(21, 128, 61, 0.5);
  background: rgba(21, 128, 61, 0.12);
}

.desk-flag--suspended {
  border-color: rgba(185, 28, 28, 0.5);
  background: rgba(185, 28, 28, 0.12);
}

/* Las fotos de verdad, en fila y con scroll lateral. Un recuento («3 fotos»)
   no permite revisar nada: lo que hay que mirar es si son suyas y si se ven. */
.desk-card__photos {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding-bottom: 0.25rem;
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar) transparent;
}

.desk-card__photos img {
  width: 11rem;
  height: 8rem;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: 0.75rem;
  background: var(--track);
}

/* Cada miniatura es además el enlace a la imagen entera: lo que se sube al
   canal es el archivo, y de una miniatura de 11rem no sale. */
.desk-card__photos a {
  display: block;
  flex-shrink: 0;
  border-radius: 0.75rem;
}

/* La fila de herramientas: copiar el mensaje y abrir el canal. Va SEPARADA
   del bloque de acciones —y encima de él— porque no decide nada sobre el
   anuncio: es lo que se usa ANTES de decidir, mientras se publica de
   verdad. Juntarlas dejaría «copiar» al lado de «devolver». */
.desk-card__tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.desk-card__hint {
  font-size: 0.85rem;
  color: var(--muted);
}

.desk-facts {
  display: grid;
  grid-template-columns: minmax(7rem, auto) minmax(0, 1fr);
  gap: 0.3rem 1rem;
  font-size: 0.82rem;
}

.desk-facts dt {
  color: rgb(var(--c-subtle));
  font-weight: 700;
}

.desk-facts dd {
  color: rgb(var(--c-body));
  min-width: 0;
  overflow-wrap: anywhere;
}

.desk-desc {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border-radius: 0.9rem;
  background: var(--pill);
}

.desk-desc__lang {
  display: block;
  color: rgb(var(--c-subtle));
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.desk-desc__text {
  color: rgb(var(--c-body));
  font-size: 0.85rem;
  line-height: 1.6;
  white-space: pre-line;
}

.desk-card__gaps {
  padding: 0.75rem 1rem;
  border-left: 3px solid #b91c1c;
  border-radius: 0 0.75rem 0.75rem 0;
  background: rgba(185, 28, 28, 0.08);
  font-size: 0.82rem;
}

.desk-card__gapsTitle {
  color: rgb(var(--c-ink));
  font-weight: 700;
}

.desk-card__gaps ul {
  margin: 0.35rem 0 0 1.1rem;
}

.desk-card__gaps li {
  list-style: disc;
}

.desk-card__note {
  padding: 0.75rem 1rem;
  border-left: 3px solid rgb(var(--c-faint));
  border-radius: 0 0.75rem 0.75rem 0;
  background: var(--pill);
  color: rgb(var(--c-body));
  font-size: 0.85rem;
  white-space: pre-line;
}

.desk-card__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--hairline);
}

.desk-card__actions .btn-primary {
  align-self: flex-end;
  margin-top: 0;
  padding: 0.7rem 1.4rem;
}

/* Devolver = la nota y el botón, juntos y en su propia caja. El botón está
   apagado hasta que la nota está escrita: la regla se ve ANTES de pulsar, no
   como respuesta a haberlo intentado. */
.desk-reject {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  flex: 1 1 20rem;
  min-width: 0;
}

.desk-reject .form-group {
  flex: 1;
  min-width: 0;
}

.desk-reject textarea {
  border: none;
  border-radius: 1rem;
  padding: 0.65rem 1rem;
  background: rgb(var(--c-elevated));
  color: rgb(var(--c-ink));
  font-size: 0.84rem;
  font-family: inherit;
  line-height: 1.5;
  resize: vertical;
  box-shadow: var(--fieldgroup-shadow);
}

.desk-reject textarea:focus {
  outline: none;
  box-shadow: var(--fieldgroup-shadow), var(--accent-ring);
}

/* ══════════════════════════════════════════════════════════════════════
   5 · /for-flight-schools — la página que convence
   ──────────────────────────────────────────────────────────────────────
   La única de las cinco que ve alguien que NO tiene cuenta, la única que se
   indexa y la única que está en los catorce idiomas. Es más ancha que las
   otras: aquí no se rellena nada, se lee.
   ══════════════════════════════════════════════════════════════════════ */

.portal-main {
  max-width: 68rem;
  gap: var(--section-gap);
  padding-top: clamp(1rem, 4vw, 2.5rem);
}

.portal-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.85rem;
  max-width: 46rem;
}

.portal-hero__title {
  color: rgb(var(--c-ink));
  font-size: clamp(2rem, 5.5vw, 3.25rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 1.05;
}

.portal-hero__subtitle {
  color: rgb(var(--c-body));
  font-size: clamp(1rem, 2vw, 1.15rem);
  line-height: 1.65;
}

.portal-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.6rem;
}

.portal-hero__actions .btn-primary {
  margin-top: 0;
}

/* «Salir es gratis» va debajo del botón y no en el titular: es lo que
   resuelve la duda justo cuando se está a punto de pulsar. */
.portal-hero__note {
  color: rgb(var(--c-muted));
  font-size: 0.82rem;
}

.portal-section {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.portal-section__title {
  color: rgb(var(--c-ink));
  font-size: clamp(1.35rem, 3vw, 1.9rem);
  font-weight: 800;
  letter-spacing: -0.03em;
}

.portal-section__intro {
  margin-top: -0.75rem;
  max-width: 58ch;
  color: rgb(var(--c-muted));
  font-size: 0.95rem;
  line-height: 1.65;
}

/* ── Los tres pasos ──────────────────────────────────────────────────
   El número va en un disco y en su sitio, no como viñeta de la lista: la
   numeración automática de un <ol> no se puede colocar, y aquí el número
   es parte de la tarjeta. */

.portal-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem;
  list-style: none;
  counter-reset: none;
}

.portal-step {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: clamp(1.15rem, 2.5vw, 1.6rem);
}

.portal-step__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 9999px;
  background: var(--accent);
  color: var(--accent-on);
  font-size: 0.9rem;
  font-weight: 800;
  box-shadow: var(--accent-shadow);
}

.portal-step h3 {
  color: rgb(var(--c-ink));
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.portal-step p {
  color: rgb(var(--c-muted));
  font-size: 0.87rem;
  line-height: 1.6;
}

/* ── Lo que enseña una ficha ──────────────────────────────────────── */

.portal-features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 0.6rem 1.5rem;
  list-style: none;
}

.portal-feature {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  color: rgb(var(--c-body));
  font-size: 0.92rem;
  line-height: 1.55;
}

.portal-feature svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  margin-top: 0.18em;
  color: #15803d;
}

@media (prefers-color-scheme: dark) {
  .portal-feature svg { color: #86efac; }
}

/* ── Por qué aquí ─────────────────────────────────────────────────── */

.portal-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
}

.portal-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: clamp(1.15rem, 2.5vw, 1.6rem);
}

.portal-card h3 {
  color: rgb(var(--c-ink));
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.portal-card p {
  color: rgb(var(--c-muted));
  font-size: 0.87rem;
  line-height: 1.6;
}

/* ── Lo que cuesta ────────────────────────────────────────────────────
   Las tres columnas en la MISMA superficie y sin una destacada sobre las
   otras. Una tabla de precios con la del medio en grande es la forma de
   decir cuál hay que elegir, y aquí no hay que elegir ninguna: se está
   contando cómo funciona el dinero, no vendiendo un plan. */

.portal-pricing {
  padding: clamp(1.35rem, 3vw, 2rem);
}

.portal-pricing__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.35rem;
}

.portal-pricing__item h3 {
  color: rgb(var(--c-ink));
  font-size: 0.95rem;
  font-weight: 800;
  margin-bottom: 0.35rem;
}

.portal-pricing__item p {
  color: rgb(var(--c-muted));
  font-size: 0.86rem;
  line-height: 1.6;
}

/* ── Preguntas ────────────────────────────────────────────────────────
   `<details>` nativo: se abre sin JavaScript, funciona con el teclado y el
   buscador lo indexa aunque esté cerrado. */

.portal-faq {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.portal-faq__item {
  padding: 1rem clamp(1rem, 2.5vw, 1.4rem);
}

.portal-faq__item summary {
  cursor: pointer;
  color: rgb(var(--c-ink));
  font-size: 0.95rem;
  font-weight: 700;
  list-style-position: inside;
}

.portal-faq__item[open] summary {
  margin-bottom: 0.6rem;
}

.portal-faq__item p {
  color: rgb(var(--c-muted));
  font-size: 0.88rem;
  line-height: 1.65;
  max-width: 62ch;
}

/* ── El cierre ────────────────────────────────────────────────────── */

.portal-final {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  padding: clamp(1.75rem, 4vw, 3rem);
  text-align: center;
}

.portal-final__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 9999px;
  color: var(--accent-on);
  background: var(--accent);
  box-shadow: var(--accent-shadow);
}

.portal-final__icon svg {
  width: 24px;
  height: 24px;
}

.portal-final h2 {
  color: rgb(var(--c-ink));
  font-size: clamp(1.5rem, 3.5vw, 2.1rem);
  font-weight: 900;
  letter-spacing: -0.03em;
}

.portal-final p {
  max-width: 44ch;
  color: rgb(var(--c-muted));
  font-size: 0.95rem;
  line-height: 1.6;
}

.portal-final .btn-primary {
  align-self: center;
  margin-top: 0.5rem;
}

.portal-final__alt {
  font-size: 0.85rem;
}

.portal-final__alt a {
  color: rgb(var(--c-ink));
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ══════════════════════════════════════════════════════════════════════
   MOVIMIENTO
   ──────────────────────────────────────────────────────────────────────
   Quien ha pedido menos movimiento en su sistema lo ha pedido para todo,
   también aquí.
   ══════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .portal-body *,
  .portal-body *::before,
  .portal-body *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   LO QUE AÑADE LA MESA DEL HUB
   ──────────────────────────────────────────────────────────────────────
   /hub-admin reutiliza entera la mesa de las escuelas —pestañas, tarjeta,
   bloque de devolver— porque son la misma herramienta con otro contenido
   dentro. Lo único que no tenía sitio son estas dos piezas, que solo
   existen aquí:

     .desk-pay    el estado del pago de un anuncio. Va con COLOR y no con
                  una palabra a secas porque es la distinción que hay que
                  ver de un vistazo al bajar por veinte tarjetas: pagado
                  es normal, eximido es una decisión de la casa, y sin
                  pagar no debería estar en esta cola siquiera.
     .desk-hours  las horas declaradas por categoría. En dos columnas y
                  con la cifra en negrita a la derecha, que es como se lee
                  la página de totales de un logbook — quien revisa la
                  tiene abierta al lado y compara renglón por renglón.
   ══════════════════════════════════════════════════════════════════════ */
.desk-pay {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 2.5rem;
  background: var(--pill);
  font-weight: 600;
}

.desk-pay--paid {
  color: rgb(var(--c-ink));
  box-shadow: inset 0 0 0 1px var(--hairline-strong);
}

/* Eximido lleva el canto marcado y no un color propio: es correcto, pero
   es una excepción, y una excepción tiene que verse sin gritar. */
.desk-pay--waived {
  color: rgb(var(--c-body));
  box-shadow: inset 0 0 0 1px var(--hairline-strong);
}

.desk-pay--pending,
.desk-pay--none {
  color: rgb(var(--c-muted));
}

.desk-hours {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.25rem 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.desk-hours li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--hairline);
  font-size: 0.85rem;
  color: rgb(var(--c-muted));
}

.desk-hours strong {
  color: rgb(var(--c-ink));
  font-variant-numeric: tabular-nums;
}

/* ══════════════════════════════════════════════════════════════════════
   LA PÁGINA DEL BOT — /bot
   ──────────────────────────────────────────────────────────────────────
   Dos reglas para la única página del sitio que enseña código: la ficha
   pública de IFlewAThingBot, que es donde acaba quien ve el nombre del
   agente en su registro de accesos. Lo que hay que leer ahí son dos
   bloques literales —el User-Agent y las dos líneas de robots.txt que lo
   bloquean— y tienen que poder copiarse sin errores.

   Van aquí y no en un archivo propio porque son cuarenta líneas: un
   quinto CSS que se descarga en una página que casi nadie visita cuesta
   más que estas reglas al final del que ya se carga.
   ══════════════════════════════════════════════════════════════════════ */

/* Monoespaciada de sistema y con desplazamiento horizontal PROPIO: la
   línea del User-Agent no cabe en un móvil, y sin esto empujaría la
   página entera de lado. Se rompe el bloque, no el documento. */
.bot-code {
  overflow-x: auto;
  margin: 0.35rem 0 0.6rem;
  padding: 0.85rem 1rem;
  border-radius: 0.75rem;
  border: 1px solid var(--hairline);
  background: rgb(var(--c-ink) / 0.04);
  color: rgb(var(--c-ink));
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.82rem;
  line-height: 1.55;
  /* Se conservan los saltos escritos —las dos líneas del robots.txt son
     dos líneas— y no se envuelve lo que no quepa: envolver una directiva
     invita a copiarla partida. */
  white-space: pre;
  -webkit-user-select: all;
  user-select: all;
}

/* El `<code>` suelto dentro de un párrafo, para `Crawl-delay` y demás. */
.portal-card p code {
  padding: 0.1em 0.35em;
  border-radius: 0.35rem;
  background: rgb(var(--c-ink) / 0.06);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
}

/* La lista de comportamientos: sin viñeta, porque cada punto ya lleva su
   propio titular y una viñeta delante de un <h3> se lee como un menú. Lo
   que los separa es el filete de arriba. */
.bot-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

.bot-list > li + li {
  padding-top: 1rem;
  border-top: 1px solid var(--hairline);
}
