/* ============================================================
   moonshot.css — Japifon Design System

   Fuente única del design system compartido por Control y Console
   (pkg/uikit). Antes existían dos copias divergentes, una por
   portal, que fueron acumulando deriva: fixes de accesibilidad y
   responsive que llegaban a una y no a la otra. Esta es la fusión
   de ambas.

   Lo que es específico de un portal (documentación y number lookup
   en Control; mapas de SmartLinks y ranking geográfico en Console)
   vive en static/css/control.css y static/css/console-shell.css de
   cada portal, cargado justo después de este archivo.
   ============================================================ */

/* ── 1. Reset ────────────────────────────────────────────── */

*,
*::before,
*::after {
    box-sizing: border-box;
}

* {
    margin: 0;
    padding: 0;
}

/* Author-origin rules (e.g. button { display: inline-flex }) otherwise beat
   the UA's [hidden] { display: none } regardless of specificity, so any
   hidden button/flex item would render anyway without this. */
[hidden] {
    display: none !important;
}

html {
    -webkit-text-size-adjust: 100%;
    tab-size: 4;
    scroll-behavior: smooth;
}

body {
    min-height: 100vh;
    font-family: var(--font-sans);
    font-size: var(--font-size);
    line-height: var(--leading);
    color: var(--text-primary);
    background: var(--surface-sunken);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img,
picture,
video,
canvas,
svg {
    display: block;
    max-width: 100%;
}

input,
button,
textarea,
select {
    font: inherit;
    color: inherit;
}

button {
    cursor: pointer;
}

p,
h1,
h2,
h3,
h4,
h5,
h6 {
    overflow-wrap: break-word;
}

a {
    color: inherit;
    text-decoration: none;
}

ul,
ol {
    list-style: none;
}

table {
    border-collapse: collapse;
    width: 100%;
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

input[type="number"] {
    appearance: textfield;
    -moz-appearance: textfield;
}

:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

:focus:not(:focus-visible) {
    outline: none;
}

@media (prefers-reduced-motion: reduce) {

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── 2. Design Tokens (ADR-portales-007) ─────────────────── */
/* Primitivos, semánticos y sus valores son una copia de
   docs/design/design-tokens.md §10 — el book es la fuente de verdad, este
   archivo la implementación. La capa de componente agrega los tokens
   propios de este repo (--role-*, --tag-color-*, --nav-*, --seg-*) con el
   mismo patrón: siempre referencian la capa semántica, nunca un primitivo. */

:root,
html[data-theme="dark"],
html[data-theme="light"] {
    color-scheme: light dark;
}

html[data-theme="dark"] { color-scheme: dark; }
html[data-theme="light"] { color-scheme: light; }

@property --text-primary { syntax: '<color>'; inherits: true; initial-value: #111111; }
@property --text-muted { syntax: '<color>'; inherits: true; initial-value: #6F6F6F; }
@property --text-secondary { syntax: '<color>'; inherits: true; initial-value: #525252; }
@property --border-divider { syntax: '<color>'; inherits: true; initial-value: #E5E5E5; }
@property --color-primary { syntax: '<color>'; inherits: true; initial-value: #00008C; }
@property --color-success { syntax: '<color>'; inherits: true; initial-value: #0B7275; }
@property --color-warning { syntax: '<color>'; inherits: true; initial-value: #7A4A00; }
@property --color-error { syntax: '<color>'; inherits: true; initial-value: #C62828; }
@property --color-info { syntax: '<color>'; inherits: true; initial-value: #00008C; }
@property --color-muted { syntax: '<color>'; inherits: true; initial-value: #5B6B80; }
@property --surface-base { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --surface-raised { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --surface-inverse { syntax: '<color>'; inherits: true; initial-value: #111111; }
/* chart-theme.js y nl-map.js leen estos con getComputedStyle(): sin
   @property, light-dark() les llega como string sin resolver. */
@property --chart-data-1 { syntax: '<color>'; inherits: true; initial-value: #3B3BB8; }
@property --chart-data-2 { syntax: '<color>'; inherits: true; initial-value: #1F9CA0; }
@property --chart-data-3 { syntax: '<color>'; inherits: true; initial-value: #B81F74; }
@property --chart-data-4 { syntax: '<color>'; inherits: true; initial-value: #C47E08; }
@property --chart-data-5 { syntax: '<color>'; inherits: true; initial-value: #00005C; }
@property --chart-data-6 { syntax: '<color>'; inherits: true; initial-value: #7A4A00; }
@property --chart-on-data-1 { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --chart-on-data-2 { syntax: '<color>'; inherits: true; initial-value: #111111; }
@property --chart-on-data-3 { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --chart-on-data-4 { syntax: '<color>'; inherits: true; initial-value: #111111; }
@property --chart-on-data-5 { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --chart-on-data-6 { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --color-on-success { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --color-on-warning { syntax: '<color>'; inherits: true; initial-value: #111111; }
@property --color-on-error { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --color-on-info { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --color-on-muted { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }
@property --chart-tooltip-bg { syntax: '<color>'; inherits: true; initial-value: #111111; }
@property --chart-tooltip-fg { syntax: '<color>'; inherits: true; initial-value: #FFFFFF; }

:root {
    --font-sans: "Inter", system-ui, -apple-system, sans-serif;
    --font-mono: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
    --font-size: 16px;
    --leading: 1.5;

    --text-display: 700 48px/56px var(--font-sans);
    --text-h1: 700 24px/28px var(--font-sans);
    --text-h2: 700 18px/22px var(--font-sans);
    --text-h3: 700 13px/17px var(--font-sans);
    --text-body: 400 16px/24px var(--font-sans);
    --text-body-s: 400 12px/16px var(--font-sans);
    --text-caption: 400 10px/13px var(--font-sans);
    --text-micro: 500 9px/12px var(--font-sans);
    --text-mono: 400 13px/20px var(--font-mono);

    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 20px;
    --sp-6: 24px;
    --sp-8: 32px;
    --sp-10: 40px;
    --sp-12: 48px;
    --sp-16: 64px;

    --radius-sm: 4px;
    --radius: 6px;
    --radius-lg: 9px;
    --radius-full: 999px;
    --ease: cubic-bezier(0.16, 1, 0.3, 1);
    --duration: 150ms;

    --z-dropdown: 10;
    --z-sticky: 40;
    --z-overlay: 50;
    --z-sidebar: 100;
    --z-modal: 200;
    --z-toast: 9999;

    /* CAPA 1 — Primitivos (docs/design/design-tokens.md §10). Nunca se usan
       en un componente. */
    --p-navy-950: #00005C;  --p-navy-900: #00068F;  --p-navy-700: #3B3BB8;
    --p-navy-600: #6666CF;  --p-navy-500: #8585DC;  --p-navy-400: #8C8CDA;
    --p-navy-300: #A0A0E8;
    --p-navy-250: #B2B2EC;
    --p-navy-200: #C4C4F2;
    --p-teal-800: #0B7275;  --p-teal-600: #1F9CA0;  --p-teal-500: #00BBAF;
    --p-teal-400: #2CCABE;
    --p-magenta-700: #B81F74; --p-magenta-500: #FB0D80; --p-magenta-300: #F07CC0;
    --p-amber-900: #7A4A00; --p-amber-700: #C47E08; --p-amber-600: #B5843A;
    --p-amber-500: #F59E0B;
    --p-red-700: #C62828;   --p-red-400: #FF6B5E;
    --p-slate-600: #5B6B80; --p-slate-400: #94A3B8;
    --p-gray-0: #FFFFFF;  --p-gray-50: #FAFAFA;  --p-gray-100: #F5F5F5;
    --p-gray-200: #E5E5E5; --p-gray-300: #D4D4D4; --p-gray-400: #A3A3A3;
    --p-gray-450: #8A8A8A; --p-gray-500: #6F6F6F; --p-gray-600: #525252;
    --p-gray-700: #404040; --p-gray-800: #262626; --p-gray-900: #111111;

    /* Ink — los neutros del tema oscuro. No son grises: llevan tinte navy, y
       por eso el fondo oscuro ya no es negro. Van aparte de --p-gray-* porque
       el tema claro sigue usando los grises puros: mezclarlos en una sola
       escala obligaría a recordar cuál mitad vale para cuál tema. */
    --p-ink-100: #F2F3F8; --p-ink-300: #CACDDD; --p-ink-350: #B4B7CB;
    --p-ink-400: #A3A7BF; --p-ink-500: #878CA8; --p-ink-600: #6C7090;
    --p-ink-700: #41455E; --p-ink-800: #2F3247; --p-ink-900: #252839;
    --p-ink-950: #1E2030;  --p-ink-975: #0A0B12;

    /* CAPA 2 — Semánticos (book §10). Es lo que se consume en producto. */
    --color-primary: light-dark(var(--p-navy-900), var(--p-navy-400));
    --color-primary-fill: light-dark(var(--p-navy-900), var(--p-navy-600));
    --color-on-primary: light-dark(var(--p-gray-0), var(--p-gray-900));

    --color-secondary: light-dark(var(--p-teal-800), var(--p-teal-500));
    --color-secondary-fill: light-dark(var(--p-teal-600), var(--p-teal-500));
    --color-on-secondary: var(--p-gray-900);

    --color-accent: light-dark(var(--p-magenta-700), var(--p-magenta-300));
    --color-accent-fill: var(--p-magenta-700);
    /* Blanco sobre el magenta, como manda el book. Sobre #B81F74 (el relleno
       del acento) el blanco da ~5.9:1 y pasa AA; sobre --p-magenta-500 no lo
       pasaría, y por eso el relleno es el 700 y no el 500. */
    --color-on-accent: var(--p-gray-0);

    --color-info: var(--color-primary);
    --color-info-fill: var(--color-primary-fill);
    --color-on-info: var(--color-on-primary);

    --color-success: light-dark(var(--p-teal-800), var(--p-teal-500));
    --color-success-fill: light-dark(var(--p-teal-800), var(--p-teal-800));
    --color-on-success: var(--p-gray-0);

    --color-warning: light-dark(var(--p-amber-900), var(--p-amber-500));
    --color-warning-fill: var(--p-amber-500);
    --color-on-warning: var(--p-gray-900);

    --color-error: light-dark(var(--p-red-700), var(--p-red-400));
    --color-error-fill: var(--p-red-700);
    --color-on-error: light-dark(var(--p-gray-0), var(--p-gray-900));

    --color-muted: light-dark(var(--p-slate-600), var(--p-slate-400));
    --color-on-muted: light-dark(var(--p-gray-0), var(--p-gray-900));

    --color-link: var(--color-primary);
    --color-link-hover: light-dark(var(--p-magenta-700), var(--p-magenta-300));
    --focus-ring: var(--color-primary);

    --text-primary: light-dark(var(--p-gray-900), var(--p-ink-100));
    --text-secondary: light-dark(var(--p-gray-600), var(--p-ink-300));
    --text-muted: light-dark(var(--p-gray-500), var(--p-ink-350));
    --text-disabled: light-dark(var(--p-gray-400), var(--p-ink-600));

    --surface-base: light-dark(var(--p-gray-0), var(--p-ink-900));
    --surface-raised: light-dark(var(--p-gray-0), var(--p-ink-800));
    --surface-sunken: light-dark(var(--p-gray-50), var(--p-ink-950));
    --surface-subtle: light-dark(var(--p-gray-100), var(--p-ink-800));
    --surface-inverse: light-dark(var(--p-gray-900), var(--p-ink-100));
    --surface-disabled: light-dark(var(--p-gray-100), var(--p-ink-800));

    --border-divider: light-dark(var(--p-gray-200), var(--p-ink-700));
    --border-component: light-dark(var(--p-gray-450), var(--p-ink-500));
    --border-error: var(--color-error);
    --border-disabled: light-dark(var(--p-gray-200), var(--p-ink-700));

    /* *-subtle: color-mix reproduce el rgba() del book referenciando el
       primitivo — la única forma de "componer alfa a mano" sin duplicar el
       valor hex en dos lados (ADR-portales-007 §1). */
    --primary-subtle: light-dark(
        color-mix(in srgb, var(--p-navy-900) 8%, transparent),
        color-mix(in srgb, var(--p-navy-400) 16%, transparent)
    );
    --secondary-subtle: light-dark(
        color-mix(in srgb, var(--p-teal-600) 10%, transparent),
        color-mix(in srgb, var(--p-teal-500) 16%, transparent)
    );
    --success-subtle: var(--secondary-subtle);
    --accent-subtle: light-dark(
        color-mix(in srgb, var(--p-magenta-500) 8%, transparent),
        color-mix(in srgb, var(--p-magenta-300) 16%, transparent)
    );
    --warning-subtle: light-dark(
        color-mix(in srgb, var(--p-amber-500) 12%, transparent),
        color-mix(in srgb, var(--p-amber-500) 16%, transparent)
    );
    --error-subtle: light-dark(
        color-mix(in srgb, var(--p-red-700) 8%, transparent),
        color-mix(in srgb, var(--p-red-400) 16%, transparent)
    );

    /* state.*: sin primitivo — el negro/blanco de overlay es el único caso
       del book que no referencia la marca (ADR-portales-007 §1). */
    --state-darken-hover: rgba(0, 0, 0, 0.12);
    --state-darken-pressed: rgba(0, 0, 0, 0.24);
    --state-lighten-hover: rgba(255, 255, 255, 0.12);
    --state-lighten-pressed: rgba(255, 255, 255, 0.24);
    --state-hover-surface: light-dark(rgba(0, 0, 0, 0.04), rgba(255, 255, 255, 0.06));

    /* El spinner vive siempre sobre un fill de color (botón primario), sin
       importar el tema — blanco fijo, igual que --state-lighten-*. */
    --spinner-fg: var(--p-gray-0);

    --chart-data-1: light-dark(var(--p-navy-700), var(--p-navy-500));
    --chart-data-2: light-dark(var(--p-teal-600), var(--p-teal-500));
    --chart-data-3: light-dark(var(--p-magenta-700), var(--p-magenta-500));
    --chart-data-4: light-dark(var(--p-amber-700), var(--p-amber-500));
    --chart-data-5: light-dark(var(--p-navy-950), var(--p-navy-200));
    --chart-data-6: light-dark(var(--p-amber-900), var(--p-amber-600));

    /* book §3, columna "Texto encima" — nombre propio, no está en §10. */
    --chart-on-data-1: light-dark(var(--p-gray-0), var(--p-gray-900));
    --chart-on-data-2: var(--p-gray-900);
    --chart-on-data-3: light-dark(var(--p-gray-0), var(--p-gray-900));
    --chart-on-data-4: var(--p-gray-900);
    --chart-on-data-5: light-dark(var(--p-gray-0), var(--p-gray-900));
    --chart-on-data-6: var(--p-gray-0);

    --nav-text: var(--text-secondary);
    --nav-text-hover: var(--color-primary);
    --nav-hover-bg: var(--primary-subtle);
    --nav-active-text: var(--color-primary);
    --nav-active-bg: var(--primary-subtle);
    --seg-active-bg: var(--primary-subtle);
    --seg-active-text: var(--color-primary);
    --seg-hover-bg: var(--primary-subtle);
    --seg-hover-text: var(--color-primary);

    --scrim: rgba(0, 0, 0, 0.5);
    --spinner-track: rgba(255, 255, 255, 0.3);

    /* CAPA 3 — Componente. Solo referencia la capa 2, nunca un primitivo. */
    --input-bg: var(--surface-raised);
    --input-border: var(--border-component);
    --input-focus-border: var(--color-primary);
    --input-placeholder: var(--text-muted);

    --btn-primary-bg: var(--color-primary-fill);
    --btn-primary-fg: var(--color-on-primary);
    --btn-secondary-bg: var(--color-secondary-fill);
    --btn-secondary-fg: var(--color-on-secondary);

    --link: var(--color-link);
    --link-hover: var(--color-link-hover);
    --sidebar-active-bg: var(--primary-subtle);
    --sidebar-active-border: var(--color-primary);

    --chart-tooltip-bg: var(--surface-inverse);
    --chart-tooltip-fg: var(--surface-base);

    --role-superadmin: var(--color-warning);
    --role-superadmin-bg: var(--warning-subtle);
    --role-superadmin-border: var(--color-warning);
    --role-admin: var(--color-primary);
    --role-admin-bg: var(--primary-subtle);
    --role-admin-border: var(--color-primary);
    --role-finance: var(--color-success);
    --role-finance-bg: var(--success-subtle);
    --role-finance-border: var(--color-success);
    --role-staff: var(--color-accent);
    --role-staff-bg: var(--accent-subtle);
    --role-staff-border: var(--color-accent);
    --role-support: var(--color-secondary);
    --role-support-bg: var(--secondary-subtle);
    --role-support-border: var(--color-secondary);
    --role-compliance: var(--color-muted);
    --role-compliance-bg: var(--surface-subtle);
    --role-compliance-border: var(--color-muted);
    --role-account-manager: var(--color-primary);
    --role-account-manager-bg: var(--primary-subtle);
    --role-account-manager-border: var(--color-primary);
    --role-viewer: var(--text-secondary);
    --role-viewer-bg: var(--surface-subtle);
    --role-viewer-border: var(--border-component);
    --role-owner: var(--role-superadmin);
    --role-owner-bg: var(--role-superadmin-bg);
    --role-owner-border: var(--role-superadmin-border);
    --role-developer: var(--role-staff);
    --role-developer-bg: var(--role-staff-bg);
    --role-developer-border: var(--role-staff-border);
    --role-billing: var(--role-support);
    --role-billing-bg: var(--role-support-bg);
    --role-billing-border: var(--role-support-border);
    --role-operations: var(--role-support);
    --role-operations-bg: var(--role-support-bg);
    --role-operations-border: var(--role-support-border);
    --role-user: var(--role-viewer);
    --role-user-bg: var(--role-viewer-bg);
    --role-user-border: var(--role-viewer-border);

    /* Slugs de tags CDP: remapeo de color sobre el CHECK ya aplicado de
       cdp_001_cdp.sql, sin tocar la migración (ADR-portales-007 §3). */
    --tag-color-slate: var(--color-muted);
    --tag-color-slate-bg: var(--surface-subtle);
    --tag-color-slate-border: var(--color-muted);
    --tag-color-blue: var(--chart-data-1);
    --tag-color-blue-bg: var(--primary-subtle);
    --tag-color-blue-border: var(--chart-data-1);
    --tag-color-teal: var(--chart-data-2);
    --tag-color-teal-bg: var(--secondary-subtle);
    --tag-color-teal-border: var(--chart-data-2);
    --tag-color-green: var(--chart-data-5);
    --tag-color-green-bg: var(--primary-subtle);
    --tag-color-green-border: var(--chart-data-5);
    --tag-color-amber: var(--chart-data-4);
    --tag-color-amber-bg: var(--warning-subtle);
    --tag-color-amber-border: var(--chart-data-4);
    --tag-color-orange: var(--chart-data-6);
    --tag-color-orange-bg: var(--warning-subtle);
    --tag-color-orange-border: var(--chart-data-6);
    --tag-color-red: var(--color-error);
    --tag-color-red-bg: var(--error-subtle);
    --tag-color-red-border: var(--color-error);
    --tag-color-violet: var(--chart-data-3);
    --tag-color-violet-bg: var(--accent-subtle);
    --tag-color-violet-border: var(--chart-data-3);
}


/* ── 3. Layout ─────────────────────────────────────────────── */

.app-shell {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    position: sticky;
    top: 0;
    width: 300px;
    min-width: 300px;
    height: 100vh;
    overflow-y: auto;
    background: var(--surface-raised);
    border-right: 1px solid var(--border-divider);
    z-index: var(--z-sidebar);
}

.app-shell > main {
    flex: 1;
    min-width: 0;
    max-width: 1440px;
    margin: 0 auto;
    padding: var(--sp-8);
    overflow-x: hidden;
}

.mobile-header,
.nav-overlay {
    display: none;
}

/* QA-5: at 768-1024px the desktop sidebar was hidden but the mobile
   hamburger only appeared below 768px, leaving tablets without any
   way to navigate. Lift the mobile shell breakpoint to 1024px so the
   hamburger covers the entire range where the sidebar is collapsed. */
@media (max-width: 1024px) {
    .app-shell {
        flex-direction: column;
    }

    .mobile-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: var(--sp-3) var(--sp-4);
        background: var(--surface-raised);
        border-bottom: 1px solid var(--border-divider);
        position: sticky;
        top: 0;
        z-index: var(--z-sticky);
    }

    .mobile-header__toggle {
        display: flex;
        align-items: center;
        cursor: pointer;
        color: var(--text-secondary);
    }

    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: 300px;
        min-width: 0;
        transform: translateX(-100%);
        visibility: hidden;
        transition: transform var(--duration) var(--ease),
            visibility 0s linear var(--duration);
    }

    html,
    body {
        overflow-x: hidden;
    }

    .sidebar.nav--open {
        transform: translateX(0);
        visibility: visible;
        transition: transform var(--duration) var(--ease),
            visibility 0s linear 0s;
    }

    .nav-overlay--visible {
        display: block;
        position: fixed;
        inset: 0;
        background: var(--scrim);
        z-index: calc(var(--z-sidebar) - 1);
    }

    .app-shell > main {
        padding: var(--sp-4);
        width: 100%;
        max-width: 100%;
    }

    .page-header {
        padding: 0 var(--sp-3);
    }

    .access-panel,
    .profile-card {
        border-radius: 0;
        border-left: none;
        border-right: none;
    }
}

/* ── 4. Navigation ─────────────────────────────────────────── */

.nav {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: var(--sp-4) 0;
}

.nav__close {
    display: none;
}

.nav__brand {
    display: flex;
    justify-content: center;
    padding: 0 var(--sp-5) var(--sp-5);
    border-bottom: 1px solid var(--border-divider);
    margin-bottom: var(--sp-4);
}

.nav__menu {
    flex: 1;
    overflow-y: auto;
    padding: 0 var(--sp-3);
}

.nav__section-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    padding: var(--sp-5) var(--sp-3) var(--sp-2);
}

.nav__link {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--radius);
    font-size: 14px;
    font-weight: 500;
    color: var(--nav-text);
    transition:
        background var(--duration) var(--ease),
        color var(--duration) var(--ease);
}

.nav__link:hover {
    background: var(--nav-hover-bg);
    color: var(--nav-text-hover);
}

.nav__link--active {
    background: var(--nav-active-bg);
    color: var(--nav-active-text);
    font-weight: 600;
}

.nav__icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    opacity: 0.7;
}

.nav__link:hover .nav__icon,
.nav__link--active .nav__icon {
    opacity: 1;
}

.nav__link--active .nav__icon {
    color: var(--color-primary);
}

.nav__link--disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.nav__link--disabled:hover {
    background: none;
    color: inherit;
}

.nav__footer {
    padding: var(--sp-4) var(--sp-4) 0;
    border-top: 1px solid var(--border-divider);
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

.nav__segmented {
    display: flex;
    gap: 2px;
    background: var(--surface-subtle);
    border-radius: var(--radius);
    padding: 2px;
}

.nav__seg-btn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-1);
    padding: var(--sp-1) var(--sp-2);
    border-radius: var(--radius-sm);
    font-size: 12px;
    font-weight: 500;
    color: var(--text-secondary);
    transition:
        background var(--duration) var(--ease),
        color var(--duration) var(--ease);
}

.nav__seg-btn:hover {
    background: var(--seg-hover-bg);
    color: var(--seg-hover-text);
}

.nav__seg-btn--active {
    background: var(--seg-active-bg);
    color: var(--seg-active-text);
    font-weight: 600;
}

.nav__seg-flag {
    font-size: 14px;
    line-height: 1;
}

.nav__seg-code {
    font-size: 11px;
    letter-spacing: 0.04em;
}

.nav__seg-icon {
    width: 16px;
    height: 16px;
}

.nav__logout {
    width: 100%;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border-divider);
    border-radius: var(--radius);
    background: transparent;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
    text-align: center;
    transition:
        background var(--duration) var(--ease),
        color var(--duration) var(--ease),
        border-color var(--duration) var(--ease);
}

.nav__logout:hover {
    background: var(--error-subtle);
    color: var(--color-error);
    border-color: var(--border-error);
}

/* Logo theme toggle */
html[data-theme="dark"] .logo-light,
html:not([data-theme]) .logo-light {
    display: none;
}

html[data-theme="dark"] .logo-dark,
html:not([data-theme]) .logo-dark {
    display: inline;
}

html[data-theme="light"] .logo-light {
    display: inline;
}

html[data-theme="light"] .logo-dark {
    display: none;
}

@media (prefers-color-scheme: light) {
    html:not([data-theme]) .logo-light {
        display: inline;
    }

    html:not([data-theme]) .logo-dark {
        display: none;
    }
}

/* ── 5. Base Elements ──────────────────────────────────────── */

h1 {
    font-size: 24px;
    font-weight: 700;
    line-height: 1.2;
}

h2 {
    font-size: 20px;
    font-weight: 600;
    line-height: 1.3;
}

h3 {
    font-size: 16px;
    font-weight: 600;
    line-height: 1.4;
}

h4 {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
}

small {
    font-size: 12px;
    color: var(--text-secondary);
}

article {
    background: var(--surface-raised);
    border: 1px solid var(--border-divider);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
}

article header {
    margin: calc(var(--sp-5) * -1) calc(var(--sp-5) * -1) var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
    background: var(--surface-subtle);
    border-bottom: 1px solid var(--border-divider);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.dash-kpi article strong {
    font-size: 22px;
    font-weight: 700;
}

th,
td {
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--border-divider);
}

th {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    text-align: left;
}

td {
    font-size: 14px;
}

tbody tr:last-child td {
    border-bottom: none;
}

tbody tr:hover {
    background: var(--state-hover-surface);
}

tbody tr.row-link {
    cursor: pointer;
}

/* Fila clicable con el otro convenio de marcado: el hover ya lo da
   `tbody tr:hover`; lo que faltaba era la señal de que se puede hacer click. */
tr[data-row-href] {
    cursor: pointer;
}

@media (max-width: 768px) {
    table.responsive thead {
        display: none;
    }

    table.responsive tbody tr {
        display: flex;
        flex-direction: column;
        padding: var(--sp-3) var(--sp-4);
        border-bottom: 1px solid var(--border-divider);
    }

    table.responsive tbody tr:last-child {
        border-bottom: none;
    }

    table.responsive td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: var(--sp-1) 0;
        border-bottom: none;
        font-size: 13px;
    }

    table.responsive td:before {
        content: attr(data-label);
        font-size: 11px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--text-secondary);
        flex-shrink: 0;
        margin-right: var(--sp-3);
    }

    table.responsive td:first-child a {
        font-weight: 600;
        color: var(--accent-text, var(--color-primary));
        padding: var(--sp-1) 0;
        min-height: 44px;
        display: flex;
        align-items: center;
    }

    table.responsive td:last-child {
        justify-content: flex-end;
        gap: var(--sp-2);
        margin-top: var(--sp-2);
        flex-wrap: wrap;
    }
}

/* Controls (shared sizing) */
/* :not([class*="jp-"]) en todo el bloque de botones: mientras el portal
   conviva con el design system, un elemento ya migrado a jp-btn/jp-menu__item
   no debe recibir además el reset de aquí. Sin esto, el `justify-content:
   center` de abajo centraba el texto de los .jp-menu__item —que no declara
   justify-content y por tanto no lo tapaba— y los items del menú salían
   centrados mientras los <a> del mismo menú iban a la izquierda. */
button:not([class*="jp-"]),
[role="button"],
.btn:not([class*="jp-"]),
a.sm,
a.xs,
a.outline,
a.secondary,
a.danger,
input,
select,
textarea {
    padding: var(--sp-2) var(--sp-3);
    font-size: 14px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    transition:
        background var(--duration) var(--ease),
        border-color var(--duration) var(--ease);
}

/* a.sm/a.xs/a.outline/a.secondary/a.danger: a real <a href> styled as a
   button (real navigation, not a JS-only action) — no role="button" needed
   or wanted, since the anchor is already keyboard-operable and role="button"
   would misreport it as a non-navigating control (and trips Sonar's
   Web:S6819 "prefer tag over ARIA role" for good reason). Scoped to these
   specific classes, never bare `a`, so plain text links are untouched. */
button:not([class*="jp-"]),
[role="button"],
.btn:not([class*="jp-"]),
a.sm,
a.xs,
a.outline,
a.secondary,
a.danger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    font-weight: 500;
    /* El hover NO reemplaza el fondo: le pone un velo encima. background-color
       lleva el color de la variante y background-image un degradado plano de
       --_overlay, que en reposo es transparente. Así cada variante se oscurece
       o se aclara sobre SU color, en vez de saltar todas al mismo. Antes era
       `background: var(--link-hover)` en el :hover, y un botón primario, uno
       outline y uno de peligro acababan idénticos al pasar el ratón. */
    --_overlay: transparent;
    background-color: var(--color-primary);
    background-image: linear-gradient(var(--_overlay), var(--_overlay));
    color: var(--color-on-primary);
}

/* El velo sigue al texto, no al fondo: el book §06 lo fija como «fills con
   texto blanco se oscurecen; fills con texto oscuro se aclaran», para que el
   contraste con el texto SUBA al pasar el ratón en vez de bajar.
   --color-on-primary y --color-on-error son light-dark(blanco, oscuro), así que
   el velo tiene que cambiar con el tema igual que ellos: oscurecer en claro,
   aclarar en oscuro. Un darken fijo hundiría el contraste en dark, que es justo
   donde el texto ya es oscuro. */
button:hover:not([class*="jp-"]),
[role="button"]:hover,
.btn:hover:not([class*="jp-"]),
a.sm:hover,
a.xs:hover,
a.danger:hover {
    --_overlay: light-dark(var(--state-darken-hover), var(--state-lighten-hover));
}

button:active:not([class*="jp-"]),
[role="button"]:active,
.btn:active:not([class*="jp-"]),
a.sm:active,
a.xs:active,
a.danger:active {
    --_overlay: light-dark(var(--state-darken-pressed), var(--state-lighten-pressed));
}


button.sm:not([class*="jp-"]),
[role="button"].sm,
.btn.sm,
a.sm {
    padding: var(--sp-1) var(--sp-3);
    font-size: 13px;
}

button.xs:not([class*="jp-"]),
[role="button"].xs,
.btn.xs,
a.xs {
    padding: var(--sp-1) var(--sp-3);
    font-size: 13px;
    min-height: 32px;
}

button.outline:not([class*="jp-"]),
button.secondary:not([class*="jp-"]),
[role="button"].outline,
[role="button"].secondary,
.btn.outline,
.btn.secondary,
a.outline,
a.secondary {
    /* background-color y no el shorthand: `background: transparent` borraría el
       background-image donde vive el velo del hover. */
    background-color: transparent;
    border-color: var(--border-component);
    color: var(--text-primary);
}

button.outline:hover,
button.secondary:hover,
[role="button"].outline:hover,
[role="button"].secondary:hover,
.btn.outline:hover,
.btn.secondary:hover,
a.outline:hover,
a.secondary:hover {
    /* Sin fondo propio, oscurecer no se vería: estos se tiñen con la superficie
       de hover, que es lo que el book reserva para los controles sin relleno. */
    --_overlay: var(--state-hover-surface);
    border-color: var(--border-component);
    color: var(--text-primary);
}

button.outline[aria-pressed="true"],
[role="button"].outline[aria-pressed="true"],
.btn.outline[aria-pressed="true"],
a.outline[aria-pressed="true"],
button[role="tab"].outline[aria-selected="true"] {
    background-color: var(--surface-subtle);
    border-color: var(--border-component);
    color: var(--text-primary);
}

button.danger:not([class*="jp-"]),
[role="button"].danger,
.btn.danger,
a.danger {
    background-color: var(--color-error);
}

button.danger:hover,
[role="button"].danger:hover,
.btn.danger:hover,
a.danger:hover {
    /* Antes repetía var(--color-error), el mismo color del reposo: el hover no
       se veía. Ahora el velo va sobre su propio rojo, y sigue al texto como el
       resto: --color-on-error es blanco en claro y oscuro en dark. */
    --_overlay: light-dark(var(--state-darken-hover), var(--state-lighten-hover));
}

input,
select,
textarea {
    width: 100%;
    background: var(--input-bg);
    border-color: var(--input-border);
}

select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23878d9c' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--sp-3) center;
    padding-right: var(--sp-8);
}

/* Chrome/Firefox ignoran `color: inherit` en <option> cuando la página
   declara color-scheme: dark — el popup nativo del select cae a texto
   blanco sobre fondo oscuro salvo que cada <option> reciba color/fondo
   explícitos. */
select option {
    color: var(--text-primary);
    background: var(--input-bg);
}

/* Un <select required> con la opción vacía todavía seleccionada queda
   :invalid — varios navegadores pintan ese estado con un color de sistema
   (texto blanco) en vez de heredar `color`, distinto al mismo <select>
   sin `required`. */
select:invalid {
    color: var(--text-primary) !important;
    background-color: var(--input-bg) !important;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--input-focus-border);
    outline: none;
}

input::placeholder,
textarea::placeholder {
    color: var(--input-placeholder);
}

label {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
    margin-bottom: var(--sp-3);
}

label > span {
    line-height: 1.3;
}

.grid label {
    margin-bottom: 0;
}

label:has(input[type="checkbox"]) {
    flex-direction: row;
    align-items: center;
    gap: var(--sp-2);
    cursor: pointer;
    margin-bottom: var(--sp-2);
}

.text--success {
    color: var(--color-success);
}

.text--danger {
    color: var(--color-error);
}

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

code {
    font-family: var(--font-mono);
    font-size: 13px;
    background: var(--surface-subtle);
    padding: 2px var(--sp-2);
    border-radius: var(--radius-sm);
}

hgroup {
    margin-bottom: var(--sp-1);
}

hgroup p {
    font-size: 14px;
    color: var(--text-secondary);
    margin-top: var(--sp-1);
}

.alert {
    display: block;
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--radius);
    font-size: 14px;
    margin-bottom: var(--sp-4);
}

.alert--error {
    background: var(--error-subtle);
    border: 1px solid var(--border-error);
    color: var(--color-error);
}

/* --success/--warning/--info: referenced by several templates (CDP, domains,
   smartlinks, whatsapp_templates) that assumed these existed alongside
   --error — they didn't, so those banners fell back to unstyled text. */
.alert--success {
    background: var(--success-subtle);
    border: 1px solid var(--color-success);
    color: var(--color-success);
}

.alert--warning {
    background: var(--warning-subtle);
    border: 1px solid var(--color-warning);
    color: var(--color-warning);
}

.alert--info {
    background: var(--primary-subtle);
    border: 1px solid var(--color-primary);
    color: var(--color-info);
}

/* ── 6. Components ─────────────────────────────────────────── */

/* Page header */
.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-bottom: var(--sp-6);
}

/* Badges */
.badge {
    display: inline-flex;
    align-items: center;
    /* Una etiqueta que se parte en dos líneas deja de leerse como etiqueta: el
       radio completo la convierte en una cápsula deforme y el padding se ve
       arbitrario. Si no cabe, el contenedor tiene que ceder, no el badge. */
    white-space: nowrap;
    padding: 2px var(--sp-2);
    border-radius: var(--radius-full);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.badge--active {
    background: var(--success-subtle);
    color: var(--color-success);
    border: 1px solid var(--color-success);
}

.badge--inactive,
.badge--muted {
    background: var(--surface-subtle);
    color: var(--text-secondary);
    border: 1px solid var(--border-divider);
}

.badge--xs {
    font-size: 10px;
    padding: 1px var(--sp-1);
}

.badge--accent {
    background: var(--primary-subtle);
    color: var(--accent-text, var(--color-primary));
    border: 1px solid transparent;
}

.badge--success {
    background: var(--success-subtle);
    color: var(--color-success);
    border: 1px solid var(--color-success);
}

.badge--error {
    background: var(--error-subtle);
    color: var(--color-error);
    border: 1px solid var(--border-error);
}

.badge--warning {
    background: var(--warning-subtle);
    color: var(--color-warning);
    border: 1px solid var(--color-warning);
}

/* Un escalón por encima de --warning: no es "revisa esto", es "esto no
   funciona". Lo usa Number Lookup para una ruta cuyo país devuelve 422. */
.badge--danger {
    background: var(--error-subtle);
    color: var(--color-error);
    border: 1px solid var(--border-error);
}

/* Estado informativo, sin connotación buena ni mala (estándar TKT-658 §2). */
.badge--info {
    background: var(--primary-subtle);
    color: var(--color-info);
    border: 1px solid var(--color-primary);
}

.badge--secondary {
    background: var(--secondary-subtle);
    color: var(--color-secondary);
    border: 1px solid var(--color-secondary-fill);
}

.badge--neutral {
    background: var(--surface-subtle);
    color: var(--text-secondary);
    border: 1px solid var(--border-divider);
}

.badge--sent {
    background: var(--success-subtle);
    color: var(--color-success);
    border: 1px solid var(--color-success);
}

.badge--scheduled {
    background: var(--primary-subtle);
    color: var(--color-info);
    border: 1px solid var(--color-primary);
}

.badge--sending {
    background: var(--warning-subtle);
    color: var(--color-warning);
    border: 1px solid var(--color-warning);
}

.badge--failed {
    background: var(--error-subtle);
    color: var(--color-error);
    border: 1px solid var(--border-error);
}

.badge--cancelled {
    background: var(--surface-subtle);
    color: var(--text-secondary);
    border: 1px solid var(--border-divider);
    text-decoration: line-through;
}

.badge--draft {
    background: var(--surface-subtle);
    color: var(--text-secondary);
    border: 1px solid var(--border-divider);
}

.badge--paused {
    background: var(--warning-subtle);
    color: var(--color-warning);
    border: 1px solid var(--color-warning);
}

.badge--expired {
    background: var(--surface-subtle);
    color: var(--text-secondary);
    border: 1px solid var(--border-divider);
    text-decoration: line-through;
}

/* Platform role badges */
.platform-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px var(--sp-2);
    border-radius: var(--radius-sm);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border: 1px solid transparent;
}

.platform-badge--superadmin {
    background: var(--role-superadmin-bg);
    color: var(--role-superadmin);
    border-color: var(--role-superadmin-border);
}

.platform-badge--admin {
    background: var(--role-admin-bg);
    color: var(--role-admin);
    border-color: var(--role-admin-border);
}

.platform-badge--staff {
    background: var(--role-staff-bg);
    color: var(--role-staff);
    border-color: var(--role-staff-border);
}

.platform-badge--finance {
    background: var(--role-finance-bg);
    color: var(--role-finance);
    border-color: var(--role-finance-border);
}

.platform-badge--support {
    background: var(--role-support-bg);
    color: var(--role-support);
    border-color: var(--role-support-border);
}

.platform-badge--compliance {
    background: var(--role-compliance-bg);
    color: var(--role-compliance);
    border-color: var(--role-compliance-border);
}

.platform-badge--account-manager {
    background: var(--role-account-manager-bg);
    color: var(--role-account-manager);
    border-color: var(--role-account-manager-border);
}

.platform-badge--viewer {
    background: var(--role-viewer-bg);
    color: var(--role-viewer);
    border-color: var(--role-viewer-border);
}

.platform-badge--owner {
    background: var(--role-owner-bg);
    color: var(--role-owner);
    border-color: var(--role-owner-border);
}

.platform-badge--developer {
    background: var(--role-developer-bg);
    color: var(--role-developer);
    border-color: var(--role-developer-border);
}

.platform-badge--billing {
    background: var(--role-billing-bg);
    color: var(--role-billing);
    border-color: var(--role-billing-border);
}

.platform-badge--operations {
    background: var(--role-operations-bg);
    color: var(--role-operations);
    border-color: var(--role-operations-border);
}

.platform-badge--user {
    background: var(--role-user-bg);
    color: var(--role-user);
    border-color: var(--role-user-border);
}

/* Profile card */
.profile-card {
    background: var(--surface-raised);
    border: 1px solid var(--border-divider);
    border-radius: var(--radius-lg);
    margin-bottom: var(--sp-5);
    overflow: hidden;
}

.profile-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-5);
    background: var(--surface-subtle);
    border-bottom: 1px solid var(--border-divider);
}

.profile-card__title {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.profile-card__title h1 {
    font-size: 20px;
}

.profile-card__details {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    padding: 0;
    gap: 0;
    background: var(--surface-raised);
}

.profile-card__field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    font-size: 14px;
    padding: var(--sp-4) var(--sp-5);
    background: var(--surface-raised);
    box-shadow: inset -1px -1px 0 var(--border-divider);
}

.profile-card__label {
    font-size: 12px;
    font-weight: 500;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Table cell utilities */
.cell-mono {
    font-family: var(--font-mono);
}

/* Table container */
.access-panel {
    background: var(--surface-raised);
    border: 1px solid var(--border-divider);
    border-radius: var(--radius-lg);
    margin: var(--sp-5) 0;
    overflow: hidden;
}

.access-panel__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--border-divider);
}

.access-panel__subtitle {
    font-size: 13px;
    color: var(--text-secondary);
    margin-top: var(--sp-1);
}

.access-panel__empty {
    padding: var(--sp-8) var(--sp-5);
    text-align: center;
    font-size: 14px;
    color: var(--text-secondary);
}

.access-panel__assign-form {
    padding: var(--sp-3) var(--sp-5);
    border-bottom: 1px solid var(--border-divider);
}

.access-panel__assign-form form {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

.access-panel__assign-form select,
.access-panel__assign-form input,
.access-panel__assign-form button {
    margin-bottom: 0;
    height: 36px;
    padding: 0 var(--sp-3);
}

.access-panel__assign-form input {
    flex: 1;
    min-width: 0;
}

.access-panel__assign-form select {
    width: auto;
    min-width: 140px;
    padding-right: var(--sp-8);
}

.access-panel__assign-form button {
    width: auto;
    flex: none;
    white-space: nowrap;
}

.access-row {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-5);
    border-bottom: 1px solid var(--border-divider);
}

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

.access-row__avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--primary-subtle);
    color: var(--color-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 600;
    flex-shrink: 0;
    text-transform: uppercase;
}

.access-row__avatar--inherited {
    background: var(--surface-subtle);
    color: var(--text-secondary);
}

.access-row__info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.access-row__name {
    font-weight: 500;
    font-size: 13px;
}

.access-row__email {
    font-size: 12px;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
}

.access-row__origin {
    font-size: 11px;
    color: var(--text-secondary);
}

.access-row__revoke {
    background: none;
    border: none;
    padding: var(--sp-1) var(--sp-2);
    color: var(--text-secondary);
    cursor: pointer;
    border-radius: var(--radius);
    font-size: 12px;
    line-height: 1;
}

.access-row__revoke:hover {
    background: var(--error-subtle);
    color: var(--color-error);
}

.access-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 7px;
    border-radius: var(--radius);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    border: 1px solid transparent;
    white-space: nowrap;
}

.access-badge--inherited {
    opacity: 0.55;
}

.access-badge--owner {
    background: var(--role-owner-bg);
    color: var(--role-owner);
    border-color: var(--role-owner-border);
}

.access-badge--admin {
    background: var(--role-admin-bg);
    color: var(--role-admin);
    border-color: var(--role-admin-border);
}

.access-badge--finance {
    background: var(--role-finance-bg);
    color: var(--role-finance);
    border-color: var(--role-finance-border);
}

.access-badge--billing {
    background: var(--role-billing-bg);
    color: var(--role-billing);
    border-color: var(--role-billing-border);
}

.access-badge--developer {
    background: var(--role-developer-bg);
    color: var(--role-developer);
    border-color: var(--role-developer-border);
}

.access-badge--operations {
    background: var(--role-operations-bg);
    color: var(--role-operations);
    border-color: var(--role-operations-border);
}

.access-badge--compliance {
    background: var(--role-compliance-bg);
    color: var(--role-compliance);
    border-color: var(--role-compliance-border);
}

.access-badge--account_manager {
    background: var(--role-account-manager-bg);
    color: var(--role-account-manager);
    border-color: var(--role-account-manager-border);
}

.access-badge--viewer {
    background: var(--role-viewer-bg);
    color: var(--role-viewer);
    border-color: var(--role-viewer-border);
}

@media (max-width: 768px) {

    .access-panel__assign-form,
    .access-panel__assign-form form {
        flex-direction: column;
        align-items: stretch;
    }

    .access-row {
        flex-wrap: wrap;
    }
}

/* Channels / Services panel */
.channels-panel {
    background: var(--surface-raised);
    border: 1px solid var(--border-divider);
    border-radius: var(--radius-lg);
    margin-top: var(--sp-5);
    overflow: hidden;
}

.channels-panel__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--sp-3) var(--sp-5);
    border-bottom: 1px solid var(--border-divider);
}

.channels-panel__title {
    font-weight: 600;
    font-size: 16px;
}

.channels-panel__subtitle {
    font-size: 13px;
    color: var(--text-secondary);
}

.channels-panel__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
}

.channel-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-5) var(--sp-4);
    background: var(--surface-raised);
    border: 1px solid var(--border-divider);
    border-radius: var(--radius-lg);
    text-align: center;
}

.channel-card--active {
    background: var(--primary-subtle);
    border-color: var(--color-primary);
}

.channel-card--inactive {
    background: var(--error-subtle);
}

.channel-card--blocked {
    opacity: 0.4;
}

.channel-card__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 10px;
    background: var(--surface-subtle);
    color: var(--text-secondary);
}

.channel-card--active .channel-card__icon {
    background: var(--primary-subtle);
    color: var(--color-primary);
}

.channel-card__info {
    text-align: center;
}

.channel-card__name {
    display: block;
    font-weight: 600;
    font-size: 14px;
}

.channel-card__status {
    display: block;
    font-size: 11px;
    color: var(--text-secondary);
    margin-top: 2px;
}

.channel-card__status--on {
    color: var(--color-success);
}

.channel-card__status--off {
    color: var(--text-secondary);
}

.channel-card__status--blocked {
    color: var(--color-error);
}

.channel-card__detail {
    display: block;
    font-size: 11px;
    color: var(--text-secondary);
    margin-top: 1px;
}

.channel-card__actions {
    margin-top: var(--sp-1);
}

/* Pagination */
.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-5);
    border-top: 1px solid var(--border-divider);
    font-size: 13px;
}

.pagination a {
    padding: var(--sp-1) var(--sp-3);
    border-radius: var(--radius);
    color: var(--text-secondary);
    transition:
        background var(--duration) var(--ease),
        color var(--duration) var(--ease);
}

.pagination a:hover {
    background: var(--state-hover-surface);
    color: var(--text-primary);
}

.pagination .active {
    padding: var(--sp-1) var(--sp-3);
    border-radius: var(--radius);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-weight: 600;
}

.pagination .disabled {
    padding: var(--sp-1) var(--sp-3);
    color: var(--text-muted);
}

.pagination .info {
    margin-left: auto;
    color: var(--text-secondary);
}

/* Danger zone */
.danger-zone {
    background: var(--error-subtle);
    border: 1px solid var(--border-error);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    margin-top: var(--sp-8);
}

.danger-zone h4 {
    color: var(--color-error);
}

.danger-zone__action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-4);
    margin-top: var(--sp-4);
    background: var(--surface-raised);
    border: 1px solid var(--border-error);
    border-radius: var(--radius);
}

.danger-zone__action p {
    font-size: 13px;
    color: var(--text-secondary);
    margin-top: var(--sp-1);
}

/* Forms */
.grid {
    display: flex;
    gap: var(--sp-4);
    align-items: start;
}

.grid > * {
    flex: 1;
    min-width: 0;
}

fieldset {
    border: none;
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

fieldset > legend {
    display: flex;
    width: 100%;
    flex-shrink: 0;
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    padding-bottom: var(--sp-2);
    margin-bottom: var(--sp-3);
    border-bottom: 1px solid var(--border-divider);
}

fieldset small {
    display: block;
}

fieldset label {
    margin-bottom: 0;
}

.input-group {
    display: flex;
    align-items: stretch;
}

.input-prefix {
    display: flex;
    align-items: center;
    padding: 0 var(--sp-3);
    background: var(--surface-subtle);
    border: 1px solid var(--input-border);
    border-right: none;
    border-radius: var(--radius) 0 0 var(--radius);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    white-space: nowrap;
}

.input-group input {
    border-radius: 0;
}

.input-prefix+input:last-child {
    border-radius: 0 var(--radius) var(--radius) 0;
}

.input-group > input:first-child {
    border-radius: var(--radius) 0 0 var(--radius);
}

.input-suffix {
    display: flex;
    align-items: center;
    padding: 0 var(--sp-3);
    background: var(--surface-subtle);
    border: 1px solid var(--input-border);
    border-left: none;
    border-radius: 0 var(--radius) var(--radius) 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    white-space: nowrap;
}

input[type="checkbox"] {
    width: auto;
    margin: 0;
}

.spinner {
    display: none;
    width: 14px;
    height: 14px;
    border: 2px solid var(--spinner-track);
    border-top-color: var(--spinner-fg);
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
}

/* Solo <button>. Un <a href> con aria-disabled sigue siendo navegable con
   Enter —pointer-events no alcanza al teclado—, así que pintarlo de bloqueado
   sería una promesa que el CSS no puede cumplir. Los enlaces que el repo marca
   así (nav__seg-btn del selector de idioma y tema) llevan tabindex="-1", que es
   lo que de verdad los saca del paso, y tienen su propio estilo. */
button[disabled]:not([class*="jp-"]),
button:disabled:not([class*="jp-"]),
.btn[aria-disabled="true"] {
    /* Tokens, no opacidad: el book §06 fija el bloqueado como
       surface-disabled + text-disabled + border-disabled, y la página 12 lo dice
       aún más corto — «patrón disabled, nunca opacidad».
       opacity: .4 lavaba el color contra lo que hubiera detrás, así que el
       mismo botón se veía distinto sobre una card que sobre el fondo, y en dark
       quedaba casi invisible. Con los tokens el estado tiene un color propio.
       El book lo exime de contraste, pero exige que nunca sea el único
       indicador: por eso se mantiene cursor y pointer-events. */
    background-color: var(--surface-disabled);
    background-image: none;
    color: var(--text-disabled);
    border-color: var(--border-disabled);
    cursor: not-allowed;
    pointer-events: none;
}

button[disabled] .spinner {
    display: inline-block;
}

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

/* Dialog */
dialog {
    border: none;
    background: transparent;
    padding: 0;
    width: min(640px, calc(100vw - var(--sp-8)));
    min-width: min(420px, 100vw);
    border-radius: var(--radius-lg);
    overflow: visible;
    margin: auto;
}

dialog[open]~*,
body:has(dialog[open]) {
    overflow: hidden;
}

dialog::backdrop {
    background: var(--scrim);
}

dialog > article {
    padding: 0;
    /* Tope absoluto ademas del relativo: sin el, un cuerpo alto estira el
       dialogo hasta rozar el viewport y deja de leerse como un modal. */
    max-height: min(760px, calc(100vh - var(--sp-16)));
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

dialog > article header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-shrink: 0;
    padding: var(--sp-4) var(--sp-5);
    background: var(--surface-subtle);
    border-bottom: 1px solid var(--border-divider);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    margin: 0;
}

dialog > article header h3,
dialog > article header h2 {
    font-size: 16px;
}

dialog .dialog-close {
    width: 28px;
    height: 28px;
    padding: 0;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-secondary);
    font-size: 16px;
    line-height: 1;
    border: 1px solid var(--border-divider);
    flex-shrink: 0;
}

dialog .dialog-close:hover {
    background: var(--error-subtle);
    color: var(--color-error);
    border-color: var(--border-error);
}

/* El cuerpo del diálogo: el hermano del header que scrollea. Es el <form>
   cuando el diálogo no es más que un formulario, y .dialog-body cuando el
   cuerpo agrupa varios bloques.

   Hijo directo a propósito. Con combinador descendiente, cualquier formulario
   del contenido se volvía un segundo contenedor de scroll y los dos se repartían
   el alto: en el modal de configuración de servicio el cuerpo real quedaba en
   32px de alto con 332px dentro. */
dialog > article > form,
dialog > article > .dialog-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--sp-4) var(--sp-5);
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

/* La maquetación de campos vale igual si el form es el cuerpo o si vive dentro
   de uno. Lo que no hereda es el scroll: ese le toca al cuerpo, y sólo a él. */
dialog > article > .dialog-body > form {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

dialog > article > form label,
dialog > article > .dialog-body > form label {
    margin-bottom: 0;
}

dialog > article > form > button[type="submit"]:not([disabled]),
dialog > article > .dialog-body > form > button[type="submit"]:not([disabled]) {
    width: 100%;
    margin-top: var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--radius);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

dialog > article > form > button[type="submit"]:not([disabled]):hover,
dialog > article > .dialog-body > form > button[type="submit"]:not([disabled]):hover {
    /* Velo, no reemplazo: este botón se había quedado fuera del cambio general
       y seguía saltando a --link-hover como el resto antes. */
    --_overlay: light-dark(var(--state-darken-hover), var(--state-lighten-hover));
}

/* ── 7. Dashboard ──────────────────────────────────────────── */

.dash-kpi {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--sp-4);
    margin: var(--sp-5) 0;
}

.dash-kpi article {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    height: 100%;
}

.dash-kpi small {
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}


.dash-section {
    margin: var(--sp-6) 0;
}

.dash-section__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-bottom: var(--sp-5);
}

.filter-bar {
    display: flex;
    align-items: flex-end;
    gap: var(--sp-2);
    flex-wrap: wrap;
    margin-bottom: var(--sp-4);
}

.access-panel > .filter-bar {
    margin: 0;
    padding: var(--sp-3) var(--sp-5);
    border-bottom: 1px solid var(--border-divider);
}

.filter-bar > select,
.filter-bar > input {
    width: auto;
    min-width: 120px;
    height: 36px;
    margin: 0;
}

.filter-bar > select {
    padding-right: var(--sp-8);
}

.filter-bar__field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
}

.filter-bar__field span {
    font-size: 12px;
    font-weight: 500;
    color: var(--text-secondary);
}

.filter-bar__field input {
    width: auto;
    min-width: 140px;
    height: 36px;
}

.filter-bar > label {
    flex: 1;
    min-width: 140px;
    margin-bottom: 0;
}

.filter-bar button,
.filter-bar [role="button"],
.filter-bar .btn,
.filter-bar a.outline {
    height: 36px;
}

.filter-bar__actions {
    display: flex;
    gap: var(--sp-2);
}

.filter-bar > label > select,
.filter-bar > label > input {
    height: 36px;
}

.filter-bar__mobile-toggle {
    display: none;
}

@media (max-width: 768px) {
    .filter-bar {
        flex-direction: column;
    }

    .filter-bar > label,
    .filter-bar > select,
    .filter-bar > input,
    .filter-bar__field,
    .filter-bar__actions {
        width: 100%;
    }

    .filter-bar__mobile-toggle {
        display: flex;
        align-items: center;
        gap: var(--sp-2);
        font-size: 13px;
        font-weight: 500;
        color: var(--color-primary);
        cursor: pointer;
        margin-bottom: var(--sp-3);
    }

    .filter-bar__mobile-toggle svg {
        width: 16px;
        height: 16px;
        stroke: var(--color-primary);
    }
}

.dash-charts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--sp-4);
    margin: var(--sp-5) 0;
}

.dash-charts article {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.dash-charts article > div {
    flex: 1;
    min-height: 0;
}

.dash-activity header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
}

.dash-activity__totals {
    display: flex;
    gap: var(--sp-5);
}

.dash-activity__totals span {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: 13px;
}

/* ── 8. Auth Page ─────────────────────────────────────────── */

.auth-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: var(--sp-4);
}

.auth-page main {
    width: 100%;
    max-width: 400px;
}

/* Reset article header: base applies negative margin + bg + border */
.auth-page article header {
    margin: 0 0 var(--sp-5);
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
}

/* Logo theme toggle — already defined in §4 Navigation */

/* Auth preferences (lang/theme toggles) */
.auth-prefs {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-3);
    margin-top: var(--sp-6);
}

.auth-prefs__group {
    display: inline-flex;
    align-items: center;
    background: var(--surface-raised);
    border: 1px solid var(--border-divider);
    border-radius: var(--radius-full);
    overflow: hidden;
}

.auth-prefs__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-1) var(--sp-3);
    font-size: 11px;
    color: var(--text-secondary);
    transition:
        background var(--duration) var(--ease),
        color var(--duration) var(--ease);
}

.auth-prefs__btn:hover {
    background: var(--state-hover-surface);
    color: var(--text-primary);
}

.auth-prefs__btn--active {
    background: var(--surface-subtle);
    color: var(--text-primary);
    font-weight: 500;
}

.auth-prefs__icon {
    width: 14px;
    height: 14px;
}

/* ── Range toggle (smart links stats) ──────────────────────────────────────── */
.range-toggle {
    display: inline-flex;
    gap: .2rem;
    border: 1px solid var(--border-divider);
    border-radius: .5rem;
    padding: .15rem;
}

.range-toggle button:not([disabled]) {
    background: transparent;
    border: 0;
    padding: .3rem .65rem;
    border-radius: .35rem;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: .8125rem;
    font-weight: 500;
    line-height: 1.2;
    transition: background .12s, color .12s;
}

.range-toggle button[aria-pressed="true"]:not([disabled]) {
    background: var(--surface-subtle, #f0f0f0);
    color: var(--text-primary);
}

.range-toggle button:hover:not([aria-pressed="true"]) {
    background: var(--surface-subtle, #f0f0f0);
    color: var(--text-primary);
}

/* ── Chip / view-toggle buttons ─────────────────────────────────────────── */
.chip {
    display: inline-flex;
    align-items: center;
    background: transparent;
    border: 1px solid var(--border-divider, #d4d4d8);
    border-radius: var(--radius);
    padding: .2rem .65rem;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
}

.chip--sm {
    padding: .15rem .5rem;
    font-size: .75rem;
}

/* --primary was never defined by this theme (light or dark) — every chip
   marked active fell back to the hardcoded #6366f1 instead of the theme's
   real --accent, wrong in light mode and unreadable in dark. --accent is
   the same token dialog > article > form > button[type="submit"] already uses
   for its own "active" affordance above. */
.chip[aria-pressed="true"],
.chip[aria-current="true"],
.chip:has(> input:checked) {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-on-primary);
}

.chip:hover:not([aria-pressed="true"]):not([aria-current="true"]):not(:has(> input:checked)) {
    background: var(--surface-subtle, #f0f0f0);
    border-color: var(--border-divider, #d4d4d8);
    color: var(--text-primary);
}

/* ── SMS skeleton loading ───────────────────────────────────────────────── */
@keyframes skeleton-pulse {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.5;
    }
}

.skeleton {
    background: var(--surface-subtle);
    border-radius: 6px;
    animation: skeleton-pulse 1.4s ease-in-out infinite;
}

.skeleton--line {
    height: 12px;
    margin: 8px 0;
}

.skeleton--title {
    height: 20px;
    width: 40%;
    margin-bottom: 16px;
}

.skeleton--card {
    height: 120px;
}

/* Generic visibility utility — the wizard JS (email + WhatsApp) toggles
   sections by mutating classList instead of inline style="display:none",
   which needed this one rule to exist somewhere shared. */
.is-hidden {
    display: none !important;
}
