/* =============================================================================
   INICIO (el dashboard) — identidad visual. Scope `.dh-ui`.
   =============================================================================
   docs/RUNBOOK-INICIO.md. Ronda de mockups cerrada el 25/08/2026: ganó A
   «el radar» con cuatro ajustes (sin cinta del turno, fraccionado primero,
   columnas compactas, gráfico por énfasis). La lámina que se construye es
   docs/dashboard/02-ronda2-A-ajustada.html.

   ── EL TRATAMIENTO, y por qué ────────────────────────────────────────────────
   CABECERA LITE. Inicio no tiene acción principal —no se carga nada acá— así
   que en la pantalla no hay NINGUNA superficie navy rellena: la barra del
   armazón lleva un solo botón, Actualizar, fantasma (manual §1.2).

   ACENTO: NAVY Y NADA MÁS. El tablero no apila cuatro zonas: es una tira y
   tres filas de tarjetas. No se inventa un segundo azul.

   CERO TOKENS PROPIOS. La paleta sale entera de core/tokens.css. Si algún día
   hace falta apartarse, se redeclara el token en este scope y SE ESCRIBE EL
   PORQUÉ al lado — hoy no hay ninguno.

   ── LAS CATORCE FAMILIAS QUE MUEREN ──────────────────────────────────────────
   El tablero tenía color = CATEGORÍA: Producción azul-índigo, Despachos
   esmeralda-teal, Recepciones ámbar-naranja, RRHH púrpura, el stock índigo,
   la MP ámbar. En la misma tarjeta el ámbar decía «materia prima» arriba y
   «pendiente» abajo. Se van etapa por etapa, y lo que queda es el vocabulario
   del manual §1.1: ámbar lo que pide algo, verde lo cumplido, rojo lo que está
   mal, gris lo que no pide nada.

   ── DE DÓNDE SALE CADA PIEZA ─────────────────────────────────────────────────
   Nada acá es nuevo: son las piezas de los módulos migrados, portadas con su
   prefijo. La tarjeta, la barra de secciones, los badges y las marcas son de
   facturas-ui.css; las celdas rótulo·cifra·nota, de produccion-dia-ui.css §3-4;
   el medidor, de rrhh-ui.css; la frescura, de stock-ui.css §2.
   (Dos pantallas del mismo objeto se dibujan igual: la tarjeta de Producción
   porta el vocabulario de Producción del Día porque ES el mismo turno.)

   ── ORDEN DE LAS SECCIONES ───────────────────────────────────────────────────
    1. EL ARMAZÓN — la raíz y las grillas                        (ETAPA 1)
    2. LA TIRA DE ACCIÓN — contadores, chips y frescura          (ETAPA 2)
    3. LAS TRES COLUMNAS DEL DÍA — tarjeta, celdas, filas        (ETAPA 2)
    4. EL STOCK — rankings con medidor                           (ETAPA 3)
    5. TENDENCIAS Y GENTE — gráficos SVG                         (ETAPA 4)
   ============================================================================= */


/* =============================================================================
   1. EL ARMAZÓN — la raíz y las grillas (ETAPA 1)
   =============================================================================
   `#page-dashboard` es un `.page-content` NORMAL, no `data-shell="full"`: el
   wrapper del armazón ya le da el padding (26/30 px) y el scroll de página, que
   es lo que un tablero que se recorre necesita. Por eso la raíz NO declara
   padding: si lo hiciera, el contenido quedaría con dos márgenes sumados.

   EL SCOPE VA EN UN <div> HIJO, no en el propio `.page-content`: `#page-dashboard`
   se oculta y se muestra con el `.hidden` de Tailwind (una clase), y una regla
   de este módulo que declarara `display` sobre ese mismo elemento le ganaría
   (trampa del §4 del RUNBOOK-NUEVA-IDENTIDAD). Y VA COMO COMPUESTO,
   `.dh-ui.dh-body`, sin espacio: las dos clases están en el MISMO elemento.
   ========================================================================== */
.dh-ui.dh-body {
    display: flex; flex-direction: column; gap: 14px;
    min-width: 0;
}

/* Las tres grillas de la página. `minmax(0, 1fr)` y no `1fr` a secas: sin el
   mínimo en cero una columna con un nombre largo se estira y corre a las otras
   dos (trampa «grid sin min-width:0 se estira»). */
.dh-ui .dh-g3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.dh-ui .dh-gc { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }

/* EN UN CELULAR LAS GRILLAS SE APILAN. El tablero mobile es otro archivo, pero
   este marcado también se ve en una tablet en vertical. */
@media (max-width: 900px) {
    .dh-ui .dh-g3, .dh-ui .dh-gc { grid-template-columns: minmax(0, 1fr); }
}


/* =============================================================================
   2. LA TIRA DE ACCIÓN — contadores, chips y frescura (ETAPA 2)
   =============================================================================
   Seis contadores accionables a la izquierda (el `.fx-alert` de Facturación,
   portado) y a la derecha lo que NO pide nada —presentes, movimientos— en gris,
   más de cuándo es el número (la frescura de Stock General §2). Es UNA fila:
   lo que pide acción y lo que no se distinguen por el color y el trazo, no por
   el lugar.
   ========================================================================== */
.dh-ui .dh-tira { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dh-ui .dh-cap {
    font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint); white-space: nowrap;
}

/* El contador accionable. Ámbar de estado: pide algo. Rojo cuando es grave
   (`.neg`), gris cuando está en cero (`.cero`: no pide nada, pero se ve que se
   contó), y `.sinDato` cuando la consulta falló — se distingue del cero. */
.dh-ui .dh-alert {
    display: inline-flex; align-items: center; gap: 9px;
    background: transparent; border: 1px solid var(--hair-strong); border-left: 3px solid var(--warn);
    border-radius: 8px; padding: 5px 12px; cursor: pointer; font: inherit; color: inherit;
    transition: background .15s, border-color .15s, transform .15s var(--curva);
}
.dh-ui .dh-alert:hover, .dh-ui .dh-alert:focus-visible { background: var(--warn-050); border-color: var(--warn); transform: translateY(-1px); outline: none; }
.dh-ui .dh-alert .k { font-size: .6rem; text-transform: uppercase; letter-spacing: .1em; font-weight: 700; color: var(--muted); }
.dh-ui .dh-alert .v { font-size: 1.05rem; font-weight: 800; color: var(--warn); line-height: 1; font-variant-numeric: tabular-nums; min-width: 1.1em; }
.dh-ui .dh-alert .material-symbols-outlined { font-size: 16px; color: var(--faint); }
.dh-ui .dh-alert.neg { border-left-color: var(--crit); }
.dh-ui .dh-alert.neg .v { color: var(--crit); }
.dh-ui .dh-alert.neg:hover, .dh-ui .dh-alert.neg:focus-visible { background: var(--crit-050); border-color: var(--crit); }
.dh-ui .dh-alert.cero { border-left-color: var(--hair-strong); }
.dh-ui .dh-alert.cero .v { color: var(--faint); font-weight: 700; }
.dh-ui .dh-alert.cero:hover, .dh-ui .dh-alert.cero:focus-visible { background: var(--navy-050); border-color: var(--hair-strong); }
.dh-ui .dh-alert.sinDato { border-left-color: var(--hair-strong); border-style: dashed; }
.dh-ui .dh-alert.sinDato .v { color: var(--faint); }
.dh-ui .dh-alert.esperando { border-left-color: var(--hair-strong); }

.dh-ui .dh-tira-r { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* El chip neutro: no pide nada, así que no lleva color de estado. Es un botón
   porque lleva a su módulo. (`.pd-chip` de Producción del Día.) */
.dh-ui .dh-chip {
    display: inline-flex; align-items: center; gap: 6px;
    border-radius: 999px; padding: 4px 11px;
    font: inherit; font-size: 12px; font-weight: 600;
    border: 1px solid var(--hair-strong); color: var(--muted); background: var(--surface);
    cursor: pointer; transition: transform .15s var(--curva), background .15s;
}
.dh-ui .dh-chip .material-symbols-outlined { font-size: 15px; }
.dh-ui .dh-chip:hover, .dh-ui .dh-chip:focus-visible { transform: translateY(-1px); background: var(--navy-050); outline: none; }
/* El turno es el único chip que puede pedir algo: «Falta 1» va en rojo. */
.dh-ui .dh-chip.neg { color: var(--crit); border-color: var(--crit-hair); background: var(--crit-050); }

/* La frescura: sin caja, es un dato de confianza y no un objeto. Verde el
   número vivo, ámbar la foto del robot. (stock-ui.css §2.) */
.dh-ui .dh-fresc { display: inline-flex; align-items: center; gap: 6px; padding: 0 4px; font-size: 11px; color: var(--muted); white-space: nowrap; }
.dh-ui .dh-fresc .material-symbols-outlined { font-size: 15px; }
.dh-ui .dh-fresc b { font-weight: 700; }
.dh-ui .dh-fresc.vivo .material-symbols-outlined, .dh-ui .dh-fresc.vivo b { color: var(--ok); }
.dh-ui .dh-fresc.foto .material-symbols-outlined, .dh-ui .dh-fresc.foto b { color: var(--warn); }


/* =============================================================================
   3. LAS TRES COLUMNAS DEL DÍA — tarjeta, celdas, filas (ETAPA 2)
   =============================================================================
   La tarjeta es la de Facturación (`.fx-card`); las celdas rótulo·cifra·nota
   son las de Producción del Día §3-4; la fila con franja de estado es la fila
   de `table.fx-g` sin ser una tabla. Las tres columnas miden lo mismo: la
   grilla las estira y el pie se pega abajo con `margin-top: auto`.
   ========================================================================== */
.dh-ui .dh-card {
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: var(--r-card); box-shadow: var(--shadow);
    overflow: hidden; display: flex; flex-direction: column; min-width: 0;
}
.dh-ui .dh-card-h {
    background: #fafbfc; border-bottom: 1px solid var(--hair);
    padding: 10px var(--gutter); display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.dh-ui .dh-card-h h4 {
    font-size: .68rem; text-transform: uppercase; letter-spacing: .11em; font-weight: 700;
    color: var(--muted); margin: 0; font-family: inherit; display: inline-flex; align-items: center; gap: 7px;
}
.dh-ui .dh-card-h h4 .material-symbols-outlined { font-size: 16px; color: var(--faint); }
.dh-ui .dh-card-h .r { margin-left: auto; display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }

/* Las celdas: rótulo · cifra · nota. «Números gigantes, no»: 19 px la cifra,
   que es el KPI del ABM. Lo que necesita gritar, grita por el color. */
.dh-ui .dh-kv { display: flex; gap: 14px; flex-wrap: nowrap; padding: 12px var(--gutter); border-bottom: 1px solid var(--hair); }
.dh-ui .dh-kv > div { flex: 1 1 0; min-width: 0; }
.dh-ui .dh-kv > .sep { flex: 0 0 1px; background: var(--hair); align-self: stretch; }
.dh-ui .dh-kv .l { font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--faint); white-space: nowrap; }
.dh-ui .dh-kv .v { font-size: 19px; font-weight: 700; letter-spacing: -.02em; line-height: 1.2; font-variant-numeric: tabular-nums; }
.dh-ui .dh-kv .v small { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.dh-ui .dh-kv .v.warn { color: var(--warn); }
.dh-ui .dh-kv .v.crit { color: var(--crit); }
.dh-ui .dh-kv .v.apagado { color: var(--muted); }
/* El dato que todavía no existe NO es un cero: dice qué está esperando. */
.dh-ui .dh-kv .v.ausente { font-size: 13px; font-weight: 600; font-style: italic; color: var(--faint); letter-spacing: 0; }
.dh-ui .dh-kv .s { font-size: 11px; color: var(--muted); margin-top: 2px; }
.dh-ui .dh-kv .s.ok { color: var(--ok); font-weight: 600; }
.dh-ui .dh-kv .s.warn { color: var(--warn); font-weight: 600; }
.dh-ui .dh-kv .s.crit { color: var(--crit); font-weight: 600; }

.dh-ui .dh-sub { padding: 8px var(--gutter) 2px; font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--faint); }
.dh-ui .dh-lista { padding: 0 calc(var(--gutter) - 9px); }

/* La fila: franja de estado a la izquierda —el ojo encuentra lo que pide
   acción sin leer la fila—, título y detalle en dos renglones que NO se
   cortan a mitad de palabra, y la cifra a la derecha con dígitos tabulares. */
.dh-ui .dh-fila {
    display: flex; align-items: center; gap: 10px;
    padding: 7px 12px 7px 9px; border-left: 3px solid transparent; border-bottom: 1px solid var(--hair);
    font-size: 12.4px; min-width: 0;
}
.dh-ui .dh-fila:last-child { border-bottom: 0; }
.dh-ui .dh-fila.st-ok  { border-left-color: var(--ok-hair); }
.dh-ui .dh-fila.st-wrn { border-left-color: var(--warn); }
.dh-ui .dh-fila.st-neg { border-left-color: var(--crit); background: rgba(198, 40, 40, .035); }
.dh-ui .dh-fila.st-nav { border-left-color: var(--navy-300); }
.dh-ui .dh-fila .t { flex: 1; min-width: 0; line-height: 1.25; }
.dh-ui .dh-fila .t b { font-weight: 700; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-ui .dh-fila .t .dim { display: block; font-size: 11px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-ui .dh-fila .n { font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
.dh-ui .dh-fila .n .u { color: var(--faint); font-weight: 600; }
.dh-ui .dh-fila .mono { font-family: 'Consolas', 'SF Mono', 'Roboto Mono', monospace; }
/* El resto de artículos se lista igual —el total del turno se reconstruye a
   ojo— pero apagado: la cifra principal es el fraccionado. */
.dh-ui .dh-fila.apagada .t b { font-weight: 600; color: var(--muted); }
.dh-ui .dh-fila.apagada .n { color: var(--muted); }
/* El esqueleto tiene el alto de la fila real (medido: 40 px con dos renglones). */
.dh-ui .dh-fila.sk .t b .gs-sk { margin: 3px 0; }
.dh-ui .dh-fila.sk .t .dim .gs-sk { margin: 3px 0 2px; }

/* Estado — badges y marcas (facturas-ui.css). */
.dh-ui .dh-b { display: inline-block; font-size: 10.5px; font-weight: 700; padding: 2px 8px; border-radius: 20px; letter-spacing: .02em; border: 1px solid; white-space: nowrap; }
.dh-ui .dh-b.ok  { background: var(--ok-050);   color: var(--ok);   border-color: var(--ok-hair); }
.dh-ui .dh-b.wrn { background: var(--warn-050); color: var(--warn); border-color: var(--warn-hair); }
.dh-ui .dh-b.neg { background: var(--crit-050); color: var(--crit); border-color: var(--crit-hair); }
.dh-ui .dh-b.nav { background: var(--navy-050); color: var(--navy); border-color: #d3e0f2; }
.dh-ui .dh-b.mut { background: #f4f6f9; color: var(--muted); border-color: var(--hair); }
.dh-ui .dh-mark { font-size: 11.5px; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.dh-ui .dh-mark .material-symbols-outlined { font-size: 16px; }
.dh-ui .dh-mark.ok  { color: var(--ok); }
.dh-ui .dh-mark.wrn { color: var(--warn); }
.dh-ui .dh-mark.neg { color: var(--crit); }
.dh-ui .dh-mark.mut { color: var(--faint); }

/* El pie: lo cerrado, en una línea, y la puerta al módulo. `margin-top: auto`
   lo pega abajo cuando la grilla estira la tarjeta. */
.dh-ui .dh-card-f {
    margin-top: auto; padding: 9px var(--gutter); border-top: 1px solid var(--hair); background: #fafbfc;
    display: flex; align-items: center; gap: 10px; font-size: 11.5px; color: var(--muted);
}
.dh-ui .dh-card-f .r { margin-left: auto; white-space: nowrap; }
/* El botón-enlace: texto gris en reposo, navy sólo al apuntarlo (manual §1.2). */
.dh-ui .dh-ln {
    background: none; border: 0; color: var(--muted); font: inherit; font-size: 12.4px; font-weight: 600;
    padding: 5px 8px; border-radius: 8px; cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
    transition: background .15s, color .15s;
}
.dh-ui .dh-ln .material-symbols-outlined { font-size: 16px; transition: transform .18s var(--curva); }
.dh-ui .dh-ln:hover, .dh-ui .dh-ln:focus-visible { background: var(--navy-050); color: var(--navy); outline: none; }
.dh-ui .dh-ln:hover .material-symbols-outlined { transform: translateX(3px); }

/* Vacío y fallo: un dato ausente es información (manual §1.4). El fallo dice
   qué no se pudo leer, en rojo, y no deja la tarjeta en blanco. */
.dh-ui .dh-vacio { padding: 22px var(--gutter); text-align: center; color: var(--faint); font-style: italic; font-size: 12.5px; }
.dh-ui .dh-vacio .material-symbols-outlined { display: block; margin: 0 auto 6px; font-size: 22px; color: var(--hair-strong); }
.dh-ui .dh-vacio.crit { color: var(--crit); font-style: normal; font-weight: 600; }
.dh-ui .dh-vacio.crit .material-symbols-outlined { color: var(--crit); }

/* §5 del manual: no se apaga la información, se apaga el movimiento. */
@media (prefers-reduced-motion: reduce) {
    .dh-ui .dh-alert, .dh-ui .dh-chip, .dh-ui .dh-ln .material-symbols-outlined { transition: none; }
    .dh-ui .dh-alert:hover, .dh-ui .dh-chip:hover, .dh-ui .dh-ln:hover .material-symbols-outlined { transform: none; }
}


/* =============================================================================
   4. EL STOCK — rankings con medidor (ETAPA 3)
   =============================================================================
   Tres tarjetas en `.dh-gc`: dónde están · producto terminado · azúcar para
   fraccionar. La pieza es UNA: el ranking con medidor —rótulo, cifra y una
   barra de posición— (`.rr-meter` de RRHH). La tarjeta de depósitos usa el
   medidor de DOS tramos: MP en navy claro, PT en navy. Es la única vez que un
   azul más claro significa algo, y es identidad (MP vs PT), no estado.
   ========================================================================== */
.dh-ui .dh-card-b { padding: 6px var(--gutter) 8px; }

.dh-ui .dh-rank {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 12px; align-items: center;
    padding: 6px 0; border-bottom: 1px solid var(--hair);
    width: 100%; text-align: left; font: inherit; color: inherit; background: none; border-left: 0; border-right: 0; border-top: 0;
}
.dh-ui .dh-rank:last-child { border-bottom: 0; }
.dh-ui .dh-rank .t { font-size: 12.4px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.dh-ui .dh-rank .n { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; font-size: 12.6px; white-space: nowrap; }
.dh-ui .dh-rank .n small { color: var(--faint); font-weight: 600; font-size: 10.5px; }
/* El Δ por producto: chico, al lado de la cifra, con el color del signo. */
.dh-ui .dh-rank .n .dlt { margin-left: 6px; font-weight: 700; }
.dh-ui .dh-rank .n .dlt.ok  { color: var(--ok); }
.dh-ui .dh-rank .n .dlt.mal { color: var(--crit); }
.dh-ui .dh-rank .dh-meter { grid-column: 1 / 3; }
/* La fila de producto terminado es un BOTÓN: abre la ficha. Se levanta como
   una fila de lista (barra a la izquierda), no como un botón. */
.dh-ui button.dh-rank { cursor: pointer; border-radius: 6px; padding-left: 6px; padding-right: 6px; margin-left: -6px; margin-right: -6px; width: calc(100% + 12px); transition: background .13s; }
.dh-ui button.dh-rank:hover, .dh-ui button.dh-rank:focus-visible { background: var(--navy-050); outline: none; }
.dh-ui button.dh-rank:hover .t { color: var(--navy); }

/* El medidor (rrhh-ui.css). El de dos tramos separa MP y PT con un hueco de
   2 px del color de la superficie: es el hueco lo que separa, no un borde. */
.dh-ui .dh-meter { background: var(--navy-050); border-radius: 99px; overflow: hidden; height: 6px; display: flex; gap: 2px; }
.dh-ui .dh-meter span { display: block; height: 100%; border-radius: 99px; background: var(--navy); flex: none; }
.dh-ui .dh-meter.dos span.mp { background: var(--navy-300); }
.dh-ui .dh-meter.dos span:not(.mp) { border-radius: 0 99px 99px 0; }
.dh-ui .dh-meter.dos span.mp { border-radius: 99px 0 0 99px; }

/* La nota al pie del cuerpo: la leyenda de los dos tramos y el tercero que
   no suma. Los cuadraditos son de identidad, no de estado. */
.dh-ui .dh-nota { font-size: 11px; color: var(--faint); margin-top: 10px; line-height: 1.55; }
.dh-ui .dh-nota b { color: var(--muted); }
.dh-ui .dh-nota .sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px; background: var(--navy); vertical-align: -1px; }
.dh-ui .dh-nota .sw.mp { background: var(--navy-300); }

/* Lo que pide algo adentro de una tarjeta: el artículo sin categoría, que
   hasta que se cargue no suma en ningún lado (facturas-ui.css `.fx-risk`). */
.dh-ui .dh-aviso { display: flex; align-items: flex-start; gap: 9px; padding: 10px 13px; border-radius: 9px; font-size: 12.2px; border: 1px solid var(--warn-hair); border-left: 3px solid var(--warn); background: var(--warn-050); color: #8a4a00; margin-top: 10px; line-height: 1.5; }
.dh-ui .dh-aviso .material-symbols-outlined { font-size: 18px; flex: none; margin-top: 1px; }
.dh-ui .dh-aviso b { font-weight: 700; }

/* El esqueleto de un ranking mide la fila real (rótulo + medidor). */
.dh-ui .dh-rank.sk .t .gs-sk { margin: 5px 0; }
.dh-ui .dh-rank.sk .n .gs-sk { margin: 5px 0; }


/* =============================================================================
   5. TENDENCIAS Y GENTE — gráficos SVG (ETAPA 4)
   =============================================================================
   Los dos gráficos se dibujan en SVG con los tokens: marcas finas (barra de
   hasta 24 px con la punta redondeada, línea de 2 px, punto de 8 px con anillo
   del color de la superficie), grilla de un pelo, texto con los tokens de
   texto y NUNCA con el color de la serie. El único color con significado es el
   del punto final del desvío, que es de ESTADO.
   ========================================================================== */
.dh-ui .dh-chart { padding: 8px var(--gutter) 6px; }
.dh-ui .dh-chart > svg { display: block; width: 100%; height: auto; overflow: visible; }
.dh-ui .dh-chart text { font-family: inherit; font-size: 10px; fill: var(--faint); font-variant-numeric: tabular-nums; }
.dh-ui .dh-chart text.v { fill: var(--ink); font-weight: 700; font-size: 11px; }
.dh-ui .dh-chart line.grid { stroke: var(--hair); stroke-width: 1; }
.dh-ui .dh-chart line.grid.cero { stroke: var(--hair-strong); }
/* El desvío: la banda de lo NORMAL (±0,6 %) se pinta con el color de estado
   casi transparente, las marcas de atención (±1,0 %) van punteadas; son las
   únicas cosas que no son dato. Un punto FUERA DE ESCALA es un triángulo
   crítico en el borde, y cada punto lleva un blanco invisible de 10 px para
   que el title salga sin cazar el punto de 3. */
.dh-ui .dh-chart rect.banda.ok { fill: var(--ok); opacity: .07; }
.dh-ui .dh-chart path.fuera { fill: var(--crit); stroke: var(--surface); stroke-width: 1.5; }
.dh-ui .dh-chart circle.hit { fill: transparent; stroke: none; pointer-events: all; }
.dh-ui .dh-leg .fuera { color: var(--crit); font-weight: 600; display: inline-flex; align-items: center; gap: 3px; }
.dh-ui .dh-leg .fuera .material-symbols-outlined { font-size: 14px; }
.dh-ui .dh-chart line.marca { stroke-width: 1.5; stroke-dasharray: 3 3; }
.dh-ui .dh-chart line.marca.ok  { stroke: var(--ok); }
.dh-ui .dh-chart line.marca.wrn { stroke: var(--warn); }
.dh-ui .dh-chart text.marca { font-weight: 700; }
.dh-ui .dh-chart text.marca.ok  { fill: var(--ok); }
.dh-ui .dh-chart text.marca.wrn { fill: var(--warn); }
.dh-ui .dh-chart circle.fin.ok  { fill: var(--ok); }
.dh-ui .dh-chart circle.fin.wrn { fill: var(--warn); }
.dh-ui .dh-chart circle.fin.neg { fill: var(--crit); }

/* La leyenda: siempre presente con dos series; el texto en tokens de texto y
   la identidad en el cuadradito de al lado. */
.dh-ui .dh-leg { display: flex; gap: 14px; flex-wrap: wrap; font-size: 11px; color: var(--muted); padding: 6px 0 0; }
.dh-ui .dh-leg i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.dh-ui .dh-leg .r { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; }
.dh-ui .dh-leg .r .material-symbols-outlined { font-size: 14px; }
.dh-ui .dh-leg b.ok  { color: var(--ok); }
.dh-ui .dh-leg b.wrn { color: var(--warn); }
.dh-ui .dh-leg b.neg { color: var(--crit); }

/* El selector de la cabecera: se lee como un dato con etiqueta, no como un
   botón (el `.shell-sel` del armazón, a escala de tarjeta). */
.dh-ui .dh-sel { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 9px; border-radius: 8px; background: var(--navy-050); border: 1px solid #cfdcef; cursor: pointer; max-width: 260px; }
.dh-ui .dh-sel span { font-size: .58rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--navy); opacity: .72; white-space: nowrap; }
.dh-ui .dh-sel select { min-width: 0; max-width: 100%; border: 0; background: none; outline: none; font-family: inherit; font-size: 12px; font-weight: 600; color: var(--navy); cursor: pointer; text-overflow: ellipsis; }
.dh-ui .dh-sel:focus-within { outline: 2px solid var(--navy-500); outline-offset: 2px; }
