@charset "UTF-8";
/*
 * SKA Admin Components — Centralized CSS
 *
 * RULE: Zero hardcoded colors. Only var(--ska-*) from ska-tokens.css.
 * Location: settings/static/settings/css/
 * Loaded per-template via {% static 'settings/css/ska-admin-components.css' %}
 *
 * Components:
 * - .ska-dashboard, .ska-dash-* — KPI cards & dashboard grids
 * - .ska-stat-* — Stat cards (LLM usage, etc.)
 * - .ska-data-table — Clean data tables
 * - .ska-badge-* — Status badges
 * - .gcm-* — Google Credentials Manager
 * - .dsf-* — Drive Sync Filter dashboard
 * - .mcp-* — MCP Tester
 * - Utility classes (.ska-text-right, etc.)
 */

/* ═══════════════════════════════════════════════════
   TAILWIND-LIKE DESIGN TOKENS (Safe Mapping)
   ═══════════════════════════════════════════════════ */
.bg-ska-surface {
    background: var(--ska-surface) !important;
}

.bg-ska-surface-alt {
    background: var(--ska-surface-alt) !important;
}

.border-ska-border {
    border-color: var(--ska-border) !important;
}

.border-ska-primary {
    border-color: var(--ska-primary) !important;
}

.text-ska-text {
    color: var(--ska-text) !important;
}

.text-ska-text-secondary {
    color: var(--ska-text-secondary) !important;
}

.text-ska-text-muted {
    color: var(--ska-text-muted) !important;
}

.text-ska-text-subtle {
    color: var(--ska-text-subtle) !important;
}

.text-ska-primary {
    color: var(--ska-primary) !important;
}

/* ── Mappings Extraídos de UI_COMPONENTS.md ── */
.text-ska-success {
    color: var(--ska-success) !important;
}

.text-ska-danger {
    color: var(--ska-danger) !important;
}

.text-ska-warning {
    color: var(--ska-warning) !important;
}

.text-ska-info {
    color: var(--ska-info) !important;
}

.bg-ska-primary {
    background-color: var(--ska-primary) !important;
}

.bg-ska-primary-dark {
    background-color: var(--ska-primary-dark) !important;
}

.hover\:text-ska-primary:hover {
    color: var(--ska-primary) !important;
}

.hover\:border-ska-primary:hover {
    border-color: var(--ska-primary) !important;
}

.hover\:bg-ska-surface:hover {
    background-color: var(--ska-surface) !important;
}

.hover\:bg-ska-surface-alt:hover {
    background-color: var(--ska-surface-alt) !important;
}

.hover\:bg-ska-primary-dark:hover {
    background-color: var(--ska-primary-dark) !important;
}

/* ═══════════════════════════════════════════════════
   NATIVE <dialog>:modal CENTERING — preflight restoration
   ═══════════════════════════════════════════════════
   Tailwind preflight (unfold/css/styles.css) declares
   `*,::backdrop{margin:0}` (author origin), which OVERRIDES the browser UA
   stylesheet rule `dialog:modal{margin:auto}` that centers modal dialogs.
   Effect: every <dialog>.showModal() sticks to the top-left corner
   (UA `:modal` gives position:fixed + inset:0, but margin is now 0 instead
   of auto). Restoring margin:auto re-centers ALL native modal dialogs
   project-wide. `dialog:modal` (specificity 0,1,1) beats `*` (0,0,0), so
   this wins regardless of stylesheet load order. */
dialog:modal {
    margin: auto;
}

/* ═══════════════════════════════════════════════════
   UNIFIED DASHBOARD & DETAIL VIEWS (ska-admin-*)
   Official standard as per DESIGN_SYSTEM.md Section 8
   ═══════════════════════════════════════════════════ */

/* ── Layout — full-width (match Flutter scaffold).
       El content area Unfold ya provee padding lateral; aquí solo padding vertical. ── */
.ska-admin-wrap {
    width: 100%;
    padding: 16px 0;
    box-sizing: border-box;
}

/* ── Page Header ── */
.ska-admin-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
}

.ska-admin-header h1 {
    font-size: 22px;
    font-weight: 700;
    color: var(--ska-text);
    margin: 0;
    display: flex;
    align-items: center;
    gap: 10px;
}

.ska-admin-header h1 i {
    color: var(--ska-primary);
}

/* ── Nav Lateral / Tabs ── */
.ska-admin-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 12px 0 20px;
    border-bottom: 1px solid var(--ska-border);
    margin-bottom: 24px;
}

.ska-admin-nav-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: var(--ska-radius-md);
    font-size: 13px;
    font-weight: 500;
    color: var(--ska-text-secondary);
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    text-decoration: none;
    transition: all 0.2s ease;
}

.ska-admin-nav-link:hover {
    color: var(--ska-text);
    background: var(--ska-surface-alt);
    border-color: var(--ska-border-hover);
    box-shadow: var(--ska-shadow-sm);
}

.ska-admin-nav-link.active {
    color: var(--ska-primary);
    background: var(--ska-surface-alt);
    border-color: var(--ska-primary);
    font-weight: 600;
}

.ska-admin-nav-link i {
    text-align: center;
    width: 1rem;
}

/* ── Breadcrumbs Unificados ── */
.ska-admin-breadcrumb {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1rem;
    margin-bottom: 1.5rem;
    font-size: 13px;
    font-weight: 500;
    width: 100%;
    background-color: var(--ska-surface-alt);
    border-radius: var(--ska-radius-md);
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
    /* shadow-sm equivalente */
    border: 1px solid var(--ska-border);
    color: var(--ska-text-muted);
}

.ska-admin-breadcrumb-link {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    color: var(--ska-text-muted);
    transition: color 0.2s ease-in-out;
    text-decoration: none;
}

.ska-admin-breadcrumb-link:hover {
    color: var(--ska-primary);
}

.ska-admin-breadcrumb-separator {
    color: var(--ska-border-medium);
    font-size: 9px;
    display: flex;
    align-items: center;
}

.ska-admin-breadcrumb-current {
    color: var(--ska-text);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── App Dock (Bento Navigation) ── */
.ska-admin-dock-nav {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 16px;
    margin-bottom: 32px;
}

.ska-admin-dock-btn {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
    color: var(--ska-text);
    transition: all 0.2s ease;
    box-shadow: var(--ska-shadow-sm);
    margin-top: 2px;
}

.ska-admin-dock-btn:hover {
    background: var(--ska-surface-alt);
    border-color: var(--ska-border-hover);
    box-shadow: var(--ska-shadow-md);
    transform: translateY(-1px);
}

.ska-admin-dock-btn .dock-icon {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 16px;
}

.ska-admin-dock-btn .dock-icon.color-green {
    background: var(--ska-badge-green-bg);
    color: var(--ska-accent-green);
}

.ska-admin-dock-btn .dock-icon.color-gray {
    background: var(--ska-surface-alt);
    color: var(--ska-text-secondary);
    border: 1px solid var(--ska-border);
}

.ska-admin-dock-btn .dock-icon.color-amber {
    background: var(--ska-badge-yellow-bg);
    color: var(--ska-accent-amber);
}

.ska-admin-dock-btn .dock-icon.color-blue {
    background: var(--ska-badge-blue-bg);
    color: var(--ska-accent-blue);
}

.ska-admin-dock-btn .dock-icon.color-purple {
    background: var(--ska-purple-bg);
    color: var(--ska-accent-purple);
}

.ska-admin-dock-btn .dock-icon.color-red {
    background: var(--ska-badge-red-bg);
    color: var(--ska-accent-red);
}

/* ── Filter Bar ── */
.ska-admin-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding: 14px 16px;
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    margin-bottom: 20px;
    align-items: flex-end;
}

.ska-admin-filter-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ska-admin-filter-group label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ska-text-muted);
}

.ska-admin-filter-group select,
.ska-admin-filter-group input {
    padding: 6px 10px;
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-sm);
    background: var(--ska-bg);
    color: var(--ska-text);
    font-size: 13px;
    min-width: 140px;
}

.ska-admin-filter-group select:focus,
.ska-admin-filter-group input:focus {
    outline: none;
    border-color: var(--ska-primary);
    box-shadow: 0 0 0 2px var(--ska-primary-glow);
}

.ska-admin-filter-btn {
    padding: 6px 16px;
    background: var(--ska-primary);
    color: var(--ska-text-on-primary);
    border: none;
    border-radius: var(--ska-radius-sm);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s;
    align-content: center;
}

.ska-admin-filter-btn:hover {
    background: var(--ska-primary-dark);
}

.ska-admin-filter-btn-reset {
    padding: 8.5px 16px;
    background: transparent;
    color: var(--ska-text-muted);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-sm);
    font-size: 13px;
    cursor: pointer;
    transition: all 0.2s;
    align-content: center;
}

.ska-admin-filter-btn-reset:hover {
    color: var(--ska-danger);
    border-color: var(--ska-danger);
}

/* ── Global Data Table (replaces ik-admin-table) ── */
.ska-admin-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    overflow: hidden;
}

.ska-admin-table thead th {
    padding: 10px 14px;
    text-align: left;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ska-text-muted);
    background: var(--ska-surface-alt);
    border-bottom: 1px solid var(--ska-border);
}

.ska-admin-table tbody tr {
    transition: background 0.15s;
}

.ska-admin-table tbody tr:hover {
    background: var(--ska-surface-alt);
}

.ska-admin-table tbody td,
.ska-admin-table tbody th {
    /* tbody th = cabecera de FILA (key-value): mismas guías que td */
    padding: 10px 14px;
    font-size: 13px;
    color: var(--ska-text);
    border-bottom: 1px solid var(--ska-border);
    vertical-align: middle;
}

.ska-admin-table tbody th {
    text-align: left;
    /* th por defecto centra → forzar izquierda */
    font-weight: 600;
}

.ska-admin-table tbody tr:last-child td,
.ska-admin-table tbody tr:last-child th {
    border-bottom: none;
}

.ska-admin-table--flush {
    /* Tabla que vive DENTRO de un panel ya bordeado (card con header propio):
       el panel aporta el borde + radio; la tabla NO debe duplicarlos (evita el
       efecto "tabla dentro de tabla"). Conserva separadores de fila y thead. */
    border: none;
    border-radius: 0;
}

/* ── Ledger agrupado por movimiento (changelist de Transaction) ──────────────
   Un `<tbody>` por movimiento: el elemento NATIVO para un grupo de filas, con
   `role=rowgroup` implícito. MDN pide no reimplementar con ARIA lo que el HTML
   ya hace, así que acá no hay ningún `role=` inventado — sólo estilo.

   ⚠️ Lo primero que hay que saber de este bloque: `.ska-admin-table tbody
   tr:last-child { border-bottom: none }` (arriba) se aplica POR `<tbody>`. Con
   varios, cada grupo perdía la línea de su última fila y los movimientos se
   pegaban entre sí. Se devuelve acá, y el separador FUERTE pasa a ser el borde
   del `<tbody>`, que es lo que de verdad separa un movimiento del siguiente. */
.ska-ledger-table tbody.ska-ledger-group:not(:last-child) {
    border-bottom: 2px solid var(--ska-border);
}

.ska-ledger-table tbody.ska-ledger-group tr:last-child td {
    border-bottom: 1px solid var(--ska-border);
}

.ska-ledger-group__head {
    background: var(--ska-surface-alt);
    cursor: pointer;
    user-select: none;
}

.ska-ledger-group__head:hover {
    background: var(--ska-surface-alt);
    filter: brightness(0.98);
}

.ska-ledger-group__head:focus-visible {
    outline: 2px solid var(--ska-primary);
    outline-offset: -2px;
}

.ska-ledger-group__head > td {
    padding: 8px 14px !important;
}

.ska-ledger-group__bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.ska-ledger-group__chevron {
    font-size: 11px;
    color: var(--ska-text-subtle);
    transition: transform 0.15s ease;
}

.ska-ledger-group__chevron.is-open {
    transform: rotate(90deg);
}

.ska-ledger-group__title {
    font-weight: 700;
    font-size: 13px;
    color: var(--ska-text);
}

/* Con quién fue el movimiento. Pesa menos que el título —el título es qué hecho es— pero más
   que la fecha: es lo que el operador busca cuando barre la lista con la vista. */
.ska-ledger-group__party {
    font-size: 12px;
    color: var(--ska-text-subtle);
    font-weight: 500;
}

.ska-ledger-group__date {
    font-size: 11px;
    color: var(--ska-text-subtle);
    text-transform: capitalize;
}

/* Los números del movimiento se van a la derecha; en pantalla angosta el
   `flex-wrap` del bar los baja a su propia línea en vez de comprimir el título. */
.ska-ledger-group__numbers {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 12px;
    white-space: nowrap;
}

/* La fila de un asiento va un punto más tenue que su cabecera: el ojo agarra
   primero el movimiento y después sus partes. */
.ska-ledger-leg > td {
    font-size: 12.5px;
}

.ska-ledger-summary {
    display: flex;
    gap: 1.25rem;
    flex-wrap: wrap;
    align-items: center;
    margin-bottom: 0.75rem;
    padding: 0.6rem 0.9rem;
    background: var(--ska-surface-alt);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    font-size: 13px;
}

/* La fila desde la que se llegó tras la redirección satélite → principal. Sin una marca, el
   operador hace click en #24743, aterriza en #24741 y no tiene forma de saber por qué la
   pantalla cambió ni dónde quedó el asiento que abrió. */
.ska-ledger-leg--from > td {
    background: var(--ska-surface-alt);
    box-shadow: inset 3px 0 0 0 var(--ska-primary);
}

.ska-ledger-summary__title {
    font-weight: 700;
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: 0.5px;
    color: var(--ska-text-subtle);
}

/* ── KPI Cards ── */
.ska-admin-kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}

.ska-admin-kpi-card {
    padding: 16px 20px;
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    transition: box-shadow 0.2s;
}

.ska-admin-kpi-card:hover {
    box-shadow: var(--ska-shadow-md);
}

/* ``.kpi-*`` sirven tanto DENTRO de ``.ska-admin-kpi-card`` (grid de KPIs) como SUELTAS
   (p.ej. el Pulso del Home, que apila los números en una lista dividida sin card por número). */
/* ── Dona de dinero ──────────────────────────────────────────────────────────
   Gráfico de torta sin librería: la CSP del admin no carga scripts externos, y una dona
   con agujero son dos cajas y un `conic-gradient`. Los cortes los inyecta el template en
   `--ska-donut-stops` (ver _money_card.html), ya calculados como % ENTEROS: un float ahí
   se serializa con COMA bajo es-CO y el navegador descarta la regla → la dona desaparece
   sólo en español. El color de cada quesito viaja en el stop, no en una var por hijo:
   las custom properties heredan hacia abajo y el padre no vería las de sus hijos. */
.ska-donut {
    position: relative;
    flex: 0 0 auto;
    width: 104px;
    height: 104px;
    border-radius: 50%;
    background: conic-gradient(var(--ska-donut-stops, var(--ska-border) 0% 100%));
}

.ska-donut__hole {
    position: absolute;
    inset: 21%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    border-radius: 50%;
    background: var(--ska-surface);
    text-align: center;
}

.ska-donut__total {
    font-size: 12px;
    font-weight: 700;
    line-height: 1.15;
    color: var(--ska-text);
    /* El total lleva moneda y miles ("$1.250.000"): sin esto rebalsa el agujero. */
    overflow-wrap: anywhere;
}

/* Cuadradito de color que ata cada fila de la leyenda a su quesito. */
.ska-donut__key {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 6px;
    border-radius: 2px;
    vertical-align: middle;
}

.kpi-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ska-text-muted);
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.ska-admin-kpi-card .kpi-value,
.kpi-value {
    font-size: 30px;
    font-weight: 700;
    color: var(--ska-text);
    line-height: 1.05;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
}

/* Fila número + curva. La usan las cards que traen serie (sparkline SVG); las que
   no, siguen apilando kpi-value normal. `--kpi-accent` (inline por card) tiñe la curva. */
.ska-admin-kpi-card .kpi-row {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 12px;
    min-height: 32px;
}
.ska-admin-kpi-card .kpi-spark {
    flex: 0 0 auto;
    width: 92px;
    height: 30px;
    overflow: visible;
    color: var(--kpi-accent, var(--ska-primary));
}
.ska-admin-kpi-card .kpi-spark polyline {
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}
.ska-admin-kpi-card .kpi-spark circle {
    fill: currentColor;
}

.ska-admin-kpi-card .kpi-sub,
.kpi-sub {
    font-size: 12px;
    color: var(--ska-text-secondary);
    margin-top: 4px;
}

/* ── Custom Detail Views (Detail Grid) ── */
.ska-admin-detail-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 20px;
    margin-bottom: 24px;
}

@media (max-width: 900px) {
    .ska-admin-detail-grid {
        grid-template-columns: 1fr;
    }
}

/* Columnas del split 2:1 (grid children). Regla compartida del platform admin:
   min-width:0 evita el overflow de grid items con contenido ancho (grids de
   fotos, texto largo); flex+gap apila las secciones con espaciado consistente
   sin depender del margin de cada sección. */
.ska-admin-detail-column-main,
.ska-admin-detail-column-side {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.ska-admin-detail-section {
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    padding: 20px;
    margin-bottom: 20px;
}

.ska-admin-detail-section h3 {
    font-size: 14px;
    font-weight: 700;
    color: var(--ska-text);
    margin: 0 0 14px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.ska-admin-detail-section h3 i {
    color: var(--ska-primary);
}

.ska-admin-detail-header {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    padding: 16px 20px;
    margin-bottom: 20px;
}

.ska-admin-detail-icon {
    font-size: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 60px;
    height: 60px;
    background: var(--ska-surface-alt);
    border-radius: var(--ska-radius-md);
    color: var(--ska-text-muted);
}

.ska-admin-detail-title {
    font-size: 22px;
    font-weight: 700;
    margin: 0 0 6px 0;
    color: var(--ska-text);
}

/* ── Universal Tabs ── */
.ska-admin-tabs {
    display: flex;
    gap: 0;
    margin-bottom: 20px;
    border-bottom: 2px solid var(--ska-border);
}

.ska-admin-tab {
    padding: 10px 20px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ska-text-muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    transition: all 0.2s;
    display: flex;
    align-items: center;
    gap: 6px;
}

.ska-admin-tab:hover {
    color: var(--ska-text);
}

.ska-admin-tab.active {
    color: var(--ska-primary);
    border-bottom-color: var(--ska-primary);
}

.ska-admin-tab .tab-count {
    background: var(--ska-border);
    color: var(--ska-text-muted);
    padding: 1px 6px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
}

.ska-admin-tab.active .tab-count {
    background: var(--ska-primary);
    color: var(--ska-text-on-primary);
}

/* ── JSON Block ── */
.ska-admin-json-block {
    background: var(--ska-bg);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
    padding: 12px;
    font-family: var(--ska-font-mono, monospace);
    font-size: 12px;
    color: var(--ska-text);
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-all;
    margin: 0;
}

/* ═══════════════════════════════════════════════════
   DASHBOARD (Admin Dashboard)
   ═══════════════════════════════════════════════════ */

.ska-dashboard,
.ik-chat-dashboard {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

.ska-dash-grid,
.dash-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 20px;
    margin-bottom: 30px;
}

.ska-dash-card,
.dash-card {
    background: var(--ska-surface);
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius-md);
    padding: 20px;
    box-shadow: var(--ska-shadow-sm);
}

.ska-dash-card h3,
.dash-card h3 {
    margin: 0 0 4px 0;
    font-size: 14px;
    color: var(--ska-text-muted);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.ska-dash-card .value,
.dash-card .value {
    font-size: 32px;
    font-weight: 700;
    color: var(--ska-text);
}

.ska-dash-card .sub,
.dash-card .sub {
    font-size: 13px;
    color: var(--ska-text-subtle);
    margin-top: 4px;
}

.ska-dash-section,
.dash-section {
    margin-bottom: 30px;
}

.ska-dash-section h2,
.dash-section h2 {
    font-size: 18px;
    font-weight: 600;
    margin: 0 0 15px 0;
    padding-bottom: 8px;
    border-bottom: 2px solid var(--ska-primary);
}

/* ═══════════════════════════════════════════════════
   DATA TABLES (shared by dashboard, llmusage, etc.)
   ═══════════════════════════════════════════════════ */

.ska-data-table,
.dash-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.ska-data-table th,
.dash-table th {
    text-align: left;
    padding: 10px 12px;
    background: var(--ska-surface-alt);
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ska-text-muted);
}

.ska-data-table td,
.dash-table td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--ska-border);
}

.ska-data-table tr:hover td,
.dash-table tr:hover td {
    background: var(--ska-surface-alt);
}

/* ═══════════════════════════════════════════════════
   BADGES
   ═══════════════════════════════════════════════════ */

.ska-badge,
[class^="ska-badge-"],
[class*=" ska-badge-"],
.badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    /* Separación consistente entre iconos y texto */
    padding: 0.125rem 0.5rem;
    /* px-2 py-0.5 fallback */
    border-radius: 9999px;
    font-size: 0.75rem;
    /* 12px text-xs */
    font-weight: 500;
    white-space: nowrap;
    /* Previene rupturas de línea inestéticas */
    line-height: 1.25rem;
}

.ska-badge-green,
.badge-green {
    background: var(--ska-badge-green-bg);
    color: var(--ska-badge-green-text);
}

.ska-badge-red,
.badge-red {
    background: var(--ska-badge-red-bg);
    color: var(--ska-badge-red-text);
}

.ska-badge-yellow,
.badge-yellow {
    background: var(--ska-badge-yellow-bg);
    color: var(--ska-badge-yellow-text);
}

.ska-badge-blue,
.badge-blue {
    background: var(--ska-badge-blue-bg);
    color: var(--ska-badge-blue-text);
}

.ska-badge-gray,
.badge-gray {
    background: var(--ska-surface-alt);
    color: var(--ska-text-muted);
}

/* ═══════════════════════════════════════════════════
   FLAG ROWS (feature flags in dashboard)
   ═══════════════════════════════════════════════════ */

.ska-flag-row,
.flag-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid var(--ska-border);
}

.ska-flag-name,
.flag-name {
    font-family: var(--ska-font-mono);
    font-size: 13px;
    font-weight: 600;
    min-width: 320px;
}

.ska-flag-value,
.flag-value {
    font-size: 13px;
}

/* ═══════════════════════════════════════════════════
   STAT CARDS (LLM Usage)
   ═══════════════════════════════════════════════════ */

.ska-stat-dashboard,
.llm-dashboard {
    margin-bottom: 24px;
}

.ska-stat-grid,
.llm-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}

.ska-stat-card,
.llm-stat-card {
    border-radius: var(--ska-radius-md);
    padding: 16px;
    text-align: center;
    border: 1px solid var(--ska-border);
    background: var(--ska-surface);
}

.ska-stat-value,
.llm-stat-value {
    font-size: 28px;
    font-weight: 700;
}

.ska-stat-label,
.llm-stat-label {
    font-size: 12px;
    margin-top: 4px;
    color: var(--ska-text-muted);
}

.ska-section-title,
.llm-section-title {
    cursor: pointer;
    font-weight: 600;
    font-size: 14px;
    padding: 8px 0;
    color: var(--ska-text-secondary);
}

.ska-stat-table,
.llm-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.ska-stat-table thead tr,
.llm-table thead tr {
    border-bottom: 2px solid var(--ska-border-medium);
}

.ska-stat-table th,
.llm-table th {
    padding: 10px 12px;
    color: var(--ska-text-muted);
}

.ska-stat-table td,
.llm-table td {
    padding: 8px 12px;
}

.ska-stat-table tbody tr,
.llm-table tbody tr {
    border-bottom: 1px solid var(--ska-border);
}

/* ── Current shift row highlight ── */
.llm-row-current {
    background: var(--ska-primary-glow);
    font-weight: 600;
}

.llm-row-current td:first-child::before {
    content: "▶ ";
}

/* ═══════════════════════════════════════════════════
   GOOGLE CREDENTIALS MANAGER
   ═══════════════════════════════════════════════════ */

.gcm-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

.gcm-section {
    margin-bottom: 32px;
}

.gcm-section-title {
    font-size: 18px;
    font-weight: 600;
    margin: 0 0 16px 0;
    padding-bottom: 8px;
    border-bottom: 2px solid var(--ska-primary);
    color: var(--ska-text);
}

.gcm-back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 20px;
    font-size: 13px;
    color: var(--ska-accent);
    text-decoration: none;
}

.gcm-back-link:hover {
    text-decoration: underline;
}

/* ── Cards ── */
.gcm-card {
    background: var(--ska-surface);
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius-md);
    padding: 24px;
    box-shadow: var(--ska-shadow-sm);
    margin-bottom: 16px;
}

.gcm-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
}

.gcm-card-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--ska-text);
    display: flex;
    align-items: center;
    gap: 8px;
}

.gcm-card-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.gcm-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
    gap: 16px;
}

/* ── GCM Badges ── */
.gcm-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
}

.gcm-badge-valid {
    background: var(--ska-success-bg);
    color: var(--ska-success);
}

.gcm-badge-expired {
    background: var(--ska-danger-bg);
    color: var(--ska-danger);
}

.gcm-badge-expiring {
    background: var(--ska-warning-bg);
    color: var(--ska-warning);
}

.gcm-badge-none {
    background: var(--ska-surface-alt);
    color: var(--ska-text-muted);
}

.gcm-badge-oauth {
    background: var(--ska-info-bg);
    color: var(--ska-info);
}

.gcm-badge-sa {
    background: var(--ska-purple-bg);
    color: var(--ska-purple);
}

/* ── GCM Info rows ── */
.gcm-info-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid var(--ska-border);
}

.gcm-info-row:last-child {
    border-bottom: none;
}

.gcm-info-label {
    font-size: 13px;
    color: var(--ska-text-muted);
    min-width: 120px;
    font-weight: 500;
}

.gcm-info-value {
    font-size: 13px;
    color: var(--ska-text);
}

/* ── Sync chips ── */
.gcm-sync-grid {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.gcm-sync-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    border-radius: 8px;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    transition: opacity 0.15s ease;
}

.gcm-sync-chip:hover {
    opacity: 0.8;
}

.gcm-sync-on {
    background: var(--ska-success-bg);
    color: var(--ska-success);
}

.gcm-sync-off {
    background: var(--ska-surface-alt);
    color: var(--ska-text-subtle);
    text-decoration: line-through;
}

/* ── GCM Buttons ── */
.gcm-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 6px 14px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    border: 1px solid transparent;
    transition: all 0.15s ease;
}

.gcm-btn-primary {
    background: var(--ska-primary);
    color: var(--ska-text-on-primary);
}

.gcm-btn-primary:hover {
    opacity: 0.9;
    color: var(--ska-surface);
}

.gcm-btn-danger {
    background: var(--ska-danger-bg);
    color: var(--ska-danger);
    border-color: var(--ska-danger-bg);
}

.gcm-btn-danger:hover {
    opacity: 0.85;
}

.gcm-btn-sm {
    padding: 0.25rem 0.6rem;
    font-size: 0.75rem;
}

.gcm-input-inline {
    padding: 0.3rem 0.5rem;
    font-size: 0.85rem;
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius);
    background: var(--ska-surface-alt);
    color: var(--ska-text);
    width: 140px;
}

.gcm-input-inline:focus {
    outline: none;
    border-color: var(--ska-accent);
}

.gcm-btn-secondary {
    background: var(--ska-surface-alt);
    color: var(--ska-text);
    border-color: var(--ska-border-medium);
}

.gcm-btn-secondary:hover {
    background: var(--ska-border-medium);
}

/* ── Contrato de overlay ─────────────────────────────────────────────────────
   Un overlay a pantalla completa DEBE poder scrollear y NO puede centrar con
   `align-items:center`. Con un hijo más alto que la pantalla, el centrado reparte
   espacio libre NEGATIVO en DOS: recorta arriba y abajo a la vez, y el navegador no
   scrollea por encima del borde inicial → el título y los botones quedan
   INALCANZABLES (no solo feos). Fue el bug del modal de reservas de jul-2026: la
   clienta no podía guardar la cita porque el botón nacía fuera de la pantalla.
   El centrado se hace con `margin:auto` en la tarjeta: cuando no hay espacio libre
   colapsa a 0 (Flexbox §9.6) y apoya la tarjeta arriba en vez de recortarla.

   Son clases CSS propias y no utilidades Tailwind A PROPÓSITO: el build de Unfold
   pasa por PurgeCSS y `m-auto` no sobrevive (verificado contra el styles.css del build).
   Lo hace cumplir scripts/check_modal_scroll.py. */
.ska-modal-scroll {
    overflow-y: auto;
    overscroll-behavior: contain;
}

.ska-modal-card {
    margin: auto;
}

/* ── GCM Inline Confirm Modal ── */
.gcm-confirm-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.65);
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--ska-radius);
    z-index: 50;
    backdrop-filter: blur(2px);
}

.gcm-confirm-box {
    background: var(--ska-surface);
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius);
    padding: 1.5rem 2rem;
    text-align: center;
    max-width: 320px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

.gcm-confirm-icon {
    font-size: 2rem;
    margin-bottom: 0.5rem;
}

.gcm-confirm-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ska-text);
    margin-bottom: 0.4rem;
}

.gcm-confirm-text {
    font-size: 0.82rem;
    color: var(--ska-text-dim);
    margin-bottom: 1rem;
    line-height: 1.4;
}

.gcm-confirm-actions {
    display: flex;
    gap: 0.75rem;
    justify-content: center;
}

.gcm-confirm-actions .gcm-btn {
    min-width: 100px;
}

/* ── GCM Username Form ── */
.gcm-username-form {
    display: inline-flex;
    gap: 0.35rem;
    align-items: center;
}

.gcm-btn-save {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--ska-radius);
    border: 1px solid var(--ska-accent);
    background: var(--ska-accent);
    color: var(--ska-text-on-primary);
    font-size: 0.9rem;
    font-weight: bold;
    cursor: pointer;
    transition: opacity 0.15s;
    padding: 0;
}

.gcm-btn-save:hover {
    opacity: 0.85;
}

/* Card needs position:relative for the confirm overlay */
.gcm-card {
    position: relative;
}

/* ── GCM Empty state ── */
.gcm-empty {
    text-align: center;
    padding: 40px 24px;
    color: var(--ska-text-subtle);
}

.gcm-empty-icon {
    font-size: 48px;
    margin-bottom: 12px;
}

.gcm-empty-text {
    font-size: 14px;
    margin-bottom: 16px;
}

/* ── Changelist banner ── */
.gcm-changelist-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    margin-bottom: 16px;
    border-radius: var(--ska-radius-md);
    background: var(--ska-primary-glow);
    border: 1px solid var(--ska-primary-glow);
}

.gcm-manage-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    background: var(--ska-primary);
    color: var(--ska-text-on-primary);
    transition: opacity 0.15s ease;
}

.gcm-manage-btn:hover {
    opacity: 0.9;
    color: var(--ska-surface);
}

.gcm-manage-hint {
    font-size: 13px;
    color: var(--ska-text-muted);
}

/* ═══════════════════════════════════════════════════
   MCP TESTER
   ═══════════════════════════════════════════════════ */

.mcp-tester-body {
    font-family: var(--ska-font-sans);
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    line-height: 1.6;
    background: var(--ska-bg);
    color: var(--ska-text);
}

.mcp-tester-body h1 {
    color: var(--ska-text);
    text-align: center;
    margin-bottom: 30px;
}

.mcp-container {
    display: flex;
    gap: 20px;
}

.mcp-panel {
    flex: 1;
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius-sm);
    padding: 15px;
    background: var(--ska-surface);
}

.mcp-tester-body textarea {
    width: 100%;
    height: 300px;
    font-family: var(--ska-font-mono);
    padding: 10px;
    box-sizing: border-box;
    border: 1px solid var(--ska-border-medium);
    border-radius: 4px;
    margin-bottom: 15px;
    background: var(--ska-surface);
    color: var(--ska-text);
}

.mcp-tester-body button {
    background-color: var(--ska-primary);
    color: var(--ska-text-on-primary);
    padding: 10px 15px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
}

.mcp-tester-body button:hover {
    background-color: var(--ska-primary-dark);
}

.mcp-examples {
    margin-top: 20px;
}

.mcp-example-btn {
    background-color: var(--ska-info);
    color: var(--ska-surface);
    margin-right: 10px;
    margin-bottom: 10px;
    padding: 10px 15px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
}

.mcp-example-btn:hover {
    background-color: var(--ska-info-light);
}

.mcp-cursor-example {
    background-color: var(--ska-purple);
}

.mcp-cursor-example:hover {
    background-color: var(--ska-purple-light);
}

.mcp-tester-body pre {
    background-color: var(--ska-surface-alt);
    padding: 10px;
    border-radius: 4px;
    overflow-x: auto;
    color: var(--ska-text);
}

.mcp-header-info {
    text-align: center;
    margin-bottom: 20px;
    color: var(--ska-text-muted);
}

/* ═══════════════════════════════════════════════════
   UTILITY CLASSES
   ═══════════════════════════════════════════════════ */

/* Color dot — replaces inline style="background:{{ color }}" */
.ska-color-dot {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    vertical-align: middle;
    margin-right: 6px;
    border: 2px solid var(--ska-border-medium);
    background: attr(data-color);
}

.ska-color-dot--lg {
    width: 16px;
    height: 16px;
    margin-right: 8px;
}

.ska-text-right {
    text-align: right;
}

.ska-text-left {
    text-align: left;
}

.ska-text-center {
    text-align: center;
}

.ska-text-bold {
    font-weight: 500;
}

.ska-text-semibold {
    font-weight: 600;
}

.ska-overflow-auto {
    overflow-x: auto;
}

.ska-mb-sm {
    margin-bottom: 8px;
}

.ska-mb-md {
    margin-bottom: 16px;
}

.ska-mb-lg {
    margin-bottom: 24px;
}

.ska-mt-sm {
    margin-top: 8px;
}

.ska-mt-md {
    margin-top: 16px;
}

/* ═══════════════════════════════════════════════════
   KPI STAT CARDS (config-inspection, memory-dashboard)
   Accent-colored number values on neutral surface cards.
   All colors derive from ska-tokens — zero hardcode.
   ═══════════════════════════════════════════════════ */

/* -- Grid -- */
.ska-kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}

/* -- Card -- */
.ska-kpi-card {
    background: var(--ska-surface);
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius-md);
    padding: 16px;
    text-align: center;
    box-shadow: var(--ska-shadow-sm);
    transition: box-shadow 0.2s;
}

.ska-kpi-card:hover {
    box-shadow: var(--ska-shadow-md);
}

.ska-kpi-card .label {
    margin: 0 0 4px;
    font-size: 11px;
    color: var(--ska-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 500;
}

.ska-kpi-card .val {
    font-size: 28px;
    font-weight: 700;
}

.ska-kpi-card .sub {
    font-size: 11px;
    color: var(--ska-text-subtle);
    margin-top: 4px;
}

/* -- Accent colors for .val numbers -- */
.ska-accent-blue {
    color: var(--ska-info);
}

.ska-accent-green {
    color: var(--ska-success);
}

.ska-accent-amber {
    color: var(--ska-warning);
}

.ska-accent-red {
    color: var(--ska-danger);
}

.ska-accent-purple {
    color: var(--ska-purple);
}

.ska-accent-cyan {
    color: var(--ska-primary);
}

/* -- Sections (h3 with bottom border) -- */
.ska-kpi-section {
    margin-bottom: 24px;
}

.ska-kpi-section h3 {
    font-size: 15px;
    margin: 0 0 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--ska-border-medium);
    color: var(--ska-text);
}

/* -- Metadata grid (dt/dd) -- */
.ska-kpi-meta {
    display: grid;
    grid-template-columns: 180px 1fr;
    gap: 4px 12px;
    font-size: 13px;
    margin-bottom: 16px;
}

.ska-kpi-meta dt {
    font-weight: 600;
    color: var(--ska-text-muted);
}

.ska-kpi-meta dd {
    margin: 0;
    font-family: var(--ska-font-mono);
    font-size: 12px;
    word-break: break-all;
    color: var(--ska-text);
}

/* -- Badge (monospace tag) -- */
.ska-kpi-badge {
    display: inline-block;
    background: var(--ska-surface-alt);
    border: 1px solid var(--ska-border-medium);
    border-radius: 4px;
    padding: 2px 8px;
    font-family: var(--ska-font-mono);
    font-size: 11px;
    margin: 2px;
    color: var(--ska-text);
}

/* -- Quiet/muted text -- */
.ska-text-quiet {
    color: var(--ska-text-subtle);
}

/* -- Data table variant (compact, for breakdown/dist tables) -- */
.ska-kpi-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 16px;
}

.ska-kpi-table th,
.ska-kpi-table td {
    padding: 8px 12px;
    text-align: left;
    border-bottom: 1px solid var(--ska-border);
    font-size: 13px;
}

.ska-kpi-table th {
    font-weight: 600;
    background: var(--ska-surface-alt);
    color: var(--ska-text-muted);
}

.ska-kpi-table .num {
    text-align: right;
    font-family: var(--ska-font-mono);
}

/* -- Collapsible sections -- */
.ska-kpi-toggle {
    cursor: pointer;
    user-select: none;
}

.ska-kpi-toggle::before {
    content: "▶ ";
    font-size: 10px;
}

.ska-kpi-toggle.open::before {
    content: "▼ ";
}

.ska-hidden {
    display: none;
}

/* -- Code/instruction block -- */
.ska-kpi-code {
    background: var(--ska-surface-alt);
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius-sm);
    padding: 16px;
    font-family: var(--ska-font-mono);
    font-size: 12px;
    line-height: 1.5;
    white-space: pre-wrap;
    word-wrap: break-word;
    max-height: 500px;
    overflow-y: auto;
    color: var(--ska-text);
}

/* -- Score pills (memory dashboard relevance) -- */
.ska-score-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
}

.ska-score-pill.green {
    background: var(--ska-badge-green-bg);
    color: var(--ska-badge-green-text);
}

.ska-score-pill.amber {
    background: var(--ska-badge-yellow-bg);
    color: var(--ska-badge-yellow-text);
}

.ska-score-pill.red {
    background: var(--ska-badge-red-bg);
    color: var(--ska-badge-red-text);
}

/* -- Preference items -- */
.ska-pref-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 12px;
    background: var(--ska-surface-alt);
    border-radius: 8px;
    font-size: 13px;
    border: 1px solid var(--ska-border);
    color: var(--ska-text);
}

.ska-pref-badge {
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 8px;
    background: var(--ska-surface);
    border: 1px solid var(--ska-border-medium);
    color: var(--ska-text-muted);
    flex-shrink: 0;
}

/* -- Alert/error box -- */
.ska-alert-error {
    background: var(--ska-danger-bg);
    border: 1px solid var(--ska-danger);
    padding: 16px;
    border-radius: 8px;
    margin-bottom: 16px;
    color: var(--ska-danger);
}

/* ═══════════════════════════════════════════════════
   KNOWLEDGE GRAPH (memory-dashboard — Cytoscape.js)
   ═══════════════════════════════════════════════════ */

/* Wrapper: provides positioning context for controls + legend */
.md-graph-wrap {
    position: relative;
}

/* Canvas container where Cytoscape renders */
.md-graph-canvas {
    width: 100%;
    height: 900px;
    border-radius: var(--ska-radius-md);
    border: 1px solid var(--ska-border);
    background: var(--ska-surface);
    position: relative;
}

/* Zoom / fit controls (top-right) */
.md-graph-controls {
    position: absolute;
    top: 24px;
    right: 24px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    z-index: 10;
}

.md-graph-controls button {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    border: 1px solid var(--ska-border-medium);
    background: var(--ska-surface-alt);
    color: var(--ska-text);
    font-size: 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
}

.md-graph-controls button:hover {
    background: var(--ska-border-medium);
}

.md-graph-controls button.fit {
    font-size: 12px;
}

/* Tooltip (follows mouse on node hover) */
.md-graph-tooltip {
    position: absolute;
    display: none;
    padding: 8px 14px;
    border-radius: 8px;
    background: var(--ska-surface-alt);
    border: 1px solid var(--ska-border-medium);
    color: var(--ska-text);
    font-size: 11px;
    line-height: 1.5;
    max-width: 260px;
    z-index: 999;
    pointer-events: none;
    box-shadow: var(--ska-shadow-md);
}

/* Floating legend card (bottom-left inside graph) */
.md-graph-legend {
    position: absolute;
    bottom: 16px;
    left: 16px;
    z-index: 10;
    background: var(--ska-surface-alt);
    border: 1px solid var(--ska-border-medium);
    border-radius: 10px;
    padding: 10px 14px;
    box-shadow: var(--ska-shadow-sm);
    font-size: 10px;
    color: var(--ska-text-subtle);
    line-height: 1.8;
    max-width: 200px;
}

.md-graph-legend-title {
    font-weight: 700;
    font-size: 11px;
    margin-bottom: 4px;
    color: var(--ska-text);
}

/* Node-type swatch (colored dot) */
.md-graph-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    vertical-align: middle;
    margin-right: 4px;
}

.md-graph-swatch.rect {
    border-radius: 4px;
}

.md-graph-swatch.user {
    background: var(--ska-graph-user);
}

.md-graph-swatch.person {
    background: var(--ska-graph-person);
}

.md-graph-swatch.organization {
    background: var(--ska-graph-org);
}

.md-graph-swatch.place {
    background: var(--ska-graph-place);
}

/* Edge-type swatch (colored line) */
.md-graph-edge-swatch {
    display: inline-block;
    width: 16px;
    vertical-align: middle;
    margin-right: 4px;
}

.md-graph-edge-swatch.relation {
    border-top: 2px solid var(--ska-graph-edge-relation);
}

.md-graph-edge-swatch.agent {
    border-top: 2px dashed var(--ska-graph-edge-agent);
}

.md-graph-edge-swatch.crossref {
    border-top: 1px dotted var(--ska-graph-edge-crossref);
}

.md-graph-edge-swatch.entity-rel {
    border-top: 2px dashed var(--ska-graph-edge-entity);
}

/* Divider inside legend */
.md-graph-legend-divider {
    margin-top: 4px;
    border-top: 1px solid var(--ska-border);
    padding-top: 4px;
}

/* No-data empty state */
.md-graph-empty {
    padding: 40px;
    text-align: center;
    color: var(--ska-text-subtle);
    font-size: 14px;
}

/* ═══════════════════════════════════════════════════
   CONFIG INSPECTION (config-inspection view)
   Copy buttons, collapsible sections, context groups.
   All colors derive from ska-tokens — zero hardcode.
   ═══════════════════════════════════════════════════ */

/* -- Copy button -- */
.ci-copy-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border: 1px solid var(--ska-border-medium);
    border-radius: 6px;
    background: transparent;
    color: var(--ska-text-muted);
    font-size: 11px;
    cursor: pointer;
    transition: all 0.15s ease;
    margin-left: 8px;
    vertical-align: middle;
}

.ci-copy-btn:hover {
    background: var(--ska-surface-alt);
    color: var(--ska-text);
    border-color: var(--ska-border-medium);
}

.ci-copy-btn.copied {
    color: var(--ska-success);
    border-color: var(--ska-success);
}

/* -- Collapsible toggle (replaces ska-kpi-toggle for smooth animation) -- */
.ci-toggle {
    cursor: pointer;
    user-select: none;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 12px 0 4px;
    padding: 8px 12px;
    border-radius: var(--ska-radius-sm);
    transition: background 0.15s ease;
    font-size: 14px;
    font-weight: 600;
    color: var(--ska-text);
}

.ci-toggle:hover {
    background: var(--ska-surface-alt);
}

.ci-toggle::before {
    content: '▶';
    font-size: 10px;
    transition: transform 0.2s ease;
    color: var(--ska-text-muted);
    flex-shrink: 0;
}

.ci-toggle.open::before {
    transform: rotate(90deg);
}

/* -- Collapsible content (smooth expand/collapse) -- */
.ci-collapsible {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease;
}

.ci-collapsible.open {
    max-height: 20000px;
}

/* -- Dynamic context groups (user info, security, time, etc.) -- */
.ci-ctx-group {
    margin: 6px 0;
    padding: 8px 12px;
    border-left: 3px solid var(--ska-border-medium);
    border-radius: 0 var(--ska-radius-sm) var(--ska-radius-sm) 0;
    background: var(--ska-surface-alt);
}

.ci-ctx-group-label {
    font-size: 12px;
    font-weight: 600;
    margin-bottom: 4px;
    color: var(--ska-text);
}

.ci-ctx-line {
    font-family: var(--ska-font-mono);
    font-size: 12px;
    line-height: 1.5;
    color: var(--ska-text-muted);
    word-break: break-word;
}

/* -- Disclaimer (admin preview warning) -- */
.ci-disclaimer {
    margin: 20px 0 0;
    padding: 10px 16px;
    border-radius: var(--ska-radius-sm);
    background: var(--ska-warning-bg);
    border: 1px solid var(--ska-warning);
    font-size: 12px;
    color: var(--ska-text-muted);
}

/* -- Role display -- */
.ci-role-line {
    margin: 12px 0 0;
    font-size: 13px;
}

/* -- Context lines heading -- */
.ci-ctx-heading {
    font-size: 13px;
    margin: 0 0 8px;
    color: var(--ska-text-muted);
}

/* ═══════════════════════════════════════════════════
   DRIVE SYNC FILTER DASHBOARD
   ═══════════════════════════════════════════════════ */

/* ── Stats grid ── */
.dsf-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 12px;
    margin-bottom: 16px;
}

/* ── Stat value color accents ── */
.dsf-stat-pending {
    color: var(--ska-warning);
}

.dsf-stat-processing {
    color: var(--ska-info);
}

.dsf-stat-completed {
    color: var(--ska-success);
}

.dsf-stat-failed {
    color: var(--ska-danger);
}

/* ── Section header with inline action ── */
.dsf-section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 2px solid var(--ska-primary);
    margin-bottom: 24px;
    padding-bottom: 12px;
}

.dsf-section-header .gcm-section-title {
    margin: 0;
    padding: 0;
    border-bottom: none;
    flex: 1;
}

/* ── Form card ── */
.dsf-form-card {
    border-left: 3px solid var(--ska-primary);
    margin-bottom: 16px;
}

.dsf-form-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--ska-text);
    margin-bottom: 16px;
}

.dsf-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 12px;
    margin-bottom: 12px;
}

.dsf-form-group {
    margin-bottom: 8px;
}

.dsf-label {
    display: block;
    font-size: 12px;
    font-weight: 500;
    color: var(--ska-text-muted);
    margin-bottom: 4px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.dsf-input {
    width: 100%;
    padding: 8px 12px;
    font-size: 13px;
    border: 1px solid var(--ska-border-medium);
    border-radius: var(--ska-radius);
    background: var(--ska-surface-alt);
    color: var(--ska-text);
    transition: border-color 0.15s ease;
    box-sizing: border-box;
}

.dsf-input:focus {
    outline: none;
    border-color: var(--ska-accent);
    box-shadow: 0 0 0 2px var(--ska-primary-glow);
}

.dsf-form-checkbox {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-top: 20px;
}

.dsf-form-checkbox .dsf-label {
    display: inline;
    text-transform: none;
    margin-bottom: 0;
    cursor: pointer;
}

.dsf-form-actions {
    display: flex;
    gap: 8px;
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--ska-border);
}

/* ── Filter cards ── */
.dsf-filter-card {
    transition: opacity 0.15s ease;
}

.dsf-filter-inactive {
    opacity: 0.6;
}

.dsf-filter-inactive:hover {
    opacity: 0.85;
}

.dsf-filter-details {
    margin-bottom: 12px;
}

.dsf-filter-details code {
    font-family: var(--ska-font-mono);
    font-size: 12px;
    background: var(--ska-surface-alt);
    padding: 2px 6px;
    border-radius: 3px;
    color: var(--ska-text-secondary);
}

/* ── Stat chips inside filter cards ── */
.dsf-filter-stats {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 8px;
    padding-top: 12px;
    border-top: 1px solid var(--ska-border);
}

.dsf-stat-chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 3px 10px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 600;
}

.dsf-chip-pending {
    background: var(--ska-warning-bg);
    color: var(--ska-warning);
}

.dsf-chip-processing {
    background: var(--ska-info-bg);
    color: var(--ska-info);
}

.dsf-chip-completed {
    background: var(--ska-success-bg);
    color: var(--ska-success);
}

.dsf-chip-failed {
    background: var(--ska-danger-bg);
    color: var(--ska-danger);
}

.dsf-chip-total {
    background: var(--ska-surface-alt);
    color: var(--ska-text-muted);
}

/* ── Visibility toggle ── */
.dsf-hidden {
    display: none !important;
}

/* Utility: accent-colored link */
.ska-link-accent {
    color: var(--ska-accent);
    text-decoration: none;
}

.ska-link-accent:hover {
    text-decoration: underline;
    opacity: 0.85;
}

/* ═══════════════════════════════════════════════════
   AGENT CONTEXT SELECTOR
   Estilos de la barra de selector que usa `brand_selector.html` y
   cualquier dashboard que necesite mostrar "estás operando como X".
   ═══════════════════════════════════════════════════ */

.ska-selector-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    padding: 16px 20px;
    margin-bottom: 24px;
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md);
}

.ska-selector-bar--single {
    justify-content: flex-start;
}

.ska-selector-info {
    display: flex;
    align-items: center;
    gap: 12px;
}

.ska-selector-avatar {
    width: 40px;
    height: 40px;
    border-radius: 8px;
    object-fit: cover;
    border: 1px solid var(--ska-border);
}

.ska-selector-avatar-placeholder {
    width: 40px;
    height: 40px;
    border-radius: 8px;
    background: color-mix(in srgb, var(--ska-primary) 10%, var(--ska-bg));
    color: var(--ska-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    border: 1px solid var(--ska-border);
}

.ska-selector-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ska-text-muted);
    font-weight: 600;
    margin-bottom: 2px;
}

.ska-selector-name {
    font-weight: 600;
    color: var(--ska-text);
    display: flex;
    align-items: center;
    gap: 8px;
}

.ska-selector-type-badge {
    font-size: 10px;
}

.ska-selector-form {
    flex-shrink: 0;
    min-width: 200px;
}

.ska-selector-form form {
    margin: 0;
}

.ska-selector-select {
    width: 100%;
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid var(--ska-border);
    background: var(--ska-surface);
    color: var(--ska-text);
    font-size: 14px;
    font-weight: 500;
    outline: none;
    appearance: auto;
}

.ska-selector-select:focus {
    border-color: var(--ska-primary);
    box-shadow: 0 0 0 2px var(--ska-primary-glow);
}

/* ── UI Element: Code Pills (Code Blocks / JSON representation) ── */
.ska-code-pill {
    display: inline-block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
    font-size: 0.75rem;
    /* text-xs */
    padding: 0.25rem 0.5rem;
    /* px-2 py-1 */
    background-color: var(--ska-surface-alt);
    border: 1px solid var(--ska-border);
    border-radius: 0.375rem;
    /* rounded-md */
    color: var(--ska-text-secondary);
}

/* ═══════════════════════════════════════════════════════════════════════
 * Changelist con CARDS — neutralizar la "caja" del toolbar de Unfold.
 *
 * El toolbar de búsqueda de Unfold (el div que contiene #toolbar) está
 * estilizado como el ENCABEZADO de una caja que la TABLA de resultados por
 * defecto completa: en desktop trae `lg:border` + `lg:rounded-t-default`
 * (borde 4 lados, solo esquinas de arriba redondeadas) + `lg:pb-11` (44px de
 * padding inferior) + `lg:-mb-8` (margin inferior -32px, que jala hacia arriba
 * lo que sigue para encajar la tabla).
 *
 * Pero TODOS nuestros changelists renderizan CARDS (no la tabla), así que la
 * caja nunca se cierra → queda: (1) padding muerto bajo "Type to search",
 * (2) una línea suelta (el borde inferior del toolbar), (3) los cards jalados
 * a traslaparse con esa línea (`-mb-8`).
 *
 * Fix: en card-pages el toolbar vuelve a ser una fila simple (buscador +
 * Filtros) y los cards flotan debajo (depth-over-borders del DS — los cards ya
 * traen su sombra).
 *
 * SCOPE SEGURO: SOLO changelists SIN la tabla default (`table#result_list`).
 * Las páginas de tabla (clinicalentitymention, consultorioprofile,
 * funneltransition, *suggestion, llm/rekognition usage, etc.) SÍ tienen
 * `table#result_list` → quedan EXCLUIDAS y conservan su caja intacta. Solo
 * aplica en `lg` (donde Unfold pinta la caja). No toca buscador ni filtros
 * (son hijos). Ver memoria [[spa-nav-htmx-boost]] / [[cards-changelist-keep-bulk-actions]].
 *
 * ⚠️ ENTREGA (causa de "siempre ocurre"): este archivo es SHARED y se carga sin
 * hash de manifest. Si su `?v=` no se bumpea, Cloudflare/el browser sirven una
 * copia VIEJA y este fix no llega → la caja vuelve a verse con los cards encima.
 * Fuente de verdad del `?v=`: `core/settings/unfold.py` STYLES (ska-admin-components.css?v=N).
 * Al editar este archivo, BUMPEAR ese `?v=N` (y los `<link>` directos que lo
 * dupliquen). Ver memoria [[changelist-toolbar-box-overlap]] + ADMIN_PATTERN §2.5.A.
 *
 * El contenedor de cards puede llamarse `*-cards` (molde per-prefijo) o
 * `ska-card-grid` (vocabulario compartido de inventory.css); ambos cubiertos.
 * ═══════════════════════════════════════════════════════════════════════ */
/* BORDE + redondeo + sombra de la caja: FUERA solo en CARD-changelists.
 *
 * ⚠️ Guard `:not(:has(#result_list))`: la TABLA default de Unfold renderiza
 * `<table id="result_list">`; un card-changelist (override de result_list) NO.
 * Así las TABLAS reales (petownership, catálogos) CONSERVAN su caja (borde) y solo
 * las cards la pierden + ganan espacio arriba. Ver ADR-019 (revierte ADR-006).
 *   Trade-off: `:has()` lo ignora Firefox <121 → ahí la regla entera se cae →
 * TODA changelist conserva la caja (cards muestran el borde; degradación cosmética
 * aceptable para un admin interno 2026; nada se rompe). Se eligió sobre marcar ~31
 * templates a mano (footgun: cada card-changelist nueva tendría que recordar la
 * marca o la caja vuelve). El combo `[class*="lg:pb-11"][class*="lg:-mb-8"]`
 * identifica el wrapper del toolbar. */
body.change-list:not(:has(#result_list)) [class*="lg:pb-11"][class*="lg:-mb-8"] {
    border: 0 none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}

@media (min-width: 1024px) {

    /* pb-11 (padding muerto) + -mb-8 (margen negativo) solo existen en lg.
     * margin-top: separa el toolbar del header (simétrico al bottom, alineado con
     * el buscador del sidebar) — antes quedaba pegado arriba en card-changelists. */
    body.change-list:not(:has(#result_list)) [class*="lg:pb-11"][class*="lg:-mb-8"] {
        padding: 0 !important;
        margin-top: 1rem !important;
        margin-bottom: 1rem !important;
    }

    /* Contenedor de cards: ya no completa una caja → flota sin borde. */
    body.change-list:not(:has(#result_list)) #changelist-form>[class*="cards"],
    body.change-list:not(:has(#result_list)) #changelist-form>[class*="card-grid"] {
        border: 0 !important;
        border-radius: 0 !important;
        margin-top: 0 !important;
        padding-top: 4px !important;
    }

    /* Estado vacío: que no quede empujado dentro de la (ex)caja. */
    body.change-list:not(:has(#result_list)) #changelist-form>[class*="empty"] {
        margin-top: 0 !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════
 * Sidebar — ítem ACTIVO (fuente ÚNICA de verdad) — "estás aquí".
 *
 * El estilo del ítem activo del menú vive SOLO acá. El HTML (app_list.html) y el
 * JS de navegación AJAX (spa-nav.js) únicamente togglean la clase marcadora
 * `.active` — NINGUNO lleva clases de color. Antes el estilo activo estaba
 * duplicado como utilities Tailwind en los dos lados; al navegar con hx-boost el
 * sidebar NO se re-renderiza y spa-nav.js repintaba el activo con una copia
 * desactualizada de esas clases → el seleccionado "desaparecía" (texto del color
 * de marca sobre fondo oscuro). Centralizar mata esa desincronización.
 *
 * Tratamiento (3 señales, inconfundible) — antes el activo usaba el MISMO
 * `bg-base-100`/`bg-base-800` que el hover → activo y hover se veían idénticos
 * (no se sabía en qué página estabas):
 *   1) BARRA de acento a la izquierda (box-shadow inset, no desplaza el flex y
 *      respeta `rounded-default`). Color de MARCA (`--color-primary-600`, igual
 *      que #spa-progress): decorativo, siempre visible en cualquier marca/tema.
 *      Se hereda al modo dark (la regla `.dark` no lo pisa).
 *   2) FONDO un paso más fuerte que el hover (base-200 vs hover base-100;
 *      dark base-700 vs hover base-800) → activo ≠ hover.
 *   3) Texto `font-important` + 600. Marca-agnóstico: el TEXTO usa font tokens
 *      (no `primary`), legible con cualquier marca (incl. Pet Club carbón).
 * La specificity con #id gana al hover utility → el activo conserva fondo+barra
 * aun en hover. Al editar este archivo BUMPEAR el `?v=` en core/settings/unfold.py
 * STYLES. Ver [[admin-sidebar-brand-agnostic-and-unfold-purgecss]].
 * ═══════════════════════════════════════════════════════════════════════ */
#nav-sidebar-apps a.active {
    /* Más sutil + armonizado al tono de la sección: tinte de MARCA translúcido (mismo
       hue que el fondo del escenario) en vez del gris opaco base-200. La barra de
       acento inset + el peso 600 + el color font-important siguen siendo la señal
       fuerte de "estás aquí"; el fondo solo es un escalón suave sobre el del grupo. */
    background-color: color-mix(in srgb, var(--color-primary-600) 13%, transparent);
    font-weight: 600;
    color: var(--color-font-important-light);
    box-shadow: inset 3px 0 0 var(--color-primary-600);
}

.dark #nav-sidebar-apps a.active {
    background-color: color-mix(in srgb, var(--color-primary-600) 18%, transparent);
    color: var(--color-font-important-dark);
}

/* ═══════════════════════════════════════════════════════════════════════
 * Sidebar — TÍTULO de sección (CONTABILIDAD, etc.) — diferenciarlo del ítem.
 *
 * Antes el título era un LABEL muteado (`text-font-subtle-*`, inline en
 * app_list.html) → se leía casi igual que sus ítems y se perdía ("¿esto es
 * encabezado o ítem?"). Bajar el tono lo empeoró. La jerarquía la dan ahora
 * tipografía (uppercase + text-xs) + TRACKING + un DIVISOR por sección, NO un
 * color apagado: el texto vuelve a contraste legible (`font-default`, el mismo
 * del cuerpo). #id gana a la utility `.text-font-subtle-*` inline sin !important.
 * Dentro de #nav-sidebar-apps los únicos <h2> son los títulos de sección (el
 * bloque "All applications" queda FUERA de ese id). Iconos teal intactos (su
 * `.text-teal-500` propio gana por su clase). BUMPEAR `?v=` al editar. */
#nav-sidebar-apps h2 {
    color: var(--color-font-default-light);
    font-size: 0.6875rem;
    /* 11px — menor que el ítem (14px): se lee como LABEL, no como fila */
    letter-spacing: 0.06em;
    border-top: 1px solid var(--color-base-200);
    margin-top: 0.85rem;
    /* más aire antes de la sección (whitespace = corte, consenso UX) */
    padding-top: 0.95rem;
}

.dark #nav-sidebar-apps h2 {
    color: var(--color-font-default-dark);
    border-top-color: var(--color-base-800);
}

/* Ítems ANIDADOS bajo su título (patrón árbol VS Code/Notion): indent + guía
 * vertical → los ítems CUELGAN del título como su contenido, no como hermanos.
 * Esta era la señal que faltaba: sin anidación, "Catálogo Clínico" se leía igual
 * que "Especie/Razas/Condiciones" (mezclados). Selector DESCENDIENTE por SimpleBar;
 * el <ol> cerrado va display:none → la guía solo aparece en secciones ABIERTAS
 * (refuerza el cue de abierto). NO tocar el <a> (su `-mx-3 px-3` estira el fondo de
 * hover/activo a todo el ancho — moverlo rompería esos estados). */
#nav-sidebar-apps ol {
    padding-left: 2.35rem;
    margin-left: 1rem;
    border-left: 1px solid var(--color-base-200);
}

.dark #nav-sidebar-apps ol {
    border-left-color: var(--color-base-800);
}

/* Sin divisor donde sobraría: el PRIMER grupo (pegado al buscador) y los grupos
 * que YA traen un divisor arriba — la banda `.ska-admin-band-label`
 * ("Administración") o un `<hr>` separador — para no dibujar línea doble. */
#nav-sidebar-apps>div:first-child h2,
#nav-sidebar-apps .ska-admin-band-label~h2,
#nav-sidebar-apps hr~h2 {
    border-top: 0;
    margin-top: 0;
    padding-top: 0.375rem;
}

/* ═══════════════════════════════════════════════════════════════════════
 * Sidebar — INTERIOR de una sección desplegada (agrupa sus ítems).
 *
 * #nav-sidebar-apps lleva `data-simplebar`: SimpleBar REESTRUCTURA el DOM en
 * runtime, envolviendo el contenido en .simplebar-wrapper/.../.simplebar-content.
 * Por eso el grupo `div[x-data]` NO es hijo directo de #nav-sidebar-apps en el
 * DOM vivo (sí lo es en el HTML del servidor) → combinador DESCENDIENTE, no `>`.
 * Verificado en el DOM vivo: `#nav-sidebar-apps div[x-data] ol` = 11 grupos;
 * con `>` desde #nav-sidebar-apps = 0 (ese era el bug). El <ol> sí es hijo
 * directo del div[x-data].
 *
 * Tratamiento (referencias: Tailwind UI / Linear / Notion / Vercel / Stripe /
 * Unfold default + DESIGN_SYSTEM propio). Consenso: la señal fuerte es el ÍTEM
 * ACTIVO (fondo base-200/700 + barra inset primary — intacto). "Abierto" se
 * comunica por el CHEVRON rotado; el tinte es solo refuerzo, ultra sutil, plano,
 * sin rail ni radio. ANTIPATRÓN evitado: rellenar TODOS los títulos o el bloque.
 *
 * LLAVE = la sección que CONTIENE el ítem ACTIVO (`:has(a.active)`), NO cualquier
 * sección abierta. El sidebar usa hx-boost y NO se re-renderiza al navegar → el
 * estado abierto/cerrado PERSISTE en el cliente (Alpine); keyear en "abierto"
 * dejaba iluminada la sección ANTERIOR al cambiar de vista. `a.active` lo actualiza
 * spa-nav.js en cada navegación → el realce sigue a la página y no queda obsoleto.
 *   (a) HEADER de la sección activa → primary ~5% (light)/9% (dark). Solo ese <h2>.
 *   (b) INTERIOR (<ol>) de la sección activa → primary ~3% (light)/6% (dark), un
 *       escalón por debajo y muy por debajo del ítem activo. Marca-agnóstico
 *       (primary carbón de Pet Club ⇒ casi nulo; jerarquía por chevron + indent).
 * BUMPEAR `?v=` en unfold.py al editar. */
/* La sección ACTIVA = UN contenedor: un solo fondo en el GRUPO (no dos fondos
 * separados en título y contenido). Antes el fondo del contenido iba INDENTADO por
 * el árbol → no cuadraba con el del título ("descuadrado"). Con una sola capa detrás
 * de todo el grupo, título y contenido quedan ALINEADOS; los ítems siguen indentados
 * DENTRO. El título pierde divisor + margen (el contenedor ya lo separa). */
#nav-sidebar-apps div[x-data]:has(a.active) {
    background-color: color-mix(in srgb, var(--color-primary-600) 5%, transparent);
    padding-top: 0.1rem;
    padding-bottom: 0.4rem;
}

.dark #nav-sidebar-apps div[x-data]:has(a.active) {
    background-color: color-mix(in srgb, var(--color-primary-600) 9%, transparent);
}

#nav-sidebar-apps div[x-data]:has(a.active)>h2 {
    background-color: transparent;
    border-top-color: transparent;
    margin-top: 0;
    padding-top: 0.55rem;
}

#nav-sidebar-apps div[x-data]:has(a.active)>ol {
    background-color: transparent;
    padding-top: 0.2rem;
    padding-bottom: 0.2rem;
}

/* ── Barra de progreso de navegación (spa-nav.js / hx-boost) ─────────────────
   Feedback de "cargando la página siguiente": una barra fina fija arriba que
   arranca en htmx:beforeRequest y termina en htmx:afterRequest. Sin esto, un
   click boosted no daba ninguna señal ("no pasa nada"). Color = primary de la
   marca activa (Unfold expone --color-primary-600 como rgb(...) por tenant). */
#spa-progress {
    position: fixed;
    top: 0;
    left: 0;
    height: 3px;
    width: 0;
    background: var(--color-primary-600, #2563eb);
    box-shadow: 0 0 8px var(--color-primary-600, #2563eb);
    z-index: 99999;
    opacity: 0;
    pointer-events: none;
    border-top-right-radius: 3px;
    border-bottom-right-radius: 3px;
}

#spa-progress.spa-progress--active {
    opacity: 1;
    width: 88%;
    /* Avance perceptual: rápido al inicio, asintótico (nunca llega al 100% solo). */
    transition: width 9s cubic-bezier(0.1, 0.7, 0.2, 1), opacity 0.15s ease;
}

#spa-progress.spa-progress--done {
    opacity: 0;
    width: 100%;
    transition: width 0.2s ease, opacity 0.4s ease 0.2s;
}

@media (prefers-reduced-motion: reduce) {
    #spa-progress.spa-progress--active {
        transition: opacity 0.15s ease;
        width: 88%;
    }
}

/* ═══════════════════════════════════════════════════════════════════════
 * Input/panel primitives — vocabulario ÚNICO de inputs SUELTOS del admin
 * (filtros de listas/reports, POS, forms de acción en detalles). Reemplaza el
 * CSS de inputs legacy del carril §1 (account_balance), ya erradicado (ADR-020).
 * Mismo look que los .jmf-field (forms) → un solo lenguaje visual. NO confundir
 * con .jmf-* (esos viven en ska_admin_form.css, scope .jmf-wrap, para el form).
 * Solo tokens var(--ska-*). Ver docs/admin/surfaces/page.md.
 * ═══════════════════════════════════════════════════════════════════════ */
.ska-panel {
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-lg, 12px);
    box-shadow: var(--ska-shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.06));
}

.ska-input,
.ska-select {
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    color: var(--ska-text);
    background: var(--ska-surface);
    border: 1px solid var(--ska-border);
    border-radius: var(--ska-radius-md, 8px);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.ska-input:focus,
.ska-select:focus {
    outline: none;
    border-color: var(--ska-primary);
    box-shadow: 0 0 0 3px var(--ska-primary-glow);
}

.ska-input::placeholder {
    color: var(--ska-text-subtle);
}

/* Select: chevron propio (appearance:none quita la flecha nativa → la dibujamos
   con dos gradientes, idéntico al de los .jmf-field, sin SVG ni hex). */
.ska-select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    cursor: pointer;
    padding-right: 2.1rem;
    background-image:
        linear-gradient(45deg, transparent 50%, var(--ska-text-muted) 50%),
        linear-gradient(135deg, var(--ska-text-muted) 50%, transparent 50%);
    background-position: calc(100% - 16px) calc(50% - 1px), calc(100% - 11px) calc(50% - 1px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}

.ska-check {
    width: 1.05rem;
    height: 1.05rem;
    accent-color: var(--ska-primary);
    cursor: pointer;
}

/* Disabled: hace VISIBLE que el control está bloqueado (p. ej. "venta a crédito"
   deshabilitada hasta asignar cliente) — sin esto el checkbox se ve activo y "no responde". */
.ska-check:disabled {
    cursor: not-allowed;
    opacity: 0.45;
}

.ska-label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ska-text);
    margin-bottom: 0.25rem;
}

/* ──────────────────────────────────────────────────────────────────────────
   Helpers servidos — reemplazan utilidades Tailwind que NO están en el safelist
   precompilado de Unfold (space-y-*, opacity-*, font-mono, divide-y, tracking-*,
   text-7xl/8xl, shadow-xl/2xl…). Esas se purgan en silencio (no hay build de
   Tailwind del proyecto) → usar estas clases servidas en su lugar.
   ────────────────────────────────────────────────────────────────────────── */
.ska-admin-stack {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.ska-admin-stack--sm {
    gap: 12px;
}

.ska-admin-stack--xs {
    gap: 8px;
}

.ska-admin-divider {
    border: 0;
    border-top: 1px solid var(--ska-border);
    margin: 12px 0;
}

.ska-admin-muted {
    color: var(--ska-text-muted);
}

.ska-admin-subtle {
    color: var(--ska-text-subtle);
}

/* Numerales tabulares/monoespaciados (tickets, montos, ids) */
.ska-admin-num {
    font-variant-numeric: tabular-nums;
    font-family: var(--ska-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}

/* Número/figura de display grande (KPIs) */
.ska-admin-display {
    font-size: 2.25rem;
    font-weight: 800;
    line-height: 1.1;
    color: var(--ska-text);
}

/* Empty-state (icono muted → texto), proporción según global-rules §3 */
.ska-admin-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 10px;
    padding: 40px 16px;
    color: var(--ska-text-muted);
}

.ska-admin-empty>i {
    font-size: 30px;
    opacity: 0.5;
}

.ska-admin-empty p {
    margin: 0;
    font-size: 14px;
}

/* Fila de metadatos (hero): chips separados, envuelve */
.ska-admin-meta-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 14px;
    font-size: 14px;
    color: var(--ska-text-subtle);
}

.ska-admin-meta-row>span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Botones servidos (ghost = secundario/volver/editar) */
.ska-admin-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border-radius: var(--ska-radius-md);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background 0.15s, border-color 0.15s;
}

.ska-admin-btn--ghost {
    background: var(--ska-surface);
    color: var(--ska-text);
    border-color: var(--ska-border);
}

.ska-admin-btn--ghost:hover {
    background: var(--ska-surface-alt);
    border-color: var(--ska-primary);
}

/* Imagen dentro del icono del hero del detalle */
.ska-admin-detail-icon img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}

/* Acciones a la derecha del hero del detalle */
.ska-admin-detail-header__actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   BARRIDO CSS MUERTO (scripts/check_dead_tailwind.py)
   Utilidades usadas por templates admin que el bundle PRECOMPILADO de Unfold
   purga (no hay build de Tailwind del proyecto → safelist fijo). Se DEFINEN acá
   para realizar la intención original sin tocar 54 templates (cero regresión).
   Las ska-* base (líneas 23-45) NO se repiten. Memoria: admin-sidebar...purgecss.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Tokens ska-* faltantes (bg/text/border + estados) ── */
.bg-ska-primary-glow {
    background-color: var(--ska-primary-glow) !important;
}

.bg-ska-danger {
    background-color: var(--ska-danger) !important;
}

.bg-ska-danger-bg {
    background-color: var(--ska-danger-bg) !important;
}

.bg-ska-success {
    background-color: var(--ska-success) !important;
}

.bg-ska-success-bg {
    background-color: var(--ska-success-bg) !important;
}

.bg-ska-warning {
    background-color: var(--ska-warning) !important;
}

.bg-ska-warning-bg {
    background-color: var(--ska-warning-bg) !important;
}

.bg-ska-text-muted {
    background-color: var(--ska-text-muted) !important;
}

.bg-ska-info-bg {
    background-color: var(--ska-info-bg) !important;
}

.bg-ska-primary-bg {
    background-color: var(--ska-primary-bg) !important;
}

.bg-ska-border {
    background-color: var(--ska-border) !important;
}

.bg-ska-primary\/10 {
    background-color: var(--ska-primary) !important;
}

.bg-ska-danger\/10 {
    background-color: var(--ska-danger) !important;
}

.bg-ska-success\/10 {
    background-color: var(--ska-success) !important;
}

.bg-ska-warning\/10 {
    background-color: var(--ska-warning) !important;
}

.bg-ska-accent\/10 {
    background-color: var(--ska-accent) !important;
}

.text-ska-accent {
    color: var(--ska-accent) !important;
}

.text-ska-accent-amber {
    color: var(--ska-accent-amber) !important;
}

.text-ska-purple {
    color: var(--ska-purple) !important;
}

.text-ska-border {
    color: var(--ska-border) !important;
}

.text-ska-danger\/90 {
    color: var(--ska-danger) !important;
}

.border-ska-border-light {
    border-color: var(--ska-border-light) !important;
}

.border-ska-accent {
    border-color: var(--ska-accent) !important;
}

.border-ska-danger {
    border-color: var(--ska-danger) !important;
}

.border-ska-success {
    border-color: var(--ska-success) !important;
}

.border-ska-success-border {
    border-color: var(--ska-success-border) !important;
}

.border-ska-warning {
    border-color: var(--ska-warning) !important;
}

.border-ska-danger\/30 {
    border-color: var(--ska-danger) !important;
}

.border-ska-success\/30 {
    border-color: var(--ska-success) !important;
}

.border-ska-warning\/30 {
    border-color: var(--ska-warning) !important;
}

.border-ska-border\/40 {
    border-color: var(--ska-border) !important;
}

.divide-ska-border> :not([hidden])~ :not([hidden]) {
    border-color: var(--ska-border) !important;
}

.hover\:bg-ska-danger-bg:hover {
    background-color: var(--ska-danger-bg) !important;
}

.hover\:bg-ska-success-bg:hover {
    background-color: var(--ska-success-bg) !important;
}

.hover\:bg-ska-danger\/10:hover {
    background-color: var(--ska-danger) !important;
}

.hover\:bg-ska-danger\/85:hover {
    background-color: var(--ska-danger) !important;
}

.hover\:bg-ska-warning\/85:hover {
    background-color: var(--ska-warning) !important;
}

.hover\:text-ska-text:hover {
    color: var(--ska-text) !important;
}

/* Hover de un link pintado con --ska-primary.
 * Antes usaba --ska-primary-dark, que en modo oscuro vale lighten(primary, 0.3)
 * mientras el base vale 0.5: el hover quedaba MENOS claro que el texto normal
 * sobre fondo oscuro, o sea el feedback al revés. --ska-link-hover se aleja de la
 * SUPERFICIE en los dos modos (ThemeEngine: darken 0.30 en claro, lighten 0.70 en
 * oscuro). Ver test_letra_legible_sobre_la_marca.py. */
.hover\:text-ska-link-hover:hover {
    color: var(--ska-link-hover) !important;
}

.hover\:text-ska-danger:hover {
    color: var(--ska-danger) !important;
}

.hover\:border-ska-border:hover {
    border-color: var(--ska-border) !important;
}

.hover\:border-ska-danger:hover {
    border-color: var(--ska-danger) !important;
}

.hover\:border-ska-success:hover {
    border-color: var(--ska-success) !important;
}

.hover\:border-ska-warning:hover {
    border-color: var(--ska-warning) !important;
}

.hover\:border-ska-surface-alt:hover {
    border-color: var(--ska-surface-alt) !important;
}

.focus\:border-ska-primary:focus {
    border-color: var(--ska-primary) !important;
}

.focus\:ring-ska-primary:focus {
    box-shadow: 0 0 0 2px var(--ska-primary) !important;
}

.focus\:ring-ska-border:focus {
    box-shadow: 0 0 0 2px var(--ska-border) !important;
}

.focus\:ring-offset-ska-surface:focus {
    --tw-ring-offset-color: var(--ska-surface) !important;
}

.group:hover .group-hover\:text-ska-primary {
    color: var(--ska-primary) !important;
}

.group:hover .group-hover\:border-ska-primary {
    border-color: var(--ska-primary) !important;
}

/* ── Compat Tailwind v3 (valores default; colores → tokens ska-*) ── */
.space-y-1> :not([hidden])~ :not([hidden]) {
    margin-top: 0.25rem;
}

.space-y-3> :not([hidden])~ :not([hidden]) {
    margin-top: 0.75rem;
}

.space-y-4> :not([hidden])~ :not([hidden]) {
    margin-top: 1rem;
}

.space-y-6> :not([hidden])~ :not([hidden]) {
    margin-top: 1.5rem;
}

.divide-y> :not([hidden])~ :not([hidden]) {
    border-top-width: 1px;
}

/* ── Pasos de media unidad (`.5`) ──────────────────────────────────────────────
   El CSS de Unfold viene precompilado y PURGADO: sólo trae las clases que usan
   SUS plantillas. Las de media unidad que sólo usan las plantillas de este repo
   no tienen regla y por lo tanto no hacen NADA — se ven como cero, en silencio.

   Medido contra `/app/static/unfold/css/styles.css` el 2026-08-13: de las 23 en
   uso, 12 sobreviven (Unfold las usa) y estas 11 no existían en ningún CSS. Eran
   125 declaraciones muertas repartidas por el admin de los cuatro productos; la
   que se veía era `gap-2.5`, que dejaba los badges de "Sync Services" pegados.

   Van acá, en un solo lugar, y no reescribiendo 40 plantillas: el problema es que
   la regla no existe, no que la clase esté mal elegida. Valores por defecto de
   Tailwind (0.5→0.125rem, 1.5→0.375rem, 2.5→0.625rem, 3.5→0.875rem). El punto va
   escapado porque en CSS `.` empieza un selector de clase. */
.gap-2\.5 { gap: 0.625rem; }

.mb-0\.5 { margin-bottom: 0.125rem; }

.mt-1\.5 { margin-top: 0.375rem; }

.p-2\.5 { padding: 0.625rem; }

.pb-1\.5 { padding-bottom: 0.375rem; }

.pt-1\.5 { padding-top: 0.375rem; }

.py-0\.5 { padding-top: 0.125rem; padding-bottom: 0.125rem; }

.py-3\.5 { padding-top: 0.875rem; padding-bottom: 0.875rem; }

.space-y-1\.5> :not([hidden])~ :not([hidden]) { margin-top: 0.375rem; }

.top-2\.5 { top: 0.625rem; }

.w-1\.5 { width: 0.375rem; }

.opacity-5 {
    opacity: 0.05;
}

.opacity-20 {
    opacity: 0.2;
}

.opacity-30 {
    opacity: 0.3;
}

.opacity-40 {
    opacity: 0.4;
}

.opacity-50 {
    opacity: 0.5;
}

.opacity-60 {
    opacity: 0.6;
}

.opacity-70 {
    opacity: 0.7;
}

.opacity-80 {
    opacity: 0.8;
}

.shadow-none {
    box-shadow: 0 0 #0000;
}

.shadow-md {
    box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}

.shadow-xl {
    box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
}

.shadow-2xl {
    box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
}

.tracking-wide {
    letter-spacing: 0.025em;
}

.tracking-wider {
    letter-spacing: 0.05em;
}

.tracking-widest {
    letter-spacing: 0.1em;
}

.text-7xl {
    font-size: 4.5rem;
    line-height: 1;
}

.text-8xl {
    font-size: 6rem;
    line-height: 1;
}

.text-\[8px\] {
    font-size: 8px;
}

.text-\[9px\] {
    font-size: 9px;
}

.text-\[10px\] {
    font-size: 10px;
}

.text-\[13px\] {
    font-size: 13px;
}

.font-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

.font-black {
    font-weight: 900;
}

.leading-tight {
    line-height: 1.25;
}

.w-11 {
    width: 2.75rem;
}

.w-12 {
    width: 3rem;
}

.w-14 {
    width: 3.5rem;
}

.w-28 {
    width: 7rem;
}

.w-64 {
    width: 16rem;
}

.w-2\/12 {
    width: 16.666667%;
}

.w-3\/12 {
    width: 25%;
}

.w-4\/12 {
    width: 33.333333%;
}

.w-5\/12 {
    width: 41.666667%;
}

.w-6\/12 {
    width: 50%;
}

.h-11 {
    height: 2.75rem;
}

.h-14 {
    height: 3.5rem;
}

.h-48 {
    height: 12rem;
}

.max-h-48 {
    max-height: 12rem;
}

.max-h-56 {
    max-height: 14rem;
}

.max-h-60 {
    max-height: 15rem;
}

.max-h-64 {
    max-height: 16rem;
}

.max-h-\[600px\] {
    max-height: 600px;
}

.max-w-xs {
    max-width: 20rem;
}

.max-w-md {
    max-width: 28rem;
}

.max-w-lg {
    max-width: 32rem;
}

.max-w-\[120px\] {
    max-width: 120px;
}

.max-w-\[200px\] {
    max-width: 200px;
}

.min-w-\[150px\] {
    min-width: 150px;
}

.min-w-\[200px\] {
    min-width: 200px;
}

.z-\[9999\] {
    z-index: 9999;
}

.flex-\[2\] {
    flex: 2 2 0%;
}

.flex-shrink-0 {
    flex-shrink: 0;
}

.col-span-full {
    grid-column: 1 / -1;
}

.items-end {
    align-items: flex-end;
}

.items-baseline {
    align-items: baseline;
}

.self-end {
    align-self: flex-end;
}

.gap-0 {
    gap: 0;
}

.gap-x-6 {
    column-gap: 1.5rem;
}

.gap-y-2 {
    row-gap: 0.5rem;
}

.gap-y-4 {
    row-gap: 1rem;
}

.rounded-b-lg {
    border-bottom-left-radius: 0.5rem;
    border-bottom-right-radius: 0.5rem;
}

.rounded-bl-full {
    border-bottom-left-radius: 9999px;
}

.rounded-r-full {
    border-top-right-radius: 9999px;
    border-bottom-right-radius: 9999px;
}

.outline-none {
    outline: 2px solid transparent;
    outline-offset: 2px;
}

.overflow-y-hidden {
    overflow-y: hidden;
}

.inset-y-0 {
    top: 0;
    bottom: 0;
}

.border-dotted {
    border-style: dotted;
}

.border-opacity-50 {
    --tw-border-opacity: 0.5;
}

.text-gray-200 {
    color: var(--ska-text-muted) !important;
}

.text-gray-400 {
    color: var(--ska-text-subtle) !important;
}

.text-gray-700 {
    color: var(--ska-text-secondary) !important;
}

.bg-black\/40 {
    background-color: rgb(0 0 0 / 0.4);
}

.border-black\/5 {
    border-color: rgb(0 0 0 / 0.05);
}

.transition-shadow {
    transition-property: box-shadow;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    transition-duration: 150ms;
}

.duration-150 {
    transition-duration: 150ms;
}

.duration-200 {
    transition-duration: 200ms;
}

.bg-gradient-to-l {
    background-image: linear-gradient(to left, var(--tw-gradient-stops));
}

@keyframes ska-spin {
    to {
        transform: rotate(360deg);
    }
}

.animate-spin-slow {
    animation: ska-spin 3s linear infinite;
}

.hover\:opacity-80:hover {
    opacity: 0.8;
}

.hover\:opacity-90:hover {
    opacity: 0.9;
}

.hover\:underline:hover {
    text-decoration-line: underline;
}

.disabled\:opacity-40:disabled {
    opacity: 0.4;
}

.focus\:ring-2:focus {
    box-shadow: 0 0 0 2px currentColor;
}

.focus\:ring-offset-2:focus {
    outline-offset: 2px;
}

@media (min-width: 640px) {
    .sm\:grid-cols-2 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .sm\:grid-cols-3 {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 768px) {
    .md\:hidden {
        display: none;
    }

    .md\:justify-between {
        justify-content: space-between;
    }

    .md\:text-right {
        text-align: right;
    }
}

/* ── Triage (hooks/legacy) ── */
.table-responsive {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.ring-1 {
    box-shadow: 0 0 0 1px var(--tw-ring-color, var(--ska-primary));
}

.ring-primary-500 {
    --tw-ring-color: var(--ska-primary);
}
/* ═══════════════════════════════════════════════════
   ACCIONES DE FILA + IDENTIFICADOR CORTO DE LA CITA
   ═══════════════════════════════════════════════════

   UN solo botón de acción de fila para las CUATRO superficies que muestran una cita (dashboard,
   agenda lista, calendario, turno de caja). Antes cada una tenía el suyo y sólo la del dashboard
   era usable; unificarlas es justamente el pedido de la tarjeta.

   EL TAMAÑO NO ES ESTÉTICA, ES EL BUG. Lo que había eran glifos con `padding: 2px` separados por
   `margin-left: 6px` (destino real ≈ 18 px) y, en el calendario, 20 px con `opacity: 0` hasta el
   hover. WCAG 2.2 SC 2.5.8 (AA) exige 24×24 px CSS de destino, O BIEN 24 px de separación entre
   destinos vecinos: fallaba las dos condiciones a la vez. Material pide además ≥8 dp de separación
   y expandir el área táctil más allá del glifo. 32 px de destino con `gap: 8px` pasa ambas con
   aire, sin agrandar el ícono (que sigue a 14 px) ni ensanchar la fila.

   VISIBLES SIEMPRE. Revelar en hover se ve limpio y rompe la descubribilidad — y en una pantalla
   táctil el hover no existe, así que la acción simplemente no está. Por eso acá no hay `opacity: 0`
   en ningún lado: el hover sólo SUBE el contraste de un botón que ya se veía.

   RÓTULO REAL, no `title=`. El tooltip no lo lee un lector de pantalla como nombre accesible ni
   aparece en táctil. Cada botón lleva su `aria-label` en el markup; acá sólo va la forma. */
.ska-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;               /* ≥8 dp entre destinos vecinos (Material) */
    justify-content: flex-end;
    white-space: nowrap;
}

.ska-row-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;            /* > 24×24 px CSS (WCAG 2.2 SC 2.5.8, AA) */
    height: 32px;
    padding: 0;
    border: 1px solid var(--ska-border);
    border-radius: 8px;
    background: var(--ska-surface);
    /* --ska-text-secondary (NEUTRAL 700), NO --ska-text-subtle (NEUTRAL 400, que la paleta define
       como "disabled, placeholders"): el ícono anterior iba en --ska-text-muted (500) y se leía como
       un fantasma gris. Un botón activo no puede tener el color de uno deshabilitado. */
    color: var(--ska-text-secondary);
    font-size: 14px;        /* el GLIFO sigue chico: lo que crece es el área de clic */
    line-height: 1;
    cursor: pointer;
    transition: background .12s ease, color .12s ease, border-color .12s ease;
}

.ska-row-action:hover {
    background: var(--ska-surface-alt);
    color: var(--ska-text);
    border-color: var(--ska-border-hover);
}

/* Foco VISIBLE con teclado: estos botones cambian el estado de una cita y cobran plata; navegarlos
   a ciegas con Tab es cómo se marca "No asistió" en la fila equivocada. */
.ska-row-action:focus-visible {
    outline: 2px solid var(--ska-primary);
    outline-offset: 2px;
}

.ska-row-action[disabled] {
    opacity: .45;
    cursor: not-allowed;
}

/* COBRAR es la acción de PLATA: se tiñe de la marca para que no sea "uno más de los cuatro íconos".
   Es la única del grupo que el operador busca activamente. */
.ska-row-action--primary {
    color: var(--ska-primary);
    border-color: var(--ska-primary);
}

.ska-row-action--primary:hover {
    background: var(--ska-primary);
    color: var(--ska-text-on-primary);
    border-color: var(--ska-primary);
}

/* DESTRUCTIVAS (No asistió / Cancelar): rojas al hover, y separadas del grupo por la línea de abajo.
   Van al final y aparte porque son las que no se deshacen desde esta pantalla. */
.ska-row-action--danger:hover {
    background: var(--ska-danger);
    color: #fff;
    border-color: var(--ska-danger);
}

/* Variante CON RÓTULO — para donde sí hay ancho (el panel lateral del calendario). NN/g: el ícono
   solo se reconoce mal salvo un puñado universal (home, imprimir, lupa); ninguno de estos cuatro lo
   es. Donde el rótulo no entra (una fila de 10 columnas) el nombre sigue en `aria-label`. */
.ska-row-actions--labelled {
    flex-wrap: wrap;
    justify-content: flex-start;
}

.ska-row-actions--labelled .ska-row-action {
    width: auto;
    min-width: 32px;
    gap: 6px;
    padding: 0 12px;
    font-size: .8125rem;
    font-weight: 600;
}

/* Separador entre las acciones normales y las destructivas: 1 px de línea + el gap de 8 a cada
   lado ⇒ 17 px reales entre el último botón seguro y el primero peligroso. */
.ska-row-actions__sep {
    width: 1px;
    height: 20px;
    background: var(--ska-border);
    flex: 0 0 auto;
}

/* En pantallas táctiles no hay hover que revele nada y el dedo no apunta como el mouse: el destino
   sube a 44 px, que es el mínimo cómodo de las guías táctiles (y el AAA de WCAG 2.5.5). */
@media (hover: none) and (pointer: coarse) {
    .ska-row-actions:not(.ska-row-actions--labelled) .ska-row-action {
        width: 44px;
        height: 44px;
    }
    /* El rotulado ya es ancho por su texto: sólo sube el alto (si le forzáramos `width` volvería a
       ser cuadrado y le cortaría el rótulo). */
    .ska-row-actions--labelled .ska-row-action {
        height: 44px;
    }
}

/* ── Identificador corto de la cita (KTD) ──
   Monoespaciado y con `tracking`: se lee letra por letra para dictarlo por teléfono, que es para lo
   que existe. Es el MISMO string en las cuatro pantallas (scheduling/short_code.py). */
.sch-code {
    display: inline-block;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .06em;
    padding: 2px 6px;
    border-radius: 6px;
    background: var(--ska-surface-alt);
    color: var(--ska-text-secondary);
    white-space: nowrap;
}

.sch-code--link {
    text-decoration: none;
}

.sch-code--link:hover {
    background: var(--ska-primary-glow);
    color: var(--ska-primary);
}

.sch-code--link:focus-visible {
    outline: 2px solid var(--ska-primary);
    outline-offset: 2px;
}

/* ─────────────────────────────────────────────────────────────────────────────
   TOOLBAR DE PERSONAS — pestañas, chips de rol y botones de alta.
   La pinta admin/includes/_ska_people_toolbar.html en los changelist de «Usuarios»
   de los tres productos. Todo con tokens --ska-*: cero hex (regla del design system).
   ───────────────────────────────────────────────────────────────────────────── */

.ska-people-toolbar {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 14px;
}

.ska-people-toolbar__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

/* ── Pestañas a otros listados (mascotas, proveedores, recursos) ── */
.ska-tabbar {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--ska-border);
}

.ska-tabbar__tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    font-size: .875rem;
    font-weight: 600;
    color: var(--ska-text-secondary);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
}

.ska-tabbar__tab:hover {
    color: var(--ska-text);
    background: var(--ska-surface-alt);
}

.ska-tabbar__tab--active {
    color: var(--ska-primary);
    border-bottom-color: var(--ska-primary);
}

/* ── Chips de rol: filtran la lista. Multi-valor por fila, ver people_role_registry ── */
.ska-rolechips {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.ska-rolechip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    border-radius: 999px;
    font-size: .8125rem;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid var(--ska-border);
    background: var(--ska-surface);
    color: var(--ska-text-secondary);
    white-space: nowrap;
}

.ska-rolechip:hover {
    border-color: var(--ska-primary);
    color: var(--ska-primary);
}

.ska-rolechip--active {
    background: var(--ska-primary);
    border-color: var(--ska-primary);
    color: var(--ska-on-primary, #fff);
}

.ska-rolechip--info    { border-color: var(--ska-info);    color: var(--ska-info); }
.ska-rolechip--success { border-color: var(--ska-success); color: var(--ska-success); }
.ska-rolechip--warning { border-color: var(--ska-warning); color: var(--ska-warning); }

.ska-rolechip--info.ska-rolechip--active    { background: var(--ska-info);    border-color: var(--ska-info); }
.ska-rolechip--success.ska-rolechip--active { background: var(--ska-success); border-color: var(--ska-success); }
.ska-rolechip--warning.ska-rolechip--active { background: var(--ska-warning); border-color: var(--ska-warning); }

.ska-rolechip--active,
.ska-rolechip--info.ska-rolechip--active,
.ska-rolechip--success.ska-rolechip--active,
.ska-rolechip--warning.ska-rolechip--active { color: #fff; }

/* ── Chip de rol EN LA FILA (no filtra; describe). La pinta cada card del producto. ── */
.ska-rolebadge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: .6875rem;
    font-weight: 700;
    background: var(--ska-surface-alt);
    color: var(--ska-text-secondary);
    border: 1px solid var(--ska-border);
    white-space: nowrap;
}

.ska-rolebadge--info    { color: var(--ska-info);    border-color: var(--ska-info); }
.ska-rolebadge--success { color: var(--ska-success); border-color: var(--ska-success); }
.ska-rolebadge--warning { color: var(--ska-warning); border-color: var(--ska-warning); }

/* ── Botón de alta. Un solo estilo para los tres que convivían: el redondo de Unfold,
      el Tailwind inline de interak y el sk-usr-btn de users (con CSS copiado en 4 productos). ── */
.ska-people-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.ska-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 16px;
    border-radius: var(--ska-radius-md, 10px);
    font-size: .875rem;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid var(--ska-border);
    background: var(--ska-surface);
    color: var(--ska-text);
    white-space: nowrap;
    cursor: pointer;
}

/* `:not(.ska-btn--primary)` y no un simple `.ska-btn:hover`: las dos reglas tenían la
   MISMA especificidad, así que el botón primario heredaba este fondo claro —y su propia
   regla de hover sólo tocaba `filter` y `color`, nunca el fondo. Resultado en pantalla:
   letra blanca sobre un gris casi blanco. El botón no se veía feo, DESAPARECÍA. */
.ska-btn:not(.ska-btn--primary):hover {
    background: var(--ska-surface-alt);
}

/* ── UN botón primario, una sola regla ─────────────────────────────────────────────
   El selector va agrupado a propósito. En el admin conviven DOS marcados para el mismo
   botón: el nuestro (`.ska-btn--primary`, la barra de personas) y el de Unfold, que pinta
   «Grabar» con utilidades de Tailwind (`bg-primary-600 text-white`) desde su propio
   paquete. No se puede unificar por variable: Unfold escribe `text-white` LITERAL en
   `unfold/components/button.html`, así que ninguna variable del tema lo alcanza.

   Lo que sí se unifica es el criterio: un solo fondo (`--ska-primary`, el color exacto de
   la marca) y una sola letra (`--ska-text-on-primary`, calculada por luminancia en el
   motor del tema). Antes había tres fondos distintos —500 acá, 600 en Unfold, y el
   aclarado en modo oscuro— cada uno con blanco encima, y los ocho combinados fallaban el
   mínimo de contraste.

   `button`/`a`/`input` en el selector de Unfold: `.bg-primary-600` también se usa en
   chips y barras de progreso, que no llevan texto encima y no deben cambiar. */
.ska-btn--primary,
button.bg-primary-600,
a.bg-primary-600,
input.bg-primary-600 {
    background: var(--ska-primary);
    border-color: var(--ska-primary);
    color: var(--ska-text-on-primary, #fff);
}

.ska-btn--primary:hover,
button.bg-primary-600:hover,
a.bg-primary-600:hover,
input.bg-primary-600:hover {
    /* El fondo del hover lo calcula el motor del tema, que sabe de qué lado está la letra:
       se ALEJA de ella, nunca se le acerca. El bug original era `filter: brightness(1.08)`,
       que aclara pase lo que pase — sobre un botón de letra blanca eso lo empeora. */
    background: var(--ska-primary-hover, var(--ska-primary));
    border-color: var(--ska-primary-hover, var(--ska-primary));
    color: var(--ska-text-on-primary, #fff);
}

.ska-btn:focus-visible {
    outline: 2px solid var(--ska-primary);
    outline-offset: 2px;
}

/* UN BOTÓN APAGADO TIENE QUE VERSE APAGADO — y no puede depender de que lo escriban.

   El 12-ago-2026 la caja de Pet Club estuvo detenida por un «Cobrar» deshabilitado sin señal.
   Al revisar la migración de botones a este patrón salió que `.ska-btn` no tenía NINGUNA regla
   `:disabled`: el gris venía de una utilidad (`disabled:opacity-40`) escrita a mano en cada
   `class`. O sea que el estado apagado sobrevivía sólo mientras nadie se olvidara de copiarla —
   y el día que alguien la olvide, el botón queda muerto con cara de vivo. Eso es peor que el
   incidente original: el cajero aprieta, no pasa nada, y no hay nada que leer.

   Vive en el patrón para que sea el defecto y no una decoración opcional. `cursor: not-allowed`
   además lo delata antes del click, que es cuando todavía sirve saberlo.

   NO lleva `pointer-events: none`, y es deliberado: un `<button disabled>` ya no dispara clicks,
   así que no aporta nada — pero apaga el `:hover`, y con él el tooltip del `title`. Ese `title` es
   donde el «Cobrar» escribe POR QUÉ está apagado. Ponerlo sería tapar la explicación con el mismo
   gesto que pinta el candado. */
.ska-btn:disabled,
.ska-btn[disabled],
.ska-btn[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ── Franja de suplantación («estás operando como otra persona») ────────────────────────────────
 * Va en ESTE archivo y no como clases Tailwind en el template por el gotcha de PurgeCSS: el CSS de
 * Unfold viene pre-compilado y purgado contra SUS plantillas, así que una clase que sólo usa un
 * override del repo se queda sin regla y no se ve. Acá la regla es nuestra y siempre existe.
 *
 * Usa `--ska-warning` y no el color de marca: la marca cambia por tenant y hay tenants con
 * primarios casi negros (Pet Club), donde una franja de marca se confunde con el chrome. Esto tiene
 * que gritar en los cuatro productos, no combinar.
 */
.ska-impersonation-bar {
    position: sticky;
    top: 0;
    z-index: 60;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 0.5rem 1rem;
    background-color: var(--ska-warning);
    color: #1a1a1a;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.3;
    text-align: center;
}

/* El botón de volver hereda la tipografía de la franja y se separa del fondo con un borde, no con
 * otro color: sobre un ámbar fuerte, un segundo color de relleno compite y se lee peor. */
.ska-impersonation-bar__back {
    padding: 0.125rem 0.625rem;
    border: 1px solid currentColor;
    border-radius: 9999px;
    background: transparent;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.ska-impersonation-bar__back:hover {
    background-color: rgba(0, 0, 0, 0.12);
}
