:root{
  /* ===== TOKENS ===== */
  --bg-0:#0a0e0f;
  --bg-1:#10161a;
  --bg-2:#161e22;
  --bg-3:#1d272c;
  --bg-elevated:#212c31;
  --line:#28343a;
  --line-strong:#3a484f;

  --text-hi:#eaf2f1;
  --text-mid:#9fb4b3;
  /* Subido de #6b7f80: aquel daba 4.32:1 sobre --bg-1 y 3.38:1 sobre
     --bg-elevated, por debajo del mínimo AA (4.5:1). Es el color de casi todos
     los labels, horarios, unidades y textos de estado vacío (357 usos). */
  --text-low:#849697;

  --signal:#36e1c4;       /* radar/sonar cyan-green — acento primario */
  --signal-dim:#1d6e60;
  --signal-bg:rgba(54,225,196,0.08);

  --warn:#f0a93f;
  --warn-bg:rgba(240,169,63,0.10);
  --crit:#ef4b4b;
  --crit-bg:rgba(239,75,75,0.12);
  /* Relleno para los botones críticos con texto BLANCO encima (dar la alarma,
     confirmar evacuación, colgar). No se puede usar --crit para eso: #fff sobre
     --crit da 3.63:1. Pero --crit tampoco se puede oscurecer, porque además se
     usa como COLOR DE TEXTO sobre fondos oscuros y ahí perdería contraste. Por
     eso son dos tokens: uno para texto, otro para relleno. */
  --crit-solid:#c62f2f;
  --ok:#5fd28a;
  --ok-bg:rgba(95,210,138,0.10);

  --port:#5b8fd1;          /* azul para Prefectura/puerto */
  --vessel:#c98ad6;        /* lila para barcos */

  --font-ui:'Inter',-apple-system,sans-serif;
  --font-data:'JetBrains Mono',monospace;

  --radius-sm:6px;
  --radius-md:10px;
  --shadow-soft:0 8px 24px rgba(0,0,0,0.35);
}

/* Modo claro: mismas variables, reemplazadas por completo cuando el body
   tiene la clase .light-theme. Como prácticamente todo el resto del CSS de
   este archivo usa var(--xxx) en vez de colores fijos, alcanza con
   redefinir estos tokens acá para que la interfaz entera cambie de tema, sin
   tener que tocar cada estilo en línea uno por uno. */
body.light-theme{
  --bg-0:#eef1f2;
  --bg-1:#ffffff;
  --bg-2:#f2f4f5;
  --bg-3:#e6eaec;
  --bg-elevated:#ffffff;
  --line:#dde3e5;
  --line-strong:#c3cccf;

  /* Los acentos del modo claro se oscurecieron: este es el tema que se usa con
     sol en pantalla y era el que PEOR cumplía contraste. Como texto sobre los
     fondos claros daban 2.8-3.5:1 (por debajo incluso del mínimo de 3:1 para
     UI), y eso hacía fallar los cuatro badges de estado, que son los que
     codifican severidad clínica. Los valores nuevos superan 4.5:1. */
  --text-hi:#101819;
  --text-mid:#48585b;
  --text-low:#5f6d6f;      /* era #7c8b8d → 3.54:1 */

  --signal:#07705f;        /* era #0d9a85 → 3.51:1 */
  --signal-dim:#0a7d6c;
  --signal-bg:rgba(7,112,95,0.09);

  --warn:#8a5410;          /* era #c07a1f → 3.47:1 */
  --warn-bg:rgba(138,84,16,0.10);
  --crit:#b8302f;          /* era #d43f3f → 4.00:1 (y el badge crit fallaba) */
  --crit-bg:rgba(184,48,47,0.10);
  --crit-solid:#b8302f;    /* en claro alcanza el mismo: #fff encima da >4.5:1 */
  --ok:#1e7845;            /* era #2f9e5d → 3.40:1 */
  --ok-bg:rgba(30,120,69,0.10);

  --port:#3f72b3;
  --vessel:#a259b5;

  --shadow-soft:0 8px 24px rgba(20,30,32,0.14);
}

*{box-sizing:border-box; margin:0; padding:0;}
html,body{
  background:var(--bg-0);
  color:var(--text-hi);
  font-family:var(--font-ui);
  height:100%;
  overflow:hidden;
}
body{
  font-size:14px;
  line-height:1.5;
}
::selection{background:var(--signal-dim); color:#fff;}
::-webkit-scrollbar{width:8px; height:8px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:var(--line-strong); border-radius:4px;}
::-webkit-scrollbar-thumb:hover{background:var(--text-low);}

button{font-family:inherit; cursor:pointer; border:none; background:none; color:inherit;}

/* Un hijo flex con `flex:1` NO puede encoger por debajo de su contenido, porque
   su min-width implícito es `auto`. Es la causa silenciosa de casi todos los
   recortes: la conversación "empujaba" y desbordaba el layout en vez de
   adaptarse. Declararlo acá lo arregla de raíz para los contenedores de a pares
   (lista + detalle) en vez de ir parcheando anchos uno por uno. */
#mensajeria-layout > section,
#flota-layout > #map-canvas,
#admin-chats-split > #admin-chats-msgs{ min-width:0; }

/* Estado DESHABILITADO visible. Antes no existía ninguna regla :disabled, así
   que los 16 botones que se deshabilitan mientras envían (incluido "Dar la
   alarma" de hombre al agua) quedaban idénticos a uno activo y con el cursor en
   manito: con señal satelital lenta, el capitán los tocaba una y otra vez sin
   saber que la acción ya había salido. */
button:disabled, button[disabled], [aria-disabled="true"]{
  opacity:.45;
  cursor:not-allowed;
  pointer-events:none;
}

/* Foco visible. No había NINGUNA regla de foco en la app y sí 12 `outline:none`
   sin reemplazo, así que al navegar con teclado no se veía dónde se estaba
   parado. :focus-visible sólo se activa con teclado, no al hacer clic con el
   mouse, así que no ensucia la interfaz táctil. */
:where(button, a, input, select, textarea, [tabindex]):focus-visible{
  outline:2px solid var(--signal);
  outline-offset:2px;
  border-radius:var(--radius-sm);
}
input,textarea{font-family:inherit; color:inherit;}
a{color:var(--signal); text-decoration:none;}

/* ===== APP SHELL ===== */
#app{
  display:grid;
  grid-template-columns:72px 1fr;
  height:100dvh;
  width:100vw;
}

/* ===== RAIL (nav lateral) ===== */
#rail{
  background:var(--bg-1);
  border-right:1px solid var(--line);
  display:flex;
  flex-direction:column;
  align-items:center;
  padding:16px 0;
  gap:4px;
  z-index:50;
}
.rail-logo{
  width:40px; height:40px;
  border-radius:9px;
  background:var(--signal);
  display:flex; align-items:center; justify-content:center;
  margin-bottom:20px;
  flex-shrink:0;
}
.rail-logo svg{width:22px; height:22px;}
.rail-btn{
  width:48px; height:48px;
  border-radius:var(--radius-sm);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:4px;
  color:var(--text-low);
  transition:background .15s, color .15s;
  position:relative;
}
.rail-btn i{font-size:19px;}
.rail-btn span{font-size:9px; font-weight:500; letter-spacing:.02em;}
.rail-btn:hover{background:var(--bg-2); color:var(--text-mid);}
.rail-btn.active{color:var(--signal); background:var(--signal-bg);}
.rail-btn.active::before{
  content:'';
  position:absolute; left:-12px; top:50%; transform:translateY(-50%);
  width:3px; height:22px; background:var(--signal); border-radius:2px;
}
.rail-btn .dot-badge{
  position:absolute; top:4px; right:8px;
  width:8px; height:8px; border-radius:50%;
  background:var(--crit);
  border:2px solid var(--bg-1);
}
.rail-spacer{flex:1;}
.rail-status{
  display:flex; flex-direction:column; align-items:center; gap:6px;
  padding-top:12px; border-top:1px solid var(--line);
  width:100%;
}
.rail-status .pulse-dot{width:8px; height:8px; border-radius:50%; background:var(--ok); box-shadow:0 0 0 0 rgba(95,210,138,.6); animation:pulseRing 2s infinite;}
@keyframes pulseRing{
  0%{box-shadow:0 0 0 0 rgba(95,210,138,.5);}
  70%{box-shadow:0 0 0 6px rgba(95,210,138,0);}
  100%{box-shadow:0 0 0 0 rgba(95,210,138,0);}
}
@keyframes pulseBtn{
  0%,100%{box-shadow:0 0 0 0 rgba(239,75,75,.5);}
  50%{box-shadow:0 0 0 6px rgba(239,75,75,0);}
}
@keyframes shakeLogin{
  0%,100%{transform:translateX(0);}
  20%{transform:translateX(-8px);}
  40%{transform:translateX(7px);}
  60%{transform:translateX(-5px);}
  80%{transform:translateX(3px);}
}

/* ===== MAIN VIEWS ===== */
#main{
  position:relative;
  overflow:hidden;
  display:flex;
  flex-direction:column;
}
.view{
  display:none;
  flex-direction:column;
  height:100%;
  width:100%;
  animation:viewIn .25s ease;
}
.view.active{display:flex;}
@keyframes viewIn{from{opacity:0; transform:translateY(6px);} to{opacity:1; transform:translateY(0);}}

/* ===== TOPBAR común ===== */
.topbar{
  height:56px;
  flex-shrink:0;
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:0 20px;
  border-bottom:1px solid var(--line);
  background:var(--bg-1);
}
.topbar-title{display:flex; align-items:center; gap:10px;}
.topbar-title h1{font-size:15px; font-weight:600; letter-spacing:.01em;}
.topbar-title .sub{font-size:12px; color:var(--text-low); font-family:var(--font-data);}
.topbar-actions{display:flex; align-items:center; gap:10px;}

/* ===== Badges / chips reutilizables ===== */
.badge{
  display:inline-flex; align-items:center; gap:5px;
  font-size:11px; font-weight:600; letter-spacing:.02em;
  padding:3px 8px; border-radius:5px;
  font-family:var(--font-ui);
}
.badge.sim{background:var(--bg-3); color:var(--text-mid); border:1px dashed var(--line-strong);}
.badge.live{background:var(--signal-bg); color:var(--signal);}
.badge.warn{background:var(--warn-bg); color:var(--warn);}
.badge.crit{background:var(--crit-bg); color:var(--crit);}
.badge.ok{background:var(--ok-bg); color:var(--ok);} /* antes era un rgba fijo que no cambiaba con el tema */

/* Chip para plegar/desplegar una sección (resumen de flota). Alto de toque
   cómodo y el ícono gira para indicar el estado. */
.chip-toggle{
  display:inline-flex; align-items:center; gap:6px;
  min-height:32px; padding:5px 10px;
  background:var(--bg-2); border:1px solid var(--line-strong);
  border-radius:20px; color:var(--text-mid);
  font-size:11px; font-weight:600;
}
.chip-toggle:hover{ background:var(--bg-3); color:var(--text-hi); }
.chip-toggle i{ transition:transform .18s ease; }
.chip-toggle[aria-expanded="false"] i{ transform:rotate(-90deg); }

/* Ficha de hombre al agua PLEGADA: queda sólo lo que no se puede perder de
   vista -quién es y cuánto lleva en el agua-. Se ocultan las partes
   secundarias del reloj (barra, ventana estimada, detalle) para que la
   tarjeta no siga tapando el mapa, que en celular mide poco más de un tercio
   del alto. Al desplegarla vuelve todo. */
#mob-ficha[data-plegada="1"] [data-rs-extra]{ display:none; }
#mob-ficha[data-plegada="1"] [data-rs]{ padding:8px 11px; margin-bottom:0; }
@media (max-width:767.98px){
  /* En celular la ficha se ajusta al ancho disponible y nunca pasa de la mitad
     del mapa, así siempre queda mapa visible detrás. */
  /* Desplegada, la ficha nunca pasa de dejar ~130px de mapa: con menos, el punto
     del náufrago no entra en la franja libre y termina debajo de la tarjeta.
     El contenido que no entra se recorre dentro de la propia ficha. */
  #mob-ficha{ width:auto !important; left:10px !important; right:10px !important;
              max-height:calc(100% - 130px) !important; }
  #mob-ficha[data-plegada="1"]{ max-height:52% !important; }
}
.badge i{font-size:12px;}

.simlabel{
  font-size:10px; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--text-low);
  display:inline-flex; align-items:center; gap:4px;
}
.simlabel i{font-size:12px; color:var(--warn);}
/* Los badges "Simulado" siempre están pegados al borde derecho de su barra
   superior, así que su tooltip se alinea a la derecha (en vez de centrado)
   para no salirse de la pantalla por ese lado. */
.simlabel[data-tip]:hover::after{ left:auto; right:0; transform:none; }

/* Tooltip simple. Aparece DEBAJO del elemento (no arriba): así nunca queda
   tapado por la barra de direcciones del navegador ni cortado por el borde
   superior de la ventana, que era el problema real cuando se abría hacia
   arriba en elementos ya pegados al techo de la página (barras superiores). */
[data-tip]{position:relative;}
[data-tip]:hover::after{
  content:attr(data-tip);
  position:absolute; top:calc(100% + 8px); left:50%; transform:translateX(-50%);
  background:var(--bg-elevated); color:var(--text-hi);
  font-size:11px; padding:6px 10px; border-radius:6px;
  white-space:normal; max-width:220px; line-height:1.4; text-align:left;
  box-shadow:var(--shadow-soft); z-index:200;
  border:1px solid var(--line-strong);
}
/* Variante para elementos pegados al borde derecho de su contenedor (badges
   "Simulado", botones de video/llamada en el header del chat): el tooltip
   se alinea a la derecha en vez de centrarse, para no salirse de la
   pantalla por ese lado. */
.tip-r[data-tip]:hover::after{
  left:auto; right:0; transform:none;
}
/* Variante LATERAL: el tooltip sale a la DERECHA del elemento y centrado en
   vertical, en vez de abajo. Es para los botones de zoom del mapa, que viven en
   la esquina INFERIOR IZQUIERDA: ahí cualquier tooltip que abra hacia abajo cae
   fuera del contenedor del mapa -que recorta con overflow:hidden- y el texto se
   ve cortado. Hacia la derecha hay todo el ancho del mapa libre.
   Se fuerza una sola línea porque son etiquetas cortas y así no se encima con
   los botones de arriba y abajo. */
.tip-side[data-tip]:hover::after{
  top:50%; left:calc(100% + 8px); right:auto;
  transform:translateY(-50%);
  white-space:nowrap; max-width:none;
}
/* Variante para elementos pegados al borde INFERIOR de la pantalla (los
   controles de la videollamada: micrófono, cámara, evacuación, cortar):
   el tooltip abre hacia ARRIBA en vez de abajo, ya que abajo no queda
   espacio dentro de la ventana y el texto se corta. */
.tip-up[data-tip]:hover::after{
  top:auto; bottom:calc(100% + 8px);
}

/* Videollamada: los dos feeds (el remoto y el propio) intercambian entre
   pantalla completa y una miniatura arrastrable, tocando la miniatura -mismo
   patrón que WhatsApp-. Se usan clases con !important porque ambos
   contenedores también tienen estilos en línea de base (display:flex,
   overflow:hidden, etc.) que deben permanecer sin tocar. */
.call-video-full{
  position:absolute !important; inset:0 !important;
  width:auto !important; height:auto !important;
  top:0 !important; left:0 !important; right:0 !important; bottom:0 !important;
  border-radius:0 !important; border:none !important;
  z-index:1 !important; cursor:default !important; box-shadow:none !important;
}
.call-video-pip{
  position:absolute !important;
  width:260px !important; height:190px !important;
  border-radius:14px !important; border:1.5px solid var(--line-strong) !important;
  z-index:15 !important; cursor:pointer !important;
  box-shadow:0 8px 26px rgba(0,0,0,0.5) !important;
  touch-action:none !important; user-select:none !important;
}

/* Scroll containers */
.scroll-y{overflow-y:auto;}

/* Botón de fijar/desfijar un chat (estilo WhatsApp). Aparece tenue al pasar el
   mouse por la conversación; en los chats fijados queda siempre visible y en
   color de acento. */
.chat-pin-btn{
  flex-shrink:0; align-self:center;
  width:28px; height:28px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  color:var(--text-low); background:none;
  opacity:0; transition:opacity .15s, background .15s;
}
.chat-item:hover .chat-pin-btn{ opacity:.55; }
.chat-pin-btn:hover{ opacity:1 !important; background:var(--bg-3); }
.chat-pin-btn.fijado{ opacity:1; color:var(--signal); }

/* ===== Panel de la médica — consulta en vivo (consola a pantalla completa) =====
   La idea es que la médica vea TODO a la vez sin scrollear: video grande +
   vitales + info a la izquierda, y el asistente IA a la derecha (con su propio
   scroll interno si el análisis es largo). En mobile se apila. */
/* El alto de la consola lo calcula el layout, no una constante. Antes era
   `height:calc(100dvh - 150px)`, y ese 150 tenía que adivinar la barra de arriba
   + el encabezado + el padding del scroller. Cuando el encabezado cambiaba de
   alto (por ejemplo al compactarse en pantallas bajas) el número dejaba de
   coincidir y la consola se pasaba de largo unos píxeles: aparecía justo el
   scroll que no queremos. Poniendo el scroller en columna, `flex:1` mide solo. */
#medico-content{ display:flex; flex-direction:column; }
.cm-split{ display:flex; gap:14px; flex:1 1 auto; min-height:470px; }
.cm-detalle-grid{ display:grid; grid-template-columns:minmax(0,1.55fr) minmax(0,1fr); gap:14px; height:100%; }
.cm-col-izq{ display:flex; flex-direction:column; gap:12px; min-height:0; }
.cm-vitales{ display:grid; grid-template-columns:repeat(5, minmax(0,1fr)); gap:10px; }
/* Columna derecha = evacuación (alto fijo, chico) + asistente clínico (todo lo
   que sobre). El reparto NO es parejo a propósito: el asistente es texto largo y
   es lo único acá que se lee de corrido. `min-height:0` en los dos es lo que
   permite que el scroller interno del asistente encoja en vez de empujar la
   página — sin eso, un análisis largo desbordaría la consola. */
.cm-col-der{ display:flex; flex-direction:column; gap:12px; min-height:0; }
.cm-ia-panel{ display:flex; flex-direction:column; min-height:0; }
/* Debajo de ~1300px el asistente IA pasa ABAJO (una columna) para que el video
   y los vitales tengan todo el ancho (5 en una fila, sin cortarse). En pantallas
   anchas (como la de la médica) va la consola de 2 columnas, sin scroll. */
@media (max-width:1300px){
  .cm-detalle-grid{ grid-template-columns:1fr; height:auto; }
  .cm-split{ flex:0 0 auto; height:auto; min-height:0; }
  /* Acá el alto pasa a ser AUTOMÁTICO, y eso rompía el asistente: con `flex:1`
     su base es 0, así que el alto de la columna lo terminaba fijando el cuadro
     de evacuación y al asistente le quedaban 9px de texto (ilegible, y sin
     forma de scrollear porque el panel entero medía 79px). En este modo la
     página SÍ scrollea, así que se le da un piso real y deja de competir. */
  .cm-ia-panel{ flex:0 0 auto; min-height:320px; }
}
/* Mismo origen, mismo síntoma que el asistente: con alto automático el video se
   quedaba en su min-height de 150px, y es lo primero que mira la médica. La
   franja va de 1025px (abajo de eso manda la regla sticky de más adelante, que
   ya le da alto propio) a 1300px. `!important` porque el alto viene inline. */
@media (min-width:1025px) and (max-width:1300px){
  #cm-video-area{ flex:0 0 auto !important; height:clamp(240px, 38vh, 380px) !important; }
}
/* ── Alto para el asistente clínico en pantallas de portátil ──────────────────
   En un monitor de 768–900px de alto la consola entra justa y al asistente le
   quedaban ~186px: ocho renglones. Como la consola NO puede scrollear (es la
   premisa: la médica ve todo de un vistazo), el alto se recupera sacando lo
   decorativo antes que lo operativo. */
@media (max-height:900px){
  /* El subtítulo repite lo que ya dice la barra de arriba ("Monitoreo de signos
     vitales"), así que en poco alto se va y la consola crece para ocupar su
     lugar (el `flex:1` de arriba reparte el hueco liberado sin que haya que
     tocar ningún número). */
  .cm-encabezado{ margin-bottom:8px; }
  .cm-encabezado-sub{ display:none; }
}
/* Entre 1301 y 1560px la consola ya es de 2 columnas, pero los seis botones de
   acción del encabezado wrappean a una segunda fila y se llevan ~45px de alto
   que le hacen falta al asistente. Compactarlos los devuelve a una sola línea.
   Los botones se pintan con `style` inline desde el JS, así que acá hace falta
   `!important` para ganarle — mismo motivo que en la regla de 430px de abajo. */
@media (min-width:1301px) and (max-width:1560px){
  .cm-head-btns > button{ font-size:11px !important; padding:7px 9px !important; gap:5px !important; }
  .cm-head-scores{ gap:9px; }
}
@media (max-width:900px){ .cm-vitales{ grid-template-columns:repeat(3, minmax(0,1fr)); } }
@media (max-width:767.98px){
  .cm-split{ flex-direction:column; }
  .cm-split > .cm-lista-col{ width:100% !important; max-height:30dvh; }
  .cm-vitales{ grid-template-columns:repeat(2, minmax(0,1fr)); }
}
/* Móvil/tablet: en la consola de la médica, el recuadro de video queda FIJO arriba
   (sticky) al scrollear los vitales/info, y vuelve a su lugar al subir. Se libera el
   overflow de #cm-detalle para que el sticky agarre el scroller real (#medico-content). */
@media (max-width:1024px){
  #cm-detalle{ overflow:visible !important; }
  #cm-video-area{ position:sticky !important; top:0; z-index:6; flex:0 0 auto !important; height:42vw; min-height:160px !important; max-height:220px; }
}
/* Header de la consola (nombre + scores NEWS2/qSOFA/Estado + botones de acción):
   en pantallas chicas se ordena en filas parejas en vez de amontonarse y wrappear
   raro. La médica usa pantalla ancha (>1300px) y mantiene el header en una línea. */
.cm-head-scores{ display:flex; align-items:center; gap:12px; }
@media (max-width:1300px){
  .cm-head{ flex-direction:column; align-items:stretch; }
  .cm-head-right{ width:100%; justify-content:space-between; }
}
@media (max-width:767.98px){
  .cm-head-right{ flex-direction:column; align-items:stretch; gap:10px; }
  .cm-head-scores{ justify-content:space-around; gap:6px; background:var(--bg-1); border:1px solid var(--line); border-radius:10px; padding:8px 4px; }
  .cm-head-scores > div{ flex:1; text-align:center !important; }
  .cm-head-btns{ width:100%; }
  .cm-head-btns > button{ flex:1 1 auto; justify-content:center; min-width:calc(33.333% - 6px); }
}
@media (max-width:430px){
  .cm-head-btns > button{ min-width:calc(50% - 5px); font-size:11px !important; padding:8px 8px !important; }
}
/* Vista previa de informes (médico · incidente SAR · admin) en celular: la
   grilla de signos vitales de 4 columnas y el padding fijo se cortan dentro del
   modal (que tiene overflow:hidden). Se colapsa a 2 columnas y se afloja. */
@media (max-width:600px){
  .doc-informe{ padding:18px 14px !important; }
  .doc-informe [style*="grid-template-columns:repeat(4"]{ grid-template-columns:repeat(2,minmax(0,1fr)) !important; }
}
/* Tira de dispositivos de la videollamada: habilitar scroll horizontal también
   en tablet (769–1024px), no solo en móvil, para que los chips no se recorten. */
@media (max-width:1024px){
  #call-devices-strip{ flex-wrap:nowrap; overflow-x:auto; justify-content:flex-start; -webkit-overflow-scrolling:touch; }
}
/* Barra inferior en pantallas muy chicas (<360px): solo íconos, sin labels, para
   que los ítems del rail no queden apretados (el badge de no-leídos se conserva). */
@media (max-width:360px){
  #rail .rail-btn span:not([id]){ display:none; }
}

/* Impresión: se oculta con display:none todo lo que no sea el contenedor
   dedicado de impresión (#informe-print-area). También hay que liberar
   explícitamente el "overflow:hidden" y "height:100%" que tiene el <body>
   para el uso normal de la app (necesarios para que la interfaz no
   scrollee como una página web común) — si no se liberan, siguen
   recortando el contenido a la altura de una sola pantalla incluso con
   todo lo demás oculto, que era la causa real de que el informe se
   cortara a una sola hoja en vez de paginarse. */
@media print{
  html, body{ height:auto !important; overflow:visible !important; }
  body > *:not(#informe-print-area){ display:none !important; }
  #informe-print-area{ display:block !important; }
}

/* ===================================================================
   RESPONSIVE: TABLET Y CELULAR
   ===================================================================
   La aplicación se diseñó originalmente para escritorio (notebook/PC), que
   es donde se usa la mayor parte del tiempo desde el puente de mando. Estas
   reglas la adaptan para que también sea usable en una tablet en cubierta o
   en el celular de un capitán, sin tocar en absoluto cómo se ve en pantallas
   grandes (todo lo de acá vive dentro de @media, por arriba de esos anchos
   no cambia nada). */

/* --- TABLET (hasta 1024px): las columnas de dos niveles pasan a una sola
   columna apilada, pero se mantiene la navegación lateral -todavía hay
   ancho de sobra para eso-. --- */
@media (max-width: 1024px){
  .medico-grid{ grid-template-columns:1fr !important; }
  #chat-info-panel{ display:none; } /* panel de info del contacto: secundario, se prioriza la conversación */
  /* En tablet vertical (iPad = 768px justos) la lista de chats se estrecha para
     que la conversación tenga aire: 280+465 no entran en los 696px útiles. */
  #mensajeria-layout > aside:first-child{ width:240px !important; }
  /* Los signos vitales pasan a 2 columnas ya en tablet, no recién en celular:
     con 4 columnas cada tarjeta queda en ~116px y la tensión arterial
     ("138/87 mmHg") no entra. Es la vista que se mira durante una consulta. */
  .vitals-grid{ grid-template-columns:repeat(2,minmax(0,1fr)) !important; }
  #flota-layout{ flex-direction:column; }
  #flota-layout > #map-canvas{ min-height:280px; }
  #flota-layout > aside{ width:100% !important; max-height:38dvh; border-left:none !important; border-top:1px solid var(--line); }
  #flota-stats-panel{ grid-template-columns:repeat(3,minmax(0,1fr)) !important; }
  .call-video-pip{ width:190px !important; height:140px !important; }
}

/* --- CELULAR (hasta 768px): el rail lateral pasa a ser una barra inferior
   fija (patrón estándar de apps móviles), y las vistas de varias columnas
   se convierten en pantallas de a una por vez, con navegación hacia atrás
   donde hace falta. --- */
@media (max-width:767.98px){
  #app{
    grid-template-columns:1fr;
    grid-template-rows:1fr auto;
    height:100dvh; /* dvh: alto real de la ventana visible en el navegador del celular, descontando barras del sistema */
  }
  html, body{ height:100dvh; }

  /* Rail → barra inferior */
  #rail{
    flex-direction:row;
    align-items:center;
    justify-content:space-around;
    padding:6px 2px;
    border-right:none;
    border-top:1px solid var(--line);
    gap:0;
    order:2;
  }
  .rail-logo{ display:none; }
  .rail-spacer{ display:none; width:0; flex:none; }
  .rail-btn{ width:auto; height:auto; padding:5px 6px; }
  .rail-btn span{ font-size:7.5px; }
  .rail-btn i{ font-size:17px; }
  .rail-btn.active::before{
    left:50%; top:auto; bottom:-6px; transform:translateX(-50%);
    width:18px; height:3px;
  }
  #btn-toggle-tema{ order:-1; }
  .rail-status{
    flex-direction:row; width:auto; padding-top:0; border-top:none; gap:5px; padding:5px 8px;
  }
  .rail-status span{ display:none; } /* solo queda el punto de estado, el texto "STARLINK" no entra */

  /* Topbars: menos padding y texto más chico para que todo entre */
  .topbar{ height:auto; min-height:50px; padding:8px 12px; flex-wrap:wrap; gap:6px; }
  .topbar-title h1{ font-size:13.5px; }
  .topbar-title .sub{ font-size:10px; }
  .topbar-actions{ gap:6px; }
  .topbar-actions .simlabel{ display:none; } /* aclaraciones de "simulado": quedan en el resto de la interfaz, acá sobran espacio */

  /* Mensajería: de a una pantalla por vez (lista o conversación), con botón
     de volver -ver renderChatWindow()/renderChatList() para la lógica-. */
  #mensajeria-layout{ position:relative; }
  #mensajeria-layout > aside:first-child{ width:100% !important; }
  #mensajeria-layout > section{ display:none !important; }
  #mensajeria-layout.mobile-chat-open > aside:first-child{ display:none !important; }
  #mensajeria-layout.mobile-chat-open > section{ display:flex !important; width:100%; }
  .chat-back-btn{ display:flex !important; }
  #chat-info-panel{ display:none !important; }

  /* Dashboard médico: todo en una sola columna, grillas más angostas */
  .medico-grid{ grid-template-columns:1fr !important; }
  .vitals-grid{ grid-template-columns:repeat(2,minmax(0,1fr)) !important; }
  #dispositivos-medicos-content{ grid-template-columns:repeat(1,1fr) !important; }

  /* Videollamada: los overlays fijos se achican para no tapar toda la
     pantalla en un celular */
  .call-video-pip{ width:120px !important; height:88px !important; }
  /* La tira de dispositivos NO se envuelve en varias líneas en mobile -se
     vuelve una sola fila con scroll horizontal propio si hace falta-, así
     su altura queda predecible y no choca con lo que va debajo (el overlay
     de duración/nombre y el widget de signos vitales), que antes se
     superponían de forma fea cuando la tira ocupaba 2 líneas. */
  #call-devices-strip{ flex-wrap:nowrap !important; overflow-x:auto !important; justify-content:flex-start !important; padding:7px 10px !important; gap:6px !important; -webkit-overflow-scrolling:touch; }
  #call-devices-strip > div{ flex-shrink:0; padding:4px 7px !important; }
  #call-devices-strip span{ font-size:9.5px !important; white-space:nowrap; }
  #call-info-overlay{ top:44px !important; left:10px !important; right:10px !important; }
  #call-info-overlay > div{ padding:7px 10px !important; gap:7px !important; }
  #call-vitals-widget{ width:150px !important; padding:9px 10px !important; top:92px !important; }
  #call-vitals-widget div[style*="font-size:16px"]{ font-size:13px !important; }
  .call-ctrl-btn{ width:42px !important; height:42px !important; }

  /* Mapa de flota: mapa y lista apilados, cada uno con su propio scroll.
     El "min-height:0" es el arreglo real acá -sin esto, un elemento flex
     dentro de otro flex no se achica más allá del tamaño de su contenido,
     así que en vez de darle scroll propio a la lista, esta empujaba todo
     el alto de la página y la volvía imposible de recorrer-. */
  #flota-layout{ flex-direction:column; min-height:0; }
  #flota-layout > #map-canvas{ min-height:34dvh; flex-shrink:0; }
  #flota-layout > aside{ width:100% !important; max-height:none; flex:1; min-height:0; border-left:none !important; border-top:1px solid var(--line); }
  #fleet-list{ min-height:0; }
  #flota-stats-panel{ grid-template-columns:repeat(2,minmax(0,1fr)) !important; }
  #vessel-detail-panel{ width:calc(100% - 24px) !important; left:12px !important; right:12px !important; }
  .vessel-panel-close{ width:34px !important; height:34px !important; } /* más fácil de tocar para salir del panel */

  /* Bandeja SAR (Prefectura): la lista pasa a ancho completo con su propio
     scroll acotado, así el detalle del incidente queda accesible sin tener que
     recorrer toda la lista primero. */
  #pref-lista{ width:100% !important; max-height:34dvh; overflow-y:auto; }

  /* Dashboard médico: el motivo real del scroll horizontal era el banner de
     alerta -como ítem de un flex-column, por defecto no se achica más allá
     del ancho de su contenido (icono + texto + hora en una sola fila) sin
     "min-width:0" explícito, así que se salía del ancho de la pantalla-.
     De paso, se compacta todo el dashboard para que entre con menos scroll
     vertical: menos separación entre paneles y tarjetas más chicas. */
  .medico-grid, .medico-grid > div{ min-width:0; }
  #alert-banner{ min-width:0; flex-wrap:wrap; padding:10px 12px; gap:6px; }
  #alert-banner > div{ min-width:0; }
  #alert-time{ font-size:9.5px !important; }
  .medico-grid{ gap:10px !important; }
  .medico-grid > div{ gap:10px !important; }
  .vital-card{ padding:10px 11px !important; }
  .vital-card .vital-value{ font-size:20px !important; }
  .vital-card svg.vital-spark{ height:20px !important; margin-top:3px !important; }

  /* Ficha del paciente: el nombre/datos y los botones de acción (historial,
     informe) competían por el mismo ancho de fila y el texto de edad/rol
     terminaba apretado en una columna angosta, partido en muchas líneas.
     Forzamos que los botones bajen a su propia fila completa en vez de
     pelear el ancho con el bloque de datos del paciente. */
  .patient-card-header{ flex-wrap:wrap; }
  .patient-card-info{ flex-basis:100%; }
  .patient-card-actions{ flex-basis:100%; justify-content:flex-start; flex-wrap:wrap; }

  /* Modales: menos padding para no perder espacio útil en pantallas chicas */
  #evac-confirm-overlay > div, #historial-overlay > div, #informe-overlay > div{ max-width:100% !important; }

  /* Panel admin y "Mi barco": menos padding lateral para ganar ancho útil. */
  #admin-content, #barco-content{ padding:14px 12px !important; }

  /* Admin · "Chats en vivo": el split lista/mensajes (por defecto dos columnas
     con una barra fija de 250px) se apila en vertical, cada parte con su propio
     scroll, para que en un celular no quede la conversación aplastada en ~90px. */
  #admin-chats-split{ flex-direction:column; height:auto !important; }
  #admin-chats-split > #admin-chats-lista{ width:100% !important; max-height:34dvh; }
  #admin-chats-split > #admin-chats-msgs{ min-height:46dvh; }
}

/* Tabler icons via CDN class fallback handled in body */
