/* Panel de gestión de Ali Bey 25.
   Comparte la identidad de la web pública —el granate y el papel— pero más
   denso: es una herramienta de trabajo, no una página de captación.

   Los tamaños de letra van en rem y no en px a propósito: quien tiene la
   letra del navegador subida —dos personas trabajando aquí ocho horas al
   día— ve el panel a su tamaño en vez de ignorarse su ajuste. Los rellenos
   y las alturas mínimas siguen en px: son cajas que pueden crecer, no
   medidas que deban escalar. */

/* ------------------------------------------------------------ tipografías
   Servidas desde el propio dominio, no desde Google. Se gana la vuelta a un
   tercero en la ruta crítica y se quita la transferencia de la IP del
   visitante a Google, que es lo que discute el RGPD. font-display: swap
   dibuja el texto con la de reserva desde el primer momento: en un panel de
   trabajo es preferible ver la lista al instante con otra letra que esperar
   a la buena mirando un hueco en blanco.

   Los ficheros van en assets/fuentes/. Si faltan, todo sigue funcionando con
   la pila de reserva: el panel se ve, solo que en Helvetica. */
@font-face {
  font-family: Archivo;
  src: url("../fuentes/archivo-variable.woff2") format("woff2");
  font-weight: 400 900;      /* una sola variable en vez de seis estáticas */
  font-style: normal;
  font-display: swap;
}

:root {
  /* -------------------------------------------------------------- física
     Apple no anima con curvas simétricas: arranca deprisa y frena largo,
     como algo que tiene masa. Sin JavaScript no hay resortes de verdad, pero
     una bezier con la salida muy tendida se le parece bastante.

     --sal-rapida  · lo que responde al dedo: color de un botón, de un enlace
     --sal         · el movimiento normal (amortiguación 1.0, ~0.4 s)
     --sal-larga   · lo que se despliega y ocupa sitio: <details>, paneles

     Un apunte de las pautas: el movimiento se añade con intención. En algo
     que se usa ocho horas al día, una animación en cada fila de la tabla
     cansa. Aquí se mueve lo que se toca, y nada más. */
  --curva: cubic-bezier(.16, 1, .3, 1);          /* frenada de resorte */
  --curva-suave: cubic-bezier(.32, .72, 0, 1);   /* paneles y desplegables */
  --sal-rapida: .14s var(--curva);
  --sal: .28s var(--curva);
  --sal-larga: .42s var(--curva-suave);

  /* --------------------------------------------------------- espaciado
     Escala armónica de 4 px. Antes había veinticuatro medidas distintas
     —6, 7, 9, 11, 14, 18, 22, 26…— puestas a ojo una por una, y por eso las
     tablas de alumnos y horarios se sentían apretadas en unos sitios y
     sueltas en otros. Con nueve peldaños el ritmo se repite y la vista
     descansa. Las alturas mínimas NO salen de aquí: son dianas para el dedo,
     no ritmo. */
  --e1: 4px;
  --e2: 8px;
  --e3: 12px;
  --e4: 16px;
  --e5: 20px;
  --e6: 24px;
  --e7: 32px;
  --e8: 40px;
  --e9: 56px;

  /* Color */
  --granate: #5b1414;
  --granate-claro: #7d1d1d;
  --granate-suave: #f7eceb;
  --tinta: #1a1512;
  --papel: #f6f5f2;
  --blanco: #fff;
  --linea: #e7e1d9;
  --linea-suave: #f1ece5;
  --gris: #6b615a;          /* 5,8:1 sobre blanco */
  --gris-suave: #766c64;    /* 5,1:1 sobre blanco y 4,6:1 sobre el papel */
  --gris-lateral: #4c443e;  /* navegación sobre blanco: 9,4:1 */
  --gris-etq: #6f6259;      /* estado sin color propio: 5,6:1 con blanco */
  --verde: #16694f;
  --verde-suave: #eaf4f0;
  --ambar: #8a5a00;
  --ambar-suave: #fbf3e4;
  --azul: #1d4f7a;
  --azul-suave: #eef4f9;
  --foco: #5b1414;
  --foco-oscuro: #f5f2ee;

  /* Forma */
  --r: 10px;                /* tarjetas, tablas, formularios */
  --r-s: 8px;               /* botones, campos */
  --r-xs: 6px;              /* etiquetas y detalles pequeños */
  --sombra: 0 1px 2px rgba(26, 21, 18, .04), 0 10px 26px -20px rgba(26, 21, 18, .4);
  --sombra-alta: 0 1px 2px rgba(26, 21, 18, .05), 0 14px 32px -20px rgba(26, 21, 18, .45);

  /* ------------------------------------------------------------ material
     La cabecera de una tabla larga se queda pegada arriba mientras se baja
     por las filas. Si fuera opaca, cortaría la lista en seco; translúcida y
     con desenfoque se nota que hay contenido pasando por debajo, que es lo
     que hace legible el truco. El color de reserva es opaco a propósito:
     donde no haya backdrop-filter, la cabecera sigue tapando el texto en vez
     de dejarlo transparentarse encima. */
  --barra-alto: 58px;       /* la cabecera de las tablas se pega justo debajo */
  --vidrio: rgba(255, 255, 255, .88);
  --vidrio-opaco: #fff;
  --vidrio-borde: rgba(26, 21, 18, .08);
  --cabecera: rgba(250, 248, 245, .9);   /* cabecera de tabla pegada */
  --cabecera-opaca: #faf8f5;
  --desenfoque: saturate(180%) blur(14px);

  --sans: Archivo, "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* La serif con la que se publica el texto: el lienzo del editor la usa
     para que lo que se escribe se parezca a lo que va a salir. */
  --serif-web: Newsreader, Georgia, "Times New Roman", serif;
}

*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0; background: var(--papel); color: var(--tinta);
  font-family: var(--sans); font-size: 0.9375rem; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--granate); text-decoration: none; }
a:hover { color: var(--granate-claro); text-decoration: underline; }
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 2px solid var(--foco); outline-offset: 2px; border-radius: 4px;
}
/* Sobre la cabecera oscura el granate da 1,40:1 contra el fondo: el anillo
   existe pero no se ve. Ahí el indicador va en papel (17,4:1). */
/* La lateral ya es clara, así que su foco vuelve al anillo normal. El de
   papel se queda solo para la pantalla de acceso, que sigue en oscuro. */
.g-acceso-body a:focus-visible { outline-color: var(--foco-oscuro); }
/* Los títulos aprietan el tracking porque son grandes: a partir de 24 px el
   espacio entre letras se ve suelto si se deja el de por defecto. El texto
   pequeño hace lo contrario, más abajo. text-wrap: balance reparte un título
   de dos líneas en dos mitades parecidas en vez de dejar una palabra huérfana
   abajo; donde no esté soportado, no pasa nada. */
h1, h2, h3 { margin: 0; letter-spacing: -.02em; text-wrap: balance; }

/* Texto funcional pequeño: a 12 px las letras se tocan y el gris se emborrona.
   Un pelo de tracking y peso 500 en vez de 400 lo separan sin engordarlo.
   Las pautas son explícitas en esto: en tamaños pequeños, nunca pesos finos. */
.g-form small, .g-nota, .g-tarjeta-txt, .g-migas { letter-spacing: .004em; }
.g-nota, .g-form small { text-wrap: pretty; }

/* Cifras en columna: diplomas, cursos, importes, teléfonos. Con las cifras de
   ancho fijo, el 1 ocupa lo mismo que el 8 y las columnas quedan a plomo; sin
   ellas, una lista de 3.144 alumnos baila a cada fila. */
.g-tabla th, .g-tabla td:first-child { font-variant-numeric: normal; }

.saltar { position: absolute; left: -9999px; }
.saltar:focus {
  left: 0; top: 0; z-index: 50; background: var(--tinta); color: #fff;
  padding: var(--e4) var(--e5); min-height: 44px; display: inline-flex; align-items: center;
  /* Al enfocarse se pinta sobre fondo oscuro. Con el anillo granate quedaba
     en 1,3:1; y en papel POR FUERA de la caja tampoco se ve, porque la
     página también es papel. Va por dentro: papel sobre tinta, 17,4:1. */
  outline: 2px solid var(--foco-oscuro); outline-offset: -4px;
}

.g-ancho { width: min(1440px, 100% - 64px); margin: 0 auto; }
.g-estrecho { max-width: 900px; }
.g-principal { flex: 1; padding: var(--e7) 0 80px; }

/* ------------------------------------------------------------ estructura */
/* Barra lateral fija y una columna de contenido que se desplaza sola. Con
   once apartados, un menú horizontal obliga a leerlos todos en fila cada vez;
   en columna y agrupados por lo que se hace con ellos, el ojo va directo. */
/* La lateral se mide en rem y no en px: con la letra del navegador al 125 %
   los rótulos crecen y en una columna fija se salían por la derecha. */
.g-cuerpo {
  display: grid; grid-template-columns: 15.5rem minmax(0, 1fr); min-height: 100vh;
}

/* Lateral clara. El apartado en el que estás se marca con pastilla de color
   y una barra de 3 px pegada al borde: sobre fondo claro, el color solo no
   basta para saber dónde estás de un vistazo, y la barra lo dice sin depender
   de distinguir dos tonos de beige. */
.g-lateral {
  background: var(--blanco); color: var(--gris-lateral);
  border-right: 1px solid var(--linea);
  padding: 0 var(--e3) var(--e6); display: flex; flex-direction: column; gap: 2px;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.g-marca {
  display: flex; flex-direction: column; gap: 3px; color: var(--tinta);
  border-bottom: 1px solid var(--linea);
  margin: 0 calc(-1 * var(--e3)) var(--e4);
  padding: var(--e5) var(--e6) var(--e5); min-height: 44px; justify-content: center;
}
.g-marca:hover { text-decoration: none; color: var(--granate); }
.g-marca-nombre { font-weight: 800; font-size: 1.0625rem; letter-spacing: -.02em; }
.g-marca-rol {
  font-size: 0.625rem; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--gris-suave);
}

.g-grupo {
  margin: var(--e5) 0 var(--e2); padding: 0 var(--e3);
  font-size: 0.625rem; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gris-suave);
}
.g-nav {
  display: flex; align-items: center; gap: var(--e3); min-height: 40px;
  padding: 0 var(--e3); border-radius: var(--r-s);
  color: var(--gris-lateral); font-size: 0.875rem; font-weight: 600;
  transition: background-color var(--sal-rapida), color var(--sal-rapida);
}
.g-nav:hover { background: var(--linea-suave); color: var(--tinta); text-decoration: none; }
/* La pastilla del apartado activo se estira hasta el borde de la lateral para
   que la barra de color quede pegada al canto, no flotando a 12 px. */
.g-nav-activo, .g-nav-activo:hover {
  background: var(--granate-suave); color: var(--granate);
  box-shadow: inset 3px 0 0 var(--granate);
  border-radius: 0 var(--r-s) var(--r-s) 0;
  margin-left: calc(-1 * var(--e3));
  padding-left: var(--e6);
}
.g-nav-tenue { color: var(--gris-suave); font-weight: 500; }
.g-icono { flex: none; opacity: .8; }
.g-nav-activo .g-icono { opacity: 1; }
.g-separador { border: 0; border-top: 1px solid var(--linea); margin: var(--e5) 0 var(--e2); }
.g-lateral-pie { margin-top: auto; padding-top: var(--e5); }

.g-columna { display: flex; flex-direction: column; min-width: 0; }

/* Barra superior: dónde estoy a la izquierda, quién soy a la derecha. */
.g-barra {
  position: sticky; top: 0; z-index: 10;
  background: var(--vidrio-opaco);
  border-bottom: 1px solid var(--linea);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--e4); padding: 0 var(--e7); min-height: var(--barra-alto); flex-wrap: wrap;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .g-barra {
    background: var(--vidrio);
    -webkit-backdrop-filter: var(--desenfoque);
    backdrop-filter: var(--desenfoque);
  }
}
.g-barra-izq { min-width: 0; }
.g-migas {
  font-size: 0.8125rem; color: var(--gris);
  display: flex; align-items: center; gap: var(--e2); flex-wrap: wrap;
}
.g-migas a, .g-migas span { display: inline-flex; align-items: center; min-height: 40px; }
.g-usuario {
  display: flex; align-items: center; gap: var(--e4);
  font-size: 0.8125rem; color: var(--gris);
}
.g-usuario a { display: inline-flex; align-items: center; min-height: 40px; font-weight: 600; }
.g-nombre { color: var(--tinta); font-weight: 600; }
/* El texto «Salir» mide 28 px: como enlace suelto es una diana demasiado
   estrecha, sobre todo en la tableta. El relleno la lleva a 44. */
a.g-nombre:hover { color: var(--granate); text-decoration: none; }
/* La contraseña que se enseña una sola vez al crear una cuenta: grande, con
   cifras de ancho fijo y separada, para poder dictarla sin equivocarse. */
.g-clave {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1.375rem; font-weight: 700; letter-spacing: .06em;
  background: var(--blanco); border: 1px solid var(--linea); border-radius: var(--r-s);
  padding: var(--e3) var(--e4); margin: var(--e3) 0; display: inline-block;
  user-select: all;   /* un clic la selecciona entera */
}
.g-salir {
  color: var(--gris); padding: 0 var(--e4); min-width: 44px; justify-content: center;
  border: 1px solid var(--linea); border-radius: var(--r-s); background: var(--blanco);
}
.g-salir:hover { color: var(--granate); border-color: #e0d4d2; background: var(--granate-suave); text-decoration: none; }

/* ------------------------------------------------------ textos y bloques */
.g-titulo { font-size: 1.75rem; font-weight: 800; letter-spacing: -.025em; }
.g-h2 { font-size: 1.125rem; font-weight: 700; margin: var(--e8) 0 var(--e4); }
.g-encabezado {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--e4) var(--e5); flex-wrap: wrap; margin-bottom: var(--e5);
}
.g-nota { font-size: 0.8438rem; color: var(--gris); margin: var(--e3) 0; }
.g-nota code {
  background: var(--linea-suave); border-radius: 5px; padding: 2px var(--e2);
  font-size: 0.9em;
}
/* 4,6:1 sobre blanco. El #9a908a de antes daba 3,12:1, y esto no es solo
   para guiones: también dice "borrador" o "ningún alumno con esos filtros". */
.g-vacio { color: var(--gris-suave); }
/* Un enlace suelto dentro de una nota mide lo que mide su línea: 15 px. Como
   se pulsa, se le da altura de diana igual que a los de las tablas. */
.g-nota > a:only-child { display: inline-flex; align-items: center; min-height: 40px; }
.g-si { color: var(--verde); font-weight: 700; }
.g-derecha { text-align: right; white-space: nowrap; }

.g-aviso {
  padding: var(--e4) var(--e5); margin: 0 0 var(--e5); background: var(--blanco);
  border: 1px solid var(--linea); border-left: 3px solid var(--linea);
  border-radius: var(--r); box-shadow: var(--sombra);
}
.g-aviso ul { margin: var(--e2) 0 0; padding-left: var(--e5); }
/* Los avisos se pintan justo detrás de la cabecera, fuera del contenedor de
   la página: sin esto salen de lado a lado y no cuadran con el contenido que
   tienen debajo. Se les da la misma caja que a .g-ancho. */
.g-principal > .g-aviso { width: min(1440px, 100% - 64px); margin-left: auto; margin-right: auto; }
.g-principal > .g-aviso:first-child { margin-top: var(--e1); }
.g-aviso-bien { border-left-color: var(--verde); background: var(--verde-suave); border-color: #cfe4db; }
.g-aviso-mal { border-left-color: var(--granate); background: var(--granate-suave); border-color: #e8d3d1; }
/* Ni bien ni mal: un dato que falta y conviene ver, sin que parezca un error
   de quien está mirando la ficha. */
.g-aviso-ojo { border-left-color: var(--ambar); background: var(--ambar-suave); border-color: #ecdcbe; }
.g-alerta {
  background: var(--ambar-suave); border: 1px solid #ecdcbe;
  border-left: 3px solid var(--ambar); border-radius: var(--r);
  padding: var(--e5) var(--e5); margin: var(--e6) 0 var(--e7); line-height: 1.6;
}
.g-alerta > div { margin-top: var(--e4); }

/* --------------------------------------------------------------- botones */
.g-boton, .g-boton-linea {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 42px; padding: var(--e3) var(--e5); border-radius: var(--r-s);
  font: inherit; font-weight: 700; font-size: 0.875rem;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  /* El color entra deprisa —el dedo espera respuesta inmediata— y la escala
     frena con la curva larga. Al pulsar se hunde un 2 %: es el gesto que
     hace que un botón se sienta físico y no pintado. */
  transition: background-color var(--sal-rapida), color var(--sal-rapida),
              border-color var(--sal-rapida), transform var(--sal),
              box-shadow var(--sal);
}
.g-boton { background: var(--granate); color: #fff; box-shadow: var(--sombra); }
.g-boton:hover { background: var(--granate-claro); color: #fff; text-decoration: none; box-shadow: var(--sombra-alta); }
.g-boton:active, .g-boton-linea:active { transform: scale(.98); transition-duration: .06s; }
.g-boton:active { background: #4a1010; }
.g-boton-linea { border-color: var(--linea); color: var(--tinta); background: var(--blanco); }
.g-boton-linea:hover { background: var(--linea-suave); color: var(--tinta); text-decoration: none; border-color: #d8d0c6; }
.g-mini {
  display: inline-flex; align-items: center; min-height: 34px;
  font-size: 0.8125rem; font-weight: 600; margin-left: var(--e3);
}

/* ----------------------------------------------------- tarjetas del panel */
.g-tarjetas-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
.g-tarjetas {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--e4); margin: var(--e6) 0 var(--e3);
}
/* Bloques de color pleno con su icono, su rótulo y su pie. Una cifra suelta
   sobre blanco no dice nada —«40», ¿de qué?—; con el rótulo arriba y el matiz
   abajo se entiende sin abrir nada. Los cuatro colores son los que el panel ya
   usaba para los estados, y todos pasan de 5,9:1 con texto blanco encima. */
.g-tarjeta {
  border: 0; border-radius: var(--r);
  padding: var(--e5) var(--e5) var(--e6); display: flex; flex-direction: column;
  color: #fff; background: var(--tinta);
  box-shadow: 0 1px 2px rgba(26, 21, 18, .06), 0 8px 18px -12px rgba(26, 21, 18, .5);
  transition: box-shadow var(--sal), transform var(--sal);
}
a.g-tarjeta:hover {
  text-decoration: none; color: #fff; transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(26, 21, 18, .08), 0 16px 28px -14px rgba(26, 21, 18, .6);
}
a.g-tarjeta:active { transform: translateY(0) scale(.995); transition-duration: .06s; }
.g-tarjeta-bien { background: var(--verde); }    /* 6,6:1 con blanco */
.g-tarjeta-nada { background: var(--gris-etq); } /* 5,6:1 — el verde en cero engaña */
.g-tarjeta-urge { background: var(--granate); }  /* 13,5:1 */
.g-tarjeta-ojo  { background: var(--ambar); }    /* 5,9:1 */
.g-tarjeta-info { background: var(--azul); }     /* 8,6:1 */
.g-tarjeta-rotulo {
  display: flex; align-items: center; gap: var(--e2);
  font-size: 0.8125rem; font-weight: 700; line-height: 1.3;
}
.g-tarjeta-rotulo .g-icono { opacity: 1; }
.g-tarjeta-num {
  display: block; font-size: 2.375rem; font-weight: 800; color: #fff;
  letter-spacing: -.04em; line-height: 1; font-variant-numeric: tabular-nums;
  margin-top: var(--e3);
}
.g-tarjeta-txt {
  display: block; font-size: 0.75rem; color: rgba(255, 255, 255, .85);
  margin-top: var(--e1); line-height: 1.4;
}

/* ---------------------------------------------------------------- tablas */
/* Las tablas viven dentro de su propia caja con desplazamiento lateral. Es la
   única manera de que una tabla de doce columnas no empuje la página entera
   cuando alguien tiene la letra del navegador subida; y desplazar una tabla de
   datos a lo ancho es una salida aceptada, esconder columnas no. */
/* La caja solo se vuelve desplazable cuando hace falta, y eso tiene una razón
   que no se ve: un contenedor con overflow es un puerto de desplazamiento, y
   dentro de uno, position:sticky se pega a ESA caja, no a la ventana. Como la
   caja no se desplaza en vertical, la cabecera no se pegaría nunca. Por eso el
   desplazamiento lateral queda para las pantallas donde la tabla no cabe, que
   es donde de verdad hace falta, y en el escritorio la cabecera puede
   quedarse arriba mientras se baja por 3.144 alumnos. */
.g-tabla-caja { margin-bottom: var(--e1); }
@media (max-width: 1100px) {
  .g-tabla-caja { overflow-x: auto; }
}
.g-tabla {
  /* Las cifras con ancho fijo: el 1 ocupa lo mismo que el 8 y las columnas
     quedan a plomo; sin esto, una lista de 3.155 alumnos baila a cada fila. */
  font-variant-numeric: tabular-nums;
  width: 100%; min-width: 640px; border-collapse: separate; border-spacing: 0;
  background: var(--blanco); border: 1px solid var(--linea);
  border-radius: var(--r); box-shadow: var(--sombra);
  font-size: 0.875rem;
}
/* Antes el redondeo lo daba overflow:hidden en la tabla, que también recorta
   el pegado. Se redondean las cuatro esquinas de las celdas en su lugar. */
.g-tabla thead tr:first-child th:first-child { border-top-left-radius: var(--r); }
.g-tabla thead tr:first-child th:last-child  { border-top-right-radius: var(--r); }
.g-tabla tbody tr:last-child td:first-child  { border-bottom-left-radius: var(--r); }
.g-tabla tbody tr:last-child td:last-child   { border-bottom-right-radius: var(--r); }

.g-tabla th {
  /* Debajo de la barra superior, que también está pegada: con top:0 la
     cabecera se metía detrás de ella y desaparecía. */
  position: sticky; top: var(--barra-alto); z-index: 2;
  /* En caja baja y sin tracking: las versalitas apretadas se leen peor y en
     una cabecera de nueve columnas obligan a descifrar cada título. */
  text-align: left; font-size: 0.8125rem; font-weight: 700; letter-spacing: 0;
  color: var(--tinta); padding: var(--e3) var(--e4);
  border-bottom: 1px solid var(--linea);
  background: var(--cabecera-opaca);
  white-space: nowrap;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .g-tabla th {
    background: var(--cabecera);
    -webkit-backdrop-filter: var(--desenfoque);
    backdrop-filter: var(--desenfoque);
  }
}
.g-tabla td {
  padding: 13px var(--e4); border-bottom: 1px solid var(--linea-suave); vertical-align: top;
}
.g-tabla tbody tr:last-child td { border-bottom: 0; }
.g-tabla tbody tr { transition: background-color var(--sal-rapida); }
.g-tabla tbody tr:hover { background: #fcfaf8; }
/* Los enlaces de las tablas son la forma normal de abrir una ficha y medían
   16 px de alto, muy poco para un dedo. Se agrandan, pero con cuidado:

   · Si el enlace es lo ÚNICO de su celda, ocupa la celda entera y los
     márgenes negativos se comen el relleno, así que pasa de 16 a 44 px sin
     que la fila crezca.
   · Si comparte celda con algo más —una etiqueta de FECHA DUDOSA, un
     POSIBLE DUPLICADO—, ese margen negativo lo colocaba justo encima de la
     etiqueta y la tapaba. Ahí crece menos y empujando, no pisando. */
.g-tabla tbody td > a { display: inline-block; padding: var(--e2) 0; font-weight: 600; vertical-align: middle; }
.g-tabla tbody td > a:only-child { display: block; padding: var(--e3) 0; margin: calc(-1 * var(--e3)) 0; }
.g-tabla tbody td > a.g-etq, .g-tabla tbody td > a.g-mini { display: inline-flex; padding: var(--e1) var(--e3); }
.g-tabla tbody td > a.g-mini { padding: 0; }
.g-tabla tbody td > .g-etq { vertical-align: middle; }
.g-futura td { background: #fdfbf6; }
.g-futura td:first-child { box-shadow: inset 3px 0 0 var(--granate); }
.g-apagada td { color: var(--gris); }
.g-tel { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Los datos de contacto de una fila, apilados. El hueco se mide aquí y no se
   hereda del interlineado de la tabla: con un <br>, una fila con móvil y fijo
   medía el doble que una con un solo número y la lista se volvía un acordeón. */
.g-tels { display: inline-flex; flex-direction: column; gap: 2px; align-items: flex-start; }
.g-tels:empty { display: none; }
/* Un teléfono es un enlace que se pulsa, así que tiene que medir lo que mide un
   objetivo pulsable: 24px en pantalla grande. La línea de texto son 21, y el
   resto se pone con relleno para no separar más las dos filas. */
.g-tels > a { padding-block: 2px; min-height: 24px; display: inline-flex; align-items: center; }
.g-tel-fijo { color: var(--gris); }
.g-tel-fijo:hover, .g-tel-fijo:focus-visible { color: var(--tinta); }
/* Con el dedo hacen falta 44. En táctil se acepta la altura extra: fallar el
   número de teléfono y llamar a otra persona es peor que una lista más larga. */
@media (pointer: coarse) {
  .g-tels { gap: var(--e2); }
  .g-tels > a { min-height: 44px; }
}
/* Fechas, horas y precios en una línea: partidos en dos se leen fatal y la
   fila crece el doble sin ganar nada. */
.g-nowrap, .g-tabla td.g-derecha { white-space: nowrap; }

/* 11,5 px y no 10,5: son información de estado, no una marca de agua. */
/* Estados en color pleno. Una pastilla pálida con letra de color se lee como
   decoración; en sólido se ve el estado antes de leer la palabra, que es de lo
   que se trata cuando hay trescientas filas. Los cuatro colores son los que ya
   tenía el panel y todos pasan de 5,9:1 con blanco encima. */
.g-etq {
  display: inline-flex; align-items: center; font-size: 0.6875rem; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; padding: 5px var(--e3);
  border: 0; border-radius: var(--r-xs); color: #fff;
  background: var(--gris-etq); margin-left: var(--e2); white-space: nowrap;
}
.g-etq-abierta, .g-etq-matriculado { background: var(--verde); }
.g-etq-en_curso { background: var(--azul); }
.g-etq-aviso { background: var(--ambar); }
.g-etq-cancelada, .g-etq-nuevo { background: var(--granate); }
.g-etq-archivado, .g-etq-descartado { background: var(--gris-etq); }

/* --------------------------------------------------- filtros y formularios */
.g-filtros {
  display: flex; gap: var(--e4) var(--e4); align-items: flex-end; flex-wrap: wrap;
  background: var(--blanco); border: 1px solid var(--linea);
  border-radius: var(--r); padding: var(--e5); margin-bottom: var(--e4); box-shadow: var(--sombra);
}
.g-filtros label {
  display: block; font-size: 0.75rem; font-weight: 700; margin-bottom: var(--e2);
  color: var(--gris); letter-spacing: .01em;
}
.g-filtro-check { display: flex; align-items: center; }
.g-filtro-check label {
  display: flex; align-items: center; gap: var(--e2); min-height: 40px;
  font-size: 0.8438rem; color: var(--tinta); margin: 0; cursor: pointer;
}
/* Sin esto la casilla hereda el width:100% de la regla general de campos y
   sale un cuadro enorme con el texto estrujado al lado. */
.g-filtro-check input[type="checkbox"] {
  flex: none; width: 22px; height: 22px; min-height: 0; margin: 0;
  accent-color: var(--granate);
}

.g-form {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--e5);
  background: var(--blanco); border: 1px solid var(--linea);
  border-radius: var(--r); padding: var(--e6); margin-top: var(--e5); box-shadow: var(--sombra);
}
.g-campo { display: block; }
.g-ancho-total { grid-column: 1 / -1; }
.g-form label, .g-campo label {
  display: block; font-size: 0.8125rem; font-weight: 700; margin-bottom: var(--e2);
}
.g-form small { display: block; font-size: 0.75rem; color: var(--gris); margin-top: var(--e2); line-height: 1.5; }
.g-form fieldset { border: 1px solid var(--linea); border-radius: var(--r-s); padding: var(--e4) var(--e5); margin: 0; }
.g-form legend { font-size: 0.8125rem; font-weight: 700; padding: 0 var(--e2); }
input, select, textarea {
  width: 100%; font: inherit; padding: var(--e3) var(--e3); min-height: 42px;
  border: 1px solid var(--linea); border-radius: var(--r-s);
  background: var(--blanco); color: var(--tinta);
  transition: border-color var(--sal-rapida), box-shadow var(--sal),
              background-color var(--sal-rapida);
}
input:hover, select:hover, textarea:hover { border-color: #d8d0c6; }

/* El campo enfocado se levanta con un halo suave que crece con la curva, en
   vez de encenderse de golpe. Es lo que separa un formulario que responde de
   uno que parpadea. El anillo de foco del navegador sigue encima: esto es
   adorno, la accesibilidad la sostiene el outline. */
input:focus, select:focus, textarea:focus {
  border-color: var(--granate);
  box-shadow: 0 0 0 4px rgba(91, 20, 20, .07);
}
/* Y el bloque entero del campo se despierta un poco cuando el cursor entra en
   él: la etiqueta se oscurece, así se sabe en qué se está escribiendo sin
   tener que buscar el cursor. */
.g-campo label { transition: color var(--sal-rapida); }
.g-campo:focus-within label { color: var(--granate); }
textarea { min-height: 96px; resize: vertical; line-height: 1.55; }
.g-casillas { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e6); }
.g-casillas label {
  display: flex; align-items: center; gap: var(--e2); font-weight: 400;
  font-size: 0.875rem; margin: 0; min-height: 40px; cursor: pointer;
}
.g-casillas input[type="checkbox"] {
  width: 22px; height: 22px; min-height: 0; margin: 0; accent-color: var(--granate);
}
/* ------------------------------------------------- subir foto o portada */
/* Se ve la imagen que hay ahora al lado del campo: sin eso no hay manera de
   saber si el fichero que se va a sustituir es el bueno. */
.g-subida { display: flex; gap: var(--e5); align-items: flex-start; }
.g-subida-campos { flex: 1 1 auto; min-width: 0; }
.g-subida-campos small { margin-top: var(--e2); }
.g-subida-mini {
  flex: none; width: 66px; height: 66px; border-radius: 50%;
  object-fit: cover; border: 1px solid var(--linea); background: var(--linea-suave);
}
.g-subida-tarjeta {
  flex: none; width: 120px; height: 75px; border-radius: var(--r-s);
  object-fit: cover; border: 1px solid var(--linea); background: var(--linea-suave);
}
.g-subida-hueco {
  flex: none; display: grid; place-items: center;
  width: 66px; height: 66px; border-radius: 50%;
  background: var(--linea-suave); border: 1px dashed var(--linea);
  /* El gris suave da 4,36:1 sobre este beige, justo por debajo del mínimo. */
  color: var(--gris); font-size: 0.875rem; font-weight: 700;
}
.g-subida-hueco-ancho {
  width: 120px; height: 75px; border-radius: var(--r-s);
  font-size: 0.6875rem; font-weight: 600; letter-spacing: .02em;
}
.g-subida input[type="file"] {
  padding: var(--e2) var(--e3); font-size: 0.875rem; background: var(--papel);
  cursor: pointer;
}
.g-subida input[type="file"]::file-selector-button {
  font: inherit; font-weight: 600; margin-right: var(--e3); cursor: pointer;
  padding: var(--e2) var(--e4); min-height: 32px;
  border: 1px solid var(--linea); border-radius: var(--r-s);
  background: var(--blanco); color: var(--tinta);
}
.g-subida input[type="file"]::file-selector-button:hover { background: var(--linea-suave); }
.g-subida-quitar {
  display: flex; align-items: center; gap: var(--e2); margin-top: var(--e3);
  font-weight: 400; font-size: 0.875rem; min-height: 40px; cursor: pointer;
}
.g-subida-quitar input[type="checkbox"] {
  width: 22px; height: 22px; min-height: 0; margin: 0; accent-color: var(--granate);
}
@media (max-width: 620px) {
  .g-subida { flex-direction: column; }
}

/* ---------------------------------------------------------------- borrar */
/* Aparte del bloque de guardar y con otro peso: borrar no es una acción más
   del formulario, y ponerla al lado de «Guardar» invita a pulsarla sin
   querer. Aquí abajo, discreta, y con una pantalla de confirmación detrás. */
.g-borrar {
  display: flex; align-items: center; gap: var(--e4); flex-wrap: wrap;
  margin: var(--e7) 0 0; padding-top: var(--e6); border-top: 1px solid var(--linea);
}
.g-borrar .g-nota { margin: 0; }
.g-boton-peligro-linea {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: var(--e3) var(--e5); font: inherit; font-weight: 600;
  border: 1px solid #e0d0ce; border-radius: var(--r-s); cursor: pointer;
  background: var(--blanco); color: var(--granate);
}
.g-boton-peligro-linea:hover { background: var(--granate-suave); border-color: #d3b8b5; }
.g-boton-peligro {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: var(--e3) var(--e6); font: inherit; font-weight: 700;
  border: 1px solid var(--granate); border-radius: var(--r-s); cursor: pointer;
  background: var(--granate); color: var(--papel);
}
.g-boton-peligro:hover { background: #4a1010; border-color: #4a1010; }

/* Órdenes para copiar y pegar: se seleccionan enteras de un clic. */
.g-orden {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8125rem; line-height: 1.6; background: var(--tinta); color: #e8e0d8;
  border-radius: var(--r-s); padding: var(--e3) var(--e4); margin: var(--e3) 0 var(--e5);
  overflow-x: auto; user-select: all;
}
.g-detalle-caja { margin-top: var(--e6); }
/* ------------------------------------------------- índice de un apartado */
/* Fichas de entrada a las pantallas de un apartado. No son las tarjetas de
   colores del panel: aquéllas son cifras que gritan, éstas son puertas. De
   ahí el fondo blanco, el borde fino y el dato en pequeño abajo. */
.g-indice {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--e3); margin: var(--e5) 0 var(--e7);
}
.g-indice-ficha {
  display: grid; grid-template-columns: 22px 1fr; grid-template-areas:
    "icono nombre" ".     que" ".     dato";
  gap: 2px var(--e3); align-content: start;
  background: var(--blanco); border: 1px solid var(--linea); border-radius: var(--r);
  padding: var(--e4) var(--e5) var(--e5); color: var(--tinta); box-shadow: var(--sombra);
  transition: border-color var(--sal), box-shadow var(--sal), transform var(--sal);
}
.g-indice-ficha:hover {
  text-decoration: none; color: var(--tinta); border-color: #d8cdc4;
  box-shadow: var(--sombra-alta); transform: translateY(-2px);
}
.g-indice-ficha:active { transform: translateY(0) scale(.995); transition-duration: .06s; }
.g-indice-ficha .g-icono { grid-area: icono; margin-top: 2px; color: var(--granate); opacity: 1; }
.g-indice-nombre { grid-area: nombre; font-weight: 700; font-size: 1rem; }
.g-indice-que { grid-area: que; font-size: 0.8125rem; color: var(--gris); line-height: 1.45; }
.g-indice-dato {
  grid-area: dato; margin-top: var(--e2); font-size: 0.75rem; color: var(--gris-suave);
}
.g-indice-dato strong { color: var(--granate); }

/* ------------------------------------------- vista previa de un correo */
/* Se pinta como llega a la bandeja, con su remitente y su asunto arriba: un
   textarea no dice nada de cómo se va a ver, y esto sale hacia mil personas. */
.g-vista {
  border: 1px solid var(--linea); border-radius: var(--r); overflow: hidden;
  background: var(--blanco); box-shadow: var(--sombra); margin: var(--e3) 0 var(--e6);
}
.g-vista-cab {
  padding: var(--e4) var(--e5); border-bottom: 1px solid var(--linea);
  background: var(--linea-suave); display: flex; flex-direction: column; gap: 3px;
}
.g-vista-de { font-size: 0.75rem; color: var(--gris); }
.g-vista-cab strong { font-size: 1rem; }
.g-vista-cuerpo { padding: var(--e2) var(--e4) var(--e5); }
.g-vista-cuerpo hr { border: 0; border-top: 1px solid var(--linea); margin: var(--e5) var(--e4); }
.g-vista-pie { font-size: 0.75rem; color: var(--gris); margin: 0 var(--e4); line-height: 1.5; }

.g-lista-tareas { margin: var(--e3) 0 0; padding-left: var(--e5); line-height: 1.65; }
.g-lista-tareas li { margin-bottom: var(--e2); }

.g-acciones { display: flex; gap: var(--e3); align-items: center; flex-wrap: wrap; }
.g-error { color: var(--granate); font-weight: 600; margin: 0 0 var(--e3); }

.g-pie {
  border-top: 1px solid var(--linea); padding: var(--e6) 0; text-align: center;
  font-size: 0.75rem; color: var(--gris);
}

/* ---------------------------------------------------------------- acceso */
.g-acceso-body { display: grid; place-items: center; min-height: 100vh; background: var(--tinta); }
.g-acceso {
  background: var(--papel); padding: var(--e8) var(--e8); width: min(430px, 100% - 32px);
  border-radius: var(--r); border-top: 3px solid var(--granate);
  box-shadow: 0 30px 60px -24px rgba(0, 0, 0, .55);
}
.g-acceso img { display: block; margin-bottom: var(--e7); width: 244px; height: auto; }
.g-acceso h1 { font-size: 1.4375rem; font-weight: 800; }
.g-acceso-intro { font-size: 0.875rem; color: var(--gris); margin: var(--e2) 0 var(--e6); }
.g-acceso label { display: block; font-size: 0.8125rem; font-weight: 700; margin: var(--e4) 0 var(--e2); }
.g-acceso button {
  width: 100%; margin-top: var(--e6); min-height: 46px; border: 0; border-radius: var(--r-s);
  background: var(--granate); color: #fff; font: inherit; font-weight: 700; cursor: pointer;
}
.g-acceso button:hover { background: var(--granate-claro); }

/* --------------------------------------------- pestañas, datos, historial */
/* 44 px de alto: el panel también se usa en tableta. */
.g-pestanas { display: flex; gap: var(--e2); flex-wrap: wrap; margin: var(--e5) 0 var(--e4); }
.g-pestanas a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--e4);
  font-size: 0.8438rem; font-weight: 600; color: var(--gris);
  border: 1px solid transparent; border-radius: 999px;
}
.g-pestanas a:hover { color: var(--tinta); text-decoration: none; background: var(--linea-suave); }
.g-pestanas a[aria-current="page"] {
  background: var(--blanco); border-color: var(--linea); color: var(--tinta);
  box-shadow: var(--sombra);
}
.g-cuenta {
  display: inline-flex; align-items: center; background: var(--linea-suave);
  border-radius: 999px; padding: 2px var(--e2); font-size: 0.7188rem; font-weight: 700;
  margin-left: var(--e2); font-variant-numeric: tabular-nums;
}
.g-pestanas a[aria-current="page"] .g-cuenta { background: var(--granate); color: #fff; }

.g-datos {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  background: var(--linea); border: 1px solid var(--linea);
  border-radius: var(--r); overflow: hidden; margin: var(--e5) 0 var(--e2); box-shadow: var(--sombra);
}
.g-datos > div { background: var(--blanco); padding: var(--e4) var(--e5); font-size: 0.875rem; }
.g-datos span {
  display: block; font-size: 0.75rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--gris); margin-bottom: var(--e2);
}
.g-historial {
  background: var(--blanco); border: 1px solid var(--linea); border-radius: var(--r);
  padding: var(--e5) var(--e5); font: inherit; font-size: 0.8438rem; white-space: pre-wrap;
  line-height: 1.65; margin: 0; box-shadow: var(--sombra);
}

.g-paginas {
  display: flex; align-items: center; justify-content: center; gap: var(--e5);
  padding: var(--e6) 0; font-size: 0.875rem;
}
.g-paginas span { color: var(--gris); }

.g-detalle {
  background: var(--blanco); border: 1px solid var(--linea); border-radius: var(--r);
  padding: var(--e4) var(--e5); margin: var(--e4) 0; font-size: 0.8438rem;
}
/* 20 px de alto medidos: es un control que se pulsa, así que se le da altura
   de diana en vez de dejarlo a la altura de la línea. */
.g-detalle summary {
  cursor: pointer; font-weight: 600;
  display: flex; align-items: center; gap: var(--e2); min-height: 40px;
  list-style: none; transition: color var(--sal-rapida);
}
.g-detalle summary::-webkit-details-marker { display: none; }
/* Triángulo propio: el del navegador no se puede animar y cambia de forma en
   cada sistema. Este gira 90° con la curva larga al abrir. */
.g-detalle summary::before {
  content: ""; flex: none; width: 7px; height: 7px;
  border-right: 2px solid var(--granate); border-bottom: 2px solid var(--granate);
  transform: rotate(-45deg); transform-origin: 60% 60%;
  transition: transform var(--sal-larga);
}
.g-detalle[open] summary::before { transform: rotate(45deg); }
.g-detalle summary:hover { color: var(--granate); }
.g-detalle p { margin: var(--e3) 0 0; color: var(--gris); line-height: 1.65; }

/* ------------------------------------------------------------ adaptación */
@media (max-width: 1180px) {
  .g-tarjetas { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 1000px) {
  /* La lateral se convierte en una tira horizontal arriba: sin JavaScript no
     hay menú desplegable que valga, y una tira que se arrastra con el dedo es
     más honesta que esconder once apartados detrás de un icono. */
  .g-cuerpo { grid-template-columns: 1fr; }
  .g-lateral {
    position: static; height: auto; flex-direction: row; align-items: center;
    gap: var(--e1); padding: var(--e2) var(--e4); overflow-x: auto; overflow-y: hidden;
  }
  .g-marca { padding: 0 var(--e4) 0 var(--e1); flex: none; }
  .g-grupo { display: none; }
  .g-nav { flex: none; white-space: nowrap; min-height: 40px; }
  .g-nav span { font-size: 0.8125rem; }
  .g-lateral-pie { margin: 0; padding: 0; flex: none; }
  .g-barra { padding: 0 var(--e5); }
  .g-form { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .g-ancho { width: calc(100% - 32px); }
  .g-tarjetas { grid-template-columns: 1fr; }
  .g-titulo { font-size: 1.5rem; }
  .g-datos { grid-template-columns: 1fr 1fr; }
  .g-icono { display: none; }
}
@media (max-width: 820px) { .g-datos { grid-template-columns: 1fr 1fr; } }
/* --------------------------------------------------- movimiento reducido
   Quien lo tiene activo no pide una versión pobre del panel: pide que no se
   mueva. Se quedan los colores, las sombras, el cristal y el redondeo —todo
   lo que es diseño y no movimiento— y desaparecen las curvas, los
   desplazamientos y el giro del triángulo. El estado final es el mismo, se
   llega a él sin recorrido. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  a.g-tarjeta:hover, a.g-tarjeta:active,
  .g-boton:active, .g-boton-linea:active { transform: none; }
  /* El triángulo sigue diciendo si está abierto o cerrado: es información,
     no adorno. Solo deja de girar. */
}

/* El teléfono tal cual lo escribió el Access. Monoespaciado porque lo que se
   mira son los signos —dónde cae una coma, dónde un espacio— y con la
   proporcional se confunden. */
.g-bruto { font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: .86em; color: var(--gris); word-break: break-all; }

/* ---------------------------------------------------------------- editor
   El lienzo lleva la clase .prosa, la misma de la web, así que lo que se
   escribe se ve con la tipografía con la que va a salir publicado. Ahí está
   la vista previa: no hace falta una segunda ventana al lado, porque el sitio
   donde se escribe YA es como queda. */
.e-editor { border: 1px solid var(--linea); border-radius: 10px; background: var(--blanco);
  overflow: hidden; transition: border-color .18s var(--curva), box-shadow .18s var(--curva); }
.e-editor:focus-within { border-color: var(--granate); box-shadow: 0 0 0 3px var(--granate-suave); }

.e-barra { display: flex; flex-wrap: wrap; align-items: center; gap: 2px;
  padding: var(--e2) var(--e3); border-bottom: 1px solid var(--linea); background: var(--papel); }
.e-boton { font: inherit; font-size: .82rem; line-height: 1; color: var(--tinta);
  background: transparent; border: 1px solid transparent; border-radius: 7px;
  padding: 0 var(--e3); min-height: 30px; cursor: pointer;
  display: inline-flex; align-items: center;
  transition: background .15s var(--curva), border-color .15s var(--curva); }
.e-boton:hover { background: var(--blanco); border-color: var(--linea); }
.e-boton:active { transform: translateY(1px); }
.e-negrita { font-weight: 700; }
.e-cursiva { font-style: italic; font-family: Georgia, serif; }
.e-separador { width: 1px; height: 18px; background: var(--linea); margin: 0 var(--e2); }

/* La tipografía se declara ENTERA aquí, sin heredar nada. El panel no carga
   web.css, así que la clase .prosa no trae consigo los estilos de la web: sin
   estas líneas el lienzo heredaba Archivo en negrita y mayúsculas de un
   ascendiente, y execCommand('bold') veía el texto ya en negrita y lo que
   hacía era QUITARLA. Un editor que hace lo contrario de lo que dice el botón.
   Además, así se parece a como sale publicado, que era la idea. */
.e-lienzo { padding: var(--e5) var(--e5) var(--e4); min-height: 190px; outline: 0;
  font-family: var(--serif-web); font-size: 1.02rem; font-weight: 400;
  font-style: normal; text-transform: none; letter-spacing: normal;
  line-height: 1.65; color: var(--tinta); }
.e-lienzo strong, .e-lienzo b { font-weight: 700; }
.e-lienzo em, .e-lienzo i { font-style: italic; }
.e-lienzo:empty::before { content: attr(data-vacio); color: var(--gris); }
.e-lienzo > :first-child { margin-top: 0; }
.e-lienzo > :last-child { margin-bottom: 0; }
.e-lienzo p { margin: 0 0 .9em; }
.e-lienzo h2 { font-size: 1.22rem; font-weight: 600; margin: 1.2em 0 .45em; }
.e-lienzo h3 { font-size: 1.06rem; font-weight: 600; margin: 1.1em 0 .4em; }
.e-lienzo ul, .e-lienzo ol { margin: 0 0 .9em; padding-left: 1.35em; }
.e-lienzo li { margin-bottom: .25em; }
.e-lienzo a { color: var(--granate); text-decoration: underline; text-underline-offset: 2px; }

/* El textarea sigue ahí y sigue siendo el que se envía: solo deja de verse.
   Con `display:none` algunos navegadores dejan de enviarlo en según qué
   casos, y sobre todo se pierde el mensaje del navegador si algún día lleva
   `required`. Así sigue existiendo, medido y accesible al formulario. */
.e-oculto { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

@media (prefers-reduced-motion: reduce) {
  .e-editor, .e-boton { transition: none; }
  .e-boton:active { transform: none; }
}

/* --------------------------------------------------- bloques del formulario
   OJO CON EL NOMBRE: se llamó .g-grupo la primera vez y esa clase ya estaba
   cogida por los rótulos del menú lateral («DÍA A DÍA», «FICHAS»). Los
   fieldsets heredaron su estilo —minúsculas de 10 px, negrita y mayúsculas— y
   con ello todos los rótulos del formulario, además de romper el editor: al
   heredar negrita, el botón de negrita QUITABA el formato en vez de ponerlo.
   Antes de inventar una clase, comprobar que no exista ya.

   Un formulario de 2.600 px sin descansos obliga a leerlo entero para saber
   dónde está cada cosa. Agrupado, se salta directamente al bloque que se va a
   tocar. No son pestañas a propósito: una pestaña esconde campos y después
   nadie recuerda que existen —de hecho así fue como «objetivos» y «a quién va
   dirigido» llevaban un año sin poder rellenarse—. */
.g-bloque { border: 0; padding: 0; margin: 0 0 var(--e7); display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e5); }
.g-bloque-titulo { grid-column: 1 / -1; padding: 0; margin: 0 0 calc(var(--e2) * -1);
  font-size: .78rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--gris); }
.g-bloque + .g-bloque { padding-top: var(--e6); border-top: 1px solid var(--linea); }
.g-bloque > .g-nota { grid-column: 1 / -1; margin: 0; }
@media (max-width: 720px) { .g-bloque { grid-template-columns: 1fr; } }

/* ------------------------------------------------------ bloque plegable
   Para lo que casi nunca se toca. Con <details>, que pliega sin JavaScript:
   si el navegador no ejecuta nada, el bloque sale abierto y todo funciona. */
.g-plegable { margin: 0 0 var(--e7); border-top: 1px solid var(--linea); padding-top: var(--e5); }
.g-plegable-titulo { cursor: pointer; list-style: none; display: flex; align-items: baseline;
  gap: var(--e3); font-size: .78rem; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--gris); padding: var(--e2) 0; min-height: 24px; }
.g-plegable-titulo::-webkit-details-marker { display: none; }
.g-plegable-titulo::before { content: "▸"; font-size: .9em; transition: transform .18s var(--curva); }
.g-plegable[open] > .g-plegable-titulo::before { transform: rotate(90deg); }
.g-plegable-titulo:hover { color: var(--tinta); }
.g-plegable-titulo:focus-visible { outline: 2px solid var(--granate); outline-offset: 3px; border-radius: 5px; }
.g-plegable-pista { text-transform: none; letter-spacing: normal; font-weight: 400; color: var(--gris); }
.g-plegable[open] > .g-bloque { margin-top: var(--e4); }
.g-plegable > .g-bloque { border-top: 0; padding-top: 0; }
@media (prefers-reduced-motion: reduce) { .g-plegable-titulo::before { transition: none; } }

/* Notas en lista dentro de un campo (la comparativa de servicios de IA). */
.g-lista-nota { margin: var(--e2) 0 0; padding-left: 1.15em; font-size: .75rem;
  color: var(--gris); line-height: 1.5; }
.g-lista-nota li { margin-bottom: var(--e2); }
.g-lista-nota strong { color: var(--tinta); }

/* ------------------------------------------------- herramientas de listado */
.g-herramientas { display: flex; flex-wrap: wrap; gap: var(--e3); align-items: center;
  margin: calc(var(--e4) * -1) 0 var(--e4); }

/* Cabecera que ordena. La flecha no es adorno: sin ella hay que pulsar para
   averiguar por dónde está ordenada la tabla. */
.g-ordenar { display: inline-flex; align-items: center; gap: 3px; color: inherit;
  text-decoration: none; min-height: 24px; }
.g-ordenar:hover { color: var(--granate); }
.g-ordenar-activo { color: var(--granate); font-weight: 700; }
.g-ordenar:focus-visible { outline: 2px solid var(--granate); outline-offset: 2px; border-radius: 4px; }

.g-columnas { position: relative; }
.g-columnas-titulo { cursor: pointer; list-style: none; display: inline-flex; align-items: center;
  gap: var(--e2); font-size: .82rem; font-weight: 600; color: var(--tinta);
  border: 1px solid var(--linea); background: var(--blanco); border-radius: 9px;
  padding: 0 var(--e4); min-height: 36px; }
.g-columnas-titulo::-webkit-details-marker { display: none; }
.g-columnas-titulo:hover { border-color: var(--linea-fuerte); }
.g-columnas-titulo:focus-visible { outline: 2px solid var(--granate); outline-offset: 2px; }
.g-columnas-pista { color: var(--gris); font-weight: 400; font-size: .78rem; }
.g-columnas-caja { position: absolute; z-index: 5; margin-top: var(--e2); min-width: 220px;
  background: var(--blanco); border: 1px solid var(--linea); border-radius: 10px;
  padding: var(--e4); box-shadow: var(--sombra-alta, 0 8px 28px rgba(26,21,18,.14)); }
.g-columnas-op { display: flex; align-items: center; gap: var(--e3); font-weight: 400;
  font-size: .875rem; padding: var(--e2) 0; min-height: 28px; margin: 0; }
.g-columnas-op input { width: auto; min-height: 0; }
.g-columnas-op small { color: var(--gris); }
.g-columnas-pie { margin-top: var(--e3); padding-top: var(--e3); border-top: 1px solid var(--linea); }

/* --- Visitas -------------------------------------------------------------
   Las barras son las de siempre en una tabla, sin librería de gráficos: un
   <span> con un ancho en tanto por ciento. No hay JavaScript detrás, se
   imprimen bien y no se rompen si falla nada. */
.g-barrita {
  display: block;
  height: 10px;
  border-radius: 5px;
  background: var(--azul);
  min-width: 2px;
}
.g-tabla td:has(> .g-barrita) { vertical-align: middle; }

/* Las horas del día, una columna por hora. */
.g-horas {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  gap: 3px;
  align-items: end;
  height: 130px;
  margin: var(--e1) 0 var(--e2);
  padding: var(--e1);
  background: var(--papel);
  border-radius: var(--r);
}
.g-hora { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.g-hora-barra { display: block; width: 100%; background: var(--azul); border-radius: 3px 3px 0 0; }
.g-hora-etq { font-size: 0.688rem; color: var(--gris-etq); margin-top: 4px; min-height: 1em; }

/* Dos bloques uno al lado del otro que se ponen en columna cuando no caben.
   Con minmax(0, 1fr) y no con 1fr a secas: una tabla ancha dentro de una
   columna «1fr» empuja la rejilla y desborda la página entera.

   Se llama «g-dos-columnas» y no «g-columnas» porque ese nombre ya era el del
   desplegable de elegir columnas de un listado, que es un <details>: ponerle
   display:grid le rompía la caja. Cuarta colisión de nombre del proyecto y la
   que hizo escribir tools/prueba_css.php. */
.g-dos-columnas {
  display: grid;
  gap: var(--e2);
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  align-items: start;
}
.g-dos-columnas > * { min-width: 0; }

/* Una tabla de dos o tres columnas dentro de media página no necesita los
   640px de ancho mínimo de las tablas de listado: con ellos se sale de su
   columna y empuja la página entera hacia la derecha. */
.g-tabla-corta { min-width: 0; }

/* «Salir» es un botón dentro de un formulario, no un enlace: la acción cambia
   algo (cierra la sesión) y eso no puede viajar por GET. Se le quita lo que
   un navegador le pone a un botón para que se siga viendo igual que antes. */
.g-salir-form { display: flex; margin: 0; }
button.g-salir {
  font: inherit; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center;
  min-height: 38px;
}
