/* ============================================================
   Armazon de la interfaz de mapa (tarea 5)
   ============================================================ */

/* ------------------------------------------------------------
   Tokens de color. UN solo juego: el tema oscuro se descarto por decision de
   Gennaro (2026-08-22) a favor de la paleta de marca de benitomartin.com.

   Los nombres son por PAPEL, no por color: --fondo-panel dice para que sirve,
   no de que color es. Eso sigue valiendo con un solo juego -- permite cambiar
   la paleta entera tocando este bloque y nada mas, que es justo lo que se hizo
   al pasar de la paleta generica a la de marca.

   Los marcadores INICIO/FIN TOKENS se mantienen tal cual: sin_colores_a_mano.sh
   los busca por texto para saber que queda dentro y que queda fuera.
   ------------------------------------------------------------ */

/* ===== INICIO TOKENS ===== */
/* ------------------------------------------------------------------
   Paleta de marca de benitomartin.com. Extraida del sitio, no inventada:
   #f7931e (naranja, 40 usos) y #252d31 (carbon, 29 usos) son los dos colores
   que mas aparecen en su CSS descontando blancos y negros.

   La restriccion que manda sobre todo el diseno esta MEDIDA:
     #f7931e sobre blanco  -> 2.30  NO sirve de texto, ni de lejos
     #f7931e sobre #252d31 -> 6.10  el naranja LUCE sobre carbon
     #252d31 sobre blanco  -> 14.02 el carbon es texto excelente

   De ahi salen las tres reglas de esta paleta:
     1. El naranja de marca es RELLENO, nunca texto.
     2. Cuando hace falta naranja en texto, va --acento-texto: el mismo tono
        con 37% menos luz, que si pasa (4.96 sobre blanco, 4.59 sobre el fondo).
     3. Lo que va sobre naranja es carbon, no blanco: blanco sobre naranja da
        2.30 y es de los errores mas comunes con colores calidos de marca.
   ------------------------------------------------------------------ */
:root {
    /* Marca, tal cual salen del sitio de Benito */
    --marca-naranja: #f7931e;
    --marca-carbon: #252d31;

    /* Superficies */
    --fondo-app: #f5f6f7;
    --fondo-panel: #ffffff;
    --fondo-panel-alt: #eef0f2;
    --fondo-flotante: rgba(255, 255, 255, 0.95);
    --fondo-marca: var(--marca-carbon);          /* la cabecera, franja de marca */

    /* Texto */
    --texto: var(--marca-carbon);                /* 14.02 sobre blanco */
    --texto-tenue: #5a6469;                      /* 5.5 sobre --fondo-app */
    --texto-invertido: #ffffff;                  /* 14.02 sobre carbon */
    --texto-sobre-acento: var(--marca-carbon);   /* 6.10 sobre naranja; NUNCA blanco */

    /* Acento: naranja de marca */
    --acento: var(--marca-naranja);              /* relleno, no texto */
    --acento-fuerte: #d97b0c;                    /* el mismo, mas oscuro, para hover */
    --acento-texto: #a85d05;                     /* la version que SI pasa como texto */
    --acento-tenue: rgba(247, 147, 30, 0.16);

    --borde: #d7dbde;
    --superficie-hover: rgba(37, 45, 49, 0.06);
    --sombra: rgba(37, 45, 49, 0.14);

    /* Estados del veredicto */
    --estado-alta: rgba(214, 40, 40, 0.92);
    --estado-baja: rgba(37, 45, 49, 0.85);
    --estado-normal: rgba(90, 100, 105, 0.9);

    /* Semanticos */
    --exito: #198754;
    --exito-fuerte: #157347;
    --advertencia: #ffc107;
    --advertencia-fuerte: #e0a800;
    --morado: #6f42c1;
    --morado-fuerte: #5a35a8;
    --peligro: #dc3545;
    --frescura-ok: #25a85c;   /* 3.20 -> 4.56 sobre el carbon de la cabecera */
    --frescura-viejo: #d57f00;   /* 3.31 -> 4.58 sobre el carbon de la cabecera */
    --frescura-error: #dd756b;   /* 2.58 -> 4.56 sobre el carbon de la cabecera */

    /* ------------------------------------------------------------------
       Escalas de datos (tarea 8): antiguedad, profundidad y magnitud colorean
       los mismos marcadores del mapa segun el selector de color (mapa.js).

       Comparten tono por casualidad de diseno -- el mismo rojo/naranja/azul
       sirve de "esto es grave" en las tres -- no por significado, asi que
       cada escala tiene su PROPIO juego de tokens en vez de uno compartido
       (--dato-1..4). Fusionarlas acoplaria las tres: tocar el rojo de
       "reciente" (antiguedad) moveria sin querer el de "superficial"
       (profundidad), aunque hoy sean el mismo numero de casualidad.

       El sufijo numerico es la posicion en la escala, de mas alarmante a mas
       neutra -- el mismo orden en que aparece en LEYENDAS_COLOR (mapa.js).
       Magnitud es la unica de las tres con un escalon extra en el rojo mas
       oscuro (>= 5.0): antiguedad y profundidad solo tienen cuatro en total,
       magnitud tiene cuatro TAMBIEN pero corridos un puesto (ver mapa.js).
       Los valores no se tocan (tarea 8, decision de Gennaro -- ver informe). */
    --dato-antiguedad-1: #d62828;   /* ultima hora */
    --dato-antiguedad-2: #f77f00;   /* hoy */
    --dato-antiguedad-3: #fcbf49;   /* esta semana */
    --dato-antiguedad-4: #8ecae6;   /* mas antiguo */

    --dato-profundidad-1: #d62828;   /* superficial, < 30 km */
    --dato-profundidad-2: #f77f00;   /* 30-70 km */
    --dato-profundidad-3: #fcbf49;   /* 70-150 km */
    --dato-profundidad-4: #8ecae6;   /* mas de 150 km */

    --dato-magnitud-1: #6a040f;   /* >= 5.0 */
    --dato-magnitud-2: #d62828;   /* 4.0 - 4.9 */
    --dato-magnitud-3: #f77f00;   /* 3.0 - 3.9 */
    --dato-magnitud-4: #8ecae6;   /* < 3.0 */

    /* ------------------------------------------------------------------
       Gravedad sismica (mapa.php: getColorMag(), boton "copiar reporte" y
       "Generar Imagenes ZIP"). No es la misma escala que --dato-magnitud-*
       de arriba: aquella colorea el MARCADOR en el mapa con cuatro escalones;
       esta describe que tan fuerte se sintio, con los cinco cortes de
       Imperceptible/Perceptible/Fuerte/Peligroso/Catastrofico (ver la leyenda
       de .tag-* mas abajo en este archivo). Coincide en valor con --exito,
       --advertencia y --peligro en tres de los cinco escalones, pero son
       tokens propios a proposito: si --exito cambia de tono porque un boton
       lo necesita, "perceptible" no tiene por que moverse con el. */
    /* El borde de cada marcador. Casi negro a proposito: separa el circulo del
       mapa sea cual sea su relleno, en las tres escalas. No es --texto ni --borde:
       esos son del cromo y cambiarlos no debe repintar el mapa. */
    --marcador-borde: #222222;

    /* Calor historico (tarea 4): sustituye a la rejilla de densidad, que tenia su
       propio token (--densidad-relleno) por la misma razon que este lo tiene ahora
       -- que el rojo de la escala de antiguedad cambie de tono no tiene por que
       mover este, aunque hoy compartan el mismo valor por casualidad de diseno.
       Es el rojo de la escala de datos actual (igual que --dato-antiguedad-1); el
       color definitivo y el fondo del mapa se deciden viendo la capa encendida con
       los 953 eventos reales, no calculando (spec SS6.2) -- este token queda listo
       para cambiar sin tocar el JS que lo consume. */
    --calor-relleno: #d62828;
    /* El punto de referencia que el visitante fija tocando el mapa. Verde azulado
       a proposito: NO pertenece a ninguna escala de datos y no debe confundirse
       con un sismo. */
    --punto-referencia: #2a9d8f;

    --gravedad-imperceptible: #adb5bd;
    --gravedad-perceptible: #198754;
    --gravedad-fuerte: #ffc107;
    --gravedad-peligroso: #fd7e14;
    --gravedad-catastrofico: #dc3545;

    /* Insignias .tag-* de la leyenda de gravedad: par fondo/texto, pastel a
       proposito para distinguirse de los colores vivos de arriba. El texto de
       --tag-fuerte-texto se oscurecio de #b85c00 a #a45200 (contraste 3.80 ->
       4.61 sobre --tag-fuerte-fondo, medido con contraste.mjs): era el unico
       par de los cinco por debajo del minimo AA de 4.5:1. */
    --tag-imperceptible-fondo: #d4edda;
    --tag-imperceptible-texto: #155724;
    --tag-perceptible-fondo: #fff3cd;
    --tag-perceptible-texto: #856404;
    --tag-fuerte-fondo: #ffe5d0;
    --tag-fuerte-texto: #a45200;
    --tag-peligroso-fondo: #f8d7da;
    --tag-peligroso-texto: #721c24;
    --tag-catastrofico-fondo: #e2d9f3;
    --tag-catastrofico-texto: #4a1b7a;
}
/* ===== FIN TOKENS ===== */

/* ------------------------------------------------------------
   Alturas del armazon: las publica medirArmazon() (mapa.js) con la altura REAL
   de cada pieza, y un ResizeObserver las republica cuando cambia.

   Los valores de aqui son solo el respaldo del primer pintado, no la verdad.
   Nada de lo que se ancla debajo puede volver a escribir un numero propio: la
   cabecera de veredicto es fixed con altura libre y crece de 42 px a 78 en
   cuanto empieza a nombrar su base -- que es lo que hara en cuanto la historia
   llegue a siete dias. Los tres "top: 64px" que habia aqui daban un solape de
   288x14 a 320 px con la cabecera hablando.

   --hueco es la separacion bajo la cabecera; los 10 px sueltos que aparecen mas
   abajo son separaciones entre dos cajas adyacentes, que si es una decision
   local y no una suposicion sobre el tamano de otro.
   ------------------------------------------------------------ */
:root {
    --cabecera-alto: 42px;
    --control-color-alto: 43px;
    --controles-alto: 0px;   /* solo cuenta en movil; en escritorio el envoltorio mide 0 */
    --hueco: 22px;
}

html, body {
    height: 100%;
    margin: 0;
    font-family: 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
}

/* El mapa ocupa todo el viewport: es la interfaz, no una pestaña mas. */
#mapa-lienzo {
    position: absolute;
    inset: 0;
}

/* ------------------------------------------------------------
   Cabecera de veredicto
   ------------------------------------------------------------ */
.veredicto {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 12px 16px;
    /* Franja de marca: carbon de benitomartin.com con texto invertido. Es lo que
       hace que la pagina se reconozca como suya de un vistazo, y ademas es donde
       el naranja de marca luce -- 6.10 de contraste sobre carbon contra 2.30 sobre
       blanco. El naranja no funciona sobre fondo claro; sobre este si. */
    background: var(--fondo-marca);
    box-shadow: 0 1px 4px var(--sombra);
    border-bottom: 3px solid var(--acento);
    font-size: 1rem;
    font-weight: 600;
    color: var(--texto-invertido);
    text-align: center;
}

/* Sin clase de estado cuando el veredicto viene sin "estado": solo el conteo,
   sobre el mismo fondo neutro. Ver Contexto::veredicto(). */
.veredicto.alta {
    background: var(--estado-alta);
    color: var(--texto-invertido);
}
.veredicto.baja {
    background: var(--estado-baja);
    color: var(--texto-invertido);
}
.veredicto.normal {
    background: var(--estado-normal);
    color: var(--texto-invertido);
}

/* ------------------------------------------------------------
   Segunda linea de la cabecera: reloj, indicador de frescura y las
   cuatro cifras (tarea 2). No se le pone altura fija a .veredicto:
   medirArmazon() (mapa.js) publica la altura real con un
   ResizeObserver y todo lo que esta debajo la sigue solo.
   ------------------------------------------------------------ */
.veredicto-linea { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.veredicto-estado { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
.cifras { display: flex; gap: 18px; margin-top: 4px; flex-wrap: nowrap; overflow: hidden; }
.cifra { display: flex; flex-direction: column; line-height: 1.15; }
.cifra-rotulo { font-size: 0.68rem; opacity: 0.75; }
.cifra-valor { font-size: 0.95rem; font-weight: 600; }
/* El valor de la cifra mas urgente --- cuando fue el ultimo --- en naranja de marca.
   Sobre el carbon de la cabecera da 6.10 de contraste. */
#ultimo { color: var(--acento); }

@media (max-width: 360px) {
    .cifra-opcional { display: none; }
    .cifras { gap: 12px; }
}

/* Los tokens de --frescura-ok/viejo/error (y el resto del cromo) viven ahora en
   el bloque INICIO/FIN TOKENS al principio del archivo (tarea 6 absorbio y
   amplio el bloque que dejo la tarea 2, sin renombrar sus marcadores). */

.frescura-ok { color: var(--frescura-ok); }
.frescura-viejo { color: var(--frescura-viejo); }
.frescura-error { color: var(--frescura-error); }

/* ------------------------------------------------------------
   Selector de color (tarea 6) y su leyenda
   ------------------------------------------------------------ */

/* En escritorio no pinta nada por si solo: cada hijo se posiciona fijo en su
   propia esquina (ver .color-control y .mapa-leyenda mas abajo). En movil
   (media query al final del archivo) es el que pasa a fijarse en pantalla,
   y los hijos sueltan su "position: fixed" propio para apilarse en flujo
   normal uno debajo del otro -- asi la leyenda nunca necesita saber cuanto
   mide el control, ni siquiera cuando este envuelve a tres filas a 320px.
   Ronda de arreglo 1 de la tarea 6: el numero fijo "top:118px" que asumia
   la altura del control se solapaba con el en cuanto el control envolvia. */

.color-control {
    position: fixed;
    top: calc(var(--cabecera-alto) + var(--hueco));
    left: 16px;
    z-index: 950;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    max-width: calc(100% - 32px);
    padding: 8px 10px;
    background: var(--fondo-flotante);
    border-radius: 8px;
    box-shadow: 0 1px 6px var(--sombra);
    font-size: 0.85rem;
}
.color-control span {
    font-weight: 600;
    color: var(--texto);
    margin-right: 2px;
}
.color-control button {
    padding: 5px 12px;
    border: 1px solid var(--borde);
    border-radius: 20px;
    background: var(--fondo-panel);
    color: var(--texto);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    transition: 0.2s;
}
.color-control button:hover {
    background: var(--fondo-panel-alt);
}
.color-control button.activo {
    background: var(--acento);
    border-color: var(--acento);
    color: var(--texto-sobre-acento);
}

/* Traduce el color de cada marcador segun el modo activo: sin esto, la
   misma paleta de tres escalas distintas confunde mas de lo que informa.

   Tarea 3: baja al inferior izquierdo (junto a lo que colorea, como Windy) y
   libera el borde derecho para el riel de navegacion de la tarea 4. Se ancla
   sobre la linea de tiempo leyendo --tiempo-alto, nunca copiando su numero
   (60 px en escritorio, 128 en movil -- copiar 60 la dejaria debajo en
   movil).

   Pero la linea de tiempo no es la unica pieza de esa franja: la tarjeta del
   ultimo sismo (mas abajo en este archivo) tambien vive ahi, y en escritorio
   comparte la MISMA esquina inferior izquierda (x=16) sin ser de ancho
   completo -- a diferencia de movil, donde es de ancho completo y no compite
   por esquina. Apilar la leyenda encima de la tarjeta (en vez de mandarla al
   inferior derecho, que es el borde que la tarea 4 necesita libre) evita esa
   pelea en los dos anchos a la vez. --tarjeta-alto la mide (mapa.js,
   medirArmazon()) y vale 0 con la tarjeta oculta, asi que sin tarjeta la
   leyenda cae sola justo encima de la linea de tiempo, sin caso especial.

   El "+ 16px" replica la separacion que la propia .tarjeta usa frente a la
   linea de tiempo en escritorio (ver su regla mas abajo); la version movil
   la redefine sin ese termino porque ahi la tarjeta queda pegada a la linea
   de tiempo (bottom: var(--tiempo-alto), sin holgura). Los 12px finales son
   la separacion propia de la leyenda frente a lo que tenga debajo. */
.mapa-leyenda {
    position: fixed;
    left: 16px;
    bottom: calc(var(--tiempo-alto) + var(--tarjeta-alto, 0px) + 16px + 12px);
    top: auto;
    right: auto;
    z-index: 950;
    max-width: 200px;
    padding: 10px 12px;
    background: var(--fondo-flotante);
    border-radius: 8px;
    box-shadow: 0 1px 6px var(--sombra);
    font-size: 0.8rem;
    color: var(--texto);
}
.mapa-leyenda strong {
    display: block;
    margin-bottom: 6px;
    font-size: 0.85rem;
}
.mapa-leyenda ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.mapa-leyenda li {
    display: flex;
    align-items: center;
    gap: 8px;
}
.leyenda-color {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1px solid var(--sombra);
    flex: none;
}

/* ------------------------------------------------------------
   Control de capas (tarea 9): densidad historica y clima, ambas apagadas
   por defecto. Mismo estilo que .color-control. En escritorio se ancla
   debajo del selector de color -- el offset se midio con Playwright contra
   la altura real de .color-control en vez de asumirla (ver tarea-9-report.md,
   la ronda de arreglo 1 de la tarea 6 ya penalizo ese atajo una vez). En
   movil entra al flujo normal como tercer hijo de #controles-superiores,
   igual que los otros dos.
   ------------------------------------------------------------ */
.capas {
    position: fixed;
    /* Debajo del selector de color, cuya altura se mide y no se supone: a 320 px
       envuelve a tres filas. */
    top: calc(var(--cabecera-alto) + var(--hueco) + var(--control-color-alto) + 10px);
    left: 16px;
    z-index: 950;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    max-width: calc(100% - 32px);
    padding: 8px 10px;
    background: var(--fondo-flotante);
    border-radius: 8px;
    box-shadow: 0 1px 6px var(--sombra);
    font-size: 0.85rem;
    color: var(--texto);
}
.capas label {
    display: flex;
    align-items: center;
    gap: 5px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

/* Procedencia/aviso de la capa de calor (tarea 4): un solo elemento, insertado por
   capas.js dentro de #capas (mapa.php no se toca). Oculto por defecto -- la capa
   arranca apagada -- para que medir.mjs, que nunca la enciende, no lo vea nunca:
   sigue midiendo #capas con su tamano de siempre. width:100% lo manda a su propia
   linea dentro del flex-wrap del contenedor, debajo de la casilla. */
.calor-estado {
    display: none;
    width: 100%;
    margin-top: 2px;
    font-size: 0.72rem;
    font-weight: 400;
    line-height: 1.3;
    color: var(--texto-tenue);
}
.calor-estado.visible { display: block; }
/* El aviso (complemento bloqueado, 503) se distingue de la procedencia por color,
   no solo por texto: --peligro es el mismo tono que ya usa el resto del sitio para
   "algo fallo" (ver .alerta-emergente). */
.calor-estado.aviso { color: var(--peligro); font-weight: 600; }

/* En telefono el control de color y las capas se apilan en flujo normal
   dentro de #controles-superiores (que aqui pasa a ser el fijo), en vez de
   que cada uno adivine su propia esquina: asi ninguno depende de un numero
   que deja de ser cierto si el control envuelve a 2 o 3 filas (320px). Este
   grupo se queda con la franja superior casi entera (right:16); el riel de
   navegacion (tarea 4) se ancla DEBAJO de el en movil, leyendo
   --controles-alto en vez de suponer donde termina -- ver su propia media
   query mas abajo. La leyenda ya no es parte de este grupo (tarea 3): vive
   sola, fija al inferior izquierdo, con su propia regla mas abajo. */
@media (max-width: 719px) {
    #controles-superiores {
        position: fixed;
        top: calc(var(--cabecera-alto) + var(--hueco));
        left: 16px;
        /* Reserva la columna del riel en vez de pasar por debajo: el riel es la
           navegacion y manda. Antes se solapaban hasta 20x119 px sobre sus iconos. */
        right: calc(var(--riel-ancho, 0px) + 8px);
        z-index: 950;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
    }
    .color-control {
        position: static;
        max-width: 100%;
    }
    .capas {
        position: static;
        max-width: 100%;
        font-size: 0.8rem;
    }
    /* La tarjeta movil (mas abajo en este archivo) pierde el "+ 16px" que
       tiene en escritorio: queda pegada a la linea de tiempo
       (bottom: var(--tiempo-alto), sin holgura). La leyenda replica ese
       mismo ajuste para seguir apilada justo encima, sin el hueco de mas. */
    .mapa-leyenda {
        bottom: calc(var(--tiempo-alto) + var(--tarjeta-alto, 0px) + 12px);
    }
}

/* ------------------------------------------------------------
   Linea de tiempo (tarea 8)
   ------------------------------------------------------------
   Ocupa todo el ancho al pie de la pantalla, por debajo de la tarjeta y del
   panel de detalle -- por eso ambos suben su "bottom" mas adelante en este
   archivo (--tiempo-alto): si compartieran la misma franja se solaparian en
   vez de apilarse. */
:root {
    --tiempo-alto: 60px;
}
.tiempo {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 960;
    box-sizing: border-box;
    min-height: var(--tiempo-alto);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--fondo-flotante);
    box-shadow: 0 -1px 6px var(--sombra);
    font-size: 0.85rem;
}
.tiempo select,
.tiempo button {
    padding: 6px 10px;
    border: 1px solid var(--borde);
    border-radius: 6px;
    background: var(--fondo-panel);
    color: var(--texto);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
}
.tiempo select:hover,
.tiempo button:hover {
    background: var(--fondo-panel-alt);
}
#tiempo-barra {
    flex: 1 1 160px;
    min-width: 100px;
}
#tiempo-etiqueta {
    min-width: 92px;
    text-align: center;
    font-weight: 600;
    color: var(--texto);
    white-space: nowrap;
}

/* En pantallas angostas el footer puede envolver a dos filas (select +
   etiqueta + boton en una, la barra sola en la siguiente): reservar solo
   --tiempo-alto ya no alcanza, asi que la version movil se recalcula en la
   media query de mas abajo en vez de asumir una sola fila aqui. */
@media (max-width: 719px) {
    /* El footer envuelve a dos filas aqui (ver #tiempo-barra abajo), asi que
       la franja que le reservan el resto de los elementos fijos al pie tiene
       que ser mas alta que en escritorio -- de ahi que --tiempo-alto se
       redefina en vez de reusar el valor de una sola fila. */
    :root {
        --tiempo-alto: 128px;
    }
    .tiempo {
        padding: 8px 12px;
        gap: 8px;
    }
    #tiempo-barra {
        flex-basis: 100%;
        order: 3;
    }
}

/* ------------------------------------------------------------
   Tarjeta flotante del ultimo sismo
   ------------------------------------------------------------ */
.tarjeta {
    position: fixed;
    left: 16px;
    bottom: calc(var(--tiempo-alto) + 16px);
    z-index: 900;
    width: 280px;
    max-width: calc(100% - 32px);
    background: var(--fondo-flotante);
    border-radius: 10px;
    box-shadow: 0 2px 10px var(--sombra);
    padding: 14px 16px;
}
.tarjeta.oculta { display: none; }

.tarjeta-cerrar {
    position: absolute;
    top: 6px;
    right: 8px;
    border: none;
    background: none;
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    color: var(--texto-tenue);
}
.tarjeta-mag {
    font-size: 1.6rem;
    font-weight: 800;
    margin: 4px 0;
    color: var(--dato-magnitud-2);
}
.tarjeta-cuando, .tarjeta-donde, .tarjeta-prof {
    margin: 2px 0;
    font-size: 0.9rem;
    color: var(--texto);
}

/* ------------------------------------------------------------
   Panel de detalle (tarea 7): contexto comparativo al tocar un sismo.
   Esquina opuesta a la tarjeta del ultimo sismo -- no la sustituye, y asi
   ambas pueden convivir sin taparse en escritorio.
   ------------------------------------------------------------ */
.detalle {
    position: fixed;
    right: 16px;
    bottom: calc(var(--tiempo-alto) + var(--atribucion-alto, 0px) + 16px);
    z-index: 995;
    /* Con content-box el max-height dejaba fuera los 28 px de relleno vertical y
       el panel medido salia 28 px mas alto de lo que decia su tope: lo justo para
       morder al vecino de arriba. Lo que se acota tiene que ser lo que se mide. */
    box-sizing: border-box;
    width: 300px;
    max-width: calc(100% - 32px);
    max-height: calc(100% - 32px);
    overflow-y: auto;
    background: var(--fondo-flotante);
    border-radius: 10px;
    box-shadow: 0 2px 10px var(--sombra);
    padding: 14px 16px;
}
.detalle.oculta { display: none; }

.detalle-cerrar {
    position: absolute;
    top: 6px;
    right: 8px;
    border: none;
    background: none;
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    color: var(--texto-tenue);
}
.detalle-mag {
    font-size: 1.6rem;
    font-weight: 800;
    margin: 4px 0;
    color: var(--dato-magnitud-2);
}
.detalle-mag span:last-child {
    font-size: 0.95rem;
    font-weight: 400;
    color: var(--texto-tenue);
}
#d-donde, #d-prof {
    margin: 2px 0;
    font-size: 0.9rem;
    color: var(--texto);
}

/* Las anclas: sin ellas la lista queda vacia, y :empty la retira del flujo
   por completo -- ni un borde suelto anunciando una comparacion que no llego. */
.detalle-anclas {
    list-style: none;
    margin: 10px 0 0;
    padding: 8px 0 0;
    border-top: 1px solid var(--fondo-panel-alt);
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.85rem;
    color: var(--texto);
}
.detalle-anclas:empty { display: none; }

@media (max-width: 719px) {
    .detalle {
        left: 0;
        right: 0;
        /* El boton mudo que ocupaba esta esquina en movil desaparecio (tarea 4):
           el riel de navegacion que lo sustituye vive en una columna fija al
           borde derecho, no en una barra al pie, asi que ya no hay nada aqui con
           quien pelearse por la franja. Las dos reglas de abajo pierden el
           termino "+ boton-cajon-alto" en vez de cambiarlo por otra variable --
           no hay equivalente que sustituir, el hueco que dejaba simplemente ya
           no hace falta reservarlo. */
        /* Tambien libra la atribucion de OpenStreetMap, que en movil le rozaba el borde:
           mostrarla es condicion de licencia, asi que manda ella. */
        bottom: calc(var(--tiempo-alto) + var(--atribucion-alto, 0px) + 24px);
        width: auto;
        max-width: none;
        /* Y por arriba tampoco puede crecer hasta comerse la cabecera ni el grupo
           de controles, que a 320 px son 78 + 22 + 236. El panel ya desborda con
           overflow-y: auto, asi que quedarse corto se lee; taparlos, no. Las
           alturas se leen medidas, no supuestas: es la misma regla de arriba. */
        max-height: calc(100% - var(--tiempo-alto) - 24px
                       - var(--cabecera-alto) - var(--hueco) - var(--controles-alto) - 8px);
        border-radius: 10px 10px 0 0;
    }

    /* En movil el detalle cubre el mismo rincon que la tarjeta. Mientras
       este abierto (sin .oculta) la tarjeta se saca del flujo visible en vez
       de quedar tapada con su boton de cerrar inalcanzable; al cerrarse el
       detalle la tarjeta reaparece sola, sin que el JS tenga que coordinar
       las dos clases .oculta. */
    body:has(#detalle:not(.oculta)) .tarjeta {
        display: none;
    }

    /* La leyenda sigue la misma regla que la tarjeta, y por el mismo motivo: en movil
       el detalle es una hoja que se adueña del pie, y la leyenda quedaba TAPADA por
       completo --- 121x101 px, medido. Ocultarla mientras el detalle esta abierto no
       quita informacion: el panel ya dice de ese sismo lo que la leyenda ayudaria a
       descifrar. Al cerrarlo reaparece sola. */
    body:has(#detalle:not(.oculta)) .mapa-leyenda {
        display: none;
    }

    /* El detalle deja libre la franja del riel en vez de pasar por debajo: se metia
       hasta 37 px bajo sus iconos. Reservar es lo mismo que se hizo con el cajon
       cuando el riel le tapaba la tabla. */
    .detalle {
        right: var(--riel-ancho, 0px);
    }
}

/* ------------------------------------------------------------
   Riel de navegacion (tarea 4): sustituye al boton mudo #cajon-abrir. Cada
   panel anuncia su nombre en vez de esconderse detras de un icono sin
   etiqueta. Flush al borde derecho (right:0, sin margen de 16px como el
   resto de los controles flotantes) A PROPOSITO: --riel-ancho (mas abajo,
   .cajon) es el ANCHO medido de este elemento, y esa cuenta solo cuadra si
   el riel no deja hueco entre el y el borde de la pantalla.
   ------------------------------------------------------------ */
.riel {
    position: fixed;
    right: 0;
    top: calc(var(--cabecera-alto) + var(--hueco));
    z-index: 985;
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: var(--fondo-flotante);
    box-shadow: -1px 0 6px var(--sombra);
    border-radius: 8px 0 0 8px;
    overflow: hidden;
}
.riel-item {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 12px; border: none; background: none; cursor: pointer;
    font-size: 0.82rem; text-align: left; color: var(--texto);
}
.riel-item:hover { background: var(--superficie-hover); }
.riel-item.activo { font-weight: 700; background: var(--acento-tenue); }

/* En telefono solo el icono: a 375 px una columna con nombres se come el
   mapa, que es lo unico que la persona vino a ver.

   Y la posicion cambia de verdad, no solo el contenido: en escritorio el
   riel es el unico que vive en la franja superior derecha, pero en movil
   #controles-superiores (mas arriba en este archivo) ocupa esa misma
   esquina casi entera (right:16) con el selector de color y las capas. Sin
   este ajuste el riel se le montaria encima -- por eso se ancla DEBAJO,
   leyendo --controles-alto (medido por mapa.js, no supuesto: a 320px puede
   llegar a envolver a tres filas). Por abajo tampoco puede crecer hasta la
   franja de la tarjeta/linea de tiempo: max-height mas overflow-y lo recorta
   antes de montarsele encima, igual que hace .detalle con la misma pareja
   de variables. */
/* Pantalla BAJA. Los dos renglones de la linea de tiempo existen por pantalla
   ESTRECHA, no por pantalla baja: en un telefono en horizontal (667x375) se llevaban
   128 px de 375, un tercio del alto.

   Y aqui ceden la leyenda y los controles de arriba. El orden de prioridades es el de
   quien acaba de sentir un temblor: primero el mapa, la cabecera con las cifras y la
   tarjeta del ultimo sismo; despues, si sobra sitio, el selector de color, las capas y
   la leyenda que los explica. En 568x320 la suma no cabe --- cabecera 97 + controles 86
   + tarjeta 119 + tiempo 60 = 362 de 320 --- asi que no es cuestion de acomodar mejor:
   sobra contenido. El mapa sigue coloreado por antiguedad, que es el modo por defecto.

   Va DESPUES del bloque de max-width: misma especificidad, gana el ultimo, y aqui el
   alto manda sobre el ancho. */
@media (max-height: 480px) {
    :root { --tiempo-alto: 60px; }
    .mapa-leyenda { display: none; }
    #controles-superiores { display: none; }
}

/* A 320 px de ancho la leyenda ocupa 121x113: un tercio del mapa, y choca con los
   controles de arriba. Cede por la misma razon --- es referencia, no control --- y el
   panel de detalle sigue explicando cada sismo por su nombre. */
@media (max-width: 359px) {
    .mapa-leyenda { display: none; }
}

@media (max-width: 719px) {
    /* El riel es la NAVEGACION: manda sobre lo demas y ocupa su columna entera, del
       pie de la cabecera al borde de la linea de tiempo. Los otros flotantes le
       reservan esa franja.

       La version anterior restaba SEIS terminos de seis duenos distintos --- incluido
       --controles-alto, que mide la columna IZQUIERDA --- y en una pantalla de 375 px de
       alto la resta daba negativo: el riel quedaba en 36x0 px. Medido contra
       produccion: en CUALQUIER telefono en horizontal, 0 de 5 botones alcanzables. Y
       empeoraba con datos, porque --tarjeta-alto solo resta cuando hay un sismo
       reciente: se rompia justo despues de un temblor. */
    .riel {
        top: calc(var(--cabecera-alto) + var(--hueco));
        max-height: calc(100% - var(--cabecera-alto) - var(--hueco) - var(--tiempo-alto) - 8px);
        overflow-y: auto;
    }
    .riel-nombre { display: none; }
    .riel-item { padding: 10px; justify-content: center; }
}

/* ------------------------------------------------------------
   Cajon lateral
   ------------------------------------------------------------ */
.cajon {
    position: fixed;
    top: 0;
    /* En escritorio deja sitio al riel: sin esto el cajon abierto (el mismo
       ancho de siempre, min(420px,100%)) le taparia los seis botones. El
       numero lo mide mapa.js (--riel-ancho) en vez de copiarlo: el riel
       ocupa distinto ancho con nombres (aqui) que sin ellos (movil, donde
       esta variable ademas no se usa -- la media query de abajo pisa "right"
       con 0 y el cajon vuelve a pantalla completa). */
    right: var(--riel-ancho, 132px);
    bottom: 0;
    z-index: 980;
    width: min(420px, 100%);
    background: var(--fondo-panel);
    box-shadow: -2px 0 10px var(--sombra);
    overflow-y: auto;
    padding: 56px 16px 24px;
    transition: transform 0.25s ease-out;
    transform: translateX(0);
}
.cajon.cerrado {
    /* No basta con 100%: eso desplaza el cajon por SU PROPIO ancho, y como su
       borde derecho ya empieza --riel-ancho px hacia adentro (no en el borde
       de la pantalla, para dejarle sitio al riel), 100% lo deja con un sliver
       de --riel-ancho px todavia visible -- medido: 127x196 de solape contra
       el propio riel a 1200px. Sumar --riel-ancho al desplazamiento es lo que
       le falta para despejar la pantalla entera, sea cual sea su ancho. */
    transform: translateX(calc(100% + var(--riel-ancho, 132px)));
}

.paneles {
    display: flex;
    flex-direction: column;
    gap: 24px;
}
/* riel.js muestra UN panel a la vez: los otros seis se ocultan con
   display:none en vez de acoplarse cada uno por su cuenta (ver la nota junto
   a #cajon mas arriba sobre por que ningun panel lleva position:fixed
   propio). */
.panel {
    display: none;
    border-bottom: 1px solid var(--fondo-panel-alt);
    padding-bottom: 20px;
}
.panel.panel-activo {
    display: block;
}
.panel:last-child {
    border-bottom: none;
}
.panel-titulo {
    margin: 0 0 12px;
    font-size: 1.05rem;
    color: var(--texto);
}

/* Por debajo de 720px el cajon sube desde abajo en vez de entrar por la
   derecha: en telefono el gesto natural es deslizar hacia arriba, y un panel
   angosto a la derecha deja casi todo el contenido ilegible. */
@media (max-width: 719px) {
    .cajon {
        top: auto;
        left: 0;
        right: 0;
        width: auto;
        height: 80vh;
        border-radius: 16px 16px 0 0;
        transform: translateY(0);
        /* El riel flota ENCIMA del cajon abierto (z-index 985 contra 980) para
           poder cambiar de panel sin cerrar primero -- ver mas arriba. Eso es
           bueno para el riel y malo para lo que quede justo debajo: medido con
           elementsFromPoint, tapaba la columna "Profundidad (km)" de la tabla
           y el boton de exportar ZIP, con datos reales debajo, no "cromo
           vacio". La solucion no es esconder el riel -- es que el contenido
           nunca pase por ahi: un relleno derecho del ancho medido del riel
           (--riel-ancho, la misma variable que ya usa #cajon en escritorio)
           en vez del 16px de siempre. */
        padding-right: calc(16px + var(--riel-ancho, 44px));
    }
    .cajon.cerrado {
        transform: translateY(100%);
    }
    /* La tarjeta pasa a ancho completo, pegada justo encima de la linea de
       tiempo (tarea 8) en vez de al borde inferior de la pantalla. */
    .tarjeta {
        left: 0;
        /* Igual que los controles de arriba: le deja su columna al riel. */
        right: var(--riel-ancho, 0px);
        bottom: var(--tiempo-alto);
        width: auto;
        max-width: none;
        border-radius: 10px 10px 0 0;
    }
}

/* ============================================================
   Paneles del cajon, copiados de index.php (tarea 5, paso 5).
   Mismos selectores y mismos colores: es la paleta de magnitud del sitio,
   y duplicar criterios de color haria que dos pantallas dijeran cosas
   distintas del mismo dato.
   ============================================================ */

.table-container {
    overflow-x: auto;
    max-height: none;
    overflow-y: visible;
    border-radius: 8px;
    border: 1px solid var(--borde);
}
table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}
th, td {
    padding: 10px 12px;
    text-align: left;
    border-bottom: 1px solid var(--fondo-panel-alt);
}
th {
    background: var(--fondo-app);
    color: var(--texto);
    font-weight: 600;
    position: sticky;
    top: 0;
    z-index: 2;
}
tr:hover { background: var(--fondo-app); }
.tag {
    display: inline-block;
    padding: 2px 12px;
    border-radius: 20px;
    font-size: 0.75rem;
    font-weight: 600;
}
.tag-imperceptible { background: var(--tag-imperceptible-fondo); color: var(--tag-imperceptible-texto); }
.tag-perceptible { background: var(--tag-perceptible-fondo); color: var(--tag-perceptible-texto); }
.tag-fuerte { background: var(--tag-fuerte-fondo); color: var(--tag-fuerte-texto); }
.tag-peligroso { background: var(--tag-peligroso-fondo); color: var(--tag-peligroso-texto); }
.tag-catastrofico { background: var(--tag-catastrofico-fondo); color: var(--tag-catastrofico-texto); }
.copiar-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.1rem;
    color: var(--acento-texto);
}

/* Gráficos */
.chart-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
    gap: 24px;
}
.chart-card {
    background: var(--fondo-app);
    border-radius: 8px;
    padding: 16px;
}
.chart-card h4 {
    margin-bottom: 12px;
    color: var(--texto);
    font-family: 'Segoe UI', 'Helvetica Neue', sans-serif;
}
.chart-container {
    position: relative;
    height: 280px;
}

/* Clima */
.weather-panel {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    margin-bottom: 20px;
}
.weather-card {
    background: var(--fondo-app);
    border: 1px solid var(--borde);
    border-radius: 12px;
    padding: 18px;
}
.weather-card h4 {
    margin: 0 0 10px;
    font-size: 1rem;
}
.weather-card .value {
    font-size: 2rem;
    font-weight: 700;
    color: var(--acento-texto);
}
#weather-map {
    min-height: 420px;
    border-radius: 12px;
    border: 1px solid var(--borde);
    overflow: hidden;
}
#mapa-sismos {
    min-height: 420px;
    border-radius: 8px;
    border: 1px solid var(--borde);
    overflow: hidden;
}
.weather-forecast-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 10px;
}
.weather-forecast-item {
    background: var(--fondo-panel);
    border: 1px solid var(--borde);
    border-radius: 10px;
    padding: 12px;
}

/* Estadísticas */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
}
.stat-item {
    background: var(--fondo-app);
    padding: 10px 16px;
    border-radius: 8px;
    border: 1px solid var(--fondo-panel-alt);
}
.stat-item .stat-label {
    font-weight: 600;
    color: var(--texto);
}
.stat-item .stat-value {
    float: right;
    font-weight: 700;
    color: var(--acento-texto);
}

/* Proyecciones */
.pred-card {
    background: var(--fondo-app);
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 16px;
    border-left: 4px solid var(--acento);
}
.pred-card h4 { margin-bottom: 8px; color: var(--texto); }
.pred-row {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}
.pred-row .field {
    flex: 1;
    min-width: 150px;
}
.pred-row .field label {
    font-weight: 600;
    font-size: 0.8rem;
    color: var(--texto-tenue);
}
.pred-row .field .value {
    background: var(--fondo-panel);
    padding: 4px 10px;
    border-radius: 4px;
    border: 1px solid var(--borde);
    min-height: 30px;
    margin-top: 2px;
}

/* Simulación */
.sim-control {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
}
.sim-control input[type="number"] {
    width: 70px;
    padding: 6px 10px;
    border: 1px solid var(--borde);
    border-radius: 6px;
}
.sim-text {
    background: var(--fondo-app);
    border: 1px solid var(--borde);
    border-radius: 8px;
    padding: 16px;
    max-height: 400px;
    overflow-y: auto;
    font-family: 'Courier New', monospace;
    font-size: 0.8rem;
    white-space: pre-wrap;
    line-height: 1.5;
}

/* Prueba de sonido */
.sound-test {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    align-items: center;
    background: var(--fondo-app);
    padding: 20px;
    border-radius: 8px;
}
.sound-test button {
    padding: 6px 16px;
    background: var(--acento);
    color: var(--texto-sobre-acento);
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 600;
    transition: 0.2s;
}
.sound-test button:hover { background: var(--acento-fuerte); }
.sound-test .voz-input {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.sound-test .voz-input input {
    padding: 6px 12px;
    border: 1px solid var(--borde);
    border-radius: 6px;
    min-width: 300px;
}

/* Botones generales */
.btn {
    padding: 8px 18px;
    background: var(--acento);
    color: var(--texto-sobre-acento);
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 600;
    transition: 0.2s;
    font-family: 'Segoe UI', 'Helvetica Neue', sans-serif;
}
.btn:hover { background: var(--acento-fuerte); }
/* Blanco, no carbon: el carbon lo hereda de .btn (que es naranja, donde si va carbon)
   y sobre este verde da 3.09. Blanco sobre #198754 da 4.53. */
.btn-success { background: var(--exito); color: var(--texto-invertido); }
.btn-success:hover { background: var(--exito-fuerte); }
.btn-warning { background: var(--advertencia); color: var(--texto); }
.btn-warning:hover { background: var(--advertencia-fuerte); }
.btn-purple { background: var(--morado); color: var(--texto-invertido); }
.btn-purple:hover { background: var(--morado-fuerte); }

/* Alerta emergente, copiada de index.php tal cual. mostrarAlerta() queda
   definida en el script de paneles pero sin llamador en este armazon: la
   disparaba el panel superior (deteccion de sismo nuevo), que la cabecera de
   veredicto sustituye. Se deja el estilo por si una tarea futura la reengancha. */
.alerta-emergente {
    position: fixed;
    top: 20px;
    right: 20px;
    background: var(--peligro);
    color: var(--texto-invertido);
    padding: 20px;
    border-radius: 12px;
    box-shadow: 0 8px 24px var(--sombra);
    z-index: 999;
    max-width: 400px;
    animation: slideIn 0.4s ease;
}
@keyframes slideIn {
    from { transform: translateX(120%); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}
.alerta-emergente button {
    background: var(--fondo-panel);
    color: var(--texto);
    border: none;
    padding: 4px 12px;
    border-radius: 4px;
    cursor: pointer;
    margin-top: 10px;
}

@media (max-width: 719px) {
    .chart-grid { grid-template-columns: 1fr; }
    .sound-test { flex-direction: column; align-items: stretch; }
    .sound-test .voz-input input { min-width: auto; }
}

/* ------------------------------------------------------------
   Controles de Leaflet: zoom y atribucion.

   Los dos viven en la esquina inferior derecha y los dos tienen que librar la
   linea de tiempo (abajo) y el riel (derecha). Se leen de sus variables, no se
   copian: --tiempo-alto vale 60 px en escritorio y 128 en movil.

   La atribucion NO es decorativa: mostrarla es condicion de la licencia de
   OpenStreetMap. Estaba quedando 168x17 px por debajo de la linea de tiempo,
   invisible, y eso no es un detalle estetico sino un incumplimiento.
   ------------------------------------------------------------ */
.leaflet-bottom.leaflet-right {
    bottom: calc(var(--tiempo-alto) + 8px);
    right: calc(var(--riel-ancho, 0px) + 8px);
}

/* El zoom va JUSTO DEBAJO del riel, no en el pie: abajo a la derecha tapaba el
   panel de detalle del sismo seleccionado --- 34x65 px medidos en 375 y en 1200.
   Se apoya en donde termina el riel, no en un numero: el riel mide distinto con
   nombres (escritorio) que solo con iconos (movil). */
.leaflet-top.leaflet-right {
    top: calc(var(--riel-fin, 0px) + 8px);
}

/* En pantalla estrecha los botones de zoom se ocultan, y no es por gusto: NO CABEN.
   Medido a 719 px --- el riel termina en y=417 y la tarjeta empieza en 453, o sea 36 px
   de hueco para una caja de 65. Debajo del riel cae sobre la tarjeta o sobre el panel
   de detalle, que ocupa de 447 a 548.

   Ocultarlos no deja a nadie sin zoom: en tactil se pellizca y con raton se usa la
   rueda, los dos gestos nativos que Leaflet trae activados. Se decidio por ANCHO y no
   por tipo de puntero: el problema es de espacio, y una ventana estrecha con raton
   tiene el mismo problema que un telefono. */
@media (max-width: 719px) {
    .leaflet-control-zoom { display: none; }
}
.leaflet-control-attribution {
    background: var(--fondo-flotante);
    color: var(--texto-tenue);
}

/* En movil el riel es una columna estrecha de iconos y la linea de tiempo es mas
   alta; el zoom se aparta del riel igual, con la misma variable. */
@media (max-width: 719px) {
    .leaflet-bottom.leaflet-right {
        bottom: calc(var(--tiempo-alto) + var(--tarjeta-alto, 0px) + 8px);
    }
}
