
  :root {
    --bg:#0f1115; --card:#1a1d24; --txt:#e7e9ee; --mut:#9aa3b2;
    --line:#2a2e38; --acc:#5b9dff; --ok:#3ecf8e; --warn:#f0b429; --bad:#ff6b6b;
  }
  * { box-sizing:border-box; }
  /* Chrome en Android agranda por su cuenta el texto de las paginas que considera «no
     pensadas para movil» (font boosting), y no lo hace igual en todos los bloques: unos
     crecen y otros no, asi que el que crece se sale de su columna y pisa la de al lado.
     El panel rotado cumple justo la condicion que lo dispara, porque el #rot declara 932 px
     de ancho en una pantalla de 430. Es lo que el usuario veia como «textos montados unos
     encima de otros» en la tarjeta de marca, y por eso no se reproducia en un navegador de
     escritorio con la ventana estrecha: ahi ese ajuste no existe. Con el 100 % el texto se
     queda del tamaño que dice el CSS. En escritorio no cambia nada, porque no hay boosting
     que desactivar. SEO-TANDA-20260922-28. */
  html { -webkit-text-size-adjust:100%; text-size-adjust:100%; }
  body { margin:0; background:var(--bg); color:var(--txt);
    font-family:system-ui,Segoe UI,Roboto,Arial,sans-serif; }
  /* Ancho util del panel. Subido de 1200 a 1800 en SEO-TANDA-20260812-04: en un monitor
     de 1920 el tope de 1200 dejaba 720px en blanco (un 37% de la pantalla) en la vista
     que mas se mira, y con el navegador estirado por dos monitores el centrado hacia
     caer el panel justo encima del bisel. 1800 aprovecha el ancho real dejando margen
     para la barra de scroll; el limite sigue existiendo porque una linea de texto de
     1900px es ilegible. */
  .wrap { max-width:1800px; margin:0 auto; padding:14px 24px; }
  h1 { font-size:20px; margin:0 0 2px; }
  .meta { color:var(--mut); font-size:12px; margin-bottom:10px; }
  .meta .meta-hora { color:var(--bad); font-weight:700; }
  /* HUECO PARA LA FRESCURA DE LOS DATOS (SEO-TANDA-20260922-32, idea del usuario).
     Lo rellena el servidor (`rutas_panel.py`), que es quien sabe cuando fue la ultima
     subida y lo pregunta en vivo; aqui nace vacio y por eso en el panel local no se ve
     nada. Existe para que esa fecha deje de ser un recuadro flotante abajo a la izquierda
     y pase a la cabecera, junto a la de generacion: en el movil girado ese recuadro
     compartia banda con la barra de desplazamiento.
     NO SE ESCRIBE SOBRE `#meta-hora`, y no es un capricho: el boton Actualizar compara su
     texto antes y despues de regenerar para saber si la pagina nueva ha llegado (seis
     usos). Pisarlo con otra fecha deja ese boton diciendo que no ha pasado nada. */
  .meta .meta-frescura { color:var(--mut); }
  .meta .meta-frescura.viejo { color:var(--bad); font-weight:700; }
  /* La ultima subida al panel web fallo (SEO-TANDA-20260903-23). Va en la cabecera y no en
     los semaforos porque no habla del contenido sino de esta pantalla: de si lo que se ve
     esta tambien en el panel web. Se apaga solo con la primera subida buena. */
  .meta .meta-subida { color:var(--warn); font-weight:600; cursor:help; }
  .toolbar { display:flex; gap:12px; align-items:center; flex-wrap:wrap; margin:0 0 12px; }
  .toolbar input { flex:1; min-width:240px; background:#13161c; border:1px solid var(--line);
    border-radius:8px; color:var(--txt); padding:9px 12px; font-size:14px; }
  .toolbar .sort { display:flex; gap:6px; align-items:center; color:var(--mut); font-size:12px; flex-wrap:wrap; }
  .toolbar button { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:6px 10px; font-size:12px; cursor:pointer; }
  .toolbar button:hover { border-color:var(--acc); }
  /* Botones de accion de la barra: pildoras con jerarquia. Actualizar = accion
     principal (verde relleno); Plegar todo = secundaria (contorno). SEO-TANDA-20260703-01 */
  /* Antes era el boton suelto "Plegar todo"; desde SEO-TANDA-20260813-03 es "Tablero" y abre
     el popover de disposicion (donde ahora viven plegar/desplegar y las configuraciones
     guardadas). Mismo aspecto de pildora secundaria, que el sitio en la barra es el mismo. */
  .toolbar #tablero-btn { background:transparent; border:1px solid var(--acc); color:var(--acc);
    border-radius:20px; padding:7px 15px; font-size:12px; font-weight:600; cursor:pointer;
    transition:background .12s ease, color .12s ease; }
  .toolbar #tablero-btn:hover { background:var(--acc); color:#0b0e14; }
  .toolbar a.refrescar { background:var(--ok); border:1px solid var(--ok); color:#06281c;
    border-radius:20px; padding:7px 15px; font-size:12px; font-weight:700; cursor:pointer;
    text-decoration:none; display:inline-flex; align-items:center; gap:6px;
    transition:filter .12s ease, box-shadow .12s ease; }
  .toolbar a.refrescar:hover { filter:brightness(1.08); box-shadow:0 2px 12px rgba(62,207,142,.4); }
  .toolbar a.refrescar:active { transform:translateY(1px); }
  .toolbar a.refrescar.cargando { opacity:.6; pointer-events:none; }
  .toolbar a.refrescar.hecho { background:var(--bad); border-color:var(--bad); color:#fff; }
  .totales { display:flex; gap:18px; margin:0 0 14px; flex-wrap:wrap; }
  .totales .t b { font-size:24px; color:var(--acc); }
  .totales .t span { color:var(--mut); font-size:13px; margin-left:6px; }
  .totales .t { cursor:pointer; }
  .totales .t:hover b { text-decoration:underline; }
  /* Rejilla de tarjetas de marca: 2 columnas fijas hasta SEO-TANDA-20260812-04 (que la paso a
     auto-fit, para que las 4 marcas cupieran en una fila en un monitor de 1920) y tablero de
     posiciones desde SEO-TANDA-20260812-07. El auto-fit sigue vivo como plan B por debajo de
     1500px, ver la media query de aqui abajo.
     TABLERO de 4 columnas x 2 filas (SEO-TANDA-20260812-07). Antes era una rejilla de flujo
     automatico: las tarjetas se colocaban una detras de otra y, al mover una, las demas se
     corrian solas para tapar el hueco, asi que era imposible dejar sitio libre a proposito ni
     poner una marca en la ultima casilla. Ahora cada tarjeta lleva su columna y su fila
     escritas (grid-column/grid-row, que pone pintarTablero() en el propio elemento), asi que
     se queda donde se la deja y nada se recoloca solo.
     Por debajo de 1500px de viewport no hay sitio para 4 columnas legibles, asi que se vuelve
     al flujo automatico de antes y las posiciones se ignoran (de ahi los !important: hay que
     poder anular un estilo escrito en el elemento). */
  /* grid-auto-rows con un minimo: sin el, una fila que solo contenga la continuacion de una
     tarjeta alta (o nada) se encogeria a cero y no se veria como fila. SEO-TANDA-20260812-09 */
  .grid { display:grid; grid-template-columns:repeat(4,1fr); grid-auto-rows:minmax(84px,auto);
    gap:12px; align-items:start; }
  @media (max-width:1499px) {
    .grid { grid-template-columns:repeat(auto-fit,minmax(min(420px,100%),1fr)); }
    .card { grid-column:auto !important; grid-row:auto !important; }
    .hueco { display:none; }
  }
  @media (max-width:680px) { .grid { grid-template-columns:1fr; } }
  .card {
    background:
      radial-gradient(135% 90% at 100% 0%, var(--neon-soft, transparent), transparent 55%),
      repeating-linear-gradient(45deg, rgba(255,255,255,0.015) 0 2px, transparent 2px 9px),
      var(--card);
    border:1px solid var(--line); border-radius:12px; padding:12px 14px;
    border-left:3px solid var(--neon, var(--acc));
    transition:box-shadow .15s ease; }
  .card:hover { box-shadow:0 0 0 1px var(--neon-soft, transparent), 0 6px 20px rgba(0,0,0,.35); }
  /* La cabecera ya NO se parte en dos lineas (SEO-TANDA-20260812-06). Con `flex-wrap:wrap`,
     la fila de botones saltaba abajo en cuanto el nombre + el dominio + los botones no cabian
     en el ancho de la tarjeta, y eso ocurria en unas marcas si y en otras no (dominios de
     distinta longitud: guardiapalomino.com parte, w2c.site no), asi que dos tarjetas iguales
     se presentaban con alturas distintas. Se agravo al estrechar las tarjetas a 4 columnas y
     sumarles un boton mas. Ahora el bloque del titulo es el que cede (se encoge y el dominio
     corta con puntos suspensivos) y los botones se quedan siempre en su linea, de modo que
     todas las cabeceras miden exactamente lo mismo. En movil se deja partir como antes,
     que ahi el ancho no da para otra cosa.
     (Vigente en su objetivo, superado en su mecanica por SEO-TANDA-20260818-09, aqui debajo:
     el dominio ya no comparte fila con los botones, asi que ya no hay nada que ceda ni que
     recortar en la fila de arriba.) */
  /* El dominio baja a una fila propia de la cabecera (SEO-TANDA-20260818-09). Antes compartia
     fila con los botones (iban dentro del mismo bloque que el h2), asi que su longitud entraba
     en el ancho MINIMO de la tarjeta y las columnas `1fr` de .grid, que son minmax(auto,1fr),
     no podian bajar de ahi: la marca con la cabecera mas larga se quedaba mas ancha y les
     robaba el hueco a las otras tres. Medido en el panel real a 1920px, con la sesion de LAM
     abierta: LAM exigia 498px y las columnas salian 498/406/406/406 en vez de 429 cada una.
     Sacando el dominio de esa fila, el minimo cae a 435 (LAM), 342 (GP), 363 (De Bares) y
     357 (W2C), todos por debajo o al filo del reparto a partes iguales.
     Se pasa de flex a grid de dos filas para que el dominio ocupe el ancho completo de la
     cabecera (fila 2) y los botones sigan compartiendo la fila 1 solo con el nombre de marca.
     La cabecera sigue sin partirse por si sola (no hay wrap): la fila 2 es fija y existe en
     las cuatro marcas, asi que todas las cabeceras miden lo mismo de alto, que es lo que
     buscaba SEO-TANDA-20260812-06 con el flex-wrap:nowrap que habia aqui. */
  .card-h { display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:center;
            column-gap:8px; row-gap:0; }
  .card-h h2 { grid-area:1 / 1; font-size:17px; margin:0; color:var(--neon, var(--txt)); }
  .card-h-r { grid-area:1 / 2; display:flex; align-items:center; gap:8px; }
  .card-h .dom { grid-area:2 / 1 / 3 / -1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* En movil no hay ancho para nombre + botones en la misma fila (los botones piden 279px y la
     tarjeta mide 327), asi que las dos columnas se deshacen y los tres bloques se apilan en el
     orden del DOM: nombre, dominio, botones. Equivale al `flex-wrap:wrap` que habia aqui antes
     de SEO-TANDA-20260818-09; sin esto, la columna del nombre se comprime a nada y el titulo y
     el dominio se parten letra a letra (cabecera de 366px de alto, medido a 375px). */
  @media (max-width:520px) {
    .card-h { grid-template-columns:1fr; row-gap:4px; align-items:start; }
    .card-h h2, .card-h .dom, .card-h-r { grid-area:auto; }
    .card-h .dom { overflow:visible; white-space:normal; }
    .card-h-r { flex-wrap:wrap; }
  }
  .dom { color:var(--mut); font-size:12px; margin-top:2px; }
  /* El chip de sesion es un boton desde SEO-TANDA-20260803-02 (abre el popover con el
     detalle de la sesion de ESA marca), asi que necesita apagar los estilos propios de
     button; su aspecto no cambia respecto a cuando era un span. */
  /* El tope del ancho del chip (SEO-TANDA-20260922-25), y el unico que hay. El chip no parte
     el texto (`white-space:nowrap`), asi que sin tope fija el ancho MINIMO de la tarjeta
     entera: un texto largo no se ve como un chip largo, se ve como una tarjeta que se come a
     las otras tres. Medido el 2026-09-22 con la linea de evidencia pegada al chip (108
     caracteres): LAM salia en 809 px y las otras tres en 319, cuando les tocan 429 a las
     cuatro. 176 px es lo que sobra en la cabecera de una tarjeta de una columna a 1900 px
     (397 de cabecera, menos 182 de los cinco botones y sus huecos, menos 37 del nombre de la
     marca), medido; con el, ese mismo texto de 108 caracteres deja la tarjeta igual que
     «sin sesion».
     El tope es de PIXELES y no de caracteres a proposito: el texto entero se queda en el HTML
     (no se destruye nada, y las comprobaciones que miran lo que dice el chip siguen viendolo),
     el navegador corta lo que no cabe con puntos suspensivos, y el estado completo se lee al
     pulsarlo, que es para lo que existe el desplegable. Un recorte en Python ademas tendria
     que adivinar cuanto mide cada caracter, y quien anada manana un estado nuevo no se va a
     acordar de el. */
  .ses { font-size:11px; padding:3px 8px; border-radius:20px; white-space:nowrap;
         font-family:inherit; border:0; background:none; cursor:pointer;
         max-width:176px; overflow:hidden; text-overflow:ellipsis; }
  .ses.sin { color:var(--mut); border:1px solid var(--line); }
  .ses.aqui { color:#06281c; background:var(--ok); }
  .ses.otro { color:#2c2206; background:var(--warn); }
  .ses.congelada { color:#fff; background:var(--bad); font-weight:600; }   /* N-247 */
  /* Candado de una persona sin latido mas del umbral de abandono: reclamable desde otro PC
     (SEO-TANDA-20260912-24). Rojo sin negrita: no es la averia de la nocturna, pero hay que verlo. */
  .ses.vencido { color:#fff; background:var(--bad); }
  /* Evidencia MUERTA del titular del candado (SEO-TANDA-20260922-25): su transcript lleva mas
     parado de lo que una tanda nocturna se para nunca, asi que ese candado esta huerfano. Va
     DESPUES de .sin/.aqui/.otro/.vencido y con los mismos dos puntos de especificidad, para
     ganarles sin necesidad de !important. El texto del chip no cambia: el color avisa y el
     desplegable explica, que es justo lo contrario de lo que hacia el chip largo. */
  .ses.ev-muerto { color:#fff; background:var(--bad); }
  .ses:hover { filter:brightness(1.12); }
  /* Popover del chip de sesion (SEO-TANDA-20260803-02). No es una pantalla del sistema de
     nomenclatura: no navega, no entra en la pila de modales y no tiene ID, igual que los
     tooltips del semaforo. Lo que si es pantalla es L1-SES, que se abre desde su pie. */
  .ses-pop { position:absolute; z-index:60; display:none; width:340px; max-width:92vw;
             background:var(--card); border:1px solid var(--line); border-radius:10px;
             box-shadow:0 10px 30px rgba(0,0,0,.5); padding:12px 14px; font-size:12px;
             text-align:left; }
  .ses-pop.open { display:block; }
  .ses-pop h4 { margin:0 0 6px; font-size:13px; color:var(--txt); }
  .ses-pop .pop-est { font-size:11px; padding:2px 7px; border-radius:20px; margin-left:6px;
                      white-space:nowrap; }
  .ses-pop .pop-est.aqui { color:#06281c; background:var(--ok); }
  .ses-pop .pop-est.otro { color:#2c2206; background:var(--warn); }
  .ses-pop .pop-est.sin { color:var(--mut); border:1px solid var(--line); }
  .ses-pop .pop-est.congelada { color:#fff; background:var(--bad); }
  .ses-pop .pop-est.vencido { color:#fff; background:var(--bad); }
  .ses-pop .pop-congelada { color:var(--bad); margin:6px 0 2px; font-weight:600; line-height:1.35; }
  .ses-pop .pop-vencido { color:var(--bad); margin:6px 0 2px; line-height:1.35; }   /* SEO-TANDA-20260912-24 */
  .ses-pop .pop-ids { color:var(--acc); margin:6px 0 2px; font-weight:600; }
  .ses-pop .pop-chat { color:var(--txt); margin:2px 0; line-height:1.4; }
  .ses-pop .pop-meta { color:var(--mut); margin-top:4px; }
  .ses-pop .pop-vacio { color:var(--mut); }
  .ses-pop .pop-pieza { padding:4px 0; border-top:1px solid var(--line); }
  .ses-pop .pop-pieza:first-of-type { border-top:0; }
  .ses-pop .pop-tarea { color:var(--txt); font-weight:400; }
  .ses-pop .pop-todas { margin-top:10px; padding-top:8px; border-top:1px solid var(--line);
                        width:100%; text-align:left; background:none; border-left:0;
                        border-right:0; border-bottom:0; color:var(--acc); cursor:pointer;
                        font-family:inherit; font-size:12px; }
  .ses-pop .pop-todas:hover { text-decoration:underline; }
  /* Popover del boton "Tablero" (SEO-TANDA-20260813-03). Reaprovecha la caja de .ses-pop y,
     por el mismo motivo que aquel, tampoco es una pantalla del sistema de nomenclatura: no
     navega, no entra en la pila de modales y no lleva ID. Pequeño a proposito. */
  .tab-pop { width:280px; }
  .tab-pop .tab-fila { display:flex; gap:6px; margin:6px 0 0; }
  .tab-pop .tab-fila input { flex:1; min-width:0; background:#13161c; border:1px solid var(--line);
    color:var(--txt); border-radius:6px; padding:6px 8px; font-size:12px; font-family:inherit; }
  .tab-pop .tab-b { flex:1; background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:6px 8px; font-size:12px; font-family:inherit; cursor:pointer;
    white-space:nowrap; }
  .tab-pop .tab-b:hover { border-color:var(--acc); color:var(--acc); }
  /* Botones de icono del popover: el emoji manda el tamano, no el texto (SEO-TANDA-20260818-12). */
  /* Fila de cuatro pasos de ancho: mismo boton, con menos aire a los lados para que entren
     los cuatro en los 280px del popover sin partirse. SEO-TANDA-20260818-17 */
  .tab-pop .tab-fila4 .tab-b { padding:5px 2px; font-size:11.5px; letter-spacing:-.2px; }
  .tab-pop .tab-icono { display:flex; align-items:center; justify-content:center; padding:5px 0; }
  .tab-pop .tab-icono svg { display:block; }
  /* Boton apagado: sigue a la vista (para que se vea que existe) pero no responde. */
  .tab-pop .tab-b:disabled { opacity:.32; cursor:default; }
  .tab-pop .tab-b:disabled:hover { border-color:var(--line); color:var(--txt); }
  .tab-pop .tab-tit { font-size:10.5px; text-transform:uppercase; letter-spacing:.5px;
    color:var(--mut); margin:12px 0 5px; }
  /* Estado de la disposicion del sistema: si la hay y de cuando. SEO-TANDA-20260813-15 */
  .tab-pop .tab-nota { font-size:11px; color:var(--mut); margin:0 0 2px; }
  .tab-pop .tab-lista { list-style:none; margin:0; padding:0; }
  .tab-pop .tab-lista li { display:flex; gap:6px; align-items:center; margin-bottom:4px; }
  .tab-pop .tab-usar { flex:1; min-width:0; text-align:left; background:#13161c;
    border:1px solid var(--line); color:var(--txt); border-radius:6px; padding:5px 8px;
    font-size:12px; font-family:inherit; cursor:pointer; overflow:hidden;
    text-overflow:ellipsis; white-space:nowrap; }
  .tab-pop .tab-usar:hover { border-color:var(--acc); color:var(--acc); }
  .tab-pop .tab-borrar { background:none; border:1px solid var(--line); color:var(--mut);
    border-radius:6px; padding:5px 7px; font-size:11px; cursor:pointer; font-family:inherit; }
  .tab-pop .tab-borrar:hover { border-color:var(--bad); color:var(--bad); }
  /* Pie del popover: a la izquierda, fijar la disposicion actual como la inicial; a la derecha,
     el reset. El reset va en rojo porque es la unica accion que deshace de golpe lo que tengas
     montado, pero pequeño y discreto: no es lo que se viene a hacer aqui. Ancho automatico, no
     al 100%. SEO-TANDA-20260813-06, afinado en SEO-TANDA-20260813-07 */
  .tab-pop .tab-pie { display:flex; align-items:center; justify-content:space-between; gap:8px;
    margin-top:12px; padding-top:9px; border-top:1px solid var(--line); }
  .tab-pop .tab-fijar { background:none; border:0; padding:0; color:var(--acc); cursor:pointer;
    font-family:inherit; font-size:11px; text-align:left; }
  .tab-pop .tab-fijar:hover { text-decoration:underline; }
  .tab-pop .tab-reset { flex:none; padding:3px 10px; border-radius:5px; background:transparent;
    border:1px solid var(--bad); color:var(--bad); font-family:inherit; font-size:11px;
    cursor:pointer; transition:background .12s ease, color .12s ease; }
  .tab-pop .tab-reset:hover { background:var(--bad); color:#fff; }
  /* Semaforo de la investigacion de recintos feriales (De Bares). SEO-TANDA-20260724-01 */
  .semaforo { font-size:10px; font-weight:600; cursor:help; margin-left:4px; }
  /* Dentro de "Ultima investigacion" el semaforo baja a su propia linea y no se parte nunca
     (SEO-TANDA-20260818-20): pegado al final del texto caia siempre a caballo entre dos
     lineas y se leia "investigacion" arriba y "hace 5 dias" abajo, en las cuatro tarjetas.
     Solo aplica dentro de .sub; en las cabeceras de seccion (Recintos y ferias, Vigilancia
     competitiva) sigue en linea junto al titulo, que ahi si cabe. */
  .sub .semaforo { display:block; white-space:nowrap; margin-left:0; margin-top:3px; }
  .semaforo.ok { color:var(--ok); }
  .semaforo.warn { color:var(--warn); }
  .semaforo.bad { color:var(--bad); }
  .collapse { background:#13161c; border:1px solid var(--line); color:var(--mut); cursor:pointer;
    font-size:15px; line-height:1; border-radius:6px; padding:4px 9px; }
  .collapse:hover { border-color:var(--acc); color:var(--txt); }
  /* Boton de imagen corporativa (cabecera de la tarjeta) y su pantalla L1-<MARCA>-IDV.
     SEO-TANDA-20260731-11 */
  .idv-btn { background:#13161c; border:1px solid var(--line); color:var(--txt); cursor:pointer;
    font-size:14px; line-height:1; border-radius:6px; padding:4px 9px; }
  .idv-btn:hover { border-color:var(--neon, var(--acc)); }
  .idv-btn.idv-off { opacity:.38; }
  .idv-btn.idv-off:hover { opacity:.7; border-color:var(--warn); }
  .idv-cab { display:flex; gap:16px; align-items:center; flex-wrap:wrap; margin-bottom:14px; }
  .idv-cab img { max-height:52px; max-width:280px; background:#fff; border-radius:6px; padding:6px; }
  .idv-cab .idv-meta { color:var(--mut); font-size:12px; line-height:1.7; }
  .idv-estado { display:inline-block; font-size:11px; font-weight:700; padding:2px 9px;
    border-radius:20px; background:var(--warn); color:#2c2206; }
  .idv-sec { margin:18px 0 6px; font-size:12px; text-transform:uppercase; letter-spacing:.06em;
    color:var(--mut); border-bottom:1px solid var(--line); padding-bottom:5px; }
  .idv-sw { display:flex; flex-wrap:wrap; gap:10px; }
  /* flex:0 0 132px y no solo width: dentro de un flex los botones se encogian hasta 2px,
     porque flex-shrink vale 1 por defecto y el overflow:hidden les quita el ancho minimo
     que impone su contenido. SEO-TANDA-20260731-11 */
  .idv-sw button { flex:0 0 132px; width:132px; border:1px solid var(--line); border-radius:8px;
    padding:0; background:transparent; cursor:pointer; overflow:hidden; text-align:left; }
  .idv-sw button:hover { border-color:var(--acc); }
  .idv-sw .idv-mu { height:52px; display:flex; align-items:flex-end; justify-content:flex-end;
    padding:4px 6px; font:600 10px/1 ui-monospace,Consolas,monospace; }
  .idv-sw .idv-nom { padding:5px 7px 7px; color:var(--txt); font-size:11px; }
  .idv-sw .idv-nom span { display:block; color:var(--mut); font-size:10px; margin-top:2px; }
  .idv-sw .idv-avi { display:block; color:var(--bad); font-size:10px; margin-top:2px; }
  .idv-tabla { width:100%; border-collapse:collapse; font-size:12px; }
  .idv-tabla td { border-bottom:1px solid var(--line); padding:5px 8px; vertical-align:top; }
  .idv-tabla td:first-child { color:var(--mut); white-space:nowrap; width:1%; }
  /* Columna de muestra tipografica: se pinta a tamano real, asi que necesita alinearse
     abajo (para que las lineas base se lean como una escala) y no partirse en dos.
     SEO-TANDA-20260731-12 */
  .idv-tabla td.idv-ej { vertical-align:bottom; color:var(--txt); line-height:1.25;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:420px; }
  .idv-fila-avisa td { background:rgba(240,180,41,.07); }
  .idv-fila-avisa td:first-child { color:var(--warn); }
  .idv-docs { display:flex; flex-direction:column; gap:5px; }
  .idv-docs a { color:var(--acc); font-size:12px; text-decoration:none; }
  .idv-docs a:hover { text-decoration:underline; }
  .idv-docs a.falta { color:var(--bad); pointer-events:none; text-decoration:line-through; }
  .idv-hal-btn { display:block; width:100%; text-align:left; background:#13161c;
    border:1px solid var(--line); border-left:3px solid var(--mut); color:var(--txt);
    border-radius:6px; padding:7px 10px; font-size:12px; cursor:pointer; margin-bottom:5px; }
  .idv-hal-btn:hover { border-color:var(--acc); }
  .idv-hal-btn.g-alta { border-left-color:var(--bad); }
  .idv-hal-btn.g-media { border-left-color:var(--warn); }
  .idv-hal-btn.g-baja { border-left-color:var(--mut); }
  .idv-hal-btn b { font-weight:600; }
  .idv-hal-btn .idv-hal-m { color:var(--mut); font-size:11px; margin-left:6px; }
  .idv-grav { font-size:10px; font-weight:700; text-transform:uppercase; padding:1px 7px;
    border-radius:20px; margin-left:6px; }
  .idv-grav.g-alta { background:var(--bad); color:#2a0606; }
  .idv-grav.g-media { background:var(--warn); color:#2c2206; }
  .idv-grav.g-baja { background:var(--line); color:var(--mut); }
  .idv-vacio { color:var(--mut); font-size:13px; line-height:1.7; }
  .idv-prompt { width:100%; height:230px; background:#0d1015; color:var(--txt);
    border:1px solid var(--line); border-radius:8px; padding:10px; font:11px/1.5
    ui-monospace,Consolas,monospace; resize:vertical; margin-top:8px; }
  /* El asa de arrastre (☰) desaparece en SEO-TANDA-20260812-07: era un boton de 9x14px, un
     blanco diminuto para agarrar una tarjeta entera. Ahora se arrastra por CUALQUIER punto de
     la cabecera, que es una franja de 40px de alto. Los botones que viven dentro de ella
     (imagen corporativa, informe, sesion, ancho, plegar) siguen siendo botones: el arrastre
     se descarta si el raton baja sobre uno de ellos. SEO-TANDA-20260703-02 (asa original) */
  .card-h { cursor:grab; user-select:none; }
  .card-h:active { cursor:grabbing; }
  .card-h button { cursor:pointer; }
  /* Boton de informe exportable (copiar/PDF/TXT/DOCX). SEO-TANDA-20260711-08 */
  .informe-btn { background:#13161c; border:1px solid var(--line); color:var(--mut); cursor:pointer;
    font-size:14px; line-height:1; border-radius:6px; padding:4px 9px; }
  .informe-btn:hover { border-color:var(--acc); color:var(--txt); }
  .card.dragging { opacity:.45; outline:2px dashed var(--acc); outline-offset:-2px; }
  .card.collapsed .card-body { display:none; }
  /* Hueco vacio del tablero: no es una tarjeta (no lleva la clase .card a proposito, para no
     colarse en el plegado, en la igualacion de alturas ni en ningun otro recorrido de
     tarjetas), solo una casilla libre donde soltar una marca. Discreto pero visible, para que
     se entienda que el panel tiene 2 filas de 4 aunque haya 4 marcas. SEO-TANDA-20260812-06 */
  /* Ocultas mientras no se arrastra (SEO-TANDA-20260813-17): con 4 marcas eran hasta 12
     cajas de puntos ocupando el panel de forma permanente, y solo hacen falta cuando se
     esta recolocando una tarjeta. Al no ocupar sitio (display:none) tampoco descolocan
     nada: las tarjetas llevan su posicion escrita, no dependen del flujo. */
  .hueco { display:none; border:1px dashed var(--line); border-radius:12px; min-height:84px; }
  #grid.arrastrando .hueco { display:block; }
  /* Casilla o tarjeta bajo el puntero mientras se arrastra. SEO-TANDA-20260812-07 */
  .hueco.destino, .card.destino { outline:2px solid var(--acc); outline-offset:-2px; }
  /* El ancho extra de una tarjeta de 2, 3 o 4 columnas se reparte de verdad en vez de quedarse
     en blanco: mas columnas de secciones dentro. data-ancho lo escribe pintarTablero().
     SEO-TANDA-20260812-07 (sustituye a la clase .ancha de dos posiciones, SEO-TANDA-20260812-05) */
  .card[data-ancho="2"] .card-secs { grid-template-columns:repeat(4,1fr); }
  .card[data-ancho="3"] .card-secs { grid-template-columns:repeat(6,1fr); }
  .card[data-ancho="4"] .card-secs { grid-template-columns:repeat(6,1fr); }
  .card[data-ancho="3"] .metrics, .card[data-ancho="4"] .metrics { max-width:60%; }
  /* Mismo numero de "puntos" en el selector que las tres reglas de arriba y declarado despues,
     para que gane sin necesidad de !important cuando no hay sitio para tarjetas anchas. */
  @media (max-width:1499px) { .card[data-ancho] .card-secs { grid-template-columns:1fr 1fr; }
    .card[data-ancho] .metrics { max-width:none; } }
  .ancho, .alto { background:#13161c; border:1px solid var(--line); color:var(--mut); cursor:pointer;
    font-size:13px; line-height:1; border-radius:6px; padding:5px 7px; }
  .ancho:hover, .alto:hover { border-color:var(--acc); color:var(--txt); }
  /* Una tarjeta de mas de una fila de alto tiene que estirarse hasta ocuparlas: por defecto la
     rejilla las alinea arriba (align-items:start) y se quedaria de su alto natural, con el
     hueco de debajo vacio y sin poder usarse. SEO-TANDA-20260812-09 */
  .card[data-alto]:not([data-alto="1"]):not(.collapsed) { align-self:stretch; }
  .card:not([data-alto="1"]) .alto { border-color:var(--acc); color:var(--acc); }
  /* El boton se marca en cuanto la tarjeta mide mas de una columna, para que se vea de un
     vistazo cual esta ensanchada. SEO-TANDA-20260812-07 */
  .card:not([data-ancho="1"]) .ancho { border-color:var(--acc); color:var(--acc); }
  .metrics { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; margin:8px 0 8px; }
  /* Movil: 4 columnas se quedan minusculas en pantalla estrecha, pasan a 2x2. SEO-TANDA-20260713-28 */
  @media (max-width:480px) { .metrics { grid-template-columns:repeat(2,1fr); } }
  .metric { cursor:pointer; border:none; font:inherit; color:inherit; text-align:center;
    background:#13161c; border-radius:8px; padding:5px 4px; }
  .metric:hover { outline:1px solid var(--neon, var(--acc)); }
  .metric .num { display:block; font-size:18px; font-weight:700; color:var(--neon, var(--txt)); }
  .metric .lbl { display:block; font-size:10px; color:var(--mut); margin-top:2px; }
  .metric.warn .num { color:var(--warn); }
  .card-secs { display:grid; grid-template-columns:1fr 1fr; gap:6px 14px; align-items:start; }
  @media (max-width:520px) { .card-secs { grid-template-columns:1fr; } }
  /* El min-width:0 es de TODAS las secciones, no solo de las anchas (SEO-TANDA-20260922-25).
     `1fr` es minmax(auto,1fr): una seccion cuyo contenido no parte (una fila de botones con
     white-space:nowrap) le impone a su columna un ancho minimo grande y la rejilla se lo da
     quitandoselo a la otra, asi que las dos columnas dejan de ser mitad y mitad sin que nada
     lo diga. Medido en el panel real a 1900px antes de este arreglo: la fila de dos botones
     de "Clusters" dejaba las columnas de LAM en 150/292 (un 34%/66% en vez de 50/50) y las de
     W2C en 99/293 (25%/75%), y de rebote las cuatro tarjetas salian de anchos distintos
     (LAM 488, W2C 439, GP y De Bares 394) porque ese minimo tambien sube el de la tarjeta.
     Con esta linea, las columnas salen 192/192 y las cuatro tarjetas 429. Es la generalizacion
     de lo que SEO-TANDA-20260818-19 ya habia tenido que hacer para .ancha-total, aqui debajo:
     el mismo sintoma aparecio dos veces, asi que el arreglo deja de ser una excepcion. */
  .card-secs .seccion { min-width:0; }
  /* Seccion a lo ancho de toda la tarjeta, sean las que sean las columnas de .card-secs
     (2 normales, 4 o 6 en tarjetas anchas). Hoy solo la usa "Recintos y ferias", que va la
     ultima y lleva cuatro botones en fila: dentro de media tarjeta sus rotulos se quedaban
     en unos 50px. El min-width:0 no es decorativo, es la mitad del arreglo: sin el, la fila
     de botones (que no parte el texto) le imponia a su columna un ancho minimo grande y la
     rejilla se lo daba quitandoselo a la otra, que es por lo que "Investigacion" se quedo
     estrecha y partia "11 / investigaciones" en dos lineas. SEO-TANDA-20260818-19 */
  .card-secs .seccion.ancha-total { grid-column:1/-1; min-width:0; }
  /* Bloque «Autonomía del stock» (I-090 Fase 3, SEO-TANDA-20261022-30). Son las reglas de la
     maqueta que aprobo el usuario (la «C ajustada», informe 004 §7), copiadas y no
     reinventadas, y TODAS acotadas a .auto-stock: ninguna cambia una clase existente. Las dos
     filas son .metrics normales, asi que heredan su paso de 4 a 2 columnas por debajo de 480
     px y el deshacerlo del movil girado. Los escenarios van a 13 px con un alto de linea fijo
     de 22 px: a ancho 1 cada celda tiene unos 87 px utiles, a 15 px las fechas se partian, y
     los 22 px dejan la celda del mismo alto que las de la fila de cifras. A ancho 3 y 4 las
     dos filas siguen la regla de las cifras de la cabecera (max-width:60%) y quedan alineadas
     con ellas, columna con columna, y el titulo se acorta igual para que la palabra de estado
     no se quede sola en el borde derecho: decidido mirandolo a ancho 3 (informe 005 de I-090).
     Por debajo de 1500 px se deshace, como la de .metrics. */
  .auto-stock[data-list] { cursor:pointer; }
  .auto-stock .sec-tit { display:flex; align-items:baseline; gap:8px; }
  .auto-stock .as-estado { margin-left:auto; font-weight:700; white-space:nowrap; }
  .as-estado.crece { color:var(--ok); }
  .as-estado.se-gasta { color:var(--warn); }
  .as-estado.estable { color:var(--mut); }
  .as-estado.no-comprobado { color:var(--bad); }
  .auto-stock .as-pie { font-size:11px; color:var(--mut); margin-top:4px; }
  .auto-stock .metrics { margin:8px 0 6px; }
  .auto-stock .esc .num { font-size:13px; line-height:22px; }
  .card[data-ancho="3"] .auto-stock .sec-tit, .card[data-ancho="4"] .auto-stock .sec-tit { max-width:60%; }
  @media (max-width:1499px) { .card[data-ancho] .auto-stock .sec-tit { max-width:none; } }
  /* Su detalle, encima de la tabla de L2-<MARCA>-OPP (cabecera_autonomia). */
  .as-cab { font-size:12.5px; line-height:1.6; background:#13161c; border-radius:8px;
    padding:9px 12px; margin:0 0 10px; }
  .sec-tit { font-size:11px; text-transform:uppercase; letter-spacing:.5px; color:var(--mut); margin:6px 0 4px; }
  .chips { display:flex; flex-direction:column; gap:6px; align-items:stretch; }
  .chip { cursor:pointer; font:inherit; font-size:12px; background:#13161c; border:1px solid var(--line);
    border-radius:6px; padding:5px 9px; color:inherit; text-align:left;
    display:flex; align-items:baseline; gap:7px; }
  .chip:hover { border-color:var(--neon, var(--acc)); }
  .chip b { color:var(--neon, var(--acc)); min-width:20px; text-align:right;
    font-variant-numeric:tabular-nums; }
  .vacio { color:var(--mut); font-size:13px; font-style:italic; }
  .inv { font-size:13px; }
  .inv-btn { cursor:pointer; border:none; background:#13161c; color:inherit; font:inherit;
    font-size:12px; text-align:left; border-radius:6px; padding:5px 8px; width:100%; }
  .inv-btn:hover { outline:1px solid var(--neon, var(--acc)); }
  /* Boton de material sin fichar (hoy, los candidatos a hueco): mismo tamano y sitio que
     los demas, pero en gris, para que se lea como "hay esto ahi" y no como trabajo
     comprometido. SEO-TANDA-20260826-07 */
  .inv-btn.btn-tenue { color:var(--mut); }
  .inv-btn.btn-tenue:hover { color:inherit; }
  .btn-row { display:flex; gap:6px; }
  .btn-row .inv-btn { flex:1; text-align:center; white-space:nowrap;
    overflow:hidden; text-overflow:ellipsis; }
  /* Variante de dos botones ALINEADOS con las dos columnas de la tarjeta, no repartidos dentro
     de media (SEO-TANDA-20260922-25). Hoy la usa "Clusters", que es una seccion ancha-total con
     un boton por columna: el `1fr 1fr` y el column-gap de 14px son los mismos de .card-secs, asi
     que el boton de la izquierda empieza y acaba donde "Pipeline por estado" y el de la derecha
     donde "Investigacion". En una tarjeta ensanchada (4 o 6 columnas) siguen cuadrando, porque
     el 50% de un numero par de columnas iguales cae siempre en un borde de columna. */
  .btn-row.cols { display:grid; grid-template-columns:repeat(2,1fr); column-gap:14px; }
  .sub { color:var(--mut); font-size:12px; margin-top:4px; }
  /* Linea de aviso con el mismo tono que las metricas en alerta (SEO-TANDA-20260827-17). */
  .sub.warn { color:var(--warn); }
  /* Rojo de la linea de anotaciones de la tarjeta: solo lo enciende una pieza con notas en
     listo_para_cms, y tambien el "no comprobado". (I-028 Fase 3, SEO-TANDA-20260922-13) */
  .sub.alerta { color:var(--bad); }
  .sub .inv-btn { padding:2px 6px; color:inherit; }
  /* Marcador de anotaciones en una fila de Pipeline/Publicados. */
  .ano-badge { font-size:11px; color:var(--warn); white-space:nowrap; }
  .ano-badge.rojo { color:var(--bad); font-weight:600; }
  footer { color:var(--mut); font-size:12px; margin-top:28px; border-top:1px solid var(--line); padding-top:12px; }
  /* El margen de la capa baja de 40 a 20px (SEO-TANDA-20260812-06) para que quepa el
     max-height nuevo de .modal-box: 92vh + 2x20px de margen sigue entrando en la ventana,
     mientras que con 40px se salia y el modal quedaba cortado por abajo. */
  .modal { position:fixed; inset:0; background:rgba(0,0,0,.6); display:none;
    align-items:flex-start; justify-content:center; padding:20px 16px; z-index:50; }
  .modal.open { display:flex; }
  /* Topes de ancho subidos en SEO-TANDA-20260812-05, en la misma linea que el ancho del
     panel (.wrap, SEO-TANDA-20260812-04): el normal pasa de 920 a 1400 (el ancho que hasta
     ahora era el "ensanchado", ya probado y conocido) y el ensanchado de 1400 a 1800, que
     es lo que da un monitor de 1920. Las listas largas (L1-ARC con cientos de archivos,
     L1-ACT, L1-TAR) eran las que mas sufrian los 920px: cortaban titulos por falta de sitio
     teniendo la pantalla vacia a los lados. `width:100%` sigue mandando por debajo del tope,
     asi que en pantallas estrechas no cambia nada. */
  .modal-box { background:var(--card); border:1px solid #ffffff; border-radius:12px;
    max-width:1400px; width:100%; max-height:92vh; overflow:hidden;
    display:flex; flex-direction:column;
    /* Entro para poder colocar dentro el indicador de desplazamiento de la vista girada,
       que se retiro en SEO-TANDA-20260923-01. Se queda porque es inocuo (el reparto lo hace
       el flex) y porque es lo que cualquier cosa posicionada dentro del modal necesitaria. */
    position:relative; }
  /* Modal ensanchado: lo usan el mapa de pantallas (L1-PAN), el mapa de Europa
     (L3-CAL-PRG-GEO) y la vista horaria (L3-CAL-PRG-HOR), que necesitan mas columnas de las
     que caben en el ancho normal. abrirMapaPantallas() la añade y abrirModal()/cerrarModal()
     la quitan al salir de esa vista. SEO-TANDA-20260715-12 */
  .modal-box.wide { max-width:1800px; }
  .modal-h { display:flex; justify-content:space-between; align-items:center; padding:14px 16px;
    border-bottom:1px solid var(--line); background:var(--card); flex:0 0 auto; }
  .modal-h b { font-size:15px; min-width:0; }
  .modal-h-r { display:flex; align-items:center; gap:10px; flex:0 0 auto; margin-left:12px; }
  .modal-h button { background:none; border:none; color:var(--mut); font-size:18px; cursor:pointer; }
  /* Buscador local de una lista (hoy L1-ACT, L1-TAR y L1-IDE, ver modalBuscable en el JS):
     oculto por defecto, solo se muestra cuando abrirModal() detecta una de esas dos
     pantallas. Filtra en cliente sobre modalRowsAll sin tocar el buscador global de
     arriba (#buscar), que desde SEO-TANDA-20260722-06 cruza id+texto+estado+det (incluye
     el titulo real del articulo, Titulo (H1)). SEO-TANDA-20260713-26 */
  .modal-search { display:none; padding:10px 16px; border-bottom:1px solid var(--line);
    background:var(--card); flex:0 0 auto; gap:8px; }
  .modal-search.open { display:flex; }
  .modal-search input { flex:1 1 auto; min-width:0; background:#13161c; border:1px solid var(--line);
    border-radius:8px; color:var(--txt); padding:8px 12px; font-size:13px; box-sizing:border-box; }
  /* Filtros de PC/Marca/Estado (solo L1-ACT, ver modalPcFiltro/modalMarcaFiltro/
     modalEstadoFiltro en el JS): ocultos por defecto y solo visibles cuando la lista
     abierta es Actividad de chats, para acotar ademas del texto libre. La regla usa la
     clase .modal-filtro (compartida por los tres <select>) en vez de sus id propios:
     un primer intento con selectores por id (#modal-pc-filtro.open) parecia funcionar
     pero en realidad el <select> nunca tenia esa clase, asi que la regla no llegaba a
     coincidir nunca; se detecto al verificar en vivo que el desplegable de PC quedaba
     visible tambien en Tareas pendientes. SEO-TANDA-20260721-03; Marca/Estado SEO-TANDA-20260721-04 */
  .modal-filtro { display:none; flex:0 0 auto; background:#13161c; border:1px solid var(--line);
    border-radius:8px; color:var(--txt); padding:8px 10px; font-size:13px; box-sizing:border-box; }
  .modal-filtro.open { display:block; }
  /* Casilla «Solo en curso» de L1-ACT (SEO-TANDA-20261002-35): misma caja que los
     desplegables, para que la barra no cambie de aspecto, con la casilla y su texto en linea. */
  .modal-filtro.modal-check.open { display:flex; align-items:center; gap:6px; white-space:nowrap;
    cursor:pointer; user-select:none; }
  .modal-check input { margin:0; cursor:pointer; }
  /* Etiqueta de procedencia de una oportunidad y aviso de lectura de una lista (I-080 Fase 4,
     SEO-TANDA-20260927-14). El color solo ayuda a distinguirlas de un vistazo; el valor se
     lee siempre en el texto. `sin_procedencia` va en rojo porque tras la Fase 3 no deberia
     existir ninguna. */
  .opp-proc { display:inline-block; font-size:11px; padding:1px 7px; border-radius:9px;
    border:1px solid var(--line); white-space:nowrap; }
  .opp-proc-nocturna { color:#7fb2ff; border-color:#34507a; }
  .opp-proc-manual { color:#3fae6a; border-color:#2f5c42; }
  .opp-proc-vigilancia { color:#a97bd6; border-color:#4f3a66; }
  .opp-proc-chat { color:#f0b429; border-color:#6b5320; }
  .opp-proc-otros { color:#9aa3b2; }
  .opp-proc-sin_procedencia { color:var(--bad); border-color:var(--bad); }
  .aviso-lectura { color:var(--warn); margin:0 0 10px; }
  /* ID de pantalla (nomenclatura obligatoria, ver 06_control/nomenclatura_pantallas_panel.md):
     etiqueta discreta junto al boton de cerrar, para poder citar la pantalla exacta al
     reportar algo ("hay un problema en L3-LAM-PIP-DET") sin tener que abrir DevTools. Un clic
     copia el ID y el nombre legible al portapapeles. */
  .screen-id { font-family:ui-monospace,Consolas,monospace; font-size:11px; color:var(--mut);
    padding:2px 7px; border:1px solid var(--line); border-radius:4px; white-space:nowrap;
    cursor:pointer; background:none; }
  .screen-id:hover { border-color:var(--acc); color:var(--txt); }
  /* Ayuda interactiva (I-064 Fase 2, SEO-TANDA-20260913-20): boton ? junto al badge del ID
     (en L0 y en la cabecera del modal) y cajon lateral. El cajon NO es una pantalla de la
     nomenclatura: no navega, no entra en la pila de modales, no tiene ID ni historial, y
     convive con la pantalla abierta (mismo criterio que los popovers del chip y de
     Escritorio). Por eso va por encima del modal (50) y de los popovers (60). */
  .ay-btn { font-weight:700; color:var(--acc); border-color:var(--acc); }
  .ay-btn:hover { background:#0f1822; }
  .ay-cajon { position:fixed; top:0; right:0; bottom:0; width:470px; max-width:94vw; z-index:70;
    background:var(--card); border-left:1px solid var(--line); box-shadow:-8px 0 24px rgba(0,0,0,.55);
    display:none; flex-direction:column; }
  .ay-cajon.open { display:flex; }
  .ay-h { display:flex; align-items:center; gap:10px; padding:12px 14px; border-bottom:1px solid var(--line);
    flex:0 0 auto; }
  .ay-h b { flex:1 1 auto; font-size:14px; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ay-h .screen-id { flex:0 0 auto; }
  .ay-nav { display:flex; gap:6px; padding:8px 14px; border-bottom:1px solid var(--line); flex:0 0 auto;
    flex-wrap:wrap; }
  .ay-nav button { background:#13161c; border:1px solid var(--line); color:var(--mut); border-radius:6px;
    padding:3px 9px; font-size:12px; cursor:pointer; }
  .ay-nav button.activo, .ay-nav button:hover { color:var(--txt); border-color:var(--acc); }
  .ay-b { padding:12px 16px; overflow:auto; flex:1 1 auto; min-height:0; font-size:13px; line-height:1.5; }
  .ay-b h2 { font-size:12px; margin:16px 0 4px; color:var(--acc); text-transform:uppercase; letter-spacing:.05em; }
  .ay-b h2:first-child { margin-top:0; }
  .ay-b h3 { font-size:13px; margin:12px 0 4px; }
  .ay-b p { margin:0 0 8px; }
  .ay-b ul, .ay-b ol { margin:0 0 8px; padding-left:20px; }
  .ay-b li { margin:2px 0; }
  .ay-b code { font-family:ui-monospace,Consolas,monospace; font-size:12px; background:#13161c;
    padding:1px 4px; border-radius:3px; }
  .ay-b pre { font-family:ui-monospace,Consolas,monospace; font-size:12px; background:#13161c;
    padding:8px 10px; border-radius:6px; overflow:auto; white-space:pre-wrap; }
  .ay-b table { border-collapse:collapse; width:100%; margin:0 0 8px; font-size:12px; }
  .ay-b th, .ay-b td { border:1px solid var(--line); padding:4px 6px; vertical-align:top; text-align:left; }
  .ay-b th { color:var(--mut); font-weight:600; }
  .ay-b .ay-id { background:none; border:1px solid var(--line); border-radius:4px; color:var(--acc);
    cursor:pointer; font-family:ui-monospace,Consolas,monospace; font-size:11px; padding:0 4px; }
  .ay-b .ay-id:hover { border-color:var(--acc); }
  .ay-b .ay-meta { color:var(--mut); font-size:11px; margin-top:14px; border-top:1px solid var(--line);
    padding-top:6px; }
  .ay-b .ay-pend { color:var(--mut); font-size:11px; }
  .ay-nota { color:var(--mut); font-size:12px; margin:0 0 10px; padding:6px 8px; border-left:3px solid var(--warn);
    background:#13161c; }
  .ay-nota.mal { border-left-color:var(--bad); color:var(--txt); }
  .ay-f { padding:8px 14px; border-top:1px solid var(--line); color:var(--mut); font-size:11px; flex:0 0 auto; }
  .ay-f.aviso { color:var(--warn); }
  .ay-f.mal { color:var(--bad); }
  /* Ayuda del panel, L1-AYU (I-064 Fase 8, SEO-TANDA-20260913-27): buscador, indice y buzon. */
  .ayi-intro { color:var(--mut); font-size:13px; margin:0 0 10px; }
  .ayi-busca { display:flex; gap:8px; margin:0 0 8px; }
  .ayi-busca input { flex:1 1 auto; background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:7px 10px; font-size:13px; min-width:0; }
  .ayi-busca input:focus { outline:none; border-color:var(--acc); }
  .ayi-busca button, .ayi-barra button { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:6px 12px; font-size:12px; cursor:pointer; }
  .ayi-busca button:hover, .ayi-barra button:hover { border-color:var(--acc); }
  .ayi-res { font-size:13px; line-height:1.5; margin:0 0 12px; }
  .ayi-lista { margin:0 0 8px; padding-left:22px; }
  .ayi-lista li { margin:4px 0; }
  .ayi-lista small { color:var(--mut); }
  .ayi-tipo { color:var(--mut); font-size:11px; text-transform:uppercase; letter-spacing:.05em; }
  .ayi-barra { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin:8px 0 14px; font-size:12px; }
  .ayi-ok { color:var(--ok); } .ayi-pend { color:var(--warn); } .ayi-mal { color:var(--bad); }
  .ayi-chequeo { font-size:12px; margin:-6px 0 14px; }
  .ayi h3 { font-size:12px; margin:16px 0 6px; color:var(--acc); text-transform:uppercase; letter-spacing:.05em; }
  .ayi-tabla { border-collapse:collapse; width:100%; font-size:12px; margin:0 0 8px; }
  .ayi-tabla th, .ayi-tabla td { border:1px solid var(--line); padding:4px 6px; text-align:left; vertical-align:top; }
  .ayi-tabla th { color:var(--mut); font-weight:600; }
  .ayi .ay-id, .ayi-res .ay-id { background:none; border:1px solid var(--line); border-radius:4px; color:var(--acc);
    cursor:pointer; font-family:ui-monospace,Consolas,monospace; font-size:11px; padding:0 4px; }
  .ayi .ay-id:hover, .ayi-res .ay-id:hover { border-color:var(--acc); }
  .ayi-apuntar { color:var(--acc); text-decoration:underline; }
  .ayi-apuntar.hecho { color:var(--ok); text-decoration:none; }
  /* «Preguntaselo a Claude» y las respuestas archivadas (I-064 Fase 9, SEO-TANDA-20260913-28) */
  .ayi-claude-p { margin:10px 0 6px; padding:8px 10px; border:1px dashed var(--line); border-radius:6px; }
  .ayi-claude { color:var(--acc); text-decoration:underline; font-weight:600; }
  .ayi-claude.hecho { color:var(--ok); text-decoration:none; font-weight:400; }
  .ayi-abrir { color:var(--acc); text-decoration:underline; }
  .ayi-res pre, .ayi-res code, .ayi code { font-family:ui-monospace,Consolas,monospace; font-size:12px;
    background:#13161c; padding:1px 4px; border-radius:3px; }
  .ayi-res pre { padding:8px 10px; white-space:pre-wrap; }
  .ayi-res .ay-nota { margin-bottom:8px; }
  #modal-body { padding:12px 16px; overflow:auto; flex:1 1 auto; min-height:0; }
  /* Mapa de pantallas (mapa mental jerarquico, L1-PAN): SVG generado en JS a partir de
     MAPA_ESTRUCTURA (misma fuente que 06_control/nomenclatura_pantallas_panel.md).
     SEO-TANDA-20260715-12 */
  /* #modal-body trae padding-top:12px de serie (comun a todas las vistas del modal); ese
     padding es zona de scroll normal (overflow:auto no lo excluye), asi que el contenido
     desplazado se colaba por esa rendija de 12px justo por ENCIMA de la barra fija (probado:
     un negative margin en .mp-toolbar no la desplazaba, el "top:0" de sticky se ancla al
     borde interior del padding, no al borde real del contenedor). Solucion mas simple y
     robusta: quitar el padding-top de #modal-body solo en esta vista (clase .mp-view, la
     ponen/quitan abrirMapaPantallas()/abrirModal()/cerrarModal() igual que .wide) y devolver
     ese hueco como margen propio de .mp-legend, que es el primer elemento de la vista.
     SEO-TANDA-20260715-15 */
  #modal-body.mp-view { padding-top:0; }
  .mp-legend { color:var(--mut); font-size:12px; margin:12px 0 10px; line-height:1.5; }
  /* Fijo arriba de #modal-body (su ancestro con scroll) mientras se desplaza el mapa: el mapa
     puede medir varios miles de px de alto, y sin esto los controles de zoom/reducir-ampliar
     se perdian de vista nada mas bajar unas pantallas. SEO-TANDA-20260715-14 */
  .mp-toolbar { display:flex; align-items:center; gap:8px; margin-bottom:10px; flex-wrap:wrap;
    position:sticky; top:0; z-index:5; background:var(--card); padding:8px 0;
    border-bottom:1px solid var(--line); }
  .mp-toolbar button { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:4px 10px; font-size:12px; cursor:pointer; }
  .mp-toolbar button:hover { border-color:var(--acc); }
  .mp-zoom-pct { color:var(--mut); font-size:12px; min-width:38px; text-align:center; }
  /* overflow:auto (no "hidden") es lo que permite acercarse/alejarse en el eje que sobre y
     desplazarse (scroll nativo) cuando el mapa no cabe entero, incluidas las zonas mas a la
     izquierda/arriba: antes la raiz quedaba recortada por un bug de posicion, no por falta de
     scroll. Ver mpBordeIzq(). SEO-TANDA-20260715-13 */
  .mp-wrap { overflow:auto; }
  .mp-node rect { fill:#13161c; stroke:var(--line); }
  .mp-node.mp-root rect { stroke:var(--acc); }
  .mp-node.mp-clicable { cursor:pointer; }
  .mp-node.mp-clicable:hover rect { stroke:var(--acc); }
  .mp-node text { fill:var(--txt); font-size:10.5px; font-family:inherit; pointer-events:none; }
  .mp-link { fill:none; stroke:var(--line); stroke-width:1.4; }
  .mp-toggle { cursor:pointer; }
  .mp-toggle circle { fill:#13161c; stroke:var(--line); }
  .mp-toggle:hover circle { stroke:var(--acc); }
  .mp-toggle text { fill:var(--txt); font-family:inherit; pointer-events:none; }
  .mp-toggle text.mp-badge { fill:var(--mut); text-anchor:start; }
  /* Icono "ir a esta pantalla" (flecha diagonal): mismo lenguaje visual que .mp-toggle,
     pero en el acento de marca para diferenciarlo de un vistazo (navegar, no plegar/copiar).
     SEO-TANDA-20260721-09 */
  .mp-go { cursor:pointer; }
  .mp-go circle { fill:#13161c; stroke:var(--acc); }
  .mp-go path { fill:none; stroke:var(--acc); stroke-width:1.3; stroke-linecap:round; stroke-linejoin:round; }
  .mp-go:hover circle { fill:var(--acc); }
  .mp-go:hover path { stroke:#0b0e14; }
  /* Destello breve sobre la tarjeta de marca en L0 al llegar ahi desde el icono "ir a esta
     pantalla" del mapa de pantallas, para que el usuario ubique el destino de un vistazo. */
  @keyframes mp-flash-anim { from { box-shadow:0 0 0 3px var(--acc); } to { box-shadow:0 0 0 3px transparent; } }
  .card.mp-flash { animation: mp-flash-anim 1.1s ease-out; }
  .tbl { width:100%; border-collapse:collapse; font-size:13px; }
  .tbl th, .tbl td { text-align:left; padding:6px 8px; border-bottom:1px solid var(--line); vertical-align:top; }
  .tbl th { color:var(--mut); font-weight:600; font-size:11px; text-transform:uppercase; }
  /* El thead se para justo DEBAJO de la barra de acciones fija (.modal-acc), no detras de
     ella: --acc-h la mide setModalBody() en cada pintado, y vale 0 en las vistas que no
     tienen barra (y en las tablas de fuera del modal, por el valor de reserva).
     SEO-TANDA-20260826-08 */
  .tbl thead th { position:sticky; top:var(--acc-h,0px); background:var(--card); z-index:1;
    box-shadow:inset 0 -1px 0 var(--line); }
  /* Barra de botones de una lista del modal, fija arriba mientras se desplaza la tabla
     (SEO-TANDA-20260826-08, pedido del usuario): en una lista larga como el registro de
     ideas los filtros se perdian de vista al segundo scroll, justo cuando hacen falta.
     El top:-12px con margin/padding de 12 es el mismo apano ya probado en .roadmap-head y
     .hor-head: #modal-body trae padding-top:12px y el "top:0" de sticky se ancla al borde
     interior de ese padding, asi que sin esto el contenido se cuela por la rendija. */
  .modal-acc { position:sticky; top:-12px; z-index:5; background:var(--card);
    margin:-12px -2px 10px; padding:12px 2px 8px; border-bottom:1px solid var(--line);
    display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
  .modal-acc .volver { margin-bottom:0; }
  /* Un contenedor de barra que caiga DENTRO de la barra (porque delante iban botones
     sueltos) ocupa su propia linea completa: si no, .det-topbar pierde su space-between. */
  .modal-acc-wrap > .arc-breadcrumb, .modal-acc-wrap > .det-topbar,
  .modal-acc-wrap > .det-nav, .modal-acc-wrap > .det-prompts { flex:1 1 100%; margin-bottom:0; }
  /* La vista del mapa de pantallas ya tiene su propia barra fija (.mp-toolbar) y ademas
     anula el padding-top del cuerpo, del que depende el top:-12px de arriba: ahi no se
     envuelve nada (lo salta envolverAccModal) y esta regla es la red por si algun dia se
     cuela una. SEO-TANDA-20260826-08 */
  #modal-body.mp-view .modal-acc { top:0; margin-top:0; padding-top:0; }
  .tbl th.num-col, .tbl td.num-col { width:1%; text-align:right; color:var(--mut);
    font-variant-numeric:tabular-nums; white-space:nowrap; padding-right:10px; }
  .tbl th.sortable { cursor:pointer; user-select:none; white-space:nowrap; }
  .tbl th.sortable:hover { color:var(--acc); }
  .tbl a { color:var(--acc); }
  .tbl td.links { white-space:nowrap; }
  /* Evita que "De Bares" (y otras marcas de dos palabras) se parta en dos lineas cuando
     la columna Marca se estrecha por columnas vecinas con contenido largo (ID, Archivos).
     SEO-TANDA-20260722-05 */
  .tbl td.marca-col { white-space:nowrap; }
  /* L1-ACT: anchos fijos (PN1, SEO-TANDA-20261020-66). Siete columnas cortas con ancho
     propio y sin salto de linea; TEMA (c-texto) no lleva ancho y se queda con el resto.
     En pantalla estrecha la tabla conserva un minimo y se desplaza DENTRO de su caja, no
     la pagina (la cabecera pegajosa solo se pierde ahi, por el overflow del contenedor). */
  .tbl-act { table-layout:fixed; width:100%; }
  /* Mismo ancho con y sin «Solo en curso» (PN3, SEO-TANDA-20261020-68): la barra vertical de
     #modal-body solo aparece con muchas filas y quitaba ~15 px a la tabla; se reserva su sitio
     siempre, solo cuando el modal lleva la lista de actividad. */
  #modal-body:has(.tbl-act-wrap) { scrollbar-gutter:stable; }
  .tbl-act col.c-num { width:48px; }
  .tbl-act col.c-marca { width:112px; }
  .tbl-act col.c-pc { width:66px; }
  .tbl-act col.c-agente_txt { width:98px; }
  .tbl-act col.c-cliente_txt { width:72px; }
  .tbl-act col.c-fecha_chat { width:62px; }
  .tbl-act col.c-estado { width:96px; }
  .tbl-act col.c-url { width:72px; }
  .tbl-act th, .tbl-act td { overflow:hidden; text-overflow:ellipsis; }
  .tbl-act th.num-col, .tbl-act td.num-col { width:auto; }
  .tbl-act th, .tbl-act td { white-space:nowrap; }
  .tbl-act td:nth-child(7) { white-space:normal; overflow-wrap:anywhere; text-overflow:clip; }
  /* Marca sin salto salvo las filas con varias marcas (hay 17 con las cuatro: "LAM · W2C
     · GP · De Bares" no cabe en 112 px y recortarlo escondia datos): ahi parte por los " · ". */
  .tbl-act td.marca-col { white-space:normal; text-overflow:clip; }
  @media (max-width:760px) {
    .tbl-act-wrap { overflow-x:auto; }
    .tbl-act { min-width:700px; }
  }
  .mono { font-family:ui-monospace,Consolas,monospace; color:var(--acc); white-space:nowrap; }
  .tbl button.idlink, .tbl button.verdet { background:none; border:none; color:var(--acc);
    font:inherit; cursor:pointer; padding:0; }
  .tbl button.idlink { text-decoration:underline; }
  /* Navegacion por carpetas de L1-ARC (Archivos del sistema). SEO-TANDA-20260722-15 */
  .arc-breadcrumb { display:flex; flex-wrap:wrap; align-items:center; gap:4px; margin-bottom:12px; }
  .arc-breadcrumb .volver { margin-bottom:0; }
  .arc-sep { color:var(--mut); }
  .arc-fila-carpeta { cursor:pointer; }
  .arc-fila-carpeta:hover td { color:var(--acc); }
  .volver { background:#13161c; border:1px solid var(--line); color:var(--txt); border-radius:6px;
    padding:6px 10px; font-size:12px; cursor:pointer; margin-bottom:12px; }
  .volver:hover { border-color:var(--acc); }
  .volver:disabled { opacity:.35; cursor:default; }
  .volver:disabled:hover { border-color:var(--line); }
  .toggle-img.activo, .toggle-rep.activo, .toggle-meta.activo, .toggle-ideas.activo { border-color:var(--acc); color:var(--acc); font-weight:600; }
  /* Navegar a anterior/siguiente sin volver a la lista. SEO-TANDA-20260706-07 */
  .det-topbar { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px; }
  .det-nav { display:flex; align-items:center; gap:8px; margin-bottom:12px; }
  .det-prompts { display:flex; align-items:center; gap:8px; margin-bottom:12px; }
  .det-prompts .volver { margin-bottom:0; }
  /* Boton RoadMap (L4-<MARCA>-PIP-DET-ROA): texto amarillo para distinguirlo a simple
     vista del resto de botones de la ficha de pipeline. SEO-TANDA-20260726-02 */
  .det-roadmap-btn { color:#ffe600; }
  .det-roadmap-btn:hover { border-color:#ffe600; }
  /* Roadmap vertical: linea de tiempo con los pasos del flujo base (idea -> ... ->
     publicado), estado hecho/actual/futuro segun donde este realmente el contenido.
     SEO-TANDA-20260726-02 */
  .roadmap-vert { margin-top:8px; }
  .roadmap-paso { display:flex; gap:12px; position:relative; padding-bottom:22px; }
  .roadmap-paso:last-child { padding-bottom:0; }
  .roadmap-paso:not(:last-child)::before { content:''; position:absolute; left:9px; top:22px;
    bottom:0; width:2px; background:var(--line); }
  /* Marcador vacio a proposito (sin glifo interior: ni check, ni punto, ni circulo hueco):
     el estado se lee solo por el color del borde y el conector, no por un simbolo dentro.
     SEO-TANDA-20260726-11, a peticion del usuario ("quita el punto del centro del circulo,
     dejalo vacio"). */
  .roadmap-marcador { flex:0 0 auto; width:20px; height:20px; border-radius:50%;
    border:2px solid var(--line); background:var(--card); z-index:1; }
  /* "hecho"/"actual" usan el color de marca (--roadmap-neon, fijado inline por verRoadmap()
     con neonPorMarca()) en vez de un verde/amarillo generico. SEO-TANDA-20260726-08. */
  .roadmap-paso.roadmap-hecho .roadmap-marcador { border-color:var(--roadmap-neon,var(--ok)); }
  .roadmap-paso.roadmap-hecho:not(:last-child)::before { background:var(--roadmap-neon,var(--ok)); }
  .roadmap-paso.roadmap-actual .roadmap-marcador { border-color:var(--roadmap-neon,#ffe600); }
  .roadmap-txt { flex:1 1 auto; padding-top:1px; }
  .roadmap-lbl { font-size:13.5px; color:var(--txt); }
  /* Pasos pendientes (futuro) en amarillo, marcador y texto, a peticion del usuario
     (SEO-TANDA-20260726-11: "los puntos pendientes seguiran en amarillo"). Fijo, no usa
     --roadmap-neon: es la misma senal de atencion que ya llevan el boton RoadMap y las
     insignias de pausa, no un color de marca. */
  .roadmap-paso.roadmap-futuro .roadmap-marcador { border-color:#ffe600; }
  .roadmap-paso.roadmap-futuro .roadmap-lbl { color:#ffe600; }
  .roadmap-paso.roadmap-actual .roadmap-lbl { color:var(--roadmap-neon,#ffe600); font-weight:600; }
  /* Paso en alerta (RoadMap de ideas, SEO-TANDA-20260809-05): puerta rebasada sin pasar
     o conflicto activo. Rojo fijo, misma senal que la fila roja del tablon L1-IDE. */
  .roadmap-paso.roadmap-alerta .roadmap-marcador { border-color:#e05252; }
  .roadmap-paso.roadmap-alerta .roadmap-lbl { color:#e05252; font-weight:600; }
  .roadmap-paso.roadmap-alerta:not(:last-child)::before { background:#e05252; }
  /* Paso en espera (dependencia de otra idea sin terminar): ambar, mismo color que la
     barra de una idea en espera del tablon. SEO-TANDA-20260809-05 */
  .roadmap-paso.roadmap-espera .roadmap-marcador { border-color:#d9a03f; }
  .roadmap-paso.roadmap-espera .roadmap-lbl { color:#d9a03f; font-weight:600; }
  /* ===== Mapa de dependencias entre ideas (L2-IDE-MAP, SEO-TANDA-20260818-04) =====
     Cascada de desbloqueo: el eje horizontal son OLAS (turnos de arranque), no fechas.
     Forma elegida por el usuario entre cinco maquetas comparadas con datos reales, en
     `.Docs/2026-08-17_mapa-dependencias-ideas/`. Las guias de arbol unen cada barra con
     la de su bloqueante; cada tramo vertical cubre el hueco de ARRIBA y termina en su
     borde inferior, contiguo con el siguiente y nunca superpuesto (con solape, las
     uniones se pintaban dos veces y, al ser la linea semitransparente, aparecian rayitas
     mas gruesas). El morado es el CUELLO DE BOTELLA: la idea que tiene otras esperandola.
     Se pinta asi solo si ella misma no esta bloqueada; si lo esta, conserva su rojo y lo
     dice con la insignia del recuento, porque una alerta activa manda sobre la etiqueta
     estructural. */
  /* Insignia de cuello de botella del tablon L1-IDE (SEO-TANDA-20260818-05). Morado
     elegido por el usuario: es un cuarto eje, distinto de los tres colores de estado
     (rojo bloqueada, ambar dependiente, verde disponible), porque no dice como esta la
     idea sino a cuantas esta frenando. Por eso convive con ellos: una idea puede estar
     bloqueada Y ser cuello de botella a la vez. */
  .idea-cuello{font-size:11px;color:#a97bd6;border:1px solid #a97bd6;border-radius:20px;
    padding:1px 8px;white-space:nowrap}
  /* Conflicto (SEO-TANDA-20260818-06): color propio, ni el morado del cuello ni los tres
     de estado. Naranja mientras es latente (declarado pero sin efecto todavia) y rojo en
     cuanto se activa, que es cuando las dos ideas estan en ejecucion a la vez. */
  .idea-conf{font-size:11px;color:#e0803c;border:1px solid #e0803c;border-radius:20px;
    padding:1px 8px;white-space:nowrap}
  .idea-conf.activo{color:#e05252;border-color:#e05252;font-weight:600}
  /* OBSOLETO (SEO-TANDA-20260922-10): una de las dos ideas ya no esta viva, asi que el
     conflicto no puede darse. Se TACHA en vez de retirarse (decision del usuario): el chip
     y el texto siguen en su naranja, y la raya del tachado va en gris, que es lo que dice
     «esto ya no cuenta» sin cambiar de que se esta hablando. La opacidad baja un poco para
     que en una lista larga el ojo salte a los que si cuentan. */
  .idea-conf.obsoleto{text-decoration:line-through;text-decoration-color:#8a94a3;
    text-decoration-thickness:1px;opacity:.78}
  /* Recien desbloqueada (I-047 Fase 4, SEO-TANDA-20260921-10): verde, el color de «ya se
     puede seguir», el mismo del distintivo de fecha cumplida. Se apaga sola al avanzar. */
  .idea-desbloq{font-size:11px;color:#3fae6a;border:1px solid #3fae6a;border-radius:20px;
    padding:1px 8px;white-space:nowrap}
  .mapa-cab{display:grid;gap:10px;margin:0 0 10px;padding-bottom:8px;
    border-bottom:1px solid var(--line)}
  .mapa-col{font-size:11px;color:var(--mut);text-transform:uppercase;letter-spacing:.06em}
  .mapa-col span{display:block;text-transform:none;letter-spacing:0;font-size:10.5px;
    opacity:.7;margin-top:2px}
  .mapa-fila{display:grid;gap:10px;margin-bottom:8px}
  .mapa-sep{height:1px;background:var(--line);margin:14px 0}
  .mapa-g{position:relative}
  .mapa-vert::before,.mapa-codo::before{content:"";position:absolute;left:16px;top:-8px;
    width:1px;background:var(--mut);opacity:.55}
  .mapa-vert::before{bottom:0}
  .mapa-codo::before{height:calc(50% + 8px)}
  .mapa-codo.mapa-sigue::before{bottom:0;height:auto}
  .mapa-codo::after{content:"";position:absolute;left:16px;right:-10px;top:50%;
    height:1px;background:var(--mut);opacity:.55}
  /* flex-wrap (SEO-TANDA-20260921-29): con las columnas fijas en minmax(0,1fr) la barra
     ya no puede ensanchar su columna, asi que los chips bajan de linea en vez de estrujar
     el texto a una palabra por linea; el porcentaje no se parte. */
  .mapa-barra{position:relative;border:1px solid var(--line);border-radius:8px;
    background:var(--card);padding:9px 12px;overflow:hidden;display:flex;flex-wrap:wrap;
    align-items:center;gap:6px 10px;cursor:pointer;text-align:left;width:100%;
    font:inherit;color:inherit}
  .mapa-barra:hover{filter:brightness(1.25)}
  .mapa-relleno{position:absolute;left:0;top:0;bottom:0;opacity:.16}
  .mapa-lbl{position:relative;font-size:12.5px;flex:1 1 260px;min-width:0}
  .mapa-madres{position:relative;display:flex;flex-direction:column;gap:4px;
    align-items:flex-start}
  .mapa-de{position:relative;font-size:10.5px;color:var(--mut);white-space:nowrap;
    border:1px solid var(--line);border-radius:20px;padding:1px 8px}
  /* Varias madres por idea (I-047 Fase 5, SEO-TANDA-20260921-21): el chip de la madre
     principal es el de siempre; las demas madres van como enlace fino (borde discontinuo,
     algo mas tenue). Los cuatro estados llevan el color del tablon: rojo la que ya toca o
     no se ha podido comprobar, ambar la pendiente, verde la servida. */
  .mapa-de.fina{border-style:dashed;opacity:.85}
  .mapa-de.est-en_espera,.mapa-de.est-no_comprobable{color:#e05252;border-color:#e05252}
  .mapa-de.est-dependiente,.mapa-de.est-adelantable{color:#d9a03f;border-color:#d9a03f}
  .mapa-de.est-servida{color:#3fae6a;border-color:#3fae6a}
  .mapa-cuello{position:relative;font-size:10.5px;color:#a97bd6;white-space:nowrap;
    border:1px solid #a97bd6;border-radius:20px;padding:1px 8px}
  .mapa-pct{position:relative;margin-left:auto;font-size:11.5px;color:var(--mut);
    font-family:ui-monospace,monospace;white-space:nowrap}
  .mapa-leyenda{display:flex;gap:18px;flex-wrap:wrap;margin:16px 0 0;font-size:12px;
    color:var(--mut)}
  .mapa-leyenda i{display:inline-block;width:11px;height:11px;border-radius:3px;
    margin-right:6px;vertical-align:-1px}
  /* ===== Plan de trabajo del registro de ideas (L2-IDE-PLA) =====
     SEO-TANDA-20261001-08 (I-077, Fase 4 de 5): pinta el JSON del motor plan_trabajo_ideas.py.
     Arriba la hora de calculo y cuanto miro el motor; debajo, si lo hay, lo que no pudo mirar;
     despues la cabeza («que toca ahora», la marca de la columna Turno con su arrastre) y los
     nueve grupos del contrato en su orden, con una tarjeta por idea. Todas las clases bajo el
     prefijo `pla-`. Hasta esa tanda aqui vivia el carril semanal del 001 del roadmap del 7 de
     septiembre (SEO-TANDA-20260912-03), retirado con el documento. */
  .pla-aviso{display:none;gap:9px;align-items:baseline;margin:0 0 12px;padding:9px 12px;
    border-radius:8px;font-size:12px;line-height:1.45}
  .pla-aviso.on{display:flex}
  .pla-aviso .ico{flex:0 0 auto;font-size:13px}
  .pla-aviso b{font-weight:600}
  .pla-aviso span{color:var(--mut);font-size:11px;display:block;margin-top:2px}
  .pla-aviso ul{margin:5px 0 0;padding-left:18px;color:var(--mut);font-size:11px}
  .pla-aviso.corto{background:rgba(240,180,41,.10);border:1px solid #f0b429;color:#f0b429}
  .pla-aviso.error{background:rgba(255,107,107,.10);border:1px solid #ff6b6b;color:#ff6b6b}
  .pla-cab{font-size:11px;color:var(--mut);margin:0 0 12px;line-height:1.55}
  .pla-cab b{color:var(--txt);font-weight:600}
  .pla-cabeza{background:#13161c;border:1px solid var(--acc);border-radius:10px;padding:9px 12px;
    margin:0 0 6px}
  .pla-cabeza.vacia{border-color:var(--line);color:var(--mut);font-size:11.5px}
  .pla-cabeza-h{font-size:12px;font-weight:600;color:var(--acc);margin-bottom:4px}
  .pla-cabeza ol{margin:0;padding-left:20px;font-size:12.5px;line-height:1.5}
  .pla-cabeza .via{color:var(--mut);font-size:11px}
  .pla-cabeza .aviso{color:#f0b429;font-size:11.5px;margin-top:4px}
  .pla-grupo{margin-top:14px}
  .pla-grupo-h{display:flex;align-items:baseline;gap:8px;font-size:12.5px;font-weight:600;
    margin-bottom:7px;padding-bottom:4px;border-bottom:1px solid var(--line)}
  .pla-grupo-h span{color:var(--mut);font-weight:400;font-size:11px}
  .pla-grupo-h .cuenta{margin-left:auto;font-family:ui-monospace,Consolas,monospace;
    color:var(--mut);font-weight:400;font-size:11px;flex:0 0 auto}
  .pla-grupo.vacio{margin-top:8px}
  .pla-grupo.vacio .pla-grupo-h{color:var(--mut);font-weight:400;border-bottom-style:dashed;
    margin-bottom:0}
  .pla-fila{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:8px}
  .pla-idea{background:var(--card);border:1px solid var(--line);border-left:3px solid var(--line);
    border-radius:8px;padding:8px 10px;cursor:pointer}
  .pla-idea:hover{border-color:var(--acc)}
  .pla-idea.sel{border-color:#fff}
  .pla-idea.ahora{border-left-color:var(--acc)}
  .pla-idea.aparcada{opacity:.72;border-left-style:dashed}
  .pla-idea.huerfana{cursor:default;color:#ff6b6b;font-size:11px}
  .pla-idea .id{display:flex;justify-content:space-between;gap:8px;font-size:10.5px;
    color:var(--mut);font-family:ui-monospace,Consolas,monospace}
  .pla-idea .id b{color:var(--txt);font-weight:600}
  .pla-idea .fs{font-size:12.5px;font-weight:600;line-height:1.3;margin-top:3px}
  .pla-idea .ti{font-size:11px;line-height:1.3;margin:3px 0 0;color:var(--mut);
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .pla-idea .pie{display:flex;gap:5px;flex-wrap:wrap;margin-top:6px}
  .pla-idea .rel{font-size:10.5px;color:var(--mut);margin-top:5px;line-height:1.4}
  .pla-rojo{color:#ff6b6b} .pla-amb{color:#f0b429} .pla-verde{color:#3ecf8e}
  .pla-tg{font-size:10px;border-radius:20px;padding:1px 7px;border:1px solid;white-space:nowrap}
  .pla-tg.e-chat{color:#3ecf8e;border-color:#3ecf8e}
  .pla-tg.e-usu{color:#e8893a;border-color:#e8893a}
  .pla-tg.e-mix{color:#f0b429;border-color:#f0b429}
  .pla-tg.e-nada{color:#ff6b6b;border-color:#ff6b6b;border-style:dashed}
  .pla-tg.t-ahora{color:var(--acc);border-color:var(--acc)}
  .pla-tg.t-aparcada{color:var(--mut);border-color:var(--mut);border-style:dashed}
  .pla-tg.puerta{color:#5b9dff;border-color:#5b9dff}

  /* ===== Ficha lateral (L3-IDE-PLA-DET) ===== */
  .pla-det{position:fixed;top:0;right:0;bottom:0;width:390px;background:var(--card);
    border-left:1px solid #fff;padding:16px;overflow:auto;transform:translateX(100%);
    transition:transform .18s ease;z-index:60}
  .pla-det.open{transform:none}
  .pla-det h3{margin:0 0 2px;font-size:14px;line-height:1.35}
  .pla-det .det-id{font-size:11px;color:var(--mut);font-family:ui-monospace,Consolas,monospace}
  .pla-det .cerrar{position:absolute;top:12px;right:14px;background:none;border:none;
    color:var(--mut);font-size:18px;cursor:pointer}
  .pla-det dl{margin:14px 0 0}
  .pla-det dt{font-size:10.5px;color:var(--mut);text-transform:uppercase;letter-spacing:.4px;
    margin-top:12px}
  .pla-det dd{margin:3px 0 0;font-size:12.5px;line-height:1.45}
  .pla-det .fuente{margin-top:16px;padding-top:10px;border-top:1px solid var(--line);
    font-size:11px;color:var(--mut);font-family:ui-monospace,Consolas,monospace;
    word-break:break-all}
  .pla-det .fuente a{color:var(--acc);text-decoration:none;border-bottom:1px dotted var(--acc)}
  .pla-det .fuente a:hover{color:#fff;border-bottom-color:#fff}
  .pla-det .fuente .abrir{display:block;margin-top:5px;font-size:10px;color:#5c6472;
    font-family:system-ui,sans-serif}
  .pla-nota{margin-top:16px;font-size:11px;color:var(--mut);line-height:1.5;
    border-top:1px dashed var(--line);padding-top:10px}

  /* ===== Hitos y fases de cada idea (L2-IDE-FAS, SEO-TANDA-20260829-05) =====
     Cada idea ocupa el ancho entero en DOS ALTURAS: abajo los siete hitos y arriba,
     solapada y mas baja, la banda de fases del plan, que cruza por encima de todos ellos.
     Tres fondos y ninguno mas: pleno (fase principal), difuso (hecho) y transparente
     (pendiente), de modo que en una pantalla con 17 ideas la vista solo se para en lo que
     importa. El color es el del proyecto GENERADOR, no el del estado: aqui dice de quien
     salen las ordenes. Forma elegida por el usuario entre cuatro maquetas con datos
     reales, en `.Docs/2026-08-29_mapa-hitos-fases/`. */
  .fas-fila{position:relative;z-index:2;margin-bottom:30px;cursor:pointer}
  .fas-fila.apagada{opacity:.13}
  .fas-graf{position:relative;height:70px}
  /* Los 34 px de la derecha son el CANAL DE CONFLICTOS: por ahi van, y solo por ahi, las
     lineas que unen dos ideas en conflicto. Estan fuera de las tiras a proposito
     (SEO-TANDA-20260902-14): un conflicto no dice "esta fase mia choca con esa tuya", dice
     "estas dos ideas se pisan", asi que su linea no puede nacer de ningun rectangulo sin
     inventarse un dato que nadie ha escrito. */
  .fas-hitos{position:absolute;left:0;right:34px;bottom:0;height:54px;display:flex;gap:2px}
  .fas-tira{position:absolute;left:0;right:34px;top:0;height:20px;display:flex;gap:1px;
    z-index:4;filter:drop-shadow(0 2px 4px rgba(0,0,0,.8))}
  /* Marca de la tira entera cuando la idea tiene algun conflicto, y enganche de su linea */
  .fas-graf.enconflicto .fas-hitos{box-shadow:0 0 0 1px rgba(224,128,60,.55);
    border-radius:4px}
  .fas-graf.enconflicto::after{content:"";position:absolute;right:30px;top:26px;width:7px;
    height:7px;border-radius:50%;background:#e0803c;z-index:6}
  .fas-cel{position:relative;flex:1 1 0;min-width:0;border-radius:3px;overflow:hidden;
    border:1px solid transparent;font-family:ui-monospace,monospace;line-height:1.15}
  .fas-hitos .fas-cel{font-size:8.5px;color:#5b6473;padding:3px 5px}
  .fas-hitos .fas-cel .nom{display:block;font-size:8px;opacity:.8;max-width:100%;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:1px}
  .fas-tira .fas-cel{font-size:8.5px;color:#69727f;border-radius:2px;display:flex;
    align-items:center;justify-content:center;gap:4px}
  .fas-tira .fas-cel .nom{font-size:8px;overflow:hidden;text-overflow:ellipsis;
    white-space:nowrap}
  .fas-cel.hecho{color:#98a1b0}
  .fas-cel.pral{color:#fff;font-weight:700}
  .fas-hitos .fas-cel.pral{font-size:9.5px}
  .fas-tira .fas-cel.pral{font-size:9px}
  .fas-pill.conf{color:#e0803c;border-color:#e0803c}
  /* Conflicto obsoleto (SEO-TANDA-20260922-10): mismo tratamiento que en el tablon, el
     naranja intacto y la raya del tachado en gris. */
  .fas-pill.conf.obsoleto{text-decoration:line-through;text-decoration-color:#8a94a3;
    text-decoration-thickness:1px;opacity:.78}
  .fas-cel .fas-gate{position:absolute;top:2px;right:2px;width:7px;height:7px;
    border-radius:2px;border:1px solid rgba(0,0,0,.6)}
  .fas-gate.pago{background:#f0b429}
  .fas-gate.irrev{background:#ff6b6b}
  .fas-gate.fecha{background:#5b9dff}
  /* Puerta de persona (SEO-TANDA-20260923-21): gris con aro naranja, los colores de su trama. */
  .fas-gate.persona{background:#9aa3b2;box-shadow:0 0 0 1.5px #e8893a}
  .fas-sinplan{position:absolute;left:0;top:3px;height:15px;font-size:8.5px;color:#414857;
    letter-spacing:.05em;padding-left:6px}
  /* El rotulo de la idea va ESCRITO DENTRO del bloque, no en una columna aparte: asi los
     rectangulos ocupan el ancho entero. Degradado de fondo porque cae sobre rectangulos
     de colores distintos y con solo text-shadow no siempre se leia. */
  .fas-rotulo{position:absolute;left:0;right:0;bottom:0;z-index:5;pointer-events:none;
    display:flex;align-items:baseline;gap:7px;padding:9px 10px 6px;
    border-radius:0 0 3px 3px;
    background:linear-gradient(to top,rgba(9,11,15,.93) 58%,rgba(9,11,15,0));
    text-shadow:0 1px 3px #000,0 0 8px #000}
  .fas-rotulo b{font-family:ui-monospace,monospace;font-size:13px;white-space:nowrap}
  .fas-rotulo .tx{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;
    white-space:nowrap}
  .fas-rotulo .st{font-size:10.5px;color:#b9c1cd;white-space:nowrap}
  .fas-rotulo .pct{margin-left:auto;font-family:ui-monospace,monospace;font-size:12px;
    color:var(--txt);white-space:nowrap}
  .fas-pill{font-size:9.5px;border:1px solid var(--line);border-radius:20px;padding:0 6px;
    color:var(--mut);white-space:nowrap}
  .fas-zona{position:relative}
  .fas-links{position:absolute;inset:0;pointer-events:none;overflow:visible;z-index:9}
  .fas-sep{height:1px;background:var(--line);margin:2px 0 28px}
  .fas-leyenda{display:flex;gap:16px;flex-wrap:wrap;margin:8px 0 0;font-size:11.5px;
    color:var(--mut);border-top:1px solid var(--line);padding-top:13px}
  .fas-leyenda s{text-decoration:none;display:inline-block;width:24px;height:12px;
    border-radius:3px;margin-right:6px;vertical-align:-2px;border:1px solid transparent}
  .fas-leyenda l{display:inline-block;width:20px;height:0;border-top:1.8px solid #a97bd6;
    margin-right:6px;vertical-align:3px}
  .fas-leyenda l.dash{border-top-style:dashed}
  /* Paso disponible (puerta de fecha cuyo dia ya ha llegado): verde, la contraparte del
     rojo de la espera. No se usa en las barras de progreso, donde el verde ya significa
     avance y "disponible" se confundiria con "terminada". SEO-TANDA-20260817-07 */
  .roadmap-paso.roadmap-libre .roadmap-marcador { border-color:#3fae6a; }
  .roadmap-paso.roadmap-libre .roadmap-lbl { color:#3fae6a; font-weight:600; }
  /* Cabecera fija del RoadMap de ideas (boton volver + titulo + barra): se queda quieta
     mientras la linea de tiempo se desplaza debajo. top:-12px porque #modal-body tiene
     12px de padding-top que es zona de scroll (mismo problema documentado en la vista
     mp-view del mapa de pantallas); asi la cabecera ancla en el borde real y el contenido
     no se cuela por la rendija. SEO-TANDA-20260809-05 */
  /* Mismo ajuste que .hor-head: si la vista tiene barra de acciones fija, esta cabecera se
     para debajo de ella y no detras. SEO-TANDA-20260826-08 */
  .roadmap-head { position:sticky; top:calc(var(--acc-h,0px) - 12px); margin:-12px -2px 10px;
    padding:12px 2px 8px;
    background:var(--card); z-index:5; border-bottom:1px solid var(--line); }
  .roadmap-det { font-size:11.5px; color:var(--mut); margin-top:2px; }
  /* Insignia de pausa de revision/confirmacion humana (SEO-TANDA-20260726-05): visible a
     simple vista (no solo texto suelto en .roadmap-det), con tooltip nativo (title) con el
     detalle completo de la pausa. Amarillo FIJO a proposito (no usa --roadmap-neon): es una
     senal universal de "control humano" igual en las 4 marcas, distinta del color de marca
     que ya llevan hecho/actual. Mismo amarillo que el boton RoadMap. SEO-TANDA-20260726-08. */
  .roadmap-pausa { display:inline-flex; align-items:center; gap:4px; font-size:11px;
    color:#ffe600; border:1px solid #ffe600; border-radius:10px; padding:1px 8px;
    margin-top:5px; cursor:help; }
  /* Tira de subpasos de un paso del RoadMap (I-046, Fase 3, SEO-TANDA-20260920-08): una
     pildora NUMERADA por parte, en HORIZONTAL bajo la linea del paso, para que el RoadMap
     no gane ni una fila vertical (001 §8.3: en vertical I-015 pasaba de 23 filas a 99).
     flex-wrap para que el caso peor real (14 pildoras, I-020 Fase 2) parta de linea en
     vez de desbordar. El numero va DENTRO porque el vocabulario real es "el punto 3 de la
     Fase 2". El texto del punto va en el title nativo, como .roadmap-pausa.
     Tamano de fuente por debajo de los 11.5px de .roadmap-det: la tira acompana al
     detalle, no compite con el. */
  .roadmap-tira { display:flex; flex-wrap:wrap; align-items:center; gap:5px; margin-top:4px; }
  .roadmap-pt { display:inline-flex; align-items:center; justify-content:center;
    box-sizing:border-box; min-width:16px; height:16px; padding:0 3px; border-radius:4px;
    font-size:10px; line-height:1; font-variant-numeric:tabular-nums;
    border:1px solid var(--line); color:var(--mut); cursor:help; }
  /* Los tres estados, con los colores que el RoadMap ya usa: cerrado en color de marca
     (--roadmap-neon, el mismo que los marcadores de paso hecho), en curso en el ambar
     #d9a03f del resto del panel, pendiente en el gris de --mut. Cerrado y en curso van
     RELLENOS y pendiente hueco, para que los tres se distingan de un vistazo sin
     depender solo del tono. */
  .roadmap-pt.pt-cerrado { background:var(--roadmap-neon,var(--ok));
    border-color:var(--roadmap-neon,var(--ok)); color:var(--bg); }
  /* El halo es lo que separa "en curso" de "cerrado" cuando el color de marca ya es
     calido: con GP (--roadmap-neon #ff9100) el ambar y el naranja se parecen demasiado a
     este tamano, asi que el estado en curso se distingue ademas por forma, y eso vale
     para cualquier marca. Comprobado en la Fase 3 forzando el neon de GP sobre I-020. */
  .roadmap-pt.pt-curso { background:#d9a03f; border-color:#d9a03f; color:var(--bg);
    font-weight:700; box-shadow:0 0 0 2px rgba(217,160,63,.38); }
  .roadmap-pt.pt-pendiente { background:transparent; border-color:var(--line); color:var(--mut); }
  /* Columna derecha con las skills de cada paso (SEO-TANDA-20260726-03): chips con
     tooltip nativo (title) que explica el uso de esa skill en ese paso concreto. */
  .roadmap-skills { flex:0 0 auto; display:flex; flex-wrap:wrap; gap:6px; align-items:flex-start;
    justify-content:flex-end; max-width:46%; padding-top:1px; }
  .roadmap-skill { font-family:ui-monospace,Consolas,monospace; font-size:11px; color:var(--acc);
    border:1px solid var(--line); border-radius:10px; padding:2px 8px; cursor:help;
    background:#13161c; white-space:nowrap; }
  .roadmap-skill:hover { border-color:var(--acc); }
  .prompt-card { border:1px solid var(--line); border-radius:8px; padding:10px 12px; margin-top:12px; }
  .prompt-card-h { display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
  .prompt-card-h b { font-size:13px; }
  .prompt-card-h .volver { margin-bottom:0; }
  .prompt-txt { white-space:pre-wrap; background:#13161c; border:1px solid var(--line); border-radius:8px;
    padding:10px 12px; font-size:12.5px; color:var(--txt); margin:0; }
  .articulo-render { font-size:14px; line-height:1.6; }
  .articulo-render h1 { font-size:22px; margin:18px 0 10px; }
  .articulo-render h2 { font-size:19px; margin:18px 0 8px; }
  .articulo-render h3 { font-size:16px; margin:16px 0 6px; }
  .articulo-render h4, .articulo-render h5, .articulo-render h6 { font-size:14px; margin:14px 0 6px; }
  .articulo-render p { margin:8px 0; }
  .articulo-render strong { color:var(--txt); }
  .articulo-render em { font-style:italic; }
  .articulo-render ul, .articulo-render ol { margin:8px 0; padding-left:24px; }
  .articulo-render li { margin:3px 0; }
  .articulo-render blockquote { margin:10px 0; padding:4px 14px; border-left:3px solid var(--line); color:var(--mut); }
  .articulo-render u { text-decoration-color:var(--acc); }
  /* Enlaces reales del cuerpo (no los tokens [futuro]): ancla <a> de verdad, no solo un
     <u> con tooltip, para que el href sobreviva al copiar/pegar en Word/WordPress.
     SEO-TANDA-20260713-18 */
  .articulo-render .art-link { color:inherit; text-decoration:underline; text-decoration-color:var(--acc); }
  .articulo-render .art-link:hover { opacity:0.8; }
  .articulo-render .mrk-fut { color:var(--mut); text-decoration-style:dashed; }
  .articulo-render .mrk-fut-tok { font-family:ui-monospace,Consolas,monospace; font-size:11px; color:var(--mut);
    background:#13161c; border:1px solid var(--line); border-radius:4px; padding:1px 5px; }
  .articulo-render .art-marker { font-family:ui-monospace,Consolas,monospace; font-size:11.5px; color:var(--mut);
    border-left:3px solid var(--line); padding:3px 10px; margin:8px 0; }
  .articulo-render .art-cta { text-align:center; margin:14px 0; }
  .articulo-render .art-code { white-space:pre-wrap; word-break:break-all; background:#13161c;
    border:1px solid var(--line); border-radius:8px; padding:10px 12px; font-size:12.5px;
    font-family:ui-monospace,Consolas,monospace; color:var(--txt); margin:4px 0 0; }
  .articulo-render .art-code-wrap { margin:8px 0; }
  .articulo-render .art-code-h { display:flex; justify-content:flex-end; }
  .articulo-render .art-code-h .volver { margin-bottom:0; }
  .articulo-render.copiando .art-code-h { display:none; }
  /* Etiquetas de campo (negrita + ":") en toda la vista Bloque tecnico, en rojo; Material/
     Color/Frase son la excepcion y se quedan en amarillo (.det-lbl, ya usado en la ficha
     resumen del modal). SEO-TANDA-20260712-23 */
  .articulo-render .campo-lbl { color:var(--bad); font-weight:600; }
  .art-tbl th, .art-tbl td { font-size:13px; }
  .det-nav .volver { margin-bottom:0; }
  .det-pos { color:var(--mut); font-size:12px; font-variant-numeric:tabular-nums; white-space:nowrap; }
  .det-h { font-size:15px; margin:2px 0 12px; }
  .det-tipo { font-size:11px; color:var(--mut); border:1px solid var(--line); border-radius:10px;
    padding:1px 7px; margin-left:6px; }
  /* Estado (en curso / cerrado) de un chat en su ficha de detalle (L2-ACT-DET), junto al
     nombre: en curso en verde y negrita, cerrado en rojo sin negrita, para verlo de un
     vistazo sin tener que leer la fila "Estado" mas abajo. SEO-TANDA-20260725-10 */
  .det-chat-estado { font-size:12px; margin-left:8px; text-transform:uppercase; letter-spacing:.02em; }
  .det-chat-estado.en-curso { color:var(--ok); font-weight:700; }
  .det-chat-estado.cerrado { color:var(--bad); font-weight:400; }
  /* El propio titulo (marca + ID) se tine del mismo color que el badge, no solo el badge
     suelto: asi el estado se ve de un vistazo en toda la cabecera, no en una esquina.
     SEO-TANDA-20260725-11 */
  .det-h.det-h-en-curso { color:var(--ok); font-weight:700; }
  .det-h.det-h-cerrado { color:var(--bad); font-weight:400; }
  .det-tbl th { width:180px; color:var(--mut); font-weight:600; text-transform:none;
    font-size:13px; vertical-align:top; }
  /* Fecha/Hora inicio/Hora fin/Tandas de la ficha de un chat: cabeceras en fila arriba,
     datos en fila debajo, en vez de 4 filas verticales clave-valor. SEO-TANDA-20260715-01 */
  .det-tbl-compacta { table-layout:fixed; }
  .det-tbl-compacta th, .det-tbl-compacta td { width:25%; text-align:left; }
  /* Codigos de tanda (SEO-TANDA-...) de la fila "Tandas": antes era una sola cadena larga
     unida por ";" sin espacios, y el navegador la partia a lo bruto por los guiones al
     ajustar linea (quedaba "SEO-" en una linea y "TANDA-20260724-16" en la siguiente, una
     ristra vertical illegible). Ahora cada codigo es su propia etiqueta suelta, en una
     rejilla que fluye y se ajusta por etiqueta completa, nunca a mitad de codigo.
     SEO-TANDA-20260725-12 */
  .tandas-chips { display:flex; flex-wrap:wrap; gap:5px; }
  .chip-tanda { display:inline-block; background:#13161c; border:1px solid var(--line);
    border-radius:5px; padding:2px 7px; font-family:ui-monospace,Consolas,monospace;
    font-size:11.5px; color:var(--acc); white-space:nowrap; }
  /* Bitacora de un chat (columna `resumen`): un apunte por linea, con su marca de tiempo
     y quien lo escribio. `sistema` (automatico) se pinta apagado y el resto de firmas
     (tt/ii/ff/rr) en color, para distinguir de un vistazo lo que hizo el sistema solo de
     lo que se pidio con un comando. `rr` (reapertura) va en ambar porque marca el punto en
     que un chat cerrado se retomo. SEO-TANDA-20260801-02 */
  .bitacora { display:flex; flex-direction:column; gap:5px; }
  .bit-ap { display:grid; grid-template-columns:118px 58px 1fr; gap:7px; align-items:baseline;
    padding-bottom:5px; border-bottom:1px solid var(--line); }
  .bit-ap:last-child { border-bottom:0; padding-bottom:0; }
  .bit-sello { font-family:ui-monospace,Consolas,monospace; font-size:11px; color:var(--dim); }
  .bit-quien { font-size:10.5px; text-transform:uppercase; letter-spacing:.5px;
    text-align:center; border-radius:4px; padding:1px 5px; background:#13161c;
    border:1px solid var(--line); color:var(--acc); }
  .bit-sistema { color:var(--dim); }
  .bit-previo { color:var(--dim); font-style:italic; }
  .bit-rr { color:#e0a33a; border-color:#5a4520; }
  .bit-txt { line-height:1.45; }
  @media (max-width:560px) {
    .bit-ap { grid-template-columns:1fr; gap:2px; }
    .bit-quien { justify-self:start; }
  }
  /* Fila de imagen (Portada/Imagen N) de la ficha de detalle: clicable para resaltarla en
     gris claro, una activa a la vez (clic en otra desactiva la anterior). SEO-TANDA-20260714-07.
     Una vez clicada una fila, queda marcada como "visitada" de forma permanente en vez de volver
     a un fondo sin marcar cuando deja de estar activa. Tono oscuro #13161c: el mismo que usan los
     elementos incrustados dentro de las tarjetas de marca de L0 (.metric/.chip/.collapse/.ancho),
     no el fondo plano de la tarjeta (var(--card)), que coincide con el del propio modal y resultaba
     invisible. .activa (mas especifica por orden) manda mientras la fila sea la seleccionada actual.
     SEO-TANDA-20260714-08 */
  /* --neon-soft aqui viene de la tabla .det-tbl (verDetalle(), no del .card de L0): un
     matiz del color de la marca de este contenido por encima del #13161c base, para que
     "visitada" no sea un gris generico. Sin marca reconocida, --neon-soft queda sin
     definir y el color base #13161c se ve solo. SEO-TANDA-20260714-10 */
  /* Boton "Reset" al final de la fila Tipo: quita de un tiron el resaltado "visitada"/
     "activa" de las filas de imagen. Flotado a la derecha de su celda para quedar
     alineado con el borde derecho de la tabla. SEO-TANDA-20260714-13 */
  .det-tbl .reset-img-rows { float:right; margin:0; padding:3px 8px; font-size:11px;
    display:inline-flex; align-items:center; gap:4px; }
  .det-img-row { cursor:pointer; }
  .det-img-row.visitada > th, .det-img-row.visitada > td {
    background:linear-gradient(0deg, var(--neon-soft, transparent), var(--neon-soft, transparent)) #13161c; }
  .det-img-row.activa > th, .det-img-row.activa > td { background:rgba(255,255,255,.07); }
  /* Chat con una incidencia sin resolver (columna "Incidencia" no vacia en su registro):
     fila en rojo oscuro tanto en la lista (L1-ACT, .fila-incidencia) como en la fila
     "Incidencia" de su ficha de detalle (L2-ACT-DET, .det-row-incidencia), para que salte
     a la vista sin tener que abrir la ficha. Solo se aplica a Actividad de chats (ver
     origen === 'Actividad de chats' en el JS), no a otras listas que tambien llevan un
     campo "Incidencia" en su det (p.ej. investigaciones). SEO-TANDA-20260714-19 */
  .fila-incidencia > td { background:#3a1414; }
  .fila-incidencia:hover > td { background:#4a1818; }
  /* Fondo por estado en las filas de Semaforos (L1-SEM), espejo de las tarjetas del
     detalle del dia del calendario (SEO-TANDA-20260811-02): amarillo difuso para
     parcial/bloqueada, rojo difuso para cancelada/en_curso. */
  /* Idea tocada en las ultimas 24 h (tablon L1-IDE, SEO-TANDA-20260827-11): marco verde
     alrededor de la fila entera. Es MARCO y no fondo a proposito, para que no se pelee
     con los tres colores que ya usa esta pantalla (rojo bloqueada, ambar dependiente,
     morado cuello): una idea puede estar en rojo y trabajandose hoy a la vez, y asi se
     leen las dos cosas. Como <tr> no admite borde con border-collapse, el marco se arma
     con los bordes de las celdas: arriba y abajo en todas, y los laterales en la primera
     y la ultima. El verde es el mismo #3fae6a de la barra de progreso normal. */
  .fila-idea-activa > td { border-top:2px solid #3fae6a; border-bottom:2px solid #3fae6a; }
  .fila-idea-activa > td:first-child { border-left:2px solid #3fae6a; }
  .fila-idea-activa > td:last-child { border-right:2px solid #3fae6a; }
  /* Idea tocada en la ULTIMA HORA (SEO-TANDA-20260913-19, pedido del usuario): el mismo marco,
     en rojo. Sustituye al verde en esa fila (la clase se pone en lugar de la otra, no
     encima). El rojo es el #e05252 de "bloqueada", pero como MARCO y no como fondo: no
     significa alarma, significa "esto es lo que se esta tocando ahora mismo". Va despues
     del verde a proposito, para ganar si alguna vez coincidieran las dos clases. */
  .fila-idea-reciente > td { border-top:2px solid #e05252; border-bottom:2px solid #e05252; }
  .fila-idea-reciente > td:first-child { border-left:2px solid #e05252; }
  .fila-idea-reciente > td:last-child { border-right:2px solid #e05252; }
  /* Las tres ideas en marcha que mas tiempo llevan sin tocarse (SEO-TANDA-20260827-14):
     fondo gris, el reverso del marco verde.

     El degradado va en el <tr> y NO en las celdas, que se quedan transparentes. Es la
     unica forma de que sea un degradado de la FILA: cada <td> pinta su propio fondo desde
     su esquina, asi que un degradado puesto en las celdas se reinicia en cada columna y en
     vez de una mancha continua salen siete manchas iguales con costura en cada borde. El
     fondo de fila pinta debajo del de celda (CSS 2.1 17.5.1, capas de la tabla) y aqui las
     celdas no traen ninguno, asi que se ve.

     Amorfo = cuatro elipses muy desproporcionadas, en posiciones que no guardan simetria
     ni ritmo entre si, sobre una base plana. Ninguna llega a cerrarse dentro de la fila,
     que es lo que quita el aire de "circulo dibujado encima" y deja la mancha irregular.

     El recorrido va de #1f2229 a #2e323c y ni un tono mas claro: el azul de var(--acc) es
     el texto mas flojo de la tabla y a #2e323c ya esta en 4,71:1; a #31363f cae a 4,46 y
     se sale del minimo legible que pidio el usuario. En el extremo oscuro sobra margen
     (5,85:1), asi que la mancha se construye hacia abajo, no hacia arriba. */
  .fila-idea-parada {
    background:
      radial-gradient(120% 260% at 6% 10%,   #2e323c 0%, rgba(46,50,60,0) 55%),
      radial-gradient(90% 220% at 34% 100%,  #1f2229 0%, rgba(31,34,41,0) 50%),
      radial-gradient(150% 180% at 63% 0%,   #2c303a 0%, rgba(44,48,58,0) 60%),
      radial-gradient(80% 260% at 88% 85%,   #21242c 0%, rgba(33,36,44,0) 55%),
      #272b33; }
  /* Los 3 px de fondo normal alrededor de la mancha (peticion del usuario): son sombras
     interiores del color de la caja del modal, var(--card), pintadas por las celdas, que
     van por encima del fondo de fila. Arriba y abajo en todas; los laterales, solo en la
     primera y la ultima, que son las que tocan el borde de la tabla. Con border-collapse
     no se puede poner un borde al <tr>, y un padding movaria el texto de sitio. */
  .fila-idea-parada > td { background:transparent;
    box-shadow:inset 0 3px 0 var(--card), inset 0 -3px 0 var(--card); }
  .fila-idea-parada > td:first-child {
    box-shadow:inset 0 3px 0 var(--card), inset 0 -3px 0 var(--card), inset 3px 0 0 var(--card); }
  .fila-idea-parada > td:last-child {
    box-shadow:inset 0 3px 0 var(--card), inset 0 -3px 0 var(--card), inset -3px 0 0 var(--card); }
  /* Parada Y bloqueada a la vez: los dos colores se combinan de verdad en vez de que uno
     tape al otro. Misma mancha, mismas posiciones, pero recorriendo el rojo de fila: de
     #351719 (mas oscuro que el rojo normal) a #47282a (el rojo con gris encima, que se lee
     como "la fila roja, apagada"). Ahi se para: a #4d3033 el azul cae a 4,32. Hoy no la
     lleva ninguna fila, las tres paradas de ahora no estan bloqueadas. */
  .fila-incidencia.fila-idea-parada {
    background:
      radial-gradient(120% 260% at 6% 10%,   #47282a 0%, rgba(71,40,42,0) 55%),
      radial-gradient(90% 220% at 34% 100%,  #351719 0%, rgba(53,23,25,0) 50%),
      radial-gradient(150% 180% at 63% 0%,   #442528 0%, rgba(68,37,40,0) 60%),
      radial-gradient(80% 260% at 88% 85%,   #381a1c 0%, rgba(56,26,28,0) 55%),
      #3e1e20; }
  /* El rojo plano de .fila-incidencia lo pintan las celdas, asi que taparia la mancha:
     aqui se apagan las dos reglas, la normal y la de hover. */
  .fila-incidencia.fila-idea-parada > td,
  .fila-incidencia.fila-idea-parada:hover > td { background:transparent; }
  /* TRAMAS DEL TABLON L1-IDE (N-348, SEO-TANDA-20260923-21). Tres rayados,
     excluyentes, que SUSTITUYEN al granate de .fila-incidencia en las ideas: verde y blanco
     (la idea no esta parada y le queda una puerta cumplida por pasar), gris y naranja
     (parada esperando a una persona) y amarillo y rojo (parada por cualquier otro motivo).
     Como la mancha de .fila-idea-parada, el dibujo va en el <tr> y las celdas quedan
     transparentes: puesto en cada <td>, el rayado volveria a empezar en cada columna y se
     veria la costura. Las rayas son de poca opacidad a proposito: con rayas finas y vivas
     el texto de encima vibra y no se lee. El contraste del texto mas flojo de la tabla
     (var(--mut)) contra la raya mas clara se midio al pintarlo, y los valores de aqui son
     los que lo dejan por encima de 4,5:1 (entre 4,56 y 5,58).
     FORMA (N-362, SEO-TANDA-20260923-24, elegida por el usuario entre tres anchuras): cada
     trama se distingue ya sin mirar el color, por giro y por anchura. Verde VERTICAL con
     bandas de 26 px; persona SUBE hacia la derecha (135deg) con bandas de 42 px, la mas
     ancha; sistema BAJA hacia la derecha (45deg) con bandas de 20 px, la mas estrecha.
     La anchura no mueve el contraste: el minimo lo fija el color de la raya mas clara, no
     cuanto mide (vuelto a medir: 4,56 a 5,58 igual). Los colores no se han tocado. */
  .fila-trama { --trama-img:none; }
  .fila-trama-libre { --trama-img:repeating-linear-gradient(90deg,
      rgba(63,174,106,.20) 0 26px, rgba(255,255,255,.06) 26px 52px); }
  .fila-trama-persona { --trama-img:repeating-linear-gradient(135deg,
      rgba(154,163,178,.16) 0 42px, rgba(232,137,58,.22) 42px 84px); }
  .fila-trama-sistema { --trama-img:repeating-linear-gradient(45deg,
      rgba(217,160,63,.18) 0 20px, rgba(224,82,82,.22) 20px 40px); }
  .fila-trama { background:var(--trama-img), var(--card); }
  .fila-trama > td { background:transparent; }
  /* Los chips de color llevan fondo liso dentro de una fila con trama: sobre el rayado, el
     rojo de «conflicto activo» bajaba a 3:1 (sobre el granate de antes daba 4,3). Medido. */
  .fila-trama .idea-conf, .fila-trama .idea-cuello, .fila-trama .idea-desbloq { background:var(--card); }
  .fila-trama:hover { background:linear-gradient(rgba(255,255,255,.04), rgba(255,255,255,.04)),
      var(--trama-img), var(--card); }
  /* Trama Y parada a la vez: el rayado encima de la mancha gris, las dos se leen. */
  .fila-trama.fila-idea-parada {
    background: var(--trama-img),
      radial-gradient(120% 260% at 6% 10%,   #2e323c 0%, rgba(46,50,60,0) 55%),
      radial-gradient(90% 220% at 34% 100%,  #1f2229 0%, rgba(31,34,41,0) 50%),
      radial-gradient(150% 180% at 63% 0%,   #2c303a 0%, rgba(44,48,58,0) 60%),
      radial-gradient(80% 260% at 88% 85%,   #21242c 0%, rgba(33,36,44,0) 55%),
      #272b33; }
  /* Muestras de la leyenda de colores de L1-IDE: el mismo rayado, en pequeno. */
  /* Ventana de la leyenda: cuelga de la barra de titulos, por encima de la tabla, y en
     movil ocupa el ancho del modal menos su margen. */
  .ley-pop { position:absolute; top:52px; right:14px; z-index:30; width:min(460px, calc(100% - 28px));
    max-height:calc(100% - 70px); overflow:auto; background:#13161c; border:1px solid var(--line);
    border-radius:10px; padding:12px 14px; box-shadow:0 10px 30px rgba(0,0,0,.55); font-size:12.5px; }
  .ley-pop[hidden] { display:none; }
  .ley-h { font-weight:700; margin-bottom:6px; }
  .ley-sec { margin:10px 0 4px; font-size:11px; color:var(--mut); text-transform:uppercase; letter-spacing:.06em; }
  .ley-it { display:flex; align-items:center; gap:10px; margin:5px 0; line-height:1.35; }
  .ley-it > span:last-child { flex:1 1 auto; min-width:0; }
  .ley-muestra { display:inline-block; width:34px; height:16px; border-radius:3px;
    flex:0 0 auto; border:1px solid var(--line); background:var(--trama-img), var(--card); }
  /* Las muestras de las tres tramas, mas grandes (N-362, SEO-TANDA-20260923-24): con
     bandas de hasta 42 px en diagonal, a 34x16 la de persona salia de un solo color y
     parecia lisa. A 96x30 cabe un periodo entero de la mas ancha (84 px medidos en
     perpendicular, y la caja da 89) y dos de las otras. */
  .ley-muestra.ley-muestra-trama { width:96px; height:30px; }
  /* Fondos lisos de L1-TAR (SEO-TANDA-20260923-27): critica en el granate de siempre y
     con fecha por delante en ambar. Las muestras (boton de filtro y leyenda) usan la misma
     variable que las tramas, asi una sola regla pinta fila, boton y leyenda. */
  .fila-tar-critica > td { background:#3a1414; }
  .fila-tar-critica:hover > td { background:#4a1818; }
  .fila-tar-fecha > td { background:#332a10; }
  .fila-tar-fecha:hover > td { background:#42371a; }
  .tar-m-critica { --trama-img:linear-gradient(#3a1414, #3a1414); }
  .tar-m-fecha { --trama-img:linear-gradient(#332a10, #332a10); }
  .tar-m-nada { --trama-img:none; }
  .tar-muestra { display:inline-block; width:26px; height:13px; margin-right:6px; vertical-align:-2px;
    border-radius:3px; border:1px solid var(--line); background:var(--trama-img), var(--card); }
  .fila-parcial > td { background:#332a10; }
  .fila-parcial:hover > td { background:#42371a; }
  .fila-cancelada > td { background:#3a1414; }
  .fila-cancelada:hover > td { background:#4a1818; }
  /* Chat que sigue en_curso (no se cierra nunca en automatico, solo con /ff manual): el
     estado se pinta en amarillo en la lista de Actividad de chats para que el usuario
     detecte a simple vista los que se han quedado abiertos y decida si cerrarlos.
     SEO-TANDA-20260724-11 */
  .estado-abierta { color:var(--warn); font-weight:600; }
  /* Celda Estado de una fila de la lista Semaforos (L1-SEM): mismo color que el punto de
     cada tarjeta (var(--ok/--warn/--bad)). SEO-TANDA-20260725-13 */
  .estado-sem-ok { color:var(--ok); font-weight:600; }
  /* Textos largos partidos en parrafos por parrafos() (columna Tema de L1-SEM, campos
     largos de las fichas de detalle): aire entre parrafos, sin margen de cierre para no
     descolgar la celda. SEO-TANDA-20260809-06 */
  .parrafos p { margin:0 0 7px; }
  .parrafos p:last-child { margin-bottom:0; }
  /* Subcuadro "Bitacora de la ejecucion" de la ficha de detalle (L2-SEM-DET): agrupa los
     apuntes de bitacora separados de los metadatos, con borde izquierdo de acento (sin
     radio: el borde es de un solo lado). Etiquetas en el mismo amarillo que .det-lbl.
     SEO-TANDA-20260809-06 */
  .det-bitacora { margin-top:12px; background:#161b24; border:1px solid #33405c;
    border-left:3px solid var(--acc); border-radius:0; padding:10px 14px; }
  .det-bit-tit { font-size:11px; letter-spacing:.06em; text-transform:uppercase;
    color:var(--acc); margin-bottom:8px; }
  .det-bit-ap { font-size:12.5px; color:var(--txt); line-height:1.55; margin:0 0 7px; }
  .det-bit-ap:last-child { margin-bottom:0; }
  .det-bit-ap .parrafos { margin-top:4px; }
  .det-bit-lbl { color:#ffe600; font-weight:600; }
  .det-bit-nota { color:var(--mut); }
  .estado-sem-warn { color:var(--warn); font-weight:600; }
  .estado-sem-bad { color:var(--bad); font-weight:600; }
  /* Distintivo del semaforo de la TAREA en la fila vigente de L1-SEM (solo si no esta
     en verde): va debajo del estado de la ejecucion, con etiqueta propia, para no tenir
     el texto del estado (SEO-TANDA-20260811-02). */
  .sem-tarea { font-size:11px; font-weight:600; white-space:nowrap; margin-top:2px; }
  /* Boton de anomalia ya pulsado en esta pestana (Visto / Anadir a tareas de L2-SEM-DET):
     se queda como confirmacion inerte hasta que el panel regenerado se recargue. */
  .visto-hecho { pointer-events:none; opacity:.55; }
  .det-row-incidencia > th, .det-row-incidencia > td { background:#3a1414; }
  /* Banda de estado y filas tenidas de la ficha de una idea (L3-IDE-ROA-DET,
     SEO-TANDA-20260817-07): mismo codigo de tres colores que el tablon L1-IDE y que los
     pasos del RoadMap, para que las tres pantallas se lean igual sin traducir nada.
     Rojo = bloqueada ahora (esperando otra idea, esperando una fecha que no ha llegado,
     puerta rebasada o conflicto activo); ambar = dependencia viva que aun deja avanzar;
     verde = puerta de fecha cumplida, la idea ya puede continuar. */
  .det-banda { margin:8px 0 2px; padding:7px 10px; border-radius:8px; font-size:12.5px;
    font-weight:600; border:1px solid; }
  .det-banda-alerta { background:#3a1414; border-color:#e05252; color:#f08a8a; }
  .det-banda-espera { background:#332714; border-color:#d9a03f; color:#e8bd6d; }
  .det-banda-libre  { background:#13301f; border-color:#3fae6a; color:#6fd396; }
  .det-row-alerta > th, .det-row-alerta > td { background:#3a1414; }
  .det-row-alerta > th { color:#f08a8a; }
  .det-row-espera > th, .det-row-espera > td { background:#332714; }
  .det-row-espera > th { color:#e8bd6d; }
  .det-row-libre > th, .det-row-libre > td { background:#13301f; }
  .det-row-libre > th { color:#6fd396; }
  /* Jerarquia de clusters (I-056, SEO-TANDA-20260908-56): arbol con sangria por nivel, rol
     como chip (verde el pilar, ambar el provisional), anomalias con los mismos rojo y ambar
     que las bandas de las ideas, y el boton de la tarjeta tenido con la peor gravedad. */
  .jer-arbol { list-style:none; margin:6px 0 0; padding-left:0; }
  .jer-arbol ul { list-style:none; margin:0; padding-left:22px; border-left:1px solid var(--line); }
  .jer-nodo { padding:3px 0; font-size:13px; }
  .jer-rol { font-size:11px; color:var(--mut); border:1px solid var(--line); border-radius:10px; padding:0 6px; margin-left:4px; }
  .jer-rol-pilar { color:#6fd396; border-color:#3fae6a; }
  .jer-rol-pilar_provisional { color:#e8bd6d; border-color:#d9a03f; }
  .jer-rol-vacio { color:#f08a8a; border-color:#e05252; }
  .jer-sub { font-size:11px; color:var(--mut); margin-left:6px; }
  .jer-nota { font-size:11px; color:#f08a8a; margin-left:6px; }
  .jer-anom { padding:4px 8px; border-radius:6px; margin:3px 0; font-size:12px; }
  .jer-anom-error { background:#3a1414; color:#f08a8a; }
  .jer-anom-aviso { background:#332714; color:#e8bd6d; }
  .jer-anom-info { color:var(--mut); }
  .inv-btn.btn-jer-error { border-color:#e05252; color:#f08a8a; }
  .inv-btn.btn-jer-aviso { border-color:#d9a03f; color:#e8bd6d; }
  .add-tarea-btn { margin-left:8px; background:#13161c; border:1px solid var(--bad); color:var(--bad);
    border-radius:6px; padding:2px 8px; font-size:11px; cursor:pointer; display:inline-flex;
    align-items:center; gap:4px; text-decoration:none; }
  .add-tarea-btn:hover { background:var(--bad); color:#1c1114; }
  /* Estado tras el clic (feedback optimista en el propio DOM, SEO-TANDA-20260715-02):
     deja de parecer un boton de accion pendiente y no admite un segundo clic. */
  .add-tarea-btn.add-tarea-hecho { border-color:var(--line); color:var(--mut);
    cursor:default; pointer-events:none; background:none; }
  /* Boton "Neutralizar la incidencia" (SEO-TANDA-20260727-11): misma forma que
     .add-tarea-btn pero en verde (--ok), para distinguir a simple vista la resolucion sin
     tarea ("descartar") de la que si crea una tarea (roja, "accion pendiente"). */
  .neutralizar-btn { margin-left:8px; background:#13161c; border:1px solid var(--ok); color:var(--ok);
    border-radius:6px; padding:2px 8px; font-size:11px; cursor:pointer; display:inline-flex;
    align-items:center; gap:4px; text-decoration:none; }
  .neutralizar-btn:hover { background:var(--ok); color:#0f1c14; }
  .neutralizar-btn.neutralizar-hecho { border-color:var(--line); color:var(--mut);
    cursor:default; pointer-events:none; background:none; }
  /* Franja de campos cortos (numeros) del detalle de un dia del calendario, en vez de una
     tabla vertical de una fila por numero. Mismo lenguaje visual que .metrics/.metric del
     dashboard, pero sin boton/hover porque aqui no son clicables. SEO-TANDA-20260714-01 */
  .det-stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(110px,1fr)); gap:6px;
    margin:0 0 8px; }
  .det-stat { background:#181b22; border:1px solid var(--line); border-radius:8px;
    padding:6px 8px; text-align:center; }
  .det-stat .det-stat-lbl { display:block; font-size:10px; color:var(--mut); }
  .det-stat .det-stat-val { display:block; font-size:15px; font-weight:700; color:var(--txt);
    margin-top:2px; word-break:break-word; }
  @media (max-width:480px) { .det-stats { grid-template-columns:repeat(2,1fr); } }
  /* Etiquetas Material/Color/Frase en las filas de imagen de la ficha resumen. SEO-TANDA-20260706-08 */
  .det-lbl { color:#ffe600; font-weight:600; }
  /* Etiquetas Alt text/Descripcion en las filas de imagen (rojo, distinto de Material/
     Color/Frase), con boton de copia individual delante. SEO-TANDA-20260713-08 */
  .det-lbl-alt { color:var(--bad); font-weight:600; }
  /* Iconos de copia en verde fosforito, a peticion expresa del usuario. SEO-TANDA-20260713-14 */
  .copiar-campo-img { background:none; border:none; cursor:pointer; padding:0;
    margin:0 4px; font-size:12px; line-height:1; vertical-align:-2px; color:#39ff14; }
  .copiar-campo-img:hover { opacity:0.75; }
  /* Resto de botones "Copiar" (bloques de codigo, prompts, Articulo, Bloque tecnico):
     mismo icono SVG y mismo verde fosforito, en vez del texto "Copiar". SEO-TANDA-20260713-15 */
  .copiar-code, .copiar-prompt, #copiar-articulo, .copiar-articulo-titulo { color:#39ff14;
    display:inline-flex; align-items:center; }
  .copiar-code:hover, .copiar-prompt:hover, #copiar-articulo:hover,
    .copiar-articulo-titulo:hover { opacity:0.75; }
  /* Titulo real del articulo (el H1 del cuerpo) con su propio boton de copia, separado
     del boton que copia el resto del cuerpo. SEO-TANDA-20260713-18 */
  .art-titulo-h { display:flex; align-items:center; justify-content:space-between; gap:10px; margin:4px 0 6px; }
  .art-titulo-h .art-titulo { margin:0; font-size:22px; line-height:1.3; }
  .art-titulo-h .copiar-articulo-titulo { flex-shrink:0; }
  .art-cuerpo-h { display:flex; justify-content:flex-end; margin-bottom:4px; }
  .art-cuerpo-h .volver { margin-bottom:0; }
  .informe { white-space:pre-wrap; background:#13161c; border:1px solid var(--line); border-radius:8px;
    padding:10px 12px; font-size:12.5px; color:var(--txt); overflow:auto; margin-top:6px; }
  /* Informe de rutina pintado por bloques (I-079 Fase 2, SEO-TANDA-20260927-12): el de antes
     entero y linea a linea; el nuevo con tres lineas fijas y secciones plegadas. */
  .informe-bloques { background:#13161c; border:1px solid var(--line); border-radius:8px;
    padding:8px 12px; font-size:12.5px; color:var(--txt); overflow:auto; margin-top:6px; }
  .informe-bloques p { margin:3px 0; }
  .informe-bloques ul { margin:3px 0; padding-left:20px; }
  .informe-bloques h4 { margin:10px 0 4px; font-size:12.5px; color:var(--mut); }
  .informe-bloques table { border-collapse:collapse; margin:6px 0; font-size:12px; }
  .informe-bloques th, .informe-bloques td { border:1px solid var(--line); padding:3px 6px; text-align:left; }
  .informe-bloques p.inf-fija { margin:1px 0; }
  .informe-bloques details.inf-sec { border-top:1px solid var(--line); padding:4px 0; }
  .informe-bloques details.inf-sec > summary { cursor:pointer; color:var(--acc); }
  mark.inf-alerta { background:#332a10; color:var(--warn); padding:0 3px; border-radius:3px; }
  .marca-humana { color:var(--warn); font-weight:600; }
  /* Calendario de investigaciones (rejilla mensual). SEO-TANDA-20260705-01 */
  #cal-open { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:6px 10px; font-size:12px; cursor:pointer; }
  #cal-open:hover { border-color:var(--acc); }
  .cal-section { margin:26px 0 0; border-top:1px solid var(--line); padding-top:14px; }
  /* Fila de dos columnas para secciones cortas tipo "totales" (Actividad de chats +
     Tareas pendientes): el borde/margen superior pasa a la fila, las columnas solo
     aportan su contenido. (SEO-TANDA-20260712-09) */
  .cal-row { display:flex; gap:32px; margin:26px 0 0; border-top:1px solid var(--line); padding-top:14px; }
  .cal-row .cal-section { flex:1; min-width:0; margin:0; border-top:none; padding-top:0; }
  /* Circulo unico de semaforos (SEO-TANDA-20260725-13): agrega los 3 semaforos que ya
     vive cada tarjeta (investigacion autonoma, recintos y ferias, vigilancia de
     rotulistas) en un solo indicador -- el peor estado manda -- para verlo de un
     vistazo sin abrir tarjeta por tarjeta. Un clic en cualquier punto de la seccion abre
     L1-SEM con el desglose completo (misma mecanica data-all que Actividad/Tareas/
     Archivos). */
  .sem-section { cursor:pointer; }
  .sem-section:hover .sec-tit { color:var(--acc); }
  /* Circulo y texto en la misma linea, con el texto a la derecha: mismo patron que las
     secciones vecinas de esta fila ("120 tareas pendientes", "553 archivos indexados"),
     donde el circulo hace de dato grande y el texto de etiqueta. Por eso la seccion ya no
     va centrada, sino alineada a la izquierda como ellas. SEO-TANDA-20260726-01 */
  .sem-estado { display:flex; align-items:center; gap:10px; }
  /* 23px y no 46: el circulo a tamano original competia visualmente con las cifras
     grandes de las secciones vecinas. El halo se reduce a la mitad tambien, para que no
     quede desproporcionado respecto al punto. SEO-TANDA-20260726-01 */
  .sem-circle { width:23px; height:23px; border-radius:50%; flex:0 0 auto;
    transition:transform .15s; }
  .sem-section:hover .sem-circle { transform:scale(1.08); }
  .sem-circle.ok { background:var(--ok); box-shadow:0 0 8px 1px rgba(62,207,142,.55); }
  .sem-circle.warn { background:var(--warn); box-shadow:0 0 8px 1px rgba(240,180,41,.55); }
  .sem-circle.bad { background:var(--bad); box-shadow:0 0 8px 1px rgba(255,107,107,.55); }
  /* Parpadeo ambar/rojo: hay una tarea automatica que se paso de las 06:30
     (SEO-TANDA-20260825-12). Va ENCIMA del color del semaforo, no en su lugar, porque
     responden a preguntas distintas: el color dice como acabo la ultima ejecucion y si la
     cadencia esta al dia; el parpadeo, que una noche se fue de madre. Se pinta por animacion,
     que en la cascada gana a las declaraciones normales de .ok/.warn/.bad sin necesidad de
     subir especificidad. steps(1) y no un degradado: es un intermitente, no un latido. */
  .sem-circle.desborde { animation:sem-desborde 1.1s steps(1, end) infinite; }
  @keyframes sem-desborde {
    0%, 49% { background:var(--warn); box-shadow:0 0 11px 2px rgba(240,180,41,.75); }
    50%, 100% { background:var(--bad); box-shadow:0 0 11px 2px rgba(255,107,107,.75); }
  }
  /* Con el sistema pidiendo menos movimiento, el aviso no se pierde: se queda fijo en rojo. */
  @media (prefers-reduced-motion: reduce) {
    .sem-circle.desborde { animation:none; background:var(--bad);
      box-shadow:0 0 11px 2px rgba(255,107,107,.75); }
  }
  .sem-sub { font-size:12px; color:var(--mut); }
  /* Linea que explica el parpadeo del circulo. SEO-TANDA-20260825-12 */
  .sem-desb { color:var(--warn); font-weight:600; }

  /* Tablero de avisos (L1-SEM), I-051 Fase 2: una tarjeta por fuente. Mismo lenguaje que las
     tarjetas de marca del panel (fondo #13161c, borde var(--line), radio 8), con el color del
     estado en el borde izquierdo, que es donde ya se lee un estado en el resto del panel. La
     rejilla se adapta sola: al anadir una fuente nueva no hay que tocar el CSS. */
  .avi-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr));
    gap:12px; padding:2px 0 4px; }
  .avi-card { background:#13161c; border:1px solid var(--line); border-left:4px solid var(--mut);
    border-radius:8px; padding:12px 14px; cursor:pointer;
    transition:border-color .12s ease, transform .12s ease; }
  .avi-card:hover { border-color:var(--acc); transform:translateY(-1px); }
  .avi-card.avi-ok { border-left-color:var(--ok); }
  .avi-card.avi-warn { border-left-color:var(--warn); }
  .avi-card.avi-bad { border-left-color:var(--bad); }
  .avi-tit { font-size:14px; font-weight:600; margin-bottom:6px; }
  .avi-num { font-size:13px; color:var(--txt); }
  /* El detalle NOMBRA a la culpable: un color sin nombre obliga a abrir la tarjeta solo para
     saber a quien mirar. Cuando no hay ninguna en aviso dice "sin avisos", no se queda vacio,
     porque un hueco se lee como dato que falta. */
  .avi-det { font-size:12px; color:var(--mut); margin-top:4px; }
  .avi-card.avi-warn .avi-det { color:var(--warn); }
  .avi-card.avi-bad .avi-det { color:var(--bad); }
  .avi-vacio { color:var(--mut); font-size:13px; }

  /* Recadero de TORRE (L1-RCD, I-036 Fase 4, SEO-TANDA-20260909-21). Reutiliza las tarjetas
     del tablero de avisos (.avi-*) para el semaforo, con la cifra mas grande porque aqui se
     lee de lejos, y anade solo lo que no existia: la caja de controles y los estados de la
     cola. */
  .rcd-card { cursor:default; }
  .rcd-card:hover { transform:none; border-color:var(--line); }
  .rcd-cifra { font-size:18px; font-weight:700; }
  .rcd-h { font-size:14px; font-weight:600; margin:18px 0 8px; color:var(--txt); }
  .rcd-aviso { font-size:13px; color:var(--mut); margin:0 0 12px; line-height:1.5; }
  .rcd-aviso.rcd-mal, .rcd-nota.rcd-mal { color:var(--bad); }
  .rcd-ctrl { border:1px solid var(--line); border-radius:8px; padding:12px 14px; margin:16px 0 4px;
    background:#13161c; }
  .rcd-fila { display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
  .rcd-fila:last-child { margin-bottom:0; }
  .rcd-fila-alta { align-items:flex-start; }
  .rcd-lbl { font-size:13px; color:var(--mut); min-width:130px; }
  .rcd-nota { font-size:12px; color:var(--mut); flex:1 1 260px; line-height:1.45; }
  .rcd-num { width:90px; background:var(--card); color:var(--txt); border:1px solid var(--line);
    border-radius:6px; padding:4px 8px; font-size:13px; }
  .rcd-txt { flex:1 1 320px; background:var(--card); color:var(--txt); border:1px solid var(--line);
    border-radius:6px; padding:6px 8px; font-size:12px; font-family:ui-monospace,Menlo,Consolas,monospace; }
  .rcd-btn[disabled] { opacity:.5; cursor:default; }
  .rcd-fila-enc { cursor:pointer; }
  .rcd-est { font-size:11px; text-transform:uppercase; letter-spacing:.03em; font-weight:700; }
  .rcd-est-pendiente { color:var(--warn); }
  .rcd-est-en_curso { color:var(--acc); }
  .rcd-est-hecho { color:var(--ok); }
  .rcd-est-rechazado, .rcd-est-fallido { color:var(--bad); }
  /* Los dos enganches del recadero en el panel web (I-036 Fase 5, SEO-TANDA-20260912-06):
     el boton "traemelo" de L1-ARC y el formulario de subida de L1-BUZ. */
  .rcd-traer { color:var(--acc); }
  .rcd-traer[disabled] { opacity:.6; cursor:default; }
  .rcd-fuera { font-size:11px; color:var(--mut); cursor:help; border-bottom:1px dotted var(--mut); }
  .rcd-descarga { font-weight:600; color:var(--ok); }
  .buz-remoto { margin:0 0 14px; }
  .buz-tit { font-size:13px; color:var(--txt); flex:0 0 auto; }
  .buz-input { font-size:12px; color:var(--txt); flex:1 1 220px; }
  .buz-enviar { flex:0 0 auto; }
  .buz-linea { margin:2px 0; }
  /* Tres pasos numerados del buzon remoto (I-069, parte 2 del Resumen, SEO-TANDA-20260921-16).
     Elegir, enviar y fichar son consecutivos con una espera en medio (TORRE recoge lo
     enviado), no alternativas: hasta hoy los botones iban en dos filas sueltas y se leian
     como dos caminos. El paso 3 se apaga con el buzon vacio, y los parrafos largos que
     habia en pantalla viven ahora en los tooltips de acciones.md (buz.paso_*). */
  .buz-pasos { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:10px; }
  .buz-paso { display:flex; align-items:flex-start; gap:10px; }
  .buz-num { flex:0 0 22px; width:22px; height:22px; border-radius:50%; background:var(--acc); color:#fff;
    font-size:12px; font-weight:700; display:flex; align-items:center; justify-content:center; margin-top:2px; }
  .buz-cuerpo { flex:1 1 220px; min-width:0; display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
  .buz-paso-tit { font-size:13px; font-weight:700; color:var(--txt); flex:0 0 auto; cursor:help;
    border-bottom:1px dotted var(--mut); }
  .buz-que { flex:1 1 200px; }
  .buz-pasos .buz-input { flex:0 1 auto; }
  .buz-est { flex:1 1 100%; }
  .buz-est:empty { display:none; }
  .buz-fichar[disabled] { opacity:.45; cursor:default; }
  .buz-apagado .buz-num { background:var(--line); color:var(--mut); }
  .buz-apagado .buz-paso-tit, .buz-apagado .buz-que { color:var(--mut); opacity:.7; }
  /* Formulario de correccion de una ficha de la bandeja (L2-DOC-DET, I-069 Fase 5,
     SEO-TANDA-20260918-08). La etiqueta va encima del campo y no al lado: seis
     filas de etiqueta+campo en linea no caben en un movil, que es justo el sitio
     desde el que se corrige una ficha sin estar en casa. */
  .doc-form { margin:14px 0 0; }
  .doc-form .rcd-fila { flex-direction:column; align-items:stretch; gap:3px; }
  .doc-form .rcd-fila:first-child { flex-direction:row; align-items:baseline; gap:8px; flex-wrap:wrap; }
  /* Los dos botones, en fila y con su ancho natural. La regla iba por
     `:last-of-type`, que mira el TIPO de elemento y no la clase: el ultimo div
     hijo del formulario es `#doc-estado`, asi que no casaba con nada y los
     botones heredaban el `stretch` de la fila de campos, uno debajo de otro y a
     todo lo ancho, con aspecto de caja de texto. Ahora la fila se marca con su
     propia clase. SEO-TANDA-20260919-19 */
  .doc-form .doc-acc { flex-direction:row; align-items:center; justify-content:flex-start;
    gap:8px; flex-wrap:wrap; margin-top:4px; }
  .doc-form .doc-acc .volver { width:auto; flex:0 0 auto; }
  .doc-lbl { font-size:11px; color:var(--mut); }
  .doc-campo, .doc-extra { font-size:12px; color:var(--txt); background:var(--bg);
    border:1px solid var(--line); border-radius:4px; padding:5px 7px; width:100%; }
  .doc-campo:focus, .doc-extra:focus { outline:1px solid var(--acc); }

  /* Movil: Actividad de chats / Tareas pendientes, en columna en vez de lado a lado. SEO-TANDA-20260713-28 */
  @media (max-width:680px) { .cal-row { flex-direction:column; gap:14px; } }
  /* Filtro de marcas DENTRO del calendario (reduce ruido de puntos). SEO-TANDA-20260705-01 */
  .cal-filter { display:flex; flex-wrap:wrap; align-items:center; gap:7px 9px; margin:0 0 12px; }
  .cal-filter .cbf-lbl { color:var(--mut); font-size:12px; }
  .cal-filter .cbf { display:inline-flex; align-items:center; gap:6px; font-size:12px; cursor:pointer;
    padding:3px 10px; border:1px solid var(--line); border-radius:20px; border-left:3px solid var(--bf);
    user-select:none; transition:opacity .12s ease, border-color .12s ease; }
  .cal-filter .cbf:hover { border-color:var(--bf); }
  .cal-filter .cbf input { accent-color:var(--bf); cursor:pointer; margin:0; }
  .cal-filter .cbf:has(input:not(:checked)) { opacity:.4; }
  .cal-nav { display:flex; align-items:center; gap:10px; margin-bottom:10px; }
  .cal-btn { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:5px 11px; font-size:14px; cursor:pointer; line-height:1; }
  .cal-btn:hover:not([disabled]) { border-color:var(--acc); }
  .cal-btn[disabled] { opacity:.35; cursor:default; }
  .cal-tit { font-size:15px; font-weight:600; min-width:150px; text-align:center; text-transform:capitalize; }
  .cal-hoy { margin-left:auto; font-size:12px; }
  .cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:6px; }
  .cal-dow { text-align:center; font-size:11px; color:var(--mut); text-transform:uppercase;
    letter-spacing:.5px; padding-bottom:2px; }
  .cal-cell { background:#13161c; border:1px solid var(--line); border-radius:8px;
    min-height:66px; padding:5px 6px; position:relative; display:flex; flex-direction:column; }
  .cal-cell.empty { background:transparent; border:none; }
  /* Dia actual o anterior: tono mas claro para separar lo ya transcurrido de lo por venir. SEO-TANDA-20260706-01 */
  .cal-cell.elapsed { background:#1f2530; border-color:#2b3340; }
  /* Dia con alguna investigacion/sondeo/manual todavia en_curso: mismo rojo oscuro que la
     tarjeta de detalle (.cal-dia-item--curso), va despues de .elapsed para ganarle el
     empate de especificidad en el dia de hoy (que tambien lleva esa clase). SEO-TANDA-20260716-08 */
  .cal-cell.cal-cell--curso { background:#3a1414; border-color:#5a2020; }
  .cal-cell.has-ev { cursor:pointer; }
  .cal-cell.has-ev:hover { border-color:var(--acc); }
  .cal-cell.today { outline:1px solid var(--acc); }
  .cal-daynum { font-size:12px; color:var(--mut); font-variant-numeric:tabular-nums; }
  .cal-cell.today .cal-daynum { color:var(--acc); font-weight:700; }
  /* Fila del numero del dia: en el modo actividad lleva a la derecha la medalla de record y el
     total de rombos. Si en una celda estrecha no cabe, el bloque de la derecha baja entero a
     la linea siguiente, pegado a la derecha, en vez de montarse sobre el numero.
     SEO-TANDA-20261006-36 */
  .cal-dayrow { display:flex; flex-wrap:wrap; align-items:center; gap:2px 4px; min-height:15px; }
  .cal-dayder { margin-left:auto; display:inline-flex; align-items:center; gap:3px; }
  /* Celeste con fondo propio, no el azul del panel: el numero del dia de hoy ya va en --acc
     (#5b9dff) y los dos tienen que distinguirse de un vistazo cuando comparten fila. */
  .cal-total { font-size:11px; font-weight:700; color:#38c9f2; background:rgba(56,201,242,.14);
    border-radius:4px; padding:0 4px; line-height:15px; font-variant-numeric:tabular-nums; }
  .cal-medalla { display:inline-flex; width:11px; height:13px; flex:none; }
  .cal-medalla svg { width:100%; height:100%; fill:currentColor; }
  .cal-medalla--roja { color:#ff4d4f; }
  .cal-medalla--amarilla { color:#ffd23f; }
  .cal-medalla--gris { color:#9aa3ad; }
  /* Ventana estrecha sin giro (apaisada y pequena): las celdas bajan de unos 60 px y numero,
     medalla y total no caben con el relleno de siempre. Se recorta el relleno y se encogen
     medalla y total para que sigan en la fila del numero. Solo en apaisado: en vertical por
     debajo de 900 px el panel entero se gira y las celdas vuelven a ser anchas.
     SEO-TANDA-20261006-36 */
  @media (max-width:640px) and (orientation:landscape) {
    .cal-grid { gap:4px; }
    .cal-cell { padding:4px 3px; }
    .cal-dayrow { gap:1px 2px; }
    .cal-dayder { gap:1px; }
    .cal-total { font-size:10px; padding:0 2px; }
    .cal-medalla { width:9px; height:11px; }
  }
  /* Vista horaria semanal del calendario (L3-CAL-PRG-HOR): siete columnas verticales sobre la
     franja nocturna, con un bloque por tarea automatica colocado en su hora real y alto
     proporcional a su duracion. El color lo pone la marca via --hc. SEO-TANDA-20260812-02 */
  /* Cabecera fija de la franja horaria (barra de semanas + leyenda): se queda quieta mientras
     las semanas se desplazan debajo, porque la vista abre ya situada en la semana en curso y
     si no el selector 2/4/6 y la clave de colores nacerian fuera de pantalla. top:-12px por el
     padding-top de #modal-body, que es zona de scroll (mismo caso que .roadmap-head y que la
     vista mp-view del mapa de pantallas). SEO-TANDA-20260821-09 */
  /* El -12px pasa a contarse desde el borde inferior de la barra de acciones cuando esa
     vista tiene una (--acc-h): asi las dos cabeceras fijas se apilan en vez de taparse.
     SEO-TANDA-20260826-08 */
  .hor-head { position:sticky; top:calc(var(--acc-h,0px) - 12px); z-index:6; background:var(--card);
    margin:-12px -2px 0; padding:12px 2px 2px; }
  /* La barra se queda solo con la nota (el selector 2/4/6 se retiro en
     SEO-TANDA-20260822-01), asi que la nota ya no necesita empujarse con margin-left:auto. */
  .hor-barra { display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
  .hor-nota { font-size:11px; color:var(--mut); }
  /* Una fila por semana real (SEO-TANDA-20260812-03). Desde SEO-TANDA-20260821-05 todos los
     bloques rotulan (el nombre va encima, fuera), pero la leyenda sigue haciendo falta: el
     rotulo dice la TAREA (Legion, Centuria, Rotulistas) y no la marca. */
  .hor-leyenda { display:flex; flex-wrap:wrap; gap:14px; margin:0 0 12px; }
  .hor-leg { display:flex; align-items:center; gap:5px; font-size:11px; color:var(--mut); }
  /* El cuadrito es un bloque en miniatura: mismo relleno tenue y mismo borde izquierdo, para
     que el estilo de linea que distingue los tipos se lea igual en la leyenda que en la rejilla. */
  .hor-leg-c { position:relative; width:15px; height:12px; border-radius:2px; display:inline-block;
    border-left:3px solid var(--hc); box-sizing:border-box; overflow:hidden; }
  .hor-leg-c::before { content:''; position:absolute; inset:0; background:var(--hc); opacity:.20; }
  /* El borde izquierdo vuelve a ser CONTINUO en todos los bloques (SEO-TANDA-20260825-12, a
     peticion del usuario: el discontinuo no le gusta). Nacio en SEO-TANDA-20260812-03 para
     separar dos tareas de una misma marca (De Bares corre temas y recintos, y el color es de
     marca, asi que compartian color sin nada que las distinguiera); desde
     SEO-TANDA-20260821-05 ese trabajo ya no le toca a el, porque todos los bloques rotulan
     con el nombre de su tarea (Legion, Centuria, Rotulistas), rotulo tambien lo suficiente en
     la leyenda. Las clases .hor-b--* se conservan: siguen marcando el tipo en el HTML y son
     el enganche por si algun dia hace falta distinguirlos otra vez. */
  /* Linea de "hasta aqui llega el historico", al principio de la pila. SEO-TANDA-20260821-11 */
  .hor-tope { font-size:11px; color:var(--mut); text-align:center; padding:2px 0 10px;
    margin-bottom:6px; border-bottom:1px dashed var(--line); }
  .hor-sem { margin-bottom:14px; }
  .hor-sem-tit { font-size:11px; color:var(--mut); margin-bottom:3px; padding-left:52px;
    text-transform:uppercase; letter-spacing:.04em; }
  .hor-wrap { display:flex; gap:6px; }
  /* Eje horario: contenedor del alto exacto de la caja (margen, no padding, para que ese alto
     sea el de la rejilla) con cada hora posicionada sobre su linea y centrada en ella con
     translateY(-50%). SEO-TANDA-20260822-05 */
  .hor-eje { width:46px; flex:none; margin-top:20px; position:relative; }
  .hor-eje-h { position:absolute; right:6px; transform:translateY(-50%); font-size:10px;
    color:var(--mut); font-variant-numeric:tabular-nums; }
  .hor-cols { flex:1; display:grid; grid-template-columns:repeat(7, minmax(0,1fr)); gap:4px; }
  .hor-dia { height:20px; font-size:11px; color:var(--mut); text-align:center; }
  .hor-dia.hoy { color:var(--acc); font-weight:700; }
  /* content-box y no el border-box global (SEO-TANDA-20260825-12): el alto que le pasa el
     JS es el de la REJILLA, y los bloques se colocan dentro de ella con posicion
     absoluta, que cuenta desde el borde hacia dentro. Con border-box, el borde de 1px se
     comia dos px de rejilla y un bloque que llegue al final de la franja (los recortados,
     justamente) asomaba un pixel por debajo del marco. */
  .hor-caja { position:relative; background:#1a1f29; border:1px solid #2b3340;
    border-radius:6px; box-sizing:content-box; }
  /* Dia todavia por venir dentro de la semana en curso: sin datos, no es que falten. */
  .hor-caja.futura { background:transparent; border-style:dashed; }
  .hor-linea { position:absolute; left:0; right:0; height:1px; background:#252c38; }
  /* Sin overflow:hidden: el rotulo vive fuera del bloque y no debe recortarse
     (SEO-TANDA-20260821-05). El tinte de ::before hereda el redondeo, que antes se lo daba el
     recorte del padre. */
  /* El contenedor se queda SOLO con la posicion, el tamano y el tooltip: ni borde ni
     relleno. Todo lo que se pinta vive en el hijo .hor-b-c (SEO-TANDA-20260825-12), porque
     el rasgado del borde se hace con clip-path y un clip-path aplicado aqui se llevaria por
     delante el rotulo, que cuelga FUERA del bloque (bottom:100%) y es descendiente suyo. */
  .hor-b { position:absolute; padding:1px 3px; box-sizing:border-box; font-size:10px;
    line-height:1.2; color:#dfe4ee; }
  .hor-b-c { position:absolute; inset:0; border-left:3px solid var(--hc); border-radius:3px;
    box-sizing:border-box; }
  /* El tinte va en ::before y no en background para no rebajar tambien el texto. */
  .hor-b-c::before { content:''; position:absolute; inset:0; background:var(--hc); opacity:.20;
    border-radius:inherit; }
  /* Corte de papel a mano (SEO-TANDA-20260825-12). Un bloque ya nunca se sale de su caja: lo
     que la ejecucion dure fuera de la franja 01:00-07:00 se recorta, y el borde por el que se
     ha recortado se dibuja rasgado en dientes desiguales, para que se lea "esto sigue mas
     alla" y no "esto acaba aqui". Los dientes van en % a lo ancho y en px a lo alto, asi que
     conservan su tamano sea cual sea el alto del bloque. El recorte se lleva tambien el borde
     izquierdo y el redondeo de ese lado, que es justo lo que hace que parezca rasgado y no
     cortado con regla. */
  .hor-b-c.rasga-abajo { border-bottom-left-radius:0; border-bottom-right-radius:0;
    clip-path:polygon(0 0, 100% 0,
      100% calc(100% - 5px), 93% 100%, 86% calc(100% - 6px), 78% calc(100% - 2px),
      69% calc(100% - 7px), 61% calc(100% - 1px), 52% calc(100% - 5px), 44% 100%,
      35% calc(100% - 4px), 27% calc(100% - 8px), 18% calc(100% - 2px), 9% calc(100% - 6px),
      0 calc(100% - 3px)); }
  .hor-b-c.rasga-arriba { border-top-left-radius:0; border-top-right-radius:0;
    clip-path:polygon(0 3px, 9% 7px, 17% 1px, 26% 6px, 34% 2px, 43% 8px, 52% 3px, 60% 7px,
      68% 0, 77% 5px, 85% 1px, 93% 6px, 100% 2px, 100% 100%, 0 100%); }
  /* Los dos a la vez (empezo antes de la 01:00 y termino despues de las 07:00): un solo
     polygon, porque dos clip-path no se suman, gana el ultimo. */
  .hor-b-c.rasga-arriba.rasga-abajo { border-radius:0;
    clip-path:polygon(0 3px, 9% 7px, 17% 1px, 26% 6px, 34% 2px, 43% 8px, 52% 3px, 60% 7px,
      68% 0, 77% 5px, 85% 1px, 93% 6px, 100% 2px,
      100% calc(100% - 5px), 93% 100%, 86% calc(100% - 6px), 78% calc(100% - 2px),
      69% calc(100% - 7px), 61% calc(100% - 1px), 52% calc(100% - 5px), 44% 100%,
      35% calc(100% - 4px), 27% calc(100% - 8px), 18% calc(100% - 2px), 9% calc(100% - 6px),
      0 calc(100% - 3px)); }
  /* Rotulo del bloque: encima de su borde superior, en el color de su marca, en una sola
     linea. Al estar fuera, lo pintan tambien los bloques de 3px, que son la mayoria.
     SEO-TANDA-20260821-05 */
  /* z-index para que un rotulo nunca quede por debajo de un bloque pintado despues que el
     suyo, ahora que los bloques se expanden a lo ancho y pueden cruzarse con nombres ajenos; y
     sombra fina para que se lea igual sobre el fondo de la caja que sobre el tinte de un
     bloque. SEO-TANDA-20260822-06 */
  .hor-b-t { position:absolute; left:0; bottom:100%; margin-bottom:1px; display:block;
    white-space:nowrap; font-size:10px; line-height:1.2; color:var(--hc); pointer-events:none;
    z-index:3; text-shadow:0 0 3px #10141c, 0 0 2px #10141c; }
  .hor-b-t.abajo { bottom:auto; top:100%; margin:1px 0 0; }
  /* Con un bloque a la derecha a esa misma altura, el rotulo se limita a su propio carril
     (--rmax), no al ancho expandido del bloque. */
  .hor-b-t.corta { max-width:var(--rmax, 100%); overflow:hidden; text-overflow:ellipsis; }
  .hor-b-h { position:relative; display:block; color:var(--mut); font-variant-numeric:tabular-nums; }
  .hor-vacio { color:var(--mut); font-size:13px; margin-top:10px; }
  .cal-dots { display:flex; flex-wrap:wrap; gap:4px; margin-top:4px; align-content:flex-start; }
  .cal-dot { width:11px; height:11px; border-radius:50%; box-sizing:border-box; position:relative; display:inline-block; }
  .cal-dot.dot { background:var(--dc); }
  .cal-dot.sq { background:var(--dc); border-radius:2px; }
  /* El relleno va en ::before (no en el propio .cal-dot) para que el clip-path de la cruz no
     recorte tambien el punto amarillo de .warn::after, que vive fuera del 0-100% del polygon. */
  .cal-dot.cross { background:transparent; border-radius:0; }
  .cal-dot.cross::before { content:''; position:absolute; inset:0; background:var(--dc);
    clip-path:polygon(35% 0%,65% 0%,65% 35%,100% 35%,100% 65%,65% 65%,65% 100%,35% 100%,35% 65%,0% 65%,0% 35%,35% 35%); }
  .cal-dot.star { background:transparent; border-radius:0; }
  .cal-dot.star::before { content:''; position:absolute; inset:0; background:var(--dc);
    clip-path:polygon(50% 0%,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%); }
  .cal-dot.diamond { background:var(--dc); border-radius:2px; box-sizing:border-box;
    border:2px solid var(--pcc,#888); transform:rotate(45deg); }
  /* Marcador de letra (SEO-TANDA-20260816-17): las tres tareas de sondeo de De Bares
     (Legion, Centuria y Repesca) comparten marca y tipo, asi que compartian tambien color y
     forma: tres cuadrados verdes identicos en la casilla del dia, imposibles de separar sin
     pasar el raton por encima uno a uno. Aqui el cuadrado se sustituye por su inicial en
     negrita, del mismo color de marca, dentro de la misma caja de 11px que el resto de
     marcadores, para que .warn / .fut / .inf le sigan aplicando igual. La letra va en
     ::before, como el resto de rellenos, y se lee de `data-letra`. */
  .cal-dot.letra { background:transparent; border-radius:0; }
  .cal-dot.letra::before { content:attr(data-letra); position:absolute; inset:0;
    color:var(--dc); font-weight:800; font-size:12px; line-height:11px; text-align:center;
    font-family:"Segoe UI",system-ui,sans-serif; }
  .cal-dot.warn::after { content:''; position:absolute; top:-3px; right:-3px; width:5px; height:5px;
    border-radius:50%; background:var(--warn); box-shadow:0 0 0 1px var(--card); }
  /* Mismo aspecto que .volver (Tabla normal / Ver frases...), pero en linea junto al titulo:
     .modal-h button ya fija tamano/color para el boton (cierre) y le ganaria por especificidad
     a .volver si no se repite aqui. SEO-TANDA-20260711-02 */
  .modal-h button.cal-modo-btn, .modal-h button.cal-stats-btn, .modal-h button.cal-agenda-btn,
  .modal-h button.cal-mapa-btn { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:6px 10px; font-size:12px; cursor:pointer;
    margin-bottom:0; margin-left:10px; vertical-align:middle; }
  .modal-h button.cal-modo-btn:hover, .modal-h button.cal-stats-btn:hover, .modal-h button.cal-agenda-btn:hover,
  .modal-h button.cal-mapa-btn:hover { border-color:var(--acc); }
  .cal-modo-btn:hover, .cal-stats-btn:hover, .cal-agenda-btn:hover, .cal-mapa-btn:hover { border-color:var(--acc); }
  .cal-dot.inf { opacity:.5; }
  .cal-dot.fut { opacity:.5; outline:1px dashed var(--dc); outline-offset:1px; }
  .cal-badge { position:absolute; bottom:4px; right:5px; font-size:10px; color:var(--mut);
    font-variant-numeric:tabular-nums; }
  .cal-legend { display:flex; flex-wrap:wrap; gap:10px 18px; margin-top:14px; font-size:11px;
    color:var(--mut); align-items:center; }
  .cal-legend .lg { display:flex; align-items:center; gap:6px; }
  .cal-legend .sw { width:11px; height:11px; border-radius:50%; box-sizing:border-box; display:inline-block; }
  /* Graficos de barras/tarta del calendario (Estadisticas -> Ver graficos), sin libreria
     externa: barras con divs a escala y tarta con conic-gradient. SEO-TANDA-20260715-10 */
  .cal-graf-barras { display:flex; flex-direction:column; gap:7px; margin-top:6px; }
  /* La columna de etiquetas sube de 150 a 230px (SEO-TANDA-20260813-05): eran las que se
     cortaban con puntos suspensivos (nombres de marca y de tarea), y con el modal ancho hay
     sitio de sobra. La barra sigue siendo 1fr, asi que se lleva el resto. */
  .cal-graf-fila { display:grid; grid-template-columns:230px 1fr 100px; align-items:center; gap:8px; font-size:12px; }
  .cal-graf-etq { color:var(--txt); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .cal-graf-pista { background:#13161c; border:1px solid var(--line); border-radius:4px; height:14px; overflow:hidden; }
  .cal-graf-barra { height:100%; border-radius:3px; }
  .cal-graf-val { color:var(--mut); text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
  .cal-graf-tarta-wrap { display:flex; align-items:center; gap:22px; margin-top:8px; flex-wrap:wrap; }
  .cal-graf-tarta { width:190px; height:190px; border-radius:50%; flex-shrink:0; }  /* 150 -> 190, SEO-TANDA-20260813-05 */
  .cal-graf-leyenda { display:flex; flex-direction:column; gap:5px; font-size:12px; color:var(--txt); }
  .cal-graf-leyenda-it { display:flex; align-items:center; gap:6px; }
  .cal-graf-sw { width:10px; height:10px; border-radius:2px; display:inline-block; flex-shrink:0; }
  /* Graficos SVG (lineas/histograma/dispersion/caja) del calendario, mismo criterio "sin
     libreria externa" que barras/tarta de arriba. SEO-TANDA-20260715-16 */
  .cal-graf-svg-wrap { margin-top:8px; overflow-x:auto; }
  /* Tope subido de 640 a 1040px (SEO-TANDA-20260813-05): con el modal a 1800px, 640 dejaba dos
     tercios del ancho en blanco. El min-width sube de 420 a 620 en la misma proporcion que el
     lienzo (560 -> 900), para que en pantalla estrecha el grafico no se encoja hasta que los
     textos dejen de leerse; por debajo de ese ancho scrollea .cal-graf-svg-wrap, como antes. */
  .cal-graf-svg { display:block; min-width:620px; width:100%; max-width:1040px; height:auto; }
  .cal-graf-svg text { font-family:inherit; }
  .cal-graf-eje-lbl { font-size:9px; fill:var(--mut); }
  .cal-graf-eje-cap { font-size:10px; fill:var(--mut); }
  /* Mapa mundial de recintos feriales (Calendario > Actividad programada > Mapa), SVG puro
     con proyeccion manual (calMapaSvg()), sin libreria de mapas. SEO-TANDA-20260721-12.
     La cabecera (#modal-tit) solo lleva el titulo y los botones de navegacion/accion (volver,
     acercar, alejar, restablecer), igual criterio que el resto de pantallas (calBotonModo(),
     calBotonAgenda()...: nunca cuelgan texto informativo del titulo). Zoom/resumen/pista viven
     en .cal-mapa-info, una fila propia encima del mapa, dentro del cuerpo. SEO-TANDA-20260722-10
     (antes SEO-TANDA-20260721-16 los metia en #modal-tit para ganar hueco vertical). */
  #modal-tit button.volver { margin:0 0 4px 10px; vertical-align:middle; }
  #modal-tit button.volver.activo { border-color:var(--acc); color:var(--acc); background:#0f1822; }
  .cal-mapa-info { margin:0 0 8px; }
  .cal-mapa-zoom-pct { color:var(--mut); font-size:12px; }
  .cal-mapa-resumen { color:var(--mut); font-size:12px; margin-left:10px; }
  /* El <svg width/height> se calculan cada render a partir del hueco disponible en el modal
     (no del zoom): el zoom (MAPA_ZOOM) solo recorta que ventana del mismo espacio de
     coordenadas se ve (viewBox), asi el mapa nunca crece/decrece ni se sale de esta caja.
     overflow:hidden reafirma que nada se escapa del cuadrante. SEO-TANDA-20260721-15;
     tamano segun hueco disponible + arrastre SEO-TANDA-20260722-06 */
  .cal-mapa-wrap { overflow:hidden; border:1px solid var(--line); border-radius:8px;
    background:#0c0e12; padding:6px; touch-action:none; }
  .cal-mapa-wrap--acercar .cal-mapa-svg { cursor:zoom-in; }
  .cal-mapa-wrap--alejar .cal-mapa-svg { cursor:zoom-out; }
  .cal-mapa-wrap:not(.cal-mapa-wrap--acercar):not(.cal-mapa-wrap--alejar) .cal-mapa-svg { cursor:grab; }
  .cal-mapa-wrap.cal-mapa-wrap--arrastrando .cal-mapa-svg { cursor:grabbing; }
  .cal-mapa-svg { display:block; margin:0 auto; }
  .cal-mapa-svg text { font-family:inherit; }
  /* Color solido (opacidad 1, no rgba con canal alpha reducido): CUALQUIER alpha por debajo de
     1 deja que el relleno de debajo (verde de Espana, azul de Alemania...) se mezcle con la
     linea y la tina de ese color, por muy blanca que sea la linea "de base" (le paso exacto al
     blanco translucido de la version anterior, SEO-TANDA-20260722-12: nada mas verlo sobre
     Espana se notaba verdoso). Un gris opaco (var(--mut), el mismo tono que ya usan los numeros
     de grados) no se mezcla con nada de debajo: se ve identico sobre mar, tierra sin color o
     cualquier pais coloreado. SEO-TANDA-20260722-13 */
  .cal-mapa-grid { stroke:var(--mut); stroke-width:1; }
  .cal-mapa-grid-lbl { font-size:9px; fill:var(--mut); }
  .cal-mapa-grid-lbl--y { dominant-baseline:middle; }
  /* La frontera siempre blanca (nunca el color del pais): con las capas del SVG (contorno
     translucido encima de la graticula/fondo), un borde del mismo tono que el relleno se funde
     y deja de leerse bien; un blanco fijo se ve sobre cualquier color de fondo o de pais.
     SEO-TANDA-20260722-10 */
  .cal-mapa-pais { fill:#1b2029; stroke:rgba(255,255,255,.55); stroke-width:0.75; }
  .cal-mapa-pt circle { stroke:#0c0e12; stroke-width:1; }
  .cal-mapa-wrap:not(.cal-mapa-wrap--acercar):not(.cal-mapa-wrap--alejar) .cal-mapa-pt { cursor:pointer; }
  .cal-mapa-pt:hover circle { stroke:var(--txt); stroke-width:1.5; }
  .cal-mapa-lbl { font-size:9.5px; fill:var(--txt); pointer-events:none; }
  .cal-mapa-leyenda { display:flex; flex-wrap:wrap; gap:10px 18px; margin-top:10px; font-size:11px;
    color:var(--mut); align-items:center; }
  .cal-mapa-leyenda .lg { display:flex; align-items:center; gap:6px; }
  .cal-mapa-leyenda .sw { width:11px; height:11px; border-radius:50%; box-sizing:border-box; display:inline-block; }
  /* Detalle de un dia del calendario: un bloque por ejecucion. SEO-TANDA-20260705-01 */
  .cal-dia-item { background:#13161c; border:1px solid var(--line); border-radius:10px;
    padding:10px 12px; margin-bottom:10px; }
  /* Investigacion/sondeo/manual todavia en_curso (fila write-ahead sin cerrar): mismo tono
     de rojo oscuro que .fila-incidencia en Actividad de chats. SEO-TANDA-20260716-08 */
  .cal-dia-item--curso { background:#3a1414; border-color:#5a2020; }
  /* Fondo por estado en el detalle del dia (L3-CAL-PRG-DIA), peticion del usuario
     SEO-TANDA-20260811-02: amarillo difuso para las parciales, rojo difuso para las
     canceladas (mismo rojo que --curso: ambas son ejecuciones que no hicieron su
     trabajo, la diferencia la da el texto del estado). */
  .cal-dia-item--parcial { background:#332a10; border-color:#57461c; }
  .cal-dia-item--cancelada { background:#3a1414; border-color:#5a2020; }
  .cal-dia-h { font-size:14px; margin-bottom:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
  .cal-dia-h .cal-dot { position:static; }
  /* Excepcion: la cruz necesita position:relative en si misma para que su ::before
     (relleno con clip-path, inset:0) no se posicione contra el modal entero cuando esta
     dentro de una tarjeta de evento (.cal-dia-h la resetea a static arriba). Especificidad
     de 3 clases para ganarle a la regla de encima sin depender del orden de aparicion. */
  .cal-dia-h .cal-dot.cross, .cal-dia-h .cal-dot.star,
  .cal-dia-h .cal-dot.letra { position:relative; }
  .cal-dia-h b { color:var(--txt); }
  .cal-dia-item .det-tbl th { width:190px; }
  /* Tarjeta colapsable (la Agenda y, desde SEO-TANDA-20260921-25 y -30, la vista Dia en sus
     dos modos):
     arranca contraida (solo cabecera basica) y un clic en la cabecera o en el boton de la
     derecha muestra/oculta el resto. SEO-TANDA-20260716-05 */
  .cal-dia-item--col .cal-dia-h { cursor:pointer; }
  .cal-dia-item--col .cal-dia-h::after { content:'\25B8\00A0 ver'; margin-left:auto; color:var(--mut);
    font-size:11px; flex-shrink:0; padding:2px 8px; border:1px solid var(--line); border-radius:6px;
    background:var(--bg); }
  .cal-dia-item--col .cal-dia-h:hover::after { color:var(--txt); }
  .cal-dia-item--col.cal-expandido .cal-dia-h::after { content:'\25BE\00A0 ocultar'; }
  .cal-dia-item--col:not(.cal-expandido) .cal-dia-h { margin-bottom:0; }
  .cal-dia-item--col:not(.cal-expandido) .cal-dia-resto { display:none; }
  /* Vista Agenda del calendario: arranca en "hoy" (o el ultimo dia con eventos) y solo
     amplia hacia atras/adelante bajo peticion explicita (flechas), nunca carga todo el
     historial de golpe. La lista tiene su propio scroll interno. SEO-TANDA-20260716-04 */
  .cal-agenda-wrap { margin-top:10px; }
  .cal-agenda-list { max-height:60vh; overflow-y:auto; padding-right:4px; }
  .cal-agenda-dia { margin-bottom:16px; }
  /* Separador de dia mas visible (grande/negrita/rojo), a peticion expresa del usuario,
     mismo estilo para los dos modos (comparten esta clase). SEO-TANDA-20260716-03 */
  .cal-agenda-fecha { font-size:18px; color:var(--bad); font-weight:700; text-transform:uppercase;
    letter-spacing:.03em; margin:0 0 8px; padding-bottom:4px; border-bottom:1px solid var(--line);
    display:flex; align-items:center; gap:8px; cursor:pointer; }
  /* Dias previstos (aun no ejecutados, solo aparecen al pulsar "Ver proximas" en modo
     investigaciones): separador en azul en vez de rojo, para no confundirlos con dias ya
     ejecutados. SEO-TANDA-20260716-06 */
  .cal-agenda-fecha--futura { color:var(--acc); }
  .cal-agenda-hoy { background:var(--acc); color:#000; font-size:10px; font-weight:700;
    border-radius:4px; padding:1px 6px; text-transform:none; letter-spacing:0; }
  /* Contraer/expandir un dia entero de la Agenda: contraido se queda en una sola linea
     (la propia cabecera de fecha, con el recuento) y el bloque de tarjetas desaparece.
     SEO-TANDA-20260716-05 */
  .cal-agenda-fecha::before { content:'\25BE'; font-size:12px; flex-shrink:0; }
  .cal-agenda-dia--col .cal-agenda-fecha::before { content:'\25B8'; }
  .cal-agenda-contador { margin-left:auto; color:var(--mut); font-size:12px; font-weight:400;
    text-transform:none; letter-spacing:0; }
  .cal-agenda-dia--col .cal-agenda-fecha { margin-bottom:0; border-bottom-color:transparent; }
  .cal-agenda-dia--col .cal-agenda-dia-cont { display:none; }
  .cal-agenda-edge { text-align:center; margin:8px 0; }
  .cal-agenda-arrow { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:6px; padding:7px 14px; font-size:12px; cursor:pointer; }
  .cal-agenda-arrow:hover { border-color:var(--acc); }
  .cal-agenda-fin { color:var(--mut); font-size:11px; font-style:italic; }
  /* Forzar vista horizontal en movil sujetando el telefono en vertical: rota todo el
     documento 90 grados e intercambia ancho/alto, para que se vea "panoramico" sin
     girar el telefono (a peticion expresa del usuario, que prefiere esto al apilado
     vertical). Con la rotacion el ancho real disponible pasa a ser el alto del
     telefono (grande), asi que aqui mismo se restauran los diseños de varias
     columnas de escritorio en vez de las reglas de apilado movil de mas arriba.
     SEO-TANDA-20260713-31 */
  @media screen and (max-width:900px) and (orientation:portrait) {
    html, body { margin:0; height:100%; overflow:hidden; }
    #rot { width:100vh; height:100vw; overflow-x:hidden; overflow-y:auto; position:absolute; top:0; left:0;
      transform-origin:top left; transform:rotate(90deg) translateY(-100%); -webkit-overflow-scrolling:touch; }
    /* EL ANCHO SE MIDE CON `dvh`, NO CON `vh` (SEO-TANDA-20260922-29, causa comun del corte
       por la derecha). En Chrome Android `100vh` es el alto de la ventana con la barra de
       direcciones ESCONDIDA, no el que se ve ahora: con la barra a la vista, el viewport
       real es menor. Como aqui ese valor es el ANCHO del panel girado, el resultado era un
       lienzo mas ancho que la pantalla, y lo que caia en esa franja quedaba cortado: el
       final de cada linea del articulo, el borde de las ventanas y el cajetin de la nota,
       que el usuario veia «salirse del ancho de la propia pantalla». `dvh` y `dvw` son el
       viewport de verdad, el que cambia cuando aparecen o se esconden las barras.
       Se declaran DESPUES de las de `vh`, que se quedan como respaldo para un navegador
       que no las entienda. NO SE HA PODIDO COMPROBAR AQUI: en un navegador de escritorio
       emulando un tamaño no hay barras dinamicas, asi que dvh y vh valen lo mismo y la
       diferencia solo se ve en el telefono. */
    #rot { width:100dvh; height:100dvw; }
    /* AQUI HUBO UNA BARRA DE DESPLAZAMIENTO PROPIA, Y SE RETIRO (SEO-TANDA-20260923-01).
       Se intento tres veces: como indicador, luego tambien dentro de las pantallas que se
       abren, y al final arrastrable de verdad, con el eje medido. Funcionaba, y aun asi el
       usuario la probo en el telefono y dicto que no servia: quedaba pegada a la barra de
       gestos del sistema, o sea en la unica franja de la pantalla donde el dedo no es del
       navegador. Ese es el motivo, y por eso no se vuelve a intentar en otro borde sin que
       lo pida el. El desplazamiento se queda como estaba: arrastrando sobre el contenido. */
    /* EL BOTON DE ADMINISTRACION, A LA ESQUINA CONTRARIA (orden del usuario, misma tanda).
       Lo pinta la API y en movil lo deja en `bottom:10px; right:10px`, que con el panel
       girado cae en la esquina mas disputada de la pantalla: ahi estan la barra de gestos
       del sistema y todo lo que flote. Se manda al extremo diametralmente opuesto.
       Lleva `!important` porque la regla de la API vive en la plantilla que envuelve a esta
       pagina y no se sabe cual de las dos se escribe despues; la especificidad es lo unico
       que no depende del orden. */
    #btn-adm { top:10px !important; left:10px !important;
      bottom:auto !important; right:auto !important; }
    /* UNA TARJETA POR FILA (SEO-TANDA-20260922-29, decision del usuario, repetida dos
       veces al verlo en el telefono: «mientras haya dos tarjetas no se va a poder ver»).
       Con dos, cada una se queda en la mitad del lienzo y no hay forma de leerla. Con una
       ocupa el ancho entero y cada dato tiene sitio.
       LO QUE CUESTA, Y SE ASUME: la tarjeta mide 560 px de alto contra 430 de lienzo, asi
       que sigue sin caber entera, y con cuatro en fila el recorrido pasa de 4 pantallas a
       6,5. Medido. La alternativa era dejar dos y no poder leer ninguna. Que quepa entera
       exige quitarle contenido en el movil, que es decidir que se deja de ver. */
    .grid { grid-template-columns:1fr; }
    .card-secs { grid-template-columns:1fr 1fr; }
    .metrics { grid-template-columns:repeat(4,1fr); }
    /* EL PIE, REPARTIDO EN VARIAS FILAS (SEO-TANDA-20260923-01, orden del usuario).
       Aqui habia un `flex-direction:row` a secas, de cuando se decidio la rotacion: deshacia
       el apilado de movil para recuperar el diseño de escritorio. Con diez secciones
       (Actividad de chats, Tareas, Bandeja, Ideas, Tandas, Nomenclatura, Skills, Recadero,
       Archivos y Semaforos) en una sola fila de 932 px, cada una se queda en 90: los titulos
       se parten letra a letra y se montan unos sobre otros, que es como lo vio el usuario.
       Con `wrap` y una base de 200 px caben cuatro por fila y bajan solas a la siguiente. */
    .cal-row { flex-direction:row; flex-wrap:wrap; gap:16px 24px; }
    .cal-row .cal-section { flex:1 1 200px; }
    /* Las ventanas, a pantalla completa. Se situaban arriba y estrechas (el modal de
       escritorio, centrado y con margen), asi que en el telefono quedaban flotando en una
       esquina con el panel asomando por los lados, y ademas se salian por la derecha. Aqui
       no hay sitio para una ventana dentro de otra cosa: ocupa todo y se acabo. */
    .modal { padding:0; align-items:stretch; }
    .modal-box { max-width:none; width:100%; border-radius:0; border-width:0; }
    /* Dentro del #rot, el alto que ve el usuario es el ANCHO del viewport, asi que el
       60vh de la hoja de notas (559 px con una pantalla de 932) le permitiria ser mas
       alta que toda la vista. Aqui se mide en vw, que es lo que aqui significa «alto».
       Va en este bloque a proposito: el criterio de estar girado es el de la rotacion,
       y asi no hay dos condiciones que puedan separarse. N-317, segunda pasada.
       EL SELECTOR LLEVA #rot Y NO ES ADORNO: el bloque del anotador se escribe DESPUES
       que este en la hoja de estilo, asi que un `.ano-hoja` a secas aqui perderia por
       orden contra el `.ano-hoja { max-height:60vh }` de alla, con la misma
       especificidad. Se comprobo midiendo: la regla estaba puesta y no se aplicaba
       (maxHeight seguia en 559.2px). Un id gana a una clase sea cual sea el orden, y
       ademas dice la verdad, que esto solo vale dentro del envoltorio girado. */
    #rot .ano-hoja { max-height:60dvw; }
    /* LA MISMA TRAMPA, EN TODO LO QUE SE MIDE EN `vh` (SEO-TANDA-20260922-28).
       Dentro del #rot, `vh` sigue siendo el alto del viewport FISICO (932 en el telefono
       del usuario), que aqui es el ANCHO; el alto que ve el usuario es `vw` (430). Asi que
       un `max-height:92vh` deja al modal en 857 px de alto cuando en pantalla caben 430:
       el doble de lo que cabe. Medido con el modal abierto: 800 px de alto util contra un
       lienzo de 430. No es un caso suelto, es una familia, y estos son los que quedaban
       despues de la hoja de notas. Cada uno conserva su proporcion, solo cambia el eje. */
    #rot .modal-box { max-height:100dvw; }
    #rot .cal-agenda-list { max-height:60dvw; }
  }
  /* ===== Anotador de articulos (I-028 Fase 2, SEO-TANDA-20260922-04) =====
     Patron de comentarios de Word y Google Docs: el texto a la izquierda, las notas a la
     derecha, todo visible a la vez y a la altura de su fragmento. El articulo NO se toca:
     lo unico que el anotador anade al DOM son los <span class="ano-mk"> del subrayado y los
     pines, y los dos se quitan antes de cada repintado (anoLimpiar) para que el texto plano
     con el que se calcula el anclaje siga siendo el del articulo y nada mas. */
  .art-anotable { display:flex; align-items:flex-start; gap:18px; position:relative; }
  .art-anotable > .articulo-render { flex:1 1 auto; min-width:0; }
  .ano-col { flex:0 0 288px; position:relative; min-height:40px; }
  /* Aviso de por que no se puede anotar. Nunca se calla: una ficha que simplemente no
     enseña el anotador es un fallo silencioso (tarea 8 del plan). */
  .ano-aviso { border:1px solid var(--line); border-left:3px solid var(--mut); border-radius:6px;
    padding:8px 12px; margin:0 0 10px; font-size:12px; color:var(--mut); line-height:1.5; }
  .ano-aviso.dudoso { border-left-color:#e8b339; color:#e8b339; }
  .ano-aviso b { color:var(--txt); }
  /* Cabecera: contador, nota general y huerfanas. */
  .ano-cab { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:0 0 10px; }
  .ano-cuenta { font-size:12px; color:var(--mut); }
  .ano-cuenta b { color:var(--acc); font-variant-numeric:tabular-nums; }
  .ano-huerf-wrap { border:1px solid #e8b339; border-radius:6px; padding:8px 12px;
    margin:0 0 10px; font-size:12px; }
  .ano-huerf-tit { color:#e8b339; font-weight:600; margin-bottom:6px; }
  .ano-huerf-it { border-top:1px solid var(--line); padding:6px 0; }
  .ano-huerf-it:first-of-type { border-top:0; }
  .ano-huerf-cita { color:var(--mut); font-style:italic; }
  /* Caja de «Ejecutar anotaciones» (I-028 Fase 5, SEO-TANDA-20260923-05). */
  .eje-caja { border:1px solid var(--line); border-left:3px solid var(--acc); border-radius:6px;
    padding:8px 12px; margin:0 0 10px; font-size:12px; line-height:1.5; }
  .eje-linea { margin:4px 0; }
  .eje-inc { color:#e8b339; }
  .eje-nota { color:var(--mut); }
  .eje-pedir { color:#39ff14; }
  .eje-prop { border-top:1px solid var(--line); padding:8px 0; }
  .eje-prop-tit { font-weight:600; }
  .eje-prop-cita { color:var(--mut); font-style:italic; margin:2px 0 4px; }
  .eje-prop-mot { white-space:pre-wrap; word-break:break-word; }
  .eje-prop-norma { color:var(--mut); font-size:11px; margin-top:3px; }
  .eje-preg .eje-prop-mot { color:#e8b339; }
  .eje-dif { display:grid; grid-template-columns:1fr 1fr; gap:6px; margin:4px 0; }
  .eje-antes, .eje-despues { background:#0e1116; border:1px solid var(--line); border-radius:5px;
    padding:5px 8px; white-space:pre-wrap; word-break:break-word; }
  .eje-antes span, .eje-despues span { display:block; font-size:10.5px; color:var(--mut); }
  .eje-antes { border-left:3px solid #ff6b6b; }
  .eje-despues { border-left:3px solid #39ff14; }
  .eje-si-no { margin-top:5px; }
  .eje-si-no label { margin-right:14px; cursor:pointer; }
  @media (max-width:640px) { .eje-dif { grid-template-columns:1fr; } }
  /* El subrayado: suave, sobre lo pendiente, y solo sobre lo pendiente. */
  .ano-mk { background:rgba(232,179,57,0.14); border-bottom:2px solid rgba(232,179,57,0.7);
    cursor:pointer; }
  .ano-mk.foco { background:rgba(232,179,57,0.32); }
  .ano-mk.nueva { background:rgba(57,255,20,0.16); border-bottom-color:rgba(57,255,20,0.7); }
  .ano-pin { background:none; border:0; padding:0 2px; cursor:pointer; font-size:11px;
    line-height:1; vertical-align:super; color:#e8b339; }
  .articulo-render.copiando .ano-pin { display:none; }
  /* Las tarjetas de la columna, colocadas a la altura de su marca por anoColocar(). */
  .ano-card { position:absolute; left:0; right:0; background:#13161c; border:1px solid var(--line);
    border-left:3px solid #e8b339; border-radius:6px; padding:8px 10px; font-size:12px;
    transition:top .12s ease; }
  .ano-card.general { border-left-color:var(--acc); }
  .ano-card.foco { border-color:var(--acc); }
  .ano-card-cita { color:var(--mut); font-style:italic; margin-bottom:5px;
    display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; }
  .ano-card-meta { color:var(--mut); font-size:10.5px; margin-top:5px; }
  .ano-card-txt { white-space:pre-wrap; word-break:break-word; line-height:1.45; }
  .ano-card textarea { width:100%; box-sizing:border-box; min-height:64px; resize:vertical;
    background:#0e1116; color:var(--txt); border:1px solid var(--line); border-radius:5px;
    padding:6px 8px; font:inherit; font-size:12px; }
  .ano-acc { display:flex; flex-wrap:wrap; gap:6px; margin-top:6px; }
  .ano-acc button { background:#13161c; border:1px solid var(--line); color:var(--txt);
    border-radius:5px; padding:3px 9px; font-size:11px; cursor:pointer; }
  .ano-acc button:hover { border-color:var(--acc); }
  .ano-acc button.ano-guardar { color:#39ff14; }
  .ano-acc button.ano-descartar { color:#ff6b6b; }
  .ano-err { color:#ff6b6b; margin-top:5px; font-size:11px; }
  .ano-ok { color:#39ff14; margin-top:5px; font-size:11px; }
  /* Boton flotante que aparece al soltar la seleccion. */
  .ano-flota { position:fixed; z-index:120; background:var(--acc); color:#0e1116; border:0;
    border-radius:5px; padding:5px 12px; font-size:12px; font-weight:600; cursor:pointer;
    box-shadow:0 2px 10px rgba(0,0,0,.5); }
  /* Movil: la columna se pliega y cada marca se abre por su pin, en una hoja de abajo.
     El criterio es el ancho, no el dispositivo: un escritorio estrecho se comporta igual. */
  .ano-hoja { position:fixed; left:0; right:0; bottom:0; z-index:130; background:#13161c;
    border-top:2px solid #e8b339; border-radius:10px 10px 0 0; padding:12px 14px 16px;
    max-height:60vh; overflow:auto; box-shadow:0 -4px 18px rgba(0,0,0,.6); display:none; }
  .ano-hoja.abierta { display:block; }
  /* DENTRO DE LA HOJA, LA TARJETA VUELVE AL FLUJO. Es lo que hacia que el formulario
     se saliera por abajo en el movil (N-317, segunda pasada): `.ano-card` es
     position:absolute porque en la columna de escritorio la coloca anoColocar() a la
     altura de su marca, pero absolute no cuenta para la altura de su contenedor, asi
     que la hoja se quedaba en 50 px (solo la ✕) con 144 px de contenido dentro, no
     crecia, no desplazaba pese a su overflow:auto, y el boton Guardar acababa en
     y=469 con una pantalla de 430: fuera. Medido asi, antes del arreglo. */
  .ano-hoja .ano-card { position:static; left:auto; right:auto; top:auto; }
  .ano-hoja-x { float:right; background:none; border:0; color:var(--mut); font-size:18px;
    cursor:pointer; line-height:1; }
  @media screen and (max-width:820px), screen and (max-height:560px) and (pointer:coarse) and (hover:none) {
    .art-anotable { display:block; }
    .ano-col { display:none; }
    /* El boton de anotar en movil no flota pegado a la seleccion: va fijo abajo y
       centrado. Dos motivos, los dos del encargo de N-317: queda donde llega el
       pulgar, y se aparta del menu nativo de seleccion (Copiar / Buscar), que el
       sistema saca SIEMPRE pegado al fragmento y que es lo que tapaba al boton.
       Con el panel en modo girado este «abajo» es el de la vista del usuario y no
       el del viewport, porque anoAnclar() cuelga el boton del propio #rot. */
    .ano-flota.movil { left:50% !important; right:auto; top:auto !important;
      bottom:22px; transform:translateX(-50%); padding:12px 26px; font-size:15px;
      border-radius:24px; box-shadow:0 3px 16px rgba(0,0,0,.65); }
    /* La barra de Guardar / Cancelar se queda pegada al fondo de la hoja mientras el
       resto se desplaza, para que el boton no dependa de que nadie se haya dado
       cuenta de que habia mas texto por debajo. Y con tamaño de dedo, que los 3x9 px
       de escritorio son un objetivo demasiado fino. N-317 segunda pasada. */
    .ano-hoja .ano-acc { position:sticky; bottom:-16px; z-index:1; margin:8px 0 0;
      padding:8px 0 4px; background:#13161c; box-shadow:0 -8px 10px -6px #13161c; }
    .ano-hoja .ano-acc button { padding:9px 18px; font-size:14px; }
    .ano-hoja textarea { min-height:56px; }
  }
