/* =========================================================
   Sistema de Laboratorio Clínico — Hoja de estilos
   Paleta: clínica, confiable, de alto contraste funcional
   ========================================================= */
@import url('https://fonts.googleapis.com/css2?family=Sora:wght@500;600;700;800&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@500&display=swap');

:root{
  --bg: #F5F8F8;
  --surface: #FFFFFF;
  --surface-2: #EFF4F4;
  --ink: #10262A;
  --muted: #5C7278;
  --muted-2: #85989D;
  --border: #DCE6E7;
  --primary: #05ADEC;            /* azul del logo (microscopio) */
  --marca-naranja: #EA660C;      /* naranja del logo (engranaje): acciones principales */
  --marca-naranja-oscuro: #C4520A;
  --primary-dark: #0281B4;
  --primary-light: #E4F2F1;
  --accent: #2E6E9E;
  --accent-light: #E7F0F8;
  --success: #1E8A5F;
  --success-light: #E5F5EE;
  --success-border: #bfe4d3;
  --warning: #B9770E;
  --warning-light: #FBF0DD;
  --warning-border: #f0dcae;
  --danger: #B23A34;
  --danger-light: #FBEAE9;
  --danger-border: #f0c9c6;
  --accent-border: #c9dcee;
  --radius: 10px;
  --radius-lg: 16px;

  /* Escala tipográfica. Antes convivían ~30 tamaños distintos entre el CSS y los estilos
     sueltos de las plantillas (de 8px a 52px), muchos separados por medio punto: eso es
     lo que hacía que la interfaz se viera armada a mano en vez de diseñada.
     Los pasos NO son redondos a propósito: están puestos sobre los valores que el sistema
     ya usaba con más frecuencia (12px aparecía 85 veces, 11.5px 59, 12.5px 58, 14.5px 44),
     de modo que al migrar ningún texto se mueve más de 0.5px — por debajo de lo que el
     ojo distingue. Elegir una escala "bonita" de números redondos habría cambiado el
     tamaño de medio sistema sin poder revisarlo pantalla por pantalla. */
  --texto-2xs: 10px;    /* micro-etiquetas, pies de tabla */
  --texto-xs: 11.5px;   /* etiquetas, insignias */
  --texto-sm: 12.5px;   /* texto secundario, ayudas */
  --texto-base: 13.5px; /* cuerpo, formularios, tablas */
  --texto-md: 14.5px;   /* texto destacado */
  --texto-lg: 16px;     /* títulos de sección */
  --texto-xl: 20px;     /* títulos de tarjeta destacada */
  --texto-2xl: 24px;    /* encabezado de página */
  --texto-3xl: 32px;    /* cifra principal de una tarjeta */

  /* Escala de espaciado en pasos de 4. Hoy hay 20 valores distintos (1,2,4,5,6,7,8,9,
     10,11,12,14,16,18,20,22,26,28,36,56), y esa irregularidad es la que rompe el ritmo
     vertical entre pantallas. */
  --esp-1: 4px;
  --esp-2: 8px;
  --esp-3: 12px;
  --esp-4: 16px;
  --esp-5: 24px;
  --esp-6: 32px;
  --esp-7: 48px;
  --shadow: 0 1px 2px rgba(16,38,42,.06), 0 4px 16px rgba(16,38,42,.05);
  --shadow-lg: 0 8px 30px rgba(16,38,42,.10);
}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;
  font-family:'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  background:var(--bg);
  color:var(--ink);
  font-size:14.5px;
  line-height:1.5;
}
h1,h2,h3,h4,.font-display{
  font-family:'Sora', 'Inter', sans-serif;
  font-weight:700;
  letter-spacing:-0.01em;
  color:var(--ink);
}
a{color:var(--primary); text-decoration:none}
a:hover{text-decoration:underline}
code, .mono{font-family:'JetBrains Mono', monospace}

/* ---------- Layout ---------- */
.app-shell{display:flex; min-height:100vh}

.sidebar{
  width:248px; flex-shrink:0;
  background: linear-gradient(180deg, var(--primary-dark), #0A5A5A 70%, #0A5555);
  color:#EAF5F4;
  display:flex; flex-direction:column;
  position:sticky; top:0; height:100vh;
}
.sidebar-nav-scroll{
  flex:1 1 auto;
  overflow-y:auto;
  overflow-x:hidden;
  min-height:0;
}
.sidebar-nav-scroll::-webkit-scrollbar{ width:6px }
.sidebar-nav-scroll::-webkit-scrollbar-track{ background:transparent }
.sidebar-nav-scroll::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.2); border-radius:3px }
.sidebar-brand{
  padding:22px 20px 16px;
  display:flex; align-items:center; gap:10px;
  border-bottom:1px solid rgba(255,255,255,.12);
  flex-shrink:0;
}
/* Cuando hay un logo real subido, se le da todo el ancho disponible (en vez del cuadro fijo
   de 36x36 que antes lo achicaba mucho) — el logo va en su propia fila junto al botón de
   colapsar, y el subtítulo debajo. Object-fit:contain preserva su proporción real, así que
   un logo ancho (ícono + texto en una sola línea) se ve nítido en vez de distorsionado. */
.sidebar-brand-con-logo{flex-direction:column; align-items:stretch; gap:6px}
.sidebar-brand-fila-logo{display:flex; align-items:center; gap:8px}
.sidebar-brand-logo{
  height:40px; width:auto; max-width:100%; align-self:flex-start;
}
.sidebar-brand .mark{
  width:36px;height:36px;border-radius:10px;background:rgba(255,255,255,.14);
  display:flex;align-items:center;justify-content:center;font-weight:800;font-family:'Sora',sans-serif;
  font-size:16px; color:#fff; flex-shrink:0;
}
.sidebar-brand .name{font-family:'Sora',sans-serif; font-weight:700; font-size:15px; line-height:1.2; color:#fff}
.sidebar-brand .sub{font-size:11px; color:rgba(234,245,244,.65); margin-top:1px}

.nav-section{padding:14px 12px}
.nav-label{font-size:10.5px; text-transform:uppercase; letter-spacing:.09em; color:rgba(234,245,244,.5); padding:10px 10px 6px}
.nav-label-toggle{
  display:flex; align-items:center; justify-content:space-between; width:100%;
  background:none; border:none; cursor:pointer; font-family:inherit;
}
.nav-label-toggle:hover{color:rgba(234,245,244,.85)}
.nav-chevron{width:14px; height:14px; flex-shrink:0; transition:transform .15s ease}
.nav-section.colapsada .nav-chevron{transform:rotate(-90deg)}
.nav-section.colapsada .nav-section-items{display:none}
.nav-item{
  display:flex; align-items:center; gap:10px;
  padding:9px 12px; border-radius:8px; color:rgba(234,245,244,.88);
  font-size:13.5px; font-weight:500; margin-bottom:2px;
}
.nav-item:hover{background:rgba(255,255,255,.08); text-decoration:none; color:#fff}
.nav-item.active{background:rgba(255,255,255,.16); color:#fff}
.nav-item svg{width:17px;height:17px;flex-shrink:0; opacity:.9}
.sidebar-foot{margin-top:auto; padding:14px 20px; font-size:11px; color:rgba(234,245,244,.5); border-top:1px solid rgba(255,255,255,.1); flex-shrink:0}

/* ---------- Botón para ocultar/colapsar el sidebar completo (modo solo íconos) ---------- */
.btn-colapsar-sidebar{
  background:rgba(255,255,255,.1); border:none; border-radius:7px; color:#fff;
  width:26px; height:26px; display:flex; align-items:center; justify-content:center;
  cursor:pointer; flex-shrink:0; margin-left:auto; transition:background .15s ease;
}
.btn-colapsar-sidebar:hover{background:rgba(255,255,255,.2)}
.btn-colapsar-sidebar svg{width:15px; height:15px}
.sidebar-colapsada .btn-colapsar-sidebar svg{transform:rotate(180deg)}

.app-shell.sidebar-colapsada .sidebar{width:70px}
.app-shell.sidebar-colapsada .sidebar-brand{justify-content:center; padding:18px 10px}
.app-shell.sidebar-colapsada .sidebar-brand-text{display:none}
/* El logo ancho (ícono + texto) no cabe legible en los 70px del menú colapsado — se oculta
   y solo queda el botón para volver a expandir, centrado. */
.app-shell.sidebar-colapsada .sidebar-brand-con-logo{padding:18px 10px}
.app-shell.sidebar-colapsada .sidebar-brand-logo{display:none}
.app-shell.sidebar-colapsada .sidebar-brand-fila-logo{justify-content:center}
.app-shell.sidebar-colapsada .btn-colapsar-sidebar{margin-left:0}
.app-shell.sidebar-colapsada .nav-label-toggle{justify-content:center; padding:8px 4px}
.app-shell.sidebar-colapsada .nav-label-toggle span:first-child{display:none}
.app-shell.sidebar-colapsada .nav-chevron{display:none}
.app-shell.sidebar-colapsada .nav-section-items{display:block !important}
.app-shell.sidebar-colapsada .nav-submenu-items{display:block !important}
.app-shell.sidebar-colapsada .nav-submenu-toggle-btn{display:none}
.app-shell.sidebar-colapsada .nav-item{justify-content:center; padding:9px 6px}
.app-shell.sidebar-colapsada .nav-text{display:none}
.app-shell.sidebar-colapsada .sidebar-foot{display:none}
@media (max-width:900px){
  .app-shell.sidebar-colapsada .sidebar{width:248px}
  .app-shell.sidebar-colapsada .sidebar-brand-text,
  .app-shell.sidebar-colapsada .nav-label-toggle span:first-child,
  .app-shell.sidebar-colapsada .nav-chevron,
  .app-shell.sidebar-colapsada .nav-text,
  .app-shell.sidebar-colapsada .sidebar-foot{display:revert}
  .app-shell.sidebar-colapsada .nav-label-toggle{justify-content:space-between; padding:10px 10px 6px}
  .app-shell.sidebar-colapsada .nav-item{justify-content:flex-start; padding:9px 12px}
  .app-shell.sidebar-colapsada .btn-colapsar-sidebar{display:none}
}

.main{flex:1; min-width:0; display:flex; flex-direction:column}
.topbar{
  height:64px; flex-shrink:0; background:var(--surface); border-bottom:1px solid var(--border);
  display:flex; align-items:center; justify-content:space-between; padding:0 28px; position:sticky; top:0; z-index:20;
}
.topbar h1{font-size:17px; margin:0}
.topbar .date-badge{font-size:12.5px; color:var(--muted); background:var(--surface-2); padding:6px 12px; border-radius:20px}
.content{padding:26px 28px 60px; max-width:1600px; width:100%; margin:0 auto}

/* ---------- Cards / componentes ---------- */
.card{background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); box-shadow:var(--shadow)}
.card-pad{padding:20px 22px}
.stat-card{
  border-radius:var(--radius-lg); padding:18px 20px; background:var(--surface); border:1px solid var(--border);
  position:relative; overflow:hidden; transition:box-shadow .15s ease, transform .15s ease;
}
.stat-card:hover{box-shadow:var(--shadow-lg); transform:translateY(-1px)}
.stat-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--accent-bar,var(--primary))}
.stat-card .label{font-size:12.5px; color:var(--muted); font-weight:600; line-height:1.3}
.stat-card .value{font-family:'Sora',sans-serif; font-size:28px; font-weight:700; margin-top:4px}
.stat-card .hint{font-size:12px; color:var(--muted-2); margin-top:2px}

.section-title{display:flex; align-items:center; justify-content:space-between; margin:0 0 14px; flex-wrap:wrap; gap:10px}
.section-title h2{font-size:16px; margin:0}

/* Tarjeta de estadística que también funciona como enlace — evita tener un botón aparte
   compitiendo visualmente con la tarjeta que ya dice lo mismo (ej. "Gastos de caja hoy"
   ya lleva a Gastos de caja, no hace falta un botón repetido arriba de la página). */
a.stat-card-clicable{display:block; text-decoration:none; color:inherit; transition:transform .12s ease, box-shadow .12s ease}
a.stat-card-clicable:hover{transform:translateY(-2px); box-shadow:var(--shadow-lg); border-color:var(--accent-bar,var(--primary))}
a.stat-card-clicable .hint{display:flex; align-items:center; gap:4px}
a.stat-card-clicable .hint svg{width:12px; height:12px; transition:transform .12s ease}
a.stat-card-clicable:hover .hint svg{transform:translateX(2px)}

.grid{display:grid; gap:18px}
.grid > *{min-width:0}
/* Grupo "requiere atención": el número pesa más que uno puramente informativo */
.stat-card--urgente .value{font-size:32px; color:var(--accent-bar,var(--danger))}
.stat-card .value{color:var(--ink)}
.stat-card .hint{min-height:1em}

/* Cabecera de la tarjeta: etiqueta a la izquierda, icono a la derecha. Antes esto vivia
   como estilo en linea repetido en cada tarjeta, y por eso se iba desalineando. */
.stat-cabecera{display:flex; align-items:flex-start; justify-content:space-between; gap:10px}
.stat-icono{
  width:30px; height:30px; border-radius:8px; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
  background:var(--ico-bg, var(--primary-light)); color:var(--ico, var(--primary));
}
.stat-icono svg{width:16px; height:16px}

/* Acciones rapidas: rejilla propia. Con la rejilla general de 2 columnas, la tercera
   accion quedaba sola en una fila con medio ancho vacio al lado. */
.grid-acciones{display:grid; gap:14px; grid-template-columns:repeat(3,1fr)}
.grid-acciones > *{min-width:0}
@media (max-width:720px){.grid-acciones{grid-template-columns:1fr}}

/* Titulo de seccion con su dato principal al lado: el grafico dice algo aunque tenga
   pocas barras. */
.titulo-con-dato{display:flex; align-items:baseline; gap:12px; flex-wrap:wrap}
.titulo-con-dato .dato-grande{
  font-family:'Sora',sans-serif; font-weight:700; font-size:20px; color:var(--primary-dark);
}

.grupo-label{font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); margin:0 0 8px 2px}

/* Alerta destacada: tratamiento propio, distinto al de las tarjetas comunes (sin franja
   lateral, con un ícono grande en un círculo) para que se sienta genuinamente urgente. */
.alerta-destacada{
  border-radius:var(--radius-lg); padding:18px 22px; background:var(--danger-light, #FBEAE9);
  border:1px solid var(--danger-border, #F0C9C6); box-shadow:var(--shadow); display:flex; gap:16px;
}
/* Variante de aviso (ámbar) frente a la crítica (roja): "hay pendientes de días
   anteriores" es algo a mirar en el día, no una emergencia. Sin esto el aviso salía en
   rojo, con el mismo peso visual que las alertas críticas del panel. */
.alerta-destacada--aviso{background:var(--warning-light); border-color:var(--warning-border, #E8D5A8)}
.alerta-destacada--aviso .icono-circulo{background:var(--warning)}

.alerta-destacada .icono-circulo{
  flex:none; width:42px; height:42px; border-radius:50%; background:var(--danger); color:#fff;
  display:flex; align-items:center; justify-content:center;
}
.alerta-destacada .icono-circulo svg{width:22px; height:22px}

.seccion-dashboard{margin-bottom:26px}
.seccion-dashboard + .seccion-dashboard{padding-top:26px; border-top:1px solid var(--border)}

.grid-4{grid-template-columns:repeat(4,1fr)}
.grid-3{grid-template-columns:repeat(3,1fr)}
.grid-2{grid-template-columns:repeat(2,1fr)}
@media (max-width:1100px){.grid-4{grid-template-columns:repeat(2,1fr)} .grid-3{grid-template-columns:repeat(2,1fr)}}

/* Fila inferior del panel (Agenda / Documentos / Top pruebas): en pantallas medianas la
   Agenda ocupa todo el ancho arriba, y los otros dos quedan lado a lado debajo — en vez de
   que uno de los 3 quede descompensado y solo en su propia fila. */
.grid-panel-inferior{display:grid; gap:18px; grid-template-columns:repeat(3,1fr)}
.grid-panel-inferior > *{min-width:0}
@media (max-width:1100px){
  .grid-panel-inferior{grid-template-columns:repeat(2,1fr)}
  .grid-panel-inferior > *:first-child{grid-column:1 / -1}
}
@media (max-width:640px){
  .grid-panel-inferior{grid-template-columns:1fr}
  .grid-panel-inferior > *:first-child{grid-column:auto}
}

/* ---------- Responsivo para tablet / celular ---------- */
.btn-hamburguesa{ display:none; background:none; border:none; padding:6px; margin-right:6px; cursor:pointer; color:var(--ink) }
.btn-hamburguesa svg{ width:24px; height:24px }
.fondo-menu-movil{ display:none }
.form-buscador-topbar{ display:flex; flex:1 1 auto; min-width:0 }

/* ---------- Desplegable de búsqueda rápida en el encabezado ---------- */
.buscador-rapido-lista{
  display:none; position:absolute; top:calc(100% + 6px); left:0; right:0; z-index:200;
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  box-shadow:var(--shadow-lg); max-height:420px; overflow-y:auto; padding:6px;
}
.buscador-rapido-lista.abierto{ display:block }
.buscador-rapido-lista .grupo-titulo{
  font-size:10.5px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted);
  font-weight:700; padding:8px 10px 4px;
}
.buscador-rapido-lista a{
  display:flex; flex-direction:column; gap:1px; padding:8px 10px; border-radius:7px; color:var(--ink);
}
.buscador-rapido-lista a:hover{ background:var(--surface-2); text-decoration:none }
.buscador-rapido-lista .item-sub{ font-size:11.5px; color:var(--muted) }
.buscador-rapido-lista .sin-resultados{ padding:14px 10px; color:var(--muted); font-size:13px; text-align:center }
.buscador-rapido-lista .ver-todos{
  display:block; text-align:center; padding:9px; font-size:12.5px; font-weight:600;
  color:var(--primary); border-top:1px solid var(--border); margin-top:4px;
}
.buscador-topbar{ width:100%; min-width:0 }

@media (max-width:900px){
  .btn-hamburguesa{ display:inline-flex; align-items:center; justify-content:center }
  .sidebar{
    position:fixed; left:0; top:0; z-index:100;
    transform:translateX(-100%); transition:transform .2s ease-out;
    box-shadow:2px 0 18px rgba(0,0,0,.25);
  }
  .sidebar.sidebar-abierta{ transform:translateX(0) }
  .fondo-menu-movil.visible{
    display:block; position:fixed; inset:0; background:rgba(0,0,0,.4); z-index:90;
  }
  .app-shell{ display:block }
  .main{ width:100%; min-width:0 }
  .topbar{ padding:0 14px; gap:8px }
  .topbar h1{ font-size:15px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
  .content{ padding:16px 14px 40px; max-width:100% }
  .grid, .grid-2, .grid-3, .grid-4{ grid-template-columns:1fr !important }
  .grid > *, .grid-2 > *, .grid-3 > *, .grid-4 > *{ min-width:0 }
  img, pre, table, input, select, textarea{ max-width:100% }
  pre{ white-space:pre-wrap; word-break:break-word }
  .card[style*="max-width"]{ max-width:100% !important }
  .form-group[style*="max-width"]{ max-width:100% !important }
  fieldset{ max-width:100%; box-sizing:border-box }
  legend{ white-space:normal; max-width:100%; font-size:13px }
  form[style*="display:flex"]{ flex-wrap:wrap !important }
  .form-row, .form-row-3{ grid-template-columns:1fr !important }
  .dte-id-grid{ grid-template-columns:1fr !important }
  .form-buscador-topbar{ display:none }
  .date-badge{ display:none }
}

/* ---------- Botones ---------- */
.btn{
  display:inline-flex; align-items:center; gap:7px; justify-content:center;
  font-family:'Inter',sans-serif; font-weight:600; font-size:13.5px;
  padding:9px 16px; border-radius:8px; border:1px solid transparent; cursor:pointer;
  transition:.12s ease;
}
.btn-primary{background:var(--primary); color:#fff}
.btn-primary:hover{background:var(--primary-dark); text-decoration:none; color:#fff}
.btn-outline{background:var(--surface); border-color:var(--border); color:var(--ink)}
.btn-outline:hover{border-color:var(--primary); color:var(--primary); text-decoration:none}
.btn-danger{background:var(--danger-light); color:var(--danger)}
.btn-danger:hover{background:var(--danger); color:#fff; text-decoration:none}
.btn-sm{padding:6px 11px; font-size:12.5px}
.btn:disabled{opacity:.5; cursor:not-allowed}
.btn svg{width:15px;height:15px}
.btn-icono{width:15px;height:15px;flex-shrink:0;vertical-align:-3px}
legend .btn-icono, h2 .btn-icono, h3 .btn-icono{width:16px;height:16px;vertical-align:-3px;margin-right:2px}

/* ---------- Formularios ---------- */
label{font-size:12.5px; font-weight:600; color:var(--muted); display:block; margin-bottom:5px}
.form-group:has(input[required], select[required], textarea[required]) > label::after{
  content:" *"; color:var(--danger); font-weight:700;
}
.form-group{margin-bottom:15px}
/* datetime-local, time, search y url faltaban en esta lista: quedaban con el aspecto por
   omisión del navegador — angostos, más bajos que el resto y en tipografía monoespaciada,
   desalineados con el campo de al lado. */
input[type=text], input[type=date], input[type=datetime-local], input[type=time],
input[type=number], input[type=email], input[type=tel], input[type=search],
input[type=url], input[type=password], select, textarea{
  width:100%; padding:9px 11px; border:1px solid var(--border); border-radius:8px;
  font-family:'Inter',sans-serif; font-size:13.5px; background:var(--surface); color:var(--ink);
}
/* Safari y Chrome renderizan la fecha con su propia tipografía y la alinean arriba dentro
   del campo; esto la deja como el resto de los campos del formulario. */
input[type=date], input[type=datetime-local], input[type=time]{
  min-height:38px; line-height:1.2; -webkit-appearance:none; appearance:none;
}
input[type=date]::-webkit-datetime-edit, input[type=datetime-local]::-webkit-datetime-edit,
input[type=time]::-webkit-datetime-edit{
  font-family:'Inter',sans-serif; padding:0;
}
/* El iconito del calendario, del color del sistema en vez del gris del navegador. */
input[type=date]::-webkit-calendar-picker-indicator,
input[type=datetime-local]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator{
  cursor:pointer; opacity:.55;
}
input[type=date]:hover::-webkit-calendar-picker-indicator,
input[type=datetime-local]:hover::-webkit-calendar-picker-indicator,
input[type=time]:hover::-webkit-calendar-picker-indicator{ opacity:1 }
input:focus, select:focus, textarea:focus{outline:2px solid var(--primary); outline-offset:0; border-color:var(--primary)}
input:user-invalid, select:user-invalid, textarea:user-invalid{
  border-color:var(--danger); background:var(--danger-light);
}
input:user-invalid:focus, select:user-invalid:focus, textarea:user-invalid:focus{
  outline-color:var(--danger);
}
.campo-ayuda-error{ display:none; color:var(--danger); font-size:11.5px; margin-top:4px }
input:user-invalid ~ .campo-ayuda-error, select:user-invalid ~ .campo-ayuda-error, textarea:user-invalid ~ .campo-ayuda-error{ display:block }
.btn:focus-visible, a:focus-visible, button:focus-visible,
.tab-item:focus-visible, .menu-opciones-lista a:focus-visible{
  outline:2px solid var(--primary); outline-offset:2px; border-radius:4px;
}
.nav-item:focus-visible{
  outline:2px solid #fff; outline-offset:-2px; border-radius:6px;
}
[data-theme="dark"] .btn:focus-visible, [data-theme="dark"] a:focus-visible, [data-theme="dark"] button:focus-visible{
  outline-color:#6FD6D0;
}
textarea{resize:vertical; min-height:70px}
.form-row{display:grid; grid-template-columns:repeat(2,1fr); gap:14px}
.form-row-3{display:grid; grid-template-columns:repeat(3,1fr); gap:14px}
.checkbox-row{display:flex; align-items:center; gap:8px}
.checkbox-row input{width:auto}
fieldset{border:1px solid var(--border); border-radius:10px; padding:14px 16px; margin-bottom:16px}
legend{font-family:'Sora',sans-serif; font-weight:600; font-size:13px; padding:0 6px; color:var(--primary-dark)}

/* ---------- Tablas ---------- */
.table-wrap{overflow-x:auto; border:1px solid var(--border); border-radius:var(--radius-lg); background:var(--surface)}
table{width:100%; border-collapse:collapse; font-size:13.5px}
thead th{
  text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted);
  padding:11px 14px; background:var(--surface-2); border-bottom:1px solid var(--border); white-space:nowrap;
}
tbody td{padding:11px 14px; border-bottom:1px solid var(--border); vertical-align:middle}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:var(--surface-2)}

/* Rayado por DEFECTO en toda tabla de lista. Antes era opcional (.tabla-zebra) y solo lo
   usaban 14 de 56 pantallas: Pacientes se veía distinto de Facturas sin ninguna razón, que
   es de lo que más rápido se lee como "cada pantalla la hizo otra persona".
   Se aplica sobre .table-wrap para que NO alcance a las tablas de maquetación (tickets,
   hojas de impresión y captura de resultados), que no están envueltas.
   Para exceptuar una tabla concreta: class="tabla-sin-zebra". */
.table-wrap table:not(.tabla-sin-zebra) tbody tr:nth-child(even){background:var(--surface-2)}
.table-wrap table:not(.tabla-sin-zebra) tbody tr:nth-child(even):hover{background:var(--primary-light)}
.tabla-zebra tbody tr:nth-child(even){background:var(--surface-2)}
.tabla-zebra tbody tr:nth-child(even):hover{background:var(--primary-light)}

/* Botones dentro de una fila: siempre pequeños. Convivían los dos tamaños (Pacientes tenía
   4 normales y ningún pequeño; Inventario 3 pequeños y 1 normal) y un botón de tamaño
   completo estira la fila y rompe el ritmo vertical de la tabla. Se resuelve aquí y no
   plantilla por plantilla para que valga también en las que se agreguen después. */
.table-wrap tbody .btn{padding:6px 11px; font-size:var(--texto-sm)}
.table-wrap tbody .btn svg{width:13px; height:13px}
.text-right{text-align:right}
.text-muted{color:var(--muted)}

/* ---------- Foco de teclado visible en todo el sistema ----------
   Antes solo había 4 reglas de foco sueltas: quien opera caja con teclado no veía dónde
   estaba parado. Se usa :focus-visible (no :focus) para que el anillo aparezca al navegar
   con teclado pero NO al hacer clic con el mouse, que es lo que molesta. */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible, summary:focus-visible{
  outline:2px solid var(--primary);
  outline-offset:2px;
  border-radius:4px;
}
/* Sobre fondo oscuro (barra lateral) el anillo del color de marca no contrasta. */
.sidebar a:focus-visible, .sidebar button:focus-visible{outline-color:#fff}

/* ---------- Tablas en pantalla angosta ----------
   Con overflow-x el usuario tenía que arrastrar la tabla de lado en el teléfono. Debajo
   de 760px cada fila pasa a leerse como una ficha apilada, con el nombre de la columna
   delante de cada dato. Ese nombre lo pone base.html copiándolo del <thead>, así que
   funciona en las 57 pantallas con tabla sin tocar ninguna. */
@media (max-width:760px){
  .table-wrap{overflow-x:visible; border:none; background:transparent}
  .table-wrap table, .table-wrap thead, .table-wrap tbody,
  .table-wrap tr, .table-wrap th, .table-wrap td{display:block}
  .table-wrap thead{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0)}
  .table-wrap tbody tr{
    background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
    padding:var(--esp-2) var(--esp-3); margin-bottom:var(--esp-2);
  }
  .table-wrap tbody tr:hover{background:var(--surface)}
  /* El rayado tiene más especificidad que la regla de tarjeta de arriba, así que hay que
     anularlo explícitamente: si no, una fila de cada dos saldría con otro fondo y las
     tarjetas se verían a dos tonos. */
  .table-wrap table:not(.tabla-sin-zebra) tbody tr:nth-child(even),
  .table-wrap table:not(.tabla-sin-zebra) tbody tr:nth-child(even):hover,
  .tabla-zebra tbody tr:nth-child(even){background:var(--surface)}
  .table-wrap tbody td{
    display:flex; justify-content:space-between; align-items:baseline; gap:var(--esp-3);
    padding:6px 0; border-bottom:1px dashed var(--border); text-align:left !important;
    /* `flex-wrap` y `min-width:0`: sin ellos el contenido de la derecha no puede
       encogerse ni bajar de línea, y un nombre largo —«MARIA ELENA CARTAGENA DE
       MENENDEZ»— o una fila de botones empujaban la tarjeta fuera de la pantalla.
       Se corrige aquí, en la conversión a tarjetas, y vale para todas las tablas. */
    flex-wrap:wrap; min-width:0;
  }
  .table-wrap tbody td > *{ min-width:0; max-width:100% }
  /* Un nombre sin espacios no tiene por dónde partirse: se permite cortarlo antes que
     desbordar. */
  .table-wrap tbody td{ overflow-wrap:anywhere }
  .table-wrap tbody tr td:last-child{border-bottom:none}
  .table-wrap tbody td::before{
    content:attr(data-columna);
    font-size:var(--texto-xs); text-transform:uppercase; letter-spacing:.05em;
    color:var(--muted); font-weight:600; flex:0 0 42%;
  }
  /* Celdas sin nombre de columna (acciones, casillas) ocupan la fila completa. */
  .table-wrap tbody td[data-columna=""]::before{display:none}
  .table-wrap tbody td[data-columna=""]{justify-content:flex-start}
}

/* Botón esperando respuesta: evita el doble clic en Caja/Facturar. */
.enviando{opacity:.65; pointer-events:none; cursor:progress}

/* ---------- Badges / Pills ---------- */
.badge{display:inline-flex; align-items:center; gap:5px; font-size:11.5px; font-weight:600; padding:4px 10px; border-radius:20px}
.badge-primary{background:var(--primary-light); color:var(--primary-dark)}
.badge-accent{background:var(--accent-light); color:var(--accent)}

/* ---------- Insignia compacta con el tipo de documento (Documentos emitidos) ---------- */
.badge-tipo-dte{
  display:inline-flex; align-items:center; justify-content:center; flex-shrink:0;
  min-width:34px; height:24px; padding:0 6px; border-radius:7px;
  font-family:'Sora',sans-serif; font-weight:700; font-size:10.5px; letter-spacing:0.2px;
}
.badge-tipo-01{background:var(--primary-light); color:var(--primary-dark)}
.badge-tipo-03{background:var(--accent-light); color:var(--accent)}
.badge-tipo-14{background:var(--warning-light); color:var(--warning)}
.badge-tipo-05, .badge-tipo-06{background:var(--danger-light); color:var(--danger)}
.badge-tipo-rec{background:var(--surface-2); color:var(--muted)}
.badge-success{background:var(--success-light); color:var(--success)}
.badge-warning{background:var(--warning-light); color:var(--warning)}
.badge-danger{background:var(--danger-light); color:var(--danger)}
.badge-muted{background:var(--surface-2); color:var(--muted)}
.badge-dot{width:6px;height:6px;border-radius:50%; background:currentColor}

/* ---------- Tarjetas colapsables de resultados por paciente/orden ---------- */
.tarjeta-resultado-header{
  display:flex; justify-content:space-between; align-items:center; gap:10px;
  cursor:pointer; user-select:none;
}
.tarjeta-resultado-chevron{width:16px; height:16px; flex-shrink:0; color:var(--muted); transition:transform .15s ease}
.tarjeta-resultado.abierta .tarjeta-resultado-chevron{transform:rotate(180deg)}
.tarjeta-resultado-cuerpo{display:none; margin-top:12px}
.tarjeta-resultado.abierta .tarjeta-resultado-cuerpo{display:block}

/* ---------- Menú desplegable de opciones por examen (⋮) ---------- */
.menu-opciones{position:relative; display:inline-block}
.menu-opciones-boton{
  background:var(--surface-2); border:1px solid var(--border); border-radius:7px;
  width:30px; height:30px; display:flex; align-items:center; justify-content:center;
  cursor:pointer; color:var(--ink); font-size:16px; line-height:1;
}
.menu-opciones-boton:hover{background:var(--primary-light)}
.menu-opciones-lista{
  display:none; position:absolute; right:0; top:calc(100% + 4px); z-index:30;
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  box-shadow:var(--shadow); min-width:200px; padding:6px; flex-direction:column; gap:2px;
}
.menu-opciones.abierto .menu-opciones-lista{display:flex}

/* En la tarjeta del teléfono el botón «⋮» queda a la IZQUIERDA, y el menú anclado por su
   derecha se salía de la pantalla: empezaba en -129px, así que 129 de sus 200px de ancho
   quedaban fuera y las opciones eran inalcanzables.
   Aquí se ancla por la izquierda del botón y se limita al ancho disponible. */
@media (max-width:760px){
  /* Anclar SIEMPRE a la izquierda arreglaba el botón de la tarjeta de documentos —que
     queda a la izquierda— pero rompía los que están a la derecha, como el de cada examen
     en Resultados validados: el menú se iba 113px fuera.
     Con `position:fixed` y las coordenadas puestas por el guion, el menú se coloca donde
     quepa sea cual sea la posición del botón. */
  .menu-opciones-lista{
    position:fixed; right:auto; min-width:0; width:max-content;
    max-width:calc(100vw - 24px);
  }
}
.menu-opciones-lista a, .menu-opciones-lista button{
  display:flex; align-items:center; gap:8px; padding:8px 10px; border-radius:7px;
  font-size:13px; color:var(--ink); text-align:left; background:none; border:none;
  cursor:pointer; width:100%; font-family:inherit;
}
.menu-opciones-lista a:hover, .menu-opciones-lista button:hover{background:var(--surface-2); text-decoration:none}
.menu-opciones-lista .separador{border-top:1px solid var(--border); margin:4px 0}

/* ---------- Submenú anidado de "Reportes (general)" dentro de Administración ---------- */
.nav-item-with-toggle{display:flex; align-items:stretch; gap:2px}
.nav-submenu-toggle-btn{
  background:none; border:none; color:rgba(234,245,244,.6); cursor:pointer;
  display:flex; align-items:center; justify-content:center; width:30px; border-radius:8px; flex-shrink:0;
}
.nav-submenu-toggle-btn:hover{background:rgba(255,255,255,.08); color:#fff}
.nav-submenu-toggle-btn .nav-chevron{width:14px; height:14px; transition:transform .15s ease}
.nav-submenu-toggle-btn.abierto .nav-chevron{transform:rotate(180deg)}
.nav-submenu-items{display:none}
.nav-submenu-items.abierto{display:block}

/* ---------- Alertas / flash ---------- */
.alert{padding:12px 16px; border-radius:10px; font-size:13.5px; margin-bottom:14px; border:1px solid transparent}
.alert-success{background:var(--success-light); color:var(--success); border-color:var(--success-border)}
.alert-danger{background:var(--danger-light); color:var(--danger); border-color:var(--danger-border)}
.alert-warning{background:var(--warning-light); color:var(--warning); border-color:var(--warning-border)}
.alert-info{background:var(--accent-light); color:var(--accent); border-color:var(--accent-border)}

/* ---------- Sello / seal (elemento distintivo) ---------- */
.seal{
  width:64px; height:64px; border-radius:50%; border:2.5px dashed var(--primary);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  color:var(--primary); font-family:'Sora',sans-serif; font-weight:700; font-size:10px; text-align:center;
  line-height:1.15; text-transform:uppercase; letter-spacing:.02em;
}
.seal.pending{border-color:var(--warning); color:var(--warning)}
.seal.void{border-color:var(--danger); color:var(--danger)}

/* ---------- Facturación (POS) ---------- */
.pos-layout{display:grid; grid-template-columns:1.3fr 1fr; gap:20px; align-items:start}
@media(max-width:1150px){.pos-layout{grid-template-columns:1fr}}
.search-result{padding:9px 12px; border-radius:8px; cursor:pointer; border:1px solid transparent}
.search-result:hover{background:var(--surface-2); border-color:var(--border)}
.cart-row{display:flex; align-items:center; gap:10px; padding:10px 0; border-bottom:1px solid var(--border)}
.cart-row:last-child{border-bottom:none}
.cart-qty{width:52px}
.doc-type-option{
  border:1.5px solid var(--border); border-radius:10px; padding:12px 14px; cursor:pointer; display:flex; gap:10px; align-items:flex-start;
}
.doc-type-option.selected{border-color:var(--primary); background:var(--primary-light)}
.total-line{display:flex; justify-content:space-between; padding:5px 0; font-size:13.5px; gap:10px}
.total-line.grand{font-size:19px; font-weight:700; font-family:'Sora',sans-serif; border-top:1px solid var(--border); margin-top:6px; padding-top:10px}
@media (max-width:600px){
  .dte-totales-box{ width:100% !important }
  .total-line{ flex-wrap:wrap }
  .total-line span:first-child{ font-size:12px }
}

/* ---------- Impresión de factura ---------- */
.invoice-paper{max-width:800px; margin:0 auto; background:#fff; padding:36px 40px; position:relative}
.invoice-paper.con-marca-agua::before{
  content:""; position:absolute; inset:0; background-image:var(--marca-agua-url);
  background-repeat:no-repeat; background-position:center; background-size:55%;
  opacity:.06; pointer-events:none; z-index:0;
}
.invoice-paper > *{ position:relative; z-index:1 }
@media print{
  .no-print{display:none !important}
  .sidebar, .topbar{display:none !important}
  .content{padding:0}
  body{background:#fff}
  .invoice-paper{box-shadow:none; padding:0; max-width:none; width:100%}
}
@page {
  margin: 14mm 12mm 16mm;
}
@page {
  @bottom-center { content: "Página " counter(page) " de " counter(pages); font-size: 9px; color: #888; }
}

/* Accesos del día: siempre a la vista, sin plegar. Se separan del resto con una línea
   para que se lean como un bloque aparte y no como el primer grupo de la lista. */
/* El menú en el teléfono: el pie ocupaba 233 px de 915 y empujaba los enlaces fuera de
   la vista, dejando «Recordatorios» cortado y sus propios botones sin alcanzar.

   Se compacta lo que no sirve para navegar: los dos avisos informativos se ocultan y los
   márgenes se reducen. En escritorio queda como estaba. */
@media (max-width: 900px){
  .pie-solo-escritorio{ display:none }
  .sidebar-foot{ padding:10px 18px; font-size:11px }
  .sidebar-foot a{ display:inline-block; padding:2px 0 }

  /* `100vh` en el teléfono NO es lo que se ve: incluye la franja del navegador, que
     aparece y desaparece al desplazar. El menú quedaba más alto que la pantalla y su pie
     —usuario, Mi perfil, Cerrar sesión— caía fuera, alcanzable solo después de bajar.

     `dvh` es la altura VISIBLE de verdad y se reajusta cuando la barra se oculta. Se deja
     `100vh` antes como respaldo para navegadores que no lo entiendan. */
  .sidebar{ height:100vh; height:100dvh; max-height:100dvh; }

  /* `sidebar-colapsada` es la barra ESTRECHA de escritorio —solo iconos— y ahí tiene
     sentido mostrar todos los grupos abiertos. En el teléfono el menú no se colapsa así,
     pero la clase queda guardada de la última vez que se usó en el ordenador, y su
     `!important` desplegaba TODOS los grupos: las cabeceras no servían de nada y el menú
     obligaba a desplazar entre cuarenta enlaces.

     Aquí se anula: en móvil manda el plegado normal. */
  .app-shell.sidebar-colapsada .nav-section.colapsada .nav-section-items{ display:none !important }
  .app-shell.sidebar-colapsada .sidebar{ width:auto }
  .app-shell.sidebar-colapsada .nav-text,
  .app-shell.sidebar-colapsada .nav-label-toggle span:first-child{ display:inline }
  .app-shell.sidebar-colapsada .nav-chevron{ display:inline-block }

  /* El pie fijo al fondo del menú: así «Mi perfil» y «Cerrar sesión» están a la vista
     desde que se abre, sin desplazar hasta el final de 40 enlaces. */
  .sidebar-foot{
    position:sticky; bottom:0; z-index:2;
    background:var(--primary-dark);
    box-shadow:0 -6px 12px rgba(0,0,0,.18);
  }
}

.nav-diario{ padding-bottom:4px }
.nav-diario .nav-item{ font-weight:600 }
.nav-separador{
  height:1px; background:rgba(255,255,255,.14); margin:8px 14px 10px;
}

/* ─────────────────────────────────────────────────────────────────────────────
   MOVIMIENTO — añadidos

   Ya existía un sistema con su escala (--mov-rapido/normal/lento) y su curva; esto
   se apoya en él en vez de introducir tiempos nuevos, o el sistema acabaría con dos
   velocidades distintas para lo mismo.

   Criterio: el movimiento sirve para no perder el hilo —dónde apareció algo, qué
   acaba de cambiar, qué se puede pulsar—. Nada decorativo que dure más de lo que
   tarda el ojo en seguirlo. Todo se anula en `prefers-reduced-motion`, más abajo.
   ───────────────────────────────────────────────────────────────────────────── */

/* Las filas responden al paso del ratón: en listas largas ayuda a no saltar de
   renglón al leer de izquierda a derecha. */
tbody tr{ transition:background-color var(--mov-rapido) var(--mov-curva) }

/* Las tarjetas pulsables se elevan: indica que llevan a algún sitio sin añadir un
   borde ni un icono. */
.card{ transition:box-shadow var(--mov-normal) var(--mov-curva),
                  border-color var(--mov-normal) var(--mov-curva) }
a > .card:hover, .card-pulsable:hover{ box-shadow:0 6px 20px rgba(0,0,0,.09) }

/* El botón se hunde al pulsarlo: confirmación física de que el toque registró,
   sobre todo en el teléfono, donde no hay puntero que lo indique. */
.btn:active{ transform:translateY(1px) }

/* Halo al enfocar un campo. En un formulario de captura con quince campos, ver de
   un vistazo dónde se está escribiendo evita meter el dato en la casilla vecina. */
input[type=text], input[type=date], input[type=datetime-local], input[type=time],
input[type=number], input[type=email], input[type=tel], input[type=search],
input[type=url], input[type=password], select, textarea{
  transition:border-color var(--mov-rapido) var(--mov-curva),
             box-shadow var(--mov-rapido) var(--mov-curva);
}

/* Un valor recién guardado parpadea un instante. Sin esto, guardar dentro de una
   lista larga no da ninguna señal de qué cambió. */
@keyframes mov-destacar{
  from{ background-color:var(--success-light, #E8F5EC) }
  to  { background-color:transparent }
}
.recien-guardado{ animation:mov-destacar var(--mov-lento) var(--mov-curva) }

/* Los bloques plegables se despliegan con el mismo gesto que los menús, que ya
   usaban `mov-desplegar`: un solo lenguaje para todo lo que aparece al pulsar. */
details[open] > *:not(summary){
  animation:mov-desplegar var(--mov-normal) var(--mov-curva) both;
}

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

/* ---------- Toasts (notificaciones flotantes) ---------- */
/* Abajo a la derecha, encima del botón flotante. Arriba estorbaban de verdad: esa
   esquina tiene el buscador y los botones de acción (+ Nuevo paciente, Exportar), y los
   avisos los cubrían justo después de guardar, que es cuando se quiere seguir trabajando.
   Abajo esa zona suele estar vacía. */
.toast-container{ position:fixed; bottom:96px; right:18px; z-index:9999; display:flex; flex-direction:column-reverse; gap:8px; max-width:360px; pointer-events:none }
.toast-container > *{ pointer-events:auto }
.toast.toast-saliendo{ animation:toast-salir .25s ease-in forwards }
@keyframes toast-salir{ to{ opacity:0; transform:translateX(12px) } }
@media (max-width:820px){
  /* En pantalla angosta ocupan el ancho disponible. */
  .toast-container{ bottom:88px; right:12px; left:12px; max-width:none }
}
.toast{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:12px 14px; border-radius:10px; font-size:13.5px; box-shadow:var(--shadow-lg);
  animation:toast-entrar .25s ease-out; border:1px solid transparent;
}
.toast button{ background:none; border:none; cursor:pointer; font-size:13px; opacity:.6; color:inherit }
.toast button:hover{ opacity:1 }
.toast-success{ background:var(--success-light); color:var(--success); border-color:var(--success-border) }
.toast-danger{ background:var(--danger-light); color:var(--danger); border-color:var(--danger-border) }
.toast-warning{ background:var(--warning-light); color:var(--warning); border-color:var(--warning-border) }
.toast-info{ background:var(--accent-light); color:var(--accent); border-color:var(--accent-border) }
.toast-salir{ animation:toast-salir .35s ease-in forwards }
@keyframes toast-entrar{ from{ opacity:0; transform:translateX(30px) } to{ opacity:1; transform:translateX(0) } }
@keyframes toast-salir{ from{ opacity:1 } to{ opacity:0; transform:translateX(30px) } }
@keyframes girar{ from{ transform:rotate(0deg) } to{ transform:rotate(360deg) } }

/* ---------- Spinner de carga reutilizable (formularios/botones enviando) ---------- */
.spinner{
  display:inline-block; width:14px; height:14px; flex-shrink:0;
  border:2px solid currentColor; border-right-color:transparent; border-radius:50%;
  animation:girar .6s linear infinite; opacity:.85; vertical-align:-2px;
}
.btn.cargando{ pointer-events:none; opacity:.75 }

.empty-state{text-align:center; padding:56px 20px 60px; color:var(--muted)}
.empty-state-icono{width:46px; height:46px; margin:0 auto 14px; opacity:.45; display:block; color:var(--muted-2)}
.empty-state p{margin:0 0 4px; font-size:14px}
.empty-state .btn{margin-top:14px}
.empty-state svg:not(.empty-state-icono){width:44px;height:44px; margin-bottom:12px; opacity:.5}

.tab-bar{display:flex; gap:4px; border-bottom:1px solid var(--border); margin-bottom:20px; flex-wrap:wrap}
.tab-item{padding:10px 16px; font-size:13.5px; font-weight:600; color:var(--muted); border-bottom:2px solid transparent; cursor:pointer; display:inline-flex; align-items:center; gap:6px; text-decoration:none}
.tab-item.active{color:var(--primary); border-color:var(--primary)}

/* =========================================================
   Captura de resultados — tabla de parámetros
   Reemplaza los estilos en línea sueltos por clases propias,
   consistentes con el resto del sistema (tarjetas, espaciados,
   tipografía). Pensado para verse bien tanto con muchas filas
   simples como con los widgets de antibiograma/organismos.
   ========================================================= */
.tabla-parametros-wrap{
  border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden;
  background:var(--surface);
}
.tabla-parametros{width:100%; border-collapse:collapse; font-size:13.5px}

/* En el teléfono esta tabla se salía 127px: cinco columnas (parámetro, valor, unidad,
   referencia y el botón de quitar) no caben en 390px, y es la pantalla que más se usa.
   Se convierte a tarjetas, igual que las demás tablas, con la etiqueta de cada campo
   delante para no perder de vista qué se está escribiendo. */
@media (max-width:760px){
  .tabla-parametros-wrap{ border:none; background:transparent; overflow:visible }
  .tabla-parametros, .tabla-parametros tbody, .tabla-parametros tr, .tabla-parametros td{
    display:block; width:100%;
  }
  /* `clip` esconde el thead pero NO anula el ancho de sus celdas: los `th` conservaban
     su `width:26%` en línea y seguían empujando la página. Hay que encogerlos también. */
  /* `display:none` y no la técnica de `clip`: encogiendo el thead sus `th` conservaban
     el `width:26%` en línea y seguían midiendo 169px cada uno, empujando la página. Aquí
     el encabezado no aporta nada —cada campo lleva su etiqueta en la tarjeta—, así que
     se quita del todo. */
  .tabla-parametros thead{ display:none }
  .tabla-parametros tbody tr{
    background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
    padding:var(--esp-3); margin-bottom:var(--esp-2);
  }
  .tabla-parametros tbody td{
    padding:5px 0; border:none; width:auto !important;
  }
  /* La etiqueta va sobre el campo, en pequeño: sin ella, tres cuadros de texto seguidos
     no dicen cuál es el valor y cuál la unidad — y al capturar resultados clínicos eso
     lleva a escribir el dato en el sitio equivocado.
     Las dos primeras celdas (parámetro y valor) se etiquetan por POSICIÓN: no llevan
     `data-etiqueta` y son las mismas en todas las filas. */
  .tabla-parametros tbody td::before{
    content:attr(data-etiqueta); display:block; margin-bottom:4px;
    font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color:var(--muted);
  }
  .tabla-parametros tbody tr > td:nth-child(1)::before{ content:"Parámetro" }
  .tabla-parametros tbody tr > td:nth-child(2)::before{ content:"Resultado" }
  .tabla-parametros tbody td:empty{ display:none }
}
.tabla-parametros thead th{
  text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted);
  padding:12px 14px; background:var(--surface-2); border-bottom:1px solid var(--border);
}
.tabla-parametros tbody td{padding:10px 14px; border-bottom:1px solid var(--border); vertical-align:middle}
.tabla-parametros tbody tr:last-child td{border-bottom:none}
.tabla-parametros tbody tr:hover{background:var(--surface-2)}
.tabla-parametros input[type=text], .tabla-parametros select, .tabla-parametros textarea{
  font-size:13.5px; padding:8px 10px;
}

/* Encabezado de sección (EXAMEN MACRÓSCOPICO, PROTOZOARIOS...) — franja lateral de color
   en vez de solo texto en negrita, para que se note de un vistazo dónde empieza cada bloque. */
.fila-seccion td{
  background:var(--primary-light); font-family:'Sora',sans-serif; font-weight:700; font-size:12.5px;
  text-transform:uppercase; letter-spacing:.04em; color:var(--primary-dark);
  padding:10px 14px !important; border-left:3px solid var(--primary);
}

/* Fila "ancha" para parámetros sin unidad (Color, Consistencia, Flora Bacteriana...) */
.fila-parametro-simple{display:flex; align-items:center; gap:12px; flex-wrap:wrap; padding:2px 0}
.fila-parametro-simple .nombre-parametro{
  font-weight:600; max-width:260px; flex:1 1 200px; background:transparent; border:none;
  padding:4px 2px !important; color:var(--ink);
}
.fila-parametro-simple .nombre-parametro:focus{outline:none; background:var(--surface-2); border-radius:6px}
.fila-parametro-simple .valor-parametro{flex:2 1 240px}

/* Widget de microorganismos / antibiograma — misma tarjeta base, distinto acento de color
   para diferenciarlos de un vistazo (cultivo = ámbar/tubo de ensayo, parásito = teal). */
.widget-hallazgo{
  border:1px solid var(--border); border-radius:var(--radius); padding:14px 16px; background:var(--surface-2);
}
.widget-hallazgo .titulo-widget{
  font-family:'Sora',sans-serif; font-weight:700; font-size:13.5px; display:flex; align-items:center; gap:8px;
  margin-bottom:10px; color:var(--ink);
}
.widget-hallazgo .fila-agregar{display:flex; gap:8px; align-items:center; margin-bottom:10px; flex-wrap:wrap}
.widget-hallazgo .fila-agregar select{min-width:230px; flex:1 1 230px}
.widget-hallazgo .lista-hallazgos{display:flex; flex-direction:column; gap:6px}
.widget-hallazgo .lista-hallazgos:empty::after{
  content:"Nada agregado todavía — se guardará como \"No se observan\"."; font-size:12px; color:var(--muted-2); font-style:italic;
}
.item-hallazgo{
  display:flex; justify-content:space-between; align-items:center; gap:10px;
  padding:7px 12px; background:var(--surface); border:1px solid var(--border); border-radius:8px; font-size:13.5px;
}
.item-hallazgo .btn-quitar{
  background:none; border:none; color:var(--danger); cursor:pointer; font-size:15px; line-height:1; padding:2px 4px; flex-shrink:0;
}
.item-hallazgo .btn-quitar:hover{background:var(--danger-light); border-radius:5px}

/* Barra de acciones pegada abajo — siempre visible mientras se llena un formulario largo,
   sin tener que bajar hasta el final para guardar/validar. */
.barra-acciones-pegajosa{
  position:sticky; bottom:0; left:0; right:0; margin:20px -22px -20px;
  background:var(--surface); border-top:1px solid var(--border); padding:14px 22px;
  display:flex; gap:10px; align-items:center; flex-wrap:wrap; border-radius:0 0 var(--radius-lg) var(--radius-lg);
  box-shadow:0 -4px 16px rgba(16,38,42,.05);
}
@media (max-width:640px){
  .barra-acciones-pegajosa{margin:20px -16px -16px; padding:12px 16px}
  .barra-acciones-pegajosa .btn{flex:1 1 auto}
}

/* =========================================================
   Panel general (dashboard)
   ========================================================= */
.saludo-header{
  display:flex; justify-content:space-between; align-items:baseline; margin-bottom:20px;
  flex-wrap:wrap; gap:6px; padding-bottom:16px; border-bottom:1px solid var(--border);
}
.saludo-header h1{margin:0; font-size:23px; font-family:'Sora',Arial,sans-serif; color:var(--primary-dark)}
.saludo-header .fecha-hoy{font-size:12.5px; color:var(--muted); font-weight:500}

/* Tarjetas de "acción rápida" (Registrar paciente / Facturar / Reportar exámenes): mismo
   patrón que .card pero con una leve elevación al pasar el mouse, para que se sientan
   como botones grandes clicables y no solo tarjetas informativas. */
.accion-rapida{
  display:flex; align-items:center; gap:14px; color:inherit; text-decoration:none;
  border-left:4px solid var(--accion-color, var(--primary));
  transition:transform .15s ease, box-shadow .15s ease;
}
.accion-rapida:hover{
  transform:translateY(-2px); box-shadow:var(--shadow-lg); text-decoration:none;
}
.accion-rapida .icono{
  width:44px; height:44px; flex:none; border-radius:12px; display:flex; align-items:center; justify-content:center;
  background:var(--primary-light);
  background:color-mix(in srgb, var(--accion-color, var(--primary)) 12%, transparent);
  color:var(--accion-color, var(--primary));
}
.accion-rapida .icono svg{width:24px; height:24px}
.accion-rapida .titulo{font-weight:700; font-size:15px}
.accion-rapida .subtitulo{font-size:12px; color:var(--muted)}
.accion-rapida.destacada-para-rol{box-shadow:0 0 0 2px var(--accion-color, var(--primary))}

/* Filas de la lista "Requiere tu atención" — ícono en círculo de color + texto, con un
   ligero cambio de fondo al pasar el mouse para reforzar que son clicables. */
.alerta-item{
  display:flex; align-items:center; gap:10px; color:inherit; text-decoration:none;
  font-size:13.5px; padding:8px 10px; margin:0 -10px; border-radius:8px;
  transition:background .12s ease;
}
.alerta-item:hover{background:rgba(0,0,0,.035); text-decoration:none}
.alerta-item .icono-mini{
  width:30px; height:30px; flex:none; border-radius:9px; display:flex; align-items:center; justify-content:center;
  background:rgba(0,0,0,.06);
}
.alerta-item .icono-mini svg{width:16px; height:16px}
.alerta-item .texto{flex:1}
.alerta-item .ir{color:var(--muted); font-size:12.5px; flex:none}
.alerta-sublista{display:flex; flex-direction:column; gap:4px; padding-left:50px; margin-top:2px}
.alerta-sublista .fila{display:flex; justify-content:space-between; font-size:12.5px; color:var(--muted)}

/* =========================================================
   Catálogo de pruebas
   ========================================================= */
/* Edición de precios en lote: por defecto se ve el precio como texto; en modo edición se
   oculta el texto y aparece un input numérico compacto en su lugar, para editar muchos
   precios de corrido sin entrar prueba por prueba. */
.precio-texto{font-weight:600}
.input-precio-lote{
  display:none; width:100%; padding:6px 8px; font-size:13px;
}
input.input-precio-lote[name^="precio_"]{width:100px; margin-left:auto; text-align:right; font-size:13.5px}
body.modo-edicion-precios .precio-texto{display:none}
body.modo-edicion-precios .input-precio-lote{display:inline-block}
.input-precio-lote.precio-cambiado{border-color:var(--warning); background:var(--warning-light)}
.barra-edicion-precios{
  display:none; align-items:center; gap:10px; background:var(--warning-light); border:1px solid var(--warning-border);
  border-radius:var(--radius); padding:10px 14px; margin-bottom:14px; font-size:13px; color:var(--warning);
}
body.modo-edicion-precios .barra-edicion-precios{display:flex}

/* =========================================================
   Caja / Facturación (POS)
   ========================================================= */
/* Insignia numerada para los pasos "1. Paciente", "2. Lista de precios", "3. Agregar
   pruebas" — refuerza que es un flujo guiado paso a paso, no solo títulos sueltos. */
.paso-numero{
  display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px;
  border-radius:50%; background:var(--primary); color:#fff; font-family:'Sora',sans-serif;
  font-weight:700; font-size:12.5px; flex-shrink:0; margin-right:8px;
}
.seccion-title-con-paso{display:flex; align-items:center}

.cart-row{transition:background .12s ease; border-radius:8px; margin:0 -8px; padding:10px 8px}
.cart-row:hover{background:var(--surface-2)}
.doc-type-option{transition:border-color .12s ease, background .12s ease}
.doc-type-option:hover{border-color:var(--primary)}

/* Resultados de búsqueda de paciente/prueba: ícono circular + texto, en vez de solo texto
   plano — más fácil de escanear rápido entre varios resultados. */
.search-result{display:flex; align-items:center; gap:10px}
.search-result .icono-resultado{
  width:32px; height:32px; border-radius:50%; background:var(--primary-light); color:var(--primary);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.search-result .icono-resultado svg{width:16px; height:16px}
.search-result .info-resultado{flex:1; min-width:0}

/* =========================================================
   Pacientes
   ========================================================= */
.avatar-iniciales{
  width:32px; height:32px; border-radius:50%; background:var(--primary-light); color:var(--primary-dark);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  font-family:'Sora',sans-serif; font-weight:700; font-size:13px;
}
.zona-riesgo{border:1px solid var(--danger-border); background:var(--danger-light)}
.zona-riesgo .icono-zona-riesgo{
  width:38px; height:38px; border-radius:50%; background:var(--danger); color:#fff; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
}
.zona-riesgo .icono-zona-riesgo svg{width:20px; height:20px}
.zona-riesgo .form-group input{background:var(--surface)}

/* =========================================================
   Portal del paciente (público, acceso por enlace/token)
   ========================================================= */
.portal-paciente-envoltura{max-width:640px; margin:0 auto; padding:28px 18px 40px}
.portal-paciente-header{text-align:center; margin-bottom:20px}
.portal-paciente-logo{max-height:56px; max-width:100%; object-fit:contain}
.tarjeta-paciente-nombre{display:flex; align-items:center; gap:14px; margin-bottom:18px}

.visita-portal-paciente{margin-bottom:14px; transition:box-shadow .15s ease}
.visita-portal-paciente:hover{box-shadow:var(--shadow-lg)}
.visita-portal-paciente-header{display:flex; justify-content:space-between; align-items:flex-start; gap:10px;
  padding-bottom:10px; margin-bottom:8px; border-bottom:1px solid var(--border)}
.lista-examenes-visita{display:flex; flex-direction:column; gap:8px}
.fila-examen-visita{display:flex; align-items:center; gap:10px}
.icono-examen-visita{
  width:28px; height:28px; border-radius:8px; background:var(--primary-light); color:var(--primary);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.icono-examen-visita svg{width:15px; height:15px}

/* Pestañas para alternar entre "por fecha específica" y "por rango" en vez de tener los
   dos formularios apilados uno encima del otro todo el tiempo. */
.filtro-tabs{display:flex; gap:4px; margin-bottom:14px; border-bottom:1px solid var(--border)}
.filtro-tab-btn{
  background:none; border:none; padding:8px 14px; font-size:13px; font-weight:600; color:var(--muted);
  border-bottom:2px solid transparent; cursor:pointer; margin-bottom:-1px;
}
.filtro-tab-btn.active{color:var(--primary); border-color:var(--primary)}
.filtro-form{display:flex; gap:10px; align-items:flex-end; flex-wrap:wrap}

/* Tarjeta de "línea de tiempo": una por fecha de visita, con todos los exámenes de ese día
   adentro — más natural para revisar la evolución de un paciente que una tabla plana. */
.tarjeta-linea-tiempo{margin-bottom:14px; transition:box-shadow .15s ease}
.tarjeta-linea-tiempo:hover{box-shadow:var(--shadow-lg)}
.tarjeta-linea-tiempo-header{display:flex; justify-content:space-between; align-items:baseline;
  padding-bottom:10px; margin-bottom:8px; border-bottom:1px solid var(--border)}

/* Categorías de exámenes: flechas para reordenar + punto de color para identidad visual */
.btn-flecha-orden{
  background:var(--surface-2); border:1px solid var(--border); border-radius:5px; width:22px; height:20px;
  font-size:10px; line-height:1; cursor:pointer; color:var(--ink);
}
.btn-flecha-orden:hover:not(:disabled){background:var(--primary-light); border-color:var(--primary)}
.btn-flecha-orden:disabled{opacity:.3; cursor:default}
.punto-categoria{width:10px; height:10px; border-radius:50%; flex-shrink:0}

/* Botón de WhatsApp reutilizable (antes repetido como estilo en línea en varias pantallas) */
.btn-whatsapp{color:#25D366; border:1px solid #25D366; background:#fff}
.btn-whatsapp:hover{background:#25D366; color:#fff}

/* Fila de tabla clicable (navega al detalle al hacer clic en cualquier parte) */
.fila-clicable{cursor:pointer}
.fila-clicable:hover{background:var(--surface-2)}

/* =========================================================
   Inventario
   ========================================================= */
.btn-expandir-movimiento{display:inline-flex; align-items:center; gap:5px}
.btn-expandir-movimiento svg{width:13px; height:13px; transition:transform .15s ease}
.btn-expandir-movimiento.abierto svg{transform:rotate(180deg)}
.titulo-con-icono{display:flex; align-items:center; gap:8px}
.titulo-con-icono .icono-titulo{
  width:30px; height:30px; border-radius:8px; background:var(--primary-light); color:var(--primary);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.titulo-con-icono .icono-titulo svg{width:16px; height:16px}

/* Cita de HOY resaltada en la agenda, para ubicarla de un vistazo entre varios días */
.fila-cita-hoy{background:var(--primary-light)}
.fila-cita-hoy:hover{background:var(--accent-light)}

/* Marco para previsualizar firma/sello en la lista de laboratoristas — fondo blanco con
   borde sutil, para que las imágenes con transparencia (firma sobre nada) se vean bien
   sin importar el tema oscuro/claro de la página. */
.marco-firma-sello{
  display:inline-flex; align-items:center; justify-content:center; background:#fff;
  border:1px solid var(--border); border-radius:8px; padding:4px 8px;
}
.marco-firma-sello img{height:28px; display:block}

/* Aviso de "sesión por expirar" — overlay centrado, por encima de todo */
.modal-sesion-aviso{
  position:fixed; inset:0; background:rgba(16,38,42,.45); z-index:9999;
  display:flex; align-items:center; justify-content:center; padding:20px;
}
.modal-sesion-aviso-caja{
  background:var(--surface); border-radius:var(--radius-lg); padding:22px; max-width:420px;
  display:flex; gap:14px; align-items:flex-start; box-shadow:var(--shadow-lg);
}

/* =========================================================
   Inventario
   ========================================================= */
/* Barra pequeña que muestra el stock actual en relación al mínimo configurado — verde si
   hay bastante margen, ámbar cerca del mínimo, roja si ya está en o por debajo del mínimo. */
.stock-barra-wrap{width:90px; height:6px; border-radius:3px; background:var(--surface-2); overflow:hidden; margin-top:4px}
.stock-barra{height:100%; border-radius:3px; transition:width .2s ease}
.stock-barra.ok{background:var(--success)}
.stock-barra.medio{background:var(--warning)}
.stock-barra.bajo{background:var(--danger)}
.mov-row{ display:none }
.mov-row.mostrar{ display:table-row }


/* ---------- Franja de respaldo del panel ----------
   Un clic para descargar el respaldo y guardarlo en una memoria o disco externo, con la
   fecha del último a la vista: la pregunta de todos los días es "¿ya respaldé?". El borde
   se pone ámbar cuando el respaldo no es de hoy. */
.franja-respaldo{display:flex; align-items:center; justify-content:space-between; gap:var(--esp-4); flex-wrap:wrap}
.franja-respaldo-titulo{
  display:flex; align-items:center; gap:var(--esp-2);
  font-family:'Sora',sans-serif; font-weight:600; font-size:var(--texto-md); color:var(--ink);
}
.franja-respaldo-titulo svg{width:18px; height:18px; color:var(--primary); flex-shrink:0}
.franja-respaldo-detalle{font-size:var(--texto-sm); color:var(--muted); margin-top:2px}
@media (max-width:560px){
  .franja-respaldo{align-items:stretch}
  .franja-respaldo .btn{width:100%}
}


/* Zona destructiva plegada: la restauración reemplaza TODA la base, así que no puede
   quedar a la vista junto al botón de respaldar, que es de uso diario. Se define aquí y
   no dentro de una plantilla para que el estado plegado no dependa de que esa plantilla
   traiga sus propios estilos. */
.zona-peligrosa{display:none}
.zona-peligrosa.mostrar{display:block}


/* ---------- Encabezado de página ----------
   Convivían tres formas distintas de <h1> entre plantillas: pelado, con flex e íconos, y
   con tamaño fijo en línea. Un solo componente da continuidad al pasar de una pantalla a
   otra, que es donde más se nota la falta de sistema. */
.encabezado-pagina{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--esp-4); flex-wrap:wrap; margin-bottom:var(--esp-4);
}
.encabezado-pagina h1{
  display:flex; align-items:center; gap:var(--esp-3);
  margin:0; font-size:var(--texto-xl); line-height:1.25;
}
.encabezado-pagina h1 svg{width:22px; height:22px; color:var(--primary); flex-shrink:0}
.encabezado-pagina .subtitulo{font-size:var(--texto-sm); color:var(--muted); margin-top:2px}
.encabezado-pagina .acciones{display:flex; gap:var(--esp-2); flex-wrap:wrap}

/* ---------- Densidad compacta de tabla ----------
   La densidad normal (11px de padding) es cómoda para revisar. En las pantallas
   operativas —cola de espera, resultados pendientes— lo que importa es ver cuántas cosas
   faltan sin desplazar, así que ahí se usa una variante más apretada. */
.tabla-compacta thead th{padding:7px 12px}
.tabla-compacta tbody td{padding:7px 12px}


/* Totales acumulados como línea discreta al pie del estado del día: son contexto de
   fondo, no algo que pida acción. Ocupaban dos tarjetas completas mostrando números que
   casi nunca cambian. */
.linea-totales{
  display:flex; align-items:center; gap:var(--esp-2); flex-wrap:wrap;
  margin-top:var(--esp-3); font-size:var(--texto-sm); color:var(--muted);
}
.linea-totales strong{color:var(--ink); font-weight:600}
.linea-totales a{color:var(--muted); text-decoration:none}
.linea-totales a:hover{color:var(--primary)}


/* Valor de la captura anterior del mismo paciente, debajo del campo. Discreto por defecto:
   es contexto, no una alerta. Solo se resalta cuando el salto es grande. */
.valor-anterior{
  font-size:var(--texto-xs); color:var(--muted); margin-top:3px; line-height:1.35;
}
.valor-anterior strong{color:var(--ink)}
.valor-anterior .delta{color:var(--muted-2, var(--muted))}
.valor-anterior--salto{
  color:var(--warning); font-weight:600;
  background:var(--warning-light); border-radius:4px; padding:2px 6px; display:inline-block;
}
.valor-anterior--salto strong, .valor-anterior--salto .delta{color:var(--warning)}


/* Selector de resultado del cultivo y su texto editable, en una sola línea: es un
   solo dato (el resultado), no dos pasos. */
/* Selector de resultado del cultivo y su texto editable. El campo necesita ancho
   MÍNIMO propio: con solo flex:1, en una pantalla angosta se comprimía hasta quedar
   inusable y parecía que no se podía escribir. Y flex-wrap deja que baje a la línea
   siguiente en vez de espachurrarse. */
.fila-resultado-cultivo{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.fila-resultado-cultivo select{ min-width:200px; }
.fila-resultado-cultivo .texto-cultivo-negativo{
  flex:1 1 280px; min-width:280px; padding:8px 10px;
}


/* Paginador con números. Va centrado y con aire arriba para separarlo de la tabla. */
.paginador{
  display:flex; justify-content:center; align-items:center; gap:6px;
  margin-top:var(--esp-4); flex-wrap:wrap;
}
.paginador .pagina-enlace,
.paginador .pagina-actual{
  min-width:32px; height:32px; padding:0 8px;
  display:inline-flex; align-items:center; justify-content:center;
  border-radius:var(--radius); font-size:var(--texto-sm); text-decoration:none;
}
.paginador .pagina-enlace{
  border:1px solid var(--border); color:var(--ink); background:var(--surface);
}
.paginador .pagina-enlace:hover{ border-color:var(--primary); color:var(--primary); }
/* La página actual no es un enlace: se marca sólida para que el ojo la encuentre sin buscar. */
.paginador .pagina-actual{
  background:var(--primary); color:#fff; font-weight:600;
}
.paginador .pagina-salto{ color:var(--muted-2); padding:0 2px; }
.paginador .paginador-total{ font-size:var(--texto-xs); margin-left:8px; }


/* Listado de documentos emitidos: filas compactas.
   Cada celda apila dos líneas (tipo sobre número, avatar junto al nombre) y con el
   relleno normal la fila llegaba a 59px — en una pantalla de portátil solo entraban 8
   documentos y el resto quedaba fuera de vista. Bajando el relleno y ajustando el
   avatar entran cerca de 12 sin perder legibilidad. */
.tabla-documentos tbody td{ padding:5px 14px; }
.tabla-documentos .avatar-iniciales{ width:24px; height:24px; }
.tabla-documentos tbody tr{ line-height:1.25; }

/* ═══════════════════════════════════════════════════════════════════════════════
   MOVIMIENTO

   Regla que sigue todo lo de abajo: el movimiento explica algo o no va. Nada gira,
   rebota ni parpadea por adorno. Cada transición responde a una de estas preguntas:

     ¿de dónde salió esto?      → lo nuevo entra desde algún sitio
     ¿esto responde al tacto?   → lo pulsable reacciona al pasar y al pulsar
     ¿qué acaba de cambiar?     → lo que se actualiza se señala una vez
     ¿está trabajando?          → lo que tarda lo dice

   Duraciones cortas (120–260 ms). Por encima de ~300 ms el sistema se siente lento,
   y esto es una herramienta que se usa cientos de veces al día: lo que hoy parece
   elegante, a la centésima vez estorba.

   La regla global de `prefers-reduced-motion` de más arriba desactiva todo esto para
   quien pida menos movimiento; no hace falta repetirla en cada bloque.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── Curvas y tiempos, en un solo sitio ─────────────────────────────────────── */
:root{
  --mov-rapido: 120ms;
  --mov-normal: 180ms;
  --mov-lento:  260ms;
  /* Sale rápido y frena al llegar: se siente físico sin rebotar. */
  --mov-curva:  cubic-bezier(.2,.7,.3,1);
}

/* ── 1. Lo que aparece, entra ───────────────────────────────────────────────── */
@keyframes mov-entrar{
  from{ opacity:0; transform:translateY(6px) }
  to  { opacity:1; transform:none }
}
/* Las tarjetas del panel entran escalonadas: se lee de arriba abajo, como se mira. */
.seccion-dashboard{ animation:mov-entrar var(--mov-lento) var(--mov-curva) both }
.seccion-dashboard:nth-of-type(2){ animation-delay:40ms }
.seccion-dashboard:nth-of-type(3){ animation-delay:80ms }
.seccion-dashboard:nth-of-type(4){ animation-delay:120ms }

/* El menú de opciones sale del botón, no aparece de la nada. */
.menu-opciones-lista{ transform-origin:top right }
.menu-opciones.abierto .menu-opciones-lista{
  animation:mov-desplegar var(--mov-rapido) var(--mov-curva) both;
}
@keyframes mov-desplegar{
  from{ opacity:0; transform:scale(.96) translateY(-4px) }
  to  { opacity:1; transform:none }
}
@media (max-width:760px){ .menu-opciones-lista{ transform-origin:top left } }

/* ── 2. Lo pulsable responde ────────────────────────────────────────────────── */
.btn{
  transition:background var(--mov-rapido) ease,
             border-color var(--mov-rapido) ease,
             box-shadow var(--mov-rapido) ease,
             transform 60ms ease;
}
/* Se hunde al pulsar: confirma el toque antes de que llegue la respuesta del servidor. */
.btn:active{ transform:translateY(1px) }

/* Las filas y tarjetas que llevan a otra pantalla se levantan al pasar por encima. */
.card[onclick], tr[onclick], .tarjeta-clicable{
  transition:transform var(--mov-rapido) var(--mov-curva),
             box-shadow var(--mov-rapido) ease;
}
.card[onclick]:hover, .tarjeta-clicable:hover{
  transform:translateY(-2px); box-shadow:var(--shadow-lg, 0 10px 28px rgba(0,0,0,.10));
}
/* En pantalla táctil no hay «pasar por encima»: el efecto se queda pegado tras tocar. */
@media (hover:none){
  .card[onclick]:hover, .tarjeta-clicable:hover{ transform:none; box-shadow:inherit }
}

/* El foco del teclado aparece de golpe, sin transición: quien navega con Tab necesita
   verlo YA, no dentro de 180ms. */
:focus-visible{ transition:none }

/* ── 3. Lo que cambia se señala ─────────────────────────────────────────────── */
/* Un solo destello, del color de la marca. Para cuando algo se acaba de guardar o
   recalcular y hace falta saber DÓNDE miró el cambio. */
@keyframes mov-destello{
  0%  { background:rgba(46,155,214,.16) }
  100%{ background:transparent }
}
.recien-cambiado{ animation:mov-destello 900ms ease-out both }

/* ── 4. Lo que tarda, lo dice ───────────────────────────────────────────────── */
/* El botón ocupado deja de aceptar toques y lo muestra, para que nadie pulse dos veces
   y emita dos documentos. */
.btn.cargando{ opacity:.75; cursor:progress; pointer-events:none }

/* Barra de progreso indeterminada en la cabecera, para esperas de red. */
.barra-progreso{
  position:fixed; top:0; left:0; right:0; height:2px; z-index:9998;
  background:transparent; overflow:hidden; display:none;
}
.barra-progreso.activa{ display:block }
.barra-progreso::after{
  content:""; position:absolute; inset:0; width:40%;
  background:linear-gradient(90deg, transparent, var(--primary), transparent);
  animation:mov-progreso 1.1s ease-in-out infinite;
}
@keyframes mov-progreso{
  from{ transform:translateX(-100%) } to{ transform:translateX(350%) }
}

/* ── 5. Detalles de formulario ──────────────────────────────────────────────── */
input, select, textarea{
  transition:border-color var(--mov-rapido) ease, box-shadow var(--mov-rapido) ease;
}
/* Un campo rechazado se sacude una vez: el mensaje de error puede quedar fuera de la
   vista, la sacudida no. */
@keyframes mov-sacudir{
  0%,100%{ transform:translateX(0) }
  25%{ transform:translateX(-4px) }
  75%{ transform:translateX(4px) }
}
.campo-invalido{ animation:mov-sacudir 220ms ease-in-out }

/* Los bloques plegables abren con suavidad en vez de saltar. */
details > summary{ transition:color var(--mov-rapido) ease }
details[open] > *:not(summary){ animation:mov-entrar var(--mov-normal) var(--mov-curva) both }

/* Franja de ambiente de pruebas: presente pero discreta. Antes era un bloque naranja a
   todo el ancho, lo más llamativo de cada pantalla — y un aviso permanente que grita
   deja de leerse en una semana. */
.franja-pruebas{ margin:0 0 var(--esp-4) }
.franja-pruebas > summary{
  cursor:pointer; list-style:none; display:flex; align-items:center; gap:8px;
  font-size:var(--texto-xs); font-weight:600; letter-spacing:.06em; text-transform:uppercase;
  color:#B45309; padding:5px 0;
}
.franja-pruebas > summary::-webkit-details-marker{ display:none }
/* Un punto ámbar en vez de un icono grande: identifica sin gritar. */
.franja-pruebas > summary::before{
  content:""; width:7px; height:7px; border-radius:50%; background:#D97706; flex-shrink:0;
}
.franja-pruebas p{
  margin:6px 0 0; padding:10px 12px; border-left:3px solid #D97706;
  background:#FEF6EC; color:#7C4A0A; font-size:var(--texto-sm); border-radius:0 8px 8px 0;
}

/* Los campos de fecha muestran el formato del NAVEGADOR, no el del sistema: en un Chrome
   en inglés salen mm/dd/aaaa aunque aquí se lea dd/mm. No se puede cambiar desde la
   página, así que esta clase permite rotularlo donde el orden importe. */
.campo-fecha-rotulado{ position:relative }
.campo-fecha-rotulado::after{
  content:"dd/mm/aaaa"; position:absolute; right:34px; top:50%; transform:translateY(-50%);
  font-family:'JetBrains Mono',monospace; font-size:9.5px; color:var(--muted);
  pointer-events:none; opacity:.75;
}
