/*
 * ============================================
 *  components.css — Veriko componentes compartidos (rediseño Fase 1)
 * ============================================
 *  Bloques de UI REUTILIZABLES entre páginas. Cualquier pantalla los usa tal
 *  cual; no se redefinen por-página (eso causa inconsistencia). Solo roles de
 *  token. Carga después de shell.css. En producción reemplaza a components.css.
 *
 *  Inventario:
 *   - Base: botones · card · section/heading · link-more · verdict (color+icono+
 *     texto) · tabla densa + celdas · bank-chip · list-row · usage · stat · quick.
 *   - Listas/filtros (hero #3): page-head · icon-action · field-search · segs ·
 *     filterbar/chip · count-note/results-meta · type-tag/row-action · pager ·
 *     dropdown · sheet/drawer · chip-set/chip-opt · amount-row.
 *   - Wizard/formulario (hero #3): step-bar · sel-card · dropzone/upload/ocr-hint ·
 *     field · options/option-row/switch · retry-config (slider/select/chips/preview) ·
 *     proc-state. (El FRAME del modal .wz* vive en su pantalla.)
 *   - Detalle/veredicto (hero #3): detail-back · verdict-hero · detail-card-title ·
 *     data-rows (.dl) · timeline · detail-actions. (Layout 2-col + CEP en la pantalla.)
 * ============================================
 */

/* ---------- Botones ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); min-height: 44px; padding: 0 var(--space-4); border-radius: var(--btn-radius); border: 1px solid transparent; font-size: var(--text-sm); font-weight: var(--font-semibold); font-family: inherit; cursor: pointer; transition: background var(--transition-fast); }
.btn .icon { width: 1.125rem; height: 1.125rem; }
.btn-primary { background: var(--color-primary); color: var(--color-primary-contrast); }
.btn-primary:hover { background: var(--color-primary-hover); }
.btn-ghost { background: transparent; color: var(--color-text-secondary); border-color: var(--color-border); }
.btn-ghost:hover { background: var(--color-surface-sunken); color: var(--color-text-primary); }
.btn-block { width: 100%; }
.btn-lg { min-height: 48px; font-size: var(--text-base); }

/* ---------- Card ---------- */
.card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--card-radius); }

/* ---------- Section + heading ---------- */
.section { display: flex; flex-direction: column; gap: var(--space-3); }
.section-head { display: flex; align-items: center; justify-content: space-between; }
.section-title { font-size: var(--text-base); font-weight: var(--font-semibold); margin: 0; }
.link-more { color: var(--color-text-link); font-weight: var(--font-medium); display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-sm); }
.link-more .icon { width: 1rem; height: 1rem; }

/* ---------- Verdict badge (SIEMPRE color + icono + texto — design.md §6) ---------- */
.verdict { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; border-radius: var(--badge-radius); font-size: 11px; font-weight: var(--font-semibold); white-space: nowrap; }
.verdict .icon { width: 13px; height: 13px; }
.verdict.ok { background: var(--color-success-light); color: var(--color-success-text); }
.verdict.no { background: var(--color-danger-light); color: var(--color-danger-text); }
.verdict.pending { background: var(--color-warning-light); color: var(--color-warning-text); }
.verdict.processing { background: var(--color-info-light); color: var(--color-info-text); }   /* async en proceso (color + icono giratorio + texto) */
.verdict.processing .icon { animation: verdict-spin 1s linear infinite; }
@keyframes verdict-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .verdict.processing .icon { animation: none; } }

/* ---------- Tabla densa ---------- */
.table-wrap { overflow-x: auto; }
table.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table thead th { text-align: left; font-size: var(--text-xs); font-weight: var(--font-semibold); letter-spacing: .04em; text-transform: uppercase; color: var(--color-text-tertiary); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-border); }
.table tbody td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-border); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--table-row-hover); }
.cell-amount { text-align: right; font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.cell-amount small { font-weight: var(--font-normal); color: var(--color-text-tertiary); font-size: var(--text-xs); }
.cell-amount.is-neg { color: var(--color-danger-text); }

/* Celda de usuario (avatar + nombre + correo). Canónico — convergencia ×5
   (usuarios·validaciones·facturación·seguridad·beneficiarios). El correo va en mono
   con .is-mono (4/5 lo usan; facturación queda sans). */
.user-cell { display: inline-flex; align-items: center; gap: var(--space-2-5); min-width: 0; }
.user-cell .avatar-sm { background: var(--color-surface-sunken); color: var(--color-text-secondary); }
.user-cell-text { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.user-cell-name { font-weight: var(--font-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-cell-name a { color: var(--color-text-link); }
.user-cell-name a:hover { text-decoration: underline; }
.user-cell-mail { font-size: var(--text-xs); color: var(--color-text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-cell-mail.is-mono { font-family: var(--font-family-mono); }
.cell-num { text-align: right; font-variant-numeric: tabular-nums; }   /* numérico simple (intento/tiempo/conteo): derecha + tnum, sin negrita */
.cell-bene { display: flex; align-items: center; gap: var(--space-2); }
.cell-mono { font-family: var(--font-family-mono); }
/* Pie de tabla: contador + enlace «ver todas». De admin/usuarios/detalle (cualquier tabla con resumen). */
.table-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-border); }
.table-foot-count { font-size: var(--text-xs); color: var(--color-text-tertiary); }

/* ---------- Bank chip (avatar de banco) ---------- */
.bank-chip { width: 36px; height: 36px; border-radius: var(--radius-md); background: var(--color-surface-sunken); display: grid; place-items: center; font-size: 10px; font-weight: var(--font-bold); color: var(--color-text-secondary); flex: 0 0 auto; }

/* ---------- List-row (lista de entidades en tarjetas — móvil/tablet) ---------- */
.recent-cards { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.rcard { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); min-height: 64px; }
/* Cuerpo en columna: línea (nombre + monto) · CLABE a ancho completo · veredicto abajo.
   Así la cuenta beneficiaria (CLABE larga) vive en su propia línea y se ve COMPLETA. */
.rcard-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--space-1); }
.rcard-line { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.rcard-name { font-weight: var(--font-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
.rcard-amount { font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.rcard-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); }
.rcard-main > .verdict { align-self: flex-start; margin-top: 2px; } /* dashboard: veredicto suelto */
/* Fila meta (lista densa): tipo · veredicto · fecha — bajo la CLABE, con wrap.
   El dashboard no la usa (su veredicto va suelto en .rcard-main). */
.rcard-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: 2px; }
.rcard-type { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-xs); color: var(--color-text-secondary); }
.rcard-type .icon { width: 14px; height: 14px; }
.rcard-date { font-size: var(--text-xs); color: var(--color-text-tertiary); }
.recent-table { display: none; } /* lista densa: tarjetas en chico, tabla en grande */
/* Tarjetas CON monto: monto DEBAJO de la cuenta/CLABE y en grande (directiva owner, paseo C4).
   Aplica a toda .rcard que tenga .rcard-amount (dashboard · validaciones · finanzas);
   beneficiarios/insights no tienen monto → no les afecta. .rcard-line display:contents pasa
   nombre y monto a ser hijos del .rcard-main (columna) y se reordena:
   nombre → cuenta/CLABE → monto(grande) → meta/veredicto. */
.rcard-line:has(.rcard-amount) { display: contents; }
.rcard-main:has(.rcard-amount) .rcard-name { order: 1; }
.rcard-main:has(.rcard-amount) .rcard-sub  { order: 2; }
.rcard-main:has(.rcard-amount) .rcard-amount { order: 3; margin-top: 2px; font-size: var(--text-xl); font-weight: var(--font-bold); font-variant-numeric: tabular-nums; }
.rcard-main:has(.rcard-amount) .rcard-meta,
.rcard-main:has(.rcard-amount) > .verdict { order: 4; }

/* ---------- Usage (barra de uso del plan) ---------- */
.usage { padding: var(--space-4) var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); }
.usage-top { display: flex; align-items: center; justify-content: space-between; }
.usage-plan { font-weight: var(--font-semibold); }
.usage-plan small { color: var(--color-text-tertiary); font-weight: var(--font-normal); }
.usage-bar { height: 8px; border-radius: var(--badge-radius); background: var(--color-surface-sunken); overflow: hidden; }
.usage-fill { height: 100%; background: var(--color-accent); }
.usage-meta { display: flex; justify-content: space-between; font-size: var(--text-xs); color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; }
/* Acciones del card de uso: al fondo, a la derecha (directiva owner) */
.usage-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-4); margin-top: var(--space-1); }

/* ---------- Stat (tarjeta de métrica compacta) ---------- */
.ministats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
.ministat { padding: var(--space-3); }
.ministat-val { font-size: var(--text-xl); font-weight: var(--font-bold); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.ministat-label { color: var(--color-text-secondary); font-size: var(--text-xs); margin-top: 2px; line-height: 1.2; }

/* ---------- Quick action (tarjeta de acción rápida) ---------- */
.quick-row { display: grid; grid-template-columns: 1fr; gap: var(--space-2); }
.quick { display: flex; align-items: center; gap: var(--space-3); text-align: left; padding: var(--space-3) var(--space-4); min-height: 56px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--card-radius); }
.quick:hover { border-color: var(--color-border-strong); background: var(--color-surface-sunken); }
.quick-ico { width: 40px; height: 40px; border-radius: var(--radius-md); background: var(--color-accent-light); color: var(--color-accent); display: grid; place-items: center; flex: 0 0 auto; }
.quick-title { font-weight: var(--font-semibold); }
.quick-copy { font-size: var(--text-xs); color: var(--color-text-tertiary); }

/* ============================================================
   Responsive de componentes.
   ============================================================ */
@media (min-width: 768px) {
    .quick-row { grid-template-columns: repeat(3, 1fr); }
    .ministat-val { font-size: var(--text-2xl); }
}
@media (min-width: 1100px) {
    .recent-cards { display: none; }   /* en grande, la lista se muestra como tabla */
    .recent-table { display: block; }
}

/* ============================================================
   LISTAS / FILTROS / DROPDOWN / DRAWER (extraído del hero #3)
   ------------------------------------------------------------
   Bloques reutilizables de cualquier pantalla de lista/CRUD. Los
   interactivos (dropdown, sheet/drawer) son el ESTILO; el comportamiento en
   producción usa las primitivas canónicas APP.dropdown / APP.drawer (ui.js).
   ============================================================ */

/* Encabezado de página */
/* Wrapper de página (#page-*) transparente: los mocks ponen las secciones DIRECTAS en
   .content (que es flex column con gap). Al envolverlas en #page-* (block) se perdía ese
   gap → secciones apretadas. display:contents devuelve las secciones a hijas directas del
   .content, recuperando el gap (idéntico al mock). Los selectores #page-* descendientes
   siguen funcionando. */
.content > [id^="page-"] { display: contents; }
/* Canon: las acciones del header NUNCA van inline con el título (a la derecha);
   se apilan DEBAJO del subtítulo, en una fila (los botones sí inline entre sí). */
.page-head { display: flex; flex-direction: column; align-items: stretch; gap: var(--space-4); margin-bottom: var(--space-8); }
.page-title { font-size: var(--text-xl); font-weight: var(--font-bold); letter-spacing: -.02em; margin: 0; }
.page-sub { color: var(--color-text-secondary); font-size: var(--text-sm); margin: var(--space-1) 0 0; }
.page-actions { display: flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; }

/* Botón de icono cuadrado (+ variante de acento) */
.icon-action { width: 40px; height: 40px; display: grid; place-items: center; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text-secondary); cursor: pointer; }
.icon-action:hover { background: var(--color-surface-sunken); color: var(--color-text-primary); }
.icon-action--accent { background: var(--color-primary); border-color: transparent; color: var(--color-primary-contrast); }
.icon-action--accent:hover { background: var(--color-primary-hover); color: var(--color-primary-contrast); }

/* Buscador de campo (página/lista) */
.field-search { position: relative; display: flex; align-items: center; }
.field-search .icon { position: absolute; left: var(--space-3); width: 1.125rem; height: 1.125rem; color: var(--color-text-tertiary); pointer-events: none; }
.field-search input { width: 100%; min-width: 0; height: var(--input-height); padding: 0 var(--space-3) 0 calc(var(--space-3) + 26px); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text-primary); font-size: var(--text-sm); font-family: inherit; }
.field-search input:focus { outline: none; border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }

/* Cluster de filtros: búsqueda + tabs + barra, compacto */
.filters { display: flex; flex-direction: column; gap: var(--space-3); }

/* Segmentos de estado (triage + conteo) */
.segs { display: flex; gap: var(--space-2); overflow-x: auto; padding-bottom: 2px; scrollbar-width: none; }
.segs::-webkit-scrollbar { display: none; }
.seg { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 var(--space-3); border: 1px solid var(--color-border); border-radius: var(--badge-radius); background: var(--color-surface); color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: var(--font-medium); white-space: nowrap; cursor: pointer; }
.seg:hover { background: var(--color-surface-sunken); }
.seg .count { font-variant-numeric: tabular-nums; color: var(--color-text-tertiary); font-size: var(--text-xs); }
.seg .sdot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
.sdot.ok { background: var(--color-success); } .sdot.pending { background: var(--color-warning); } .sdot.no { background: var(--color-danger); } .sdot.proc { background: var(--color-info); }
.seg.active { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-text-inverse); }
.seg.active .count { color: rgba(255,255,255,.82); }
.seg.active .sdot { box-shadow: 0 0 0 2px rgba(255,255,255,.5); }

/* Barra de chips de filtro */
.filterbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.filterbar-spacer { flex: 1; }
.chip { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: var(--font-medium); cursor: pointer; }
.chip:hover { background: var(--color-surface-sunken); color: var(--color-text-primary); }
.chip .icon { width: 1rem; height: 1rem; color: var(--color-text-tertiary); }
/* Contador de filtros activos dentro de un .chip (botón "Filtros"). De admin/validaciones/lista. */
.chip-count { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; margin-left: 2px; border-radius: var(--radius-full); background: var(--color-accent); color: var(--color-text-inverse); font-size: 11px; font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; line-height: 1; }
.chip-count[hidden] { display: none; }

/* Filtros activos removibles + Limpiar (fila de chips bajo la barra de filtros).
   Canónico — convergencia de usuarios/beneficiarios/notificaciones (PR convergencia IA). */
.filter-active { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.filter-active[hidden] { display: none; }
.filter-active-label { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-right: var(--space-1); }
.filter-chip {
    display: inline-flex; align-items: center; gap: 4px;
    height: 30px; padding: 0 4px 0 var(--space-3);
    border: 1px solid var(--color-accent);
    background: var(--color-accent-light);
    color: var(--color-text-link);
    border-radius: var(--badge-radius);
    font-size: var(--text-xs); font-weight: var(--font-medium);
    white-space: nowrap;
}
.filter-chip-x {
    display: grid; place-items: center; width: 20px; height: 20px;
    border: 0; background: transparent; color: inherit;
    border-radius: 50%; cursor: pointer; flex: 0 0 auto; padding: 0;
}
.filter-chip-x:hover { background: var(--color-surface); }
.filter-chip-x .icon { width: 13px; height: 13px; }
.filters-clear {
    background: transparent; border: 0; padding: 0 var(--space-1);
    color: var(--color-text-link); font-family: inherit;
    font-size: var(--text-xs); font-weight: var(--font-semibold); cursor: pointer;
}
.filters-clear:hover { text-decoration: underline; }

/* Conteo de resultados + fila de resultados (conteo izq · acciones der) */
.count-note { color: var(--color-text-tertiary); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.results-meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.results-actions { display: flex; align-items: center; gap: var(--space-2); }

/* Tabla: etiqueta de tipo + acción de fila (kebab) */
.type-tag { font-size: var(--text-xs); color: var(--color-text-secondary); display: inline-flex; align-items: center; gap: 5px; }
.type-tag .icon { width: 14px; height: 14px; color: var(--color-text-tertiary); }
.row-action { width: 40px; height: 40px; display: grid; place-items: center; border: 0; border-radius: var(--radius-md); background: transparent; color: var(--color-text-tertiary); cursor: pointer; }
.row-action:hover { background: var(--color-surface-sunken); color: var(--color-text-primary); }

/* List-row: extras (tipo + fecha). La base .rcard está más arriba. */
.rcard { cursor: pointer; }
.rcard-type { font-size: var(--text-xs); color: var(--color-text-tertiary); display: inline-flex; align-items: center; gap: 4px; }
.rcard-type .icon { width: 12px; height: 12px; }
.rcard-date { font-size: var(--text-xs); color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; }

/* Paginación */
.pager { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding-top: var(--space-2); }
.pager-info { color: var(--color-text-tertiary); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }

/* Dropdown / popover — ESTILO; en prod el comportamiento = APP.dropdown */
.dropdown-wrap { position: relative; flex: 0 0 auto; }
.dropdown { position: absolute; top: calc(100% + 6px); left: 0; min-width: 200px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-1); z-index: var(--z-popover); }
.dropdown[hidden] { display: none; }
.dropdown-item { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); width: 100%; min-height: 38px; padding: 0 var(--space-2-5); border: 0; border-radius: var(--radius-md); background: transparent; color: var(--color-text-primary); font-size: var(--text-sm); font-family: inherit; cursor: pointer; text-align: left; }
.dropdown-item:hover { background: var(--color-surface-sunken); }
.dropdown-item .check { width: 1rem; height: 1rem; color: var(--color-accent); visibility: hidden; }
.dropdown-item[aria-selected="true"] { color: var(--color-text-link); font-weight: var(--font-semibold); }
.dropdown-item[aria-selected="true"] .check { visibility: visible; }
.ddi-label { display: inline-flex; align-items: center; gap: var(--space-2-5); min-width: 0; }   /* icono+texto de un .dropdown-item (menú ⋯) — canónico (convergencia bn/mg/op) */
.menu-go { width: 1rem; height: 1rem; color: var(--color-text-tertiary); }   /* chevron "ir a" al final de un ítem de menú */

/* Diff badge (cambios en step-up): etiqueta mayúscula + valor viejo tachado + flecha.
   Canónico — convergencia planes/facturación. */
.diff-tag { display: inline-flex; align-items: center; gap: 5px; min-width: 64px; justify-content: center; padding: 2px 8px; border-radius: var(--radius-sm); font-size: 10px; font-weight: var(--font-bold); text-transform: uppercase; letter-spacing: .04em; flex: 0 0 auto; }
.diff-tag.is-create { background: var(--color-success-light); color: var(--color-success-text); }
.diff-tag.is-edit, .diff-tag.is-credit { background: var(--color-warning-light); color: var(--color-warning-text); }
.diff-tag.is-archive, .diff-tag.is-refund { background: var(--color-danger-light); color: var(--color-danger-text); }
.diff-old { color: var(--color-text-tertiary); text-decoration: line-through; }
.diff-arrow { color: var(--color-text-tertiary); margin: 0 4px; }

/* Mini-barra de progreso (track + relleno con tono). Canónico — convergencia
   roles/notificaciones/seguridad/servicios/validaciones-detalle. (.meter = medidor
   SEGMENTADO de fuerza; .usage-bar = cuota de app — son distintos.) */
.minibar { height: 6px; border-radius: var(--badge-radius); background: var(--color-surface-sunken); overflow: hidden; }
.minibar-fill { height: 100%; border-radius: var(--badge-radius); background: var(--color-accent); transition: width var(--transition-normal); }
.minibar-fill.is-ok { background: var(--color-success); }
.minibar-fill.is-warn { background: var(--color-warning); }
.minibar-fill.is-bad { background: var(--color-danger); }
.minibar-fill.is-muted { background: var(--color-border-strong); }
/* Separador · icono guía · ítem destructivo dentro del menú (⋯). De admin/usuarios/detalle. */
.dropdown-sep { height: 1px; background: var(--color-border); margin: var(--space-1) var(--space-2); }
.dropdown-item .icon { width: 1rem; height: 1rem; color: var(--color-text-tertiary); }
.dropdown-item.is-danger { color: var(--color-danger-text); }
.dropdown-item.is-danger:hover { background: var(--color-danger-light); }
.dropdown-item.is-danger .icon { color: var(--color-danger-text); }

/* Sheet/Drawer — ESTILO; en prod el comportamiento = APP.drawer.
   Bottom sheet en móvil; drawer lateral derecho en ≥768. */
.sheet-overlay { position: fixed; inset: 0; background: var(--color-surface-overlay); z-index: var(--z-modal); opacity: 0; visibility: hidden; transition: opacity var(--transition-fast); }
.sheet-overlay.open { opacity: 1; visibility: visible; }
.sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-modal); background: var(--color-surface); border-radius: var(--radius-xl) var(--radius-xl) 0 0; max-height: 85vh; display: flex; flex-direction: column; transform: translateY(100%); transition: transform var(--transition-normal); box-shadow: 0 -8px 30px rgb(0 0 0 / .18); }
.sheet.open { transform: translateY(0); }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-border); }
.sheet-head h3 { margin: 0; font-size: var(--text-base); font-weight: var(--font-semibold); }
.sheet-body { padding: var(--space-5); overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-5); min-height: 0; }
/* min-height:0 + hijos sin encoger: contenido largo (p.ej. diff de auditoría) hace scroll en vez de comprimirse. De admin/seguridad. */
.sheet-body > * { flex-shrink: 0; }
.sheet-foot { display: flex; gap: var(--space-3); padding: var(--space-4) var(--space-5); padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0)); border-top: 1px solid var(--color-border); }
.sheet-foot .btn { flex: 1; }

/* Encabezado de confirmación destructiva (icono tintado + título + descripción) para
   sheets/modales de acción peligrosa. De admin/usuarios/detalle. En prod el comportamiento
   lo da APP.confirm/APP.modal; esto es la composición visual del cuerpo. */
.confirm-lead { display: flex; gap: var(--space-3); align-items: flex-start; }
.confirm-ico { width: 40px; height: 40px; border-radius: var(--radius-md); display: grid; place-items: center; flex: 0 0 auto; }
.confirm-ico .icon { width: 20px; height: 20px; }
.confirm-ico.is-warn { background: var(--color-warning-light); color: var(--color-warning-text); }
.confirm-ico.is-danger { background: var(--color-danger-light); color: var(--color-danger-text); }
.confirm-body { min-width: 0; }
.confirm-title { font-weight: var(--font-semibold); font-size: var(--text-base); }
.confirm-desc { font-size: var(--text-sm); color: var(--color-text-secondary); margin-top: 2px; }

/* Caja mono read-only para claves/identificadores (api key regenerada, ids…). Canónico tras
   3er consumidor; api-docs .api-keybox + usuarios/lista .usr-keybox convergen aquí (ver porting-notes). */
.keybox { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-sunken); font-family: var(--font-family-mono); font-size: var(--text-xs); overflow-wrap: anywhere; }
.keybox code { flex: 1; min-width: 0; color: var(--color-text-primary); overflow-wrap: anywhere; }
.keybox.is-masked { letter-spacing: .12em; color: var(--color-text-secondary); user-select: none; }
.filter-group-label { font-size: var(--text-sm); font-weight: var(--font-semibold); margin-bottom: var(--space-2); }
.chip-set { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.chip-opt { height: 36px; padding: 0 var(--space-3); border: 1px solid var(--color-border); border-radius: var(--badge-radius); background: var(--color-surface); color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: var(--font-medium); font-family: inherit; cursor: pointer; }
.chip-opt:hover { background: var(--color-surface-sunken); }
.chip-opt.selected { background: var(--color-accent-light); border-color: var(--color-accent); color: var(--color-text-link); }
.amount-row { display: flex; align-items: center; gap: var(--space-2); }
.amount-row input { flex: 1; min-width: 0; height: var(--input-height); padding: 0 var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--text-sm); font-family: inherit; color: var(--color-text-primary); }
.amount-row input:focus { outline: none; border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }
.amount-row span { color: var(--color-text-tertiary); }

@media (min-width: 768px) {
    .page-title { font-size: var(--text-2xl); }
    .toolbar-row { display: flex; align-items: center; gap: var(--space-3); }
    .toolbar-row .segs { flex: 1; }
    /* drawer lateral derecho */
    .sheet { top: 0; left: auto; right: 0; bottom: 0; width: min(420px, 92vw); max-height: none; height: 100vh; border-radius: 0; transform: translateX(100%); box-shadow: -8px 0 30px rgb(0 0 0 / .18); }
    .sheet.open { transform: translateX(0); }
    .sheet-body { flex: 1; }
}
@media (min-width: 1100px) {
    .page-head { margin-bottom: var(--space-5); }
}

/* ============================================================
   WIZARD / FORMULARIO (extraído del hero #3)
   ------------------------------------------------------------
   Captura y multipaso reutilizables por cualquier wizard/formulario
   (validaciones/importar, beneficiarios/importar, etc.). El FRAME del modal
   (.wz*) y el layout de página viven en su pantalla; esto es el contenido.
   Comportamiento interactivo en prod = primitivas APP.* / hooks reales.
   ============================================================ */

/* Step-bar (indicador de pasos) — etiquetas solo ≥768 (abajo) */
.step-bar { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-5) 0 var(--space-4); }
.step { display: flex; align-items: center; gap: var(--space-2); color: var(--color-text-tertiary); font-size: var(--text-sm); font-weight: var(--font-medium); white-space: nowrap; }
.step-dot { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--color-surface-sunken); color: var(--color-text-tertiary); font-size: var(--text-xs); font-weight: var(--font-semibold); border: 1px solid var(--color-border); flex: 0 0 auto; }
.step-dot .icon { width: 14px; height: 14px; }
.step.active { color: var(--color-text-primary); }
.step.active .step-dot { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-text-inverse); }
.step.done .step-dot { background: var(--color-success); border-color: var(--color-success); color: var(--color-text-inverse); }
.step-line { flex: 1; height: 1px; background: var(--color-border); min-width: 12px; }
.step-label { display: none; }

/* Selection-card (elegir método/opción) */
.sel-grid { display: flex; flex-direction: column; gap: var(--space-3); }
.sel-card { display: flex; align-items: center; gap: var(--space-3); text-align: left; padding: var(--space-4); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--card-radius); cursor: pointer; }
.sel-card:hover { border-color: var(--color-border-strong); background: var(--color-surface-sunken); }
.sel-card.selected { border-color: var(--color-accent); box-shadow: inset 0 0 0 1px var(--color-accent); background: var(--color-accent-light); }
.sel-ico { width: 44px; height: 44px; border-radius: var(--radius-md); background: var(--color-accent-light); color: var(--color-accent); display: grid; place-items: center; flex: 0 0 auto; }
.sel-card.selected .sel-ico { background: var(--color-accent); color: var(--color-text-inverse); }
.sel-ico .icon { width: 22px; height: 22px; }
.sel-text { display: flex; flex-direction: column; min-width: 0; }
.sel-title { font-weight: var(--font-semibold); }
.sel-desc { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: 2px; }
.sel-check { margin-left: auto; color: var(--color-accent); flex: 0 0 auto; visibility: hidden; }
.sel-card.selected .sel-check { visibility: visible; }

/* Dropzone (subir archivo) + preview + nota */
.dropzone { border: 1.5px dashed var(--color-border-strong); border-radius: var(--card-radius); background: var(--color-surface-sunken); padding: var(--space-8) var(--space-5); text-align: center; cursor: pointer; }
.dropzone:hover { border-color: var(--color-accent); background: var(--color-accent-light); }
.dropzone-ico { width: 48px; height: 48px; border-radius: 50%; background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-accent); display: grid; place-items: center; margin: 0 auto var(--space-3); }
.dropzone-ico .icon { width: 24px; height: 24px; }
.dropzone-title { font-weight: var(--font-semibold); }
.dropzone-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: 2px; }
.upload-preview { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--card-radius); }
.upload-thumb { width: 56px; height: 56px; border-radius: var(--radius-md); background: var(--color-surface-sunken); object-fit: cover; flex: 0 0 auto; }
.upload-name { font-weight: var(--font-medium); font-size: var(--text-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.upload-meta { font-size: var(--text-xs); color: var(--color-text-tertiary); white-space: nowrap; }
.upload-preview > button { flex: 0 0 auto; white-space: nowrap; margin-left: auto; align-self: center; }
@media (max-width: 480px) { .upload-preview > button { flex: 0 0 100%; margin-left: 0; } }
.ocr-hint { display: flex; gap: var(--space-2); align-items: flex-start; margin: 0 0 var(--space-3); padding: var(--space-3); background: var(--color-accent-light); border-radius: var(--radius-md); font-size: var(--text-xs); color: var(--color-text-link); }
.ocr-hint .icon { width: 1rem; height: 1rem; flex: 0 0 auto; }

/* Campos de formulario */
.field { margin-bottom: var(--space-4); }
.field-label { display: block; font-size: var(--text-sm); font-weight: var(--font-medium); margin-bottom: var(--space-1-5); }
.field-input { width: 100%; height: var(--input-height); padding: 0 var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--text-sm); font-family: inherit; color: var(--color-text-primary); }
.field-input--mono { font-family: var(--font-family-mono); letter-spacing: .02em; }
.field-input:focus { outline: none; border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }
.field-row { display: flex; gap: var(--space-3); }
.field-row > .field { flex: 1; min-width: 0; }   /* min-width:0 = los items pueden encoger (combobox/date no desbordan) */
/* xs: solo las filas con combobox apilan dentro de modales (dos comboboxes —
   Banco emisor/receptor — no caben en ~286px y se desbordaban). Los pares de
   inputs cortos (Fecha/Monto) siguen lado a lado. Gap vertical = margin-bottom de .field. */
@media (max-width: 480px) {
    .mx-modal .field-row:has(.combobox) { flex-direction: column; gap: 0; }
}
.field-hint { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: var(--space-1); }
.field-opt { color: var(--color-text-tertiary); font-weight: var(--font-normal); }   /* "· opcional" en el label */

/* Opciones en tarjeta (toggles como filas con divisor) + switch */
.options { margin-top: var(--space-7); border: 1px solid var(--color-border); border-radius: var(--card-radius); }
.option-row { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-4); cursor: pointer; }
.option-row + .option-row { border-top: 1px solid var(--color-border); }
.switch { position: relative; width: 40px; height: 24px; flex: 0 0 auto; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch-track { position: absolute; inset: 0; background: var(--color-border-strong); border-radius: var(--badge-radius); transition: background var(--transition-fast); }
.switch-thumb { position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; background: var(--color-surface); border-radius: 50%; box-shadow: var(--shadow-sm); transition: transform var(--transition-fast); }
.switch input:checked + .switch-track { background: var(--color-accent); }
.switch input:checked + .switch-track + .switch-thumb { transform: translateX(16px); }
.switch input:focus-visible + .switch-track { outline: var(--ring-width) solid var(--ring-color); outline-offset: 2px; }
/* Switch bloqueado (toggle inmutable: candado + siempre-on). De admin/acceso/roles (columna owner). */
.switch.is-locked { cursor: not-allowed; }
.switch.is-locked input { cursor: not-allowed; }
.switch.is-locked .switch-track { background: var(--color-accent); opacity: .5; }
.switch.is-locked .switch-thumb { background: var(--color-surface); }
.switch.is-locked .switch-lock { position: absolute; inset: 0; display: grid; place-items: center; color: var(--color-text-link); pointer-events: none; }
.switch.is-locked .switch-lock .icon { width: 11px; height: 11px; }
.switch-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.switch-text .switch-title { font-weight: var(--font-medium); font-size: var(--text-sm); }
.switch-text .switch-desc { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: 2px; }

/* Config inline (sección dentro de .options): slider + select + chips + preview */
.retry-config { border-top: 1px solid var(--color-border); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); }
.cfg-label { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); font-size: var(--text-sm); font-weight: var(--font-medium); margin-bottom: var(--space-2); }
.cfg-val { color: var(--color-text-link); font-variant-numeric: tabular-nums; font-weight: var(--font-semibold); }
.range { width: 100%; accent-color: var(--color-accent); cursor: pointer; }
.select { width: 100%; height: var(--input-height); padding: 0 var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--text-sm); font-family: inherit; color: var(--color-text-primary); cursor: pointer; }
.select:focus { outline: none; border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }
.cfg-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.retry-preview { display: flex; gap: 6px; align-items: flex-start; font-size: var(--text-xs); color: var(--color-text-secondary); }
.retry-preview .icon { width: 14px; height: 14px; color: var(--color-text-tertiary); flex: 0 0 auto; margin-top: 1px; }

/* Estado "procesando" (spinner centrado). NO usar `.processing` solo: choca con el
   modificador de badge `.verdict.processing` y con `.sdot.proc`. */
.proc-state { text-align: center; padding: var(--space-10) var(--space-5); }
.proc-spinner { width: 48px; height: 48px; margin: 0 auto var(--space-4); color: var(--color-accent); animation: wz-spin 1s linear infinite; }
.proc-spinner .icon { width: 48px; height: 48px; }
@keyframes wz-spin { to { transform: rotate(360deg); } }
.proc-title { font-size: var(--text-lg); font-weight: var(--font-bold); margin: 0 0 var(--space-1); }
.proc-desc { color: var(--color-text-secondary); font-size: var(--text-sm); margin: 0; }
@media (prefers-reduced-motion: reduce) { .proc-spinner { animation: none; } }
/* Estado de error de lectura OCR (faro #5): "no se leyó bien → sube otra" */
.proc-error-ico { width: 56px; height: 56px; margin: 0 auto var(--space-4); border-radius: 50%; background: var(--color-warning-light); color: var(--color-warning-text); display: grid; place-items: center; }
.proc-error-ico .icon { width: 28px; height: 28px; }
.proc-state .btn { margin-top: var(--space-4); }

@media (min-width: 768px) {
    .step-label { display: inline; }   /* etiquetas de paso en pantallas grandes */
}

/* ============================================================
   DETALLE / VEREDICTO (extraído del hero #3)
   ------------------------------------------------------------
   Pantalla de detalle de una entidad con veredicto: back · verdict-hero ·
   data-rows (clave/valor) · timeline (máquina de estado). El layout 2-col y lo
   específico de cada pantalla (p.ej. CEP) viven en la pantalla. La base
   .verdict (color+icono+texto) está más arriba.
   ============================================================ */

/* Volver a la lista (flecha = arrow-right rotada) */
.detail-back { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: var(--font-medium); margin-bottom: var(--space-4); }
.detail-back:hover { color: var(--color-text-primary); }
.detail-back .icon { width: 1rem; height: 1rem; transform: rotate(180deg); }

/* Veredicto hero (entidad + monto grande + badge + prueba) */
.verdict-hero { padding: var(--space-5); }
.vh-top { display: flex; align-items: center; gap: var(--space-3); }
.vh-bank { width: 44px; height: 44px; font-size: 11px; }
.vh-bene { font-weight: var(--font-semibold); }
.vh-bene-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); font-family: var(--font-family-mono); }
.vh-amount { font-size: var(--text-4xl); font-weight: var(--font-bold); letter-spacing: -.03em; line-height: 1.05; font-variant-numeric: tabular-nums; margin: var(--space-4) 0 var(--space-3); }
.verdict-hero .verdict { font-size: var(--text-sm); padding: 5px 12px; }
.verdict-hero .verdict .icon { width: 16px; height: 16px; }
.vh-proof { display: inline-flex; align-items: center; gap: 6px; margin-top: var(--space-3); font-size: var(--text-xs); color: var(--color-success-text); }
.vh-proof .icon { width: 14px; height: 14px; }

/* Título de sección dentro de una card */
.detail-card-title { font-size: var(--text-sm); font-weight: var(--font-semibold); margin: 0; padding: var(--space-4) var(--space-5) 0; }

/* Data rows (clave/valor) + separador de grupo (.dl-group = hairline + etiqueta) */
.dl { display: flex; flex-direction: column; padding: var(--space-2) 0; }
/* mobile-first: clave ARRIBA, valor ABAJO (alineado a la izq) — evita que los valores
   largos (clave de rastreo de 20 chars, fecha+hora, CLABE de 18) se encavalguen con la
   etiqueta en pantallas chicas. En >=768px vuelve a fila «clave … valor» (media abajo). */
.dl-row { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); padding: var(--space-2-5) var(--space-5); font-size: var(--text-sm); }
.dl-k { color: var(--color-text-tertiary); flex: 0 0 auto; }
.dl-v { font-weight: var(--font-medium); text-align: left; min-width: 0; overflow-wrap: anywhere; }
.dl-v.mono { font-family: var(--font-family-mono); font-size: var(--text-xs); }
.dl-group { margin-top: var(--space-2); padding: var(--space-3) var(--space-5) var(--space-1); border-top: 1px solid var(--color-border); font-size: var(--text-xs); font-weight: var(--font-bold); letter-spacing: .04em; text-transform: uppercase; color: var(--color-text-primary); }
@media (min-width: 768px) {
  .dl-row { flex-direction: row; align-items: center; justify-content: space-between; gap: var(--space-3); }
  .dl-v { text-align: right; }
}

/* Timeline (máquina de estado del proceso) */
.timeline { list-style: none; margin: 0; padding: var(--space-4) var(--space-5) var(--space-5); }
.tl-item { display: flex; gap: var(--space-3); }
.tl-marker { display: flex; flex-direction: column; align-items: center; flex: 0 0 auto; }
.tl-dot { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--color-success); color: var(--color-text-inverse); flex: 0 0 auto; }
.tl-dot .icon { width: 14px; height: 14px; }
.tl-dot.is-pending { background: var(--color-surface-sunken); color: var(--color-text-tertiary); border: 1px solid var(--color-border); }
.tl-dot.is-warn { background: var(--color-warning); color: var(--color-text-inverse); }
.tl-dot.is-error { background: var(--color-danger); color: var(--color-text-inverse); }
.tl-line { flex: 1; width: 2px; min-height: 14px; background: var(--color-border); margin: 2px 0; }
.tl-item:last-child .tl-line { display: none; }
.tl-body { padding-bottom: var(--space-4); }
.tl-item:last-child .tl-body { padding-bottom: 0; }
.tl-title { font-weight: var(--font-medium); font-size: var(--text-sm); }
.tl-title.is-pending { color: var(--color-text-tertiary); font-weight: var(--font-normal); }
.tl-time { font-size: var(--text-xs); color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; margin-top: 1px; }

/* Bloque de código/marcado CRUDO (JSON·XML·HTML): cabecera (label/meta/copiar/colapsar) +
   cuerpo scrollable. De admin/validaciones/detalle; reusable por playground/i18n/operación.
   JS: [data-code]/[data-toggle]/[data-copy] + .is-collapsed/.is-copied (sin clases nuevas). */
.codeblock { border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-sunken); overflow: hidden; min-width: 0; max-width: 100%; }
.codeblock-head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--color-border); background: var(--color-surface); flex-wrap: wrap; }
.codeblock.is-collapsed .codeblock-head { border-bottom-color: transparent; }
.codeblock-label { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-family-mono); font-size: var(--text-xs); font-weight: var(--font-semibold); color: var(--color-text-secondary); min-width: 0; }
.codeblock-label .icon { width: 14px; height: 14px; color: var(--color-text-tertiary); flex: 0 0 auto; }
.codeblock-meta { font-size: 11px; color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.codeblock-actions { margin-left: auto; display: flex; align-items: center; gap: 4px; }
.codeblock-btn { display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 var(--space-2); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text-secondary); font-size: 11px; font-weight: var(--font-medium); font-family: inherit; cursor: pointer; }
.codeblock-btn:hover { background: var(--color-surface-sunken); color: var(--color-text-primary); }
.codeblock-btn .icon { width: 13px; height: 13px; }
.codeblock-btn .codeblock-copied { display: none; color: var(--color-success-text); }
.codeblock-btn.is-copied .codeblock-copylabel { display: none; }
.codeblock-btn.is-copied .codeblock-copied { display: inline; }
.codeblock-toggle .icon { transition: transform var(--transition-fast); }
.codeblock:not(.is-collapsed) .codeblock-toggle .icon { transform: rotate(180deg); }
.codeblock.is-collapsed .codeblock-toggle .icon { transform: rotate(0deg); }
.codeblock-body { overflow: auto; max-height: 420px; -webkit-overflow-scrolling: touch; }
.codeblock.is-collapsed .codeblock-body { display: none; }
.codeblock pre { margin: 0; padding: var(--space-3) var(--space-4); font-family: var(--font-family-mono); font-size: var(--text-xs); line-height: 1.65; color: var(--color-text-primary); tab-size: 2; }
.codeblock pre code { white-space: pre; }
.codeblock-truncate { display: block; margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px dashed var(--color-border-strong); color: var(--color-text-tertiary); font-style: italic; }

/* Fila de acciones del detalle */
.detail-actions { display: flex; gap: var(--space-2); }

/* ============================================================
   CHARTS / KPI atoms (extraído del hero #2)
   ------------------------------------------------------------
   Primitivas de visualización reutilizables por dashboard · finanzas · métricas ·
   uso: anillo de progreso (donut) + sparkline. Genéricas — el consumidor pasa el
   % (stroke-dasharray) y los puntos (polyline). Debajo, la COMPOSICIÓN "KPI hero"
   (monto + delta + anillo + sparkline) ya COMPARTIDA por dashboard #2 y finanzas #4.
   ============================================================ */
.ring { position: relative; width: 84px; height: 84px; flex: 0 0 auto; }
.ring svg { transform: rotate(-90deg); }
.ring-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.ring-pct { font-size: var(--text-base); font-weight: var(--font-bold); font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: -.02em; }
.ring-cap { font-size: 9px; color: var(--color-text-tertiary); text-transform: uppercase; letter-spacing: .04em; }
/* Trazo de relleno del aro (stroke-dasharray lo anima el consumidor); acento → verde al completar */
.ring-fg { stroke: var(--color-accent); transition: stroke-dasharray var(--transition-normal), stroke var(--transition-fast); }
.ring-fg.is-complete { stroke: var(--color-success); }
.spark { width: 100%; height: 40px; display: block; }

/* Leyenda de gráfica (COMPARTIDA: finanzas #4 + banxico). Punto + etiqueta; el
   consumidor colorea el .legend-dot por estado/serie (modificadores .is-* abajo). */
.chart-legend { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--color-text-secondary); }
.legend-dot { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }
.legend-dot.is-ok { background: var(--color-success); }
.legend-dot.is-degraded { background: var(--color-warning); }
.legend-dot.is-down { background: var(--color-danger); }
/* Modifiers por veredicto Banxico / serie de percentiles (de insights/métricas) */
.legend-dot.is-valid { background: var(--color-success); }
.legend-dot.is-notfound { background: var(--color-warning); }
.legend-dot.is-cep { background: var(--color-info); }
.legend-dot.is-error { background: var(--color-danger); }
.legend-dot.is-proc { background: var(--color-accent); }
.legend-dot.is-pend { background: var(--color-border-strong); }
.legend-dot.is-s1 { background: var(--color-accent); }
.legend-dot.is-s2 { background: var(--color-success); }
.legend-dot.is-s3 { background: var(--color-warning); }
.legend-dot.is-s4 { background: var(--color-border-strong); }
.legend-dot.is-p50 { background: var(--color-success); }
.legend-dot.is-p95 { background: var(--color-warning); }
.legend-dot.is-p99 { background: var(--color-danger); }
.legend-dot.is-avg { background: var(--color-accent); }
.legend-dot.is-soft { opacity: .5; }

/* Tira de uptime / salud en el tiempo (status page densa). Una barra por
   intervalo, coloreada por estado (ok/degraded/down); pie con extremos y dato
   central opcional. COMPARTIDA: banxico (estado del servicio) + futuras vistas
   de salud. El consumidor genera las barras y el % a partir de su serie. */
.uptime { display: flex; flex-direction: column; gap: var(--space-3); }
.uptime-track { display: flex; gap: 3px; height: 38px; align-items: stretch; }
.uptime-bar { flex: 1 1 0; min-width: 0; border-radius: 2px; background: var(--color-success); }
.uptime-bar.is-ok { background: var(--color-success); }
.uptime-bar.is-degraded { background: var(--color-warning); }
.uptime-bar.is-down { background: var(--color-danger); }
/* Bucket sin lectura (pocas probes): gris neutro para que la tira muestre el
   periodo completo de forma coherente sin pintar "caída" donde no hubo dato. */
.uptime-bar.is-empty { background: var(--color-border); }
.uptime-foot { display: flex; align-items: center; gap: var(--space-3); }
.uptime-rule { flex: 1; height: 1px; background: var(--color-border); }
.uptime-end { font-size: var(--text-xs); color: var(--color-text-tertiary); white-space: nowrap; }
.uptime-mid { font-size: var(--text-xs); color: var(--color-text-secondary); font-weight: var(--font-medium); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* KPI hero (COMPARTIDO: dashboard #2 + finanzas #4) — monto grande + delta + anillo +
   sparkline. Generaliza las antiguas .flujo (dashboard) y .fin-hero (finanzas). El
   consumidor mete .ring (con su %) y .spark dentro; el footer es opcional. */
.kpi-hero { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); }
.kpi-hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); }
.kpi-hero .label { color: var(--color-text-secondary); font-size: var(--text-sm); }
.kpi-hero .val { font-size: var(--text-4xl); font-weight: var(--font-bold); letter-spacing: -.03em; line-height: 1.05; font-variant-numeric: tabular-nums; }
.kpi-hero .delta { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-xs); color: var(--color-success-text); font-variant-numeric: tabular-nums; margin-top: var(--space-1); }
/* Negativos SIN color (format-spec): la bajada va neutra; el ícono ↓ da la dirección. */
.kpi-hero .delta.delta-down { color: var(--color-text-secondary); }
.kpi-hero .delta .icon { width: 14px; height: 14px; }
.kpi-hero-foot { display: flex; justify-content: space-between; font-size: var(--text-xs); color: var(--color-text-tertiary); }
.kpi-hero-foot b { color: var(--color-text-secondary); font-variant-numeric: tabular-nums; }
@media (min-width: 768px) { .kpi-hero-top { align-items: center; } }

/* ============================================================
   TABS (extraído del hero #4) — tabs de contenido (Resumen/SAT/Facturas…). El
   comportamiento en prod usa los hooks reales; aquí el estilo. El gap del
   .tab-panel da aire entre secciones del panel activo.
   ============================================================ */
.tabs { display: flex; gap: var(--space-5); border-bottom: 1px solid var(--color-border); overflow-x: auto; scrollbar-width: none; margin-bottom: var(--space-5); }
.tabs::-webkit-scrollbar { display: none; }
.tab-btn { flex: 0 0 auto; position: relative; display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-3) 0; border: 0; background: transparent; color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: var(--font-medium); font-family: inherit; cursor: pointer; white-space: nowrap; }
.tab-btn:hover { color: var(--color-text-primary); }
.tab-btn.active { color: var(--color-text-primary); }
.tab-btn.active::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--color-accent); border-radius: 2px 2px 0 0; }
.tab-soon { font-size: 9px; font-weight: var(--font-semibold); text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-tertiary); background: var(--color-surface-sunken); border: 1px solid var(--color-border); padding: 1px 6px; border-radius: var(--badge-radius); }
.tab-panel { display: flex; flex-direction: column; gap: var(--space-7); }
.tab-panel[hidden] { display: none; }
.tab-empty { text-align: center; padding: var(--space-10) var(--space-5); color: var(--color-text-tertiary); }
.tab-empty .icon { width: 40px; height: 40px; margin: 0 auto var(--space-3); color: var(--color-text-tertiary); }
.tab-empty-title { font-weight: var(--font-semibold); color: var(--color-text-secondary); }

/* ============================================================
   PLAN CARD (extraído del hero #6) — tarjeta de plan + grid (faro de pricing; la
   landing /precios hereda este patrón). La tabla comparativa (.compare*), los
   toggles (.seg-toggle) y el resultado (.result) siguen en checkout.css.
   ============================================================ */
.plan-grid { display: grid; grid-template-columns: 1fr; row-gap: var(--space-6); column-gap: var(--space-4); }
.plan-card { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); position: relative; }
.plan-card--featured { border-color: var(--color-accent); box-shadow: inset 0 0 0 1px var(--color-accent); }
.plan-badge { position: absolute; top: -11px; left: var(--space-5); background: var(--color-accent); color: var(--color-text-inverse); font-size: 11px; font-weight: var(--font-semibold); letter-spacing: .02em; padding: 3px 10px; border-radius: var(--badge-radius); }
.plan-head { display: flex; flex-direction: column; gap: 2px; }
.plan-name { font-size: var(--text-lg); font-weight: var(--font-bold); }
.plan-desc { font-size: var(--text-sm); color: var(--color-text-secondary); }
.plan-price { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.plan-amount { font-size: var(--text-4xl); font-weight: var(--font-bold); letter-spacing: -.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.plan-unit { color: var(--color-text-tertiary); font-size: var(--text-sm); }
.plan-iva { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: var(--space-1); }
.plan-features { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.plan-features li { display: flex; gap: var(--space-2); align-items: flex-start; font-size: var(--text-sm); }
.plan-features li .icon { width: 1rem; height: 1rem; flex: 0 0 auto; margin-top: 2px; }
.plan-features li.yes .icon { color: var(--color-success); }
.plan-features li.no { color: var(--color-text-tertiary); }
.plan-features li.no .icon { color: var(--color-text-tertiary); }
.plan-card .plan-cta { margin-top: auto; }
@media (min-width: 768px) { .plan-grid { grid-template-columns: repeat(3, 1fr); align-items: stretch; } }

/* Nota de mockup (SOLO en los candidatos de diseño; no es componente de producción) */
.note { font-size: 11px; color: var(--color-text-tertiary); text-align: center; padding-top: var(--space-2); }

/* ============================================================
   EXTRAÍDO de validaciones/importar (2026-06-03) — primitivos reutilizables que
   esa pantalla aportó. Genéricos, solo tokens, SIN márgenes de página (la página
   coloca). Las pantallas dejan de redefinir estos bloques.
   ============================================================ */

/* Verdict: variantes extra (completa ok/no/pending/processing de arriba) */
.verdict.warn { background: var(--color-warning-light); color: var(--color-warning-text); }
.verdict.info { background: var(--color-info-light); color: var(--color-info-text); }
.verdict.muted { background: var(--color-surface-sunken); color: var(--color-text-secondary); }
.verdict.queued { background: var(--color-surface-sunken); color: var(--color-text-tertiary); }
.verdict.running { background: var(--color-info-light); color: var(--color-info-text); }
.verdict.running .icon { animation: verdict-spin 1s linear infinite; }
@media (prefers-reduced-motion: reduce) { .verdict.running .icon { animation: none; } }

/* Botón peligro + estado disabled */
.btn-danger { background: var(--color-danger); color: var(--color-text-inverse); }
.btn-danger:hover { background: var(--color-danger-hover); }
.btn:disabled { opacity: var(--opacity-disabled, .5); cursor: not-allowed; }

/* KPI strip compacto (conteos derivados) — complementa .kpi-hero */
.kpi-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(108px, 1fr)); gap: var(--space-2); }
.kpi-tile { padding: var(--space-3) var(--space-3-5); display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.kpi-tile-val { font-size: var(--text-2xl); font-weight: var(--font-bold); font-variant-numeric: tabular-nums; letter-spacing: -.02em; line-height: 1; }
.kpi-tile-label { display: inline-flex; align-items: center; gap: 6px; color: var(--color-text-secondary); font-size: var(--text-xs); line-height: 1.2; }
.kpi-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--color-border-strong); }
.kpi-dot.ok { background: var(--color-success); }
.kpi-dot.warn { background: var(--color-warning); }
.kpi-dot.bad { background: var(--color-danger); }
.kpi-dot.info { background: var(--color-info); }
.kpi-dot.muted { background: var(--color-text-tertiary); }
.kpi-tile.is-total { background: var(--color-surface-sunken); }
.kpi-tile.is-total .kpi-tile-val { color: var(--color-text-primary); }
@media (min-width: 1100px) { .kpi-strip { gap: var(--space-3); } }

/* Checkbox inline (primitivo de formulario) */
.check-inline { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--color-text-secondary); cursor: pointer; min-height: 32px; user-select: none; }
.check-inline input { position: absolute; opacity: 0; width: 0; height: 0; }
.check-box { width: 18px; height: 18px; border: 1.5px solid var(--color-border-strong); border-radius: var(--radius-sm); display: grid; place-items: center; flex: 0 0 auto; background: var(--color-surface); transition: background var(--transition-fast), border-color var(--transition-fast); }
.check-box .icon { width: 13px; height: 13px; color: var(--color-text-inverse); opacity: 0; }
.check-inline input:checked + .check-box { background: var(--color-accent); border-color: var(--color-accent); }
.check-inline input:checked + .check-box .icon { opacity: 1; }
.check-inline input:focus-visible + .check-box { outline: var(--ring-width) solid var(--ring-color); outline-offset: 2px; }

/* Tira "avísame cuando termine" (flujos async) */
.notify-strip { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-4); padding: var(--space-3) var(--space-4); }
.notify-lead { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); font-weight: var(--font-medium); color: var(--color-text-primary); }
.notify-lead .icon { width: 1.125rem; height: 1.125rem; color: var(--color-accent); }
.notify-channels { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin-left: auto; }

/* Indicador de progreso async (committing) */
.progress-card { padding: var(--space-4) var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); }
.progress-top { display: flex; align-items: center; gap: var(--space-3); }
.progress-spin { width: 22px; height: 22px; color: var(--color-accent); flex: 0 0 auto; animation: verdict-spin 1s linear infinite; }
.progress-spin .icon { width: 22px; height: 22px; }
@media (prefers-reduced-motion: reduce) { .progress-spin { animation: none; } }
.progress-label { font-weight: var(--font-semibold); font-size: var(--text-sm); }
.progress-count { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: var(--font-semibold); color: var(--color-text-link); font-family: var(--font-family-mono); font-size: var(--text-sm); }
.progress-bar { height: 8px; border-radius: var(--badge-radius); background: var(--color-surface-sunken); overflow: hidden; }
.progress-fill { height: 100%; background: var(--color-accent); border-radius: var(--badge-radius); transition: width var(--transition-normal); }
.progress-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); }

/* Panel de estado (vacío / terminal / error / éxito) + result banner */
.state-panel { display: flex; flex-direction: column; align-items: center; text-align: center; padding: var(--space-12) var(--space-5); gap: var(--space-2); }
.state-ico { width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center; margin-bottom: var(--space-2); }
.state-ico .icon { width: 28px; height: 28px; }
.state-ico.bad { background: var(--color-danger-light); color: var(--color-danger-text); }
.state-ico.muted { background: var(--color-surface-sunken); color: var(--color-text-tertiary); }
.state-ico.ok { background: var(--color-success-light); color: var(--color-success-text); }
.state-title { font-size: var(--text-lg); font-weight: var(--font-bold); margin: 0; }
.state-desc { color: var(--color-text-secondary); font-size: var(--text-sm); margin: 0; max-width: 44ch; }
.state-actions { display: flex; gap: var(--space-2); margin-top: var(--space-4); flex-wrap: wrap; justify-content: center; }
.result-banner { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4); }
.result-banner .state-ico { margin: 0; width: 40px; height: 40px; }
.result-banner .state-ico .icon { width: 20px; height: 20px; }
.result-banner-body { min-width: 0; }
.result-banner-title { font-weight: var(--font-semibold); font-size: var(--text-base); }
.result-banner-sub { color: var(--color-text-secondary); font-size: var(--text-sm); margin-top: 2px; }

/* Skeleton de filas (loader) */
.skeleton-rows { display: flex; flex-direction: column; gap: 1px; width: 100%; }
.sk-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-border); }
.sk-bar { height: 12px; border-radius: var(--radius-sm); background: linear-gradient(90deg, var(--color-surface-sunken) 0%, var(--color-surface-muted) 50%, var(--color-surface-sunken) 100%); background-size: 200% 100%; animation: sk-shimmer 1.3s ease-in-out infinite; }
@keyframes sk-shimmer { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .sk-bar { animation: none; } }
.sk-1 { width: 18px; flex: 0 0 auto; } .sk-2 { width: 84px; flex: 0 0 auto; } .sk-3 { flex: 1; } .sk-4 { width: 72px; flex: 0 0 auto; }
/* Líneas de texto apiladas (detalle/prosa) — APP.skeleton.lines() */
.sk-lines { display: flex; flex-direction: column; gap: var(--space-2); width: 100%; }
.sk-lines .sk-bar { flex: 0 0 auto; }

/* Alerta inline (preflight / cuota 422 / error de banda) */
.preflight { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-4); border: 1px solid var(--color-danger); border-radius: var(--card-radius); background: var(--color-danger-light); }
.preflight .icon { width: 1.25rem; height: 1.25rem; color: var(--color-danger-text); flex: 0 0 auto; margin-top: 1px; }
.preflight-body { min-width: 0; }
.preflight-title { font-weight: var(--font-semibold); font-size: var(--text-sm); color: var(--color-danger-text); }
.preflight-desc { font-size: var(--text-sm); color: var(--color-text-secondary); margin-top: 2px; }
.preflight-actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); flex-wrap: wrap; }

/* Celdas editables inline (tablas/cards con edición) */
.cell-input { width: 100%; min-width: 0; height: 36px; padding: 0 var(--space-2-5); border: 1px solid transparent; border-radius: var(--radius-md); background: var(--color-surface-sunken); color: var(--color-text-primary); font-size: var(--text-sm); font-family: inherit; }
.cell-input:hover { border-color: var(--color-border-strong); }
.cell-input:focus { outline: none; background: var(--color-surface); border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }
.cell-input.mono { font-family: var(--font-family-mono); font-size: var(--text-xs); letter-spacing: -.01em; }
.cell-input.amount { font-family: var(--font-family-mono); font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; }
.cell-input[readonly] { background: transparent; border-color: transparent; padding-left: 0; cursor: default; }
.cell-input[readonly]:hover { border-color: transparent; }
.cell-input[data-missing="true"] { border-color: var(--color-warning); background: var(--color-warning-light); }
.cell-input[data-bad="true"] { border-color: var(--color-danger); background: var(--color-danger-light); }
.cell-money { display: flex; align-items: center; gap: 3px; }
.cell-money .cur { color: var(--color-text-tertiary); flex: 0 0 auto; font-weight: var(--font-semibold); }
.cell-select { flex: 1; min-width: 0; height: 36px; padding: 0 var(--space-2); border: 1px solid transparent; border-radius: var(--radius-md); background: var(--color-surface-sunken); color: var(--color-text-primary); font-size: var(--text-sm); font-family: inherit; cursor: pointer; }
.cell-select:hover { border-color: var(--color-border-strong); }
.cell-select:focus { outline: none; background: var(--color-surface); border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }
.cell-select[disabled] { background: transparent; cursor: default; padding-left: 0; }

/* ============================================================
   GAPS DE NORMALIZACIÓN (2026-06-04) — primitivos que faltaban y que casi toda
   pantalla usa (las pantallas dejan de inventar su versión). Genéricos, solo
   tokens. dist NO regenerado: se hornean junto con lo que aporte cuenta/perfil.
   ============================================================ */

/* Variantes de botón faltantes (usadas por webhooks/perfil/otros) */
.btn-secondary { background: var(--color-surface-sunken); color: var(--color-text-primary); border-color: var(--color-border); }
.btn-secondary:hover { background: var(--color-surface); border-color: var(--color-border-strong); }
.btn-outline { background: var(--color-surface); color: var(--color-text-primary); border-color: var(--color-border); }
.btn-outline:hover { background: var(--color-surface-sunken); border-color: var(--color-border-strong); }
.btn-sm { min-height: 36px; padding: 0 var(--space-3); font-size: var(--text-xs); }
.btn-sm .icon { width: 1rem; height: 1rem; }

/* Badge genérico (etiqueta/estado NO-veredicto: tipo de cuenta, rol, "Nuevo", "Archivada") */
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; border-radius: var(--badge-radius); font-size: 11px; font-weight: var(--font-semibold); white-space: nowrap; background: var(--color-surface-sunken); color: var(--color-text-secondary); border: 1px solid var(--color-border); }
.badge .icon { width: 13px; height: 13px; }
.badge-neutral { background: var(--color-surface-sunken); color: var(--color-text-tertiary); }
.badge-info { background: var(--color-info-light); color: var(--color-info-text); border-color: transparent; }
.badge-accent { background: var(--color-accent-light); color: var(--color-text-link); border-color: transparent; }
.badge-success { background: var(--color-success-light); color: var(--color-success-text); border-color: transparent; }
.badge-warning { background: var(--color-warning-light); color: var(--color-warning-text); border-color: transparent; }
.badge-danger { background: var(--color-danger-light); color: var(--color-danger-text); border-color: transparent; }

/* Callout / banner inline accionable (info/warning/success/danger). El danger
   intenso de preflight ya existe (.preflight); esto es el banner sobrio. */
.callout { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-radius: var(--radius-md); font-size: var(--text-sm); line-height: var(--leading-normal); background: var(--color-surface-sunken); color: var(--color-text-secondary); }
.callout > .icon { width: 1.125rem; height: 1.125rem; flex: 0 0 auto; margin-top: 1px; }
.callout-body { min-width: 0; flex: 1; }
.callout-title { font-weight: var(--font-semibold); }
.callout-action { margin-left: auto; flex: 0 0 auto; align-self: center; }
.callout-info { background: var(--color-info-light); color: var(--color-info-text); }
.callout-info > .icon { color: var(--color-info-text); }
.callout-warning { background: var(--color-warning-light); color: var(--color-warning-text); }
.callout-warning > .icon { color: var(--color-warning-text); }
.callout-success { background: var(--color-success-light); color: var(--color-success-text); }
.callout-success > .icon { color: var(--color-success-text); }
.callout-danger { background: var(--color-danger-light); color: var(--color-danger-text); }
.callout-danger > .icon { color: var(--color-danger-text); }

/* Avatar de iniciales reusable (cards/identidad). El topbar le añade su margen
   vía `.topbar .avatar` en shell.css. */
.avatar { width: 36px; height: 36px; border-radius: var(--badge-radius); background: var(--color-accent); color: var(--color-text-inverse); display: grid; place-items: center; font-weight: var(--font-semibold); font-size: var(--text-sm); flex: 0 0 auto; }
.avatar-sm { width: 28px; height: 28px; font-size: var(--text-xs); }
.avatar-lg { width: 48px; height: 48px; font-size: var(--text-base); }
.avatar-muted { background: var(--color-surface-sunken); color: var(--color-text-secondary); }

/* OTP — fila de inputs de dígito (el modal contenedor usa .mx-modal/overlays) */
.otp-input { display: flex; gap: var(--space-2); justify-content: center; }
.otp-digit { width: 44px; height: 52px; text-align: center; font-size: var(--text-xl); font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; font-family: var(--font-family-mono); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text-primary); }
.otp-digit:focus { outline: none; border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }
.otp-digit.is-filled { border-color: var(--color-border-strong); }
.otp-digit.is-error { border-color: var(--color-danger); }

/* ============================================================
   EXTRACCIÓN cuenta/perfil (2026-06-04) — composiciones reusables que el perfil
   estrenó y que sirven a settings/detalle en general. Genéricas, solo tokens.
   (CD las generó como `.pf-*`/`.notice`/`.kpi-strip`[stat] sobre un dist viejo →
   aquí quedan CANÓNICAS; la reconciliación de vocab se anota en porting-notes.)
   ============================================================ */

/* Composición de tarjeta: cabecera + cuerpo + pie + divisor full-bleed (sobre .card) */
.card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-border); }
.card-head.no-border { border-bottom: 0; padding-bottom: 0; }
.card-title { font-size: var(--text-base); font-weight: var(--font-semibold); margin: 0; display: inline-flex; align-items: center; gap: var(--space-2); }
.card-title .icon { width: 1.125rem; height: 1.125rem; color: var(--color-text-tertiary); }
.card-title.danger, .card-title.danger .icon { color: var(--color-danger-text); }
.card-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: 2px; }
.card-body { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-5); }
.card-body.tight { gap: var(--space-3); }
.card-foot { display: flex; justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap; padding: var(--space-4) var(--space-5); border-top: 1px solid var(--color-border); }
.card-foot.between { justify-content: space-between; align-items: center; }
.card-foot.start { justify-content: flex-start; }
.card-divider { height: 1px; background: var(--color-border); margin: 0 calc(-1 * var(--space-5)); }
.card-danger { border-color: var(--color-danger-text); background: var(--color-danger-light); }
.card-danger .card-head { border-bottom-color: var(--color-danger-light); }

/* Campo en modo lectura (label + valor + acciones inline) — settings ver→editar */
.readfield { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.readfield-main { min-width: 0; flex: 1 1 auto; }
.readfield-label { font-size: var(--text-xs); color: var(--color-text-tertiary); }
.readfield-val { font-size: var(--text-base); font-weight: var(--font-medium); margin-top: 2px; display: inline-flex; align-items: center; gap: 6px; max-width: 100%; overflow-wrap: anywhere; }
.readfield-val .icon { width: 1rem; height: 1rem; color: var(--color-text-tertiary); }
.readfield-val.flush { margin-top: 0; }
.inline-actions { display: flex; align-items: center; gap: var(--space-3); flex: 0 0 auto; flex-wrap: wrap; }

/* Input con botón pegado (toggle ver/ocultar, copiar, limpiar) */
.input-affix { position: relative; display: flex; align-items: center; }
.input-affix .field-input { padding-right: 44px; }
.affix-btn { position: absolute; right: 4px; width: 36px; height: 36px; display: grid; place-items: center; border: 0; background: transparent; color: var(--color-text-tertiary); border-radius: var(--radius-md); cursor: pointer; }
.affix-btn:hover { color: var(--color-text-primary); background: var(--color-surface-sunken); }
.affix-btn .icon { width: 1.125rem; height: 1.125rem; }

/* Medidor de nivel (fuerza de contraseña, etc.) — 4 segmentos por data-level */
.meter { display: flex; flex-direction: column; gap: 6px; }
.meter-track { display: flex; gap: 4px; }
.meter-seg { flex: 1; height: 5px; border-radius: var(--badge-radius); background: var(--color-surface-sunken); transition: background var(--transition-fast); }
.meter[data-level="1"] .meter-seg:nth-child(-n+1) { background: var(--color-danger); }
.meter[data-level="2"] .meter-seg:nth-child(-n+2) { background: var(--color-warning); }
.meter[data-level="3"] .meter-seg:nth-child(-n+3) { background: var(--color-info); }
.meter[data-level="4"] .meter-seg { background: var(--color-success); }
.meter-label { font-size: var(--text-xs); color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; }
.meter-label b { font-weight: var(--font-semibold); color: var(--color-text-secondary); }

/* Selector de opción como FILAS (radio) — distinto de .sel-card (grid de tarjetas) */
.radio-group { display: flex; flex-direction: column; gap: var(--space-2); }
.radio-row { position: relative; display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border: 1px solid var(--color-border); border-radius: var(--card-radius); cursor: pointer; }
.radio-row:hover { background: var(--color-surface-sunken); }
.radio-row.selected { border-color: var(--color-accent); box-shadow: inset 0 0 0 1px var(--color-accent); background: var(--color-accent-light); }
.radio-row input { position: absolute; opacity: 0; width: 0; height: 0; }
.radio-dot { width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--color-border-strong); flex: 0 0 auto; display: grid; place-items: center; }
.radio-dot::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--color-accent); transform: scale(0); transition: transform var(--transition-fast); }
.radio-row.selected .radio-dot { border-color: var(--color-accent); }
.radio-row.selected .radio-dot::after { transform: scale(1); }
.radio-row input:focus-visible + .radio-dot { outline: var(--ring-width) solid var(--ring-color); outline-offset: 2px; }
.radio-ico { width: 36px; height: 36px; border-radius: var(--radius-md); background: var(--color-surface-sunken); color: var(--color-text-secondary); display: grid; place-items: center; flex: 0 0 auto; }
.radio-text { flex: 1; min-width: 0; }
.radio-title { font-weight: var(--font-medium); font-size: var(--text-sm); display: flex; align-items: center; gap: var(--space-2); }
.radio-desc { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: 1px; }

/* Fila con icono (canal de notif / sesión / dispositivo): ico + cuerpo + meta + acciones */
.media-row { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-4) var(--space-5); }
.media-row + .media-row { border-top: 1px solid var(--color-border); }
.media-ico { width: 40px; height: 40px; border-radius: var(--radius-md); background: var(--color-surface-sunken); color: var(--color-text-secondary); display: grid; place-items: center; flex: 0 0 auto; }
.media-row.on .media-ico { background: var(--color-accent-light); color: var(--color-accent); }
.media-main { flex: 1; min-width: 0; }
.media-titlerow { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.media-title { font-weight: var(--font-semibold); font-size: var(--text-sm); }
.media-meta { font-size: var(--text-xs); color: var(--color-text-tertiary); margin-top: 3px; }
.media-meta .mono { font-family: var(--font-family-mono); }
.media-actions { display: flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; flex-wrap: wrap; justify-content: flex-end; }
/* Estados de fila (checklist/onboarding): hecho · siguiente (resalte) · automático */
.media-row.is-done .media-ico { background: var(--color-success-light); color: var(--color-success-text); }
.media-row.is-next { background: var(--color-accent-light); }
.media-row.is-next .media-ico { background: var(--color-accent); color: var(--color-text-inverse); }
.media-row.is-auto .media-ico { background: var(--color-surface-sunken); color: var(--color-text-tertiary); }

/* Stat strip (resumen de métricas con deeplink, dividido por hairline).
   NOTA: distinto de .kpi-strip (tiras de CONTEO de import) — nombres separados a propósito. */
.stat-strip { display: grid; grid-template-columns: 1fr 1fr; }
.stat-cell { padding: var(--space-4) var(--space-5); border-top: 1px solid var(--color-border); border-left: 1px solid var(--color-border); display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.stat-cell:nth-child(-n+2) { border-top: 0; }
.stat-cell:nth-child(odd) { border-left: 0; }
.stat-val { font-size: var(--text-2xl); font-weight: var(--font-bold); letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat-val small { font-size: var(--text-sm); font-weight: var(--font-medium); color: var(--color-text-tertiary); letter-spacing: 0; }
.stat-label { font-size: var(--text-xs); color: var(--color-text-tertiary); }
.stat-deeplink { margin-top: 2px; align-self: flex-start; display: inline-flex; align-items: center; gap: 3px; color: var(--color-text-link); font-size: var(--text-xs); font-weight: var(--font-medium); }
.stat-deeplink .icon { width: 13px; height: 13px; }
.stat-deeplink:hover { text-decoration: underline; }
@media (min-width: 768px) {
    .stat-strip { grid-template-columns: repeat(3, 1fr); }
    .stat-cell:nth-child(-n+3) { border-top: 0; }
    .stat-cell:nth-child(odd) { border-left: 1px solid var(--color-border); }
    .stat-cell:nth-child(3n+1) { border-left: 0; }
}

/* Variantes de botón estrenadas por perfil */
.btn-link { background: transparent; border: 0; min-height: 0; padding: 0; color: var(--color-text-link); font-weight: var(--font-semibold); font-size: var(--text-sm); cursor: pointer; }
.btn-link:hover { color: var(--color-text-link-hover); text-decoration: underline; }
.btn-link.danger { color: var(--color-danger-text); }
.btn-danger-ghost { background: transparent; color: var(--color-danger-text); border-color: var(--color-danger-text); }
.btn-danger-ghost:hover { background: var(--color-danger-light); }

/* Completar state-panel con título + descripción (vacío de sesiones) */
.state-title { font-weight: var(--font-semibold); color: var(--color-text-secondary); }
.state-desc { font-size: var(--text-sm); color: var(--color-text-tertiary); max-width: 34ch; }

/* Badge extra-chico (inline dentro de un título) */
.badge-xs { font-size: 10px; }

/* Callout: completar el patrón de banner accionable (icono + texto + acciones).
   Consolida la `.notice` que CD re-inventó en perfil → al portar, `.notice`→`.callout`. */
.callout-ico { flex: 0 0 auto; margin-top: 1px; }
.callout-ico .icon { width: 1.25rem; height: 1.25rem; }
.callout-text { font-size: var(--text-sm); margin-top: 2px; }
.callout-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }

/* ============================================================
   EXTRACCIÓN acceso/pre-auth (2026-06-04) — primitivos de FORMULARIO globales que
   estrenó el cluster de acceso (login/registro/recuperar). Genéricos, solo tokens.
   El chrome pre-auth vive en su capa de familia `preauth.css`.
   ============================================================ */

/* Campo con icono guía a la izquierda (mail/lock/usuario…) sobre .field-input */
.field-icon { position: relative; }
.field-icon > .icon { position: absolute; left: var(--space-3); top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--color-text-tertiary); pointer-events: none; }
.field-icon .field-input { padding-left: calc(var(--space-3) + 26px); }

/* Campo de teléfono compuesto: icono + prefijo de país (+52) + dígitos (tabular) */
.field-phone { display: flex; align-items: center; gap: var(--space-2); height: var(--input-height); padding-left: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); transition: border-color var(--transition-fast), box-shadow var(--transition-fast); }
.field-phone:focus-within { border-color: var(--color-border-focus); box-shadow: var(--input-focus-ring); }
.field-phone.is-error { border-color: var(--color-danger); }
.field-phone > .icon { width: 18px; height: 18px; color: var(--color-text-tertiary); flex: 0 0 auto; }
.field-phone .phone-cc { color: var(--color-text-secondary); font-weight: var(--font-medium); font-variant-numeric: tabular-nums; flex: 0 0 auto; padding-right: var(--space-2); border-right: 1px solid var(--color-border); }
.field-phone input { flex: 1; min-width: 0; height: 100%; border: 0; background: transparent; outline: none; font-family: inherit; font-size: var(--text-sm); color: var(--color-text-primary); padding: 0 var(--space-3) 0 0; font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.field-input.is-error { border-color: var(--color-danger); }

/* Estado "cargando" del botón (.btn): oculta el label y muestra el spinner */
.btn .btn-spin { display: none; width: 18px; height: 18px; }
.btn.is-loading { pointer-events: none; }
.btn.is-loading .btn-label, .btn.is-loading .btn-ico { display: none; }
.btn.is-loading .btn-spin { display: inline-block; animation: btn-spin .8s linear infinite; }
.btn.is-loading .btn-spin .icon { width: 18px; height: 18px; }
@keyframes btn-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .btn.is-loading .btn-spin { animation: none; } }

/* ============================================================
   EXTRACCIÓN uso (2026-06-04) — completaciones SIN conflicto de familias que ya
   existen (card-head · stat-cell · usage). Genéricas, solo tokens. (CD redefinió
   además badge/callout/card/stat-strip en su bundle; eso NO se toma — ver
   porting-notes; la reconciliación va al portar uso.)
   ============================================================ */

/* Sub-partes de la cabecera de tarjeta (texto + aside de acciones) */
.card-head-text { min-width: 0; }
.card-head-aside { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-2); }

/* Completar .stat-cell: fila val+badge · subtexto · valor atenuado */
.stat-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.stat-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; }
.stat-val.is-muted { color: var(--color-text-tertiary); font-weight: var(--font-semibold); }

/* Usage: tonos del relleno (ok/warn/danger) + porcentaje con tono */
.usage-fill.is-warn { background: var(--color-warning); }
.usage-fill.is-danger { background: var(--color-danger); }
.usage-pct { font-variant-numeric: tabular-nums; font-weight: var(--font-semibold); }
.usage-pct.is-warn { color: var(--color-warning-text); }
.usage-pct.is-danger { color: var(--color-danger-text); }

/* ============================================================
   Charts — capa centralizada (movido de finanzas.css + extraído de insights/métricas).
   Card de gráfica · donut · viz de serie temporal. Leyenda: ver .chart-legend arriba.
   ============================================================ */

/* Card de gráfica (movido de finanzas.css; compartido finanzas/insights/banxico) */
.chart-card { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); }
.chart-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
.chart-title { font-size: var(--text-base); font-weight: var(--font-semibold); margin: 0; }
.chart-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); margin: 2px 0 0; }

/* Donut (movido de finanzas.css) — distribución categórica multi-segmento */
.donut-wrap { display: flex; align-items: center; gap: var(--space-5); }
.donut { position: relative; width: 116px; height: 116px; flex: 0 0 auto; }
.donut svg { transform: rotate(-90deg); }
.donut-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.donut-total { font-size: var(--text-lg); font-weight: var(--font-bold); font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: -.02em; }
.donut-cap { font-size: 9px; color: var(--color-text-tertiary); text-transform: uppercase; letter-spacing: .04em; }
.donut-legend { display: flex; flex-direction: column; gap: var(--space-2); flex: 1; min-width: 0; }
.dleg { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); }
.dleg .legend-dot { border-radius: 50%; width: 9px; height: 9px; }
.dleg-name { color: var(--color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dleg-val { margin-left: auto; font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
/* Segmento de dona (trazo por veredicto). El contenedor .donut ya rota -90°. De admin/usuarios/detalle. */
.donut-seg { fill: none; stroke-width: 14; }
.donut-seg.is-valid    { stroke: var(--color-success); }
.donut-seg.is-notfound { stroke: var(--color-warning); }
.donut-seg.is-cep      { stroke: var(--color-info); }
.donut-seg.is-error    { stroke: var(--color-danger); }
.donut-seg.is-track    { stroke: var(--color-surface-sunken); }
.donut-seg.is-proc     { stroke: var(--color-accent); }
.donut-seg.is-pend     { stroke: var(--color-border-strong); }
/* Paleta categórica genérica (series sin semántica de veredicto). De admin/planes (dona por plan). */
.donut-seg.is-s1 { stroke: var(--color-accent); }
.donut-seg.is-s2 { stroke: var(--color-success); }
.donut-seg.is-s3 { stroke: var(--color-warning); }
.donut-seg.is-s4 { stroke: var(--color-border-strong); }

/* Viz de serie temporal SVG (barras apiladas / líneas de percentiles + ejes/grid).
   El consumidor pinta stroke/fill con getComputedStyle de tokens (no #hex). De insights. */
.chart { width: 100%; display: flex; flex-direction: column; gap: var(--space-4); }
.chart-svg { width: 100%; height: auto; display: block; }
.chart-svg .chart-grid-line { stroke: var(--color-border); stroke-width: 1; }
.chart-svg .chart-axis-base { stroke: var(--color-border-strong); stroke-width: 1; }
/* Etiquetas de eje de chart (<text> SVG). Canónico — convergencia de los charts admin. */
.chart-axis-label { font-size: 11px; fill: var(--color-text-tertiary); font-family: var(--font-family-mono); }   /* tick numérico */
.chart-cat-label { font-size: 12px; fill: var(--color-text-tertiary); font-family: var(--font-family); }   /* etiqueta de categoría */
.chart-bar-val { font-size: 10px; fill: var(--color-text-secondary); font-family: var(--font-family-mono); font-variant-numeric: tabular-nums; }   /* valor sobre la barra */
.chart-axis-x { text-anchor: middle; }
.chart-axis-y { text-anchor: end; }
.chart-bar { shape-rendering: crispEdges; }
.chart-bar.is-valid    { fill: var(--color-success); }
.chart-bar.is-notfound { fill: var(--color-warning); }
.chart-bar.is-cep      { fill: var(--color-info); }
.chart-bar.is-error    { fill: var(--color-danger); }
.chart-line { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.chart-line.is-avg { stroke-dasharray: 5 5; }
.chart-point { stroke: var(--color-surface); stroke-width: 1.5; }

/* Lista-ranking con barra de proporción (de insights · admin top-banks/top-errors reusa) */
.rank { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.rank-row { display: grid; grid-template-columns: 1.5em 36px minmax(0, 1fr) auto; align-items: center; gap: var(--space-2) var(--space-3); padding: var(--space-3) var(--space-4); }
.rank-row + .rank-row { border-top: 1px solid var(--color-border); }
.rank-no { font-family: var(--font-family-mono); font-size: var(--text-xs); color: var(--color-text-tertiary); text-align: right; }
.rank-main { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.rank-namerow { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; }
.rank-name { font-weight: var(--font-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.rank-bar-track { height: 6px; border-radius: var(--badge-radius); background: var(--color-surface-sunken); overflow: hidden; }
.rank-bar-fill { height: 100%; border-radius: var(--badge-radius); background: var(--color-accent); transition: width var(--transition-normal); }
.rank-bar-fill.is-error { background: var(--color-danger); }
.rank-stats { text-align: right; display: flex; flex-direction: column; gap: 2px; flex: 0 0 auto; }
.rank-val { font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; }
.rank-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rank-sub .is-bad { color: var(--color-danger-text); }
@media (min-width: 1100px) {
  .rank-row { padding: var(--space-3) var(--space-5); gap: var(--space-2) var(--space-4); }
}

/* Panel KPI — superficie única dividida por hairlines (gap 1px); celda hero + medidor.
   Reflujo 2 col (hero a todo el ancho) → 5 col en una fila. De insights/métricas. */
.kpi-panel { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--color-border); border: 1px solid var(--color-border); border-radius: var(--card-radius); overflow: hidden; }
.kpi-cell { background: var(--color-surface); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.kpi-cell-val { font-size: var(--text-2xl); font-weight: var(--font-bold); font-variant-numeric: tabular-nums; letter-spacing: -.02em; line-height: 1.05; }
.kpi-cell-label { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: 1.2; }
.kpi-cell-sub { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-xs); color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; margin-top: 1px; }
.kpi-cell-sub .icon { width: 13px; height: 13px; flex: 0 0 auto; }
.kpi-cell-meter { height: 4px; border-radius: var(--badge-radius); background: var(--color-surface-sunken); overflow: hidden; margin-top: var(--space-2); }
.kpi-cell-meter-fill { height: 100%; background: var(--color-success); border-radius: var(--badge-radius); transition: width var(--transition-normal); }
/* KPI deeplinkable (la celda es <a>) + delta ↑/↓ + sufijo de unidad. De admin/validaciones/lista. */
a.kpi-cell { text-decoration: none; transition: background var(--transition-fast); }
a.kpi-cell:hover { background: var(--color-surface-sunken); }
a.kpi-cell.is-hero:hover { background: var(--color-surface-muted); }
.kpi-delta { display: inline-flex; align-items: center; gap: 3px; font-weight: var(--font-medium); }
.kpi-delta.is-up { color: var(--color-success-text); }
.kpi-delta.is-down { color: var(--color-danger-text); }
.kpi-delta .icon { width: 13px; height: 13px; }
.kpi-unit { font-size: var(--text-base); font-weight: var(--font-medium); color: var(--color-text-tertiary); letter-spacing: 0; }
.kpi-cell.is-hero { grid-column: 1 / -1; background: var(--color-surface-sunken); gap: var(--space-1); }
.kpi-cell.is-hero .kpi-cell-val { font-size: var(--text-4xl); }
@media (min-width: 720px) {
  .kpi-panel { grid-template-columns: 1.25fr 1fr 1fr 1fr 1fr; }
  .kpi-cell.is-hero { grid-column: auto; justify-content: center; }
}

/* sr-only — utilidad solo-lectores-de-pantalla (faltaba en el sistema) */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Skeleton — superficie shimmer reutilizable (usa @keyframes sk-shimmer ya central) */
.skeleton { border-radius: var(--radius-md); background: linear-gradient(90deg, var(--color-surface-sunken) 0%, var(--color-surface-muted) 50%, var(--color-surface-sunken) 100%); background-size: 200% 100%; animation: sk-shimmer 1.3s ease-in-out infinite; }
.skeleton.is-chart { width: 100%; }
.skeleton.is-donut { width: 116px; height: 116px; border-radius: 50%; flex: 0 0 auto; }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

/* Disclosure — sección colapsable (plegada por defecto): cabecera + contador + chevron (de notificaciones) */
.disclosure-head { display: flex; align-items: center; gap: var(--space-2); width: 100%; padding: var(--space-1) 0; background: transparent; border: 0; cursor: pointer; color: inherit; min-height: 36px; font-family: inherit; }
.disclosure-count { font-size: var(--text-xs); font-weight: var(--font-semibold); color: var(--color-text-secondary); background: var(--color-surface-sunken); border-radius: var(--badge-radius); padding: 1px 7px; font-variant-numeric: tabular-nums; }
.disclosure-chev { width: 16px; height: 16px; color: var(--color-text-tertiary); margin-left: auto; transition: transform var(--transition-fast); }
.disclosure-head[aria-expanded="true"] .disclosure-chev { transform: rotate(180deg); }
.disclosure-body { padding-top: var(--space-2); }
.disclosure-body[hidden] { display: none; }

/* State pill — indicador on/off con punto + texto (de notificaciones) */
.state-pill { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm); font-weight: var(--font-semibold); }
.state-pill-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.state-pill.is-on { color: var(--color-success-text); }
.state-pill.is-on .state-pill-dot { background: var(--color-success); }
.state-pill.is-off { color: var(--color-text-tertiary); }
.state-pill.is-off .state-pill-dot { background: var(--color-text-tertiary); }
.state-pill.is-down { color: var(--color-danger-text); font-weight: var(--font-semibold); }
.state-pill.is-down .state-pill-dot { background: var(--color-danger); }

/* HTTP method badge — método coloreado en mono (de api-docs; playground/admin devtools reusa) */
.method-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 52px; padding: 2px 8px; border-radius: var(--radius-sm); font-family: var(--font-family-mono); font-size: 11px; font-weight: var(--font-bold); letter-spacing: .02em; text-transform: uppercase; flex: 0 0 auto; }
.method-badge.is-get { background: var(--color-accent-light); color: var(--color-text-link); }
.method-badge.is-post { background: var(--color-success-light); color: var(--color-success-text); }
.method-badge.is-put { background: var(--color-warning-light); color: var(--color-warning-text); }
.method-badge.is-delete { background: var(--color-danger-light); color: var(--color-danger-text); }

/* HTTP status pill — código + punto + texto (nunca solo color) (de api-docs) */
.http-status { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.http-status-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.http-status.is-2xx { color: var(--color-success-text); }
.http-status.is-2xx .http-status-dot { background: var(--color-success); }
.http-status.is-4xx { color: var(--color-warning-text); }
.http-status.is-4xx .http-status-dot { background: var(--color-warning); }
.http-status.is-5xx { color: var(--color-danger-text); }
.http-status.is-5xx .http-status-dot { background: var(--color-danger); }
