/* Sistema visual de la vista publica del calendario de Casa Lavalle.
 *
 * ORDEN DE CARGA OBLIGATORIO en el <head>:
 *   1. vendor/fullcalendar/skeleton.css
 *   2. vendor/fullcalendar/theme.css
 *   3. vendor/fullcalendar/palette.css
 *   4. este archivo
 * Y al final del <body>, en este orden: vendor/fullcalendar/global.js y luego
 * vendor/fullcalendar/theme.js. theme.js es el complemento del tema classic:
 * sin el no existe ni una clase .fc-classic-* en el DOM y los overrides de
 * mas abajo no pintan nada.
 * Los overrides de --fc-classic-* viven en :root igual que los de palette.css:
 * misma especificidad, gana el ultimo en cargar.
 *
 * El bloque de tokens esta duplicado respecto a admin/recursos/admin.css a
 * proposito. Los dos subdominios se despliegan a carpetas distintas dentro de
 * public_html y no hay ninguna ruta que puedan compartir, asi que una hoja
 * comun tendria que servirse desde uno de los dos y volveria a cada vista
 * dependiente del otro. Si un token cambia, cambia en los dos archivos.
 *
 * Todo literal hexadecimal vive en :root. pruebas/test-tokens.php lo comprueba.
 *
 * Esta vista se abre una vez, casi siempre desde el celular, para responder
 * "esta libre el 14?". No es la herramienta diaria que describe §7: es la
 * primera impresion de la casa, y por eso aqui el movimiento si tiene permiso
 * cuando comunica algo.
 */

:root {
  /* Paleta de marca (§7 del blueprint) */
  --azul-lavalle:    #09394C;
  --marfil:          #F7F4EF;
  --carbon:          #2C2C2C;
  --gris-piedra:     #A7A19A;
  --bronce-anzures:  #9C7A45;
  --blanco:          #FFFFFF;
  --rojo-alerta:     #8C2F26;
  --linea:           #E4DFD7;

  /* Derivados con alfa. --gris-piedra da 2.3:1 sobre marfil y nunca es texto:
     el texto secundario es carbon con opacidad, 8.5:1. */
  --carbon-70:  #2C2C2CB3;
  --carbon-50:  #2C2C2C80;
  --carbon-14:  #2C2C2C24;
  --carbon-08:  #2C2C2C14;
  --carbon-04:  #2C2C2C0A;
  --azul-30:    #09394C4D;
  --azul-08:    #09394C14;
  --bronce-30:  #9C7A454D;
  --bronce-17:  #9C7A452B;
  --bronce-08:  #9C7A4514;
  --rojo-30:    #8C2F264D;
  --rojo-08:    #8C2F2614;
  --linea-60:   #E4DFD799;
  --azul-04:    #09394C0A;
  --blanco-70:  #FFFFFFB3;
  --blanco-30:  #FFFFFF4D;
  --blanco-16:  #FFFFFF29;
  --blanco-08:  #FFFFFF14;

  /* Azul opaco al 92%, para la cabecera de vidrio. Solido seria un bloque y
     transparente del todo dejaria el texto blanco sobre marfil. */
  --azul-92:    #09394CEB;

  /* Dos vecinos del azul de marca para degradados y estados. No son colores
     nuevos: es el mismo tono con la luminosidad movida, y existen como token
     porque un degradado escrito a mano seria un hex fuera de :root. */
  --azul-hondo: #062836;
  --azul-alto:  #0C4C64;

  --fuente-ui:         "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  --fuente-editorial:  "Newsreader", Georgia, serif;

  --e1: 4px;
  --e2: 8px;
  --e3: 12px;
  --e4: 16px;
  --e6: 24px;
  --e8: 32px;
  --e12: 48px;
  --e16: 64px;

  --radio: 4px;
  --radio-int: 2px;   /* interior: muestra de leyenda, bloque de evento */

  /* Profundidad. §7 reserva la sombra al panel y al desplegable, y esa regla se
     mantiene para lo que de verdad flota. --sombra-canto no es una sombra en el
     sentido de §7: son 2px que definen el borde de una superficie que ya tiene
     borde, y sin ella tarjeta, aviso y tabla pesan exactamente igual. */
  --sombra-canto:   0 1px 2px rgba(44, 44, 44, .05);
  --sombra-alzada:  0 2px 4px rgba(44, 44, 44, .06), 0 6px 16px rgba(44, 44, 44, .07);
  --sombra-panel:   0 2px 12px rgba(44, 44, 44, .10);
  --sombra-menu:    0 8px 28px rgba(44, 44, 44, .16);
  --sombra-elevada: 0 16px 40px rgba(44, 44, 44, .18);
  --sombra-barra:   0 1px 0 rgba(44, 44, 44, .04), 0 6px 20px rgba(44, 44, 44, .08);

  --anillo-foco: 0 0 0 3px var(--bronce-17);

  /* ease-out-quart. Sin rebote y sin elastico: la casa no rebota. */
  --curva: cubic-bezier(.22, .78, .28, 1);
  --transicion:       120ms var(--curva);
  --transicion-media: 200ms var(--curva);
  --transicion-larga: 320ms var(--curva);

  /* Radio de pastilla. La escala del sistema sigue siendo 4px para superficies;
     esto es solo para lo que es un disco o una pildora por definicion: avatar,
     punto de estado, control segmentado. */
  --radio-pastilla: 999px;

  /* --- FullCalendar 7 classic, reasignado a la paleta de la casa --- */
  --fc-classic-button:               var(--blanco);
  --fc-classic-button-border:        var(--linea);
  /* Es el fondo del boton en hover, no el del boton activo. Marfil sobre
     blanco casi no se ve; el bronce al 8% es el mismo hover que .boton. */
  --fc-classic-button-strong:        var(--bronce-08);
  --fc-classic-button-strong-border: var(--bronce-anzures);
  --fc-classic-button-outline:       var(--bronce-anzures);
  --fc-classic-button-foreground:    var(--carbon);

  --fc-classic-primary:            var(--azul-lavalle);
  --fc-classic-primary-foreground: var(--blanco);

  --fc-classic-background-event: var(--gris-piedra);
  --fc-classic-highlight:        var(--bronce-17);
  --fc-classic-today:            var(--bronce-08);
  --fc-classic-now:              var(--bronce-anzures);
  --fc-classic-ring-color:       var(--bronce-anzures);

  --fc-classic-background: var(--blanco);
  --fc-classic-faint:      var(--marfil);
  --fc-classic-muted:      var(--carbon-08);
  --fc-classic-strong:     var(--carbon-14);

  --fc-classic-foreground:       var(--carbon);
  --fc-classic-faint-foreground: var(--carbon-50);
  --fc-classic-muted-foreground: var(--carbon-70);

  --fc-classic-border:        var(--linea);
  --fc-classic-strong-border: var(--gris-piedra);
}

/* ---------- Tipografias ---------- */

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fuentes/inter-tight-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fuentes/inter-tight-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("fuentes/newsreader-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("fuentes/newsreader-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- Base ---------- */

*, *::before, *::after { box-sizing: border-box; }

/* El atributo hidden gana sobre cualquier regla de display de esta hoja.
   Sin este !important, .aviso { display: flex } le gana a la regla [hidden]
   del navegador (una hoja de autor siempre vence a la del agente de usuario) y
   el aviso de error del calendario queda visible desde el primer pintado,
   pase lo que pase con la peticion. Es lo que hacia que la pagina publica
   dijera "Error al cargar la disponibilidad" con el calendario funcionando. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font: 400 14px/1.5 var(--fuente-ui);
  color: var(--carbon);
  background: var(--marfil);
}

/* Escala con contraste real entre pasos. Antes 24/16/14/12 caian casi en la
   misma mancha: el h1 en Newsreader a 24px no alcanzaba a leerse como el gesto
   editorial que §7 pide. */
h1 {
  margin: 0;
  font: 300 32px/1.1 var(--fuente-editorial);
  letter-spacing: -0.02em;
}

a {
  color: var(--azul-lavalle);
  text-decoration-color: var(--azul-30);
  text-underline-offset: 3px;
  transition: color var(--transicion), text-decoration-color var(--transicion);
}

a:hover {
  color: var(--bronce-anzures);
  text-decoration-color: var(--bronce-anzures);
}

:focus-visible {
  outline: 2px solid var(--bronce-anzures);
  outline-offset: 2px;
}

.secundario { color: var(--carbon-70); }

.solo-lectores {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Tercer escalon de la jerarquia. No se distingue del cuerpo por tamano, que
   ya esta en el minimo legible, sino por caja alta, tracking y color. */
.etiqueta {
  display: block;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--carbon-70);
}

/* ---------- Encabezado ---------- */

/* Antes el logotipo quedaba a la izquierda y el titulo empujado a la derecha
   con margin-left:auto. Dos anclas opuestas y nada en medio: se leia como dos
   encabezados distintos. Ahora es una sola masthead alineada a la izquierda,
   con el filete que separa la cabecera del contenido. */
/* La cabecera es una banda con fondo propio y no texto suelto sobre el marfil
   de la pagina. Sin ella, la primera pantalla de la vista publica era un titulo
   flotando encima de una tabla, que es exactamente como se ve una herramienta
   interna. El degradado va de blanco a marfil, muy corto, y el filete de bronce
   de abajo es el unico acento de marca que entra aqui.
   El logotipo se queda azul sobre claro, que es como esta hecho: recolorearlo
   para poder ponerlo sobre un fondo oscuro seria componer el logotipo. */
.encabezado {
  position: relative;
  background: linear-gradient(180deg, var(--blanco), var(--marfil));
  border-bottom: 1px solid var(--linea);
}

.encabezado::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: linear-gradient(90deg, var(--bronce-anzures), var(--bronce-30) 40%, transparent);
}

.encabezado-interior {
  max-width: 1120px;
  margin: 0 auto;
  padding: var(--e8) var(--e4) var(--e12);
}

.encabezado-marca {
  display: inline-block;
  margin-bottom: var(--e8);
  border-radius: var(--radio);
}

.encabezado-logo {
  display: block;
  height: 30px;
  width: auto;
}

.encabezado-titulo { max-width: 60ch; }

.encabezado-nota {
  display: block;
  margin-top: var(--e3);
  font-size: 16px;
  line-height: 1.6;
  max-width: 52ch;
}

.envoltura {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 var(--e4) var(--e16);
}

.tarjeta {
  /* La tarjeta arranca debajo de la banda, no montada sobre ella. Se intento el
     solape de --e8 y en pantalla el canto superior cae justo encima del filete
     de bronce y lo parte: se lee como un error de maquetacion, no como un
     gesto. Aire limpio dice lo mismo sin la duda. */
  margin-top: var(--e6);
  padding: var(--e6);
  background: var(--blanco);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-alzada);
}

/* ---------- Reticula del calendario ---------- */

/* El bloque de evento traia el relleno de fabrica de FullCalendar, pensado
   para una retícula mas apretada que esta. */
#calendario {
  --fc-classic-small-dot-width: 6px;
  --fc-classic-large-dot-width: 10px;
  transition: opacity var(--transicion-media);
}

/* Mientras llega la primera respuesta manda la silueta de carga. Sin esto las
   dos se pintan encima y se ve una reticula vacia sobre otra. publico.js quita
   aria-busy en cuanto hay respuesta, buena o mala. */
#calendario[aria-busy="true"] {
  opacity: 0;
  pointer-events: none;
}

#calendario a {
  text-decoration: none;
  transition: color var(--transicion);
}

/* ---------- Estados del evento ---------- */

/* FullCalendar 7 no expone clases semanticas: las suyas van hasheadas
   (.fc-classic-YjJ). El unico enganche estable es el refiner className del
   evento, y tiene que ser una CADENA: con un arreglo, refineClassName()
   devuelve '' y la clase no llega al DOM (ver publico.js).

   Los dos --fc-event-* llevan !important y no es descuido. FullCalendar
   escribe esas dos variables como estilo EN LINEA sobre cada evento
   (style="--fc-event-color: var(--fc-classic-event)"), y un estilo en linea le
   gana a cualquier regla de clase por especificidad. !important en una hoja de
   autor es lo unico que gana a un estilo en linea sin !important, y sin el la
   marca del bloque, el punto de los eventos con hora y el borde salen todos del
   color por defecto del tema, que es el mismo para los tres estados.

   background-color, border y color NO lo necesitan: ahi competimos contra la
   clase hasheada del tema, misma especificidad, y esta hoja carga despues.

   El estado nunca se comunica solo por color: cada bloque lleva su etiqueta. */

/* Aqui no existe el estado cancelado: la API publica no lo devuelve. */

/* El color del texto lo tiene que heredar TODO lo que hay dentro del bloque.
   FullCalendar pinta el texto en un hijo con clase propia, y esa clase usa
   --fc-event-contrast-color en unos casos y el color de texto normal del tema en
   otros, segun el bloque quepa en una linea o en varias. El resultado se ve en
   pantalla: el mismo bloque salia con la palabra blanca cuando cabia en una
   linea y en carbon, ilegible sobre el azul, cuando no.
   Heredar del contenedor lo deja en un solo color, sea cual sea el caso. */
.evento-ocupado * {
  color: inherit;
}

.evento-ocupado {
  padding: 2px var(--e2);
  border-radius: var(--radio-int);
  overflow: hidden;
  cursor: pointer;
  transition: box-shadow var(--transicion), transform var(--transicion);
}

/* El bloque se levanta 1px al pasar el puntero. Es la unica pista de que se
   puede abrir: sin ella, un bloque y una celda vacia se ven igual de inertes.

   El fondo se vuelve a declarar aqui, identico al reposo, y eso no es
   redundante: el tema aplica .fc-classic-4yP:hover (mutedHoverClass) a los
   eventos que dibuja como punto en vez de bloque solido, y esa regla pinta
   --fc-classic-muted, que en este :root es --carbon-08. Con especificidad (0,2,0)
   le gana a .evento-ocupado (0,1,0), asi que al pasar el puntero el fondo se
   iba a un velo casi transparente mientras el texto seguia blanco: blanco sobre
   casi blanco. Solo se ve cuando la celda es estrecha, que es cuando FullCalendar
   cambia a la forma de punto. Estas reglas empatan en especificidad y esta hoja
   carga despues del tema, asi que ganan por orden.

   El color NO se intensifica al pasar el puntero: aqui solo hay un color y
   moverlo insinuaria una diferencia que no existe. La pista de que el bloque se
   puede abrir es el levantamiento y la sombra, no el tono. */
.evento-ocupado:hover {
  transform: translateY(-1px);
  box-shadow: var(--sombra-panel);
  background-color: var(--azul-lavalle);
}

/* Un solo bloque y un solo color para toda la vista publica: azul de la casa,
   texto blanco. El evento, su montaje y su desmontaje se pintan igual porque
   dicen lo mismo, que la casa esta tomada. Confirmado, apartado y las horas de
   trabajo eran tres tonos que contestaban una pregunta que aqui no se hace: el
   bronce y el gris piedra se quedan en el admin, que es donde esa diferencia
   cambia una decision. */
.evento-ocupado {
  --fc-event-color: var(--azul-lavalle) !important;
  --fc-event-contrast-color: var(--blanco) !important;
  background-color: var(--azul-lavalle);
  border: none;
  color: var(--blanco);
}

/* El envoltorio unico del contenido del bloque. Lo pinta contenidoEvento() y
   existe para que el texto no se reparta en columnas de la caja flexible en la
   que FullCalendar lo mete. */
.evento-cuerpo {
  display: block;
  min-width: 0;
  /* En una columna de 50 px una palabra larga no cabe en ningun punto de corte
     y el navegador la deja salirse de la celda: en el telefono los bloques del
     sabado se montaban sobre el canto de la tarjeta. 'anywhere' parte la
     palabra donde haga falta, que es feo pero cabe. */
  overflow-wrap: anywhere;
}

/* ---------- Leyenda ---------- */

/* Una sola entrada, porque un solo estado. Sigue existiendo por el telefono:
   ahi el bloque es una barra de 6 px sin texto, y sin la leyenda nada dice que
   esa raya azul quiere decir ocupado.
   La leyenda se hunde sobre marfil dentro de la tarjeta blanca: es referencia,
   no contenido, y el tercer plano de profundidad lo dice sin escribirlo. */
.leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e3) var(--e6);
  margin: var(--e6) calc(var(--e6) * -1) calc(var(--e6) * -1);
  padding: var(--e3) var(--e6);
  border-top: 1px solid var(--linea);
  border-radius: 0 0 var(--radio) var(--radio);
  background: var(--marfil);
  font-size: 12px;
  color: var(--carbon-70);
}

.leyenda > li {
  display: flex;
  align-items: center;
  gap: var(--e2);
  list-style: none;
}

.leyenda-muestra {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: var(--radio-int);
  flex: none;
}

.leyenda-ocupado { background: var(--azul-lavalle); }

/* ---------- Esqueleto de carga ---------- */

/* Entre la peticion y el primer pintado no habia nada: la tarjeta quedaba en
   blanco y la pagina parecia rota. Un spinner tampoco sirve, no dice que viene.
   La silueta de la reticula si: el ojo ya sabe donde van a caer los dias. */
.esqueleto[hidden] { display: none; }

.esqueleto-barra {
  height: 34px;
  width: 220px;
  margin: 0 auto var(--e4);
  border-radius: var(--radio);
}

.esqueleto-reticula {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  padding: 1px;
  background: var(--linea);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
}

.esqueleto-celda { height: 92px; }

.esqueleto-barra,
.esqueleto-celda {
  background-color: var(--blanco);
  background-image: linear-gradient(
    100deg,
    var(--blanco) 20%,
    var(--marfil) 42%,
    var(--linea-60) 50%,
    var(--marfil) 58%,
    var(--blanco) 80%
  );
  background-size: 300% 100%;
  animation: esqueleto-brillo 1600ms linear infinite;
}

/* Se anima la posicion del fondo, no una propiedad de maquetacion. */
@keyframes esqueleto-brillo {
  from { background-position: 150% 0; }
  to   { background-position: -150% 0; }
}

/* ---------- Lista del mes sin JavaScript ---------- */

/* El calendario si requiere JavaScript. Sin el, PHP pinta la lista del mes en
   curso: un mensaje y una tabla, no una pantalla en blanco. */
.lista-mes {
  width: 100%;
  border-collapse: collapse;
  margin-top: var(--e3);
}

.lista-mes th, .lista-mes td {
  padding: var(--e2) var(--e3);
  text-align: left;
  border-bottom: 1px solid var(--linea);
}

.lista-mes th {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--carbon-70);
  background: var(--marfil);
}

.lista-mes tbody tr:last-child td { border-bottom: none; }

/* ---------- Avisos, vacio y error ---------- */

/* Sin franja lateral de color. Ese borde de 3px es el detalle que hace que un
   aviso se lea como plantilla: el estado se dice con el borde completo, el
   fondo tenido y la palabra escrita. */
.aviso {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--e2) var(--e3);
  padding: var(--e3) var(--e4);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  background: var(--blanco);
}

.aviso-error {
  color: var(--carbon);
  border-color: var(--rojo-30);
  background: var(--rojo-08);
}

/* El vacio no es un error y no debe verse como uno. Aqui no hay caja: hay
   espacio, una frase que dice que significa, y otra que dice que sigue. */
.aviso-vacio {
  display: block;
  padding: var(--e6) var(--e4);
  border: none;
  background: none;
  text-align: center;
}

.vacio-titulo {
  margin: 0;
  font: 300 22px/1.3 var(--fuente-editorial);
  color: var(--carbon);
}

.vacio-cuerpo {
  margin: var(--e2) auto 0;
  max-width: 46ch;
  color: var(--carbon-70);
}

/* ---------- Botones ----------
 *
 * La vista publica tiene dos botones (reintentar y cerrar el detalle) y no
 * tenia regla .boton: salian con el estilo de fabrica del navegador dentro de
 * una pagina que no se parece en nada a eso. */

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--e2);
  min-height: 36px;
  padding: var(--e2) var(--e4);
  font: 500 14px/1 var(--fuente-ui);
  color: var(--carbon);
  background: var(--blanco);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-canto);
  cursor: pointer;
  transition: border-color var(--transicion), background-color var(--transicion),
              box-shadow var(--transicion), transform var(--transicion);
}

.boton:hover {
  border-color: var(--bronce-anzures);
  background: var(--bronce-08);
  box-shadow: var(--sombra-alzada);
  transform: translateY(-1px);
}

/* El boton se hunde al presionar. Un boton que no se mueve bajo el dedo se
   siente roto en tactil, que es donde se usa esta vista. */
.boton:active {
  transform: translateY(1px);
  box-shadow: none;
}

.boton:focus-visible { box-shadow: var(--anillo-foco); }

.boton-mini {
  min-height: 28px;
  padding: var(--e1) var(--e3);
  font-size: 12px;
}

.boton-en-aviso { margin-left: auto; }

/* ---------- Utilidades de maquetacion ----------
 *
 * Igual que en el admin: nada de style="..." en el marcado, para que la
 * politica de contenido del .htaccess no tenga que abrir 'unsafe-inline'. */

.aviso-bloque { margin-bottom: var(--e4); }

.aviso-nota {
  display: block;
  margin-top: var(--e4);
  background: var(--marfil);
}

.nota-titulo {
  margin: 0 0 var(--e2);
  font-weight: 500;
}

.nota-cuerpo { margin: 0 0 var(--e3); }
.nota-vacia { margin: 0; }

.celda-nowrap { white-space: nowrap; }

/* ---------- Detalle del evento ---------- */

.modal {
  padding: 0;
  max-width: 440px;
  width: calc(100% - var(--e8));
  background: var(--blanco);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-elevada);
}

.modal::backdrop { background: var(--carbon-50); }

/* El detalle entra con el mismo gesto con el que sale el panel del admin.
   Esto no es adorno: dice de donde vino la tarjeta y a que bloque pertenece. */
.modal[open] { animation: modal-entra var(--transicion-media) var(--curva); }
.modal[open]::backdrop { animation: fundido var(--transicion-media) var(--curva); }

@keyframes modal-entra {
  from { opacity: 0; transform: translateY(8px) scale(.985); }
}

@keyframes fundido {
  from { opacity: 0; }
}

.modal-cabecera {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--e3);
  padding: var(--e4);
  border-bottom: 1px solid var(--linea);
}

.modal-titulo {
  margin: 0;
  font: 300 22px/1.25 var(--fuente-editorial);
  letter-spacing: -0.01em;
}

.modal-cuerpo { padding: var(--e4); }

.modal-campo {
  padding-bottom: var(--e3);
  margin-bottom: var(--e3);
  border-bottom: 1px solid var(--linea-60);
}

.modal-campo:last-child {
  padding-bottom: 0;
  margin-bottom: 0;
  border-bottom: none;
}

.modal-etiqueta {
  display: block;
  margin-bottom: var(--e1);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--carbon-70);
}

.modal-valor { font-weight: 500; }

/* Un dia puede traer un evento o cinco. Cada uno es su propia tarjeta con su
   titulo, y no una lista de campos corridos: con dos eventos seguidos sin nada
   que los separe no se sabe donde acaba el horario de uno y empieza el del
   otro. */
.detalle-evento + .detalle-evento {
  margin-top: var(--e4);
  padding-top: var(--e4);
  border-top: 1px solid var(--linea);
}

.detalle-titulo {
  margin: 0 0 var(--e3);
  font: 500 16px/1.3 var(--fuente-ui);
  letter-spacing: -0.01em;
}

/* ---------- Movil ---------- */

/* Esta vista se abre casi siempre desde un celular, asi que el bloque movil no
   es un remiendo del de escritorio: es el caso normal. Lo que cambia no es solo
   el tamano, es la jerarquia. La cabecera se comprime, la tarjeta deja de subir
   sobre la banda (con 12 px de aire a cada lado, el gesto no se lee) y la
   reticula recupera el ancho completo. */
@media (max-width: 800px) {
  h1 { font-size: 26px; }

  .encabezado-interior { padding: var(--e6) var(--e3) var(--e8); }
  .encabezado-marca { margin-bottom: var(--e4); }
  .encabezado-nota { font-size: 15px; }

  .envoltura { padding: 0 var(--e3) var(--e12); }

  .tarjeta {
    margin-top: var(--e4);
    padding: var(--e3);
  }

  .leyenda {
    margin: var(--e3) calc(var(--e3) * -1) calc(var(--e3) * -1);
    padding: var(--e3);
    gap: var(--e2) var(--e4);
  }

  .esqueleto-celda { height: 56px; }

  .aviso-vacio { padding: var(--e4) var(--e3); }

  /* El detalle en pantalla chica sube desde abajo y ocupa el ancho completo:
     un dialogo centrado de 440 px en un telefono deja franjas a los lados y se
     lee como una ventana de escritorio encogida. */
  .modal {
    width: 100%;
    max-width: none;
    margin: auto 0 0;
    border-radius: var(--radio) var(--radio) 0 0;
    border-bottom: none;
  }

  @keyframes modal-entra {
    from { opacity: 0; transform: translateY(24px); }
  }

  /* --- El mes en un telefono ---
     Aqui es donde la vista deja de ser la de escritorio encogida. El bloque de
     evento pierde el texto y se queda en una barra de 6 px del color de su
     estado. En una columna de 48 px ningun titulo cabe: se partia letra por
     letra y llenaba la celda de tiras verticales ilegibles.

     Barra y no punto porque la barra conserva el tramo. Una boda de viernes a
     sabado se ve cruzando las dos celdas, y esa es justo la informacion que
     alguien viene a buscar: no cuantos eventos hay, sino desde cuando y hasta
     cuando esta tomada la casa. El punto por dia la pierde.

     El texto no se pierde, cambia de sitio: toca el dia y el dialogo dice el
     horario, los espacios, el montaje y el desmontaje. Y el objetivo de ese
     toque es la celda de 60 px, no la barra de 6: publico.js abre el mismo dia
     desde eventClick y desde dateClick, asi que da igual donde caiga el dedo
     dentro del dia. */
  .evento-ocupado {
    height: 6px;
    min-height: 0;
    padding: 0;
    margin-bottom: 2px;
    border-radius: var(--radio-pastilla);
    overflow: hidden;
  }

  .evento-cuerpo { display: none; }

  /* El levantamiento al pasar el puntero no existe en tactil, y sobre una barra
     de 6 px la sombra se ve como un borrón. */
  .evento-ocupado:hover {
    transform: none;
    box-shadow: none;
  }

  /* 44x44 minimo en tactil. Los bloques del calendario quedan fuera a
     proposito: son barras de 6 px y quien recibe el toque es la celda. */
  .boton, button { min-height: 44px; }
}

/* ---------- Transicion de vista y de fechas ---------- */

/* Se anima el CUERPO de la vista, nunca el contenedor entero. La barra de
   botones y el titulo del mes tienen que quedarse quietos: si se mueven, el
   boton que se acaba de pulsar se va de debajo del cursor, y el siguiente clic
   cae en otro sitio.

   FullCalendar 7 hashea sus clases estructurales (.fc-ei, .fc-vB), asi que no
   hay selector estable para ese cuerpo. El enganche lo da viewDidMount, que
   entrega el elemento raiz de la vista; el guion le pone la clase. Mismo
   razonamiento que el className de los eventos: en la 7 se pide el asa, no se
   adivina el nombre.

   Cambiar de vista y cambiar de mes no son el mismo gesto y no se animan igual.
   Cambiar de vista sustituye la reticula entera: entra de abajo, 280ms, que es
   lo que tarda en leerse una forma nueva. Navegar conserva la forma y solo mueve
   el tiempo: entra de un lado, 200ms, y el lado dice hacia donde se fue. Sin esa
   direccion las dos serian la misma animacion contando cosas distintas. */

@keyframes vista-entra {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

@keyframes vista-avanza {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes vista-retrocede {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: none; }
}

.vista-entra     { animation: vista-entra     280ms var(--curva) both; }
.vista-avanza    { animation: vista-avanza    200ms var(--curva) both; }
.vista-retrocede { animation: vista-retrocede 200ms var(--curva) both; }

/* Los 14px de desplazamiento asoman por el borde mientras dura la animacion y
   el navegador contesta con una barra de scroll horizontal que aparece y
   desaparece. 'clip' recorta sin crear contenedor desplazable, y la clase solo
   vive los 200ms: fuera de ellos el popover de "+N mas" vuelve a poder salirse
   del contenedor. */
.calendario-animando { overflow-x: clip; }

/* ---------- Movimiento ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }

  /* El esqueleto pierde el brillo pero no la silueta: sigue diciendo que algo
     esta por llegar, sin nada moviendose. */
  .esqueleto-barra,
  .esqueleto-celda {
    background-image: none;
    background-color: var(--marfil);
  }

  .evento-ocupado:hover,
  .boton:hover,
  .boton:active {
    transform: none;
  }

  /* El dialogo aparece sin deslizarse. Sigue apareciendo: es el contenido que
     se pidio, no un adorno, y quitarlo dejaria la vista sin detalle. */
  .modal[open],
  .modal[open]::backdrop {
    animation: none !important;
  }

  /* La transicion de vista se apaga entera, no se acelera. Acelerada seguiria
     siendo un parpadeo de opacidad, y un parpadeo es justo lo que esta consulta
     pide no ver. La reticula nueva aparece ya puesta. */
  .vista-entra,
  .vista-avanza,
  .vista-retrocede {
    animation: none !important;
  }
}
