/* estilo.css — BRIEF-08 §6. Adaptado de arquitectura/cardioinfos_pantalla.html,
   sin los elementos de voz/dictado (fuera de alcance, ver BRIEF-09). */

:root {
    --bg: #11151b;
    --panel: #171d25;
    --panel2: #1c232c;
    --borde: #2a323d;
    --texto: #dbe2ea;
    --texto2: #8a95a3;
    --verde: #3fb950;
    --naranja: #d99a1e;
    --rojo: #ef5350;
    --blue: #4d9fd6;

    /* BRIEF-30: azul eléctrico, pedido por el PO para «Salir». Vive acá y no dentro de la regla
       para que la paleta siga teniendo un solo lugar. Es a propósito MÁS saturado que `--blue`:
       tiene que distinguirse de «Abrir caso», que está al lado. */
    --azul-electrico: #2f8bff;

    /* BRIEF-09.4 §1 -- `--ancho-visor` ya no existe. El 09.3 se había contradicho a sí mismo
       (§2 pedía ≈14 % y §7.5 ≈33 %) y quedó en esta variable justamente por no elegir en
       silencio. El 09.4 no elige el número: elimina la pregunta. No hay visor fijo, así que
       no hay ancho que repartir -- las miniaturas son la única presencia permanente de las
       imágenes y el resto es informe. */
    --ancho-thumbs: 104px;
}

* { box-sizing: border-box; }

/* BRIEF-09.5 §3a: el alto de la barra superior se MIDE, no se supone. Antes `.grid` restaba
   46 px fijos a `100vh` mientras `.top` medía 46,4 px reales -- el documento desbordaba 0,4 px,
   aparecía una barra de scroll vertical y el viewport útil caía de 1440 a 1425. Con `body` como
   columna flex, `.top` ocupa lo que necesita y `.grid` toma el resto exacto: el número mágico
   desaparece y el defecto no puede volver aunque la barra cambie de alto (que es justo lo que
   el §3b la obliga a hacer al envolver). */
body {
    margin: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    color: var(--texto);
    font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
    font-size: 14px;
}

button {
    font-family: inherit;
    cursor: pointer;
}

/* BRIEF-09.5 §3b: la barra envuelve. Sin `flex-wrap` los 9 campos se apretaban hasta que
   `#estadoPill` se salía 40 px por la derecha y arrastraba scroll horizontal a toda la página.
   Ahora, cuando no entran, bajan de renglón: la barra crece en alto -- que es gratis porque el
   §3a dejó de suponer que mide 46 px -- y nunca crece en ancho. El `row-gap` es más chico que
   el de columna a propósito: dos renglones separados 16 px se leen como dos barras distintas. */
.top {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 16px;
    padding: 8px 14px;
    background: var(--panel);
    border-bottom: 1px solid var(--borde);
}

.top select, .top input {
    background: var(--panel2);
    border: 1px solid var(--borde);
    color: var(--texto);
    padding: 4px 8px;
    border-radius: 4px;
}

.top .campo { display: flex; align-items: center; gap: 4px; }
.top .campo label { color: var(--texto2); font-size: 12px; }
.top .campo input { width: 60px; }

/* BRIEF-10.4.1 §3.4: `.estado-pill` se eliminó junto con la píldora del encabezado. No queda
   ningún elemento con esa clase; dejar la regla sería invitar a que alguien la reviva sin el
   diagnóstico que explica por qué se fue. */

/* BRIEF-09.5 §3a (segunda mitad): `flex: 1` toma el alto que sobra después de `.top`, sea cual
   sea. `min-height: 0` es imprescindible: sin él un ítem flex no baja de su tamaño de contenido
   y la grilla empujaría el `body` más allá de la pantalla, que es el mismo desborde con otro
   disfraz. Con él, `#thumbs` y `.rep` vuelven a hacer su propio scroll interno. */
.grid {
    display: grid;
    grid-template-columns: var(--ancho-thumbs) 1fr;
    flex: 1;
    min-height: 0;
}

#thumbs {
    overflow-y: auto;
    border-right: 1px solid var(--borde);
    padding: 6px;
}

.th {
    position: relative;
    margin-bottom: 6px;
    border: 2px solid transparent;
    border-radius: 4px;
    cursor: pointer;
    overflow: hidden;
}

.th.act { border-color: var(--blue); }
.th img { display: block; width: 100%; }

.dot {
    position: absolute;
    top: 3px;
    right: 3px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
}
.dot.v { background: var(--verde); }
.dot.n { background: var(--naranja); }
.dot.r { background: var(--rojo); }

/* BRIEF-09.4 §1: el visor a pantalla completa. `position:fixed` sobre todo lo demás, fuera
   del grid -- el informe queda intacto abajo, con su scroll y su plegado, y volver a él no
   requiere restaurar nada (§4 punto 6). El fondo es opaco, no translúcido: acá se leen
   milímetros en el panel del ecógrafo y una trama por detrás molesta. */
.visor {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: #05070a;
    display: flex;
    flex-direction: column;
    padding: 10px 14px 6px;
}
.visor.hidden { display: none; }

.visor-barra {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-bottom: 8px;
}

.visor-barra .zbtn { padding: 4px 12px; font-size: 14px; line-height: 1; }
.visor-sep { width: 18px; }
.visor-contador { font-size: 12px; color: var(--texto2); min-width: 92px; text-align: center; }

.viewer-canvas {
    position: relative;
    flex: 1;
    min-height: 0;
    overflow: hidden;
    border: 1px solid var(--borde);
    background: #05070a;
    cursor: grab;
}

.viewer-canvas.dragging { cursor: grabbing; }

.viewer-canvas img {
    position: absolute;
    top: 0;
    left: 0;
    max-width: none;
    max-height: none;
    transform-origin: 0 0;
    user-select: none;
    -webkit-user-drag: none;
}

#vname { color: var(--texto2); margin-top: 6px; font-size: 12px; text-align: center; }

.rep {
    border-left: 1px solid var(--borde);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

/* BRIEF-09.6 §1: a la izquierda. Con el panel ocupando casi toda la pantalla (09.4 §1), contra
   el borde derecho quedaban a más de un metro de pantalla del contenido que gobiernan. El
   `padding` lateral iguala al de `.rep-body` para que el borde izquierdo del primer botón caiga
   en la misma vertical que el resto del informe. */
.repbar {
    display: flex;
    justify-content: flex-start;
    gap: 8px;
    padding: 8px 14px;
    border-bottom: 1px solid var(--borde);
    background: var(--panel);
    /* BRIEF-30, corrección posterior: la barra se queda arriba mientras el informe scrollea.
       `.rep` hace su propio scroll (BRIEF-09.5 §3a) y esta barra iba dentro como `static`, así
       que se iba de la vista con el contenido. BRIEF-09.3 §3 y BRIEF-22.1 habían tratado el
       síntoma dos veces, duplicando en el pie un botón cada vez; esto trata la causa y cubre a
       los cinco de una. El `background` opaco de arriba es lo que hace que el contenido pase por
       DEBAJO y no se lea encima: no está de adorno. `z-index: 1` alcanza para ganarle al cuerpo
       del informe y queda muy por debajo del visor (60) y de los popups (50), que deben seguir
       tapándola. */
    position: sticky;
    top: 0;
    z-index: 1;
}

.btn {
    background: var(--panel2);
    border: 1px solid var(--borde);
    color: var(--texto);
    padding: 6px 12px;
    border-radius: 4px;
}
.btn.pri { background: var(--blue); border-color: var(--blue); color: #0b1117; font-weight: 600; }

/* BRIEF-30, decisión del PO: «Salir» en azul eléctrico.
   Contradice explícitamente lo que él mismo había pedido un momento antes ("el estilo neutro que
   la app ya tenga, sin color nuevo") y roza BRIEF-09.3 §3, que reserva el celeste para la acción
   principal de cada bloque. Queda anotado en el AUDIT §9.6; se aplica porque es su decisión y es
   reversible borrando esta regla y el token.
   Dos cosas se conservan de lo anterior, y no son cosméticas:
   - El color va en un token de `:root`, no como hex suelto acá. La paleta sigue viviendo en un
     solo lugar, que es lo que el pedido anterior protegía.
   - NO es `--blue`. «Abrir caso» está pegado al lado y es `.btn.pri`; si los dos usaran el mismo
     celeste, el botón que abre un estudio y el que mata la sesión serían indistinguibles.
   Texto oscuro como en `.btn.pri`, por la misma razón: sobre un fondo saturado y claro, el
   contraste con `#0b1117` es 5,7:1 y con blanco sería 3,4:1 -- no alcanza para texto normal. */
#btnSalir {
    background: var(--azul-electrico);
    border-color: var(--azul-electrico);
    color: #0b1117;
    font-weight: 600;
}

.rep-body { padding: 10px 14px; }

/* BRIEF-09.6 §3: acá vivía `.hdr`, el bloque de encabezado de pantalla. Se fue entero con la
   tabla que lo usaba: sus 10 filas repetían lo que ya está en la barra superior (código, edad,
   peso, talla, SC) o eran datos administrativos que van al PDF y no a la pantalla donde Miguel
   decide qué informar. Ver el comentario de renderEstudio() en app.js. */

/* BRIEF-09.5 §1: las 8 secciones en dos columnas cuando hay ancho, en una sola cuando no.
   `auto-fit` con un mínimo en vez de una media query porque el que decide no es el ancho de la
   ventana sino el que le queda a este panel -- y ese depende de la columna de miniaturas, que
   podría cambiar. Con la media query habría que recalcular el punto de corte a mano cada vez;
   así, se ajusta moviendo un solo número.
   El mínimo de 460 px está elegido para que a 1000 px de ventana no entren dos (2×460+20 = 940 >
   los ~867 útiles) y a 1440 sí (de ~1307 útiles; tres tampoco: 3×460+40 = 1420). Cada hijo es un
   `.seccion` completo, así que una sección nunca queda repartida entre columnas.
   `align-items: start` para que una sección corta no se estire al alto de la larga de al lado.
   BRIEF-09.6 §2: el hueco entre columnas baja de 24 a 20 px. Poco, a propósito: ahora que las
   etiquetas van alineadas a la derecha (ver `table.filas`), el borde izquierdo de la columna 2
   queda dentado, y un hueco demasiado angosto la pegaría a los valores de la columna 1. */
#secciones {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(460px, 1fr));
    gap: 18px 20px;
    align-items: start;
}

/* El margen superior del título lo pone ahora el `row-gap`. Si lo dejáramos, las secciones de la
   primera fila arrancarían 18 px más abajo que el resto del panel y las dos columnas no
   empezarían parejas. */
.seccion > .sec-titulo { margin-top: 0; }

.sec-titulo {
    font-size: 13px;
    color: var(--texto2);
    text-transform: uppercase;
    letter-spacing: .04em;
    margin: 18px 0 6px;
    border-bottom: 1px solid var(--borde);
    padding-bottom: 4px;
}

/* BRIEF-09.6 §2: el valor pegado a la etiqueta que nombra, no en el extremo opuesto.
   Antes: la columna de etiquetas era el 45% fijo (285 px) y el valor arrancaba recién ahí, a
   159 px promedio del final del texto -- "Mitral" quedaba a 250 px de su número.
   El arreglo NO es alinear el valor a la izquierda pegado a cada etiqueta: los largos van de
   34 a 236 px y los números quedarían en zigzag, que es justo lo que la baranda del brief
   prohíbe. Se alinea la ETIQUETA a la derecha: así todas terminan en la misma vertical, el
   valor arranca a una distancia constante y chica, y la columna de números sigue leyéndose de
   arriba abajo de un vistazo.
   `width: 1%` + `nowrap` hace que la columna se encoja al ancho de la etiqueta más larga en vez
   de quedar clavada en el 45%; el ancho que sobra queda del lado del valor, donde entran la
   marca de corregido y el tag de motivo.
   El tamaño de fuente NO se toca: 13 px es el piso que fijó el PO (Miguel lee esto todo el día).
   La única compactación vertical es 4->3 px de padding, que sobre 38 filas son ~76 px. */
table.filas { width: 100%; border-collapse: collapse; font-size: 13px; }
table.filas td { padding: 3px 8px; border-bottom: 1px solid var(--borde); }
table.filas td.etiqueta {
    color: var(--texto2);
    width: 1%;
    white-space: nowrap;
    text-align: right;
}
table.filas td.val { position: relative; }
table.filas td.val.ed { cursor: pointer; }
table.filas td.val.ed:hover { background: var(--panel2); }
table.filas td.val .vacio { color: var(--texto2); font-style: italic; }

.sem { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; }
.sem.verde { background: var(--verde); }
.sem.naranja { background: var(--naranja); }
.sem.rojo { background: var(--rojo); }

.marca { color: var(--naranja); font-size: 11px; margin-left: 6px; }

.tag {
    display: inline-block;
    font-size: 10px;
    padding: 1px 6px;
    margin-left: 6px;
    border-radius: 9px;
    background: var(--panel2);
    color: var(--blue);
    border: 1px solid var(--borde);
}

#chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 0; }

.chip {
    border: 1px solid var(--borde);
    background: var(--panel2);
    color: var(--texto);
    border-radius: 12px;
    padding: 4px 10px;
    font-size: 12px;
}
.chip.sust { border-color: var(--verde); color: var(--verde); }
.chip.parc { border-color: var(--naranja); color: var(--naranja); }
.chip.sin { border-color: var(--texto2); color: var(--texto2); }

.pendiente-nota {
    font-size: 12px;
    color: var(--texto2);
    border: 1px dashed var(--borde);
    border-radius: 4px;
    padding: 8px;
}

.advertencia-contradiccion {
    font-size: 12px;
    color: var(--naranja);
    border: 1px solid var(--naranja);
    border-radius: 4px;
    padding: 8px;
    margin-top: 8px;
}
.advertencia-contradiccion p { margin: 2px 0; }

/* BRIEF-08.5 §5: cada línea de conclusión es un recuadro individual, mismo lenguaje
   visual que .chip (frases con coherencia, arriba) -- borde suave, fondo panel2. */
#lineasConclusion { display: flex; flex-direction: column; gap: 6px; padding: 8px 0; }

.linea-concl {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    border: 1px solid var(--borde);
    background: var(--panel2);
    border-radius: 6px;
    padding: 6px 10px;
}

.linea-concl .texto {
    flex: 1;
    white-space: pre-wrap;
    cursor: text;
}

.linea-concl .origen {
    font-size: 10px;
    color: var(--texto2);
    white-space: nowrap;
    margin-top: 2px;
}

.linea-concl .x {
    background: none;
    border: none;
    color: var(--texto2);
    font-size: 14px;
    line-height: 1;
    padding: 0 2px;
}
.linea-concl .x:hover { color: var(--rojo); }

.texto-edicion {
    flex: 1;
    background: var(--panel);
    border: 1px solid var(--blue);
    color: var(--texto);
    border-radius: 4px;
    padding: 4px 6px;
    font: inherit;
    resize: vertical;
    min-height: 1.4em;
    outline: none;
}

/* BRIEF-09.1 §5: el micrófono convive con el campo de escritura -- fila flex, el input
   ocupa el espacio disponible y el botón queda al lado.
   BRIEF-09.4 §2: el orden lo fija el HTML (micrófono primero). Acá lo único que hace falta
   es `min-width: 0`: sin eso el input no baja de su ancho intrínseco (~177 px) y al achicar
   la ventana la fila desborda en vez de encogerse, que es justo lo que el §4 punto 8 mide. */
.linea-nueva { margin-top: 4px; display: flex; align-items: center; gap: 6px; }
.linea-nueva input {
    flex: 1;
    min-width: 0;
    background: var(--panel2);
    border: 1px solid var(--borde);
    border-radius: 4px;
    padding: 6px 8px;
    color: var(--texto);
    outline: none;
}
.linea-nueva input:focus { border-color: var(--blue); }

/* BRIEF-09.3 §4: el micrófono era un emoji (🎤) -- se veía mal y desentonaba con el resto
   de los íconos. Ahora es SVG inline, dibujado con `currentColor`: los tres estados siguen
   siendo cambios de `color` sobre el botón y el ícono los hereda sin una regla extra. */
.btn-mic {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--panel2);
    border: 1px solid var(--borde);
    color: var(--texto);
    border-radius: 4px;
    padding: 6px 10px;
    line-height: 1;
    cursor: pointer;
}
.btn-mic:hover { border-color: var(--blue); }
.ico-mic { display: block; width: 16px; height: 16px; }
/* Grabando: corte explícito por botón (§5) -- el cambio de color tiene que ser inequívoco. */
.btn-mic.grabando { background: var(--rojo); border-color: var(--rojo); color: #0b1117; }
.btn-mic.transcribiendo { background: var(--panel2); border-color: var(--blue); color: var(--blue); opacity: .7; cursor: default; }

/* BRIEF-09.2 §5: el botón pulsa con el nivel de voz. `--nivel` (0..1) lo escribe medirNivel()
   en app.js desde un AnalyserNode sobre el mismo stream del MediaRecorder. La transición es
   corta a propósito: si fuera lenta el pulso iría atrasado respecto de la voz y confundiría
   más de lo que confirma. Sin --nivel (o sin grabar) el valor por defecto es 0 y no escala. */
.btn-mic.grabando {
    --nivel: 0;
    transform: scale(calc(1 + var(--nivel) * 0.35));
    box-shadow: 0 0 calc(var(--nivel) * 14px) rgba(255,255,255,.35);
    transition: transform .06s linear, box-shadow .06s linear;
}

.dictado-estado { font-size: 11px; color: var(--texto2); white-space: nowrap; }
.dictado-estado.grabando { color: var(--rojo); }
.dictado-estado.transcribiendo { color: var(--blue); }

/* BRIEF-09.2 §4: barra y panel del micrófono de comando. */
.comando-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.comando-rotulo { font-size: 11px; color: var(--texto2); }

.comando-panel {
    border: 1px solid var(--borde);
    border-radius: 4px;
    background: var(--panel2);
    padding: 8px;
    margin-bottom: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.comando-entendido { font-size: 13px; }
.comando-nota { font-size: 11px; color: var(--texto2); }
/* Naranja, el mismo color que ya usan las advertencias de contradicción y el cartel de
   pendientes: es un aviso, no un error -- el informe se completó igual (§4). */
.comando-aviso { font-size: 12px; color: var(--naranja); }
.comando-opciones { display: flex; flex-wrap: wrap; gap: 6px; }
.comando-ofrecidas { display: flex; flex-wrap: wrap; gap: 6px; }

/* BRIEF-09.3 §1: la vía muda. Botones de grupo al lado del micrófono -- misma escalera,
   con el dedo. Se pintan desde el catálogo (GET /api/comando/grupos): hoy hay uno solo y
   no se agregan los otros vacíos, porque mostrar botones que no hacen nada es mostrar
   promesas en vez de producto. Van a la derecha del rótulo para que la barra se lea
   "comando: por voz o por acá".

   SIN `margin-left: auto` (corregido en la validación visual del propio 09.3): con el panel
   derecho angosto de antes el margen automático se notaba poco, pero el §2 lo ensanchó a ~74 %
   y el botón se fue a 928 px del micrófono, en la punta opuesta de la barra. El §1 pide que
   esté *al lado* del micrófono, y a 928 px la vía muda deja de leerse como la alternativa de
   la voz. Es el estado el que se va a la derecha, no los grupos. */
.comando-grupos { display: flex; flex-wrap: wrap; gap: 6px; }
#comandoEstado { margin-left: auto; }

/* BRIEF-09.3 §2: cabecera plegable de la tabla de mediciones. Se lee como el resto de los
   títulos de sección (.sec-titulo) porque es uno -- lo único que agrega es el triángulo y
   que se puede tocar. */
.sec-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    background: none;
    border: none;
    border-bottom: 1px solid var(--borde);
    color: var(--texto2);
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: .04em;
    text-align: left;
    margin: 18px 0 6px;
    padding: 0 0 4px;
}
.sec-toggle:hover { color: var(--texto); }
.sec-toggle .caret { transition: transform .12s linear; }
.sec-toggle[aria-expanded="false"] .caret { transform: rotate(-90deg); }

/* BRIEF-09.3 §3: el segundo "Generar PDF", donde Miguel termina de revisar y da el OK.
   BRIEF-09.5 §2: se cae el `width: 100%; padding: 10px` que lo estiraba de lado a lado. Un botón
   del ancho del panel se lee como el eje de la pantalla, y ésta es la última acción, no la
   principal. Queda del tamaño de cualquier botón y pegado a la izquierda -- que sale solo, porque
   `.pdf-pie` es un bloque y el botón es inline: arranca en el mismo borde que "Vaciar todo".
   Conserva el celeste de `.btn.pri`: sigue siendo la acción principal de su bloque. */
.pdf-pie { margin-top: 14px; }

.concl-tools {
    display: flex;
    gap: 8px;
    margin-top: 6px;
}

.edin {
    width: 70px;
    background: var(--panel2);
    border: 1px solid var(--blue);
    color: var(--texto);
    padding: 2px 4px;
    border-radius: 3px;
}

.overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 50;
}
.overlay.hidden { display: none; }

.popup {
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: 6px;
    padding: 16px;
    min-width: 280px;
}
.popup p { margin: 0 0 12px; }
.popup .fila { display: flex; gap: 8px; }
.popup .fila button { flex: 1; }

#printv .sheet { background: #fff; color: #111; padding: 24px; max-width: 720px; margin: 24px auto; }
#printv table { width: 100%; border-collapse: collapse; }
#printv td, #printv th { border: 1px solid #ccc; padding: 4px 6px; font-size: 12px; }
.firm { margin-top: 24px; font-size: 12px; }

#confirmarPdf .popup { max-width: 420px; }
#confirmarPdfBody p { color: var(--naranja); font-size: 13px; margin: 4px 0; }

/* BRIEF-10 §5: barra de progreso de la carga de un caso. Avanza por imagen con lo que
   informa el back; la transición corta es para que el salto entre pasos no se vea a tirones,
   no para simular avance -- el ancho siempre refleja trabajo ya hecho. */
.barra {
    height: 8px;
    background: var(--panel2);
    border: 1px solid var(--borde);
    border-radius: 4px;
    overflow: hidden;
    margin: 12px 0 6px;
}
.barra-relleno {
    height: 100%;
    width: 0;
    background: var(--blue);
    transition: width .12s linear;
}
.barra-texto { font-size: 12px; color: var(--texto2); margin-bottom: 12px; }

/* La fila de la ruta necesita separación del bloque de botones de abajo, que reusa .fila. */
#dlgCaso .fila { margin-bottom: 10px; }
#dlgCaso input[type="text"] {
    background: var(--panel2);
    border: 1px solid var(--borde);
    color: var(--texto);
    padding: 5px 7px;
    border-radius: 3px;
    font-size: 13px;
}

/* BRIEF-10.1 §4: ancho propio para el campo de nombre. `.top .campo input { width: 60px }`
   está escrito para Peso y Talla (números de cuatro dígitos) y el campo de nombre lo heredaba:
   42 px usables, siete caracteres. El dato nunca se truncó -- estaba completo en base, API,
   PDF e `input.value` -- pero en pantalla se veía `Villafa`. 22ch entra un nombre de 25
   caracteres con holgura, y `ch` y no px porque la unidad correcta para "cuántos caracteres
   entran" es el ancho del carácter, no un número de píxeles que hay que recalcular si cambia
   la fuente. */
.top .campo input#nombrePaciente { width: 22ch; }

/* El selector de sexo (§1) al lado de los números: lo justo para "Femenino". */
.top .campo select#sexo { min-width: 108px; }

/* El botón que dispara el input[type=file] oculto (§3): un <label> tiene que verse y
   comportarse como los demás botones de la fila. */
#dlgCaso label.btn { cursor: pointer; text-align: center; }

/* BRIEF-10.2 §1: el aviso de bloqueo dejaba de verse. Era `.pendiente-nota` -- 12 px, gris,
   borde punteado -- para lo que IMPIDE que el sistema clasifique. Tres niveles, y el peso
   visual sigue a la consecuencia real, no al hecho de que algo falte.
   Sin estridencias (pedido explícito del brief): color y borde, nada de parpadeos ni íconos
   grandes. Miguel va a ver esto muchas veces por día. */
.aviso {
    font-size: 13px;
    border-radius: 4px;
    padding: 8px 10px;
    margin-bottom: 6px;
    border: 1px solid transparent;
}
.aviso:last-child { margin-bottom: 0; }

/* Crítico: sin el sexo no se clasifica NADA. Es el único que se lee como alerta. */
.aviso-critico {
    color: var(--texto);
    background: rgba(239, 83, 80, .12);
    border-color: var(--rojo);
    font-weight: 600;
}
/* Advertencia: falta peso/talla -- solo se pierden los indexados, el resto clasifica igual. */
.aviso-advertencia {
    color: var(--texto);
    background: rgba(217, 154, 30, .10);
    border-color: var(--naranja);
}
/* Informativo: no hay nada que Miguel pueda hacer (motor pediátrico, confirmación de rama,
   carotídeo). BRIEF-10.4.1 §3.8: iba en gris con borde punteado y se leía como texto plano --
   el PO lo comprobó sobre Carrizo, donde estos dos avisos pasaban desapercibidos mientras el
   cartel de frases, que dice la MISMA causa, saltaba a la vista por su borde ámbar.
   Eso contesta la pregunta que el §3.4 había dejado abierta al eliminar la píldora: sin
   resalte no se detecta de un vistazo. La píldora vieja mentía, pero se notaba.
   Ahora comparte el tratamiento ámbar de `.aviso-advertencia`. Que no haya nada que hacer no
   significa que no haya nada que ver: el estudio igual está bloqueado.

   Es un cambio PURAMENTE VISUAL. `severidad` sigue valiendo `informativo` en el modelo, y la
   distinción semántica entre "no puedo trabajar" y "hallazgo leve" espera al campo `clase`
   (bloqueo/hallazgo) que quedó decidido en §3.7.1 y NO se adelanta acá. El día que exista,
   estas dos reglas pueden volver a divergir. */
.aviso-informativo {
    color: var(--texto);
    background: rgba(217, 154, 30, .10);
    border-color: var(--naranja);
}

.aviso-accionable { cursor: pointer; }
.aviso-accionable:hover { filter: brightness(1.15); }
.aviso-accionable:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* El campo que falta se destaca mientras esté vacío, y vuelve a normal al completarse (§1).
   Ámbar y no rojo: el rojo ya lo usa el aviso de arriba, y dos rojos compiten entre sí. */
.top .campo .campo-falta,
.top .campo select.campo-falta {
    border-color: var(--naranja);
    box-shadow: 0 0 0 1px var(--naranja);
}

/* BRIEF-10.3 §3: cada campo del color de SU alerta. En 10.2 iban todos en ámbar para no poner
   dos rojos que compitieran; el PO decidió lo contrario -- rojo el sexo, ámbar peso y talla --
   y es más simple de leer: el campo y su cartel dicen lo mismo, sin que haya que explicarlo. */
.top .campo .campo-critico,
.top .campo select.campo-critico {
    border-color: var(--rojo);
    box-shadow: 0 0 0 1px var(--rojo);
}
.top .campo .campo-advertencia,
.top .campo select.campo-advertencia {
    border-color: var(--naranja);
    box-shadow: 0 0 0 1px var(--naranja);
}

/* BRIEF-10.3 §1: la señal de que se guardó. Aparece y se va sola -- que Miguel vea que pasó
   algo, sin un cartel que haya que cerrar. */
.guardado-aviso {
    font-size: 12px;
    color: var(--verde);
    opacity: 0;
    transition: opacity .15s;
    min-width: 64px;
}
.guardado-aviso.visible { opacity: 1; }
.guardado-aviso.guardado-error { color: var(--rojo); }

/* BRIEF-08.6: el drawer de mediciones crudas. Tres columnas para que la etiqueta del equipo,
   el valor y la nota se lean en vertical y no como prosa corrida. Las lecturas sin equivalente
   en el catálogo van con el ámbar que YA existe (`--naranja`, el mismo de `.aviso-advertencia`);
   no se agrega un color nuevo para no abrir una tercera convención de severidad. */
.crudas-resumen {
    font-size: 12px;
    color: var(--texto2);
    margin: 0 0 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--borde);
}
.crudas-fila {
    display: grid;
    grid-template-columns: 150px 90px 1fr;
    gap: 8px;
    font-size: 12px;
    margin: 2px 0;
    align-items: baseline;
}
.crudas-etiqueta { font-family: monospace; }
.crudas-valor { text-align: right; }
.crudas-nota { color: var(--texto2); }
.crudas-sin-reconocer .crudas-nota { color: var(--naranja); }
.crudas-sin-reconocer .crudas-etiqueta { color: var(--naranja); }
.crudas-titulo2 { margin-top: 14px; border-top: 1px solid var(--borde); padding-top: 10px; }
.crudas-procedencia .crudas-nota { color: var(--texto2); }

/* BRIEF-15 §3.1: la clasificación clínica, ahora legible al lado del valor. SIN COLOR a
   propósito -- ver el comentario de `renderFila` en app.js: pintarla exigiría decidir qué
   clasificación es buena y cuál mala en las seis escalas, y eso es autoría clínica. Usa
   `--texto2` (el mismo gris de las notas) para no competir con el número, que sigue siendo lo
   primero que se lee. */
.clasif {
    color: var(--texto2);
    font-size: 11px;
    margin-left: 8px;
}

/* §3.3: la leyenda. Los puntos reusan `.sem`, así que si algún color cambia, cambia acá solo. */
.leyenda-sem {
    font-size: 11px;
    color: var(--texto2);
    margin: 2px 0 8px;
    line-height: 1.5;
}
.leyenda-sem .sem { margin-left: 4px; }

/* BRIEF-18: la procedencia del valor y los otros métodos del mismo concepto. Mismo gris que
   `.clasif` -- no compiten con el número, que sigue siendo lo primero que se lee. La referencia
   va en cursiva para que se distinga de la procedencia del valor principal a simple vista. */
.metodo {
    color: var(--texto2);
    font-size: 11px;
    margin-left: 8px;
}
.referencia {
    color: var(--texto2);
    font-size: 11px;
    font-style: italic;
    margin-left: 8px;
}

/* --- BRIEF-22: vista previa del informe ------------------------------------------------ */
/* La hoja imita el papel: fondo claro y ancho de A4, porque lo que se ve acá es lo que se
   imprime. El resto de la aplicación es oscura -- esta vista NO, a propósito: si la preview
   tuviera el tema de la pantalla, Miguel estaría aprobando algo distinto de lo que sale. */
#preview .sheet {
    background: #fff;
    color: #111;
    width: 210mm;
    max-width: 96vw;
    max-height: 92vh;
    overflow-y: auto;
    padding: 14mm 16mm;
    border-radius: 4px;
}

.preview-barra {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin-bottom: 10mm;
}

/* BRIEF-28: el logo ocupa el ancho de la hoja y conserva su proporción -- `height: auto` es
   lo que garantiza que no se deforme cuando el PO reemplace la imagen por una de mayor
   calidad (§2 del brief), sin tocar CSS. `display: block` evita el hueco que el navegador
   deja debajo de una imagen inline por la línea base del texto: son 4-5 px que en una hoja
   apretada contra el límite de BRIEF-27 no hay por qué regalar. */
.preview-logo { display: block; width: 100%; height: auto; margin: 0 0 4mm; }

.preview-titulo { font-size: 20px; margin: 0 0 6mm; }
.preview-seccion { font-size: 14px; margin: 6mm 0 2mm; }

.preview-tabla { width: 100%; border-collapse: collapse; }
.preview-tabla td {
    border: 1px solid #999;
    padding: 3px 6px;
    font-size: 12px;
    vertical-align: top;
}
.preview-tabla td:first-child { width: 65%; }

.preview-conclusion { margin: 0 0 4px; font-size: 12px; min-height: 1em; }

/* Imprimir la HOJA, no la aplicación. Sin esto, `window.print()` saca la pantalla de trabajo
   entera -- barra, miniaturas, semáforos -- que es justo lo que el informe no debe mostrar.
   `visibility` y no `display:none`: el subárbol de #hojaPreview tiene que seguir maquetando. */
@media print {
    body * { visibility: hidden; }
    #hojaPreview, #hojaPreview * { visibility: visible; }
    #hojaPreview {
        position: absolute;
        inset: 0;
        margin: 0;
        width: auto;
        max-width: none;
        max-height: none;
        overflow: visible;
        border-radius: 0;
        padding: 0;
    }
    /* los botones son de la pantalla, no del papel */
    .preview-barra { display: none; }
    #preview.overlay { position: static; background: none; display: block; }
}

/* --- BRIEF-30: pantalla de login ------------------------------------------------------- */
/* Reusa `.overlay` y `.popup`, que ya existen para los diálogos: un login que se ve distinto
   al resto de la aplicación parece de otro sistema, y eso es justo lo que no se quiere en la
   pantalla donde se escribe la contraseña. */
.login-caja { min-width: 320px; max-width: 360px; }
.login-titulo { margin: 0 0 4px; font-size: 20px; }
.login-sub { margin: 0 0 18px; color: var(--tenue, #8a94a6); font-size: 13px; }
.login-label { display: block; margin: 10px 0 4px; font-size: 12px; color: var(--tenue, #8a94a6); }
.login-input {
    width: 100%; box-sizing: border-box; padding: 9px 10px; font-size: 14px;
    border-radius: 5px; border: 1px solid var(--borde); background: var(--fondo, #11151c);
    color: var(--texto);
}
.login-input:focus { outline: none; border-color: var(--acento, #4a9eff); }
.login-boton { width: 100%; margin-top: 16px; padding: 10px; font-size: 14px; }
.login-error {
    margin: 12px 0 0; padding: 8px 10px; font-size: 13px; border-radius: 5px;
    color: var(--texto); background: rgba(239, 83, 80, .12); border: 1px solid var(--rojo, #ef5350);
}
/* La regla de ocultado va CON ALCANCE, como `.visor.hidden` y `.overlay.hidden`: en esta hoja
   no existe un `.hidden` global, y suponer que sí dejaba la caja de error visible y vacía al
   cargar la pantalla -- se vio en la primera validación por clics. */
.login-error.hidden { display: none; }
