/* Lenguaje de movimiento de toda la app (skill emilkowalski-motion): 150-220ms,
   ease-out en entradas, siempre transform/opacity — nunca top/left/width/height.
   Un usuario con prefers-reduced-motion activado no debería ver nada de esto. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;}
}
:root{
  --azul:#0b4f3d; --azul-claro:#0f6e56; --gris:#f4f6f8; --gris-borde:#d9dee3;
  --texto:#22292f; --verde:#2e7d4f; --amarillo:#c58a00; --rojo:#b3261e; --blanco:#fff;
  /* Paleta de riesgo accesible: varía en claridad además de matiz, y siempre
     se usa junto con un ícono (✓ ✓ ▲ ⚠), nunca solo el color.
     --r-medio se oscureció de #b5720a a #985d08 (auditoría impeccable-design-
     review): el tono original caía a 3.9:1 sobre blanco y 3.4:1 sobre su
     propio tinte de fondo — bajo el mínimo de 4.5:1 para texto normal en el
     chip/badge de riesgo medio. #985d08 da 5.4:1 / 4.7:1 y se ve prácticamente
     igual (mismo matiz ámbar). RIESGO_COLORES.medio en mail.service.ts se
     actualizó igual, por diseño deben coincidir. */
  --r-ninguno:#0f6b52; --r-bajo:#2f8f6f; --r-medio:#985d08; --r-alto:#a3222c;
  /* Mismos tintes que ya se usaban sueltos en .risk-* y .badge-* — aquí como
     variables para poder reusarlos en el gauge de bullet graph. */
  --t-ninguno:#e2edea; --t-bajo:#e6f2ee; --t-medio:#f6eee2; --t-alto:#f4e4e6;
  /* --gris-texto: etiquetas/metadatos secundarios en toda la app (encabezados
     de tabla, "n=" de gráficos, notas al pie...). Antes #8a94a0 (3.1:1 sobre
     blanco, 2.8:1 sobre --gris — reprueba WCAG-AA en los dos casos). #5a6470
     da 6.0:1 / 5.6:1 — mismo gris que ya usaba index.html como --texto-sec. */
  --gris-texto:#5a6470;
  --estatus-revision:#6b7783; --estatus-contratado:#1d6b45; --estatus-no-contratado:#5a6470;
}
*{box-sizing:border-box;}
/* Saltar al contenido (auditoría taste-redesign-audit): invisible hasta que
   recibe foco de teclado — el primer Tab en cualquier página con header/
   stepper/filtros repetidos salta directo al contenido real en vez de tener
   que recorrer todo eso primero. */
.skip-link{
  position:absolute;left:-9999px;top:0;background:var(--azul-claro);color:#fff;
  padding:10px 16px;border-radius:0 0 8px 0;z-index:100;font-size:.85rem;font-weight:600;
  text-decoration:none;
}
.skip-link:focus{left:0;}
body{
  font-family:'Karla',-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
  background:var(--gris); color:var(--texto); margin:0; padding:0;
}
/* Kit de UI: titulares en Space Grotesk (pesos 500/600 únicamente, nunca 700
   para no perder calidez), cuerpo y controles en Karla. */
h1,h2,h3{font-family:'Space Grotesk',-apple-system,sans-serif;font-weight:600;}
/* Íconos de Lucide: heredan el color del texto que los rodea (así se ven
   blancos dentro de un badge de riesgo sin configurar nada aparte). */
.icon-inline{width:13px;height:13px;vertical-align:-2px;stroke:currentColor;margin-right:6px;}
button .icon-inline{margin-right:5px;vertical-align:-2px;}
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}
#app{max-width:880px;margin:0 auto;padding:24px 20px 60px;}
/* El panel de administrador necesita más espacio para tablas y filtros —
   el candidato se queda en el ancho angosto, más legible en móvil. */
#app.ancho{max-width:1180px;}
/* El tope era 1120px, pensado para que la pantalla no se sintiera comprimida
   en monitores grandes. Bajó a 940px: a 1120px las líneas del consentimiento
   y de las preguntas pasaban de 110 caracteres — muy por encima del rango
   cómodo de lectura (65-75), y era lo que obligaba a ponerle max-width a las
   cajas por separado, que a su vez las dejaba desalineadas entre sí. Con 940
   el texto queda en un largo razonable y todas las cajas pueden ocupar el
   ancho completo de la tarjeta. No toca móvil/tablet: ahí manda el
   max-width base. */
@media (min-width:900px){
  #app:not(.ancho){max-width:min(80vw, 940px);}
}
header{padding:18px 0 10px;}
header h1{font-size:1.4rem;margin:0 0 4px;color:var(--azul);}
header p{margin:0;color:var(--gris-texto);font-size:.92rem;}
#progress-bar{height:8px;background:var(--gris-borde);border-radius:4px;overflow:hidden;margin:14px 0 22px;}
#progress-fill{height:100%;background:var(--azul-claro);width:0%;transition:width .3s;}
.card{background:var(--blanco);border:1px solid var(--gris-borde);border-radius:10px;padding:22px 24px;margin-bottom:16px;}
.card h2{margin-top:0;font-size:1.15rem;color:var(--azul);}
.card h3{font-size:.95rem;color:var(--azul-claro);margin:0 0 14px;text-transform:uppercase;letter-spacing:.03em;}
label{display:block;font-size:.85rem;font-weight:600;margin:12px 0 4px;}
input[type=text],input[type=date],input[type=password],input[type=email],select{
  width:100%;padding:9px 10px;border:1px solid var(--gris-borde);border-radius:6px;font-size:.95rem;background:#fff;
}
.question{padding:14px 0;border-bottom:1px solid #eef1f3;}
.question:last-child{border-bottom:none;}
.qtext{font-size:.95rem;margin-bottom:10px;line-height:1.4;}
.qnum{color:var(--gris-texto);font-weight:600;margin-right:6px;}
.likert-row{display:flex;gap:6px;flex-wrap:wrap;}
.likert-opt{flex:1;min-width:90px;}
.likert-opt input{display:none;}
.likert-opt label{
  display:block;text-align:center;font-weight:500;font-size:.78rem;padding:9px 4px;
  border:1px solid var(--gris-borde);border-radius:6px;cursor:pointer;margin:0;color:var(--gris-texto);
  /* Antes: transition:all .15s — animar "all" es impreciso y más caro de lo
     necesario. Se acota a las propiedades que de verdad cambian. */
  transition:background-color .15s ease-out,border-color .15s ease-out,color .15s ease-out,transform .1s ease-out;
}
.likert-opt label:active{transform:scale(.97);}
.likert-opt input:checked + label{background:var(--azul-claro);border-color:var(--azul-claro);color:#fff;}
.mc-opt{margin:6px 0;}
.mc-opt label{display:flex;align-items:center;gap:8px;font-weight:400;font-size:.9rem;cursor:pointer;padding:8px 10px;border:1px solid var(--gris-borde);border-radius:6px;line-height:1.35;}
.mc-opt input:checked + span{font-weight:600;}
.mc-opt input{margin:0;flex-shrink:0;}
.scenario-box{background:#eef3f8;border-left:4px solid var(--azul-claro);border-radius:6px;padding:10px 12px;font-size:.9rem;margin-bottom:10px;font-style:italic;color:#33475b;}
.fc-section{margin-top:24px;padding-top:16px;border-top:2px solid var(--gris-borde);}
.fc-instructions{font-size:.85rem;color:var(--gris-texto);margin-bottom:12px;}
.btn-row{display:flex;justify-content:space-between;margin-top:8px;gap:10px;}
button{
  background:var(--azul-claro);color:#fff;border:none;padding:11px 20px;border-radius:7px;
  font-size:.92rem;font-weight:600;cursor:pointer;
}
button.secondary{background:#fff;color:var(--azul-claro);border:1px solid var(--azul-claro);}
button.ghost{background:transparent;color:var(--azul-claro);border:none;padding:11px 14px;}
button.ghost:hover{background:rgba(15,110,86,.08);}
/* Feedback táctil al presionar (auditoría taste-redesign-audit): antes solo
   había hover, sin ninguna respuesta al clic/tap en sí — un scale sutil
   simula el "click físico" que le falta a una superficie plana. Se excluye
   button:disabled para no dar la sensación de que respondió al tacto. */
button{transition:opacity .15s ease-out,background-color .15s ease-out,transform .1s ease-out;}
button:hover{opacity:.9;}
button:active:not(:disabled){transform:scale(.97);}
button:disabled{opacity:.6;cursor:not-allowed;}
input[type=text]:focus,input[type=date]:focus,input[type=password]:focus,input[type=email]:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--azul-claro);box-shadow:0 0 0 3px rgba(15,110,86,.15);
}
.error-msg{color:var(--rojo);font-size:.85rem;margin-top:8px;display:none;}
/* max-width en los bloques de texto largo (auditoría taste-redesign-audit):
   #app puede llegar a 1120px en escritorio (ver regla de @media min-width:900px
   arriba) — sin límite, un párrafo de advertencia/consentimiento se estira a
   ese ancho completo, muy por encima de las ~65-75ch legibles. */
/* Mismo caso que .consent-box: caja, no bloque de texto — sin max-width. */
.warn-box{background:#fff7e6;border:1px solid #f0c869;border-radius:8px;padding:12px 14px;font-size:.82rem;color:#6b5100;margin-bottom:16px;line-height:1.45;}
/* Kit de UI — "Alertas": fondo blanco + acento de color a la izquierda +
   texto oscuro. Antes llevaban un tinte de fondo sólido, pero con el bullet
   graph la barra ya carga el color (franjas + segmento) — el fondo teñido
   encima se sentía como una capa de rojo/naranja de más. El chip, el borde
   y la barra ya bastan para comunicar el nivel. */
.risk-banner{border-radius:0 8px 8px 0;padding:16px 18px;margin-bottom:18px;border:1px solid var(--gris-borde);border-left:4px solid transparent;background:#fff;}
.risk-ninguno{border-left-color:var(--r-ninguno);}
.risk-bajo{border-left-color:var(--r-bajo);}
.risk-medio{border-left-color:var(--r-medio);}
.risk-alto{border-left-color:var(--r-alto);}
.risk-ninguno h3,.risk-ninguno .chip{color:var(--r-ninguno);}
.risk-bajo h3,.risk-bajo .chip{color:var(--r-bajo);}
.risk-medio h3,.risk-medio .chip{color:var(--r-medio);}
.risk-alto h3,.risk-alto .chip{color:var(--r-alto);}
.risk-note{margin-top:10px;padding-top:10px;border-top:1px solid rgba(0,0,0,.08);font-size:.8rem;color:#5a6470;}
/* Card secundario (p.ej. índice de confiabilidad domicilio): igual que el
   principal pero un poco más compacto y sin titular grande — evita duplicar
   el mensaje cuando ambos caen en el mismo nivel de riesgo. */
.risk-banner-secundario{padding:14px 18px;}
.risk-banner-secundario .chip{margin-bottom:8px;}
.risk-banner-secundario .sub{margin:0 0 10px;}
.risk-banner h3{margin:0 0 4px;font-size:1.05rem;text-transform:none;letter-spacing:normal;}
.risk-banner p{margin:0;font-size:.85rem;color:#4a5560;}
/* Kit de UI — cabecera del gauge: chip de nivel + titular de acción (más
   grande que el porcentaje) + dato de apoyo. La recomendación de siguiente
   paso es lo primero que se ve, no el número. */
.risk-banner .chip{display:inline-flex;align-items:center;padding:3px 10px;border-radius:20px;font-size:.7rem;font-weight:700;background:rgba(0,0,0,.06);margin-bottom:10px;}
.risk-banner .accion{margin:0 0 4px;font-size:1.3rem;line-height:1.2;}
.risk-banner .sub{font-size:.85rem;margin:0 0 14px;color:#4a5560;}
.risk-banner .sub b{font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:1rem;color:var(--texto);}
.risk-banner .desc{margin:10px 0 0;font-size:.85rem;color:#4a5560;}
/* Panel "Información de la prueba" — consolida metadatos dispersos (puesto,
   área, estatus, fechas) en un solo lugar, útil como bitácora si la empresa
   necesita documentar por qué tomó su decisión. */
.meta-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:14px 20px;margin-top:4px;}
.meta-item .lbl{font-size:.72rem;color:var(--gris-texto);text-transform:uppercase;letter-spacing:.03em;margin-bottom:3px;}
.meta-item .val{font-size:.88rem;font-weight:600;color:var(--texto);}
.bar-row{margin:14px 0;}
.bar-label{display:flex;justify-content:space-between;font-size:.85rem;font-weight:600;margin-bottom:4px;}
.bar-bg{background:var(--gris-borde);border-radius:5px;height:14px;overflow:hidden;}
.bar-fill{height:100%;background:var(--azul-claro);border-radius:5px;}
.bar-desc{font-size:.8rem;color:var(--gris-texto);margin-top:3px;line-height:1.4;}
.sub-bar .bar-fill{background:#8aa9c4;}
.quality-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-top:10px;}
@media (max-width:600px){.quality-grid{grid-template-columns:1fr 1fr;}}
.quality-item{border:1px solid var(--gris-borde);border-radius:8px;padding:12px;text-align:center;}
.quality-item .qlabel{font-size:.75rem;color:var(--gris-texto);text-transform:uppercase;letter-spacing:.03em;margin-bottom:6px;}
.quality-item .qval{font-size:1rem;font-weight:700;}
.qval.ok{color:var(--verde);}
.qval.warn{color:var(--amarillo);}
.qval.bad{color:var(--rojo);}
.actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:20px;}
/* Grises consolidados a --gris-texto (auditoría taste-redesign-audit): antes
   este mismo rol de "texto secundario" usaba grises neutros sueltos (#555,
   #666, #888, #9aa3ad) mezclados con la familia con tinte azulado que ya
   existía en risk-banner/notes/consent (#4a5560, #3a4450...) — dos familias
   de gris distintas para el mismo propósito. Se unifican los neutros hacia
   --gris-texto, que además mejora el contraste en varios casos. */
footer{font-size:.75rem;color:var(--gris-texto);text-align:center;margin-top:30px;line-height:1.5;}
table{width:100%;border-collapse:collapse;font-size:.88rem;}
table th, table td{text-align:left;padding:14px 10px;border-bottom:1px solid #eef1f3;}
table th{color:var(--gris-texto);font-weight:600;font-size:.78rem;}
tr.clickable{cursor:pointer;}
/* Mismo caso que .opcion-btn:hover (ver comentario allá): en tablet el hover
   pegado dejaría una fila resaltada como si estuviera seleccionada. */
@media (hover:hover){
  tr.clickable:hover{background:#f7f9fb;}
}
/* Kit de UI — "Insignias de riesgo": píldora con fondo suave, texto del
   color de la marca semántica, y un punto (currentColor) — nunca relleno
   sólido con texto blanco, para que el color en sí no sea la única señal. */
.badge{display:inline-flex;align-items:center;gap:6px;padding:4px 12px;border-radius:20px;font-size:.75rem;font-weight:700;white-space:nowrap;}
.badge::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor;flex-shrink:0;}
.badge-ninguno{background:#e2edea;color:var(--r-ninguno);}
.badge-bajo{background:#e6f2ee;color:var(--r-bajo);}
.badge-medio{background:#f6eee2;color:var(--r-medio);}
.badge-alto{background:#f4e4e6;color:var(--r-alto);}
.badge-en_revision{background:#edeff0;color:var(--estatus-revision);}
.badge-contratado{background:#e4ede9;color:var(--estatus-contratado);}
.badge-no_contratado{background:#f1f2f4;color:var(--estatus-no-contratado);}
select.select-estatus{width:auto;display:inline-block;padding:6px 10px;font-size:.82rem;font-weight:600;border-radius:20px;border:1px solid var(--gris-borde);background:#fafbfc;color:var(--texto);}
/* Borde punteado se reserva por convención para "vacío/por llenar" — una nota
   ya guardada usa un acento sólido, igual que .scenario-box en el resto de la app. */
.notes-box{border:1px solid var(--gris-borde);border-left:3px solid var(--azul-claro);border-radius:0 8px 8px 0;padding:12px 14px;font-size:.85rem;color:#4a5560;background:#fafbfc;margin-top:8px;}
.notes-box + .notes-box{margin-top:8px;}
.notes-empty{font-size:.85rem;color:var(--gris-texto);font-style:italic;margin:8px 0;}
.nota-meta{font-size:.72rem;color:var(--gris-texto);margin-top:6px;display:flex;align-items:center;}
textarea.nota-input{width:100%;padding:9px 10px;border:1px solid var(--gris-borde);border-radius:6px;font-size:.9rem;font-family:inherit;resize:vertical;min-height:60px;}
.nota-counter{font-size:.72rem;color:var(--gris-texto);text-align:right;margin-top:4px;}
.nota-counter.limite{color:var(--r-alto);font-weight:600;}
/* Incidentes: mismo patrón que las notas pero con acento rojo — son datos
   distintos (hechos confirmados post-contratación, no observaciones internas). */
.incident-box{border:1px solid var(--gris-borde);border-left:3px solid var(--r-alto);border-radius:0 8px 8px 0;padding:12px 14px;font-size:.85rem;color:#4a5560;background:#fdf6f5;margin-top:8px;}
.incident-tipo{display:inline-block;font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--r-alto);margin-bottom:4px;}
select.incidente-tipo{width:100%;padding:9px 10px;border:1px solid var(--gris-borde);border-radius:6px;font-size:.9rem;background:#fff;margin-bottom:8px;}
.incident-hint{font-size:.82rem;color:var(--gris-texto);margin:8px 0;}
.nav-link{font-size:.85rem;color:var(--azul-claro);text-decoration:none;font-weight:600;display:inline-flex;align-items:center;}
.nav-link:hover{text-decoration:underline;}

/* Barra de plataforma (super_admin viendo el panel de una organización).
   Va fuera de #app para poder ser de ancho completo; su contenido interno
   se alinea al mismo max-width que el resto del panel. Oculta por defecto
   — el script la muestra solo si corresponde. */
.barra-plataforma{background:var(--azul);color:#fff;display:none;}
.barra-plataforma.activa{display:block;}
.barra-plataforma-inner{max-width:1180px;margin:0 auto;padding:0 20px;display:flex;align-items:center;justify-content:space-between;height:46px;font-size:.85rem;flex-wrap:wrap;gap:6px;}
.bp-izq{display:flex;align-items:center;gap:10px;}
.bp-badge{display:flex;align-items:center;gap:6px;font-size:.72rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#fff;opacity:.75;}
.bp-sep{width:1px;height:16px;background:rgba(255,255,255,.25);}
.bp-switcher{position:relative;}
.bp-switcher-btn{display:flex;align-items:center;gap:7px;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.18);color:#fff;padding:6px 12px;border-radius:7px;font-size:.85rem;font-weight:600;font-family:'Karla',sans-serif;cursor:pointer;}
.bp-switcher-btn:hover{background:rgba(255,255,255,.16);}
.bp-switcher-btn .chev{transition:transform .15s;margin:0;}
.bp-switcher-btn.abierto .chev{transform:rotate(180deg);}
/* Antes: display:none/block — abría y cerraba en seco. Ahora transiciona
   opacidad + un leve desplazamiento; visibility+pointer-events reemplazan lo
   que hacía display:none (fuera del tab order y sin clicks mientras está
   cerrado), sin tocar el JS que ya solo hace classList.toggle('abierta'). */
.bp-dropdown{position:absolute;top:calc(100% + 8px);left:0;background:#fff;color:var(--texto);border-radius:10px;box-shadow:0 12px 32px rgba(11,79,61,.18);width:280px;padding:6px;z-index:30;
  opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-6px);
  transition:opacity .15s ease-out,transform .15s ease-out,visibility 0s linear .15s;}
.bp-dropdown.abierta{opacity:1;visibility:visible;pointer-events:auto;transform:translateY(0);transition:opacity .15s ease-out,transform .15s ease-out;}
.bp-dropdown-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 10px;border-radius:7px;cursor:pointer;font-size:.85rem;}
.bp-dropdown-item:hover{background:var(--gris);}
.bp-dropdown-item .nombre{font-weight:600;}
.bp-dropdown-item .meta{font-size:.72rem;color:var(--gris-texto);}
.bp-dropdown-item svg{width:15px;height:15px;color:var(--azul-claro);flex-shrink:0;}
.bp-dropdown-sep{height:1px;background:var(--gris-borde);margin:6px 4px;}
.bp-dropdown-link{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:7px;cursor:pointer;font-size:.83rem;color:var(--azul-claro);font-weight:600;}
.bp-dropdown-link:hover{background:var(--gris);}
.bp-ver-todas{display:flex;align-items:center;gap:6px;color:#fff;opacity:.85;text-decoration:none;font-size:.83rem;}
.bp-ver-todas:hover{opacity:1;text-decoration:underline;}
/* Pantalla de validación */
.stat-row{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:20px;}
@media (max-width:700px){.stat-row{grid-template-columns:1fr 1fr;}}
.stat{border:1px solid var(--gris-borde);border-radius:10px;padding:13px 15px;}
.stat .num{font-size:1.4rem;font-weight:700;color:var(--azul);line-height:1.2;}
.stat .lbl{font-size:.71rem;color:var(--gris-texto);text-transform:uppercase;letter-spacing:.03em;}
.chart{display:flex;align-items:flex-end;gap:14px;height:170px;padding:10px 0 0;border-bottom:1px solid var(--gris-borde);}
.chart .col{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;gap:6px;height:100%;}
/* Antes: transition:height .3s — animar height es una propiedad de layout
   (causa reflow) y en la práctica nunca se veía animar porque el JS ya
   insertaba la barra con su altura final. Ahora la altura queda fija de
   entrada (se sigue calculando igual en el JS) y lo que transiciona es
   transform:scaleY, que arranca en 0 y crece al agregar .cb-lista. */
.chart .cb{width:100%;border-radius:5px 5px 0 0;min-height:2px;transform-origin:bottom;transform:scaleY(0);transition:transform .35s ease-out;}
.chart .cb.cb-lista{transform:scaleY(1);}
.chart .cl{font-size:.72rem;color:var(--gris-texto);text-align:center;}
/* Bloque D: consentimiento + progreso por sección */
/* Sin max-width: es una caja con borde y fondo, no un bloque de texto suelto.
   Con 70ch quedaba a media anchura mientras .consent-check (abajo) ocupaba
   todo el ancho, y ese desalineado entre las dos cajas se leía como un error
   de layout. El largo de línea se controla acotando el contenedor del
   candidato (ver #app), que es donde corresponde. */
.consent-box{border:1px solid var(--gris-borde);border-radius:8px;padding:16px 18px;font-size:.9rem;color:#3a4450;line-height:1.6;margin-bottom:14px;background:#fafbfc;}
.consent-box p{margin:0 0 10px;}
.consent-box p:last-child{margin-bottom:0;}
.consent-check{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border:1px solid var(--gris-borde);border-radius:8px;cursor:pointer;background:#fff;}
.consent-check input{margin-top:3px;flex-shrink:0;}
.consent-check span{font-size:.88rem;line-height:1.45;color:var(--texto);}
.print-only{display:none;}
/* Barra de progreso segmentada (una pregunta a la vez). #stepper es el
   contenedor fijo en index.html — debe apilar sus dos hijos (.seg-row y
   .seg-labels) uno debajo del otro, por eso NO lleva display:flex aquí
   (un display:flex por accidente los ponía lado a lado y aplastaba las
   barras de color casi a cero ancho). */
#stepper{display:block;margin:0 0 20px;}
#stepper:empty{display:none;}
.seg-row{display:flex;gap:8px;margin:0 0 8px;}
.seg{flex:1;height:8px;border-radius:4px;background:#dde2e7;transition:background-color .2s ease-out;}
.seg.active{background:var(--azul-claro);}
.seg.done{background:var(--verde);}
.seg-labels{display:flex;gap:8px;}
.seg-label{flex:1;font-size:.72rem;color:var(--gris-texto);text-align:left;line-height:1.3;transition:color .2s ease-out;}
.seg-label.active{color:var(--azul-claro);font-weight:700;}
.seg-label.done{color:var(--verde);}
@media (max-width:640px){.seg-label{font-size:.62rem;}}

.pregunta-meta{font-size:.82rem;color:var(--gris-texto);margin:-8px 0 20px;}
.qtext-grande{font-size:1.05rem;font-weight:500;line-height:1.55;margin-bottom:20px;color:var(--texto);max-width:65ch;}
.opciones-grid{display:flex;gap:8px;flex-wrap:wrap;}
.opciones-lista{display:flex;flex-direction:column;gap:8px;}
/* Antes: transition:all .15s (mismo caso que .likert-opt label). */
.opcion-btn{flex:1;min-width:110px;padding:14px 12px;border:1px solid var(--gris-borde);border-radius:8px;background:#fff;font-size:.85rem;font-weight:500;font-family:inherit;color:var(--texto);cursor:pointer;text-align:center;transition:background-color .15s ease-out,border-color .15s ease-out,color .15s ease-out;}
.opcion-btn.ancha{width:100%;text-align:left;padding:14px 16px;}
/* @media (hover:hover) es obligatorio aquí, no un adorno: en una pantalla
   táctil no hay cursor, así que iOS/Android SIMULAN el hover sobre el último
   punto que tocaste y lo dejan pegado hasta que toques otra cosa. Como al
   pasar de pregunta el contenido se vuelve a dibujar, la opción que queda
   debajo de ese punto heredaba el borde verde y parecía ya seleccionada
   (reportado en producción: "Internet parece preseleccionada"). Con esto la
   regla solo existe en dispositivos con cursor real. */
@media (hover:hover){
  .opcion-btn:hover{border-color:var(--azul-claro);}
}
.opcion-btn.seleccionada{background:var(--azul-claro);border-color:var(--azul-claro);color:#fff;font-weight:700;}
/* Revelado de entrada del candidato: render() en app.js reemplaza por
   completo el contenido de #content en cada paso (pregunta, intro,
   consentimiento, final...) envolviéndolo en <div class="pantalla">. Al ser
   un nodo nuevo cada vez, la animación se re-dispara sola sin necesitar
   trucos de reflow en JS. */
.pantalla{animation:pantalla-entra .2s ease-out;}
@keyframes pantalla-entra{
  from{opacity:0;transform:translateY(8px);}
  to{opacity:1;transform:translateY(0);}
}

/* Dashboard: teclado en filas de tabla (auditoría impeccable-design-review) —
   tr.clickable ya trae tabindex/role por JS; solo falta el foco visible. */
tr.clickable:focus-visible{outline:2px solid var(--azul-claro);outline-offset:-2px;}

/* Encabezados de tabla ordenables. */
.th-orden{cursor:pointer;user-select:none;}
.th-orden:hover{color:var(--azul-claro);}
.orden-flecha{display:inline-block;width:10px;margin-left:2px;font-size:.7rem;}

/* Toast: reemplaza los alert() nativos (rompían la consistencia visual del
   resto del panel, ya rediseñado a medida). Mismo lenguaje visual que
   .bp-dropdown: opacity+transform+visibility, nunca display, para poder
   transicionar sin animar layout. */
.toast{
  position:fixed;bottom:22px;left:50%;max-width:360px;width:calc(100% - 40px);
  background:var(--texto);color:#fff;padding:13px 16px;border-radius:9px;font-size:.85rem;
  /* Sombra con tinte de marca en vez de negro puro (auditoría taste-redesign-
     audit) — mismo tratamiento que .reporte-card en index.html, ya lo hacía
     bien ahí pero no se había propagado a este stylesheet. */
  box-shadow:0 16px 40px rgba(11,79,61,.22);z-index:70;text-align:center;
  opacity:0;visibility:hidden;pointer-events:none;
  transform:translate(-50%,8px);
  transition:opacity .2s ease-out,transform .2s ease-out,visibility 0s linear .2s;
}
.toast.mostrando{opacity:1;visibility:visible;transform:translate(-50%,0);transition:opacity .2s ease-out,transform .2s ease-out;}
.toast.toast-error{background:var(--r-alto);}

/* Modal de confirmación — se usa para acciones con consecuencia real (ej.
   cambiar el Estatus de un candidato), donde interrumpir es lo correcto en
   vez de aplicar el cambio de una vez (ver piso de craft: "un modal para una
   tarea que sí necesita interrupción/foco protegido" es la excepción válida
   a evitar modales por default). */
.modal-overlay{
  position:fixed;inset:0;background:rgba(15,20,25,.45);display:flex;align-items:center;justify-content:center;
  padding:20px;z-index:80;
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .15s ease-out,visibility 0s linear .15s;
}
.modal-overlay.abierto{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .15s ease-out;}
.modal-card{
  background:#fff;border-radius:12px;padding:22px 24px;max-width:380px;width:100%;
  box-shadow:0 24px 60px rgba(11,79,61,.28);transform:scale(.96);transition:transform .15s ease-out;
}
.modal-overlay.abierto .modal-card{transform:scale(1);}
.modal-card p{margin:0;font-size:.92rem;color:var(--texto);line-height:1.5;}

/* Gauge del dashboard: la barra de score aparece de golpe mientras el gráfico
   de Validación sí crece con transform (mismo patrón, aquí en horizontal).
   transform-box:fill-box hace que transform-origin se calcule sobre la caja
   del propio <rect> en vez del viewport del SVG completo — sin esto,
   scaleX(0) no arranca desde el borde izquierdo de la barra. */
.gauge-score{transform-box:fill-box;transform-origin:0 0;transform:scaleX(0);transition:transform .4s ease-out;}
.gauge-score.gauge-lista{transform:scaleX(1);}
/* .gauge-ayuda vive DENTRO del risk-banner, pegada bajo la línea ".sub" — de
   ahí el margen superior negativo. No sirve para notas sueltas después de
   otro bloque: ese -6px las encima con lo de arriba (pasó con la nota de
   "Calidad de respuesta", que quedó montada sobre las tarjetas). Para esas
   usar .nota-ayuda, que sí respeta el flujo normal. */
.gauge-ayuda{font-size:.78rem;color:var(--gris-texto);margin:-6px 0 12px;}
.nota-ayuda{font-size:.78rem;color:var(--gris-texto);margin:10px 0 4px;max-width:75ch;}

@media print{
  button,.actions,#progress-bar,.warn-box,.no-print{display:none !important;}
  body{background:#fff;}
  .card{border:none;box-shadow:none;padding:0;margin-bottom:20px;}
  .print-only{display:inline;}
}
