/* ============================================================================
   V12 · Sistema de diseño
   Blanco, naranja y gris. Se apoya sobre Bootstrap 4 sin pelearse con él:
   todo lo propio va con prefijo .v12- y las sobrescrituras son deliberadas.
   ========================================================================== */

:root {
    /* --- Marca ------------------------------------------------------------ */
    --v12-orange-700: #C24A10;
    --v12-orange-600: #E05A15;
    --v12-orange-500: #F26A21;   /* principal: acciones e interacción */
    --v12-orange-400: #FF8442;
    --v12-orange-100: #FFE2D2;
    --v12-orange-50:  #FFF4ED;

    /* --- Relleno de acción ------------------------------------------------
       El acento de marca (#F26A21) es un color de IDENTIDAD: vale para reglas,
       bordes y realces. Como FONDO de un texto blanco de 14px no llega a AA
       —3,06:1 frente al 4,5:1 que se exige—, y estos informes se presentan
       ante auditores y reguladores. El relleno de los botones sale por tanto
       de un tono más profundo del mismo acento, no del acento a secas.
       Branding.php emite estos mismos tokens con las mismas mezclas cuando el
       cliente pone su color, y elige ahí el color del texto por medición: un
       acento claro llevaría tinta oscura en vez de blanca. */
    --v12-fill-accent:        #A04616;   /* mezcla 0,34 con negro · blanco encima: 6,21:1 */
    --v12-fill-accent-hover:  #8C3D13;   /* mezcla 0,42 · 7,52:1 */
    --v12-fill-accent-active: #793511;   /* mezcla 0,50 · 9,01:1 */
    --v12-on-accent:          #FFFFFF;

    /* --- Neutros (gris cálido, para convivir con el naranja) --------------- */
    --v12-gray-900: #1B1F24;     /* texto principal */
    --v12-gray-800: #2C333A;
    --v12-gray-700: #414A54;     /* texto secundario fuerte */
    --v12-gray-600: #56606B;
    --v12-gray-500: #6B7681;     /* texto atenuado */
    --v12-gray-400: #98A2AC;
    --v12-gray-300: #C9D0D7;     /* bordes marcados */
    --v12-gray-200: #E3E8ED;     /* bordes */
    --v12-gray-100: #F1F4F7;     /* superficie hundida */
    --v12-gray-50:  #F8FAFB;     /* fondo de página */
    --v12-white: #FFFFFF;

    /* --- Semánticos ------------------------------------------------------- */
    --v12-ok:    #1F8A54;
    --v12-ok-bg: #E7F5ED;
    --v12-warn:  #B67300;
    --v12-warn-bg: #FDF4E3;
    --v12-danger: #B3261E;
    --v12-danger-bg: #FBEBEA;
    --v12-info:  #2E6FA8;
    --v12-info-bg: #EAF2F9;

    /* --- Severidad -------------------------------------------------------- */
    /* Deliberadamente distintas del naranja de marca: el naranja es "acción",
       nunca "gravedad". Además cada chip lleva punto + texto, así que no
       dependen solo del color. */
    --sev-critical: #B3261E;
    --sev-high:     #E07C00;
    --sev-medium:   #C9A227;
    --sev-low:      #3E7CB1;
    --sev-info:     #7A8592;

    /* --- Series de gráficos (identidad, sin semántica) --------------------- */
    /* Orden FIJO: nunca se recicla un tono ni se repinta al filtrar. La primera
       sigue al acento de marca (white-label). Paleta validada (visión normal y
       CVD) sobre superficie clara; severidad y estado usan SUS tokens, no estos. */
    --v12-chart-1: var(--v12-orange-600);
    --v12-chart-2: #3A6EA5;
    --v12-chart-3: #B08A2E;
    --v12-chart-4: #0F9583;
    --v12-chart-5: #7A5AA0;
    --v12-chart-6: #9E3648;

    /* --- Elevación (sutil; el papel manda, no la sombra) ------------------- */
    --v12-shadow-sm: 0 1px 2px rgba(27,31,36,.06), 0 1px 3px rgba(27,31,36,.04);
    --v12-shadow-md: 0 2px 6px rgba(27,31,36,.07), 0 6px 16px rgba(27,31,36,.06);
    --v12-shadow-lg: 0 8px 24px rgba(27,31,36,.10), 0 2px 6px rgba(27,31,36,.06);
    --v12-ring: 0 0 0 3px rgba(242,106,33,.22);

    /* --- Geometría y ritmo ------------------------------------------------ */
    --v12-r-sm: 6px;
    --v12-r-md: 10px;
    --v12-r-lg: 14px;
    --v12-r-pill: 999px;
    --v12-ease: cubic-bezier(.2,.7,.3,1);
    /* La plantilla de administración impone una serif a los encabezados; los
       componentes propios fijan su familia para no heredarla. */
    --v12-font: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                "Helvetica Neue", Arial, sans-serif;

    --v12-fast: 140ms;
    --v12-slow: 260ms;
}

/* ============================================================================
   Base
   ========================================================================== */

.v12 {
    color: var(--v12-gray-900);
    font-feature-settings: "cv02","cv03","cv04","tnum" 0;
}

.v12 h1, .v12 h2, .v12 h3, .v12 h4 {
    color: var(--v12-gray-900);
    letter-spacing: -.011em;
    font-weight: 600;
}

.v12-page-title {
    font-size: 1.375rem;
    font-weight: 650;
    letter-spacing: -.02em;
    margin: 0;
}
.v12-page-sub {
    color: var(--v12-gray-500);
    font-size: .875rem;
    margin: .25rem 0 0;
}

.v12-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

/* Números tabulares donde se comparan cifras */
.v12-num { font-variant-numeric: tabular-nums; }

/* ============================================================================
   Superficies
   ========================================================================== */

.v12-card {
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    box-shadow: var(--v12-shadow-sm);
    transition: box-shadow var(--v12-fast) var(--v12-ease),
                border-color var(--v12-fast) var(--v12-ease),
                transform var(--v12-fast) var(--v12-ease);
}
.v12-card--hover:hover {
    box-shadow: var(--v12-shadow-md);
    border-color: var(--v12-gray-300);
}
.v12-card__head {
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--v12-gray-200);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
}
/* Cuando el subtítulo explica el título en lugar de acompañarlo (los pasos del
   asistente), apilarlos se lee mucho mejor que enfrentarlos a los extremos. */
.v12-card__head--stack {
    flex-direction: column;
    align-items: flex-start;
    gap: .25rem;
}
.v12-card__head--stack .v12-card__title { font-size: 1.125rem; font-weight: 700; letter-spacing: -.015em; }
.v12-card__head--stack .v12-card__sub { font-size: .875rem; }
.v12-card__title {
    font-size: .9375rem;
    font-weight: 600;
    margin: 0;
    display: flex;
    align-items: center;
    gap: .5rem;
}
.v12-card__title .mdi { color: var(--v12-gray-400); font-size: 1.1rem; }
.v12-card__body { padding: 1.25rem; }
.v12-card__foot {
    padding: .875rem 1.25rem;
    border-top: 1px solid var(--v12-gray-200);
    background: var(--v12-gray-50);
    border-radius: 0 0 var(--v12-r-md) var(--v12-r-md);
}

/* ============================================================================
   Métricas
   ========================================================================== */

.v12-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 1rem;
}

.v12-stat {
    position: relative;
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    padding: 1.125rem 1.25rem;
    box-shadow: var(--v12-shadow-sm);
    overflow: hidden;
    transition: transform var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-stat::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    background: var(--v12-gray-300);
}
.v12-stat--accent::before { background: var(--v12-orange-500); }
.v12-stat--danger::before { background: var(--sev-critical); }
.v12-stat--ok::before     { background: var(--v12-ok); }
.v12-stat:hover { transform: translateY(-1px); box-shadow: var(--v12-shadow-md); }

.v12-stat__label {
    /* Los <span> quedarían en la misma línea que el valor. */
    display: block;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--v12-gray-500);
    margin-bottom: .375rem;
}
.v12-stat__value {
    display: block;
    font-size: 1.875rem;
    font-weight: 650;
    line-height: 1.1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
.v12-stat__meta {
    display: flex;
    align-items: center;
    gap: .3rem;
    font-size: .8125rem;
    color: var(--v12-gray-500);
    margin-top: .375rem;
}
.v12-trend { display: inline-flex; align-items: center; gap: .15rem; font-weight: 600; }
.v12-trend--up   { color: var(--v12-danger); }   /* más vulnerabilidades = malo */
.v12-trend--down { color: var(--v12-ok); }

/* ============================================================================
   Severidad
   ========================================================================== */

.v12-sev {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1;
    padding: .3125rem .5625rem .3125rem .5rem;
    border-radius: var(--v12-r-pill);
    white-space: nowrap;
    border: 1px solid transparent;
}
.v12-sev::before {
    content: "";
    width: 7px; height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}
.v12-sev--critical { color: var(--sev-critical); background: #FBEBEA; border-color: #F3D3D1; }
.v12-sev--high     { color: #A85C00;            background: #FDF1E0; border-color: #F5DFC0; }
.v12-sev--medium   { color: #8C7016;            background: #FBF5E0; border-color: #EFE3BC; }
.v12-sev--low      { color: #2C5C86;            background: #EAF2F9; border-color: #CFE0EE; }
.v12-sev--info     { color: var(--sev-info);    background: var(--v12-gray-100); border-color: var(--v12-gray-200); }

/* Barra de distribución por severidad */
.v12-sevbar {
    display: flex;
    height: 8px;
    border-radius: var(--v12-r-pill);
    overflow: hidden;
    background: var(--v12-gray-100);
}
.v12-sevbar span { display: block; height: 100%; transition: width var(--v12-slow) var(--v12-ease); }

/* Los colores de segmento van por clase y no anidados bajo un contenedor
   concreto: los usan tanto la barra del informe como la del panel de inicio, y
   tenerlos atados a .v12-sevbar hacía que la segunda se dibujara sin fondo. */
.s-critical { background: var(--sev-critical); }
.s-high     { background: var(--sev-high); }
.s-medium   { background: var(--sev-medium); }
.s-low      { background: var(--sev-low); }
.s-info     { background: var(--sev-info); }

/* ============================================================================
   Puntuación de prioridad
   ========================================================================== */

.v12-score {
    display: inline-flex;
    align-items: baseline;
    gap: .125rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    letter-spacing: -.02em;
}
.v12-score__n { font-size: 1.0625rem; }
.v12-score__d { font-size: .6875rem; color: var(--v12-gray-400); font-weight: 500; }
.v12-score--critical .v12-score__n { color: var(--sev-critical); }
.v12-score--high     .v12-score__n { color: #A85C00; }
.v12-score--medium   .v12-score__n { color: #8C7016; }
.v12-score--low      .v12-score__n { color: #2C5C86; }

/* ============================================================================
   Botones
   ========================================================================== */

.v12-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4375rem;
    font-size: .875rem;
    font-weight: 600;
    line-height: 1;
    padding: .5625rem .875rem;
    border-radius: var(--v12-r-sm);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    transition: background var(--v12-fast) var(--v12-ease),
                border-color var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease),
                transform var(--v12-fast) var(--v12-ease);
}
.v12-btn:focus-visible { outline: none; box-shadow: var(--v12-ring); }
.v12-btn:active { transform: translateY(.5px); }
.v12-btn .mdi { font-size: 1.05rem; }

.v12-btn--primary {
    background: var(--v12-fill-accent);
    color: var(--v12-on-accent);
    box-shadow: 0 1px 2px rgba(145,64,20,.28);
}
.v12-btn--primary:hover {
    background: var(--v12-fill-accent-hover);
    color: var(--v12-on-accent);
    text-decoration: none;
}
.v12-btn--primary:active { background: var(--v12-fill-accent-active); }

.v12-btn--secondary {
    background: var(--v12-white);
    color: var(--v12-gray-700);
    border-color: var(--v12-gray-300);
}
.v12-btn--secondary:hover {
    background: var(--v12-gray-50);
    border-color: var(--v12-gray-400);
    color: var(--v12-gray-900);
    text-decoration: none;
}

.v12-btn--ghost { background: transparent; color: var(--v12-gray-600); }
.v12-btn--ghost:hover { background: var(--v12-gray-100); color: var(--v12-gray-900); text-decoration: none; }

.v12-btn--danger { background: var(--v12-danger); color: #fff; }
.v12-btn--danger:hover { background: #96201A; color: #fff; }

.v12-btn--lg { font-size: .9375rem; padding: .75rem 1.125rem; }
.v12-btn--sm { font-size: .8125rem; padding: .4375rem .6875rem; }
.v12-btn[disabled], .v12-btn.disabled { opacity: .5; pointer-events: none; }

/* ============================================================================
   Tablas
   ========================================================================== */

/* `overflow-x: auto` y no `hidden`: el tema deja `#wrapper`, `.content-page` y
   `body` con `overflow: hidden`, así que un contenedor de tabla que también
   recorta deja las últimas columnas inalcanzables en móvil —sin barra, sin
   paneo táctil y sin scroll de página—. Es lo que hacía el `.table-responsive`
   de Bootstrap al que sustituye. `overflow-y` se deja visible para no romper
   la cabecera `position: sticky` de más abajo. */
.v12-table-wrap {
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    overflow-x: auto;
    overflow-y: visible;
    box-shadow: var(--v12-shadow-sm);
}
.v12-table { width: 100%; margin: 0; border-collapse: separate; border-spacing: 0; }
.v12-table thead th {
    position: sticky; top: 0; z-index: 2;
    background: var(--v12-gray-50);
    border-bottom: 1px solid var(--v12-gray-200);
    color: var(--v12-gray-600);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: .6875rem .875rem;
    white-space: nowrap;
}
.v12-table tbody td {
    padding: .8125rem .875rem;
    border-bottom: 1px solid var(--v12-gray-100);
    font-size: .875rem;
    vertical-align: middle;
}
.v12-table tbody tr { transition: background var(--v12-fast) var(--v12-ease); }
.v12-table tbody tr:hover { background: var(--v12-orange-50); }
.v12-table tbody tr:last-child td { border-bottom: none; }
.v12-table .v12-td-strong { font-weight: 600; color: var(--v12-gray-900); }
.v12-table .v12-td-muted { color: var(--v12-gray-500); font-size: .8125rem; }

/* ============================================================================
   Estados y etiquetas
   ========================================================================== */

.v12-dot {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    flex: none;
    position: relative;
}
.v12-dot--ok     { background: var(--v12-ok); }
.v12-dot--warn   { background: var(--v12-warn); }
.v12-dot--error  { background: var(--v12-danger); }
.v12-dot--idle   { background: var(--v12-gray-400); }
.v12-dot--live   { background: var(--v12-ok); }
.v12-dot--live::after {
    content: "";
    position: absolute; inset: -4px;
    border-radius: 50%;
    border: 2px solid var(--v12-ok);
    opacity: .55;
    animation: v12-pulse 1.8s var(--v12-ease) infinite;
}
@keyframes v12-pulse {
    0%   { transform: scale(.7); opacity: .6; }
    70%  { transform: scale(1.35); opacity: 0; }
    100% { transform: scale(1.35); opacity: 0; }
}

.v12-tag {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    font-size: .75rem;
    font-weight: 600;
    padding: .3125rem .5625rem;
    border-radius: var(--v12-r-sm);
    background: var(--v12-gray-100);
    color: var(--v12-gray-700);
    border: 1px solid var(--v12-gray-200);
}
.v12-tag--ok     { background: var(--v12-ok-bg);     color: var(--v12-ok);     border-color: #C9E7D6; }
.v12-tag--warn   { background: var(--v12-warn-bg);   color: var(--v12-warn);   border-color: #F0E0BE; }
.v12-tag--danger { background: var(--v12-danger-bg); color: var(--v12-danger); border-color: #F3D3D1; }
.v12-tag--info   { background: var(--v12-info-bg);   color: var(--v12-info);   border-color: #CFE0EE; }
.v12-tag--accent { background: var(--v12-orange-50); color: var(--v12-orange-700); border-color: var(--v12-orange-100); }

/* ============================================================================
   Formularios
   ========================================================================== */

.v12-field { margin-bottom: 1.125rem; }
.v12-label {
    display: block;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--v12-gray-700);
    margin-bottom: .375rem;
}
.v12-label__hint { font-weight: 400; color: var(--v12-gray-400); margin-left: .25rem; }

.v12-input,
.v12-select,
.v12-textarea {
    width: 100%;
    font-size: .875rem;
    color: var(--v12-gray-900);
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-300);
    border-radius: var(--v12-r-sm);
    padding: .5625rem .75rem;
    transition: border-color var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-input::placeholder { color: var(--v12-gray-400); }
.v12-input:focus,
.v12-select:focus,
.v12-textarea:focus {
    outline: none;
    border-color: var(--v12-orange-400);
    box-shadow: var(--v12-ring);
}
.v12-input--mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8125rem; }
.v12-help { font-size: .78125rem; color: var(--v12-gray-500); margin-top: .375rem; }
.v12-error { font-size: .78125rem; color: var(--v12-danger); margin-top: .375rem; display: flex; gap: .25rem; align-items: center; }

/* ============================================================================
   Asistente por pasos
   ========================================================================== */

.v12-steps {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-bottom: 1.75rem;
    /* El marcador va como <ol> por semántica, pero Bootstrap le mete sangría y
       viñetas que descolocan la fila entera. */
    list-style: none;
    padding-left: 0;
}
.v12-step { display: flex; align-items: center; gap: .5rem; flex: none; }
.v12-step__bullet {
    width: 26px; height: 26px;
    border-radius: 50%;
    display: grid; place-items: center;
    font-size: .75rem; font-weight: 700;
    background: var(--v12-gray-100);
    color: var(--v12-gray-500);
    border: 1px solid var(--v12-gray-200);
    transition: all var(--v12-slow) var(--v12-ease);
}
.v12-step__label { font-size: .8125rem; font-weight: 600; color: var(--v12-gray-500); }
.v12-step__line { flex: 1 1 auto; height: 2px; background: var(--v12-gray-200); border-radius: 2px; min-width: 18px; }

.v12-step--done .v12-step__bullet {
    background: var(--v12-ok); border-color: var(--v12-ok); color: #fff;
}
.v12-step--done .v12-step__label { color: var(--v12-gray-700); }
.v12-step--current .v12-step__bullet {
    background: var(--v12-orange-500); border-color: var(--v12-orange-500); color: #fff;
    box-shadow: var(--v12-ring);
}
.v12-step--current .v12-step__label { color: var(--v12-gray-900); }

/* ============================================================================
   Tarjetas de escáner (el momento de elegir origen)
   ========================================================================== */

.v12-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(238px, 1fr));
    gap: .875rem;
}
.v12-source {
    position: relative;
    display: flex;
    align-items: center;
    gap: .8125rem;
    padding: 1rem;
    background: var(--v12-white);
    border: 1.5px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    cursor: pointer;
    text-align: left;
    transition: all var(--v12-fast) var(--v12-ease);
}
.v12-source:hover {
    border-color: var(--v12-orange-400);
    box-shadow: var(--v12-shadow-md);
    transform: translateY(-2px);
}
.v12-source--selected {
    border-color: var(--v12-orange-500);
    background: var(--v12-orange-50);
    box-shadow: var(--v12-ring);
}
.v12-source--selected::after {
    content: "\F012C";                 /* mdi-check */
    font-family: "Material Design Icons";
    position: absolute; top: .5rem; right: .625rem;
    color: var(--v12-orange-600);
    font-size: 1rem;
}
.v12-source > span:last-child { min-width: 0; padding-right: .75rem; }
.v12-source__logo {
    width: 40px; height: 40px;
    border-radius: var(--v12-r-sm);
    display: grid; place-items: center;
    background: var(--v12-gray-50);
    border: 1px solid var(--v12-gray-200);
    font-size: 1.25rem;
    color: var(--v12-gray-600);
    flex: none;
}
.v12-source__name { display: block; font-weight: 650; font-size: .875rem; line-height: 1.2; }
.v12-source__meta { display: block; font-size: .75rem; color: var(--v12-gray-500); margin-top: .1875rem; }
.v12-source[disabled] { opacity: .55; cursor: not-allowed; }
.v12-source[disabled]:hover { transform: none; border-color: var(--v12-gray-200); box-shadow: none; }

/* ============================================================================
   Verificación en vivo (el "probar conexión")
   ========================================================================== */

.v12-check { display: flex; flex-direction: column; gap: .625rem; }
.v12-check__row {
    display: flex; align-items: center; gap: .625rem;
    font-size: .875rem;
    color: var(--v12-gray-500);
    transition: color var(--v12-fast) var(--v12-ease);
}
.v12-check__icon {
    width: 20px; height: 20px;
    border-radius: 50%;
    display: grid; place-items: center;
    font-size: .8125rem;
    background: var(--v12-gray-100);
    color: var(--v12-gray-400);
    border: 1px solid var(--v12-gray-200);
    flex: none;
    transition: all var(--v12-slow) var(--v12-ease);
}
.v12-check__row--run .v12-check__icon {
    background: var(--v12-orange-50); border-color: var(--v12-orange-100); color: var(--v12-orange-600);
}
.v12-check__row--run { color: var(--v12-gray-800); }
.v12-check__row--ok .v12-check__icon {
    background: var(--v12-ok-bg); border-color: #C9E7D6; color: var(--v12-ok);
}
.v12-check__row--ok { color: var(--v12-gray-800); }
.v12-check__row--fail .v12-check__icon {
    background: var(--v12-danger-bg); border-color: #F3D3D1; color: var(--v12-danger);
}
.v12-check__row--fail { color: var(--v12-danger); }
.v12-spin { animation: v12-rotate .9s linear infinite; display: inline-block; }
@keyframes v12-rotate { to { transform: rotate(360deg); } }

/* ============================================================================
   Progreso de importación
   ========================================================================== */

.v12-progress {
    height: 8px;
    background: var(--v12-gray-100);
    border-radius: var(--v12-r-pill);
    overflow: hidden;
}
.v12-progress__bar {
    height: 100%;
    background: linear-gradient(90deg, var(--v12-orange-500), var(--v12-orange-400));
    border-radius: var(--v12-r-pill);
    transition: width var(--v12-slow) var(--v12-ease);
    position: relative;
}
.v12-progress__bar--live::after {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent);
    animation: v12-sheen 1.4s linear infinite;
}
@keyframes v12-sheen { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.v12-pipeline { display: flex; flex-direction: column; gap: .5rem; }
.v12-pipeline__row {
    display: flex; align-items: center; justify-content: space-between;
    font-size: .875rem; padding: .375rem 0;
    color: var(--v12-gray-500);
}
.v12-pipeline__row--active { color: var(--v12-gray-900); font-weight: 600; }
.v12-pipeline__n { font-variant-numeric: tabular-nums; font-weight: 650; }

/* ============================================================================
   Estados vacíos
   ========================================================================== */

.v12-empty { text-align: center; padding: 3rem 1.5rem; }
.v12-empty__icon {
    width: 56px; height: 56px;
    margin: 0 auto 1rem;
    border-radius: var(--v12-r-lg);
    display: grid; place-items: center;
    background: var(--v12-orange-50);
    color: var(--v12-orange-500);
    font-size: 1.625rem;
}
.v12-empty__title { font-size: 1rem; font-weight: 650; margin-bottom: .375rem; }
.v12-empty__text { font-size: .875rem; color: var(--v12-gray-500); max-width: 420px; margin: 0 auto 1.25rem; }

/* ============================================================================
   Carga (esqueleto)
   ========================================================================== */

.v12-skel {
    background: linear-gradient(90deg, var(--v12-gray-100) 25%, var(--v12-gray-200) 37%, var(--v12-gray-100) 63%);
    background-size: 400% 100%;
    animation: v12-shimmer 1.3s ease infinite;
    border-radius: var(--v12-r-sm);
    height: 12px;
}
@keyframes v12-shimmer { from { background-position: 100% 50%; } to { background-position: 0 50%; } }

/* ============================================================================
   Avisos
   ========================================================================== */

.v12-callout {
    display: flex;
    gap: .75rem;
    padding: .875rem 1rem;
    border-radius: var(--v12-r-sm);
    border: 1px solid var(--v12-gray-200);
    background: var(--v12-gray-50);
    font-size: .875rem;
}
.v12-callout__icon { flex: none; font-size: 1.125rem; line-height: 1.35; color: var(--v12-gray-500); }
.v12-callout--info   { background: var(--v12-info-bg);   border-color: #CFE0EE; }
.v12-callout--info .v12-callout__icon { color: var(--v12-info); }
.v12-callout--warn   { background: var(--v12-warn-bg);   border-color: #F0E0BE; }
.v12-callout--warn .v12-callout__icon { color: var(--v12-warn); }
.v12-callout--danger { background: var(--v12-danger-bg); border-color: #F3D3D1; }
.v12-callout--danger .v12-callout__icon { color: var(--v12-danger); }
.v12-callout--accent { background: var(--v12-orange-50); border-color: var(--v12-orange-100); }
.v12-callout--accent .v12-callout__icon { color: var(--v12-orange-600); }

/* ============================================================================
   Utilidades
   ========================================================================== */

.v12-stack   { display: flex; flex-direction: column; }
.v12-row     { display: flex; align-items: center; }
.v12-gap-xs  { gap: .25rem; }  .v12-gap-sm { gap: .5rem; }
.v12-gap     { gap: .75rem; }  .v12-gap-md { gap: 1rem; }  .v12-gap-lg { gap: 1.5rem; }
.v12-grow    { flex: 1 1 auto; }
.v12-muted   { color: var(--v12-gray-500); }
.v12-mono    { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8125rem; }
.v12-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; animation-iteration-count: 1 !important;
        transition-duration: .01ms !important; }
}

/* ============================================================================
   Cabecera de página
   ========================================================================== */

.v12-page-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
    margin-bottom: 1.5rem;
}
.v12-page-title {
    font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em;
    color: var(--v12-gray-900); margin: 0;
}
.v12-page-sub { font-size: .9375rem; color: var(--v12-gray-500); margin: .3125rem 0 0; }

/* ============================================================================
   Formularios del asistente
   ========================================================================== */

.v12-form { display: grid; gap: .25rem; }
@media (min-width: 768px) {
    /* Dos columnas sólo cuando hay sitio: en móvil un campo por fila siempre. */
    .v12-form { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1.25rem; }
    .v12-form .v12-field--wide { grid-column: 1 / -1; }
}

.v12-check-inline {
    display: inline-flex; align-items: center; gap: .5rem;
    font-size: .875rem; color: var(--v12-gray-700); cursor: pointer;
    user-select: none;
}
.v12-check-inline input { accent-color: var(--v12-orange-500); width: 16px; height: 16px; }

/* ============================================================================
   Selección de alcance
   ========================================================================== */

.v12-scopes { display: flex; flex-direction: column; gap: .5rem; margin-bottom: 1.25rem; }
.v12-scope {
    display: flex; align-items: center; gap: .75rem;
    padding: .75rem .875rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-white);
    cursor: pointer;
    transition: border-color var(--v12-fast) var(--v12-ease),
                background var(--v12-fast) var(--v12-ease);
}
.v12-scope:hover { border-color: var(--v12-orange-400); background: var(--v12-orange-50); }
.v12-scope input { accent-color: var(--v12-orange-500); width: 16px; height: 16px; flex: none; }
.v12-scope__body { min-width: 0; }
.v12-scope__name {
    display: block; font-weight: 650; font-size: .875rem;
    color: var(--v12-gray-900); line-height: 1.2;
}
.v12-scope__meta {
    display: block; font-size: .75rem; color: var(--v12-gray-500); margin-top: .1875rem;
}
.v12-scope--on { border-color: var(--v12-orange-500); background: var(--v12-orange-50); }

.v12-sevpick { display: flex; flex-wrap: wrap; gap: .5rem; }
.v12-sevpick__item { display: inline-flex; align-items: center; gap: .375rem; cursor: pointer; margin: 0; }
.v12-sevpick__item input { accent-color: var(--v12-orange-500); width: 15px; height: 15px; }
/* Sin marcar la severidad se apaga, pero el texto sigue ahí: nunca dependemos
   sólo del color para decir qué está activo. */
.v12-sevpick__item input:not(:checked) + .v12-sev { opacity: .4; }

/* ============================================================================
   Previsualización
   ========================================================================== */

.v12-preview__head { margin: 1.5rem 0 .875rem; }
.v12-preview__title { font-size: 1rem; font-weight: 650; color: var(--v12-gray-900); margin: 0; }
.v12-preview__sub { font-size: .875rem; color: var(--v12-gray-500); margin: .25rem 0 0; }

/* ============================================================================
   Pantalla final
   ========================================================================== */

.v12-done { text-align: center; padding: 1.5rem .5rem .5rem; }
.v12-done__icon {
    width: 72px; height: 72px; margin: 0 auto 1.125rem;
    border-radius: 50%; display: grid; place-items: center;
    font-size: 2.25rem;
    background: var(--v12-orange-50); color: var(--v12-orange-500);
    border: 1px solid var(--v12-orange-100);
}
.v12-done__icon--ok { background: var(--v12-ok-bg); color: var(--v12-ok); border-color: #C9E7D6; }
.v12-done__icon--fail { background: var(--v12-danger-bg); color: var(--v12-danger); border-color: #F3D3D1; }
.v12-done__title {
    font-size: 1.375rem; font-weight: 700; letter-spacing: -.02em;
    color: var(--v12-gray-900); margin: 0;
}
.v12-done__sub {
    font-size: .9375rem; color: var(--v12-gray-500);
    margin: .5rem auto 1.5rem; max-width: 46ch;
}
.v12-done__actions {
    display: flex; gap: .625rem; justify-content: center; flex-wrap: wrap;
    margin-top: 1.5rem;
}

.v12-skel--row { height: 56px; border-radius: var(--v12-r-md); margin-bottom: .5rem; }

/* ============================================================================
   Tarjetas de conector (listado)
   ========================================================================== */

.v12-conn-grid {
    display: grid; gap: 1rem;
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
}
.v12-conn { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.v12-conn--busy { opacity: .75; }

.v12-conn__head {
    display: flex; align-items: center; gap: .75rem;
    padding: 1rem 1.125rem;
    border-bottom: 1px solid var(--v12-gray-100);
}
.v12-conn__icon {
    font-size: 1.5rem; color: var(--v12-orange-500);
    width: 40px; height: 40px; flex: none;
    display: grid; place-items: center;
    background: var(--v12-orange-50); border-radius: var(--v12-r-md);
}
.v12-conn__id { min-width: 0; flex: 1; }
.v12-conn__name {
    display: block; font-weight: 650; font-size: .9375rem;
    color: var(--v12-gray-900); line-height: 1.25;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v12-conn__vendor { display: block; font-size: .75rem; color: var(--v12-gray-500); margin-top: .125rem; }

.v12-conn__body { padding: 1rem 1.125rem; flex: 1; }
.v12-conn__last { font-size: .8125rem; color: var(--v12-gray-700); margin: 0 0 .875rem; line-height: 1.5; }
.v12-conn__last--muted { color: var(--v12-gray-400); font-style: italic; }

/* La ecuación del recuento en la tarjeta del conector. Va plegada porque no es lo
   primero que se mira, y abierta es lo que decide una evaluación: por qué el número de
   V12 no es el de la consola del escáner. */
.v12-conn__recuento { font-size: .8125rem; margin: 0 0 .875rem; }
.v12-conn__recuento > summary {
    cursor: pointer;
    color: var(--v12-gray-700);
    display: flex;
    align-items: center;
    gap: .5rem;
}
.v12-conn__recuento > summary:hover { color: var(--v12-gray-900); }
.v12-conn__recuento table { margin-top: .5rem; }
.v12-table--tight th, .v12-table--tight td { padding: .25rem .5rem; font-size: .78125rem; }
/* El alta de un agente: la tarjeta que explica qué es, con qué garantías y los tres pasos. */
.v12-agente__garantias li { padding: .2rem 0; font-size: .85rem; color: var(--v12-gray-700); }
.v12-agente__garantias .mdi { color: var(--v12-ok); margin-right: .35rem; }
.v12-agente__pasos { border-left: 2px solid var(--v12-gray-200); padding-left: 1rem; }
.v12-agente__paso { display: flex; gap: .75rem; padding: .45rem 0; }
.v12-agente__n {
    flex: 0 0 auto; width: 1.6rem; height: 1.6rem; border-radius: 50%;
    background: var(--v12-ok-bg); color: var(--v12-ok); font-weight: 700;
    display: flex; align-items: center; justify-content: center; font-size: .85rem;
}
.v12-agente__resultado { margin-top: 1rem; border-top: 1px solid var(--v12-gray-200); padding-top: 1rem; }
.v12-agente__codigo { font-size: 1.15rem; letter-spacing: .04em; }
.v12-agente__instrucciones { background: #0F201D; color: #D9E6E2; border-radius: 4px; padding: .75rem 1rem; font-size: .8rem; overflow-x: auto; }

/* Procedencia y sello de una evidencia. Va en letra pequeña bajo el nombre del fichero
   porque no compite con él: se busca cuando alguien pregunta, y entonces tiene que estar. */
.v12-file__meta { display: block; font-size: .6875rem; color: var(--v12-gray-500); margin-top: .125rem; }
.v12-sello { color: var(--v12-ok); white-space: nowrap; }

/* La historia de un hallazgo: qué le pasó, cuándo y quién lo hizo. Es lo que se enseña
   cuando un auditor pregunta por un hallazgo concreto, así que se lee de arriba abajo
   como una línea de tiempo y no como una tabla. */
.v12-historia { list-style: none; margin: 0; padding: 0; }
.v12-historia__paso {
    padding: .5rem 0 .5rem .75rem;
    border-left: 2px solid var(--v12-gray-200);
    margin-left: .25rem;
}
.v12-historia__paso + .v12-historia__paso { margin-top: .125rem; }
.v12-historia__estado { font-size: .8125rem; display: flex; align-items: center; gap: .375rem; flex-wrap: wrap; }
.v12-historia__meta { font-size: .75rem; color: var(--v12-gray-500); margin-top: .125rem; }
.v12-historia__comentario {
    font-size: .78125rem;
    color: var(--v12-gray-700);
    margin-top: .25rem;
    padding-left: .5rem;
    border-left: 2px solid var(--v12-gray-100);
}

/* Dueño y compromiso en la ruta de parcheo. El compromiso es una fecha que una persona
   prometió, distinta del plazo que calcula V12: se pintan en columnas separadas porque
   enseñar la diferencia es la mitad del valor. */
/* Un recuento que es un SUELO y no un total se pinta apagado: la diferencia entre «hay
   4.000» y «hay al menos 4.000» decide si el usuario acota el alcance o no. */
.v12-stat--muted .v12-stat__value { color: var(--v12-gray-500); }
.v12-stat--muted .v12-stat__label { font-style: italic; }

.v12-route__owner { font-size: .8125rem; }
.v12-route__owner .v12-muted { display: block; font-size: .75rem; }
.v12-route__commit { font-size: .8125rem; white-space: nowrap; }
.v12-input--date { padding: .25rem .375rem; font-size: .78125rem; width: auto; }
.v12-route__commit-meta { display: block; margin-top: .25rem; font-size: .75rem; }

.v12-table--tight tfoot th, .v12-table--tight tfoot td {
    border-top: 1px solid var(--v12-gray-200);
    font-weight: 600;
}

.v12-conn__meta { display: flex; gap: 1.5rem; margin: 0; flex-wrap: wrap; }
.v12-conn__meta dt {
    font-size: .6875rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: .04em; color: var(--v12-gray-400); margin: 0 0 .1875rem;
}
.v12-conn__meta dd { font-size: .8125rem; color: var(--v12-gray-800); margin: 0; font-weight: 550; }

.v12-conn__foot {
    display: flex; gap: .375rem; flex-wrap: wrap;
    padding: .75rem 1.125rem;
    border-top: 1px solid var(--v12-gray-100);
    background: var(--v12-gray-50);
}

/* El panel de «Qué importar» dentro de la tarjeta: reutiliza .v12-scope del
   asistente; aquí sólo se le da sitio y pie. */
.v12-conn__scope {
    display: flex; flex-direction: column; gap: .5rem;
    padding: .75rem 1.125rem;
    border-top: 1px solid var(--v12-gray-100);
}
.v12-conn__scope-label {
    font-size: .6875rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: .04em; color: var(--v12-gray-400); margin: 0;
}
.v12-conn__scope-foot { display: flex; justify-content: flex-end; margin-top: .25rem; }

.v12-conn__status {
    display: flex; align-items: center; gap: .5rem;
    padding: .75rem 1.125rem;
    font-size: .8125rem; line-height: 1.4;
    border-top: 1px solid var(--v12-gray-100);
}
.v12-conn__status--run { background: var(--v12-orange-50); color: var(--v12-orange-700); }
.v12-conn__status--ok { background: var(--v12-ok-bg); color: var(--v12-ok); }
.v12-conn__status--fail { background: var(--v12-danger-bg); color: var(--v12-danger); }
.v12-conn__status em { font-size: 1rem; flex: none; }

.v12-btn--danger-ghost { color: var(--v12-danger); margin-left: auto; }
.v12-btn--danger-ghost:hover { background: var(--v12-danger-bg); }

.v12-callout--tight { margin-bottom: .875rem; padding: .625rem .75rem; font-size: .8125rem; }

/* La plantilla de administración impone una serif a los encabezados. */
.v12-page-title,
.v12-card__title,
.v12-done__title,
.v12-preview__title,
.v12-empty__title { font-family: var(--v12-font); }

/* ============================================================================
   Paneles del asistente
   ========================================================================== */

.v12-pane { margin-bottom: 1.25rem; }
/* El contenido del paso son hijos directos de la tarjeta; la cabecera y el pie
   traen su propio espaciado, así que se excluyen. */
.v12-pane > *:not(.v12-card__head):not(.v12-card__foot) {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
}
.v12-pane > *:not(.v12-card__head):not(.v12-card__foot):first-of-type { padding-top: 1.25rem; }
.v12-pane > .v12-card__head + * { padding-top: 1.25rem; }
.v12-pane > .v12-card__foot {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    margin-top: 1.25rem;
}
/* La acción principal a la derecha: es donde el ojo termina de leer la fila. */
.v12-pane > .v12-card__foot > .v12-btn--primary { margin-left: auto; }
.v12-pane > .v12-card__foot > .v12-btn--primary:only-child { margin-left: 0; }

.v12-btn[disabled] { opacity: .45; cursor: not-allowed; box-shadow: none; }
.v12-btn[disabled]:hover { transform: none; }

/* ============================================================================
   Correcciones al tema base
   ============================================================================
   El tema declara `font-family: "Cerebri Sans,sans-serif"` — la lista entera
   dentro de unas comillas —, así que el navegador busca una familia llamada
   literalmente «Cerebri Sans,sans-serif», no la encuentra, y cae a la serif por
   defecto. Afecta a TODOS los encabezados de la aplicación, no sólo a los de
   estas pantallas. Se corrige aquí porque tocar el CSS del tema significaría
   perder el arreglo en la próxima actualización. */

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--v12-font);
}

/* Las tarjetas de escáner se alinean arriba: los nombres ocupan una o dos
   líneas según el fabricante y centrarlos deja la fila desigual. */
.v12-source { align-items: flex-start; }
.v12-source__logo { font-size: 1.375rem; color: var(--v12-orange-500); background: var(--v12-orange-50); border-color: var(--v12-orange-100); }
.v12-source--selected .v12-source__logo { background: var(--v12-white); border-color: var(--v12-orange-200, var(--v12-orange-100)); }

/* ============================================================================
   Informe ejecutivo
   ========================================================================== */

/* Los avisos se escriben con el icono como hijo directo; se le da el mismo
   tratamiento que a .v12-callout__icon para no repetir clase en cada plantilla. */
.v12-callout > em.mdi {
    flex: none; font-size: 1.125rem; line-height: 1.35; color: var(--v12-gray-500);
}
.v12-callout p:last-child { margin-bottom: 0; }
.v12-callout--ok { background: var(--v12-ok-bg); border-color: #C9E7D6; }
.v12-callout--ok > em.mdi { color: var(--v12-ok); }
.v12-callout--danger > em.mdi { color: var(--v12-danger); }
.v12-callout--warn > em.mdi { color: var(--v12-warn); }
.v12-callout--info > em.mdi { color: var(--v12-info); }

.v12-input--sm { padding: .375rem .5rem; font-size: .8125rem; width: auto; }
.v12-stats--4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

.v12-head-actions { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.v12-range { display: flex; align-items: center; gap: .375rem; margin: 0; }
.v12-range__label { font-size: .8125rem; color: var(--v12-gray-500); margin: 0; }

.v12-report {
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    box-shadow: var(--v12-shadow-sm);
    padding: 2rem 2.25rem;
    max-width: 1000px;
}
.v12-report__head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem;
    padding-bottom: 1.25rem;
    border-bottom: 2px solid var(--v12-orange-500);
    margin-bottom: 1.75rem;
}
.v12-report__eyebrow {
    font-size: .6875rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .08em; color: var(--v12-orange-600); margin: 0 0 .25rem;
}
.v12-report__title {
    font-family: var(--v12-font);
    font-size: 1.625rem; font-weight: 700; letter-spacing: -.02em;
    color: var(--v12-gray-900); margin: 0;
}
.v12-report__meta { font-size: .8125rem; color: var(--v12-gray-500); margin: .375rem 0 0; }
.v12-report__logo { max-height: 44px; max-width: 180px; object-fit: contain; flex: none; }

.v12-report__section { margin-bottom: 2.25rem; }
.v12-report__h3 {
    font-family: var(--v12-font);
    font-size: 1.0625rem; font-weight: 700; letter-spacing: -.01em;
    color: var(--v12-gray-900); margin: 0 0 .375rem;
}
.v12-report__lead {
    font-size: .875rem; color: var(--v12-gray-500);
    margin: 0 0 1rem; max-width: 68ch;
}
.v12-report__empty { font-size: .875rem; color: var(--v12-gray-400); font-style: italic; }
.v12-report__section .v12-stats { margin-bottom: 1.25rem; }
.v12-report__section .v12-sevbar { margin-bottom: 1.25rem; }
.v12-report__foot {
    border-top: 1px solid var(--v12-gray-200);
    padding-top: .875rem; margin-top: 2rem;
    font-size: .75rem; color: var(--v12-gray-400);
}

/* Barras de evolución: entradas frente a cierres, mes a mes. */
.v12-trend {
    display: flex; align-items: flex-end; gap: .5rem;
    height: 180px; padding: 0 .25rem;
    border-bottom: 1px solid var(--v12-gray-200);
}
.v12-trend__col { flex: 1; display: flex; flex-direction: column; height: 100%; min-width: 0; }
.v12-trend__bars { flex: 1; display: flex; align-items: flex-end; gap: 2px; }
.v12-trend__bar { flex: 1; border-radius: 2px 2px 0 0; min-height: 2px; }
.v12-trend__bar--in  { background: var(--sev-high); }
.v12-trend__bar--out { background: var(--v12-ok); }
.v12-trend__label {
    font-size: .625rem; color: var(--v12-gray-500);
    text-align: center; padding-top: .375rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Volumen de un alcance y total de la selección, en el asistente de conectores.
   El chip va a la derecha del nombre para que los números queden alineados en
   columna y se puedan comparar de un vistazo, que es de lo que se trata. */
.v12-scope__vol {
    margin-left: auto;
    padding-left: .75rem;
    font-size: .75rem;
    font-variant-numeric: tabular-nums;
    color: var(--v12-gray-600);
    white-space: nowrap;
}
.v12-scope-total {
    margin: .625rem 0 0 0;
    font-size: .8125rem;
    font-variant-numeric: tabular-nums;
    color: var(--v12-gray-700);
}

.v12-legend { display: flex; gap: 1rem; margin-top: .75rem; }
.v12-legend__item { display: inline-flex; align-items: center; gap: .375rem; font-size: .75rem; color: var(--v12-gray-600); }
.v12-legend__key { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.v12-legend__key--in  { background: var(--sev-high); }
.v12-legend__key--out { background: var(--v12-ok); }

/* ============================================================================
   Impresión
   ============================================================================
   El informe de verdad se DESCARGA: lo compone el servidor con su portada, su
   numeración y sus gráficos vectoriales. Estas reglas son para quien de todos
   modos pulsa imprimir —que pasa— y sirven para que salga la página y no la
   interfaz alrededor. No son el camino recomendado ni el que usa el envío
   agendado. */

@media print {
    /* Todo lo que es interfaz y no informe desaparece. */
    .left-side-menu,
    .navbar-custom,
    .topbar,
    .footer,
    .v12-noprint { display: none !important; }

    /* #wrapper por IDENTIFICADOR: el layout emite <div id="wrapper"> y la
       versión con punto no casaba con nada, así que el `overflow:hidden` del
       tema heredado sobrevivía a la impresión y recortaba el informe. */
    .content-page, .content, .container-fluid, body, #wrapper {
        margin: 0 !important;
        padding: 0 !important;
        width: 100% !important;
        background: #fff !important;
    }

    .v12-report {
        border: 0;
        box-shadow: none;
        padding: 0;
        max-width: none;
    }

    /* Una sección no debe partirse a la mitad si cabe entera en la página. */
    .v12-report__section { break-inside: avoid; page-break-inside: avoid; }
    /* Sin saltos forzados: con `break-inside: avoid` cada bloque se mueve
       entero a la página siguiente sólo cuando no cabe, y el informe no deja
       hojas medio vacías cuando hay pocos datos. */
    .v12-report__head { break-after: avoid; page-break-after: avoid; }
    .v12-report__h3 { break-after: avoid; page-break-after: avoid; }
    .v12-table-wrap { overflow: visible !important; }
    .v12-table thead { display: table-header-group; }
    .v12-table tr { break-inside: avoid; page-break-inside: avoid; }

    /* Sin esto el navegador descarta los fondos y las barras de severidad
       salen en blanco, que es justo la información que hay que ver. */
    .v12-stat, .v12-sev, .v12-sevbar span, .v12-trend__bar,
    .v12-legend__key, .v12-callout, .v12-stat::before {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .v12-stats { grid-template-columns: repeat(4, 1fr) !important; gap: .5rem !important; }
    .v12-stat { padding: .75rem !important; box-shadow: none !important; }
    .v12-stat__value { font-size: 1.375rem !important; }
    a[href]::after { content: none !important; }
}

@page {
    size: A4 portrait;
    margin: 16mm 14mm;
}

/* Con pocos meses las columnas se estirarían hasta ocupar media página; se
   limita el ancho para que la gráfica siga leyéndose como una serie. */
.v12-trend__col { max-width: 90px; }

/* ============================================================================
   Centro de escaneo
   ========================================================================== */

.v12-board { margin-bottom: 1.5rem; }
.v12-board__head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 1rem; margin: 1.5rem 0 .875rem;
}
.v12-board__title {
    font-family: var(--v12-font);
    display: flex; align-items: center; gap: .5rem;
    font-size: 1.0625rem; font-weight: 700; color: var(--v12-gray-900); margin: 0;
}
.v12-board__meta { font-size: .75rem; color: var(--v12-gray-400); font-variant-numeric: tabular-nums; }
.v12-board__grid {
    display: grid; gap: 1rem;
    grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
}
.v12-board__empty {
    display: flex; align-items: center; gap: .625rem;
    padding: 1.5rem; border: 1px dashed var(--v12-gray-300);
    border-radius: var(--v12-r-md); background: var(--v12-gray-50);
    font-size: .875rem; color: var(--v12-gray-500);
}
.v12-board__empty em { font-size: 1.25rem; color: var(--v12-gray-400); }

.v12-scan {
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-left: 3px solid var(--v12-gray-300);
    border-radius: var(--v12-r-md);
    box-shadow: var(--v12-shadow-sm);
    padding: 1rem 1.125rem;
}
.v12-scan--run  { border-left-color: var(--v12-orange-500); }
.v12-scan--ok   { border-left-color: var(--v12-ok); }
.v12-scan--fail { border-left-color: var(--v12-danger); }
.v12-scan--idle { border-left-color: var(--v12-gray-400); }

.v12-scan__head { display: flex; align-items: center; gap: .5rem; margin-bottom: .625rem; }
.v12-scan__name {
    flex: 1; min-width: 0;
    font-weight: 650; font-size: .9375rem; color: var(--v12-gray-900);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v12-scan__target {
    display: flex; align-items: center; gap: .375rem;
    font-size: .8125rem; color: var(--v12-gray-600);
    margin: 0 0 .75rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v12-scan__target em { color: var(--v12-gray-400); flex: none; }
.v12-scan__meta {
    display: flex; justify-content: space-between; gap: .75rem;
    font-size: .75rem; color: var(--v12-gray-500);
    margin: .625rem 0 0;
}
.v12-scan__msg {
    font-size: .75rem; color: var(--v12-gray-500);
    margin: .5rem 0 0; line-height: 1.45;
}
.v12-scan__foot { display: flex; gap: .375rem; flex-wrap: wrap; margin-top: .875rem; }
.v12-scan__foot:empty { display: none; }

/* Barra indeterminada: ningún fabricante publica porcentaje de avance, así que
   la alternativa honesta a un 0 % inmóvil es no fingir que se sabe. */
.v12-progress--indeterminate { position: relative; overflow: hidden; }
.v12-progress--indeterminate span {
    position: absolute; left: 0; top: 0; bottom: 0;
    width: 35%;
    animation: v12-slide 1.4s var(--v12-ease) infinite;
}
@keyframes v12-slide {
    0%   { left: -35%; }
    100% { left: 100%; }
}

.v12-muted { font-size: .75rem; color: var(--v12-gray-400); }

/* ============================================================================
   Panel lateral
   ========================================================================== */

.v12-drawer { position: fixed; inset: 0; z-index: 1050; }
.v12-drawer__scrim {
    position: absolute; inset: 0;
    background: rgba(27, 31, 36, .45);
    animation: v12-fade var(--v12-fast) var(--v12-ease);
}
.v12-drawer__panel {
    position: absolute; top: 0; right: 0; bottom: 0;
    width: min(520px, 100vw);
    background: var(--v12-white);
    box-shadow: var(--v12-shadow-lg);
    display: flex; flex-direction: column;
    animation: v12-slide-in var(--v12-slow) var(--v12-ease);
}
@keyframes v12-fade { from { opacity: 0; } }
@keyframes v12-slide-in { from { transform: translateX(100%); } }

.v12-drawer__head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
    padding: 1.25rem 1.5rem;
    border-bottom: 1px solid var(--v12-gray-200);
}
.v12-drawer__title {
    font-family: var(--v12-font);
    font-size: 1.125rem; font-weight: 700; color: var(--v12-gray-900); margin: 0;
}
.v12-drawer__sub { font-size: .8125rem; color: var(--v12-gray-500); margin: .25rem 0 0; }
.v12-drawer__body { flex: 1; overflow-y: auto; padding: 1.25rem 1.5rem; }
.v12-drawer__foot {
    display: flex; justify-content: flex-end; gap: .5rem;
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--v12-gray-200);
    background: var(--v12-gray-50);
}

.v12-icon-btn {
    width: 32px; height: 32px; flex: none;
    display: grid; place-items: center;
    border: 0; border-radius: var(--v12-r-sm);
    background: transparent; color: var(--v12-gray-500);
    cursor: pointer;
    transition: background var(--v12-fast) var(--v12-ease);
}
.v12-icon-btn:hover { background: var(--v12-gray-100); color: var(--v12-gray-900); }

.v12-picker--tight { grid-template-columns: 1fr; gap: .5rem; }
.v12-picker--tight .v12-source { padding: .75rem; }

.v12-input--area { resize: vertical; min-height: 72px; font-family: inherit; }

@media (prefers-reduced-motion: reduce) {
    .v12-drawer__panel, .v12-drawer__scrim,
    .v12-progress--indeterminate span { animation: none; }
    .v12-progress--indeterminate span { left: 0; width: 100%; opacity: .4; }
}

/* ============================================================================
   Cromado oscuro
   ============================================================================
   Menú y cabecera en oscuro, contenido en blanco. La razón no es estética: el
   contenido de esta herramienta son tablas densas y texto largo, que se leen
   mejor sobre blanco; el cromado oscuro los enmarca y hace que el naranja de
   marca signifique siempre "acción" en lugar de competir con la cabecera. */

:root {
    --v12-chrome-900: #0F1318;   /* menú lateral */
    --v12-chrome-800: #12161C;   /* cabecera */
    --v12-chrome-700: #1A2028;   /* superficies elevadas del cromado */
    --v12-chrome-line: #262E38;  /* separadores */
    --v12-chrome-text: #A9B3BF;  /* texto del cromado en reposo */
    --v12-chrome-text-strong: #F2F5F8;
}

/* --- Menú lateral -------------------------------------------------------- */

.left-side-menu {
    background: var(--v12-chrome-900) !important;
    border-right: 1px solid var(--v12-chrome-line);
}
.left-side-menu .logo,
.left-side-menu .logo-box { background: var(--v12-chrome-900) !important; }

#sidebar-menu > ul > li > a {
    color: var(--v12-chrome-text) !important;
    border-left: 2px solid transparent;
    transition: background var(--v12-fast) var(--v12-ease),
                color var(--v12-fast) var(--v12-ease),
                border-color var(--v12-fast) var(--v12-ease);
}
#sidebar-menu > ul > li > a:hover,
#sidebar-menu > ul > li > a:focus,
#sidebar-menu > ul > li.mm-active > a {
    color: var(--v12-chrome-text-strong) !important;
    background: rgba(255, 255, 255, .04);
    /* El filo naranja marca dónde estás. Es el único naranja del cromado, así
       que no compite con nada y se encuentra de un vistazo. */
    border-left-color: var(--v12-orange-500);
}
#sidebar-menu > ul > li > a > em,
#sidebar-menu > ul > li > a > span.mdi { color: var(--v12-gray-400); }
#sidebar-menu > ul > li > a:hover > em,
#sidebar-menu > ul > li.mm-active > a > em { color: var(--v12-orange-400); }

.nav-second-level { background: rgba(0, 0, 0, .25); }
.nav-second-level li a {
    color: var(--v12-gray-400) !important;
    transition: color var(--v12-fast) var(--v12-ease), background var(--v12-fast) var(--v12-ease);
}
.nav-second-level li a:hover,
.nav-second-level li.mm-active > a {
    color: var(--v12-chrome-text-strong) !important;
    background: rgba(255, 255, 255, .05);
}
.menu-arrow { color: var(--v12-gray-500); }

/* --- Cabecera ------------------------------------------------------------ */

.navbar-custom {
    background-color: var(--v12-chrome-800) !important;
    border-bottom: 1px solid var(--v12-chrome-line);
    box-shadow: none;
}
.navbar-custom .nav-link,
.navbar-custom .nav-user,
.navbar-custom .pro-user-name { color: var(--v12-chrome-text) !important; }
.navbar-custom .nav-link:hover,
.navbar-custom .nav-user:hover { color: var(--v12-chrome-text-strong) !important; }
.navbar-custom .nav-user { background: transparent; border: 0; }

/* El desplegable del usuario cuelga de una cabecera oscura: en blanco daba un
   salto de contraste incómodo justo bajo el cursor. */
.navbar-custom .dropdown-menu {
    background: var(--v12-chrome-700);
    border: 1px solid var(--v12-chrome-line);
    box-shadow: var(--v12-shadow-lg);
}
.navbar-custom .dropdown-menu .dropdown-item { color: var(--v12-chrome-text); }
.navbar-custom .dropdown-menu .dropdown-item:hover,
.navbar-custom .dropdown-menu .dropdown-item:focus {
    background: rgba(255, 255, 255, .06);
    color: var(--v12-chrome-text-strong);
}
.navbar-custom .dropdown-menu .dropdown-divider { border-color: var(--v12-chrome-line); }
.navbar-custom .dropdown-header { color: var(--v12-gray-500); }

/* --- Contenido: sigue en blanco ------------------------------------------ */

.content-page, .wrapper { background: var(--v12-gray-50); }
.footer {
    background: transparent;
    border-top: 1px solid var(--v12-gray-200);
    color: var(--v12-gray-400);
}

/* ============================================================================
   Catálogo de integraciones
   ========================================================================== */

.v12-catalog { margin-top: 2.5rem; }
.v12-catalog__group {
    font-family: var(--v12-font);
    font-size: .75rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .06em; color: var(--v12-gray-500);
    margin: 1.5rem 0 .75rem;
}
.v12-catalog__grid {
    display: grid; gap: .625rem;
    grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
}
.v12-catalog__foot {
    font-size: .8125rem; color: var(--v12-gray-500);
    margin-top: 1.75rem; padding-top: 1rem;
    border-top: 1px solid var(--v12-gray-200);
}

.v12-integration {
    display: flex; align-items: flex-start; gap: .75rem;
    padding: .875rem;
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    transition: border-color var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-integration:hover { border-color: var(--v12-gray-300); box-shadow: var(--v12-shadow-sm); }

/* En la galería de destinos la tarjeta disponible es un BOTÓN: misma anatomía,
   más lo que anuncia que se puede pulsar — el cursor y un foco visible para el
   teclado. `font: inherit` y el alineado deshacen los estilos de botón del
   agente de usuario. */
button.v12-integration { width: 100%; text-align: left; cursor: pointer; font: inherit; }
button.v12-integration:focus-visible {
    outline: 2px solid var(--v12-orange-500);
    outline-offset: 2px;
}

/* Lo que aún no existe se atenúa, pero sigue siendo legible: es información,
   no un placeholder. La etiqueta "Pronto" es lo que lo dice, no el color. */
.v12-integration--soon { background: var(--v12-gray-50); }
.v12-integration--soon .v12-integration__mark { opacity: .55; }

.v12-integration__mark {
    width: 38px; height: 38px; flex: none;
    display: grid; place-items: center;
    border-radius: var(--v12-r-sm);
    background: var(--brand, var(--v12-gray-400));
    color: #fff;
    font-weight: 700; font-size: .8125rem; letter-spacing: .02em;
}
.v12-integration__body { flex: 1; min-width: 0; }
.v12-integration__name {
    display: block; font-weight: 650; font-size: .875rem; line-height: 1.2;
    color: var(--v12-gray-900);
}
.v12-integration__vendor {
    display: block; font-size: .75rem; color: var(--v12-gray-500); margin-top: .125rem;
}
.v12-integration__note {
    display: block; font-size: .75rem; color: var(--v12-gray-600);
    margin-top: .375rem; line-height: 1.45;
}
.v12-integration__site {
    display: inline-block; font-size: .6875rem; margin-top: .375rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    color: var(--v12-orange-600);
}
.v12-integration__tag { flex: none; align-self: center; }
.v12-tag--muted {
    background: var(--v12-gray-100); color: var(--v12-gray-500);
    border-color: var(--v12-gray-200);
}

/* ============================================================================
   Login
   ============================================================================
   Dos mitades: la marca a la izquierda sobre el oscuro del cromado, el
   formulario a la derecha sobre blanco. En móvil desaparece la mitad
   decorativa en lugar de encogerse — en una pantalla estrecha lo único que
   importa es poder escribir usuario y contraseña. */

.v12-login-body {
    margin: 0;
    background: var(--v12-white);
    font-family: var(--v12-font);
}

.v12-login { display: grid; min-height: 100vh; grid-template-columns: 1fr; }
@media (min-width: 992px) {
    .v12-login { grid-template-columns: 1.05fr 1fr; }
}

/* --- Mitad de marca ------------------------------------------------------ */

.v12-login__brand {
    display: none;
    position: relative;
    overflow: hidden;
    flex-direction: column;
    justify-content: space-between;
    padding: 3rem;
    background: var(--v12-chrome-900);
    color: var(--v12-chrome-text);
}
@media (min-width: 992px) { .v12-login__brand { display: flex; } }

/* Un solo foco naranja difuminado: da profundidad sin robarle atención al
   formulario, que es donde la persona tiene que mirar. */
.v12-login__glow {
    position: absolute;
    width: 620px; height: 620px;
    top: -180px; right: -220px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(242,106,33,.28) 0%, rgba(242,106,33,0) 68%);
    pointer-events: none;
}

.v12-login__brandtop { position: relative; }
.v12-login__logo { max-width: 190px; height: auto; }
.v12-login__logo--mobile { display: block; max-width: 160px; margin: 0 auto 2rem; }
@media (min-width: 992px) { .v12-login__logo--mobile { display: none; } }

.v12-login__pitch { position: relative; max-width: 30rem; }
.v12-login__claim {
    font-size: 2.5rem; font-weight: 800; line-height: 1.1;
    letter-spacing: -.03em;
    color: var(--v12-white);
    margin: 0 0 .875rem;
}
.v12-login__lead {
    font-size: 1rem; line-height: 1.6;
    color: var(--v12-gray-400);
    margin: 0 0 2rem;
}
.v12-login__points { list-style: none; padding: 0; margin: 0; display: grid; gap: .875rem; }
.v12-login__points li {
    display: flex; align-items: flex-start; gap: .75rem;
    font-size: .9375rem; line-height: 1.45;
    color: var(--v12-chrome-text);
}
.v12-login__points em {
    flex: none;
    width: 32px; height: 32px;
    display: grid; place-items: center;
    border-radius: var(--v12-r-sm);
    background: rgba(242, 106, 33, .14);
    color: var(--v12-orange-400);
    font-size: 1.0625rem;
}
.v12-login__foot { position: relative; font-size: .75rem; color: var(--v12-gray-600); margin: 0; }

/* --- Mitad del formulario ------------------------------------------------ */

.v12-login__panel {
    display: flex; align-items: center; justify-content: center;
    padding: 2.5rem 1.5rem;
    background: var(--v12-white);
}
.v12-login__form { width: 100%; max-width: 24rem; }
.v12-login__title {
    font-size: 1.75rem; font-weight: 700; letter-spacing: -.02em;
    color: var(--v12-gray-900); margin: 0;
}
.v12-login__sub { font-size: .9375rem; color: var(--v12-gray-500); margin: .375rem 0 2rem; }
.v12-login__legal {
    font-size: .75rem; color: var(--v12-gray-400);
    margin: 1.75rem 0 0; line-height: 1.5;
}

.v12-btn--block { width: 100%; justify-content: center; }

.v12-input-group { position: relative; display: flex; }
.v12-input-group .v12-input { padding-right: 2.75rem; width: 100%; }
.v12-reveal {
    position: absolute; right: 0; top: 0; bottom: 0;
    width: 2.75rem;
    display: grid; place-items: center;
    border: 0; background: transparent;
    color: var(--v12-gray-400);
    cursor: pointer;
    border-radius: 0 var(--v12-r-sm) var(--v12-r-sm) 0;
}
.v12-reveal:hover { color: var(--v12-gray-700); }
.v12-reveal:focus-visible { outline: 0; box-shadow: var(--v12-ring); }

.v12-login__divider {
    display: flex; align-items: center; gap: .75rem;
    margin: 1.25rem 0;
    font-size: .75rem; color: var(--v12-gray-400);
}
.v12-login__divider::before,
.v12-login__divider::after {
    content: ""; flex: 1; height: 1px; background: var(--v12-gray-200);
}

/* El login hereda estilos del tema pensados para su propio marcado; se anulan
   aquí para que el formulario nuevo no salga con dos cajas superpuestas. */
.v12-login-body .card,
.v12-login-body .account-pages { background: transparent; border: 0; box-shadow: none; }

/* El botón de acceso llegaba con `visibility: hidden` puesto en línea por el
   JavaScript heredado del tema, que espera el marcado de Bootstrap y no lo
   encuentra. Se fuerza aquí en lugar de tocar ese JS, que lo comparten todas
   las pantallas antiguas. */
.v12-login__form .v12-btn,
.v12-login__form .v12-btn .ladda-label {
    visibility: visible !important;
    opacity: 1 !important;
}
.v12-login__form .v12-btn--primary { background: var(--v12-orange-500) !important; color: #fff !important; }
.v12-login__form .v12-btn--primary:hover { background: var(--v12-orange-600) !important; }

/* ============================================================================
   Índice de cuadros de mando
   ========================================================================== */

/* TRES COLUMNAS Y TODAS LAS TARJETAS IGUALES. La versión anterior usaba
   `auto-fill` y dejaba que la destacada ocupara dos columnas: con la miniatura
   dentro, esa tarjeta se estiraba a todo el ancho de la pantalla y la miniatura
   con ella. Una rejilla donde una tarjeta mide el triple que otra no ayuda a
   elegir — que es lo único para lo que existe este índice. */
.v12-dashgrid {
    display: grid; gap: .875rem;
    grid-template-columns: 1fr;
    align-items: stretch;
}
@media (min-width: 700px) { .v12-dashgrid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .v12-dashgrid { grid-template-columns: repeat(3, 1fr); } }

.v12-dashcard {
    display: flex; align-items: flex-start; gap: .875rem;
    padding: 1.125rem;
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    box-shadow: var(--v12-shadow-sm);
    text-decoration: none;
    color: inherit;
    transition: transform var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease),
                border-color var(--v12-fast) var(--v12-ease);
}
.v12-dashcard:hover {
    transform: translateY(-2px);
    box-shadow: var(--v12-shadow-md);
    border-color: var(--v12-orange-400);
    text-decoration: none;
    color: inherit;
}
.v12-dashcard:focus-visible { outline: none; box-shadow: var(--v12-ring); }

/* Los nuevos se distinguen POR COLOR, no por tamaño. Ocupar dos columnas los hacía
   el triple de altos que sus vecinos y rompía la rejilla. */
.v12-dashcard--featured { border-color: var(--v12-orange-100); background: var(--v12-orange-50); }
.v12-dashcard--featured .v12-dashcard__icon {
    background: var(--v12-orange-500); color: #fff; border-color: var(--v12-orange-500);
}

.v12-dashcard__icon {
    width: 44px; height: 44px; flex: none;
    display: grid; place-items: center;
    border-radius: var(--v12-r-md);
    background: var(--v12-gray-50);
    border: 1px solid var(--v12-gray-200);
    color: var(--v12-orange-500);
    font-size: 1.375rem;
    transition: background var(--v12-fast) var(--v12-ease),
                color var(--v12-fast) var(--v12-ease);
}
.v12-dashcard:hover .v12-dashcard__icon {
    background: var(--v12-orange-500); color: #fff; border-color: var(--v12-orange-500);
}

.v12-dashcard__body { flex: 1; min-width: 0; }
.v12-dashcard__title {
    display: block;
    font-family: var(--v12-font);
    font-weight: 700; font-size: 1rem; line-height: 1.25;
    letter-spacing: -.01em;
    color: var(--v12-gray-900);
}
.v12-dashcard__text {
    display: block;
    font-size: .8125rem; line-height: 1.5;
    color: var(--v12-gray-500);
    margin-top: .3125rem;
}

.v12-dashcard__go {
    flex: none; align-self: center;
    color: var(--v12-gray-300);
    font-size: 1.125rem;
    transition: color var(--v12-fast) var(--v12-ease),
                transform var(--v12-fast) var(--v12-ease);
}
.v12-dashcard:hover .v12-dashcard__go {
    color: var(--v12-orange-500);
    transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
    .v12-dashcard:hover { transform: none; }
    .v12-dashcard:hover .v12-dashcard__go { transform: none; }
}

/* Logotipo oficial del fabricante cuando está disponible. Va sobre blanco y no
   sobre el color de marca: las marcas de terceros llegan con su propio color y
   superponerlas a otro fondo las deforma. */
.v12-integration__mark--logo {
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    padding: 5px;
}
.v12-integration__mark--logo img {
    max-width: 100%; max-height: 100%;
    object-fit: contain;
}

/* Selector de idioma del acceso. Arriba a la derecha, discreto: es una salida
   de emergencia para quien llega en el idioma que no es, no una acción
   principal. */
.v12-login__lang {
    position: absolute; top: 1.5rem; right: 1.75rem;
    display: flex; gap: .25rem;
}
.v12-login__langlink {
    padding: .3125rem .625rem;
    border-radius: var(--v12-r-sm);
    font-size: .75rem; font-weight: 600;
    color: var(--v12-gray-400);
    text-decoration: none;
    transition: background var(--v12-fast) var(--v12-ease),
                color var(--v12-fast) var(--v12-ease);
}
.v12-login__langlink:hover { background: var(--v12-gray-100); color: var(--v12-gray-700); text-decoration: none; }
.v12-login__langlink--on { background: var(--v12-orange-50); color: var(--v12-orange-600); }
.v12-login__panel { position: relative; }

/* ============================================================================
   Panel de inicio
   ============================================================================
   La jerarquía es deliberada: el encabezado va oscuro y ocupa el ancho, los
   avisos son una fila de fichas compactas, y los paneles tienen tamaños
   distintos según lo que pesan. Una rejilla de cajas blancas idénticas obliga a
   leerlas todas para descubrir cuál importa.

   Barras y anillos arrancan a cero y el JavaScript les fija su valor un
   fotograma después; el valor final vive en una variable CSS para que también
   sirva de respaldo si el JavaScript no llega. */

.v12-cockpit {
    position: relative;
    overflow: hidden;
    display: flex; align-items: center; justify-content: space-between;
    gap: 2rem; flex-wrap: wrap;
    padding: 2rem 2.25rem;
    margin-bottom: 1rem;
    border-radius: var(--v12-r-lg);
    background: var(--v12-chrome-900);
    color: var(--v12-chrome-text);
}
.v12-cockpit__glow {
    position: absolute; width: 460px; height: 460px;
    top: -190px; right: 6%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(242,106,33,.26) 0%, rgba(242,106,33,0) 70%);
    pointer-events: none;
}
.v12-cockpit__main { position: relative; min-width: 0; }
.v12-cockpit__eyebrow {
    font-size: .6875rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .1em; color: var(--v12-orange-400); margin: 0 0 .5rem;
}
.v12-cockpit__number {
    font-family: var(--v12-font);
    font-size: 4rem; font-weight: 800; line-height: .95;
    letter-spacing: -.04em; color: var(--v12-white);
    font-variant-numeric: tabular-nums; margin: 0;
}
.v12-cockpit__label { font-size: .9375rem; color: var(--v12-gray-400); margin: .625rem 0 1.25rem; }

.v12-cockpit__chips { display: flex; gap: .5rem; flex-wrap: wrap; }
.v12-chip {
    display: flex; align-items: center; gap: .4375rem;
    padding: .4375rem .75rem;
    border-radius: var(--v12-r-pill);
    background: rgba(255, 255, 255, .05);
    border: 1px solid rgba(255, 255, 255, .08);
    text-decoration: none;
    transition: background var(--v12-fast) var(--v12-ease),
                border-color var(--v12-fast) var(--v12-ease);
}
.v12-chip:hover { background: rgba(255, 255, 255, .1); border-color: rgba(255, 255, 255, .18); text-decoration: none; }
.v12-chip i { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.v12-chip--critical i { background: var(--sev-critical); }
.v12-chip--high i     { background: var(--sev-high); }
.v12-chip--medium i   { background: var(--sev-medium); }
.v12-chip--low i      { background: var(--sev-low); }
.v12-chip__value {
    font-size: .9375rem; font-weight: 700; color: var(--v12-white);
    font-variant-numeric: tabular-nums;
}
.v12-chip__label { font-size: .75rem; color: var(--v12-gray-400); }

/* --- Anillo de severidad -------------------------------------------------- */

.v12-cockpit__ring { position: relative; flex: none; width: 168px; height: 168px; }
.v12-cockpit__ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.v12-ring__track { fill: none; stroke: rgba(255, 255, 255, .07); stroke-width: 11; }
.v12-ring__seg {
    fill: none; stroke-width: 11; stroke-linecap: butt;
    /* Arranca sin longitud: el JavaScript aplica --len y el trazo se dibuja. */
    stroke-dasharray: 0 var(--gap);
    stroke-dashoffset: var(--off);
    transition: stroke-dasharray 900ms var(--v12-ease);
}
.s-stroke-critical { stroke: var(--sev-critical); }
.s-stroke-high     { stroke: var(--sev-high); }
.s-stroke-medium   { stroke: var(--sev-medium); }
.s-stroke-low      { stroke: var(--sev-low); }

.v12-ring__center {
    position: absolute; inset: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .125rem; pointer-events: none;
}
.v12-ring__pct {
    font-family: var(--v12-font);
    font-size: 1.75rem; font-weight: 800; color: var(--v12-white);
    letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1;
}
.v12-ring__cap { font-size: .6875rem; color: var(--v12-gray-500); text-align: center; }

/* --- Avisos accionables --------------------------------------------------- */

.v12-alerts {
    display: grid; gap: .75rem; margin-bottom: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.v12-alert {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas: "icon value" "icon title" "text text";
    align-items: center;
    column-gap: .75rem;
    padding: 1rem 1.125rem;
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    text-decoration: none; color: inherit;
    position: relative; overflow: hidden;
    transition: transform var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-alert::before {
    content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
    background: var(--v12-gray-300);
}
.v12-alert--danger::before { background: var(--sev-critical); }
.v12-alert--warn::before   { background: var(--sev-high); }
.v12-alert:hover { transform: translateY(-2px); box-shadow: var(--v12-shadow-md); text-decoration: none; color: inherit; }

.v12-alert__icon {
    grid-area: icon;
    width: 40px; height: 40px;
    display: grid; place-items: center;
    border-radius: var(--v12-r-sm);
    font-size: 1.25rem;
}
.v12-alert--danger .v12-alert__icon { background: var(--v12-danger-bg); color: var(--v12-danger); }
.v12-alert--warn .v12-alert__icon   { background: var(--v12-warn-bg);   color: var(--v12-warn); }
.v12-alert__value {
    grid-area: value; align-self: end;
    font-family: var(--v12-font);
    font-size: 1.625rem; font-weight: 800; line-height: 1;
    letter-spacing: -.02em; color: var(--v12-gray-900);
    font-variant-numeric: tabular-nums;
}
.v12-alert__title { grid-area: title; align-self: start; font-size: .8125rem; color: var(--v12-gray-600); }
.v12-alert__text {
    grid-area: text; font-size: .75rem; color: var(--v12-gray-400);
    margin-top: .625rem; line-height: 1.4;
}

/* --- Rejilla de paneles --------------------------------------------------- */

.v12-grid { display: grid; gap: 1rem; margin-bottom: 1rem; grid-template-columns: 1fr; }
@media (min-width: 1100px) {
    .v12-grid { grid-template-columns: 1fr 1fr; }
    /* El panel de la serie temporal pesa más: es la única pregunta que no se
       responde con un número suelto. */
    .v12-grid--wide { grid-template-columns: 1.6fr 1fr; }
}
.v12-panel { display: flex; flex-direction: column; }
.v12-panel__body { padding: 1.25rem; flex: 1; }
.v12-panel .v12-card__foot { margin-top: auto; }

/* --- Serie temporal ------------------------------------------------------- */

.v12-balance {
    display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
    font-size: .8125rem; color: var(--v12-gray-500); margin: 0 0 1rem;
}
.v12-balance strong {
    font-family: var(--v12-font);
    font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
.v12-balance em { font-size: 1.125rem; }
.v12-balance--up strong, .v12-balance--up em { color: var(--v12-danger); }
.v12-balance--down strong, .v12-balance--down em { color: var(--v12-ok); }

.v12-chart { position: relative; }
.v12-chart svg { width: 100%; height: 130px; display: block; overflow: visible; }
.v12-chart__area { fill: url(#v12FillIn); }
.v12-chart__line {
    fill: none; stroke-width: 1.6;
    vector-effect: non-scaling-stroke;
    stroke-linecap: round; stroke-linejoin: round;
}
.v12-chart__line--in  { stroke: var(--sev-high); }
.v12-chart__line--out { stroke: var(--v12-ok); stroke-dasharray: 3 2.5; }
.v12-chart__axis {
    display: flex; justify-content: space-between;
    margin-top: .5rem; font-size: .6875rem; color: var(--v12-gray-400);
}

/* --- Flujo ---------------------------------------------------------------- */

.v12-flow { display: flex; flex-direction: column; gap: .625rem; }
.v12-flow__step {
    position: relative;
    display: grid; grid-template-columns: auto 1fr; align-items: baseline;
    gap: .5rem;
    padding: .75rem .875rem;
    border-radius: var(--v12-r-sm);
    background: var(--v12-gray-50);
    overflow: hidden;
    text-decoration: none; color: inherit;
}
.v12-flow__step:hover { text-decoration: none; color: inherit; background: var(--v12-gray-100); }
/* La barra vive detrás del texto: el ancho ES el dato, no un adorno al lado. */
.v12-flow__bar {
    position: absolute; inset: 0 auto 0 0;
    width: 0;
    opacity: .16;
    transition: width 800ms var(--v12-ease);
}
.v12-flow__step--in   .v12-flow__bar { background: var(--sev-high); }
.v12-flow__step--work .v12-flow__bar { background: var(--v12-info); }
.v12-flow__step--done .v12-flow__bar { background: var(--v12-ok); }
.v12-flow__value {
    position: relative;
    font-family: var(--v12-font);
    font-size: 1.375rem; font-weight: 800; letter-spacing: -.02em;
    color: var(--v12-gray-900); font-variant-numeric: tabular-nums;
}
.v12-flow__label { position: relative; font-size: .8125rem; color: var(--v12-gray-600); }

/* --- Concentración -------------------------------------------------------- */

.v12-ranking { display: flex; flex-direction: column; gap: .75rem; }
.v12-rank {
    display: grid; grid-template-columns: minmax(0, 1fr) 42% auto;
    align-items: center; gap: .75rem;
    padding: .3125rem .5rem; margin: 0 -.5rem;
    border-radius: var(--v12-r-sm);
    text-decoration: none; color: inherit;
    transition: background var(--v12-fast) var(--v12-ease);
}
.v12-rank:hover { background: var(--v12-gray-50); text-decoration: none; color: inherit; }
.v12-rank__name {
    font-size: .8125rem; color: var(--v12-gray-800);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v12-rank__track { height: 10px; background: var(--v12-gray-100); border-radius: var(--v12-r-pill); overflow: hidden; }
/* Apilada por gravedad: con varios activos del mismo total, una barra lisa no
   dice nada y el reparto por severidad sí. */
.v12-rank__fill {
    display: flex; height: 100%; width: 0;
    border-radius: var(--v12-r-pill); overflow: hidden;
    transition: width 800ms var(--v12-ease);
}
.v12-rank__fill i { display: block; height: 100%; }
.v12-rank__value {
    font-size: .8125rem; font-weight: 650; color: var(--v12-gray-900);
    font-variant-numeric: tabular-nums; text-align: right; min-width: 2.25rem;
}

/* --- Últimas críticas ----------------------------------------------------- */

.v12-feed { list-style: none; margin: 0; padding: 0; }
.v12-feed li + li { border-top: 1px solid var(--v12-gray-100); }
.v12-feed__item {
    display: flex; align-items: center; gap: .75rem;
    padding: .75rem 1.25rem;
    text-decoration: none; color: inherit;
    transition: background var(--v12-fast) var(--v12-ease);
}
.v12-feed__item:hover { background: var(--v12-orange-50); text-decoration: none; color: inherit; }
.v12-feed__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.v12-feed__body { flex: 1; min-width: 0; }
.v12-feed__title {
    display: block; font-size: .875rem; font-weight: 600; color: var(--v12-gray-900);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v12-feed__meta { display: block; font-size: .75rem; color: var(--v12-gray-500); margin-top: .125rem; }
.v12-feed__go { color: var(--v12-gray-300); flex: none; }
.v12-feed__item:hover .v12-feed__go { color: var(--v12-orange-500); }

@media (prefers-reduced-motion: reduce) {
    .v12-ring__seg, .v12-flow__bar, .v12-rank__fill { transition: none; }
    .v12-alert:hover { transform: none; }
}

/* El tema deja `.content-page` con `padding-top: 0`, así que el contenido queda
   pegado al borde inferior de la cabecera. Con las pantallas antiguas apenas se
   notaba —empiezan con un título sobre fondo claro—, pero el encabezado oscuro
   del inicio se funde con la cabecera y parece un solo bloque. Se da el aire
   aquí, para todas las pantallas del sistema de diseño. */
.container-fluid > .v12-cockpit:first-child,
.container-fluid > .v12-page-head:first-child,
.container-fluid > .row:first-child > .col-12 > .v12-page-head {
    margin-top: 1.25rem;
}

/* ============================================================================
   Listado de activos
   ========================================================================== */

/* Selector de riesgo de la cabecera. Son enlaces, no botones: cada corte tiene
   su URL y se puede compartir o volver atrás con el navegador. */
.v12-riskpick {
    display: inline-flex; flex-wrap: wrap; gap: .25rem;
    padding: .25rem;
    background: var(--v12-gray-100);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
}
.v12-riskpick__item {
    display: inline-flex; align-items: center; gap: .375rem;
    padding: .4375rem .75rem;
    font-size: .8125rem; font-weight: 600; line-height: 1;
    color: var(--v12-gray-600);
    border-radius: calc(var(--v12-r-md) - 3px);
    white-space: nowrap;
    transition: background var(--v12-fast) var(--v12-ease),
                color var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-riskpick__item:hover { color: var(--v12-gray-900); background: var(--v12-white); text-decoration: none; }
.v12-riskpick__item .mdi { font-size: 1rem; opacity: .75; }
.v12-riskpick__item--on {
    background: var(--v12-white);
    color: var(--v12-orange-700);
    box-shadow: var(--v12-shadow-sm);
}
.v12-riskpick__item--on .mdi { opacity: 1; color: var(--v12-orange-500); }

/* Panel de filtros: se reaprovecha la rejilla Bootstrap de InlineForm porque es
   la que también emiten los campos personalizados. Lo que cambia es la piel. */
.v12-filters__count { font-size: .8125rem; color: var(--v12-gray-500); }
.v12-filters__count strong { color: var(--v12-gray-900); margin-right: .25rem; }
.v12-filters .form-group { margin-bottom: 1rem; }
.v12-filters .form-group label {
    display: block; font-size: .75rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--v12-gray-500); margin-bottom: .375rem;
}
.v12-filters .form-control,
.v12-filters .bootstrap-select > .dropdown-toggle {
    height: auto;
    min-height: 38px;
    padding: .5rem .75rem;
    font-size: .875rem;
    color: var(--v12-gray-900);
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-300);
    border-radius: var(--v12-r-sm);
    box-shadow: none;
    transition: border-color var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-filters .form-control:focus,
.v12-filters .bootstrap-select > .dropdown-toggle:focus {
    border-color: var(--v12-orange-500);
    box-shadow: 0 0 0 3px var(--v12-orange-100);
    outline: none;
}
.v12-filters__foot {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: .75rem;
    padding-top: .25rem;
}

/* Etiquetas de filtro activo. El aspa es parte del enlace entero: el objetivo
   táctil es la etiqueta completa, no una cruz de diez píxeles.
   Se llaman `fchip` y no `chip` a propósito: `.v12-chip` ya existe más arriba,
   es la píldora sobre fondo oscuro del panel de inicio, y reutilizar el nombre
   le ponía texto blanco sobre fondo casi blanco. */
.v12-fchips { display: flex; flex-wrap: wrap; gap: .375rem; align-items: center; }
.v12-fchip {
    display: inline-flex; align-items: center; gap: .375rem;
    padding: .3125rem .5rem .3125rem .625rem;
    font-size: .75rem; line-height: 1;
    background: var(--v12-orange-50);
    border: 1px solid var(--v12-orange-100);
    color: var(--v12-orange-700);
    border-radius: var(--v12-r-pill);
    max-width: 22rem;
    transition: background var(--v12-fast) var(--v12-ease);
}
.v12-fchip:hover { background: var(--v12-orange-100); text-decoration: none; color: var(--v12-orange-700); }
.v12-fchip__key { font-weight: 700; text-transform: uppercase; letter-spacing: .03em; opacity: .75; }
.v12-fchip__val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v12-fchip .mdi { font-size: .875rem; opacity: .6; }
.v12-fchip:hover .mdi { opacity: 1; }
.v12-fchip--clear {
    background: transparent; border-color: transparent;
    color: var(--v12-gray-500); text-decoration: underline;
}
.v12-fchip--clear:hover { background: transparent; color: var(--v12-gray-900); }

/* Tabla de activos */
.v12-assets__pick { width: 2.5rem; text-align: center; }
.v12-assets__pick input { accent-color: var(--v12-orange-500); width: 15px; height: 15px; }
.v12-assets__name {
    display: block; font-weight: 650; font-size: .875rem;
    color: var(--v12-gray-900); line-height: 1.25;
}
.v12-assets__name:hover { color: var(--v12-orange-600); text-decoration: none; }
.v12-assets__ip {
    display: block; margin-top: .125rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .75rem; color: var(--v12-gray-500);
}
.v12-assets__none { font-size: .8125rem; color: var(--v12-gray-400); font-style: italic; }
.v12-assets__clean { display: inline-flex; align-items: center; gap: .375rem; font-size: .8125rem; color: var(--v12-ok); }
.v12-assets__actions { width: 2.5rem; text-align: right; }
.v12-assets__risk { min-width: 13rem; }
.v12-assets__worst { display: inline-flex; gap: .25rem; margin-left: .5rem; vertical-align: middle; }

/* Barra de riesgo: el ancho compara el activo con el peor de la página y los
   segmentos reparten ese ancho por gravedad. Dos lecturas en un solo gesto —
   cuánto hay, y de qué tipo. */
.v12-riskbar {
    display: inline-flex; align-items: center; gap: .5rem;
    min-width: 9rem; vertical-align: middle;
}
.v12-riskbar:hover { text-decoration: none; }
/* El carril es el ancho de referencia y la barra el trozo proporcional. Sin
   separarlos, el porcentaje se calculaba contra el flex-container completo y el
   recuento acababa encima de las etiquetas de gravedad. */
.v12-riskbar__rail {
    display: block; width: 7rem; flex: none;
    height: 8px; border-radius: var(--v12-r-pill);
    background: var(--v12-gray-100); overflow: hidden;
}
.v12-riskbar__track {
    display: flex; height: 100%; min-width: 6px;
    border-radius: var(--v12-r-pill); overflow: hidden;
    transition: filter var(--v12-fast) var(--v12-ease);
}
.v12-riskbar__track i { display: block; height: 100%; min-width: 3px; }
.v12-riskbar:hover .v12-riskbar__track { filter: brightness(.92); }
.v12-riskbar__count {
    font-size: .8125rem; font-weight: 650; font-variant-numeric: tabular-nums;
    color: var(--v12-gray-700);
}

/* Pie del listado: edición masiva a la izquierda, recuento y paginación a la
   derecha, en una sola línea. */
.v12-listfoot {
    display: flex; align-items: center; justify-content: flex-end;
    flex-wrap: wrap; gap: .75rem;
}
.v12-listfoot #bulk-edit { margin-right: auto; }
.v12-listfoot__info { font-size: .8125rem; color: var(--v12-gray-500); }
.v12-listfoot .dataTables_paginate { margin: 0; }

@media (max-width: 767px) {
    .v12-riskpick { width: 100%; }
    .v12-assets__risk { min-width: 0; }
}

/* El tema pinta la página activa del paginador en violeta, que es el acento de
   la plantilla comprada y no el del producto. Se corrige aquí y no dentro de
   `.v12-listfoot` porque el paginador es el mismo en todos los listados. */
.pagination .page-item.active .page-link,
.pagination .page-item.active .page-link:hover,
.pagination .page-item.active .page-link:focus {
    background-color: var(--v12-orange-500);
    border-color: var(--v12-orange-500);
    color: var(--v12-white);
    box-shadow: none;
}
.pagination .page-link {
    color: var(--v12-gray-600);
    border-color: var(--v12-gray-200);
}
.pagination .page-link:hover {
    color: var(--v12-orange-700);
    background-color: var(--v12-orange-50);
    border-color: var(--v12-orange-100);
}
.pagination .page-link:focus { box-shadow: 0 0 0 3px var(--v12-orange-100); }

/* Ordenación de columnas.
   Las flechas y el cursor de mano los ponía dataTables.bootstrap4.css, pero
   todas sus reglas cuelgan de `table.dataTable`, y `.v12-table` no lleva esa
   clase. La cabecera seguía siendo pulsable y nada lo indicaba. Se resuelve
   aquí, con el acento del producto, en vez de heredar el aspecto de DataTables. */
.v12-table thead th.sorting {
    cursor: pointer;
    padding-right: 1.75rem;
    position: relative;
    user-select: none;
}
.v12-table thead th.sorting:hover { color: var(--v12-gray-900); }
.v12-table thead th.sorting::before,
.v12-table thead th.sorting::after {
    content: "";
    position: absolute;
    right: .75rem;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    opacity: .28;
}
.v12-table thead th.sorting::before { top: calc(50% - 8px); border-bottom: 5px solid currentColor; }
.v12-table thead th.sorting::after  { top: calc(50% + 3px); border-top: 5px solid currentColor; }
.v12-table thead th.sorting_asc::before,
.v12-table thead th.sorting_desc::after { opacity: 1; color: var(--v12-orange-500); }

/* ============================================================================
   Ficha de registro (detalle de una vulnerabilidad)
   ========================================================================== */

/* Cabecera de un registro concreto, no de una pantalla: la identidad
   —gravedad, título, CVE— tiene que leerse antes que cualquier campo del
   formulario. El filo de color de la izquierda lleva la gravedad. */
.v12-rechead {
    position: relative;
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    box-shadow: var(--v12-shadow-sm);
    padding: 1.25rem 1.5rem 1.25rem 1.75rem;
    margin-bottom: 1.25rem;
    overflow: hidden;
}
.v12-rechead::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
    background: var(--v12-gray-300);
}
.v12-rechead--critical::before { background: var(--sev-critical); }
.v12-rechead--high::before     { background: var(--sev-high); }
.v12-rechead--medium::before   { background: var(--sev-medium); }
.v12-rechead--low::before      { background: var(--sev-low); }
.v12-rechead--info::before     { background: var(--sev-info); }

.v12-rechead__top {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
}
.v12-rechead__main { min-width: 0; flex: 1 1 22rem; }
.v12-rechead__eyebrow {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    font-size: .75rem; color: var(--v12-gray-500);
    margin-bottom: .375rem;
}
.v12-rechead__sep { color: var(--v12-gray-300); }
.v12-rechead__id {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    color: var(--v12-gray-600); font-weight: 600;
}
.v12-rechead__title {
    font-size: 1.375rem; font-weight: 700; letter-spacing: -.02em;
    color: var(--v12-gray-900); margin: 0; line-height: 1.25;
    overflow-wrap: anywhere;
}
.v12-rechead__actions { display: flex; align-items: center; gap: .5rem; flex: none; }
.v12-rechead__meta {
    display: flex; flex-wrap: wrap; gap: .875rem 1.75rem;
    margin: 1rem 0 0; padding-top: .875rem;
    border-top: 1px solid var(--v12-gray-100);
}
.v12-rechead__item { display: flex; flex-direction: column; gap: .1875rem; min-width: 0; }
.v12-rechead__key {
    font-size: .6875rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; color: var(--v12-gray-400);
}
.v12-rechead__value {
    font-size: .875rem; font-weight: 600; color: var(--v12-gray-800);
    display: flex; align-items: center; gap: .375rem;
}
.v12-rechead__value .mdi { color: var(--v12-gray-400); }
.v12-rechead__cvss { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 1rem; }
.v12-rechead__cvss small { font-weight: 500; color: var(--v12-gray-400); }

/* ============================================================================
   Formulario de detalle: etiqueta a la izquierda, valor a la derecha
   ========================================================================== */

/* Reaprovecha la rejilla que emite el helper `Form::` en vez de reescribir los
   campos. No es pereza: el JavaScript de esta pantalla lee cada campo por su id
   (#title, #scan, #cvss…) y los campos personalizados por sus `data-cf-*`.
   Cambiando sólo la piel, el contrato con el JS queda intacto. */
.v12-vform .form-group.row {
    margin: 0; padding: .75rem 0;
    border-bottom: 1px solid var(--v12-gray-100);
}
.v12-vform .form-group.row:last-of-type { border-bottom: none; }
.v12-vform .col-form-label {
    font-size: .8125rem; font-weight: 600; color: var(--v12-gray-600);
    padding-top: .5rem; line-height: 1.35;
}
.v12-vform .col-form-label .text-danger { color: var(--v12-orange-500) !important; }
.v12-vform .form-control,
.v12-vform .bootstrap-select > .dropdown-toggle {
    height: auto; min-height: 38px;
    padding: .5rem .75rem;
    font-size: .875rem; color: var(--v12-gray-900);
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-300);
    border-radius: var(--v12-r-sm);
    box-shadow: none;
}
.v12-vform textarea.form-control { min-height: 96px; line-height: 1.55; }
.v12-vform .form-control:focus,
.v12-vform .bootstrap-select > .dropdown-toggle:focus {
    border-color: var(--v12-orange-500);
    box-shadow: 0 0 0 3px var(--v12-orange-100);
    outline: none;
}
.v12-vform .form-control[readonly] { background: var(--v12-gray-50); color: var(--v12-gray-600); }
.v12-vform .form-control-plaintext {
    font-size: .875rem; color: var(--v12-gray-800); padding-top: .5rem; margin: 0;
}
.v12-formfoot {
    display: flex; justify-content: flex-end; gap: .5rem;
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--v12-gray-200);
    background: var(--v12-gray-50);
    border-radius: 0 0 var(--v12-r-md) var(--v12-r-md);
}

/* ============================================================================
   Paneles laterales del detalle
   ========================================================================== */

.v12-side { margin-bottom: 1rem; }
.v12-side__head {
    display: flex; align-items: center; gap: .5rem;
    width: 100%;
    padding: .875rem 1rem;
    font-size: .8125rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--v12-gray-700);
    background: none; border: 0; text-align: left;
    cursor: pointer;
}
.v12-side__head:hover { color: var(--v12-gray-900); text-decoration: none; }
.v12-side__head > .mdi:first-child { font-size: 1rem; color: var(--v12-orange-500); }
.v12-side__title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v12-side__caret { flex: none; color: var(--v12-gray-400); transition: transform var(--v12-fast) var(--v12-ease); }
.v12-side__head[aria-expanded="false"] .v12-side__caret { transform: rotate(-90deg); }
.v12-side__body { padding: 0 1rem 1rem; }
.v12-side__body > *:first-child { margin-top: 0; }

/* Pares clave-valor en vertical, que es como se leen los metadatos de un
   registro. `.v12-conn__meta` no vale: es horizontal y vive en otra tarjeta. */
.v12-meta { display: grid; grid-template-columns: minmax(0, 7.5rem) minmax(0, 1fr); gap: .5rem .75rem; margin: 0; }
.v12-meta__key {
    font-size: .75rem; font-weight: 600; color: var(--v12-gray-500);
    display: flex; align-items: center; gap: .25rem;
}
.v12-meta__value { font-size: .8125rem; color: var(--v12-gray-900); margin: 0; min-width: 0; overflow-wrap: anywhere; }
.v12-meta__value--none { color: var(--v12-gray-400); font-style: italic; }
.v12-meta__link { color: var(--v12-gray-400); }
.v12-meta__link:hover { color: var(--v12-orange-500); }

/* Estado del flujo de trabajo del registro. */
.v12-wfstate {
    display: flex; align-items: center; gap: .625rem;
    padding: .75rem .875rem;
    background: var(--v12-orange-50);
    border: 1px solid var(--v12-orange-100);
    border-radius: var(--v12-r-sm);
    margin-bottom: .75rem;
}
.v12-wfstate__icon { flex: none; font-size: 1.25rem; line-height: 1; }
.v12-wfstate__body { min-width: 0; }
.v12-wfstate__key {
    display: block; font-size: .6875rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; color: var(--v12-orange-600);
}
.v12-wfstate__name {
    display: block; font-size: .9375rem; font-weight: 650; color: var(--v12-gray-900);
    line-height: 1.2; margin-top: .125rem;
}

/* Ficheros adjuntos. */
.v12-upload {
    display: block; position: relative;
    padding: .875rem; margin-bottom: .75rem;
    border: 1px dashed var(--v12-gray-300);
    border-radius: var(--v12-r-sm);
    background: var(--v12-gray-50);
    text-align: center; cursor: pointer;
    transition: border-color var(--v12-fast) var(--v12-ease),
                background var(--v12-fast) var(--v12-ease);
}
.v12-upload:hover { border-color: var(--v12-orange-400); background: var(--v12-orange-50); }
.v12-upload__icon { display: block; font-size: 1.375rem; color: var(--v12-gray-400); }
.v12-upload:hover .v12-upload__icon { color: var(--v12-orange-500); }
.v12-upload__text { display: block; font-size: .8125rem; color: var(--v12-gray-600); margin-top: .25rem; }
.v12-upload__hint { display: block; font-size: .6875rem; color: var(--v12-gray-400); margin-top: .125rem; }
/* El input real sigue en el DOM porque el JS se engancha a su `change`; sólo se
   le quita el aspecto nativo. */
.v12-upload input[type="file"] {
    position: absolute; inset: 0; width: 100%; height: 100%;
    opacity: 0; cursor: pointer;
}

.v12-files { display: flex; flex-direction: column; gap: .375rem; max-height: 13rem; overflow-y: auto; }
.v12-file {
    display: flex; align-items: center; gap: .5rem;
    padding: .5rem .625rem;
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-sm);
    background: var(--v12-white);
}
.v12-file__icon { flex: none; color: var(--v12-gray-400); }
.v12-file__name {
    flex: 1 1 auto; min-width: 0; font-size: .8125rem; color: var(--v12-gray-800);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v12-file__actions { flex: none; display: flex; gap: .125rem; }

/* Estado vacío de panel: `.v12-empty` mete 3rem de aire y aquí sobra. */
.v12-empty--sm { padding: 1.25rem .75rem; }
.v12-empty--sm .v12-empty__icon { width: 40px; height: 40px; font-size: 1.25rem; margin-bottom: .5rem; }
.v12-empty--sm .v12-empty__text { font-size: .8125rem; margin-bottom: .875rem; }

/* Tabla embebida en un campo del formulario: la del sistema es de pantalla
   completa (cabecera pegajosa, mayúsculas) y aquí resulta demasiado. */
.v12-minitable { width: 100%; margin: 0; font-size: .8125rem; }
.v12-minitable td { padding: .4375rem .5rem; border-top: 1px solid var(--v12-gray-100); vertical-align: middle; }
.v12-minitable tr:first-child td { border-top: none; }
.v12-minitable__actions { width: 2rem; text-align: right; }
.v12-minitable th {
    padding: .25rem .5rem .4375rem;
    font-size: .6875rem; font-weight: 600; letter-spacing: .04em;
    text-transform: uppercase; color: var(--v12-gray-500);
    border-bottom: 1px solid var(--v12-gray-200); text-align: left;
}
.v12-nowrap { white-space: nowrap; }

/* La fuente que vio un hallazgo en un activo. Clase propia y no `.v12-chip`:
   aquélla está pensada para superficie oscura (fondos rgba blancos) y la ficha
   del hallazgo es clara, así que allí el texto quedaría casi invisible. */
.v12-fuente {
    display: inline-flex; align-items: baseline; gap: .3125rem;
    max-width: 100%;
    padding: .1875rem .4375rem;
    margin: .125rem .25rem .125rem 0;
    border-radius: var(--v12-r-sm);
    background: var(--v12-gray-50);
    border: 1px solid var(--v12-gray-200);
    font-size: .75rem; color: var(--v12-gray-800);
}
.v12-fuente small { color: var(--v12-gray-500); font-size: .6875rem; }
.v12-scroll { max-height: 11rem; overflow-y: auto; }

@media (max-width: 991px) {
    .v12-rechead__meta { gap: .875rem 1.25rem; }
}

/* ============================================================================
   Ruta de parcheo
   ========================================================================== */

.v12-route__pos {
    width: 2.5rem; text-align: center;
    font-variant-numeric: tabular-nums; font-weight: 700;
    color: var(--v12-gray-400);
}
.v12-route__num { text-align: right; white-space: nowrap; }
.v12-route__name {
    display: block; font-weight: 650; font-size: .9375rem;
    color: var(--v12-gray-900); line-height: 1.3;
}
.v12-route__name:hover { color: var(--v12-orange-600); text-decoration: none; }
.v12-route__meta {
    display: flex; align-items: center; gap: .375rem; flex-wrap: wrap;
    margin-top: .25rem; font-size: .75rem; color: var(--v12-gray-500);
}
/* La regla aplicada, discreta: está para poder auditar la decisión, no para
   competir con ella. */
.v12-route__rule {
    display: block; margin-top: .25rem;
    font-size: .6875rem; color: var(--v12-gray-400);
}
.v12-route__unit {
    display: block; font-size: .6875rem; color: var(--v12-gray-500);
    text-transform: uppercase; letter-spacing: .03em;
}

/* --- Publicación hacia la herramienta del cliente (ruta de parcheo) --------- */

.v12-route__pub {
    white-space: nowrap;
    min-width: 9rem;
}

.v12-route__ticket {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-weight: 600;
    color: var(--sev-low, #2f855a);
    text-decoration: none;
}

.v12-route__ticket:hover {
    text-decoration: underline;
}

/* El aviso de que el alcance creció. Deliberadamente discreto: informa de que hay
   una decisión pendiente del analista, no reclama atención como un error —porque
   no lo es—. */
.v12-route__crecio {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    margin-left: .4rem;
    font-size: .75rem;
    color: var(--texto-suave, #6b7280);
}

.v12-route__aviso {
    margin-top: .35rem;
    padding: .35rem .5rem;
    border-radius: 4px;
    font-size: .78rem;
    line-height: 1.35;
    white-space: normal;
    max-width: 22rem;
}

.v12-route__aviso--info {
    background: var(--fondo-suave, #f3f4f6);
    border-left: 3px solid var(--suave, #9ca3af);
}

.v12-route__aviso--danger {
    background: #fdf2f2;
    border-left: 3px solid var(--sev-critical, #c53030);
}

/* ============================================================================
   Flujos de trabajo
   ============================================================================
   La tubería: cada etapa con su recuento VIVO dentro — es la vista de las
   vulnerabilidades por flujo, no un adorno. El editor de alta va debajo con
   las etapas del producto renombrables. */

.v12-flujo { margin-bottom: 1rem; }
.v12-flujo__tuberia {
    display: flex; align-items: stretch; flex-wrap: wrap; gap: .375rem 0;
    padding: 1rem 1.25rem 1.25rem;
}
.v12-flujo__etapa {
    display: flex; flex-direction: column; align-items: center; gap: .125rem;
    padding: .625rem 1rem; min-width: 96px;
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    text-decoration: none;
    transition: border-color var(--v12-fast) var(--v12-ease);
}
.v12-flujo__etapa:hover { border-color: var(--v12-orange-400); text-decoration: none; }
.v12-flujo__etapa--initial { border-left: 3px solid var(--v12-gray-400); }
.v12-flujo__etapa--final { border-left: 3px solid var(--v12-ok); }
.v12-flujo__n { font-size: 1.25rem; font-weight: 650; color: var(--v12-gray-900); line-height: 1.2; }
.v12-flujo__nombre { font-size: .75rem; color: var(--v12-gray-600); text-align: center; }
.v12-flujo__union { align-self: center; width: 22px; height: 2px; background: var(--v12-gray-300); flex: none; }

.v12-flujo-editor {
    display: grid; gap: .625rem; padding: 0 1.25rem;
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
}
.v12-flujo-editor__etapa {
    display: flex; gap: .75rem; align-items: flex-start; justify-content: space-between;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    padding: .75rem;
}
.v12-flujo-editor__control { display: flex; gap: .5rem; align-items: flex-start; margin: 0; }
.v12-flujo-editor__etapa .v12-input--sm { max-width: 190px; flex: none; }

/* ============================================================================
   Diseñador de flujos
   ============================================================================
   El diagrama ES el flujo: tarjetas sobre una cuadrícula punteada, aristas SVG
   con flecha calculadas de la geometría real, y el avance animado — salvo que
   el sistema pida quietud. */

/* EL REPARTO DEL ANCHO. Medido, no supuesto: con las tres columnas fijas hasta
   1100px, en una pantalla de 1440 al lienzo le quedaban 554px para un diagrama
   que necesita 1192, y en 1180 se quedaba en 294. Es decir: en las resoluciones
   más comunes se veía un cuarto del flujo por una rendija, con la paleta y las
   propiedades ocupando el resto.

   Y las tres columnas NO se recuperan en pantallas grandes, que fue el segundo
   intento: incluso en 1920 dejaban el lienzo en 1034px, todavía por debajo de lo
   que mide el diagrama. Un reparto que no funciona en ninguna resolución no es un
   reparto que necesite un punto de corte más alto.

   Así que el lienzo ocupa SIEMPRE todo el ancho —es la superficie de trabajo— y
   la paleta y las propiedades se reparten una fila debajo. Una sola disposición,
   correcta en todas las resoluciones, y el flujo se lee de una pasada. */
.v12-ds { display: grid; gap: 1rem; }

.v12-ds__paleta { padding-bottom: 1rem; }
.v12-ds__ayuda { font-size: .8125rem; color: var(--v12-gray-600); padding: 0 1.125rem; }
.v12-ds-pieza {
    display: flex; align-items: center; gap: .625rem; width: calc(100% - 2.25rem);
    margin: 0 1.125rem .5rem; padding: .625rem .75rem; text-align: left;
    background: var(--v12-white); border: 1px dashed var(--v12-gray-300);
    border-radius: var(--v12-r-md); cursor: pointer; font: inherit;
    transition: border-color var(--v12-fast) var(--v12-ease);
}
.v12-ds-pieza:hover:not(:disabled) { border-color: var(--v12-orange-400); }
.v12-ds-pieza:disabled { opacity: .55; cursor: not-allowed; }
.v12-ds-pieza--puesta { border-style: solid; }
.v12-ds-pieza > .mdi:first-child { font-size: 1.25rem; color: var(--v12-orange-500); }
.v12-ds-pieza > .mdi:last-child { margin-left: auto; color: var(--v12-gray-400); }
.v12-ds-pieza strong { display: block; font-size: .8125rem; }
.v12-ds-pieza small { display: block; font-size: .71875rem; color: var(--v12-gray-500); line-height: 1.35; }
.v12-ds__nueva { margin: .25rem 1.125rem 0; width: calc(100% - 2.25rem); }

.v12-ds__lienzo {
    position: relative; overflow-x: auto; min-height: 420px;
    /* El desplazamiento horizontal es del lienzo, nunca de la página: mover la
       pantalla entera de lado para ver el final del flujo descoloca la cabecera y
       los botones de guardar. */
    overscroll-behavior-x: contain;
    padding: 2rem 1.5rem 2.5rem;
    background-image: radial-gradient(var(--v12-gray-200) 1px, transparent 1px);
    background-size: 22px 22px;
}
/* `top/left` y no `inset: 0`: con los cuatro lados a cero el ancho lo impondría
   la caja del lienzo y el SVG no podría ser más grande que la parte visible, que
   es justo lo que necesita cuando el diagrama se desplaza. El tamaño lo pone el
   guion, del área desplazable. */
#dsAristas { position: absolute; top: 0; left: 0; pointer-events: none; }
#dsAristas path.v12-ds-arista {
    fill: none; stroke: var(--v12-gray-400); stroke-width: 2;
}
#dsAristas marker path { fill: var(--v12-gray-400); }
.v12-ds-arista--avance {
    stroke: var(--v12-orange-500) !important; stroke-dasharray: 6 5;
    animation: v12-ds-fluir 1.2s linear infinite;
}
.v12-ds-arista--descarte { stroke-dasharray: 2 4; }
.v12-ds-arista--lateral, .v12-ds-arista--vuelta { stroke-dasharray: 2 4; }
@keyframes v12-ds-fluir { to { stroke-dashoffset: -11; } }
@media (prefers-reduced-motion: reduce) {
    .v12-ds-arista--avance { animation: none; }
}

.v12-ds__fila { display: flex; align-items: center; gap: .375rem; position: relative; }
.v12-ds__fila--cadena { min-height: 150px; flex-wrap: nowrap; width: max-content; }
.v12-ds__fila--lateral { margin-top: 3.5rem; justify-content: flex-end; gap: 2rem; width: max-content; min-width: 100%; }

.v12-ds-card {
    position: relative; display: flex; flex-direction: column; align-items: center;
    gap: .125rem; min-width: 128px; max-width: 170px; padding: .875rem 1rem .75rem;
    background: var(--v12-white); border: 1.5px solid var(--v12-gray-300);
    border-radius: var(--v12-r-md); cursor: pointer; user-select: none;
    box-shadow: var(--v12-shadow-sm);
    transition: transform var(--v12-fast) var(--v12-ease), border-color var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-ds-card:hover { transform: translateY(-2px); border-color: var(--v12-gray-400); }
.v12-ds-card:focus-visible { outline: 2px solid var(--v12-orange-500); outline-offset: 2px; }
.v12-ds-card--sel { border-color: var(--v12-orange-500); box-shadow: 0 0 0 3px var(--v12-orange-50); }
.v12-ds-card--fantasma { opacity: .35; }
.v12-ds-card--pending { border-left: 4px solid var(--v12-gray-500); }
.v12-ds-card--solved { border-left: 4px solid var(--v12-ok); }
.v12-ds-card--discarded { border-left: 4px solid var(--v12-danger); }
.v12-ds-card--custom { border-style: dashed; }
.v12-ds-card__icono { font-size: 1.375rem; color: var(--v12-orange-500); }
.v12-ds-card__fija {
    position: absolute; top: .375rem; right: .5rem;
    font-size: .8125rem; color: var(--v12-gray-400);
}
.v12-ds-card__n {
    position: absolute; top: -.5625rem; left: -.5625rem;
    background: var(--v12-orange-500); color: #fff; font-size: .71875rem; font-weight: 700;
    min-width: 1.375rem; height: 1.375rem; padding: 0 .25rem; border-radius: 99px;
    display: grid; place-items: center;
}
.v12-ds-card__nombre { font-weight: 650; font-size: .8125rem; text-align: center; line-height: 1.25; }
.v12-ds-card__rol { font-size: .6875rem; text-transform: uppercase; letter-spacing: .05em; color: var(--v12-gray-500); }
.v12-ds-card__area {
    margin-top: .25rem; font-size: .71875rem; color: var(--v12-gray-700);
    background: var(--v12-gray-100); border-radius: 99px; padding: .125rem .5rem;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.v12-ds-paso { width: 26px; height: 2px; flex: none; }
.v12-ds-hueco {
    width: 18px; align-self: stretch; flex: none; border-radius: var(--v12-r-sm);
    border: 2px dashed transparent; transition: all var(--v12-fast) var(--v12-ease);
}
.v12-ds-hueco--activo { width: 64px; border-color: var(--v12-orange-500); background: var(--v12-orange-50); }

.v12-ds__props .v12-card__head { padding-top: 1rem; }
.v12-ds__props-vacio {
    text-align: center; color: var(--v12-gray-500); font-size: .8125rem; padding: 1.5rem 1.125rem;
}
.v12-ds__props-vacio .mdi { font-size: 1.75rem; display: block; margin-bottom: .375rem; }

/* Lienzo libre del diseñador: interior desplazable, cajas absolutas en vuelo. */
.v12-ds__interior { position: relative; min-height: 420px; }
.v12-ds__interior .v12-ds-card { position: absolute; margin: 0; touch-action: none; }
.v12-ds-card--vuelo {
    cursor: grabbing; transform: scale(1.04) !important;
    box-shadow: 0 12px 28px rgba(0,0,0,.16); z-index: 5;
}
.v12-ds__interior .v12-ds-card { cursor: grab; }

/* Mini-diagramas de la lista de flujos: el lenguaje del diseñador, en compacto. */
.v12-mini { padding: .875rem 1.25rem 1.25rem; overflow-x: auto; }
.v12-mini__cadena { display: flex; align-items: stretch; gap: 0; width: max-content; }
.v12-mini__etapa {
    display: flex; flex-direction: column; align-items: center; gap: .125rem;
    min-width: 108px; padding: .625rem .875rem;
    background: var(--v12-white); border: 1.5px solid var(--v12-gray-300);
    border-radius: var(--v12-r-md); text-decoration: none;
    box-shadow: var(--v12-shadow-sm);
    transition: transform var(--v12-fast) var(--v12-ease), border-color var(--v12-fast) var(--v12-ease);
}
.v12-mini__etapa:hover { transform: translateY(-2px); border-color: var(--v12-orange-400); text-decoration: none; }
.v12-mini__etapa--initial { border-left: 4px solid var(--v12-gray-500); }
.v12-mini__etapa--final { border-left: 4px solid var(--v12-ok); }
.v12-mini__etapa--rama { border-style: dashed; }
.v12-mini__etapa > .mdi { font-size: 1.125rem; color: var(--v12-orange-500); }
.v12-mini__nombre { font-size: .75rem; font-weight: 650; color: var(--v12-gray-900); text-align: center; line-height: 1.2; }
.v12-mini__n { font-size: .8125rem; font-weight: 700; color: var(--v12-gray-400); }
.v12-mini__etapa--viva .v12-mini__n { color: var(--v12-orange-600); }
.v12-mini__flecha {
    align-self: center; flex: none; width: 30px; height: 2px; position: relative;
    background: var(--v12-orange-400);
}
.v12-mini__flecha::after {
    content: ''; position: absolute; right: -1px; top: -3.5px;
    border-left: 7px solid var(--v12-orange-400);
    border-top: 4.5px solid transparent; border-bottom: 4.5px solid transparent;
}
.v12-mini__ramas { display: flex; align-items: center; gap: .25rem; margin-top: .625rem; padding-left: 2.5rem; width: max-content; }
.v12-mini__ramal {
    flex: none; width: 26px; height: 16px;
    border-left: 2px dotted var(--v12-gray-400); border-bottom: 2px dotted var(--v12-gray-400);
    border-bottom-left-radius: 10px; margin-top: -14px;
}

/* La ruta en portada: cuatro decisiones, lo que más cierra, y la salud operativa. */
.v12-ruta-hoy { margin-bottom: 1rem; }
.v12-ruta-hoy__cuerpo { display: grid; gap: 1rem; padding: 1rem 1.25rem 1.25rem; grid-template-columns: auto minmax(0,1fr) auto; align-items: start; }
@media (max-width: 1100px) { .v12-ruta-hoy__cuerpo { grid-template-columns: 1fr; } }
.v12-ruta-hoy__decisiones { display: grid; grid-template-columns: repeat(2, minmax(120px, 1fr)); gap: .5rem; }
.v12-ruta-hoy__decision {
    display: flex; flex-direction: column; align-items: center; gap: .125rem;
    padding: .75rem .5rem; border-radius: var(--v12-r-md); text-decoration: none;
    border: 1.5px solid var(--v12-gray-200); background: var(--v12-white);
    transition: transform var(--v12-fast) var(--v12-ease), border-color var(--v12-fast) var(--v12-ease);
}
.v12-ruta-hoy__decision:hover { transform: translateY(-2px); text-decoration: none; }
.v12-ruta-hoy__decision > .mdi { font-size: 1.25rem; }
.v12-ruta-hoy__decision--danger > .mdi { color: var(--v12-danger); }
.v12-ruta-hoy__decision--warn > .mdi { color: var(--v12-orange-600); }
.v12-ruta-hoy__decision--info > .mdi { color: var(--v12-gray-600); }
.v12-ruta-hoy__decision--calm > .mdi { color: var(--v12-gray-500); }
.v12-ruta-hoy__decision--danger:hover { border-color: var(--v12-danger); }
.v12-ruta-hoy__n { font-size: 1.375rem; font-weight: 700; color: var(--v12-gray-900); line-height: 1.1; }
.v12-ruta-hoy__et { font-size: .6875rem; text-transform: uppercase; letter-spacing: .06em; color: var(--v12-gray-500); font-weight: 700; }
.v12-ruta-hoy__titulo { font-size: .6875rem; text-transform: uppercase; letter-spacing: .06em; color: var(--v12-gray-500); font-weight: 700; margin: 0 0 .375rem; }
.v12-ruta-hoy__accion {
    display: flex; align-items: baseline; gap: .625rem; padding: .5rem .625rem;
    border-radius: var(--v12-r-sm); text-decoration: none;
    border: 1px solid var(--v12-gray-100); margin-bottom: .375rem; background: var(--v12-white);
}
.v12-ruta-hoy__accion:hover { border-color: var(--v12-orange-400); text-decoration: none; }
.v12-ruta-hoy__accion-titulo {
    font-weight: 600; color: var(--v12-gray-900); font-size: .875rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0;
}
.v12-ruta-hoy__accion-meta { flex: none; font-size: .75rem; color: var(--v12-gray-500); }
.v12-ruta-hoy__salud { display: flex; flex-direction: column; gap: .375rem; min-width: 210px; }
.v12-ruta-hoy__chip {
    display: flex; align-items: center; gap: .5rem; padding: .5rem .625rem;
    border-radius: var(--v12-r-sm); font-size: .8125rem; text-decoration: none;
    color: var(--v12-gray-800); border: 1px solid var(--v12-gray-200); background: var(--v12-white);
}
.v12-ruta-hoy__chip:hover { text-decoration: none; border-color: var(--v12-gray-400); }
.v12-ruta-hoy__chip--danger { border-left: 3px solid var(--v12-danger); }
.v12-ruta-hoy__chip--warn { border-left: 3px solid var(--v12-orange-500); }

/* La línea de producción: etapas grandes con stock, edad y ritmo. */
.v12-linea__flujos { display: flex; gap: .375rem; flex-wrap: wrap; margin-bottom: 1rem; }
.v12-linea { display: flex; align-items: stretch; padding: 1rem 1.25rem 1.25rem; overflow-x: auto; }
.v12-linea__flecha { margin: auto .25rem; }
.v12-linea__etapa {
    display: flex; flex-direction: column; align-items: center; gap: .25rem;
    min-width: 148px; padding: .875rem 1rem;
    background: var(--v12-white); border: 1.5px solid var(--v12-gray-300);
    border-radius: var(--v12-r-md); text-decoration: none;
    box-shadow: var(--v12-shadow-sm);
    transition: transform var(--v12-fast) var(--v12-ease), border-color var(--v12-fast) var(--v12-ease);
}
.v12-linea__etapa:hover { transform: translateY(-2px); border-color: var(--v12-orange-400); text-decoration: none; }
.v12-linea__etapa--initial { border-left: 4px solid var(--v12-gray-500); }
.v12-linea__etapa--final { border-left: 4px solid var(--v12-ok); }
.v12-linea__cabecera { font-size: .75rem; font-weight: 700; color: var(--v12-gray-700); display: flex; gap: .375rem; align-items: center; }
.v12-linea__cabecera .mdi { color: var(--v12-orange-500); }
.v12-linea__stock { font-size: 1.75rem; font-weight: 700; color: var(--v12-gray-400); line-height: 1.1; }
.v12-linea__etapa--viva .v12-linea__stock { color: var(--v12-gray-900); }
.v12-linea__edad { font-size: .71875rem; color: var(--v12-gray-500); }
.v12-linea__ritmo { font-size: .8125rem; color: var(--v12-gray-600); display: flex; align-items: center; gap: .125rem; }
.v12-linea__ritmo small { color: var(--v12-gray-400); margin-left: .125rem; }
.v12-linea__grafico { padding: .5rem 1rem 1rem; }

/* El viaje por el flujo en la ficha: escalera vertical con la etapa actual
   marcada, y la cinta métrica del SLA. */
.v12-viaje { list-style: none; margin: 0; padding: 0; }
.v12-viaje__etapa { display: flex; gap: .625rem; position: relative; padding-bottom: .875rem; }
.v12-viaje__etapa::before {
    content: ''; position: absolute; left: 11px; top: 24px; bottom: 0;
    width: 2px; background: var(--v12-gray-200);
}
.v12-viaje__etapa:last-child::before { display: none; }
.v12-viaje__punto {
    flex: none; width: 24px; height: 24px; border-radius: 99px;
    display: grid; place-items: center; font-size: .875rem;
    background: var(--v12-gray-100); color: var(--v12-gray-400);
    border: 1.5px solid var(--v12-gray-300); z-index: 1;
}
.v12-viaje__etapa--hecha .v12-viaje__punto { background: var(--v12-ok-bg); color: var(--v12-ok); border-color: var(--v12-ok); }
.v12-viaje__etapa--actual .v12-viaje__punto { background: var(--v12-orange-500); color: #fff; border-color: var(--v12-orange-500); }
.v12-viaje__etapa--actual::before { background: var(--v12-gray-200); }
.v12-viaje__cuerpo { flex: 1; min-width: 0; }
.v12-viaje__nombre { font-weight: 650; font-size: .8125rem; color: var(--v12-gray-900); display: flex; gap: .375rem; align-items: center; flex-wrap: wrap; }
.v12-viaje__etapa--futura .v12-viaje__nombre { color: var(--v12-gray-400); font-weight: 500; }
.v12-viaje__tiempo { font-size: .75rem; color: var(--v12-gray-600); margin-top: .125rem; }
.v12-viaje__tiempo .mdi { color: var(--v12-orange-500); }
.v12-viaje__entrada { font-size: .71875rem; color: var(--v12-gray-500); margin-top: .25rem; }
.v12-viaje__comentario {
    font-size: .75rem; color: var(--v12-gray-700); background: var(--v12-gray-50);
    border-left: 2px solid var(--v12-gray-300); padding: .25rem .5rem; margin-top: .125rem;
    border-radius: 0 var(--v12-r-sm) var(--v12-r-sm) 0;
}
.v12-viaje__evidencia {
    display: inline-flex; align-items: center; gap: .25rem; margin: .25rem .25rem 0 0;
    font-size: .71875rem; padding: .125rem .5rem; border-radius: 99px;
    background: var(--v12-gray-100); color: var(--v12-gray-700); text-decoration: none;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v12-viaje__evidencia:hover { background: var(--v12-orange-50); color: var(--v12-orange-600); text-decoration: none; }

.v12-slabar { padding-top: .25rem; }
.v12-slabar__pista {
    position: relative; height: 10px; border-radius: 99px;
    background: var(--v12-gray-100); overflow: visible;
}
.v12-slabar__lleno { height: 100%; border-radius: 99px; transition: width .6s var(--v12-ease); }
.v12-slabar__lleno--ok { background: var(--v12-ok); }
.v12-slabar__lleno--warn { background: var(--v12-orange-500); }
.v12-slabar__lleno--danger { background: var(--v12-danger); }
.v12-slabar__aviso {
    position: absolute; top: -3px; bottom: -3px; width: 2px;
    background: var(--v12-gray-500); border-radius: 1px;
}
.v12-slabar__pie { display: flex; justify-content: space-between; font-size: .75rem; color: var(--v12-gray-600); margin-top: .375rem; }

/* ============================================================================
   La ficha del hallazgo, en denso
   ============================================================================
   El formulario horizontal (etiqueta ancha a la izquierda, un campo por fila)
   dejaba la mitad de la pantalla en blanco. Se convierte en CUADRÍCULA con la
   etiqueta compacta ENCIMA: los campos cortos comparten fila de dos en dos y lo
   que se lee de verdad —título, descripción, solución, activos— va a lo ancho.
   Cero cambios de marcado: los ids y names del formulario son un contrato con
   vulnedit.js y con el POST, y no se tocan. */

.v12-vform {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 1.5rem;
    align-items: start;
}
.v12-vform > .form-group.row {
    display: block;
    padding: .5rem 0 .625rem;
    border-bottom: 1px solid var(--v12-gray-100);
}
.v12-vform > .form-group.row > .col-form-label,
.v12-vform > .form-group.row > [class*="col-"] {
    max-width: 100%; width: 100%; flex: none; padding-left: 0; padding-right: 0;
}
.v12-vform > .form-group.row > .col-form-label {
    font-size: .6875rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; color: var(--v12-gray-500);
    padding-top: 0; padding-bottom: .25rem;
}
/* Lo que se LEE va a lo ancho: título, escaneo (nombres largos), descripción,
   solución y la tabla de activos. Todo lo demás comparte fila. */
.v12-vform > .form-group.row:has(#title),
.v12-vform > .form-group.row:has(#scan),
.v12-vform > .form-group.row:has(#description),
.v12-vform > .form-group.row:has(#solution),
.v12-vform > .form-group.row:has(table) {
    grid-column: 1 / -1;
}
.v12-vform #description, .v12-vform #solution {
    min-height: 130px; line-height: 1.5; font-size: .875rem;
    background: var(--v12-gray-50);
}
.v12-vform #description:focus, .v12-vform #solution:focus { background: var(--v12-white); }
@media (max-width: 900px) { .v12-vform { grid-template-columns: 1fr; } }

/* =========================================================================
   Portal del operador (v12-op*)
   Reino visual propio: NOC oscuro sobre la paleta v12-chrome. No comparte
   layout con el producto — estas clases solo viven bajo body.v12-opbody.
   ========================================================================= */

.v12-opbody {
    margin: 0;
    min-height: 100vh;
    background: var(--v12-chrome-900);
    color: var(--v12-chrome-text-strong, #E8EAED);
    font-family: var(--v12-font);
}

.v12-optop {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    padding: 0.65rem 1.5rem;
    background: var(--v12-chrome-800);
    border-bottom: 1px solid var(--v12-chrome-line, #232A33);
}
.v12-optop__brand {
    font-weight: 800;
    letter-spacing: .14em;
    color: var(--v12-orange-500);
    text-decoration: none;
    font-size: 1rem;
}
.v12-optop__brand { display: inline-flex; align-items: center; gap: .6rem; }
.v12-optop__logo { height: 26px; width: auto; display: block; }
.v12-optop__brand span { color: var(--v12-chrome-text, #A8AFB8); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; font-size: .82rem; }
.v12-optop__brand:hover { color: var(--v12-orange-400); text-decoration: none; }
.v12-optop__nav { display: flex; gap: 1rem; flex: 1; }
.v12-optop__nav a { color: var(--v12-chrome-text, #A8AFB8); text-decoration: none; font-weight: 600; font-size: .9rem; }
.v12-optop__nav a:hover { color: var(--v12-orange-400); }
.v12-optop__who { display: flex; align-items: center; gap: .75rem; }
.v12-optop__name { color: var(--v12-chrome-text, #A8AFB8); font-size: .9rem; }
.v12-optop__exit { margin: 0; }

.v12-opmain { max-width: 76rem; margin: 0 auto; padding: 1.5rem; }
.v12-opmain .v12-page-title { color: #E8EAED; }
.v12-opmain .v12-page-sub { color: #A8AFB8; }

/* Login */
.v12-oplogin { min-height: 100vh; display: flex; align-items: center; justify-content: center; }
.v12-oplogin__caja {
    width: min(24rem, 92vw);
    background: var(--v12-chrome-800);
    border: 1px solid var(--v12-chrome-line, #232A33);
    border-radius: var(--v12-r-lg);
    padding: 2.5rem 2rem;
    box-shadow: var(--v12-shadow-lg);
}
.v12-oplogin__brand { text-align: center; }
.v12-oplogin__logo { height: 84px; width: auto; display: block; margin: 0 auto; }
.v12-oplogin__eyebrow { display: block; margin-top: 1rem; color: var(--v12-orange-500); font-weight: 800; letter-spacing: .28em; text-transform: uppercase; font-size: .8rem; }
.v12-oplogin__sub { text-align: center; color: #A8AFB8; margin: .5rem 0 1.75rem; font-size: .9rem; }
.v12-oplogin__form { display: grid; gap: 1rem; }
.v12-oplogin__foot { margin-top: 1.5rem; text-align: center; color: #6B7280; font-size: .78rem; }

/* Campos sobre fondo oscuro */
.v12-opbody .v12-field span { color: #A8AFB8; font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.v12-opbody .v12-input,
.v12-opbody .v12-select {
    background: var(--v12-chrome-900);
    border-color: var(--v12-chrome-line, #232A33);
    color: #E8EAED;
}
.v12-opbody .v12-input:focus { border-color: var(--v12-orange-500); }
.v12-opbody .v12-help { color: #6B7280; }

/* Tarjetas y tablas en oscuro */
.v12-opcard {
    background: var(--v12-chrome-800);
    border: 1px solid var(--v12-chrome-line, #232A33);
    color: #E8EAED;
    margin-bottom: 1.25rem;
    padding: 1.25rem 1.5rem;
}
.v12-opcard__title { font-size: .85rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: #A8AFB8; margin: 0 0 1rem; }
.v12-opbody .v12-table { color: #E8EAED; }
.v12-opbody .v12-table th { color: #8A93A0; border-color: var(--v12-chrome-line, #232A33); }
.v12-opbody .v12-table td { color: #E8EAED; border-color: var(--v12-chrome-line, #232A33); }
.v12-opbody .v12-table tbody tr:hover { background: rgba(255, 255, 255, 0.03); }
/* El «apagado» del producto usa un gris de fondo CLARO; sobre el cromado
   oscuro del portal hay que subirlo o el texto secundario queda ilegible. */
.v12-opbody .v12-muted { color: #9AA2AE; }
.v12-oplink { color: #E8EAED; font-weight: 700; text-decoration: none; }
.v12-oplink:hover { color: var(--v12-orange-400); }
.v12-opfoot { margin: 1rem 0 0; color: #6B7280; font-size: .8rem; }
.v12-opfoot code { color: #A8AFB8; }

/* Vitales */
.v12-opvitals {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .75rem;
    margin-bottom: 1rem;
}
.v12-opvital {
    background: var(--v12-chrome-800);
    border: 1px solid var(--v12-chrome-line, #232A33);
    border-radius: var(--v12-r-md);
    padding: .85rem 1rem;
    display: grid;
    gap: .15rem;
}
.v12-opvital__label { font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: #6B7280; }
.v12-opvital__value { font-size: 1.05rem; font-weight: 700; color: #E8EAED; font-variant-numeric: tabular-nums; }
.v12-opvital__par { display: block; font-size: .85rem; }
.v12-opvital__hint { font-size: .72rem; color: #6B7280; }

/* Agregados de cartera */
.v12-opsums { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.25rem; }
.v12-opsum {
    background: var(--v12-chrome-800);
    border: 1px solid var(--v12-chrome-line, #232A33);
    border-radius: var(--v12-r-pill);
    padding: .35rem .9rem;
    font-size: .85rem;
    color: #A8AFB8;
}
.v12-opsum .v12-num { color: #E8EAED; font-weight: 800; }
.v12-opsum--warn { border-color: var(--v12-warn); }
.v12-opsum--warn .v12-num { color: var(--v12-warn); }
.v12-opsum--danger { border-color: var(--v12-danger); }
.v12-opsum--danger .v12-num { color: var(--v12-danger); }

/* Ficha */
.v12-opgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); gap: 1.25rem; }
.v12-oplista { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.v12-oplista li { color: #A8AFB8; }
.v12-oplista .v12-num { color: #E8EAED; font-weight: 700; }
.v12-opacciones { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: 1.25rem; }
.v12-opaccion { display: grid; gap: .5rem; align-content: start; margin: 0; }
.v12-opcredenciales { margin-bottom: 1.25rem; }
.v12-opcredenciales__par { margin-top: .5rem; font-size: 1.05rem; }
.v12-opcredenciales__par code { background: rgba(0, 0, 0, .35); padding: .2rem .5rem; border-radius: 4px; }
.v12-opbaja { margin-bottom: 1.25rem; }
.v12-opbaja__forma { display: inline-block; margin: 0 0 0 .75rem; }
.v12-opalta__form { display: grid; gap: 1.1rem; max-width: 28rem; }

/* Marca del cliente (white-label) en la ficha del operador */
.v12-opmarca { display: grid; gap: 1rem; }
.v12-opmarca__campos { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 1rem; align-items: end; }
.v12-opmarca__color { height: 2.6rem; padding: .2rem; cursor: pointer; }
.v12-opmarca__actual { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.v12-opmarca__label { color: #9AA2AE; font-size: .85rem; }
.v12-opmarca__logo { max-height: 44px; max-width: 200px; background: #fff; padding: 6px 10px; border-radius: var(--v12-r-sm); }
.v12-opbody .v12-check { color: #9AA2AE; display: inline-flex; align-items: center; gap: .4rem; }

/* White-label: logo del cliente en el login del producto */
.v12-login__chip { display: inline-block; background: #fff; padding: 14px 20px; border-radius: var(--v12-r-lg); box-shadow: var(--v12-shadow-md); }
.v12-login__clientlogo { display: block; max-width: 200px; max-height: 72px; width: auto; height: auto; }
/* En el formulario (fondo claro) el logo del cliente va sin chip */
.v12-login__logo--mobile { object-fit: contain; }

/* ============================================================================
   Mapa de riesgo por negocio (inicio)
   ============================================================================
   Tres bandas y no cuatro: el validador de la guía rechaza naranja y amarillo
   juntos (ΔE 9,3, indistinguibles incluso con visión normal). Las tres que
   quedan pasan, pero la separación bajo daltonismo queda en el mínimo, así que
   el color NUNCA va solo: cada punto lleva su nombre y la leyenda lleva icono. */

/* EL REPARTO DEL ANCHO.
   Antes eran dos fracciones —1,35 y 1— y el resultado era el peor de los dos
   mundos: la columna del mapa quedaba mucho más ancha que el dibujo, que tiene
   tope, así que sobraba un pasillo vacío EN MEDIO de los dos, y el panel de la
   derecha se estiraba hasta ser una caja enorme con cuatro cifras y aire.

   Ahora la columna del mapa vale exactamente lo que mide el mapa (`auto`), el
   panel tiene un ancho de lectura acotado, y el par se centra en la tarjeta. El
   espacio que sobra queda repartido a los dos lados por igual, que se lee como
   una decisión y no como un hueco. */
.v12-riesgo__cuerpo {
    display: grid;
    /* El tope del mapa se declara AQUÍ, en la pista, y no como `auto`: con `auto`
       el ancho de la columna depende del contenido y el del SVG depende de la
       columna —`width: 100%`—, así que el navegador resolvía el círculo por lo
       bajo y el mapa salía encogido a la mitad. Con la pista acotada a 40rem
       (los mismos 640px del tope del SVG) el mapa ocupa lo que le toca. */
    grid-template-columns: minmax(20rem, 40rem) minmax(18rem, 30rem);
    justify-content: center;
    /* Que el panel mida lo que ocupa su contenido y no la altura del mapa. */
    align-items: start;
    gap: 1.25rem;
    padding: 0 1.25rem 1.25rem;
}
@media (max-width: 1199px) {
    /* Sin sitio para los dos, manda el mapa y el panel pasa debajo a todo lo
       ancho: partirlo en dos columnas estrechas no deja leer ninguna. */
    .v12-riesgo__cuerpo { grid-template-columns: minmax(0, 1fr); }
}

/* EL ANCHO DEL MAPA SE ACOTA, y el tope no es un gusto: dentro de un SVG con
   viewBox la tipografía va en unidades del sistema de coordenadas y se estira con
   el contenedor, así que un mapa sin tope acaba con rótulos gigantes. Con 640px,
   una unidad ≈ 4,8px.

   Al subir el tope de 560 a 640 se bajaron EN LA MISMA PROPORCIÓN todos los
   tamaños en unidades —tipografía, radios y trazos— para que en pantalla midan lo
   mismo que antes. Lo que crece es el plano: los puntos tienen más sitio entre sí
   y caben más nombres sin pisarse. Si se vuelve a mover este tope hay que mover
   con él esos tamaños y las distancias del colocador de rótulos en
   Home/Index.phtml, que están en las mismas unidades. */
.v12-riesgo__mapa svg { width: 100%; max-width: 640px; height: auto; overflow: visible; }

/* Pestañas del mapa: el mismo plano visto por proceso, por servicio o por
   activo. Las tres capas llegan ya dibujadas y la pestaña sólo enseña una, así
   que cambiar de vista es instantáneo y no hay estado que pueda quedar a medias.

   Es una barra de pestañas de verdad —`role="tablist"`— y no tres botones: con
   lector de pantalla se anuncia cuál está activa, y las flechas mueven entre
   ellas como en cualquier otra pestaña del sistema. */
.v12-riesgo__tabs {
    display: flex; gap: .25rem; flex-wrap: wrap;
    margin: -.25rem 1.25rem .75rem;
    border-bottom: 1px solid var(--v12-gray-200);
}
.v12-riesgo__tab {
    appearance: none; background: none; border: 0;
    padding: .5rem .875rem; margin-bottom: -1px;
    font-size: .8125rem; font-weight: 600; color: var(--v12-gray-500);
    border-bottom: 2px solid transparent;
    cursor: pointer;
    transition: color var(--v12-fast) var(--v12-ease),
                border-color var(--v12-fast) var(--v12-ease);
}
.v12-riesgo__tab:hover { color: var(--v12-gray-800); }
.v12-riesgo__tab[aria-selected="true"] {
    color: var(--v12-fill-accent);
    border-bottom-color: var(--v12-fill-accent);
}
.v12-riesgo__tab em { margin-right: .375rem; }
.v12-riesgo__tab .v12-riesgo__cuenta {
    margin-left: .375rem; font-weight: 500; color: var(--v12-gray-400);
}

/* La capa que no toca se apaga por completo: `display:none` y no una opacidad,
   porque un punto invisible pero presente sigue recibiendo el tabulador y el
   teclado saltaría a negocios que no están en pantalla. */
.v12-capa[hidden] { display: none; }

/* Al entrar una capa, sus puntos aparecen escalonados desde el centro del punto:
   el ojo sigue el movimiento y entiende que el plano es el mismo y lo que cambió
   son las marcas. Se respeta a quien pidió menos movimiento. */
@keyframes v12-punto-entra {
    from { opacity: 0; transform: scale(.6); }
    to   { opacity: 1; transform: scale(1); }
}
.v12-capa--entra .v12-punto {
    animation: v12-punto-entra var(--v12-normal, .24s) var(--v12-ease) both;
    transform-box: fill-box; transform-origin: center;
}
@media (prefers-reduced-motion: reduce) {
    .v12-capa--entra .v12-punto { animation: none; }
}

/* Cuando la vista trae más marcas de las que caben legibles, se dice cuántas se
   están enseñando y de cuántas. Un recorte silencioso se lee como «esto es
   todo», que es justo lo que no es. */
.v12-riesgo__recorte {
    margin: .5rem 0 0; font-size: .75rem; color: var(--v12-gray-500);
}

/* Las cuatro bandas de la matriz: verde → amarillo → naranja → rojo.
   Elegidas MIDIENDO con el validador de la guía, no a ojo: su luminosidad baja
   de forma monótona y con paso amplio, que es lo que permite que con daltonismo
   rojo-verde las celdas se sigan ordenando por claridad. Los tramos van
   rotulados, así que el color nunca es lo único que informa.

   SIN `fill-opacity`, a propósito. Antes se pintaba al 58 % sobre blanco y lo
   que se validaba no era lo que se veía: el rojo del extremo llegaba a la
   pantalla convertido en un rosa apagado. Ahora el color declarado es el color
   compuesto, así que la medición vale para lo que hay en el monitor. */
.v12-q--b0  { fill: #D0EAD9; }   /* bajo y remoto */
.v12-q--b1  { fill: #EBC934; }   /* el centro, amarillo */
.v12-q--b2  { fill: #E88E2E; }
.v12-q--b3  { fill: #C62D20; }   /* muy alto y probable */

.v12-riesgo__eje   { stroke: var(--v12-gray-300); stroke-width: .44; }
.v12-riesgo__guia  { stroke: var(--v12-white); stroke-width: .53; opacity: .85; }
.v12-riesgo__rot   { font-size: 2.45px; fill: var(--v12-gray-500); letter-spacing: .04em; }
.v12-riesgo__tramo { font-size: 2.1px; fill: var(--v12-gray-500); }
/* La letra pequeña que explica el eje: recesiva a propósito, está para
   quien pregunta «¿control de qué?», no para competir con el gráfico. */
.v12-riesgo__pie   { font-size: 1.9px; fill: var(--v12-gray-400); }

.v12-punto { cursor: pointer; }
.v12-punto__halo { fill: transparent; }
.v12-punto__dot  { stroke: var(--v12-white); stroke-width: .96; transition: r var(--v12-fast) var(--v12-ease); }
/* Reborde blanco POR DEBAJO del texto (`paint-order: stroke`): con las bandas
   al color pleno, un nombre podía caer sobre el rojo del extremo y perderse.
   Así el rótulo se lee igual sobre cualquiera de las cuatro. */
.v12-punto__txt  {
    font-size: 2.36px; fill: var(--v12-gray-900); font-weight: 600;
    paint-order: stroke; stroke: var(--v12-white); stroke-width: .96;
    stroke-linejoin: round;
}
.v12-punto__kev  { fill: none; stroke: var(--v12-gray-900); stroke-width: .61; stroke-dasharray: 1.4 1.2; opacity: .75; }

.v12-punto--critico .v12-punto__dot { fill: #B3261E; }
.v12-punto--medio   .v12-punto__dot { fill: #E07C00; }
.v12-punto--bajo    .v12-punto__dot { fill: #1F8A54; }

.v12-punto:hover .v12-punto__dot,
.v12-punto:focus-visible .v12-punto__dot,
.v12-punto--activo .v12-punto__dot { r: 3.7; }

/* El navegador dibuja SU anillo de foco sobre un <g tabindex>, y en Chrome es un
   trazo azul grueso que tapaba el punto y su rótulo. Se apaga en las dos
   pseudoclases —:focus y :focus-visible— porque apagar sólo una lo deja salir por
   la otra, y se sustituye por un aro propio, fino y del color de la marca, que
   señala sin esconder. */
.v12-punto:focus,
.v12-punto:focus-visible { outline: none; }

.v12-punto__anillo {
    fill: none;
    stroke: var(--v12-fill-accent);
    stroke-width: 0;
    transition: stroke-width var(--v12-fast) var(--v12-ease);
}
.v12-punto:focus-visible .v12-punto__anillo,
.v12-punto--activo .v12-punto__anillo { stroke-width: .96; }

.v12-riesgo__leyenda {
    display: grid;
    grid-template-columns: 5.5rem auto 1fr auto;
    align-items: center; gap: .25rem .5rem;
    margin: .875rem 0 0;
    font-size: .75rem; color: var(--v12-gray-500);
}
.v12-escala {
    grid-column: 1; height: 8px; border-radius: 99px;
    background: linear-gradient(90deg, #D0EAD9, #EBC934, #E88E2E, #C62D20);
    border: 1px solid var(--v12-gray-200);
}
.v12-escala__rot--fin { justify-self: start; }
.v12-escala__kev { grid-column: 4; display: inline-flex; align-items: center; gap: .3125rem; }
.v12-lg { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.v12-lg--kev { border: 1.5px dashed var(--v12-gray-900); background: transparent; }

.v12-riesgo__detalle {
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    background: var(--v12-gray-50);
    padding: 1rem;
    /* Mide lo que ocupa su contenido. Antes se estiraba a la altura del mapa y
       quedaba una caja enorme con cuatro cifras arriba y el resto vacío. Un
       mínimo para que el estado inicial no sea una franja fina. */
    min-height: 13rem;
    display: flex;
    flex-direction: column;
}
/* El estado vacío se centra: así se lee como una invitación y no como un panel
   que se quedó a medio cargar. */
.v12-riesgo__vacio {
    color: var(--v12-gray-500); font-size: .8125rem;
    margin: auto; text-align: center; max-width: 22ch; line-height: 1.5;
}
.v12-riesgo__nombre { font-size: 1rem; font-weight: 700; color: var(--v12-gray-900); margin: 0 0 .125rem; }
.v12-riesgo__banda {
    display: inline-flex; align-items: center; gap: .3125rem;
    font-size: .75rem; font-weight: 600; margin-bottom: .75rem;
}
.v12-riesgo__banda--critico { color: #B3261E; }
.v12-riesgo__banda--medio   { color: #A85C00; }
.v12-riesgo__banda--bajo    { color: #1F8A54; }

.v12-riesgo__cifras { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .625rem; margin: 0 0 .875rem; }
.v12-riesgo__cifra { background: var(--v12-white); border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-sm); padding: .5rem .625rem; }
.v12-riesgo__cifra b { display: block; font-size: 1.125rem; color: var(--v12-gray-900); font-variant-numeric: tabular-nums; }
.v12-riesgo__cifra span { font-size: .6875rem; color: var(--v12-gray-500); }
.v12-riesgo__nota { font-size: .75rem; color: var(--v12-gray-500); margin: .5rem 0 0; }

/* ============================================================================
   Ficha de riesgo — proceso de negocio y servicio

   Es el destino de un punto del mapa, así que reutiliza sus piezas a propósito:
   las cuatro bandas (.v12-q--b0..b3), la barra de severidades y los chips de
   severidad. Que se lea como la misma herramienta y no como otra pantalla.

   EL MOVIMIENTO ENTRA UNA VEZ, AL CARGAR, y no se repite: las secciones aparecen
   en cascada de arriba abajo, que es el orden en que se leen. Nada se mueve
   después —un panel que sigue animándose mientras alguien lee una cifra
   estorba— y todo se apaga con `prefers-reduced-motion`.
   ========================================================================== */

.v12-ficha { display: grid; gap: 1.25rem; }

@keyframes v12-ficha-entra {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: none; }
}
.v12-ficha__paso {
    animation: v12-ficha-entra .46s var(--v12-ease) both;
    /* La cascada: cada sección arranca un poco después que la anterior. */
    animation-delay: calc(var(--paso, 0) * .07s);
}

/* ---------------------------------------------------------------- cabecera */

.v12-ficha__hero {
    position: relative; overflow: hidden;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 1.75rem;
    align-items: center;
    padding: 1.5rem 1.75rem;
}
/* Un velo de color según la banda, muy leve y sólo arriba: da carácter a la
   ficha sin que ningún texto pierda contraste, porque el tinte se queda por
   encima del blanco y por debajo del 6 %. */
.v12-ficha__hero::before {
    content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
}
.v12-ficha__hero--critico::before { background: linear-gradient(90deg, var(--sev-critical), #E8836B); }
.v12-ficha__hero--medio::before   { background: linear-gradient(90deg, var(--sev-high), #F2C879); }
.v12-ficha__hero--bajo::before    { background: linear-gradient(90deg, var(--v12-ok), #7FCFA3); }

@media (max-width: 899px) { .v12-ficha__hero { grid-template-columns: 1fr; } }

.v12-ficha__tipo {
    display: flex; align-items: center; gap: .375rem; flex-wrap: wrap;
    margin: 0 0 .375rem;
    font-size: .6875rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: var(--v12-gray-500);
}
.v12-ficha__miga::before { content: "·"; margin: 0 .375rem; color: var(--v12-gray-300); }
.v12-ficha__miga a { font-weight: 600; letter-spacing: .04em; }

.v12-ficha__nombre {
    margin: 0 0 .625rem; font-size: 1.75rem; line-height: 1.15;
    font-weight: 700; color: var(--v12-gray-900); letter-spacing: -.01em;
}

/* EL VEREDICTO. Es lo primero que se lee y por eso va con cuerpo de titular
   pequeño y no de párrafo: en un comité, una ficha que empieza por una rejilla de
   números hace que cada lector saque su propia conclusión. */
.v12-ficha__veredicto {
    display: flex; align-items: flex-start; gap: .5rem;
    margin: 0 0 .75rem; padding: .625rem .75rem;
    border-radius: var(--v12-r-md);
    font-size: .9375rem; font-weight: 600; line-height: 1.45;
}
.v12-ficha__veredicto .mdi { font-size: 1.125rem; line-height: 1.3; flex: none; }
.v12-ficha__veredicto--critico { color: #7A1A14; background: #FBEBEA; }
.v12-ficha__veredicto--medio   { color: #7A4300; background: #FDF1E0; }
.v12-ficha__veredicto--bajo    { color: #145C38; background: var(--v12-ok-bg); }

.v12-ficha__desc {
    margin: 0 0 .75rem; color: var(--v12-gray-600); font-size: .875rem;
    max-width: 70ch; line-height: 1.6;
}
.v12-ficha__desc--falta { font-style: italic; color: var(--v12-gray-500); }

.v12-ficha__meta {
    display: flex; align-items: center; gap: .25rem 1rem; flex-wrap: wrap;
    margin: 0; font-size: .8125rem; color: var(--v12-gray-600);
}
.v12-ficha__meta > span { display: inline-flex; align-items: center; gap: .3125rem; }
.v12-ficha__editar { display: inline-flex; align-items: center; gap: .25rem; font-weight: 600; }
/* El PDF, con más peso que «editar»: es lo que se hace para llevarse la ficha a
   una reunión, y en una ficha de negocio eso pasa más que corregir el nombre. */
.v12-ficha__pdf {
    display: inline-flex; align-items: center; gap: .3125rem;
    padding: .3125rem .625rem; margin-left: auto;
    font-size: .75rem; font-weight: 700;
    color: var(--v12-fill-accent);
    border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-md);
    transition: border-color var(--v12-fast) var(--v12-ease),
                background var(--v12-fast) var(--v12-ease);
}
.v12-ficha__pdf:hover {
    border-color: var(--v12-fill-accent); background: var(--v12-orange-50);
    text-decoration: none;
}

/* Las dos medidas, separadas y rotuladas: el anillo es el riesgo calculado y el
   sello es la posición en el plano. Juntarlas en un número obligaría a elegir una
   y perder la otra. */
.v12-ficha__medidas { display: flex; align-items: flex-start; gap: 1.25rem; }
@media (max-width: 599px) { .v12-ficha__medidas { flex-wrap: wrap; } }

.v12-ficha__anillo, .v12-ficha__mini { margin: 0; text-align: center; }
.v12-ficha__anillo svg { width: 124px; height: 124px; }
.v12-ficha__anillo figcaption, .v12-ficha__mini figcaption {
    margin-top: .375rem; font-size: .6875rem; color: var(--v12-gray-500);
    letter-spacing: .04em; text-transform: uppercase; font-weight: 600;
}
.v12-ficha__mini figcaption small {
    display: block; margin-top: .1875rem;
    font-size: .6875rem; font-weight: 400; letter-spacing: 0;
    text-transform: none; color: var(--v12-gray-400);
}

.v12-anillo__fondo { fill: none; stroke: var(--v12-gray-100); stroke-width: 10; }
.v12-anillo__trazo {
    fill: none; stroke-width: 10; stroke-linecap: round;
    /* Arranca a las doce y avanza en el sentido del reloj. */
    transform: rotate(-90deg); transform-origin: 60px 60px;
    stroke-dasharray: var(--tramo) var(--vuelta);
    animation: v12-anillo-crece 1s var(--v12-ease) .15s both;
}
@keyframes v12-anillo-crece {
    from { stroke-dasharray: 0 var(--vuelta); }
    to   { stroke-dasharray: var(--tramo) var(--vuelta); }
}
.v12-anillo__trazo--critico { stroke: var(--sev-critical); }
.v12-anillo__trazo--medio   { stroke: var(--sev-high); }
.v12-anillo__trazo--bajo    { stroke: var(--v12-ok); }
.v12-anillo__n {
    font-size: 30px; font-weight: 700; fill: var(--v12-gray-900);
    font-variant-numeric: tabular-nums;
}
.v12-anillo__de { font-size: 10px; fill: var(--v12-gray-400); letter-spacing: .06em; }

.v12-ficha__mini svg {
    width: 124px; height: 124px;
    border-radius: var(--v12-r-sm); overflow: hidden;
}
/* La celda donde cae el negocio se marca con un borde, no con otro color: el
   color ya significa riesgo y pintarla distinta rompería la escala. */
.v12-mini__aqui { stroke: var(--v12-gray-900); stroke-width: 1.6; }
.v12-mini__punto { fill: var(--v12-gray-900); stroke: var(--v12-white); stroke-width: 2; }
/* Un latido lento y una sola vez: señala dónde mirar al entrar y se aparta. */
.v12-mini__pulso {
    fill: none; stroke: var(--v12-gray-900); stroke-width: 2;
    animation: v12-mini-latido 1.6s var(--v12-ease) .4s 2;
    transform-box: fill-box; transform-origin: center;
}
@keyframes v12-mini-latido {
    from { opacity: .55; transform: scale(1); }
    to   { opacity: 0; transform: scale(2.6); }
}

/* ------------------------------------------------------------------ cifras */

.v12-ficha__cifras {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
    gap: .75rem;
}
.v12-ficha__cifra {
    position: relative;
    display: block;
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    padding: .875rem 1rem;
    border-top: 3px solid var(--v12-gray-300);
    transition: transform var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease),
                border-color var(--v12-fast) var(--v12-ease);
}
.v12-ficha__cifra--critico { border-top-color: var(--sev-critical); }
.v12-ficha__cifra--aviso   { border-top-color: var(--sev-high); }
/* Un cero se apaga: es una buena noticia, no un dato que reclame atención. */
.v12-ficha__cifra--cero { border-top-color: var(--v12-gray-200); }
.v12-ficha__cifra--cero b { color: var(--v12-gray-400); }

a.v12-ficha__cifra:hover {
    transform: translateY(-2px);
    box-shadow: var(--v12-shadow-md);
    border-color: var(--v12-gray-300);
    text-decoration: none;
}
.v12-ficha__cifraIcono {
    position: absolute; top: .75rem; right: .875rem;
    font-size: 1.125rem; color: var(--v12-gray-300);
}
.v12-ficha__cifraIr {
    position: absolute; bottom: .75rem; right: .875rem;
    font-size: .875rem; color: var(--v12-gray-300);
    opacity: 0; transition: opacity var(--v12-fast) var(--v12-ease);
}
a.v12-ficha__cifra:hover .v12-ficha__cifraIr { opacity: 1; }
.v12-ficha__cifra b {
    display: block; font-size: 1.75rem; font-weight: 700; color: var(--v12-gray-900);
    font-variant-numeric: tabular-nums; line-height: 1.1;
}
.v12-ficha__cifra span { font-size: .75rem; color: var(--v12-gray-500); line-height: 1.4; }

.v12-ficha__rejilla {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(23rem, 1fr));
    gap: 1.25rem;
}

/* --------------------------------------------------------------- evolución */

.v12-ficha__cabSerie {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .75rem; flex-wrap: wrap; margin-bottom: .5rem;
}
.v12-ficha__periodo { font-size: .75rem; color: var(--v12-gray-400); }

.v12-ficha__serie { position: relative; padding-left: 2rem; }
/* Aire para que el rótulo de la marca más baja no toque las fechas. */
.v12-ficha__serie .v12-chart__axis { margin-top: .625rem; }
.v12-ficha__serie svg { width: 100%; height: 160px; display: block; }
.v12-ficha__area { fill: url(#v12FichaFill); stroke: none; }
.v12-ficha__ref { stroke: var(--v12-gray-200); stroke-width: .3; stroke-dasharray: 1 1.5; }
.v12-ficha__linea {
    fill: none; stroke: var(--sev-high); stroke-width: 1.8;
    stroke-linejoin: round; stroke-linecap: round;
    /* Sin esto, el trazo se estira con el viewBox y sale más gordo en horizontal
       que en vertical. */
    vector-effect: non-scaling-stroke;
    stroke-dasharray: 1000; stroke-dashoffset: 1000;
    animation: v12-ficha-traza 1.2s var(--v12-ease) .25s forwards;
}
@keyframes v12-ficha-traza { to { stroke-dashoffset: 0; } }

/* Los rótulos de la escala van FUERA del SVG: dentro, con
   `preserveAspectRatio="none"`, la tipografía se estiraría. */
.v12-ficha__refRot {
    position: absolute; left: 0; top: 0; width: 2rem; height: 160px;
    display: flex; flex-direction: column; justify-content: space-between;
    padding: 0 .375rem calc(160px * 6 / 46) 0;
    text-align: right; font-size: .625rem; color: var(--v12-gray-400);
    font-variant-numeric: tabular-nums;
}

/* Sólo tres marcas —primera, última y la peor—, en HTML y no dentro del SVG por
   lo mismo: un círculo en un viewBox estirado sale ovalado.
   
   La capa ocupa exactamente el área del gráfico, así que cada marca se coloca con
   un `left` en tanto por ciento y nada más. */
.v12-ficha__capaMarcas {
    position: absolute; left: 2rem; right: 0; top: 0; height: 160px;
    pointer-events: none;
}
.v12-ficha__marcaSerie {
    position: absolute;
    left: var(--x);
    top: var(--y);
    transform: translate(-50%, -50%);
    pointer-events: auto;
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--sev-high); border: 2px solid var(--v12-white);
    box-shadow: var(--v12-shadow-sm);
}
.v12-ficha__marcaSerie--peor { background: var(--sev-critical); }
.v12-ficha__marcaSerie b {
    position: absolute; bottom: 130%; left: 50%; transform: translateX(-50%);
    font-size: .6875rem; font-weight: 700; color: var(--v12-gray-700);
    background: var(--v12-white); padding: 0 .25rem; border-radius: var(--v12-r-sm);
    white-space: nowrap;
}

.v12-ficha__nota { margin: .75rem 0 0; font-size: .75rem; color: var(--v12-gray-500); line-height: 1.55; }
.v12-ficha__sub {
    margin: 1.25rem 0 .5rem; font-size: .75rem; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--v12-gray-500);
}

/* ------------------------------------------------------- plazo y exposición */

.v12-ficha__barra {
    display: flex; height: 14px; border-radius: var(--v12-r-pill);
    overflow: hidden; background: var(--v12-gray-100);
}
.v12-ficha__tramo {
    display: block; height: 100%; width: var(--w);
    /* Crece desde cero al entrar, para que se lea como un reparto y no como una
       imagen fija. */
    animation: v12-ficha-crece .8s var(--v12-ease) .2s both;
}
@keyframes v12-ficha-crece { from { width: 0; } to { width: var(--w); } }
.v12-ficha__tramo--ok    { background: var(--v12-ok); }
.v12-ficha__tramo--aviso { background: var(--sev-high); }
.v12-ficha__tramo--mal   { background: var(--sev-critical); }

.v12-ficha__leyenda {
    list-style: none; margin: .75rem 0 0; padding: 0;
    display: flex; flex-wrap: wrap; gap: .25rem 1.25rem;
    font-size: .75rem; color: var(--v12-gray-600);
}
.v12-ficha__leyenda li { display: inline-flex; align-items: center; gap: .375rem; }
.v12-ficha__leyenda b { color: var(--v12-gray-900); font-variant-numeric: tabular-nums; }
.v12-ficha__llave { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.v12-ficha__llave--ok    { background: var(--v12-ok); }
.v12-ficha__llave--aviso { background: var(--sev-high); }
.v12-ficha__llave--mal   { background: var(--sev-critical); }

.v12-ficha__expo { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.v12-ficha__expoItem {
    display: flex; justify-content: space-between; align-items: center; gap: .75rem;
    padding: .625rem .75rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-gray-50);
    font-size: .8125rem;
}
/* Lo expuesto a internet se marca: es el tramo que cambia la decisión. */
.v12-ficha__expoItem--publico { border-color: #F5DFC0; background: #FDF9F2; }
.v12-ficha__expoRot { display: inline-flex; align-items: center; gap: .375rem; color: var(--v12-gray-700); font-weight: 600; }
.v12-ficha__expoCifra { color: var(--v12-gray-500); font-size: .75rem; }
.v12-ficha__expoCifra b { color: var(--v12-gray-900); }

/* -------------------------------------------------------------- componentes */

.v12-ficha__tablaEnv { overflow-x: auto; padding: 0 1.25rem 1.25rem; }
.v12-ficha__tabla { width: 100%; border-collapse: collapse; font-size: .8125rem; }
.v12-ficha__tabla th {
    text-align: left; padding: .5rem .625rem;
    font-size: .625rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
    color: var(--v12-gray-400); border-bottom: 1px solid var(--v12-gray-200);
    white-space: nowrap;
}
.v12-ficha__tabla td { padding: .75rem .625rem; border-bottom: 1px solid var(--v12-gray-100); vertical-align: middle; }
.v12-ficha__tabla tbody tr { transition: background var(--v12-fast) var(--v12-ease); }
.v12-ficha__tabla tbody tr:hover { background: var(--v12-gray-50); }
.v12-ficha__col--n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.v12-ficha__comp { font-weight: 650; }
.v12-ficha__fqdn { display: block; font-size: .6875rem; color: var(--v12-gray-400); }
.v12-ficha__sinDeclarar { font-size: .75rem; color: var(--v12-gray-400); font-style: italic; }

.v12-ficha__crit {
    display: inline-block; font-size: .6875rem; font-weight: 700;
    padding: .1875rem .5rem; border-radius: var(--v12-r-pill);
    border: 1px solid transparent; white-space: nowrap;
}
.v12-ficha__crit--alta  { color: var(--sev-critical); background: #FBEBEA; border-color: #F3D3D1; }
.v12-ficha__crit--media { color: #A85C00; background: #FDF1E0; border-color: #F5DFC0; }
.v12-ficha__crit--baja  { color: #2C5C86; background: #EAF2F9; border-color: #CFE0EE; }

.v12-ficha__expoChip {
    display: inline-flex; align-items: center; gap: .25rem;
    font-size: .75rem; color: var(--v12-gray-600); white-space: nowrap;
}
.v12-ficha__expoChip--publico { color: #A85C00; font-weight: 600; }

.v12-ficha__riesgo { display: inline-flex; align-items: center; gap: .5rem; min-width: 8.5rem; }
.v12-ficha__riesgo .v12-sevbar { width: 5.5rem; }
.v12-ficha__riesgo b { font-variant-numeric: tabular-nums; }
.v12-ficha__limpio { display: inline-flex; align-items: center; gap: .25rem; font-size: .75rem; color: var(--v12-ok); }
.v12-ficha__marcas { display: flex; gap: .3125rem; margin-top: .3125rem; flex-wrap: wrap; }
.v12-ficha__marca {
    font-size: .625rem; font-weight: 700; letter-spacing: .03em;
    padding: .125rem .375rem; border-radius: var(--v12-r-sm);
    border: 1px solid transparent; white-space: nowrap;
}
.v12-ficha__marca--kev     { color: var(--sev-critical); background: #FBEBEA; border-color: #F3D3D1; }
.v12-ficha__marca--vencido { color: #8A2C22; background: #FBEDE9; border-color: #F0D2CA; }
.v12-ficha__marca--aviso   { color: #A85C00; background: #FDF1E0; border-color: #F5DFC0; }

/* -------------------------------------------------------- áreas y vecindad */

.v12-ficha__areas { list-style: none; margin: 0; padding: 0; display: grid; gap: .75rem; }
.v12-ficha__areas li {
    display: grid; grid-template-columns: minmax(0, 1fr) 6rem auto;
    align-items: center; gap: .625rem; font-size: .8125rem;
}
.v12-ficha__areaRot { color: var(--v12-gray-800); font-weight: 600; min-width: 0; }
.v12-ficha__areaRot small { display: block; font-weight: 400; font-size: .6875rem; color: var(--v12-gray-400); }
.v12-ficha__areaBarra { height: 8px; border-radius: var(--v12-r-pill); background: var(--v12-gray-100); overflow: hidden; }
.v12-ficha__areaBarra i {
    display: block; height: 100%; width: var(--w); background: var(--v12-fill-accent);
    animation: v12-ficha-crece .8s var(--v12-ease) .25s both;
}
.v12-ficha__areaCifra { text-align: right; white-space: nowrap; }
.v12-ficha__areaCifra b { font-variant-numeric: tabular-nums; color: var(--v12-gray-900); }
.v12-ficha__areaCifra em { display: block; font-size: .6875rem; font-style: normal; color: var(--sev-critical); }

.v12-ficha__vecinos { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.v12-ficha__vecinos a {
    display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center; gap: .75rem;
    padding: .75rem .875rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-white);
    transition: border-color var(--v12-fast) var(--v12-ease),
                transform var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-ficha__vecinos a:hover {
    border-color: var(--v12-fill-accent);
    /* Un empujón mínimo: dice «esto lleva a otro sitio» sin dar un salto. */
    transform: translateX(3px);
    box-shadow: var(--v12-shadow-sm);
    text-decoration: none;
}
.v12-ficha__vecinoTxt { min-width: 0; }
.v12-ficha__vecinoN { display: block; font-weight: 650; color: var(--v12-gray-900); }
.v12-ficha__vecinoD { display: block; font-size: .6875rem; color: var(--v12-gray-500); }
.v12-ficha__vecinoR {
    font-weight: 700; font-variant-numeric: tabular-nums; color: var(--v12-gray-700);
    font-size: 1rem;
}

/* ----------------------------------------------------------------- hallazgos */

.v12-ficha__hallazgos { list-style: none; margin: 0; padding: 0 1.25rem 1.25rem; display: grid; gap: .5rem; }
.v12-ficha__hallazgos li {
    display: grid; grid-template-columns: 5.75rem minmax(0, 1fr) auto auto;
    align-items: center; gap: .875rem;
    padding: .625rem .75rem;
    border: 1px solid var(--v12-gray-100); border-radius: var(--v12-r-md);
    font-size: .8125rem;
    transition: border-color var(--v12-fast) var(--v12-ease);
}
.v12-ficha__hallazgos li:hover { border-color: var(--v12-gray-200); }
@media (max-width: 767px) {
    .v12-ficha__hallazgos li { grid-template-columns: minmax(0, 1fr) auto; }
}
.v12-ficha__hTit { display: block; color: var(--v12-gray-900); font-weight: 600; }
.v12-ficha__hMeta { display: block; font-size: .6875rem; color: var(--v12-gray-500); }
.v12-ficha__hMeta code { font-size: .6875rem; color: var(--v12-gray-600); }
.v12-ficha__hMarcas { display: flex; gap: .3125rem; flex-wrap: wrap; }
.v12-ficha__hEpss {
    font-variant-numeric: tabular-nums; font-weight: 700; color: var(--v12-gray-800);
    white-space: nowrap;
}
.v12-ficha__pie { padding: 0 1.25rem 1.25rem; }

@media (prefers-reduced-motion: reduce) {
    .v12-ficha__paso,
    .v12-ficha__linea,
    .v12-ficha__tramo,
    .v12-anillo__trazo,
    .v12-mini__pulso,
    .v12-ficha__areaBarra i { animation: none; }
    .v12-ficha__linea { stroke-dashoffset: 0; }
    .v12-mini__pulso { display: none; }
    .v12-ficha__vecinos a:hover,
    a.v12-ficha__cifra:hover { transform: none; }
}

/* ============================================================================
   Buscador de vulnerabilidades en dos alturas

   Una caja de texto y, detrás de un botón, los catorce filtros. La búsqueda que
   se hace nueve de cada diez veces es por nombre, y para eso no hace falta
   atravesar una rejilla de selectores vacíos.
   ========================================================================== */

.v12-busca {
    display: flex; align-items: center; gap: .625rem; flex-wrap: wrap;
}
.v12-busca__campo {
    position: relative; display: flex; align-items: center;
    flex: 1 1 22rem; min-width: 0; margin: 0;
}
.v12-busca__campo > .mdi {
    position: absolute; left: .75rem; color: var(--v12-gray-400); font-size: 1.125rem;
    pointer-events: none;
}
.v12-busca__campo input {
    width: 100%; padding: .625rem .875rem .625rem 2.375rem;
    font-size: .875rem; color: var(--v12-gray-900);
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-md);
    transition: border-color var(--v12-fast) var(--v12-ease),
                box-shadow var(--v12-fast) var(--v12-ease);
}
.v12-busca__campo input:focus {
    outline: none;
    border-color: var(--v12-fill-accent);
    box-shadow: 0 0 0 3px var(--v12-orange-50);
}
/* La etiqueta del campo existe para el lector de pantalla y para quien navegue
   con teclado; en pantalla el icono y el texto de ejemplo ya lo dicen, y un
   rótulo encima de una sola caja de búsqueda sólo añade altura. */
.v12-busca__etiqueta {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
}

.v12-busca__mas { display: inline-flex; align-items: center; gap: .375rem; }
.v12-busca__flecha { transition: transform var(--v12-fast) var(--v12-ease); }
.v12-busca__mas[aria-expanded="true"] .v12-busca__flecha { transform: rotate(180deg); }
/* Cuántos filtros hay puestos. Es lo que evita que alguien mire un listado
   recortado creyendo que eso es todo lo que hay. */
.v12-busca__cuenta {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 1.25rem; height: 1.25rem; padding: 0 .25rem;
    border-radius: var(--v12-r-pill);
    background: var(--v12-fill-accent); color: var(--v12-on-accent);
    font-size: .6875rem; font-weight: 700;
}
.v12-busca__limpiar {
    display: inline-flex; align-items: center; gap: .25rem;
    font-size: .8125rem; color: var(--v12-gray-500);
}
.v12-busca__limpiar:hover { color: var(--sev-critical); }

.v12-busca__panel { margin-top: 1rem; }
.v12-busca__panel[hidden] { display: none; }

/* EL PANEL APARECE ENTERO Y SE DESLIZA; NO SE LE ANIMA LA ALTURA.
 *
 * El primer intento interpolaba `grid-template-rows` de 0fr a 1fr, que es la
 * forma moderna de animar una altura desconocida. Medido en el navegador, se
 * quedaba en cero al abrir: el panel pasa de `hidden` a visible en el mismo
 * turno y el navegador no tiene un estado de partida del que transicionar. La
 * versión con `max-height` es peor todavía —obliga a adivinar un número, y con
 * campos personalizados el panel crece— y cuando la adivinanza queda corta
 * ESCONDE FILTROS sin decirlo.
 *
 * Así que la altura salta y lo que se mueve es el contenido: entra con un
 * desplazamiento corto y un desvanecido. No hay ningún estado intermedio en el
 * que el panel pueda quedarse recortado, que es la única cosa que aquí no puede
 * pasar: un filtro que existe y no se ve cambia el listado sin que nadie sepa
 * por qué. */
@keyframes v12-busca-abre {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}
.v12-busca__interior { animation: v12-busca-abre .22s var(--v12-ease) both; }

@media (prefers-reduced-motion: reduce) {
    .v12-busca__interior { animation: none; }
    .v12-busca__flecha { transition: none; }
}

/* La casilla del catálogo KEV, dentro de la rejilla de filtros: se alinea con la
   altura de los selectores para que la fila no quede escalonada. */
.v12-busca__casilla {
    display: flex; align-items: center; gap: .5rem;
    min-height: 2.625rem; margin: 0;
    font-size: .875rem; color: var(--v12-gray-800); cursor: pointer;
}
.v12-busca__casilla input { width: 1rem; height: 1rem; accent-color: var(--v12-fill-accent); }

/* ============================================================================
   Acciones de fila: dos botones y un menú para lo que no se hace a diario

   Esconder «ver la ficha» y «editar» detrás de tres puntos obligaba a abrir el
   menú para saber cuál era cuál, y el nombre de la fila llevaba al formulario, así
   que la ficha no tenía forma de abrirse. Salen las dos.
   ========================================================================== */

.v12-acciones { display: flex; align-items: center; justify-content: flex-end; gap: .375rem; }

.v12-acc {
    display: inline-flex; align-items: center; gap: .3125rem;
    padding: .3125rem .625rem;
    font-size: .75rem; font-weight: 600; white-space: nowrap;
    color: var(--v12-gray-600);
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    transition: border-color var(--v12-fast) var(--v12-ease),
                color var(--v12-fast) var(--v12-ease),
                background var(--v12-fast) var(--v12-ease);
}
.v12-acc:hover {
    color: var(--v12-fill-accent); border-color: var(--v12-fill-accent);
    background: var(--v12-orange-50); text-decoration: none;
}
.v12-acc .mdi { font-size: .9375rem; }
/* La ficha es la acción principal de la fila y se marca como tal: es lo que se
   pulsa nueve de cada diez veces. */
.v12-acc--ficha { color: var(--v12-gray-800); border-color: var(--v12-gray-300); }

.v12-acc__mas > .dropdown-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.75rem; height: 1.75rem; border-radius: var(--v12-r-md);
    color: var(--v12-gray-400);
}
.v12-acc__mas > .dropdown-toggle:hover { color: var(--v12-gray-700); background: var(--v12-gray-100); }

/* En pantallas estrechas el rótulo estorba más de lo que ayuda: se queda el
   icono, que ya lleva su `title`. La columna cabe sin desbordar la tabla. */
@media (max-width: 991px) {
    .v12-acc { padding: .375rem; }
    .v12-acc span, .v12-acc { font-size: 0; }
    .v12-acc .mdi { font-size: 1.0625rem; }
}

/* ============================================================================
   Ficha de un activo — lo propio de esta altura

   Reutiliza toda la maquinaria de las otras dos fichas (.v12-ficha__*) y sólo
   añade lo que un activo tiene y un negocio no: su tecnología, sus dos
   declaraciones —criticidad y exposición— y de qué escáner sale.
   ========================================================================== */

/* LA TECNOLOGÍA. El glifo NO es el logo del fabricante: los logos son marcas de
   terceros y este producto se revende y genera PDF que salen hacia clientes. El
   glifo dice de qué familia es sin apropiarse de nada. */
.v12-activo__tec {
    display: flex; align-items: center; gap: .75rem;
    margin: 0 0 .875rem; padding: .625rem .75rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-gray-50);
    max-width: 46rem;
}
.v12-activo__tecIcono {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.5rem; height: 2.5rem; flex: none;
    border-radius: var(--v12-r-md);
    background: var(--v12-white); border: 1px solid var(--v12-gray-200);
}
.v12-activo__tecIcono .mdi { font-size: 1.5rem; color: var(--v12-gray-700); }
/* Sin tecnología reportada el bloque se apaga: es un hueco de dato, no una
   afirmación. */
.v12-activo__tecIcono--vacio .mdi { color: var(--v12-gray-300); }
.v12-activo__tecTxt { min-width: 0; }
.v12-activo__tecTxt b { display: block; font-size: .9375rem; color: var(--v12-gray-900); }
.v12-activo__tecTxt small {
    display: block; font-size: .75rem; color: var(--v12-gray-500); line-height: 1.45;
}
.v12-activo__tecTxt code { font-size: .6875rem; color: var(--v12-gray-600); }

/* Criticidad y exposición son DECLARACIONES DEL CLIENTE, no medidas: van como
   sellos y no como números, porque no se promedian ni se calculan. */
.v12-activo__sellos { display: grid; gap: .5rem; min-width: 13rem; }
.v12-activo__sello {
    padding: .5rem .75rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-white);
}
.v12-activo__sello span {
    display: block; font-size: .625rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--v12-gray-400);
}
.v12-activo__sello b {
    display: flex; align-items: center; gap: .3125rem;
    font-size: .9375rem; color: var(--v12-gray-900);
}
.v12-activo__sello--alta    { border-color: #F3D3D1; background: #FDF7F6; }
.v12-activo__sello--alta b  { color: var(--sev-critical); }
.v12-activo__sello--media   { border-color: #F5DFC0; background: #FDFAF4; }
.v12-activo__sello--media b { color: #A85C00; }
.v12-activo__sello--baja    { border-color: #CFE0EE; background: #F7FAFC; }
.v12-activo__sello--publico { border-color: #F5DFC0; background: #FDFAF4; }
.v12-activo__sello--publico b { color: #A85C00; }
/* Un dato sin declarar se enseña flojo y en cursiva: es lo que falta, no un valor. */
.v12-activo__sello--vacio b { color: var(--v12-gray-400); font-style: italic; font-weight: 400; }

.v12-activo__sevbar { height: 14px; }

.v12-activo__fuentes { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.v12-activo__fuentes li {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .75rem; flex-wrap: wrap;
    padding: .5rem .625rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-gray-50); font-size: .8125rem;
}
.v12-activo__fuenteN {
    display: inline-flex; align-items: center; gap: .375rem;
    font-weight: 650; color: var(--v12-gray-800);
}
.v12-activo__fuenteD { font-size: .75rem; color: var(--v12-gray-500); }

/* De qué escáner viene un hallazgo concreto: es el dato que evita la discusión
   de «eso lo dice el otro escáner». */
.v12-activo__fuenteChip {
    display: inline-block; padding: 0 .3125rem;
    border-radius: var(--v12-r-sm);
    background: var(--v12-gray-100); color: var(--v12-gray-600);
    font-size: .625rem; font-weight: 600;
}

/* La zona derecha de la cabecera de página, cuando lleva más de una cosa: los
   filtros rápidos y el botón de crear. En pantalla estrecha se apilan en vez de
   empujar el título fuera. */
.v12-page-head__acciones {
    display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
    justify-content: flex-end;
}

/* Los activos sin visibilidad: no van en el mapa, van nombrados debajo. No es una
   nota al pie sino una llamada a la acción con su recuento — «no están bien ni
   mal, están sin mirar» es información accionable que hoy no da ninguna
   pantalla. */
.v12-riesgo__ciego {
    display: flex; align-items: flex-start; gap: .5rem; flex-wrap: wrap;
    margin: .5rem 0 0; padding: .625rem .75rem;
    border: 1px dashed var(--v12-gray-300); border-radius: var(--v12-r-md);
    background: var(--v12-gray-50);
    font-size: .75rem; color: var(--v12-gray-600); line-height: 1.5;
}
.v12-riesgo__ciego[hidden] { display: none; }
.v12-riesgo__ciego b { color: var(--v12-gray-900); font-size: .875rem; }
.v12-riesgo__ciego > .mdi { font-size: 1rem; color: var(--v12-gray-400); }
.v12-riesgo__ciego a { margin-left: auto; font-weight: 600; white-space: nowrap; }

/* ============================================================================
   Diseñador de flujos: paleta y propiedades FLOTANDO sobre el lienzo

   Con las tres columnas el lienzo se quedaba en 554px de los 1192 que mide el
   diagrama. Al darle todo el ancho se arregló eso y se rompió otra cosa: los dos
   paneles bajaron a una fila debajo, o sea por debajo del pliegue en una pantalla
   normal, y para colocar una etapa había que bajar a cogerla y subir a ver dónde
   caía. En arrastrar y soltar, tener el origen y el destino en dos pantallas
   distintas es peor que tener el destino pequeño.
   ========================================================================== */

/* La zona NO se desplaza; el lienzo de dentro sí. Los flotantes cuelgan de ella:
   dentro del lienzo se irían con el contenido y desaparecerían por la izquierda
   en cuanto alguien moviera el diagrama. */
.v12-ds__zona { position: relative; }

.v12-ds__flota {
    position: absolute;
    z-index: 3;
    width: 17.5rem; max-width: calc(100% - 2rem);
    background: var(--v12-white);
    border: 1px solid var(--v12-gray-200);
    border-radius: var(--v12-r-md);
    box-shadow: var(--v12-shadow-lg);
    /* Que un panel alto no se salga del lienzo: se desplaza por dentro. */
    max-height: calc(100% - 2rem);
    display: flex; flex-direction: column;
}
.v12-ds__flota[hidden] { display: none; }
/* LA PALETA VA ABAJO A LA IZQUIERDA, y no arriba, que fue el primer intento.
   Los flujos se dibujan de izquierda a derecha por la banda superior —entrada,
   asignación, trabajo, verificación— así que arriba a la izquierda está SIEMPRE
   la primera etapa, que es justo la que más se mira. Y no se arregla empujando
   el diagrama: las cajas van posicionadas en absoluto con las coordenadas que el
   usuario guardó, así que un relleno en el contenedor no las mueve —se probó—.
   Abajo a la izquierda es la zona que los flujos dejan libre. */
.v12-ds__paleta { bottom: 1rem; left: 1rem; }
.v12-ds__props  { top: 1rem; right: 1rem; }

.v12-ds__flotaCab {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    padding: .625rem .75rem;
    border-bottom: 1px solid var(--v12-gray-100);
    flex: none;
}
.v12-ds__flotaTit {
    display: flex; align-items: center; gap: .375rem;
    margin: 0; font-size: .8125rem; font-weight: 700; color: var(--v12-gray-800);
}
.v12-ds__flotaTit .mdi { color: var(--v12-gray-400); font-size: 1rem; }
.v12-ds__plegar {
    appearance: none; border: 0; background: none; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.5rem; height: 1.5rem; border-radius: var(--v12-r-sm);
    color: var(--v12-gray-400);
    transition: background var(--v12-fast) var(--v12-ease), color var(--v12-fast) var(--v12-ease);
}
.v12-ds__plegar:hover { background: var(--v12-gray-100); color: var(--v12-gray-800); }

.v12-ds__flotaCuerpo { overflow-y: auto; padding: .75rem 0; }
/* Plegada queda la barra con el título: un panel que desaparece sin dejar rastro
   obliga a recordar que existía. */
.v12-ds__flota--plegada .v12-ds__flotaCuerpo { display: none; }

/* La paleta flotante recupera los márgenes que tenía dentro de la tarjeta. */
.v12-ds__flota .v12-ds__ayuda { padding: 0 .75rem; margin-bottom: .625rem; }
.v12-ds__flota .v12-ds-pieza { width: calc(100% - 1.5rem); margin: 0 .75rem .5rem; }
.v12-ds__flota .v12-ds__nueva { margin: .25rem .75rem 0; width: calc(100% - 1.5rem); }
.v12-ds__flota .v12-form { padding: 0 .75rem; }

/* El nombre del flujo, debajo y en dos columnas: se escribe una vez y no compite
   con el diagrama. */
.v12-ds__flujoForm {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 1rem; padding: 0 1.125rem 1.125rem;
}

/* En pantalla estrecha los flotantes taparían el lienzo entero: vuelven al flujo
   normal del documento, uno debajo del otro. */
@media (max-width: 767px) {
    .v12-ds__flota {
        position: static; width: auto; max-width: none; max-height: none;
        box-shadow: none; margin-top: 1rem;
    }
}

/* ============================================================================
   La fila viva: carga y tendencia en el listado

   Un 60,0 que viene bajando desde 90 y un 60,0 que viene subiendo desde 20 se
   enseñaban idénticos, y son situaciones opuestas. La serie ya estaba guardada
   por el cálculo diario y no la usaba ninguna pantalla.
   ========================================================================== */

.v12-fila__riesgo { white-space: nowrap; }
.v12-fila__sev { display: inline-block; width: 5.5rem; vertical-align: middle; }
.v12-fila__n {
    margin-left: .5rem; font-variant-numeric: tabular-nums; color: var(--v12-gray-900);
}
.v12-fila__limpio {
    display: inline-flex; align-items: center; gap: .25rem;
    font-size: .75rem; color: var(--v12-ok);
}
.v12-fila__marcas { display: flex; gap: .3125rem; margin-top: .25rem; flex-wrap: wrap; }
.v12-fila__marca {
    font-size: .625rem; font-weight: 700; white-space: nowrap;
    padding: .125rem .375rem; border-radius: var(--v12-r-sm);
    border: 1px solid transparent;
}
.v12-fila__marca--kev   { color: var(--sev-critical); background: #FBEBEA; border-color: #F3D3D1; }
.v12-fila__marca--tarde { color: #8A2C22; background: #FBEDE9; border-color: #F0D2CA; }

.v12-fila__tend { white-space: nowrap; }
.v12-chispa { vertical-align: middle; }
.v12-fila__delta {
    margin-left: .375rem; font-size: .75rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
}
/* SUBIR ES MALO AQUÍ, al revés que en una gráfica de ventas: esto es riesgo. El
   color lo dice, y la flecha del signo también, para que no dependa del color. */
.v12-fila__delta--sube  { color: var(--sev-critical); }
.v12-fila__delta--baja  { color: var(--v12-ok); }
.v12-fila__delta--igual { color: var(--v12-gray-400); }
.v12-fila__sinSerie { font-size: .75rem; color: var(--v12-gray-400); font-style: italic; }

/* ============================================================================
   Informe de debida diligencia

   Ordenado por preguntas y no por controles: el texto de las normas está
   protegido y la correspondencia con un control concreto es juicio experto, no
   dato. Y cada pregunta enseña lo que NO puede demostrar, que es lo que separa
   un informe de un folleto.
   ========================================================================== */

.v12-dd { display: grid; gap: 1rem; }

.v12-dd__aviso {
    display: flex; gap: .875rem; align-items: flex-start;
    padding: 1rem 1.25rem; margin-bottom: 1.25rem;
    border-left: 3px solid var(--v12-fill-accent);
}
.v12-dd__aviso > .mdi { font-size: 1.5rem; color: var(--v12-fill-accent); flex: none; }
.v12-dd__aviso b { display: block; margin-bottom: .25rem; color: var(--v12-gray-900); }
.v12-dd__aviso p { margin: 0; font-size: .8125rem; color: var(--v12-gray-600); line-height: 1.6; max-width: 80ch; }

.v12-dd__pregunta .v12-card__title { display: flex; align-items: center; gap: .625rem; }
.v12-dd__n {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.625rem; height: 1.625rem; flex: none;
    border-radius: 50%; background: var(--v12-gray-100);
    font-size: .8125rem; font-weight: 700; color: var(--v12-gray-500);
}

.v12-dd__cifras {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: .75rem;
}
.v12-dd__cifras li {
    padding: .75rem .875rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-white);
}
.v12-dd__cifras b {
    display: block; font-size: 1.375rem; font-weight: 700; color: var(--v12-gray-900);
    font-variant-numeric: tabular-nums; line-height: 1.15;
}
.v12-dd__cifras span { font-size: .75rem; color: var(--v12-gray-500); line-height: 1.4; }

.v12-dd__limites {
    margin-top: 1rem; padding: .875rem 1rem;
    border: 1px solid #F5DFC0; border-radius: var(--v12-r-md); background: #FDFAF4;
}
.v12-dd__limites h3 {
    display: flex; align-items: center; gap: .375rem;
    margin: 0 0 .5rem; font-size: .75rem; font-weight: 700;
    letter-spacing: .05em; text-transform: uppercase; color: #A85C00;
}
.v12-dd__limites ul { margin: 0; padding-left: 1.125rem; }
.v12-dd__limites li { font-size: .8125rem; color: var(--v12-gray-700); line-height: 1.6; margin-bottom: .375rem; }

.v12-dd__sinLimites {
    display: flex; align-items: center; gap: .375rem;
    margin: 1rem 0 0; font-size: .8125rem; color: var(--v12-ok);
}
.v12-dd__pie { margin-top: 1rem; font-size: .75rem; color: var(--v12-gray-400); }

/* Una precisión REFUERZA la evidencia; un límite la acota. No comparten recuadro
   ni color: ponerlas juntas hacía que un dato verificado por CISA se leyera como
   una advertencia. */
.v12-dd__precisiones {
    margin-top: 1rem; padding: .875rem 1rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
    background: var(--v12-gray-50);
}
.v12-dd__precisiones h3 {
    display: flex; align-items: center; gap: .375rem;
    margin: 0 0 .5rem; font-size: .75rem; font-weight: 700;
    letter-spacing: .05em; text-transform: uppercase; color: var(--v12-gray-500);
}
.v12-dd__precisiones ul { margin: 0; padding-left: 1.125rem; }
.v12-dd__precisiones li { font-size: .8125rem; color: var(--v12-gray-700); line-height: 1.6; }

/* Los ejemplos concretos de cada respuesta. Un recuento es un dato; tres nombres
   son evidencia, que es lo que un auditor pide. */
.v12-dd__ejemplos {
    margin-top: 1rem; padding: .875rem 1rem;
    border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md);
}
.v12-dd__ejemplos h3 {
    margin: 0 0 .5rem; font-size: .75rem; font-weight: 700;
    letter-spacing: .05em; text-transform: uppercase; color: var(--v12-gray-500);
}
.v12-dd__ejemplos ul { margin: 0; padding-left: 1.125rem; }
.v12-dd__ejemplos li { font-size: .8125rem; color: var(--v12-gray-700); line-height: 1.6; }
.v12-dd__restantes { color: var(--v12-gray-400); font-style: italic; list-style: none; margin-left: -1.125rem; }

/* ===========================================================================
   CUADRO DE EXPOSICIÓN · el dibujo de Trazo.php

   EL COLOR VIVE AQUÍ Y NO EN EL PHP, y no es una preferencia de organización: el
   producto lleva marca blanca por cliente, así que un hexadecimal escrito en el
   generador de SVG rompe el color de ese cliente sin dar ningún error. `Trazo.php`
   no contiene un solo `#rrggbb` y hay una prueba que lo vigila.
   =========================================================================== */

.v12-exp__titular {
    font-size: 1.125rem; line-height: 1.5; font-weight: 600;
    color: var(--v12-gray-900); margin: 0 0 .5rem; max-width: 70ch;
}
.v12-exp__procedencia {
    font-size: .8125rem; line-height: 1.6; color: var(--v12-gray-500);
    margin: 0; max-width: 78ch;
}

/* La cifra dominante y su variación. */
.v12-exp__cifra {
    font-size: 2.75rem; font-weight: 700; line-height: 1;
    color: var(--v12-gray-900); font-variant-numeric: tabular-nums;
}
.v12-exp__delta { font-size: .9375rem; font-weight: 650; }
.v12-exp__delta--sube { color: var(--v12-danger); }
.v12-exp__delta--baja { color: var(--v12-ok); }
.v12-exp__delta--nulo { color: var(--v12-gray-500); font-weight: 500; }

/* La serie. El SVG se estira; el tope lo pone el contenedor. */
.v12-trazo { width: 100%; height: 200px; display: block; }
.v12-trazo__guia { stroke: var(--v12-gray-200); stroke-width: 1; stroke-dasharray: 2 3; }
.v12-trazo__rotulo,
.v12-trazo__fecha { font-size: 10px; fill: var(--v12-gray-400); }
.v12-trazo__area { fill: var(--v12-fill-accent); fill-opacity: .10; stroke: none; }
.v12-trazo__linea {
    fill: none; stroke: var(--v12-fill-accent); stroke-width: 2;
    stroke-linejoin: round; stroke-linecap: round;
}
.v12-trazo__fin { fill: var(--v12-fill-accent); }
.v12-trazo__fin-rotulo {
    font-size: 12px; font-weight: 700; fill: var(--v12-gray-900);
    font-variant-numeric: tabular-nums;
}
.v12-trazo__corte { stroke: var(--v12-gray-300); stroke-width: 1; stroke-dasharray: 3 3; }
.v12-trazo__corte-rotulo { font-size: 9px; fill: var(--v12-gray-500); }

/* La cascada. Los tipos NO son colores de severidad: son suma, resta y total.
   Reutilizar los tokens de severidad aquí haría que «cierres» se leyera como
   «grave», que es lo contrario de lo que significa. */
.v12-cascada { width: 100%; height: 150px; display: block; }
.v12-cascada__barra--total { fill: var(--v12-gray-600); }
.v12-cascada__barra--suma { fill: var(--v12-fill-accent); fill-opacity: .85; }
.v12-cascada__barra--resta { fill: var(--v12-ok); fill-opacity: .85; }
/* El residuo va rayado: es la parte que NO cuadra y no debe parecer un dato más. */
.v12-cascada__barra--residuo { fill: var(--v12-warn); fill-opacity: .55; }
.v12-cascada__cifra {
    font-size: 11px; font-weight: 700; fill: var(--v12-gray-800);
    font-variant-numeric: tabular-nums;
}
.v12-cascada__rotulo { font-size: 10px; fill: var(--v12-gray-500); }

/* Cuando no hay serie NO se dibuja una plana: se dice. */
.v12-exp__sinserie {
    display: flex; align-items: center; gap: .625rem;
    padding: 1.75rem 1.25rem; border: 1px dashed var(--v12-gray-300);
    border-radius: 8px; color: var(--v12-gray-500); font-size: .875rem;
    background: var(--v12-gray-50);
}
.v12-exp__sinserie .mdi { font-size: 1.25rem; color: var(--v12-gray-400); }

/* La ficha de medición del pie: texto corrido, sin gráfico. */
.v12-exp__ficha {
    display: flex; flex-wrap: wrap; gap: .5rem 1.75rem;
    padding: .875rem 1.125rem; background: var(--v12-gray-100);
    border-radius: 8px; font-size: .8125rem; color: var(--v12-gray-600);
}
.v12-exp__ficha b { color: var(--v12-gray-900); font-weight: 650; }

@media (prefers-reduced-motion: no-preference) {
    .v12-trazo__linea { animation: v12-trazo-entra .6s ease-out; }
}
@keyframes v12-trazo-entra { from { opacity: 0; } to { opacity: 1; } }

/* Selector de periodo. Es un COMPONENTE COMPARTIDO y no una clase del cuadro de
   exposición: los cuatro cuadros nuevos llevan el mismo control, y cuatro copias
   con cuatro nombres distintos es como se llegó a tener quince pantallas que no se
   parecen entre sí.

   Son ENLACES y no botones porque cada periodo es una dirección distinta: se puede
   compartir, marcar y abrir en otra pestaña. Un botón que recarga con JavaScript
   pierde las tres cosas. */
.v12-seg {
    display: inline-flex; gap: .125rem; padding: .1875rem;
    background: var(--v12-gray-100); border-radius: 8px;
}
.v12-seg__op {
    padding: .375rem .75rem; border-radius: 6px;
    font-size: .8125rem; font-weight: 600; color: var(--v12-gray-600);
    text-decoration: none; white-space: nowrap;
    transition: background var(--v12-fast) var(--v12-ease),
                color var(--v12-fast) var(--v12-ease);
}
.v12-seg__op:hover { color: var(--v12-gray-900); text-decoration: none; }
.v12-seg__op.is-on {
    background: var(--v12-white); color: var(--v12-fill-accent);
    box-shadow: 0 1px 2px rgb(27 31 36 / .10);
}
.v12-seg__op:focus-visible { outline: 2px solid var(--v12-fill-accent); outline-offset: 1px; }

/* Bloques 4 a 7 del cuadro de exposición. */

/* La barra de origen del plazo. DOS SEGMENTOS Y NO CUATRO COLORES: la pregunta es
   binaria —lo puso CISA o lo pusimos nosotros— y con dos tramos no hace falta
   leyenda de color, basta el rótulo escrito debajo. */
.v12-exp__barra {
    height: 10px; border-radius: 5px; overflow: hidden;
    background: var(--v12-gray-300); margin: .75rem 0 .625rem;
}
.v12-exp__barra-cisa { display: block; height: 100%; background: var(--v12-fill-accent); }
.v12-exp__leyenda { list-style: none; margin: 0; padding: 0; font-size: .8125rem; color: var(--v12-gray-600); }
.v12-exp__leyenda li { display: flex; align-items: center; gap: .5rem; margin-bottom: .25rem; }
.v12-exp__leyenda b { color: var(--v12-gray-900); margin-left: auto; font-variant-numeric: tabular-nums; }
.v12-exp__punto { width: .625rem; height: .625rem; border-radius: 50%; flex: none; }
.v12-exp__punto--cisa { background: var(--v12-fill-accent); }
.v12-exp__punto--casa { background: var(--v12-gray-300); }

/* «ninguna correcta» no es un hueco: es el hallazgo de la tabla. */
.v12-exp__nunca { color: var(--v12-danger); font-weight: 600; }
.v12-num { text-align: right; font-variant-numeric: tabular-nums; }
.v12-num--mal { color: var(--v12-danger); font-weight: 650; }

/* Las semanas de reincidencia. Barras horizontales porque las etiquetas son fechas
   y en vertical habría que girarlas. */
.v12-exp__semanas { list-style: none; margin: 0; padding: 0; display: grid; gap: .375rem; }
.v12-exp__semanas li { display: flex; align-items: center; gap: .75rem; font-size: .8125rem; }
.v12-exp__semana { color: var(--v12-gray-500); min-width: 3.25rem; font-variant-numeric: tabular-nums; }
.v12-exp__barra-sem { flex: 1; height: 8px; background: var(--v12-gray-100); border-radius: 4px; overflow: hidden; }
.v12-exp__barra-sem span { display: block; height: 100%; background: var(--v12-warn); border-radius: 4px; }
.v12-exp__semanas b { min-width: 3rem; text-align: right; font-variant-numeric: tabular-nums; color: var(--v12-gray-900); }

/* CUADRO DE RIESGO DE NEGOCIO */

/* La banda de alcance. Tres fracciones ESCRITAS y no dibujadas: «28 de 7.285» se
   entiende de un vistazo, una barra al 0,4 % parece un error de renderizado. */
.v12-alcance {
    display: flex; flex-wrap: wrap; gap: .75rem 2.5rem;
    margin: 1rem 0 .75rem; padding: .875rem 1.125rem;
    background: var(--v12-gray-100); border-radius: 8px;
}
.v12-alcance__par { display: flex; align-items: baseline; gap: .5rem; font-size: .875rem; }
.v12-alcance__par b {
    font-size: 1.375rem; font-weight: 700; color: var(--v12-gray-900);
    font-variant-numeric: tabular-nums;
}
.v12-alcance__par span { color: var(--v12-gray-600); }
.v12-alcance__par i {
    font-style: normal; font-weight: 650; color: var(--v12-fill-accent);
    font-variant-numeric: tabular-nums;
}

/* El plano 4x4. El fondo va de claro a oscuro en un SOLO tono: es una escala de
   magnitud, no cuatro categorías, y un arcoíris aquí insinuaría que «amarillo» y
   «rojo» son cosas distintas en vez de más y menos de lo mismo. */
.v12-plano { width: 100%; max-width: 580px; height: auto; display: block; }
.v12-plano__celda { stroke: var(--v12-white); stroke-width: 2; }
.v12-plano__celda--n0 { fill: var(--v12-gray-100); }
.v12-plano__celda--n1 { fill: var(--v12-orange-50); }
.v12-plano__celda--n2 { fill: var(--v12-orange-100); }
.v12-plano__celda--n3 { fill: var(--v12-orange-400); fill-opacity: .55; }
.v12-plano__punto { fill: var(--v12-gray-800); stroke: var(--v12-white); stroke-width: 2; }
/* El anillo del KEV es un SEGUNDO canal, no un color más: la posición ya dice
   cuánto, y esto dice «además, esto se está explotando de verdad». */
.v12-plano__punto--kev { fill: var(--v12-danger); }
.v12-plano__etiqueta { font-size: 11px; fill: var(--v12-gray-700); font-weight: 600; }
.v12-plano__eje { font-size: 11px; fill: var(--v12-gray-500); letter-spacing: .02em; }

.v12-dep__lineas { color: var(--v12-gray-600); font-size: .8125rem; }
.v12-num--ojo { color: var(--v12-warn); font-weight: 700; }

/* Índice de cuadros de mando: los nuevos arriba, los sustituidos atenuados. */
.v12-dashgrid__titulo {
    font-size: .75rem; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--v12-gray-500);
    margin: 1.5rem 0 .75rem;
}
.v12-dashgrid__titulo:first-of-type { margin-top: .5rem; }
.v12-dashcard__audiencia {
    font-size: .6875rem; font-weight: 600; letter-spacing: .04em;
    color: var(--v12-gray-500); margin-left: .5rem; text-transform: lowercase;
}
/* Atenuado, NO oculto: alguien puede tener un ritual mensual colgando de él. */
.v12-dashcard--viejo { opacity: .72; }
.v12-dashcard--viejo:hover { opacity: 1; }
.v12-dashcard__relevo {
    display: inline-flex; align-items: center; gap: .25rem;
    margin-top: .5rem; font-size: .75rem; font-weight: 600;
    color: var(--v12-fill-accent);
}

/* Miniaturas del índice. Van ARRIBA de la tarjeta y no al lado: el ojo lee la forma
   antes que el texto, y la forma es lo que permite elegir sin entrar.

   ALTURA FIJA Y MODESTA. La miniatura ilustra, no es el contenido: si crece se come
   la descripción, que es lo que de verdad permite elegir. Con 64 px y el ancho de una
   columna de tres, la proporción queda cerca del 260x72 con que se dibuja. */
.v12-dashcard { flex-direction: column; align-items: stretch; gap: .75rem; }
.v12-dashcard__mini {
    display: block; width: 100%; border-radius: 6px; overflow: hidden;
    background: var(--v12-gray-50); border: 1px solid var(--v12-gray-200);
    flex: none;
}
.v12-mini { display: block; width: 100%; height: 64px; }
.v12-dashcard__title .mdi { color: var(--v12-fill-accent); margin-right: .375rem; }

/* El cuerpo empuja la flecha al fondo para que todas las tarjetas de una fila
   terminen igual, aunque sus descripciones tengan distinto largo. */
.v12-dashcard__body { display: flex; flex-direction: column; gap: .25rem; }
.v12-dashcard__go { margin-top: auto; align-self: flex-end; }

/* La silueta: geometría hueca. Recesiva a propósito — dice «esta es la forma», no
   «estos son tus datos». */
.v12-mini__guia { stroke: var(--v12-gray-200); stroke-width: 1; stroke-dasharray: 2 3; }
.v12-mini__suelo { stroke: var(--v12-gray-300); stroke-width: 1; }
.v12-mini__barra { fill: var(--v12-gray-200); }
.v12-mini__renglon { fill: var(--v12-gray-200); }
.v12-mini__renglon--cabecera { fill: var(--v12-gray-300); }
.v12-mini__celda { stroke: var(--v12-white); stroke-width: 1; }
.v12-mini__celda--n0 { fill: var(--v12-gray-100); }
.v12-mini__celda--n1 { fill: var(--v12-orange-50); }
.v12-mini__celda--n2 { fill: var(--v12-orange-100); }
.v12-mini__celda--n3 { fill: var(--v12-orange-400); fill-opacity: .5; }

/* El dato en vivo sí lleva el acento: es la diferencia visible entre «esta es la
   forma del cuadro» y «esto es lo que dice hoy». */
.v12-mini__area { fill: var(--v12-fill-accent); fill-opacity: .12; }
.v12-mini__linea { fill: none; stroke: var(--v12-fill-accent); stroke-width: 1.5;
    stroke-linejoin: round; stroke-linecap: round; }
.v12-mini__punto { fill: var(--v12-gray-800); stroke: var(--v12-white); stroke-width: 1; }
.v12-mini__punto--kev { fill: var(--v12-danger); }

/* CUADRO DE FLUJO · la tubería etapa por etapa.

   LAS CLASES SE LLAMAN `v12-tuberia` Y NO `v12-linea` porque `v12-linea*` YA EXISTE:
   la usa /ProductionLine con otra geometría —tarjetas horizontales con flecha— y mi
   bloque se la redefinía. Dos pantallas compartiendo nombre de clase con estilos
   distintos se pisan según cuál cargue después, y el síntoma aparece en la pantalla
   que nadie tocó.
   Barras VERTICALES con la misma escala en todas: la pregunta es «dónde se acumula»,
   y eso sólo se lee si las alturas son comparables. Una barra por etapa con su propia
   escala haría que todas parecieran igual de llenas. */
.v12-tuberia {
    list-style: none; margin: 0; padding: 0;
    display: flex; gap: .5rem; align-items: flex-end; overflow-x: auto;
}
.v12-tuberia__etapa {
    flex: 1 1 0; min-width: 88px;
    display: flex; flex-direction: column; align-items: center; gap: .375rem;
}
.v12-tuberia__barra {
    width: 100%; height: 96px; display: flex; align-items: flex-end;
    background: var(--v12-gray-100); border-radius: 4px; overflow: hidden;
}
.v12-tuberia__barra span { width: 100%; background: var(--v12-fill-accent); border-radius: 4px 4px 0 0; }
.v12-tuberia__nombre {
    font-size: .75rem; font-weight: 650; color: var(--v12-gray-700);
    text-align: center; line-height: 1.25; min-height: 2.2em;
}
.v12-tuberia__stock {
    font-size: 1.0625rem; font-weight: 700; color: var(--v12-gray-900);
    font-variant-numeric: tabular-nums;
}
.v12-tuberia__edad { font-size: .75rem; color: var(--v12-gray-500); }
.v12-tuberia__nunca {
    display: block; font-size: .6875rem; font-weight: 600;
    color: var(--v12-warn); white-space: nowrap;
}

/* CUADRO DE CONFIANZA DEL DATO */
.v12-conf__aviso { color: var(--v12-warn); }

/* La cinta apilada al 100 %: una sola barra con tramos. Secuencial de un tono para
   la antigüedad (más viejo = más oscuro), no arcoíris: es una escala, no categorías. */
.v12-conf__cinta {
    display: flex; height: 14px; border-radius: 7px; overflow: hidden;
    margin: .75rem 0; background: var(--v12-gray-100);
}
.v12-conf__tramo { height: 100%; width: var(--w, 0); flex: none; }
.v12-conf__tramo--d7 { background: var(--v12-ok); }
.v12-conf__tramo--d30 { background: var(--v12-orange-100); }
.v12-conf__tramo--d90 { background: var(--v12-orange-400); }
.v12-conf__tramo--masd90 { background: var(--v12-danger); }
/* «nunca» va en gris, no en un color de estado: es ausencia de dato, no gravedad. */
.v12-conf__tramo--nunca { background: var(--v12-gray-400); }

.v12-conf__leyenda { list-style: none; margin: .5rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: .375rem 1.25rem; font-size: .8125rem; color: var(--v12-gray-600); }
.v12-conf__leyenda li { display: flex; align-items: center; gap: .5rem; }
.v12-conf__leyenda b { color: var(--v12-gray-900); font-variant-numeric: tabular-nums; }
.v12-conf__punto { width: .625rem; height: .625rem; border-radius: 2px; flex: none; }

.v12-conf__pareja { display: flex; gap: 2.5rem; }
.v12-conf__etiqueta { font-size: .8125rem; color: var(--v12-gray-600); }

/* Los supuestos y los descartes: barra horizontal con texto y cifra. */
.v12-conf__supuestos { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.v12-conf__supuestos li { display: grid; grid-template-columns: minmax(10rem, 22rem) 1fr auto; align-items: center; gap: .875rem; font-size: .875rem; }
.v12-conf__sup-texto { color: var(--v12-gray-800); }
.v12-conf__sup-barra { height: 10px; background: var(--v12-gray-100); border-radius: 5px; overflow: hidden; }
.v12-conf__sup-barra span { display: block; height: 100%; background: var(--v12-fill-accent); border-radius: 5px; }
.v12-conf__sup-cifra { white-space: nowrap; color: var(--v12-gray-600); font-variant-numeric: tabular-nums; }
.v12-conf__sup-cifra b { color: var(--v12-gray-900); }
@media (max-width: 680px) { .v12-conf__supuestos li { grid-template-columns: 1fr; gap: .25rem; } }

/* ---- Constructor de paneles: la rejilla de piezas compuestas ---- */
.v12-panel__rejilla { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; align-items: start; }
.v12-panel__rejilla > .v12-panel__pieza { margin: 0; }
.v12-panel__pieza--ancho { grid-column: 1 / -1; }
@media (max-width: 900px) { .v12-panel__rejilla { grid-template-columns: 1fr; } .v12-pe2__grip { display: none; } }

/* ---- Índice: tarjeta de un panel compuesto (icono en vez de silueta) ---- */
.v12-dashcard__mini--panel { display: flex; align-items: center; justify-content: center; }
.v12-dashcard__mini--panel .mdi { font-size: 2.5rem; color: var(--v12-fill-accent); opacity: .55; }
.v12-dashcard--panel .v12-dashcard__audiencia { text-transform: uppercase; letter-spacing: .04em; font-size: .6875rem; }

/* ---- Editor de paneles (constructor): paleta + lienzo ---- */
.v12-pe { display: grid; grid-template-columns: minmax(16rem, 20rem) 1fr; gap: 1.25rem; align-items: start; }
.v12-pe__paleta { position: sticky; top: 1rem; background: var(--v12-white); border: 1px solid var(--v12-gray-200); border-radius: 8px; padding: 1rem; }
.v12-pe__titulo { font-size: .9375rem; margin: 0 0 .75rem; color: var(--v12-gray-800); }
.v12-pe__lista { display: grid; gap: .5rem; }
.v12-pe__pieza { display: flex; align-items: center; gap: .625rem; border: 1px solid var(--v12-gray-200); border-radius: 6px; padding: .5rem .625rem; }
.v12-pe__pieza > .mdi { font-size: 1.25rem; color: var(--v12-fill-accent); flex: none; }
.v12-pe__pieza-cuerpo { min-width: 0; flex: 1; display: grid; }
.v12-pe__pieza-cuerpo strong { font-size: .8125rem; color: var(--v12-gray-900); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v12-pe__chips { font-size: .6875rem; color: var(--v12-gray-600); text-transform: uppercase; letter-spacing: .03em; }
.v12-pe__lienzo { display: grid; gap: 1rem; }
.v12-pe__meta { display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: end; }
.v12-pe__campo { display: grid; gap: .25rem; font-size: .8125rem; color: var(--v12-gray-700); }
.v12-pe__campo input[type="text"] { min-width: min(20rem, 100%); padding: .4375rem .625rem; border: 1px solid var(--v12-gray-300); border-radius: 6px; font-size: .875rem; }
.v12-pe__campo--check { grid-auto-flow: column; align-items: center; gap: .5rem; }
.v12-pe__grid { display: grid; gap: .5rem; }
.v12-pe__card { display: flex; align-items: center; gap: .75rem; background: var(--v12-white); border: 1px solid var(--v12-gray-200); border-radius: 8px; padding: .625rem .75rem; }
.v12-pe__card--flotando { opacity: .55; border-style: dashed; }
.v12-pe__asa { cursor: grab; color: var(--v12-gray-400); font-size: 1.25rem; touch-action: none; flex: none; }
.v12-pe__asa:active { cursor: grabbing; }
.v12-pe__card-titulo { flex: 1; min-width: 0; font-size: .875rem; color: var(--v12-gray-900); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v12-pe__ancho { font-size: .8125rem; padding: .25rem .375rem; border: 1px solid var(--v12-gray-300); border-radius: 6px; flex: none; }
.v12-pe__card-acciones { display: flex; gap: .25rem; flex: none; }
.v12-pe__icono { padding: .25rem .375rem; line-height: 1; }
.v12-pe__card--retirada { border-color: var(--v12-danger); border-style: dashed; }
.v12-pe__retirada { font-size: .6875rem; color: var(--v12-danger); text-transform: uppercase; letter-spacing: .04em; flex: none; }
.v12-pe__vacio { color: var(--v12-gray-600); font-size: .875rem; border: 1px dashed var(--v12-gray-300); border-radius: 8px; padding: 1.25rem; text-align: center; }
.v12-pe__aviso { background: var(--v12-danger-bg); color: var(--v12-danger, #b3261e); border-radius: 6px; padding: .625rem .875rem; font-size: .875rem; }
.v12-pe__acciones { display: flex; gap: .625rem; align-items: center; }
@media (max-width: 900px) { .v12-pe { grid-template-columns: 1fr; } .v12-pe__paleta { position: static; } }

/* ---- Editor de paneles: lienzo WYSIWYG (la tarjeta real + botonera superpuesta) ---- */
.v12-pe__previa { position: relative; }
.v12-pe__mando { position: absolute; top: .375rem; right: .375rem; display: flex; gap: .25rem; align-items: center; background: var(--v12-white); border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-sm); padding: .125rem .25rem; box-shadow: 0 2px 8px rgba(15, 23, 42, .10); opacity: 0; transition: opacity .12s ease; z-index: 5; }
.v12-pe__previa:hover .v12-pe__mando, .v12-pe__mando:focus-within { opacity: 1; }
@media (pointer: coarse) { .v12-pe__mando { opacity: 1; } }
.v12-pe__previa--flotando { opacity: .55; outline: 2px dashed var(--v12-gray-400); }
.v12-pe__lienzo--cargando .v12-panel__rejilla { opacity: .55; pointer-events: none; }

/* ---- Pieza a medida: paleta de series (por tokens, marca blanca) y tabla ---- */
.v12-cinta--v1 { background: var(--v12-fill-accent); }
.v12-cinta--v2 { background: var(--v12-ok); }
.v12-cinta--v3 { background: var(--v12-orange-400); }
.v12-cinta--v4 { background: var(--v12-danger); }
.v12-cinta--v5 { background: var(--v12-gray-400); }
.v12-cinta--v6 { background: var(--v12-orange-100); }
.v12-pc__desborda { overflow-x: auto; }
.v12-pc__tabla { width: 100%; border-collapse: collapse; font-size: .875rem; }
.v12-pc__tabla th, .v12-pc__tabla td { padding: .375rem .625rem; border-bottom: 1px solid var(--v12-gray-200); text-align: left; }
.v12-pc__tabla th { font-size: .75rem; text-transform: uppercase; letter-spacing: .04em; color: var(--v12-gray-600); }
.v12-pc__num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---- Editor de paneles: el formulario de pieza a medida ---- */
.v12-pe__amedida { display: grid; gap: .625rem; border: 1px solid var(--v12-gray-200); border-left: 3px solid var(--v12-fill-accent); border-radius: var(--v12-r-sm); padding: .875rem; margin-bottom: 1.25rem; }
.v12-pe__nota { font-size: .75rem; color: var(--v12-gray-600); margin: 0; }
.v12-pe__amedida select, .v12-pe__amedida input { width: 100%; min-width: 0; padding: .375rem .5rem; border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-sm); font-size: .8125rem; }

/* ---- Editor v2: barra de herramientas, desplegable, panel flotante, grip ---- */
.v12-pe2 { display: grid; gap: 1rem; }
.v12-pe2__barra { position: sticky; top: 78px; z-index: 30; display: flex; align-items: end; gap: .625rem; flex-wrap: wrap; background: var(--v12-white); border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md); padding: .625rem .875rem; box-shadow: 0 2px 10px rgba(15, 23, 42, .06); }
.v12-pe2__campo { display: grid; gap: .25rem; font-size: .8125rem; color: var(--v12-gray-700); }
.v12-pe2__rotulo { font-size: .6875rem; text-transform: uppercase; letter-spacing: .05em; color: var(--v12-gray-500); }
.v12-pe2__campo input[type="text"] { min-width: min(18rem, 100%); padding: .4375rem .625rem; border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-sm); font-size: .875rem; }
.v12-pe2__campo--check { grid-auto-flow: column; align-items: center; gap: .5rem; align-self: center; }
.v12-pe2__sep { width: 1px; align-self: stretch; background: var(--v12-gray-200); margin: 0 .25rem; }
.v12-pe2__hueco { flex: 1; }
.v12-pe2__menu { position: relative; }
.v12-pe2__desplegable { position: absolute; top: calc(100% + 6px); left: 0; z-index: 40; width: 22rem; max-height: 26rem; overflow-y: auto; background: var(--v12-white); border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md); box-shadow: 0 8px 28px rgba(15, 23, 42, .14); padding: .625rem; }
.v12-pe2__lienzo { min-height: 12rem; }
.v12-pe2__flotante { position: fixed; top: 92px; right: 24px; z-index: 50; width: min(21rem, calc(100vw - 2rem)); background: var(--v12-white); border: 1px solid var(--v12-gray-200); border-left: 3px solid var(--v12-fill-accent); border-radius: var(--v12-r-md); box-shadow: 0 12px 36px rgba(15, 23, 42, .18); }
.v12-pe2__flotante-cab { display: flex; align-items: center; justify-content: space-between; padding: .625rem .875rem; border-bottom: 1px solid var(--v12-gray-200); cursor: grab; user-select: none; font-size: .875rem; }
.v12-pe2__flotante-cab:active { cursor: grabbing; }
.v12-pe2__flotante-cuerpo { padding: .875rem; display: grid; gap: .625rem; max-height: min(60vh, 34rem); overflow-y: auto; }
.v12-pe2__flotante-cuerpo select, .v12-pe2__flotante-cuerpo input { width: 100%; min-width: 0; padding: .375rem .5rem; border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-sm); font-size: .8125rem; }
.v12-pe2__grip { position: absolute; top: 20%; bottom: 20%; right: -3px; width: 8px; border-radius: 4px; cursor: ew-resize; background: transparent; z-index: 6; touch-action: none; }
.v12-pe__previa:hover .v12-pe2__grip { background: var(--v12-fill-accent); opacity: .45; }
.v12-pe2__grip:hover, .v12-pe2__previa--midiendo .v12-pe2__grip { background: var(--v12-fill-accent); opacity: .9; }
.v12-pe2__previa--midiendo { outline: 2px dashed var(--v12-fill-accent); outline-offset: 2px; }
.v12-pe__previa { cursor: grab; }
.v12-pe__previa:active { cursor: grabbing; }

/* ---- Grilla dinámica de 12 columnas (visor y editor comparten) ---- */
.v12-panel__rejilla { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.v12-an-3 { grid-column: span 3; } .v12-an-4 { grid-column: span 4; }
.v12-an-6 { grid-column: span 6; } .v12-an-8 { grid-column: span 8; }
.v12-an-12 { grid-column: 1 / -1; }
@media (max-width: 900px) { .v12-an-3, .v12-an-4, .v12-an-6, .v12-an-8 { grid-column: 1 / -1; } }

/* ---- Pieza de texto ---- */
.v12-texto { font-size: .9375rem; line-height: 1.6; color: var(--v12-gray-800); max-width: 65ch; }

/* ---- Selector de variables: chips clicables con descripción ---- */
.v12-pe3__grupo { display: grid; gap: .375rem; }
.v12-pe3__chips { display: flex; flex-wrap: wrap; gap: .375rem; }
.v12-pe3__chip { border: 1px solid var(--v12-gray-300); background: var(--v12-white); border-radius: 999px; padding: .3125rem .75rem; font-size: .8125rem; cursor: pointer; font-family: inherit; color: var(--v12-gray-800); }
.v12-pe3__chip[aria-pressed="true"] { background: var(--v12-fill-accent); border-color: var(--v12-fill-accent); color: #fff; font-weight: 600; }
.v12-pe3__chip:focus-visible { outline: 2px solid var(--v12-fill-accent); outline-offset: 2px; }

/* ---- Lienzo total: el menú lateral se aparta y manda el constructor ---- */
body.v12-lienzo-total .left-side-menu { display: none; }
body.v12-lienzo-total .content-page { margin-left: 0; }

/* ---- Pieza de imagen ---- */
.v12-imagen { max-width: 100%; height: auto; display: block; border-radius: var(--v12-r-sm); }

/* ---- Rejilla: un hijo SIN clase de ancho ocupa la fila entera (el estado vacío
   colapsaba a 1/12 y salía enano a la izquierda) ---- */
.v12-panel__rejilla > :not([class*="v12-an-"]) { grid-column: 1 / -1; }

/* ---- Editor: lienzo a pantalla y la invitación centrada cuando está vacío ---- */
.v12-pe2__lienzo { min-height: calc(100vh - 240px); }
.v12-pe2__invita { display: grid; place-items: center; text-align: center; min-height: calc(100vh - 260px); border: 2px dashed var(--v12-gray-300); border-radius: var(--v12-r-md); color: var(--v12-gray-600); }
.v12-pe2__invita .mdi { font-size: 3.5rem; color: var(--v12-fill-accent); opacity: .5; display: block; margin-bottom: .75rem; }
.v12-pe2__invita strong { display: block; font-size: 1.125rem; color: var(--v12-gray-800); margin-bottom: .375rem; }
.v12-pe2__invita p { margin: 0; font-size: .875rem; max-width: 46ch; }

/* ---- Alto de pieza: pasos de respiración vertical ---- */
.v12-al-corto { min-height: 11rem; } .v12-al-medio { min-height: 19rem; } .v12-al-grande { min-height: 27rem; }

/* ---- Redimensionado wow: grips siempre visibles, guías y globo ---- */
.v12-pe2__grip { opacity: .25; background: var(--v12-fill-accent); }
.v12-pe2__grip-v { position: absolute; left: 20%; right: 20%; bottom: -3px; height: 8px; border-radius: 4px; cursor: ns-resize; background: var(--v12-fill-accent); opacity: .25; z-index: 6; touch-action: none; }
.v12-pe__previa:hover .v12-pe2__grip, .v12-pe__previa:hover .v12-pe2__grip-v { opacity: .55; }
.v12-pe2__grip:hover, .v12-pe2__grip-v:hover, .v12-pe2__previa--midiendo .v12-pe2__grip, .v12-pe2__previa--midiendo .v12-pe2__grip-v { opacity: .95; }
.v12-pe2__rejilla--guias { background-image: repeating-linear-gradient(to right, var(--v12-gray-200) 0, var(--v12-gray-200) 1px, transparent 1px, transparent calc((100% - 11rem) / 12 + 1rem)); background-clip: content-box; }
.v12-pe2__globo { position: absolute; top: -0.75rem; left: 50%; transform: translateX(-50%); background: var(--v12-gray-900); color: var(--v12-white); font-size: .75rem; padding: .25rem .625rem; border-radius: 999px; white-space: nowrap; z-index: 10; box-shadow: 0 2px 8px rgba(15,23,42,.25); }
@media (max-width: 900px) { .v12-pe2__grip-v { display: none; } }

/* ---- Rebanada 6: el cross-filter ----
   Un valor clicable de una pieza marcada como filtro del panel: affordance clara
   sin repintar la pieza. El chip del filtro activo comparte forma entre el visor
   y la vista previa del editor (#peFiltroVivo reutiliza la misma clase). */
[data-fd][data-fv] { cursor: pointer; }
[data-fd][data-fv]:hover, [data-fd][data-fv]:focus-visible { background: var(--v12-gray-100); }
[data-fd][data-fv]:focus-visible { outline: 2px solid var(--v12-fill-accent); outline-offset: 1px; }

.v12-panel__filtro { display: flex; align-items: center; gap: .5rem; margin: 0 0 1rem; padding: .375rem .75rem; border: 1px solid var(--v12-fill-accent); background: var(--v12-white); border-radius: 999px; width: fit-content; font-size: .875rem; color: var(--v12-gray-800); }
.v12-panel__filtro > .mdi-filter-outline { color: var(--v12-fill-accent); }
.v12-panel__filtro-quita { display: inline-flex; align-items: center; gap: .25rem; font-weight: 600; }

/* La alta de un filtro de pieza: dimensión + valor + botón en una fila. */
.v12-pe3__filtro-alta { display: flex; gap: .5rem; align-items: center; }
.v12-pe3__filtro-alta select { flex: 0 1 40%; }
.v12-pe3__filtro-alta input { flex: 1 1 auto; min-width: 0; }
.v12-pe3__chip--filtro { background: var(--v12-gray-100); }
.v12-pe3__filtra input[type="checkbox"] { margin-right: .375rem; }

/* ---- Ciclo de vida del panel: borrador → publicado ⇄ pausado ----
   El chip del editor y el aviso del visor comparten paleta: ámbar para lo no
   publicado (trabajo en curso o retirado), verde sobrio para lo publicado. */
.v12-pe2__estado { border-radius: 999px; padding: .25rem .625rem; font-size: .75rem; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }
.v12-pe2__estado--publicado { background: var(--v12-green-100, #e6f4ea); color: var(--v12-green-800, #1e6e42); }
.v12-pe2__estado--borrador, .v12-pe2__estado--pausado { background: var(--v12-amber-100, #fdf3e1); color: var(--v12-amber-800, #8a5a12); }

.v12-panel__estado { display: flex; align-items: center; gap: .5rem; margin: 0 0 1rem; padding: .5rem .875rem; border-radius: var(--v12-r-sm); border: 1px solid var(--v12-amber-800, #8a5a12); background: var(--v12-amber-100, #fdf3e1); color: var(--v12-amber-800, #8a5a12); font-size: .875rem; }

.v12-dashcard__audiencia--estado { color: var(--v12-amber-800, #8a5a12); font-weight: 600; }

.v12-pe__aviso--ok { border-color: var(--v12-green-800, #1e6e42); color: var(--v12-green-800, #1e6e42); background: var(--v12-green-100, #e6f4ea); }

/* ---- El asistente de IA del constructor ---- */
.v12-pe2__ia .mdi-creation { color: var(--v12-fill-accent); }
.v12-pe__campo textarea { resize: vertical; min-height: 5.5rem; font: inherit; padding: .5rem .625rem; border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-sm); background: var(--v12-white); color: var(--v12-gray-800); }
.v12-pe3__ia-aviso { color: var(--v12-gray-800); }
#peFlotanteIa { width: min(30rem, calc(100vw - 2rem)); }

/* ---- Fase B1: la cola de prioridad residual ---- */
.v12-pc__pista { color: var(--v12-gray-500); font-size: .8125rem; }

/* ---- Flujos de trabajo como tarjetas: la lista aguanta veinte flujos ---- */
.v12-wf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(24rem, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
.v12-wf-card { display: flex; flex-direction: column; gap: .625rem; background: var(--v12-white); border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-md, 10px); padding: 1rem 1.125rem; color: inherit; text-decoration: none; transition: border-color .15s ease, box-shadow .15s ease; }
.v12-wf-card:hover, .v12-wf-card:focus-visible { border-color: var(--v12-fill-accent); box-shadow: 0 2px 10px rgba(0, 0, 0, .06); color: inherit; }
.v12-wf-card__cab { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; }
.v12-wf-card__nombre { font-size: 1.05rem; font-weight: 650; margin: 0; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.v12-wf-card__vivos { display: inline-flex; align-items: center; gap: .3rem; font-weight: 700; color: var(--v12-fill-accent); white-space: nowrap; }
.v12-wf-card__desc { margin: 0; color: var(--v12-gray-600); font-size: .875rem; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.v12-wf-card__pasos { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .375rem; }
.v12-wf-paso { border: 1px solid var(--v12-gray-300); border-radius: 999px; padding: .125rem .55rem; font-size: .75rem; color: var(--v12-gray-700); white-space: nowrap; }
.v12-wf-paso b { margin-left: .3rem; color: var(--v12-fill-accent); }
.v12-wf-paso--vivo { border-color: var(--v12-fill-accent); }
.v12-wf-paso--rama { border-style: dashed; color: var(--v12-gray-500); }
.v12-wf-card__flecha { color: var(--v12-gray-400); font-size: .75rem; }
.v12-wf-card__pie { margin-top: auto; display: inline-flex; align-items: center; gap: .375rem; font-size: .8125rem; font-weight: 600; color: var(--v12-fill-accent); }

/* ---- El latido de la IA: el logo respira mientras arma el panel ---- */
/* ---- EL EMBLEMA DE TWELVY: el disco oscuro con la marca y los arcos naranjos
   girando alrededor (dos arcos a ritmos distintos, la maqueta del dueño).
   --girando enciende los arcos; --mini para burbuja y diálogos. El logo va
   sobre disco oscuro SIEMPRE: la marca (y los white-label) son claras. ---- */
.v12-pe3__latido { display: flex; justify-content: center; padding: .75rem 0 .25rem; }
.v12-pe3__latido[hidden] { display: none !important; }

.v12-twemblema { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 4.5rem; height: 4.5rem; }
.v12-twemblema img { width: 62%; height: 62%; object-fit: contain; background: #16191d; border-radius: 50%; padding: 12%; box-sizing: border-box; position: relative; z-index: 1; }
.v12-twemblema::before, .v12-twemblema::after { content: ''; position: absolute; inset: 0; border-radius: 50%; border: 4px solid #3a4048; }
.v12-twemblema::before { border-top-color: var(--v12-fill-accent); border-right-color: var(--v12-fill-accent); }
.v12-twemblema::after { inset: -7px; border-width: 3px; border-color: transparent; border-bottom-color: var(--v12-fill-accent); opacity: .8; }
.v12-twemblema--girando::before { animation: v12-tw-gira 1.4s linear infinite; }
.v12-twemblema--girando::after { animation: v12-tw-gira 2.3s linear infinite reverse; }
.v12-twemblema--mini { width: 3.25rem; height: 3.25rem; }
.v12-twemblema--mini::before { border-width: 3px; }
.v12-twemblema--mini::after { inset: -5px; border-width: 2px; }
@keyframes v12-tw-gira { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .v12-twemblema--girando::before, .v12-twemblema--girando::after { animation-duration: 6s; }
}

/* ---- El título del panel sobre el lienzo, y la barra de filtros del visor ---- */
.v12-pe2__titulo-lienzo { font-size: 1.35rem; font-weight: 700; margin: .25rem 0 .75rem; letter-spacing: -.01em; }
.v12-pv__filtros { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin: 0 0 1rem; }
.v12-pv__area { display: inline-flex; align-items: center; gap: .5rem; font-size: .875rem; color: var(--v12-gray-700); }
.v12-pv__area select { padding: .3rem .5rem; border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-sm); background: var(--v12-white); color: var(--v12-gray-800); font: inherit; }
.v12-pv__area--fija strong { color: var(--v12-gray-800); }

/* ---- B2: la lectura de la cola por IA ---- */
.v12-pc__narrativa { margin-top: .75rem; }
.v12-pc__narrativa-texto { margin-top: .625rem; padding: .75rem .9rem; background: var(--v12-gray-100); border-left: 3px solid var(--v12-fill-accent); border-radius: var(--v12-r-sm); font-size: .9rem; line-height: 1.55; }
.v12-pc__narrativa-texto p { margin: 0 0 .5rem; }
.v12-pc__narrativa-texto p:last-child { margin-bottom: 0; }

/* ---- El análisis guiado: el ESCENARIO ----
   Arco en dos actos: --inicio pone la pregunta protagonista al centro (hero,
   ejemplos de un clic); con la primera respuesta el prompt se ACOPLA arriba y
   la conversación manda. La oferta del dashboard es una barra flotante que
   SUBE cuando hay piezas. Todo transiciona en transform/opacity y respeta
   prefers-reduced-motion. */
.v12-ag { display: flex; flex-direction: column; }
.v12-ag--inicio { min-height: 58vh; justify-content: center; }

.v12-ag__hero { text-align: center; max-height: 0; opacity: 0; overflow: hidden; transition: max-height .35s ease, opacity .35s ease; }
.v12-ag--inicio .v12-ag__hero { max-height: 12rem; opacity: 1; margin-bottom: 1.25rem; }
.v12-ag__hero-titulo { font-size: 2rem; font-weight: 750; letter-spacing: -.02em; margin: 0 0 .375rem; }
.v12-ag__hero-sub { color: var(--v12-gray-600); max-width: 42rem; margin: 0 auto; }

.v12-ag__prompt { display: flex; gap: .625rem; align-items: flex-end; background: var(--v12-white); border: 1px solid var(--v12-gray-300); border-radius: 14px; padding: .75rem .875rem; box-shadow: 0 1px 3px rgba(0,0,0,.05); transition: box-shadow .2s ease, border-color .2s ease, max-width .35s ease; max-width: 100%; margin: 0 auto; width: 100%; }
.v12-ag--inicio .v12-ag__prompt { max-width: 46rem; box-shadow: 0 6px 24px rgba(0,0,0,.09); }
.v12-ag__prompt:focus-within { border-color: var(--v12-fill-accent); box-shadow: 0 6px 24px rgba(200,80,30,.14); }
.v12-ag__prompt textarea { flex: 1; border: 0; outline: 0; resize: none; font: inherit; font-size: 1.05rem; line-height: 1.5; background: transparent; color: var(--v12-gray-800); min-height: 2.6rem; max-height: 180px; }
.v12-ag__prompt .v12-btn { white-space: nowrap; }

.v12-ag__ejemplos { display: flex; flex-wrap: wrap; gap: .5rem; justify-content: center; margin: 1rem auto 0; max-width: 46rem; max-height: 0; opacity: 0; overflow: hidden; transition: max-height .35s ease, opacity .35s ease; }
.v12-ag--inicio .v12-ag__ejemplos { max-height: 8rem; opacity: 1; }
.v12-ag__ejemplo { border: 1px solid var(--v12-gray-300); background: var(--v12-white); border-radius: 999px; padding: .45rem .95rem; font: inherit; font-size: .875rem; color: var(--v12-gray-700); cursor: pointer; transition: border-color .15s ease, transform .15s ease; }
.v12-ag__ejemplo:hover, .v12-ag__ejemplo:focus-visible { border-color: var(--v12-fill-accent); color: var(--v12-fill-accent); transform: translateY(-1px); }

.v12-ag__latido { margin-top: 1rem; }
.v12-ag__hero-emblema { margin: 0 auto .9rem; display: flex; width: 5.5rem; height: 5.5rem; }
.v12-ag--inicio .v12-ag__latido .v12-twemblema { width: 5rem; height: 5rem; }
.v12-ag__aviso { text-align: center; margin-top: .75rem; }

.v12-ag__respuestas { margin-top: 1.25rem; }
.v12-ag__bloque { margin-top: 1rem; transition: opacity .3s ease, transform .3s ease; }
.v12-ag__bloque--entrando { opacity: 0; transform: translateY(10px); }
.v12-ag__pregunta { font-weight: 700; margin: 0 0 .25rem; }
.v12-ag__pregunta::before { content: '» '; color: var(--v12-fill-accent); }
.v12-ag__texto { color: var(--v12-gray-700); margin: 0 0 .75rem; }

.v12-ag__oferta { position: fixed; left: 50%; bottom: 1.25rem; transform: translate(-50%, 140%); z-index: 60; display: flex; align-items: center; gap: 1.25rem; background: #16191d; color: #fff; border-radius: 999px; padding: .625rem .75rem .625rem 1.25rem; box-shadow: 0 10px 30px rgba(0,0,0,.28); transition: transform .35s ease; max-width: min(92vw, 52rem); }
.v12-ag__oferta--arriba { transform: translate(-50%, 0); }
.v12-ag__oferta-texto { display: inline-flex; align-items: center; gap: .5rem; white-space: nowrap; }
.v12-ag__oferta-texto .mdi { color: var(--v12-fill-accent); font-size: 1.15rem; }
.v12-ag__oferta-texto small { color: #aeb9c6; }
.v12-ag__oferta-botones { display: inline-flex; gap: .5rem; }

@media (prefers-reduced-motion: reduce) {
    .v12-ag__hero, .v12-ag__prompt, .v12-ag__ejemplos, .v12-ag__bloque, .v12-ag__oferta, .v12-ag__ejemplo { transition: none; }
}

/* ---- Twelvy flotante: la burbuja y su panel, como los chats de sitio ---- */
.v12-tw__boton { position: fixed; right: 1.4rem; bottom: 1.4rem; z-index: 70; border: 0; background: transparent; padding: 0; cursor: pointer; filter: drop-shadow(0 6px 16px rgba(0,0,0,.28)); transition: transform .15s ease; }
.v12-tw__boton:hover, .v12-tw__boton:focus-visible { transform: scale(1.07); }
.v12-tw__panel { position: fixed; right: 1.4rem; bottom: 5.4rem; z-index: 70; width: min(24rem, calc(100vw - 2rem)); max-height: min(70vh, 40rem); display: flex; flex-direction: column; background: var(--v12-white); border: 1px solid var(--v12-gray-300); border-radius: 16px; box-shadow: 0 16px 48px rgba(0,0,0,.24); overflow: hidden; }
.v12-tw__cab { display: flex; align-items: center; gap: .6rem; padding: .6rem .75rem; background: #16191d; color: #fff; }
.v12-tw__cab strong { flex: 1; font-size: 1.02rem; }
.v12-tw__cab .v12-twemblema--mini { width: 2.1rem; height: 2.1rem; }
.v12-tw__cab .v12-twemblema--mini::after { display: none; }
.v12-tw__lleno { color: #aeb9c6; display: inline-flex; }
.v12-tw__lleno:hover { color: #fff; }
.v12-tw__respuestas { flex: 1; overflow-y: auto; padding: .75rem .875rem; min-height: 6rem; }
.v12-tw__bloque { border-bottom: 1px solid var(--v12-gray-200, #eef1f4); padding-bottom: .625rem; margin-bottom: .625rem; }
.v12-tw__bloque:last-child { border-bottom: 0; }
/* En 24rem las piezas van APILADAS a lo ancho: la rejilla de 12 no cabe. */
.v12-tw__respuestas .v12-panel__rejilla { display: block; }
.v12-tw__respuestas .v12-panel__rejilla > * { margin-bottom: .75rem; }
.v12-tw__girando { display: flex; justify-content: center; padding: .5rem 0; }
.v12-tw__aviso { padding: 0 .875rem .5rem; }
.v12-tw__oferta { margin: 0 .875rem .6rem; border: 1px dashed var(--v12-fill-accent); background: var(--v12-white); color: var(--v12-fill-accent); border-radius: 999px; padding: .4rem .8rem; font: inherit; font-size: .875rem; font-weight: 600; cursor: pointer; }
.v12-tw__oferta:hover { background: var(--v12-gray-100); }
.v12-tw__entrada { display: flex; gap: .5rem; padding: .6rem .75rem; border-top: 1px solid var(--v12-gray-300); }
.v12-tw__entrada input { flex: 1; border: 1px solid var(--v12-gray-300); border-radius: 999px; padding: .45rem .9rem; font: inherit; background: var(--v12-white); color: var(--v12-gray-800); outline: none; }
.v12-tw__entrada input:focus { border-color: var(--v12-fill-accent); }
@media print { .v12-tw__boton, .v12-tw__panel { display: none !important; } }

/* ---- El historial de conversaciones del análisis guiado (estilo Claude) ---- */
.v12-ag__cabecera { display: flex; align-items: center; gap: .75rem; }
/* Por la DERECHA: el menú principal vive a la izquierda y el cajón lo tapaba. */
.v12-ag__historial { position: fixed; right: 0; top: 70px; bottom: 0; z-index: 65; width: min(20rem, 85vw); background: var(--v12-white); border-left: 1px solid var(--v12-gray-300); box-shadow: -8px 0 24px rgba(0,0,0,.12); display: flex; flex-direction: column; padding: .75rem; }
.v12-ag__historial-cab { display: flex; align-items: center; justify-content: space-between; margin-bottom: .5rem; }
.v12-ag__historial-nueva { margin-bottom: .75rem; }
.v12-ag__historial-lista { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; }
.v12-ag__historial-item { display: flex; flex-direction: column; gap: .15rem; width: 100%; text-align: left; border: 0; background: transparent; padding: .55rem .6rem; border-radius: 8px; cursor: pointer; font: inherit; color: var(--v12-gray-800); }
.v12-ag__historial-item:hover { background: var(--v12-gray-100); }
.v12-ag__historial-item.is-actual { background: var(--v12-gray-100); border-left: 3px solid var(--v12-fill-accent); }
.v12-ag__historial-item span { font-weight: 600; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v12-ag__historial-item small { color: var(--v12-gray-500); font-size: .75rem; }

/* ---- El taller de riesgo residual ---- */
.v12-taller__total { text-align: right; }
.v12-taller__total span { display: block; font-size: .75rem; text-transform: uppercase; letter-spacing: .05em; color: var(--v12-gray-500); }
.v12-taller__total b { font-size: 1.9rem; font-variant-numeric: tabular-nums; }
.v12-taller__total small { margin-left: .4rem; font-weight: 700; }
.v12-taller__delta--baja { color: #1e6e42; }
.v12-taller__delta--sube { color: #b23b3b; }
.v12-taller__tabla td { vertical-align: top; }
.v12-taller__controles { display: flex; flex-direction: column; gap: .2rem; font-size: .8125rem; }
.v12-taller__controles label { display: flex; align-items: center; gap: .35rem; white-space: nowrap; }
.v12-taller__tabla select { padding: .3rem .5rem; border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-sm); background: var(--v12-white); color: var(--v12-gray-800); font: inherit; }


/* ---- El taller en lote ---- */
.v12-taller__filtro { width: min(24rem, 100%); margin-bottom: .75rem; padding: .45rem .75rem; border: 1px solid var(--v12-gray-300); border-radius: 999px; font: inherit; background: var(--v12-white); color: var(--v12-gray-800); }
.v12-taller__otronota { margin-top: .25rem; padding: .3rem .5rem; border: 1px solid var(--v12-gray-300); border-radius: var(--v12-r-sm); font: inherit; font-size: .8125rem; width: 100%; }
.v12-taller__observado { display: block; margin-bottom: .35rem; border: 1px dashed var(--v12-fill-accent); background: var(--v12-white); color: var(--v12-fill-accent); border-radius: 999px; padding: .2rem .6rem; font: inherit; font-size: .75rem; cursor: pointer; }
.v12-taller__lote { flex-wrap: wrap; max-width: min(96vw, 72rem); border-radius: 16px; }
.v12-taller__lote select { font: inherit; padding: .3rem .5rem; border-radius: 8px; border: 0; }
.v12-taller__lote-controles { flex-direction: row !important; flex-wrap: wrap; gap: .3rem .8rem !important; color: #fff; }
.v12-taller__lote-controles .v12-taller__otronota { width: 14rem; }
.v12-taller__lote-cierra { border: 0; background: transparent; color: #fff; font-size: 1.3rem; line-height: 1; cursor: pointer; padding: 0 .3rem; opacity: .75; }
.v12-taller__lote-cierra:hover { opacity: 1; }

/* Las vistas del taller: la lupa (por activo) y la brocha (por grupos). */
.v12-taller__vistas { display: flex; align-items: center; gap: .4rem; margin-bottom: .75rem; flex-wrap: wrap; }
.v12-taller__vistas .v12-pc__pista { margin-left: auto; }
.v12-taller__vista { border: 1px solid var(--v12-gray-300); background: var(--v12-white); color: var(--v12-gray-600); border-radius: 999px; padding: .35rem .9rem; font: inherit; font-size: .8125rem; cursor: pointer; }
.v12-taller__vista--activa { border-color: var(--v12-fill-accent); color: var(--v12-fill-accent); font-weight: 600; }
.v12-taller__dims { display: flex; gap: .4rem; flex-wrap: wrap; margin: .25rem 0 1rem; }
.v12-taller__dim { display: inline-flex; align-items: center; gap: .35rem; border: 1px solid var(--v12-gray-300); background: var(--v12-white); color: var(--v12-gray-600); border-radius: 999px; padding: .35rem .8rem; font: inherit; font-size: .8125rem; cursor: pointer; }
.v12-taller__dim:hover { border-color: var(--v12-gray-500); }
.v12-taller__dim--activa { border-color: var(--v12-fill-accent); color: var(--v12-fill-accent); font-weight: 600; background: color-mix(in srgb, var(--v12-fill-accent) 8%, var(--v12-white)); }
.v12-taller__dim-n { background: var(--v12-gray-100); color: var(--v12-gray-600); border-radius: 999px; padding: 0 .45rem; font-size: .72rem; font-variant-numeric: tabular-nums; }
.v12-taller__dim--activa .v12-taller__dim-n { background: var(--v12-fill-accent); color: #fff; }
.v12-taller__grupos-malla { display: grid; grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr)); gap: .75rem; }
.v12-taller__grupo { border: 1px solid var(--v12-gray-200); border-radius: var(--v12-r-md); padding: .8rem .95rem; display: flex; flex-direction: column; gap: .5rem; background: var(--v12-white); font: inherit; text-align: left; cursor: pointer; transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
.v12-taller__grupo:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(15, 23, 42, .10); border-color: var(--v12-fill-accent); }
.v12-taller__grupo:hover .v12-taller__grupo-pie { color: var(--v12-fill-accent); }
.v12-taller__grupo-cabeza { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; min-width: 0; }
.v12-taller__grupo-cabeza b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v12-taller__grupo-estado { flex: none; font-size: .72rem; color: var(--v12-gray-500); background: var(--v12-gray-100); border-radius: 999px; padding: .1rem .5rem; font-variant-numeric: tabular-nums; }
.v12-taller__grupo-estado--parcial { background: #fdf6e7; color: #7a5410; }
.v12-taller__grupo-estado--listo { background: #e6f4ea; color: #1e6e42; }
.v12-taller__grupo-cifra b { font-size: 1.65rem; font-variant-numeric: tabular-nums; line-height: 1; }
.v12-taller__grupo-cifra span { font-size: .78rem; color: var(--v12-gray-500); }
.v12-taller__grupo-avance { height: 6px; border-radius: 999px; background: var(--v12-gray-200); overflow: hidden; }
.v12-taller__grupo-barra { height: 100%; border-radius: 999px; background: var(--v12-fill-accent); }
.v12-taller__grupo-barra--lista { background: #1e6e42; }
.v12-taller__grupo-pie { font-size: .78rem; color: var(--v12-gray-500); display: inline-flex; align-items: center; gap: .15rem; margin-top: .1rem; }
.v12-taller__grupos-mas { margin-top: .75rem; }

/* La propuesta de flujo de Twelvy: se revisa antes de existir. */
.v12-tw__propuesta { border: 1px solid var(--v12-fill-accent); border-radius: var(--v12-r-md); padding: .7rem .85rem; margin-top: .5rem; display: flex; flex-direction: column; gap: .4rem; background: color-mix(in srgb, var(--v12-fill-accent) 5%, var(--v12-white)); }
.v12-tw__propuesta > b { font-size: .95rem; }
.v12-tw__etapas { margin: .2rem 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: .2rem; font-size: .8125rem; }
.v12-tw__etapas li { padding-left: .15rem; }
.v12-tw__propuesta-pie { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-top: .2rem; }
.v12-tw__ir { align-self: flex-start; margin-top: .5rem; text-decoration: none; display: inline-flex; align-items: center; gap: .3rem; }
.v12-taller__grupo-borra { flex: none; color: var(--v12-gray-400); font-size: .8rem; cursor: pointer; padding: 0 .15rem; }
.v12-taller__grupo-borra:hover { color: #b23b3b; }
.v12-taller__miga { display: inline-flex; align-items: center; gap: .5rem; margin: 0 0 .6rem; padding: .3rem .4rem .3rem .8rem; border: 1px solid var(--v12-fill-accent); background: color-mix(in srgb, var(--v12-fill-accent) 8%, var(--v12-white)); color: var(--v12-fill-accent); border-radius: 999px; font-size: .8125rem; font-weight: 600; }
.v12-taller__miga-cierra { border: 0; background: transparent; color: inherit; font-size: 1.05rem; line-height: 1; cursor: pointer; padding: 0 .25rem; }
.v12-taller__guarda { display: inline-flex; align-items: center; gap: .35rem; }
.v12-taller__guarda-nombre { border: 0; border-radius: 8px; padding: .35rem .6rem; font: inherit; font-size: .8125rem; width: 11rem; }

/* Las ponderaciones del cliente: diálogo con advertencia NUESTRA y pinza a la vista. */
.v12-taller__punto { display: inline-block; width: .55rem; height: .55rem; margin-left: .35rem; border-radius: 999px; background: var(--v12-fill-accent); vertical-align: middle; }
.v12-taller__fondo { position: fixed; inset: 0; background: rgba(15, 23, 42, .45); z-index: 1200; display: flex; align-items: center; justify-content: center; padding: 1rem; }
.v12-taller__dialogo { background: var(--v12-white); color: var(--v12-gray-800); border-radius: var(--v12-r-lg); box-shadow: 0 18px 50px rgba(0, 0, 0, .28); width: min(34rem, 100%); max-height: 90vh; overflow: auto; padding: 1.25rem 1.4rem; }
.v12-taller__dialogo h2 { font-size: 1.05rem; margin: 0 0 .75rem; }
.v12-taller__advertencia { border: 1px solid #d9a441; background: #fdf6e7; color: #7a5410; border-radius: var(--v12-r-md); padding: .6rem .8rem; font-size: .8125rem; line-height: 1.45; }
.v12-taller__ctrl-fila { display: grid; grid-template-columns: minmax(0, 1fr) minmax(8rem, 13rem) 3rem; align-items: center; gap: .8rem; padding: .55rem 0; border-bottom: 1px solid var(--v12-gray-100); font-size: .875rem; }
.v12-taller__ctrl-fila label { display: block; }
.v12-taller__ctrl-fila .v12-pc__pista { display: block; font-size: .75rem; }
.v12-taller__banda { position: relative; display: flex; align-items: center; }
.v12-taller__banda input[type='range'] { width: 100%; accent-color: var(--v12-fill-accent); margin: 0; }
.v12-taller__marca-reco { position: absolute; bottom: -3px; width: 2px; height: 7px; background: var(--v12-gray-400); transform: translateX(-50%); pointer-events: none; }
.v12-taller__chip { font-variant-numeric: tabular-nums; text-align: right; font-size: .95rem; }
.v12-taller__ctrl-fila--propia label { font-weight: 700; }
.v12-taller__ctrl-fila--propia .v12-taller__chip { color: var(--v12-fill-accent); }
.v12-taller__leyenda { margin: .4rem 0 .2rem; }
.v12-taller__ejemplo { margin: .8rem 0 .3rem; font-size: .8125rem; color: var(--v12-gray-600); font-style: italic; }
.v12-taller__piso { display: flex; gap: .45rem; align-items: flex-start; background: var(--v12-gray-100); border-radius: var(--v12-r-md); padding: .55rem .8rem; font-size: .8125rem; color: var(--v12-gray-600); margin: 0; }
.v12-taller__dialogo-pie { display: flex; gap: .5rem; margin-top: 1rem; align-items: center; }
.v12-taller__dialogo-hueco { flex: 1; }
