/* ============================================================================
   app.css — Sistema de diseño del panel.

   MOBILE FIRST, y no por moda: el profesional abre esto desde el teléfono,
   de pie, entre cliente y cliente. El escritorio es el caso raro.

   Puntos de corte (los del esquema clásico de dispositivos):
     base     320px+   teléfonos en vertical
     480px+   teléfonos grandes / vertical ancho y horizontal pequeño
     768px+   tablets en vertical
     1024px+  netbooks y tablets en horizontal
     1280px+  escritorio

   ── EL TEMA ─────────────────────────────────────────────────────────────────
   Tres estados, no dos: claro, oscuro y AUTOMÁTICO (el del sistema), que es el
   de fábrica. Quien nunca toca el interruptor obtiene lo que ya eligió en su
   teléfono, que casi siempre es lo que quiere.

   Se implementa con un atributo en <html>:
     sin atributo        → manda el sistema
     data-tema="claro"   → claro a la fuerza
     data-tema="oscuro"  → oscuro a la fuerza

   El atributo lo pone un script diminuto en el <head>, ANTES de que se pinte
   nada. Si se hiciera al final, en cada carga se vería el tema claro un
   instante antes de saltar al oscuro.
   ============================================================================ */


/* ── Tokens ────────────────────────────────────────────────────────────────── */

/* Cada color se define UNA SOLA VEZ con light-dark(): primero el valor claro,
   después el oscuro. Quién manda lo decide `color-scheme`, y eso es lo único
   que toca el interruptor.

   La alternativa —repetir la paleta entera dentro de una media query y otra vez
   bajo [data-tema="oscuro"]— ya se probó aquí y falló exactamente como falla
   siempre: al añadir un token se actualizó una copia y no la otra, y el tema
   oscuro se quedó heredando un valor del claro. Con una definición no se puede
   cometer ese error.

   Cada línea lleva dos declaraciones: primero el color plano y luego la versión
   light-dark(). Un navegador que no entienda light-dark() descarta la segunda y
   se queda con el tema claro, que es una degradación digna; uno moderno aplica
   la segunda y gana los dos temas. Van pegadas en la misma línea a propósito:
   así es imposible tocar una y olvidar la otra. */

:root {
  /* «light dark» = automático, manda el sistema. Es el estado de fábrica. */
  color-scheme: light dark;

  --bg:        #f2f5f9;  --bg:        light-dark(#f2f5f9, #0e1319);
  --bg-alt:    #e9eef5;  --bg-alt:    light-dark(#e9eef5, #161d26);  /* campos, franjas */
  --card:      #ffffff;  --card:      light-dark(#ffffff, #171e27);
  --tx:        #131c2b;  --tx:        light-dark(#131c2b, #e8eef5);
  --tx-2:      #3d4b5c;  --tx-2:      light-dark(#3d4b5c, #c2ccd8);  /* aún legible */
  --mut:       #6b7a8d;  --mut:       light-dark(#6b7a8d, #8d9bab);
  --br:        #e3e9f0;  --br:        light-dark(#e3e9f0, #252e3a);
  --br-fuerte: #cfd8e3;  --br-fuerte: light-dark(#cfd8e3, #35414f);

  --pri:       #0d9488;  --pri:       light-dark(#0d9488, #2dd4bf);
  --pri-alt:   #0f766e;  --pri-alt:   light-dark(#0f766e, #5eead4);  /* hover / pulsado */
  --pri-tx:    #ffffff;  --pri-tx:    light-dark(#ffffff, #04251f);
  --pri-suave: #d7f3ef;  --pri-suave: light-dark(#d7f3ef, #0d3330);  /* fondo teñido */

  --ok:         #15803d;  --ok:         light-dark(#15803d, #4ade80);
  --ok-suave:   #dcfce7;  --ok-suave:   light-dark(#dcfce7, #10301d);
  --err:        #be123c;  --err:        light-dark(#be123c, #fb7185);
  --err-suave:  #ffe4e6;  --err-suave:  light-dark(#ffe4e6, #3a1620);
  --warn:       #b45309;  --warn:       light-dark(#b45309, #fbbf24);
  --warn-suave: #fef3c7;  --warn-suave: light-dark(#fef3c7, #3a2c0d);

  /* La barra lateral SIGUE AL TEMA. Se probó dejarla siempre oscura —es el look
     de las herramientas de agenda al uso— pero quien pide «modo claro» está
     pidiendo que la pantalla entera sea clara, y una franja negra fija se lee
     como un fallo, no como una decisión de diseño. */
  --side-bg:     #ffffff;  --side-bg:     light-dark(#ffffff, #0b1017);
  --side-tx:     #556274;  --side-tx:     light-dark(#556274, #8d9bab);
  --side-tx-on:  #131c2b;  --side-tx-on:  light-dark(#131c2b, #ffffff);
  --side-br:     #e3e9f0;  --side-br:     light-dark(#e3e9f0, rgb(255 255 255 / 0.07));
  --side-hover:  #f1f4f9;  --side-hover:  light-dark(#f1f4f9, rgb(255 255 255 / 0.05));
  --side-act:    #d7f3ef;  --side-act:    light-dark(#d7f3ef, rgb(45 212 191 / 0.14));
  --side-act-tx: #0f766e;  --side-act-tx: light-dark(#0f766e, #5eead4);
  --side-pill:   #ffffff;  --side-pill:   light-dark(#ffffff, rgb(255 255 255 / 0.13));

  /* Calendario. El rojo marca "aquí hay trabajo", el verde "día libre".
     Invertido respecto a la convención habitual, y es intencional. */
  --dia-ocupado:    #fee2e2;  --dia-ocupado:    light-dark(#fee2e2, #3b1f20);
  --dia-ocupado-br: #fca5a5;  --dia-ocupado-br: light-dark(#fca5a5, #7f3d3d);
  --dia-ocupado-tx: #991b1b;  --dia-ocupado-tx: light-dark(#991b1b, #fca5a5);
  --dia-libre:      #dcfce7;  --dia-libre:      light-dark(#dcfce7, #12301f);
  --dia-libre-br:   #86efac;  --dia-libre-br:   light-dark(#86efac, #2f6b45);
  --dia-libre-tx:   #14532d;  --dia-libre-tx:   light-dark(#14532d, #86efac);

  /* Sombras en vez de bordes. Un borde de 1px hace que todo parezca una hoja de
     cálculo; la sombra da profundidad sin añadir líneas. En oscuro tienen que
     ser mucho más densas: sobre fondo negro una sombra suave no se ve. */
  --sh-1: 0 1px 2px rgb(16 24 40 / 0.04), 0 1px 3px rgb(16 24 40 / 0.06);
  --sh-1: 0 1px 2px light-dark(rgb(16 24 40 / 0.04), rgb(0 0 0 / 0.22)),
          0 1px 3px light-dark(rgb(16 24 40 / 0.06), rgb(0 0 0 / 0.28));
  --sh-2: 0 4px 12px rgb(16 24 40 / 0.07), 0 2px 4px rgb(16 24 40 / 0.04);
  --sh-2: 0 4px 12px light-dark(rgb(16 24 40 / 0.07), rgb(0 0 0 / 0.34)),
          0 2px 4px  light-dark(rgb(16 24 40 / 0.04), rgb(0 0 0 / 0.22));
  --sh-3: 0 14px 38px rgb(16 24 40 / 0.16), 0 4px 10px rgb(16 24 40 / 0.06);
  --sh-3: 0 14px 38px light-dark(rgb(16 24 40 / 0.16), rgb(0 0 0 / 0.5)),
          0 4px 10px  light-dark(rgb(16 24 40 / 0.06), rgb(0 0 0 / 0.3));

  --r:      14px;          /* radio estándar */
  --r-sm:   10px;
  --r-pill: 999px;
  --tap:    44px;          /* objetivo táctil mínimo */
  --gap:    0.85rem;
  --side-w: 256px;
}

/* Lo ÚNICO que hace el interruptor: fijar el esquema. Todos los light-dark()
   de arriba se recalculan solos, sin repetir un solo color. */
:root[data-tema="claro"]  { color-scheme: light; }
:root[data-tema="oscuro"] { color-scheme: dark; }


/* ── Base ──────────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }   /* iOS no reescala al girar */

body {
  margin: 0;
  background: var(--bg);
  color: var(--tx);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  letter-spacing: -0.005em;
  /* Quita el retardo de 300ms al tocar y el destello gris de Android. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; }

h1, h2, h3 { letter-spacing: -0.02em; }

/* Sin esto los enlaces usan el azul/morado por defecto del navegador, que
   sobre fondo oscuro es prácticamente ilegible. Los enlaces con estilo propio
   (menú, botones, casillas del calendario) ganan por especificidad. */
a { color: var(--pri); text-decoration: none; }
a:hover { text-decoration: underline; }

::selection { background: var(--pri-suave); color: var(--tx); }

:focus-visible { outline: 2px solid var(--pri); outline-offset: 2px; border-radius: 4px; }


/* ── Carcasa ───────────────────────────────────────────────────────────────── */

.app { display: flex; min-height: 100dvh; }
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.wrap {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  /* Respeta la muesca y la barra de gestos del iPhone. */
  padding: 1rem max(0.9rem, env(safe-area-inset-left)) calc(2rem + env(safe-area-inset-bottom));
}
@media (min-width: 768px) { .wrap { padding: 1.4rem 1.6rem 3rem; } }


/* ── Barra lateral ─────────────────────────────────────────────────────────── */

/* En pantalla ancha está abierta y se puede plegar; en teléfono está plegada y
   se abre por encima del contenido con un fondo oscuro detrás, para que quede
   claro que hay que cerrarla. Al caber todas las entradas agrupadas, nada
   queda escondido detrás de un «Más». */

.side {
  position: fixed;
  z-index: 60;
  top: 0; bottom: 0; left: 0;
  width: var(--side-w);
  display: flex;
  flex-direction: column;
  background: var(--side-bg);
  color: var(--side-tx);
  /* Imprescindible en tema claro: sin la línea, la barra blanca y el contenido
     blanco se funden en una sola mancha. */
  border-right: 1px solid var(--side-br);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(-100%);
  transition: transform 0.22s cubic-bezier(0.32, 0.72, 0, 1);
  padding-bottom: env(safe-area-inset-bottom);
  scrollbar-width: thin;
}
body.menu-abierto .side { transform: none; }

.side-marca {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1.05rem 1.15rem;
  font-weight: 800;
  font-size: 1.02rem;
  color: var(--side-tx-on);
  border-bottom: 1px solid var(--side-br);
}
.side-marca .logo {
  width: 30px; height: 30px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 9px;
  background: linear-gradient(140deg, var(--pri), var(--pri-alt));
  font-size: 0.95rem;
}

.side-grupo {
  padding: 1.05rem 1.2rem 0.35rem;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--side-tx);
  opacity: 0.55;
}

.side nav { padding: 0 0.6rem; }
.side nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: var(--tap);
  padding: 0.5rem 0.7rem;
  margin-bottom: 2px;
  border-radius: var(--r-sm);
  color: var(--side-tx);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 500;
  transition: background 0.14s, color 0.14s;
}
.side nav a i { font-style: normal; font-size: 1.05rem; width: 1.35rem; text-align: center; flex: none; }
.side nav a:hover { background: var(--side-hover); color: var(--side-tx-on); text-decoration: none; }

.side nav a.on {
  background: var(--side-act);
  color: var(--side-act-tx);
  font-weight: 700;
}
/* Barrita a la izquierda: el color solo no basta para señalar "estás aquí" a
   quien no distingue bien los tonos. */
.side nav a.on::before {
  content: "";
  position: absolute;
  left: -0.6rem; top: 50%;
  transform: translateY(-50%);
  width: 3px; height: 1.35rem;
  border-radius: 0 3px 3px 0;
  background: var(--side-act-tx);
}

/* Contador de cosas pendientes pegado a la entrada del menú. Sin esto el
   administrador tiene que entrar a mirar para saber si hay algo esperando. */
.side nav a .badge {
  margin-left: auto;
  min-width: 1.35rem;
  padding: 0.05rem 0.4rem;
  border-radius: var(--r-pill);
  background: var(--err);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 800;
  text-align: center;
  line-height: 1.5;
}

.side-pie {
  margin-top: auto;
  padding: 0.9rem 1.15rem calc(1rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--side-br);
  font-size: 0.82rem;
}
.side-pie b { display: block; color: var(--side-tx-on); font-weight: 700; }
.side-pie .mut { color: var(--side-tx); opacity: 0.8; font-size: 0.8rem; }
.side-pie a.salir { color: var(--err); font-weight: 600; }

/* Fondo oscuro tras la barra abierta en teléfono. */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgb(4 8 14 / 0.55);
  backdrop-filter: blur(2px);
  display: none;
}
body.menu-abierto .backdrop { display: block; }


/* ── Interruptor de tema ───────────────────────────────────────────────────── */

/* Tres posiciones: automático, claro, oscuro. Se ve el estado actual, no hay
   que pulsar para descubrirlo — que es lo que pasa con los que solo alternan. */

/* Se usa en dos sitios con fondos opuestos: el pie de la barra lateral, que es
   oscuro en los dos temas, y las pantallas sin barra —entrar, recuperar—, que
   siguen el tema de la página. De ahí las dos paletas. */

.tema {
  display: flex;
  gap: 2px;
  margin: 0 0 0.85rem;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--bg-alt);
  border: 1px solid var(--br);
}
.tema button {
  flex: 1;
  width: auto;
  min-height: 30px;
  padding: 0.25rem 0;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--mut);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: none;
  transition: background 0.15s, color 0.15s;
}
.tema button:hover { color: var(--tx); background: transparent; filter: none; box-shadow: none; }
.tema button.on {
  background: var(--card);
  color: var(--tx);
  box-shadow: var(--sh-1);
}

.side .tema { background: var(--side-hover); border-color: var(--side-br); }
.side .tema button { color: var(--side-tx); }
.side .tema button:hover { color: var(--side-tx-on); }
.side .tema button.on { background: var(--side-pill); color: var(--side-tx-on); }


/* ── Cabecera superior ─────────────────────────────────────────────────────── */

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.9rem;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--br);
}
.topbar .burger {
  width: auto;
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0.4rem 0.7rem;
  background: var(--card);
  color: var(--tx);
  border: 1px solid var(--br);
  border-radius: var(--r-sm);
  box-shadow: var(--sh-1);
  font-size: 1.05rem;
}
.topbar .burger:hover { background: var(--bg-alt); }
.topbar .titulo { font-weight: 700; letter-spacing: -0.015em; }

@media (min-width: 1024px) {
  /* Abierta por defecto y empujando el contenido, no encima de él. */
  .side { position: sticky; height: 100dvh; transform: none; }
  body.menu-cerrado .side { display: none; }
  .backdrop { display: none !important; }
  .topbar {
    background: transparent;
    backdrop-filter: none;
    border-bottom: 0;
    padding: 1rem 1.6rem 0;
  }
  .topbar .titulo { display: none; }   /* ya está en el <h1> de la sección */
}


/* ── Cabecera de página ────────────────────────────────────────────────────── */

.top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.2rem;
  flex-wrap: wrap;
}
.top h1 { font-size: 1.4rem; margin: 0; line-height: 1.2; }
.top p  { margin: 0.2rem 0 0; }
@media (min-width: 768px) { .top h1 { font-size: 1.6rem; } }


/* ── Tarjetas ──────────────────────────────────────────────────────────────── */

.card {
  background: var(--card);
  border: 1px solid var(--br);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
  padding: 1.05rem;
  margin-bottom: var(--gap);
}
@media (min-width: 768px) { .card { padding: 1.3rem 1.5rem; } }

.card h2 {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 0.9rem;
}
.card > h2:first-child + .mut { margin-top: -0.55rem; }

/* Tarjeta en la que se puede pinchar. */
.card-link { display: block; color: inherit; transition: box-shadow 0.15s, transform 0.15s; }
.card-link:hover { box-shadow: var(--sh-2); transform: translateY(-1px); text-decoration: none; }


/* ── Formularios ───────────────────────────────────────────────────────────── */

label {
  display: block;
  font-size: 0.85rem;
  font-weight: 650;
  color: var(--tx-2);
  margin: 0.85rem 0 0.3rem;
}

input, select, textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 0.62rem 0.8rem;
  border: 1px solid var(--br-fuerte);
  border-radius: var(--r-sm);
  background: var(--bg-alt);
  color: var(--tx);
  font-family: inherit;
  /* 16px EXACTOS: por debajo de eso, Safari en iOS hace zoom al enfocar el
     campo y descoloca toda la pantalla. Es la causa número uno de que un
     formulario "responsive" se sienta roto en iPhone. */
  font-size: 16px;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
input::placeholder, textarea::placeholder { color: var(--mut); }
textarea { min-height: 5.5rem; resize: vertical; line-height: 1.55; }

input:focus, select:focus, textarea:focus {
  outline: none;
  background: var(--card);
  border-color: var(--pri);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pri) 22%, transparent);
}
input:disabled, select:disabled, textarea:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
input[type="file"] {
  padding: 0.5rem;
  background: var(--bg-alt);
  border-style: dashed;
  font-size: 0.85rem;
  cursor: pointer;
}
input[type="checkbox"], input[type="radio"] {
  accent-color: var(--pri);
  min-height: auto;
}

/* Filas que se apilan en móvil y se reparten en pantallas anchas.
   El apilado es el estado por defecto, no la excepción. */
.row { display: flex; flex-direction: column; gap: 0 var(--gap); }
@media (min-width: 480px) {
  .row { flex-direction: row; }
  .row > * { flex: 1; min-width: 0; }   /* min-width:0 evita desbordes */
}


/* ── Botones ───────────────────────────────────────────────────────────────── */

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  width: 100%;
  min-height: var(--tap);
  padding: 0.7rem 1.15rem;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--pri);
  color: var(--pri-tx);
  font: inherit;
  font-size: 0.94rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--sh-1);
  transition: filter 0.15s, box-shadow 0.15s, transform 0.08s, background 0.15s;
}
button:hover, .btn:hover { filter: brightness(1.07); box-shadow: var(--sh-2); text-decoration: none; }
button:active, .btn:active { transform: translateY(1px); box-shadow: var(--sh-1); }
button:disabled { opacity: 0.45; cursor: not-allowed; filter: none; transform: none; }

.btn-sec {
  background: var(--card);
  color: var(--tx);
  border-color: var(--br-fuerte);
}
.btn-sec:hover { background: var(--bg-alt); filter: none; }

.btn-peligro { background: var(--err); color: #fff; }
.btn-plano   { background: transparent; color: var(--tx-2); border-color: transparent; box-shadow: none; }
.btn-plano:hover { background: var(--bg-alt); filter: none; box-shadow: none; }

@media (min-width: 480px) { button, .btn { width: auto; } }

/* Fila de botones al cierre de un formulario. El principal primero: en
   teléfono se apilan y el pulgar llega antes al de arriba. */
.acciones {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1.4rem;
}
@media (min-width: 480px) {
  .acciones { flex-direction: row; flex-wrap: wrap; }
  .acciones > * { width: auto; }
}

/* El botón que cierra un formulario necesita aire: pegado al último campo
   parece parte de él y se pulsa sin querer.
   Se aplica solo cuando el botón viene DESPUÉS de un campo o un bloque, nunca
   dentro de una fila de botones — de ahí el :not([type=hidden]): los campos
   ocultos del CSRF preceden a casi todos los botones de acción en línea, y sin
   esa exclusión se descolgarían de su fila. */
input:not([type="hidden"]) + button,
select   + button,
textarea + button,
label    + button,
p        + button,
.row     + button,
.card    + button {
  margin-top: 1.4rem;
}


/* ── Fichas de filtro ──────────────────────────────────────────────────────── */

/* Las filas de "Por revisar / Rechazados / Aprobados" no son botones de acción:
   son un selector. Como botones llenos parecen cuatro cosas que ejecutar. */

.chips { display: flex; gap: 0.4rem; flex-wrap: wrap; margin: 0 0 1.1rem; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  width: auto;
  min-height: 36px;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--br-fuerte);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--tx-2);
  font-size: 0.86rem;
  font-weight: 600;
  box-shadow: none;
  cursor: pointer;
  text-decoration: none;
}
.chip:hover { background: var(--bg-alt); text-decoration: none; filter: none; box-shadow: none; }
.chip.on {
  background: var(--pri);
  border-color: var(--pri);
  color: var(--pri-tx);
  font-weight: 700;
}
.chip .n {
  padding: 0 0.35rem;
  border-radius: var(--r-pill);
  background: var(--bg-alt);
  color: var(--tx-2);
  font-size: 0.74rem;
  font-weight: 800;
}
.chip.on .n { background: rgb(255 255 255 / 0.25); color: inherit; }


/* ── Calendario del mes ────────────────────────────────────────────────────── */

.cal {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
@media (min-width: 480px) { .cal { gap: 7px; } }

.cal-dow {
  text-align: center;
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--mut);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding-bottom: 0.4rem;
}

.cal-dia {
  aspect-ratio: 1;              /* cuadrado siempre, sin importar el ancho */
  min-height: 40px;             /* a 320px caben 7 columnas de ~41px */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: 1px solid var(--br);
  border-radius: var(--r-sm);
  background: var(--card);
  color: var(--tx);
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.1s, box-shadow 0.15s;
}
.cal-dia:hover { transform: translateY(-1px); box-shadow: var(--sh-2); text-decoration: none; }
.cal-dia.libre   { background: var(--dia-libre);   border-color: var(--dia-libre-br);   color: var(--dia-libre-tx); }
.cal-dia.ocupado { background: var(--dia-ocupado); border-color: var(--dia-ocupado-br); color: var(--dia-ocupado-tx); }
.cal-dia.fuera   { opacity: 0.3; pointer-events: none; box-shadow: none; }
.cal-dia.hoy {
  outline: 2px solid var(--pri);
  outline-offset: -2px;
  font-weight: 800;
}

/* El número de citas NO es decoración: rojo y verde son el par más común de
   daltonismo, así que el color nunca puede ser la única señal. */
.cal-n {
  font-size: 0.64rem;
  font-weight: 800;
  line-height: 1;
  opacity: 0.85;
}

/* En teléfono el cuadrado perfecto funciona: la casilla ocupa lo que da el
   ancho y se lee de un vistazo. En escritorio ese mismo aspect-ratio la
   convierte en un bloque de 110px de alto para mostrar dos cifras. Aquí se
   suelta la proporción y se acota el ancho: el calendario es un resumen, el
   detalle está al entrar en el día. */
@media (min-width: 768px) {
  .cal      { max-width: 560px; }
  .cal-dia  { aspect-ratio: auto; min-height: 56px; font-size: 0.98rem; }
  .cal-n    { font-size: 0.7rem; }
}

/* Leyenda del par rojo/verde. Va siempre visible: la convención está invertida
   a propósito y sin explicarla nadie la adivina. */
.cal-leyenda { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 0.9rem; font-size: 0.8rem; color: var(--mut); }
.cal-leyenda span { display: inline-flex; align-items: center; gap: 0.4rem; }
.cal-leyenda i { width: 13px; height: 13px; border-radius: 4px; border: 1px solid; flex: none; }
.cal-leyenda .l-libre   { background: var(--dia-libre);   border-color: var(--dia-libre-br); }
.cal-leyenda .l-ocupado { background: var(--dia-ocupado); border-color: var(--dia-ocupado-br); }


/* ── Citas del día ─────────────────────────────────────────────────────────── */

/* Cada cita como una franja con la hora a la izquierda y una barra de color:
   se recorre la columna de horas con la vista sin leer nada más. */

.cita {
  display: flex;
  gap: 0.85rem;
  align-items: stretch;
  padding: 0.75rem 0.9rem;
  margin-bottom: 0.55rem;
  background: var(--card);
  border: 1px solid var(--br);
  border-left: 4px solid var(--pri);
  border-radius: var(--r-sm);
  box-shadow: var(--sh-1);
  color: inherit;
  text-decoration: none;
}
.cita:hover { box-shadow: var(--sh-2); text-decoration: none; }
.cita .hora { flex: none; width: 4.6rem; font-weight: 800; font-size: 0.92rem; line-height: 1.35; }
.cita .hora small { display: block; font-weight: 500; color: var(--mut); font-size: 0.76rem; }
.cita .quien { flex: 1; min-width: 0; }
.cita .quien b { display: block; font-size: 0.97rem; }
.cita .quien span { color: var(--mut); font-size: 0.85rem; }

.cita.vino     { border-left-color: var(--ok); }
.cita.no-vino  { border-left-color: var(--err); opacity: 0.72; }
.cita.pendiente{ border-left-color: var(--warn); }


/* ── Tablas → tarjetas en móvil ────────────────────────────────────────────── */

/* Una tabla de reportes con 5 columnas no cabe en 320px. Por debajo de 768px
   cada fila se convierte en una tarjeta y cada celda muestra su etiqueta desde
   data-label. Por encima, es una tabla normal. */

.tabla-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--card);
  border: 1px solid var(--br);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
}
@media (max-width: 767px) {
  .tabla-wrap:has(.tabla-cards) { background: none; border: 0; box-shadow: none; }
}

table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
th, td { padding: 0.7rem 0.85rem; text-align: left; }
th {
  font-size: 0.74rem;
  font-weight: 800;
  color: var(--mut);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--bg-alt);
  white-space: nowrap;
}
tbody tr + tr td { border-top: 1px solid var(--br); }

@media (max-width: 767px) {
  .tabla-cards thead { display: none; }
  .tabla-cards tr {
    display: block;
    background: var(--card);
    border: 1px solid var(--br);
    border-radius: var(--r);
    box-shadow: var(--sh-1);
    padding: 0.7rem 0.9rem;
    margin-bottom: 0.6rem;
  }
  .tabla-cards td {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.3rem 0;
    border: 0 !important;
  }
  .tabla-cards td::before {
    content: attr(data-label);
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--mut);
    flex: none;
  }
}


/* ── Matriz de precios (servicios × variantes) ─────────────────────────────── */

/* Es la pantalla más difícil de todo el panel: en un car wash son 4 lavados por
   4 tipos de vehículo = 16 campos de precio. En escritorio es una cuadrícula
   cómoda; en teléfono una cuadrícula es inusable, así que se convierte en un
   acordeón: un servicio abierto a la vez, con sus variantes en lista. */

.matriz-grid { display: none; }
.matriz-lista { display: block; }
@media (min-width: 1024px) {
  .matriz-grid  { display: block; overflow-x: auto; }
  .matriz-lista { display: none; }
}


/* ── Cifras del resumen ────────────────────────────────────────────────────── */

.cifras { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.7rem; margin-bottom: var(--gap); }
@media (min-width: 900px) { .cifras { grid-template-columns: repeat(4, 1fr); } }

.cifra {
  position: relative;
  background: var(--card);
  border: 1px solid var(--br);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
  padding: 0.95rem 1rem;
  overflow: hidden;
}
/* Filo de color arriba: distingue las cifras del resto de tarjetas sin
   añadirles ruido. */
.cifra::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--pri);
  opacity: 0.85;
}
.cifra b {
  display: block;
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.03em;
}
.cifra span { font-size: 0.79rem; color: var(--mut); font-weight: 600; }
.cifra.ok::before   { background: var(--ok); }
.cifra.warn::before { background: var(--warn); }
.cifra.err::before  { background: var(--err); }


/* ── Dos columnas ──────────────────────────────────────────────────────────── */

/* Apiladas por defecto; lado a lado solo cuando de verdad hay ancho. El corte
   está en 1100px y no en 768 porque la barra lateral ya se come 256px: con
   menos, dos columnas quedarían más estrechas que apiladas. */
.split { display: grid; gap: var(--gap); }
.split > .card { margin-bottom: 0; }

@media (min-width: 1100px) {
  .split {
    grid-template-columns: minmax(0, 580px) minmax(0, 1fr);
    align-items: start;
  }
}


/* ── Avisos ────────────────────────────────────────────────────────────────── */

.msg {
  border: 1px solid;
  border-radius: var(--r-sm);
  padding: 0.85rem 1rem;
  margin-bottom: var(--gap);
  font-size: 0.9rem;
  line-height: 1.5;
}
.msg-ok   { border-color: color-mix(in srgb, var(--ok) 45%, transparent);   background: var(--ok-suave);   color: var(--ok); }
.msg-err  { border-color: color-mix(in srgb, var(--err) 45%, transparent);  background: var(--err-suave);  color: var(--err); }
.msg-warn { border-color: color-mix(in srgb, var(--warn) 45%, transparent); background: var(--warn-suave); color: var(--warn); }
.msg strong { color: inherit; }
.msg ul { margin: 0.4rem 0 0; padding-left: 1.15rem; }
.msg code {
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
  background: color-mix(in srgb, currentColor 14%, transparent);
  font-size: 0.86em;
}


/* ── Etiquetas de estado ───────────────────────────────────────────────────── */

.tag {
  display: inline-block;
  padding: 0.18rem 0.6rem;
  border-radius: var(--r-pill);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  border: 1px solid;
  text-transform: capitalize;
}
.tag-pendiente,
.tag-incompleto { color: var(--warn); border-color: transparent; background: var(--warn-suave); }
.tag-activo,
.tag-aprobado   { color: var(--ok);   border-color: transparent; background: var(--ok-suave); }
.tag-rechazado,
.tag-suspendido { color: var(--err);  border-color: transparent; background: var(--err-suave); }


/* ── Aviso de asistencia ───────────────────────────────────────────────────── */

/* En teléfono va abajo, al alcance del pulgar, como hoja inferior.
   En escritorio, tarjeta flotante en la esquina. Nunca bloquea la pantalla:
   quien lo recibe puede tener las tijeras en la mano. */

.aviso {
  position: fixed;
  z-index: 50;
  left: 0; right: 0; bottom: 0;
  background: var(--card);
  border-top: 1px solid var(--br);
  border-radius: var(--r) var(--r) 0 0;
  padding: 1.05rem 1.05rem calc(1.05rem + env(safe-area-inset-bottom));
  box-shadow: var(--sh-3);
  animation: sube 0.25s cubic-bezier(0.32, 0.72, 0, 1);
}
@keyframes sube { from { transform: translateY(100%); } }

.aviso-acciones { display: flex; gap: 0.6rem; margin-top: 0.9rem; }
.aviso-acciones button { flex: 1; }

@media (min-width: 768px) {
  .aviso {
    left: auto; right: 1.3rem; bottom: 1.3rem;
    width: 370px;
    border: 1px solid var(--br);
    border-radius: var(--r);
  }
  @keyframes sube { from { transform: translateY(12px); opacity: 0; } }
}


/* ── Vacío ─────────────────────────────────────────────────────────────────── */

.vacio { text-align: center; padding: 2.6rem 1rem; color: var(--mut); }
.vacio .ico { font-size: 2.4rem; display: block; margin-bottom: 0.6rem; opacity: 0.8; }


/* ── Desplegables ──────────────────────────────────────────────────────────── */

summary { cursor: pointer; }
summary::-webkit-details-marker { color: var(--mut); }


/* ── Utilidades ────────────────────────────────────────────────────────────── */

.mut  { color: var(--mut); font-size: 0.86rem; line-height: 1.55; }
.hide { display: none !important; }
.nowrap { white-space: nowrap; }

/* Cualquier bloque ancho (código, diagrama) se desplaza dentro de sí mismo.
   El body NUNCA debe tener scroll horizontal. */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
