/* ─────────────────────────────────────────────────────────────────────────
   Portal shared styles — admin / merchant / agent layouts
   Design language: dark-first, one colour identity per portal
   (admin = violet, merchant = emerald, agent = amber). Light mode is an
   adapted lighter counterpart of the same system so the theme toggle keeps
   working. Portal identity is set via <html data-portal="admin|merchant|agent">.
   ───────────────────────────────────────────────────────────────────────── */

/* ── Theme tokens — light (default) ──────────────────────────────────── */
:root {
    --bg-page: #f3f4f6;
    --bg-surface: #ffffff;
    --bg-surface-alt: #f9fafb;
    --bg-surface-hover: #fafafa;
    --bg-subtle: #f3f4f6;
    --border: #e5e7eb;
    --border-strong: #d1d5db;
    --divider: #eef0f3;
    --text-primary: #111827;
    --text-secondary: #374151;
    /* muted/faint nudged darker for WCAG AA small text (u1-kit, 2026-10-16): muted was #6b7280
       (4.39:1 on --bg-page), faint was #9ca3af (2.5:1 on white). Now muted ≥ 5.5:1 and faint
       ≥ 4.5:1 on every light surface (surface/alt/subtle/page). */
    --text-muted: #5b6270;
    --text-faint: #687080;
    --text-disabled: #d1d5db;
    --accent: #6D43F5;
    --accent-strong: #5a32d9;
    --accent-deep: #4c2ba8;
    --accent-tint: #f1edfd;
    --accent-solid: #6D43F5;
    --accent-ring: rgba(109,67,245,.22);
    --danger: #dc2626; /* was #ef4444 (3.8:1 as error text / under white button text); now 4.8:1 */
    --danger-bg: #fee2e2;
    --danger-text: #991b1b;
    --danger-border: #fca5a5;
    --success-bg: #d1fae5;
    --success-text: #065f46;
    --success-border: #6ee7b7;
    --shadow-sm: 0 1px 4px rgba(0,0,0,.08);
    --shadow-md: 0 20px 60px rgba(0,0,0,.2);
    --icon-filter: none;
    color-scheme: light; /* native scrollbars and form controls follow the theme */
    --warning-bg: #fffbeb;
    --warning-bg-hover: #fef3c7;
    --warning-text: #92400e;
    --warning-text-soft: #b45309;
    --warning-border: #fde68a;
    --warning-strong-bg: #fbbf24; /* solid banner, e.g. impersonation */
    --warning-strong-text: #111827;
    --warning-strong-border: #d97706;
    --warning-strong-icon: #92400e;
    --info-bg: #e0f2fe;
    --info-text: #0c4a6e;
    --highlight-bg: #e0e7ff;
    --highlight-text: #3730a3;
    --highlight-border: #c7d2fe;
    --orange-bg: #ffedd5;
    --orange-text: #9a3412;
    --backdrop-dim: transparent;

    /* Kit tokens (u1-kit) — focus, links, elevation, overlays, motion. Dark values below. */
    --focus-ring: 0 0 0 3px var(--accent-ring);   /* soft halo around a focused field */
    --focus-outline: 2px solid var(--accent);     /* keyboard focus on buttons / links / controls */
    --link: var(--accent);                        /* AA link colour (portal blocks override) */
    --danger-solid: #dc2626;                      /* solid danger button fill under white text */
    --info-border: #bae6fd;
    --shadow-xs: 0 1px 2px rgba(16,24,40,.06);
    --shadow-lg: 0 12px 32px rgba(16,24,40,.14), 0 2px 6px rgba(16,24,40,.06);
    --overlay-bg: rgba(15,17,21,.45);
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235b6270' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    --ease-out: cubic-bezier(.2,.8,.2,1);
    --dur-fast: .12s;
    --dur: .18s;

    /* Semantic — identical in every portal/theme */
    --series-bot: #7C4DFF;
    --series-bot-2: #5E2FDE;
    --series-human: #E08A2B;
    --success: #0EA36F;

    /* Portal switcher dots — identical in every portal/theme */
    --dot-admin: #8B6CFF;
    --dot-merchant: #10B981;
    --dot-agent: #F59E0B;

    /* Radius + spacing scale */
    --r-sm: 6px;  --r-md: 9px;  --r-lg: 12px;  --r-xl: 16px;  --r-2xl: 18px;  --r-pill: 999px;
    --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 20px; --s-6: 24px; --s-8: 32px; --s-10: 40px;

    /* Type */
    --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --font-mono: 'Geist Mono', 'SF Mono', Monaco, Inconsolata, monospace;

    /* No glow in light mode — kept calm/flat; dark mode gets the portal glow (see 2.3) */
    --glow-1: transparent;
    --glow-2: transparent;
    --dot-grid: transparent;

    /* Light-mode portal identity (defaults to admin/violet; overridden below) */
    --accent-text: #4c2ba8;
    --accent-soft: #f1edfd;
    --logo-gradient: 135deg, #6D43F5, #22B8CF;
}

/* ── Theme tokens — dark ──────────────────────────────────────────────── */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg-page: #08070E;
        --bg-surface: #15131f;
        --bg-surface-alt: #1b1828;
        --bg-surface-hover: #1f1c2c;
        --bg-subtle: #181522;
        --border: rgba(255,255,255,.08);
        --border-strong: rgba(255,255,255,.14);
        --divider: rgba(255,255,255,.06);
        --text-primary: #ECEAF5;
        --text-secondary: #C9C5D8;
        --text-muted: #A39FB5;
        --text-faint: #8C88A0;
        --text-disabled: #55506A;
        --accent: #8B6CFF;
        --accent-strong: #7454E0;
        --accent-deep: #B9A6FF;
        --accent-tint: rgba(139,108,255,.16);
        --accent-solid: #8B6CFF;
        --accent-ring: rgba(185,166,255,.40);
        --danger: #F06A6A;
        --danger-bg: rgba(240,106,106,.14);
        --danger-text: #FCA5A5;
        --danger-border: rgba(240,106,106,.35);
        --success-bg: rgba(14,163,111,.16);
        --success-text: #6EE7B7;
        --success-border: rgba(61,224,154,.35);
        --shadow-sm: 0 1px 4px rgba(0,0,0,.45);
        --shadow-md: 0 20px 60px rgba(0,0,0,.65);
        --icon-filter: invert(1);
        color-scheme: dark;
        --warning-bg: #1A1510;
        --warning-bg-hover: #241c12;
        --warning-text: #fcd34d;
        --warning-text-soft: #e8b84b;
        --warning-border: #4a3a18;
        --warning-strong-bg: #3a2f14;
        --warning-strong-text: #fcd34d;
        --warning-strong-border: #5a4718;
        --warning-strong-icon: #fbbf24;
        --info-bg: #0f2635;
        --info-text: #7dd3fc;
        --highlight-bg: var(--accent-tint);
        --highlight-text: var(--accent-deep);
        --highlight-border: var(--accent-ring);
        --orange-bg: rgba(245,158,11,.16);
        --orange-text: #fdba74;
        --backdrop-dim: rgba(5,4,9,.72);

        /* Kit tokens (u1-kit) — dark */
        --link: var(--accent);
        --danger-solid: #c93b3b; /* white text 5.0:1 (the #F06A6A text red is only 3.0:1 under white) */
        --info-border: rgba(125,211,252,.28);
        --shadow-xs: 0 1px 2px rgba(0,0,0,.4);
        --shadow-lg: 0 12px 32px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.35);
        --overlay-bg: rgba(3,2,8,.62);
        --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a39fb5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");

        --accent-text: #B9A6FF;
        --accent-soft: rgba(139,108,255,.22);
        --logo-gradient: 135deg, #6D43F5, #22B8CF;

        /* Dark-only: portal glow + dot-grid body treatment (2.3) */
        --glow-1: rgba(109,67,245,.38);
        --glow-2: rgba(34,184,207,.20);
        --dot-grid: rgba(255,255,255,.05);
    }
}
:root[data-theme="dark"] {
    --bg-page: #08070E;
    --bg-surface: #15131f;
    --bg-surface-alt: #1b1828;
    --bg-surface-hover: #1f1c2c;
    --bg-subtle: #181522;
    --border: rgba(255,255,255,.08);
    --border-strong: rgba(255,255,255,.14);
    --divider: rgba(255,255,255,.06);
    --text-primary: #ECEAF5;
    --text-secondary: #C9C5D8;
    --text-muted: #A39FB5;
    --text-faint: #8C88A0;
    --text-disabled: #55506A;
    --accent: #8B6CFF;
    --accent-strong: #7454E0;
    --accent-deep: #B9A6FF;
    --accent-tint: rgba(139,108,255,.16);
    --accent-solid: #8B6CFF;
    --accent-ring: rgba(185,166,255,.40);
    --danger: #F06A6A;
    --danger-bg: rgba(240,106,106,.14);
    --danger-text: #FCA5A5;
    --danger-border: rgba(240,106,106,.35);
    --success-bg: rgba(14,163,111,.16);
    --success-text: #6EE7B7;
    --success-border: rgba(61,224,154,.35);
    --shadow-sm: 0 1px 4px rgba(0,0,0,.45);
    --shadow-md: 0 20px 60px rgba(0,0,0,.65);
    --icon-filter: invert(1);
    color-scheme: dark;
    --warning-bg: #1A1510;
    --warning-bg-hover: #241c12;
    --warning-text: #fcd34d;
    --warning-text-soft: #e8b84b;
    --warning-border: #4a3a18;
    --warning-strong-bg: #3a2f14;
    --warning-strong-text: #fcd34d;
    --warning-strong-border: #5a4718;
    --warning-strong-icon: #fbbf24;
    --info-bg: #0f2635;
    --info-text: #7dd3fc;
    --highlight-bg: var(--accent-tint);
    --highlight-text: var(--accent-deep);
    --highlight-border: var(--accent-ring);
    --orange-bg: rgba(245,158,11,.16);
    --orange-text: #fdba74;
    --backdrop-dim: rgba(5,4,9,.72);

    /* Kit tokens (u1-kit) — dark (same values as the media-query block above) */
    --link: var(--accent);
    --danger-solid: #c93b3b;
    --info-border: rgba(125,211,252,.28);
    --shadow-xs: 0 1px 2px rgba(0,0,0,.4);
    --shadow-lg: 0 12px 32px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.35);
    --overlay-bg: rgba(3,2,8,.62);
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a39fb5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");

    --accent-text: #B9A6FF;
    --accent-soft: rgba(139,108,255,.22);
    --logo-gradient: 135deg, #6D43F5, #22B8CF;

    --glow-1: rgba(109,67,245,.38);
    --glow-2: rgba(34,184,207,.20);
    --dot-grid: rgba(255,255,255,.05);
}

/* ── Portal identity — light mode ────────────────────────────────────── */
[data-portal="merchant"] {
    --accent: #0E9F6E; --accent-strong: #0b8a5f; --accent-deep: #047857;
    --accent-tint: #e9f8f1; --accent-solid: #0E9F6E; --accent-ring: rgba(16,185,129,.22);
    --accent-text: #047857; --accent-soft: #e9f8f1;
    --logo-gradient: 135deg, #10B981, #0E7490;
    --link: #047857; /* #0E9F6E link text is 3.4:1 on white; this is 5.5:1 (dark blocks reset --link) */
}
[data-portal="agent"] {
    --accent: #D97706; --accent-strong: #b96404; --accent-deep: #92400e;
    --accent-tint: #fdf1e0; --accent-solid: #D97706; --accent-ring: rgba(245,158,11,.22);
    --accent-text: #92400e; --accent-soft: #fdf1e0;
    --logo-gradient: 135deg, #F59E0B, #E1555F;
    --link: #b45309; /* #D97706 link text is 3.2:1 on white; this is 5.0:1 */
}

/* ── Portal identity — dark mode (overrides the dark block above) ────── */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"])[data-portal="admin"] {
        --bg-page: #08070E; --glow-1: rgba(109,67,245,.38); --glow-2: rgba(34,184,207,.20);
        --accent: #8B6CFF; --accent-strong: #7454E0; --accent-deep: #B9A6FF;
        --accent-tint: rgba(139,108,255,.16); --accent-solid: #8B6CFF; --accent-ring: rgba(185,166,255,.40);
        --accent-text: #B9A6FF; --accent-soft: rgba(139,108,255,.22);
        --logo-gradient: 135deg, #6D43F5, #22B8CF;
    }
    :root:not([data-theme="light"])[data-portal="merchant"] {
        --bg-page: #05110E; --glow-1: rgba(16,185,129,.32); --glow-2: rgba(45,212,191,.16);
        --accent: #10B981; --accent-strong: #0EA371; --accent-deep: #6EE7B7;
        --accent-tint: rgba(16,185,129,.16); --accent-solid: #10B981; --accent-ring: rgba(110,231,183,.40);
        --accent-text: #6EE7B7; --accent-soft: rgba(16,185,129,.22);
        --logo-gradient: 135deg, #10B981, #0E7490;
        --text-primary: #E8F2EE; --text-muted: #9DB8AE; --text-faint: #86A096;
    /* u1-kit: emerald-neutral surfaces instead of the violet-tinted defaults (all text tokens ≥ 5.7:1) */
    --bg-surface: #0f1916; --bg-surface-alt: #141f1b; --bg-surface-hover: #17231f; --bg-subtle: #121c18;
    --text-secondary: #C4D3CC; --text-disabled: #4d5c56;
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239db8ae' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    }
    :root:not([data-theme="light"])[data-portal="agent"] {
        --bg-page: #120D08; --glow-1: rgba(245,158,11,.30); --glow-2: rgba(251,113,133,.14);
        --accent: #F59E0B; --accent-strong: #DB9009; --accent-deep: #FBBF77;
        --accent-tint: rgba(245,158,11,.14); --accent-solid: #F59E0B; --accent-ring: rgba(251,191,119,.40);
        --accent-text: #FBBF77; --accent-soft: rgba(245,158,11,.20);
        --logo-gradient: 135deg, #F59E0B, #E1555F;
        --text-primary: #F3ECE4; --text-muted: #BFAF9E; --text-faint: #A8998A;
    /* u1-kit: warm amber-neutral surfaces instead of the violet-tinted defaults (all text tokens ≥ 5.5:1) */
    --bg-surface: #1a1510; --bg-surface-alt: #201a14; --bg-surface-hover: #241d16; --bg-subtle: #1d1712;
    --text-secondary: #D9CDBF; --text-disabled: #5c5248;
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23bfaf9e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    }
}
:root[data-theme="dark"][data-portal="admin"] {
    --bg-page: #08070E; --glow-1: rgba(109,67,245,.38); --glow-2: rgba(34,184,207,.20);
    --accent: #8B6CFF; --accent-strong: #7454E0; --accent-deep: #B9A6FF;
    --accent-tint: rgba(139,108,255,.16); --accent-solid: #8B6CFF; --accent-ring: rgba(185,166,255,.40);
    --accent-text: #B9A6FF; --accent-soft: rgba(139,108,255,.22);
    --logo-gradient: 135deg, #6D43F5, #22B8CF;
}
:root[data-theme="dark"][data-portal="merchant"] {
    --bg-page: #05110E; --glow-1: rgba(16,185,129,.32); --glow-2: rgba(45,212,191,.16);
    --accent: #10B981; --accent-strong: #0EA371; --accent-deep: #6EE7B7;
    --accent-tint: rgba(16,185,129,.16); --accent-solid: #10B981; --accent-ring: rgba(110,231,183,.40);
    --accent-text: #6EE7B7; --accent-soft: rgba(16,185,129,.22);
    --logo-gradient: 135deg, #10B981, #0E7490;
    --text-primary: #E8F2EE; --text-muted: #9DB8AE; --text-faint: #86A096;
    /* u1-kit: emerald-neutral surfaces instead of the violet-tinted defaults (all text tokens ≥ 5.7:1) */
    --bg-surface: #0f1916; --bg-surface-alt: #141f1b; --bg-surface-hover: #17231f; --bg-subtle: #121c18;
    --text-secondary: #C4D3CC; --text-disabled: #4d5c56;
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239db8ae' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
:root[data-theme="dark"][data-portal="agent"] {
    --bg-page: #120D08; --glow-1: rgba(245,158,11,.30); --glow-2: rgba(251,113,133,.14);
    --accent: #F59E0B; --accent-strong: #DB9009; --accent-deep: #FBBF77;
    --accent-tint: rgba(245,158,11,.14); --accent-solid: #F59E0B; --accent-ring: rgba(251,191,119,.40);
    --accent-text: #FBBF77; --accent-soft: rgba(245,158,11,.20);
    --logo-gradient: 135deg, #F59E0B, #E1555F;
    --text-primary: #F3ECE4; --text-muted: #BFAF9E; --text-faint: #A8998A;
    /* u1-kit: warm amber-neutral surfaces instead of the violet-tinted defaults (all text tokens ≥ 5.5:1) */
    --bg-surface: #1a1510; --bg-surface-alt: #201a14; --bg-surface-hover: #241d16; --bg-subtle: #1d1712;
    --text-secondary: #D9CDBF; --text-disabled: #5c5248;
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23bfaf9e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

/* ── White-label brand identity (public pages, e.g. the landing page) ───
   Same mechanism as portal identity above, keyed by [data-brand] instead of
   [data-portal], so a white-labeled domain doesn't just swap its logo image
   while reusing gotalk's own violet-teal everywhere else. cgaichat.online and
   ocgaichat.online currently share one visual identity (same logo/icon
   assets), hence one [data-brand="cgaichat"] block for both. ───────────── */
[data-brand="cgaichat"] {
    --accent: #2563EB; --accent-strong: #1D4ED8; --accent-deep: #1E3A8A;
    --accent-tint: #eaf1fe; --accent-solid: #2563EB; --accent-ring: rgba(37,99,235,.22);
    --accent-text: #1D4ED8; --accent-soft: #eaf1fe;
    --logo-gradient: 135deg, #2563EB, #06B6D4;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"])[data-brand="cgaichat"] {
        --glow-1: rgba(37,99,235,.36); --glow-2: rgba(6,182,212,.20);
        --accent: #5B8DEF; --accent-strong: #4A7FE0; --accent-deep: #A9C7FF;
        --accent-tint: rgba(91,141,239,.16); --accent-solid: #5B8DEF; --accent-ring: rgba(169,199,255,.40);
        --accent-text: #A9C7FF; --accent-soft: rgba(91,141,239,.22);
        --logo-gradient: 135deg, #2563EB, #06B6D4;
    }
}
:root[data-theme="dark"][data-brand="cgaichat"] {
    --glow-1: rgba(37,99,235,.36); --glow-2: rgba(6,182,212,.20);
    --accent: #5B8DEF; --accent-strong: #4A7FE0; --accent-deep: #A9C7FF;
    --accent-tint: rgba(91,141,239,.16); --accent-solid: #5B8DEF; --accent-ring: rgba(169,199,255,.40);
    --accent-text: #A9C7FF; --accent-soft: rgba(91,141,239,.22);
    --logo-gradient: 135deg, #2563EB, #06B6D4;
}

/* Reset */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
    font-family: var(--font-sans);
    background-color: var(--bg-page);
    background-image:
        radial-gradient(ellipse 60% 40% at 30% -5%, var(--glow-1), transparent 70%),
        radial-gradient(ellipse 45% 35% at 95% 0%,  var(--glow-2), transparent 70%),
        radial-gradient(var(--dot-grid) 1px, transparent 1px);
    background-size: 100% 100%, 100% 100%, 22px 22px;
    background-attachment: fixed;
    color: var(--text-primary);
    font-size: 14px;
    display: flex;
    flex-direction: row;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    accent-color: var(--accent); /* native checkboxes / radios / range / progress take the portal colour */
}

/* Keyboard focus ring for every interactive element. :where() keeps it at zero specificity, so any
   component or page rule (including an explicit `outline: none` with its own ring) still wins. */
:where(a, button, summary, select, [role="button"], [role="tab"], [role="menuitem"], [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: var(--focus-outline); outline-offset: 2px;
}
::selection { background: color-mix(in srgb, var(--accent) 24%, transparent); }

/* Reduced motion: keep state changes, drop the movement (one switch for every page/component). */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important; animation-iteration-count: 1 !important;
        transition-duration: .01ms !important; scroll-behavior: auto !important;
    }
}

/* ── App shell ────────────────────────────────────────────────────────── */
/* Geometry shared by the three portals (PortalShell.vue): containers sit on a 12px gutter,
   their content (nav icons, section labels, footer rows, avatar) on a 22px line. */
.app-sidebar {
    width: 240px;
    flex-shrink: 0;
    background: var(--bg-surface);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Skip link (first focusable element of every portal page) */
.skip-link {
    position: fixed; top: 8px; left: 8px; z-index: 1100;
    padding: 8px 14px; border-radius: var(--r-md);
    background: var(--bg-surface); color: var(--text-primary); border: 1px solid var(--accent-ring);
    font-size: 13px; font-weight: 600; text-decoration: none;
    opacity: 0; pointer-events: none; transform: translateY(-200%); transition: transform .12s ease, opacity .12s ease;
}
.skip-link:focus, .skip-link:focus-visible {
    opacity: 1; pointer-events: auto; transform: none; box-shadow: var(--shadow-md);
    outline: 2px solid var(--accent); outline-offset: 2px; text-decoration: none;
}
@media (prefers-reduced-motion: reduce) { .skip-link { transition: none; } }

/* Sidebar head: workspace button (+ merchant code chip) and, in the mobile drawer, a close button */
.sidebar-head { display: flex; align-items: flex-start; gap: 6px; padding: 12px 12px 6px; flex-shrink: 0; }
.sidebar-head-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.sidebar-close {
    display: none; flex-shrink: 0; width: 36px; height: 36px; margin-top: 7px;
    align-items: center; justify-content: center; padding: 0;
    background: transparent; border: 1px solid transparent; border-radius: var(--r-md);
    color: var(--text-muted); cursor: pointer; transition: background .12s, color .12s;
}
.sidebar-close:hover { background: color-mix(in srgb, var(--text-primary) 6%, transparent); color: var(--text-primary); }
.sidebar-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sidebar-close svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

/* Workspace button: logo tile + name + mono eyebrow subtitle (spec §3.1.1) */
.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    background: var(--bg-surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    color: var(--text-primary);
    min-width: 0;
}
.sidebar-brand-logo {
    width: 32px; height: 32px; border-radius: var(--r-md);
    background: linear-gradient(var(--logo-gradient));
    box-shadow: 0 0 18px color-mix(in srgb, var(--accent) 35%, transparent);
    display: flex; align-items: center; justify-content: center;
    padding: 5px; flex-shrink: 0;
}
.sidebar-brand-logo img { width: 100%; height: 100%; object-fit: contain; display: block; filter: brightness(0) invert(1); }
.sidebar-brand-text { overflow: hidden; min-width: 0; flex: 1; }
.sidebar-brand-name { font-size: 14px; font-weight: 600; letter-spacing: -.2px; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-brand-sub  {
    font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: .07em; text-transform: uppercase;
    line-height: 1.4; color: var(--text-faint); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Merchant code chip under the workspace button (MerchantLayout.vue) — click to copy */
.sidebar-slug {
    display: flex; align-items: center; gap: 8px; width: 100%; min-height: 28px; padding: 4px 10px;
    background: transparent; border: 1px dashed var(--border-strong); border-radius: var(--r-md);
    color: var(--text-muted); font: inherit; text-align: left; cursor: pointer;
    transition: border-color .12s, color .12s, background .12s;
}
.sidebar-slug:hover { border-color: var(--accent-ring); color: var(--text-primary); background: var(--bg-surface-alt); }
.sidebar-slug:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sidebar-slug-label { font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .07em; text-transform: uppercase; color: var(--text-faint); flex-shrink: 0; }
.sidebar-slug code {
    flex: 1; min-width: 0; font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .02em; color: inherit;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-slug svg { width: 13px; height: 13px; flex-shrink: 0; color: var(--text-faint); }
.sidebar-slug.copied, .sidebar-slug.copied svg { color: var(--success); border-color: color-mix(in srgb, var(--success) 45%, transparent); }

/* Nav. min-height:0 lets the item list scroll on short screens while the head and footer stay. */
.sidebar-nav { flex: 1 1 auto; min-height: 96px; padding: 12px 12px 14px; overflow-y: auto; position: relative; }

/* SidebarNav.vue's shared sliding active-item indicator — JS measures the active <a>/<Link>'s
   offsetTop/offsetHeight and sets transform/height here, so it visibly travels between items
   on navigation instead of a new bar just appearing on the new item. left:12px matches
   .sidebar-nav's own padding, so the bar sits on each item's left edge. */
.nav-active-bar {
    position: absolute; left: 12px; width: 3px; top: 0; height: 0;
    background: var(--accent); border-radius: 0 3px 3px 0;
    transition: transform .2s cubic-bezier(.4,0,.2,1), height .15s ease, opacity .15s ease;
    opacity: 0; pointer-events: none;
    /* Without this, the nav items (each `position:relative`, coming later in the DOM) paint
       over the bar despite neither side setting a z-index — same-stacking-context elements
       without one just paint in DOM order, and the bar is the first child. */
    z-index: 1;
}
@media (prefers-reduced-motion: reduce) {
    .nav-active-bar { transition: opacity .15s ease; }
}

.nav-group + .nav-group { margin-top: 16px; }
.nav-section {
    padding: 0 10px 6px;
    font-family: var(--font-mono);
    font-size: 10.5px; font-weight: 500; line-height: 1.4;
    text-transform: uppercase; letter-spacing: .07em;
    color: var(--text-faint);
    overflow-wrap: anywhere;
}

/* Scripts without letter case: tracking only spreads their glyphs apart (Thai, Burmese, CJK…) */
:is(:lang(th), :lang(lo), :lang(km), :lang(my), :lang(zh), :lang(ja), :lang(ko), :lang(ar), :lang(fa), :lang(ur), :lang(he),
    :lang(hi), :lang(mr), :lang(ne), :lang(bn), :lang(gu), :lang(pa), :lang(ta), :lang(te), :lang(ml), :lang(si), :lang(ka),
    :lang(hy), :lang(am)) :is(.nav-section, .sidebar-brand-sub, .sidebar-slug-label) { letter-spacing: 0; }

.nav-item {
    display: flex; align-items: center; gap: 10px;
    min-height: 36px; padding: 7px 10px;
    font-size: 13.5px; font-weight: 500; line-height: 1.35; color: var(--text-secondary);
    text-decoration: none; border-radius: var(--r-md);
    transition: color .18s ease;
    position: relative;
}
.nav-item + .nav-item { margin-top: 2px; }
/* A flat background swap reads as dated — instead, a soft accent-colored glow sweeps in
   from the left (same direction/feel as .active's own gradient below, so hover reads as
   "warming up toward active" rather than an unrelated effect) and the icon gets a light
   lift. Pseudo-element (not `background` directly) so it can transform independently of
   the item's own box and overshoot slightly on the way in for a touch of bounce. */
.nav-item::before {
    content: ''; position: absolute; inset: 0; border-radius: inherit;
    background: linear-gradient(90deg, var(--accent-soft), transparent 80%);
    opacity: 0; transform: translateX(-6px) scaleX(.97); transform-origin: left center;
    transition: opacity .22s ease, transform .3s cubic-bezier(.22, 1, .36, 1);
    pointer-events: none; z-index: 0;
}
.nav-item:hover::before { opacity: 1; transform: translateX(0) scaleX(1); }
.nav-item > * { position: relative; z-index: 1; }
.nav-item:hover { color: var(--text-primary); text-decoration: none; }
.nav-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.nav-item.active {
    background: var(--accent-soft);
    color: var(--text-primary); font-weight: 600;
}
.nav-item.active::before { content: none; } /* active already has its own solid tint */
.nav-item svg    { width: 16px; height: 16px; flex-shrink: 0; stroke: currentColor; fill: none; }
.nav-item img    { width: 16px; height: 16px; flex-shrink: 0; opacity: .65; transition: opacity .12s, transform .3s cubic-bezier(.34, 1.56, .64, 1); filter: var(--icon-filter); }
.nav-item:hover img,
.nav-item.active img { opacity: 1; }
.nav-item:hover img { transform: scale(1.1); }
.nav-item .nav-item-icon {
    width: 18px; height: 18px; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
    color: var(--text-faint); transition: color .18s ease, transform .3s cubic-bezier(.34, 1.56, .64, 1);
}
.nav-item:hover .nav-item-icon { color: var(--text-secondary); transform: scale(1.1); }
.nav-item.active .nav-item-icon { color: var(--accent-text); }
@media (prefers-reduced-motion: reduce) {
    .nav-item::before { transition: opacity .15s ease; transform: none; }
    .nav-item img, .nav-item .nav-item-icon { transition: opacity .12s, color .12s; }
    .nav-item:hover img, .nav-item:hover .nav-item-icon { transform: none; }
}
.nav-item-label { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.nav-item-count {
    margin-left: auto; flex-shrink: 0; min-width: 20px; padding: 1px 6px; border-radius: var(--r-pill);
    background: var(--bg-subtle); font-family: var(--font-mono); font-size: 11px; text-align: center;
    color: var(--text-muted); font-variant-numeric: tabular-nums;
}

/* ── Sidebar footer: status + user menu (replaces the old top bar) ──── */
.sidebar-footer { margin-top: auto; padding: 10px 12px 12px; flex-shrink: 0; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 8px; }

/* Agent status rows (AgentLayout.vue): online/offline + notification sound */
.sidebar-status { display: flex; flex-direction: column; gap: 2px; }
.online-toggle {
    display: flex; align-items: center; gap: 10px;
    min-height: 36px; padding: 6px 10px; border-radius: var(--r-md);
    cursor: pointer; user-select: none; position: relative; transition: background .12s;
}
.online-toggle:hover { background: color-mix(in srgb, var(--text-primary) 6%, transparent); }
.online-dot {
    width: 8px; height: 8px; margin: 0 5px; border-radius: 50%; flex-shrink: 0;
    background: var(--success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--success) 22%, transparent);
    transition: background .2s, box-shadow .2s;
}
.online-dot.offline { background: var(--text-faint); box-shadow: 0 0 0 3px color-mix(in srgb, var(--text-faint) 18%, transparent); }
.online-label { font-size: 13px; font-weight: 500; line-height: 1.35; color: var(--text-secondary); flex: 1; min-width: 0; overflow-wrap: anywhere; }
.online-toggle input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.toggle-switch { position: relative; width: 30px; height: 18px; border-radius: 99px; background: var(--border-strong); transition: background .2s; flex-shrink: 0; }
.toggle-switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25); transition: transform .2s; }
.online-toggle input:checked + .toggle-switch { background: var(--accent); }
.online-toggle input:checked + .toggle-switch::after { transform: translateX(12px); }
.online-toggle input:focus-visible + .toggle-switch { outline: 2px solid var(--accent); outline-offset: 2px; }
.sound-toggle svg { width: 18px; height: 18px; flex-shrink: 0; fill: none; stroke: var(--text-faint); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }

/* Desktop-notification toggle + its "show preview" sub-setting (AgentLayout.vue): grouped under
   a divider so the pair reads as one related cluster, not two peer rows like online/sound above. */
.notif-group { margin-top: 4px; padding-top: 4px; border-top: 1px dashed var(--border); }
/* Before permission is granted, this row is a button (not a real toggle) — the accent tint
   marks it as actionable/clickable rather than looking like an already-set preference. */
.notif-toggle-row.is-action { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.notif-toggle-row.is-action:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* This row's label text must NOT grow to fill the row (unlike every other .online-toggle row),
   so .notif-help-wrap sits right after the text instead of being pushed to the row's far end. */
.notif-toggle-row .online-label { flex: 0 1 auto; }
/* Own flex item (sibling of the label text, not nested inside it) with margin-right:auto to push
   the switch to the row's end in the text's place — keeps a fixed, guaranteed gap from the
   switch regardless of how the label text wraps. */
.notif-help-wrap {
    position: relative; display: inline-flex; align-items: center; justify-content: center;
    padding: 5px; margin: -5px auto -5px 0; flex-shrink: 0;
}
.notif-help-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 16px; height: 16px; flex-shrink: 0;
    border-radius: 50%; border: 1px solid var(--border-strong); background: var(--bg-surface-alt);
    color: var(--text-muted); font-size: 10px; font-weight: 700; line-height: 1; cursor: help;
    font-family: inherit; padding: 0;
}
.notif-help-wrap:hover .notif-help-btn, .notif-help-wrap:focus-within .notif-help-btn {
    color: var(--text-primary); border-color: var(--accent); background: var(--accent-soft);
}
.notif-help-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Pure hover/keyboard-focus, no JS state — shows while the cursor or focus is on the "?" or
   the popover itself. */
.notif-hint-popover {
    position: absolute; right: -6px; top: calc(100% + 6px); z-index: 30; width: 180px;
    padding: 8px 10px; border-radius: var(--r-md); background: var(--bg-surface); border: 1px solid var(--border);
    box-shadow: 0 10px 28px rgba(0,0,0,.22); font-size: 11px; line-height: 1.4; color: var(--text-secondary);
    opacity: 0; visibility: hidden; transform: translateY(-4px); pointer-events: none;
    transition: opacity .15s ease, transform .15s ease, visibility 0s linear .15s;
}
.notif-help-wrap:hover .notif-hint-popover, .notif-help-wrap:focus-within .notif-hint-popover {
    opacity: 1; visibility: visible; transform: translateY(0); pointer-events: auto;
    transition: opacity .15s ease, transform .15s ease, visibility 0s linear 0s;
}
.notif-subrow-compact {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 2px 10px 4px 34px; font-size: 12px; color: var(--text-muted);
}
.notif-text-toggle {
    border: none; background: none; padding: 2px 8px; margin: -2px -8px;
    font-family: inherit; font-size: 11.5px; font-weight: 600; color: var(--accent-text);
    cursor: pointer; border-radius: var(--r-sm, 6px);
}
.notif-text-toggle:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
@media (prefers-reduced-motion: reduce) {
    .toggle-switch, .toggle-switch::after, .online-dot { transition: none; }
}

.sidebar-avatar {
    width: 30px; height: 30px; border-radius: 50%;
    background: var(--accent-soft); color: var(--accent-text);
    box-shadow: inset 0 0 0 1px var(--accent-ring);
    display: flex; align-items: center; justify-content: center;
    font-size: 12px; font-weight: 700; flex-shrink: 0;
}

.sidebar-user-info { overflow: hidden; min-width: 0; flex: 1; }
.sidebar-user-name, .sidebar-user-role { display: block; }
.sidebar-user-name { font-size: 13px; font-weight: 600; line-height: 1.35; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user-role { font-size: 11.5px; line-height: 1.35; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Sign out — a menu row in the account menu (danger tint on hover) */
.btn-logout {
    width: 100%; min-height: 36px; padding: 7px 10px;
    display: flex; align-items: center; gap: 10px;
    background: transparent; color: var(--text-secondary);
    border: none; border-radius: var(--r-md);
    cursor: pointer; font: inherit; font-size: 13px; font-weight: 500; line-height: 1.35;
    text-align: left; transition: background .12s, color .12s;
}
.btn-logout:hover { background: var(--danger-bg); color: var(--danger-text); }
.btn-logout:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.btn-logout svg { width: 18px; height: 18px; flex-shrink: 0; stroke: currentColor; fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.btn-logout img { width: 16px; height: 16px; flex-shrink: 0; opacity: .7; filter: var(--icon-filter); }
.btn-logout:hover img { opacity: 1; }

/* ── Theme toggle (now a row inside the sidebar user menu) ───────────── */
.theme-toggle {
    width: 100%; padding: 8px 10px;
    display: flex; align-items: center; gap: 9px;
    background: transparent; color: var(--text-secondary);
    border: none; border-radius: var(--r-md);
    cursor: pointer; font-size: 13px; font-weight: 500; text-align: left;
    transition: background .12s, color .12s;
}
.theme-toggle:hover { background: var(--bg-surface-alt); color: var(--text-primary); }
.theme-toggle svg { width: 16px; height: 16px; flex-shrink: 0; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.theme-toggle .icon-dark { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-light { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-dark  { display: block; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .theme-toggle .icon-light { display: none; }
    :root:not([data-theme="light"]) .theme-toggle .icon-dark  { display: block; }
}

/* ── Account menu (sidebar footer "user row" that opens on click) ────── */
.sidebar-account { position: relative; }
.sidebar-account > summary { list-style: none; cursor: pointer; }
.sidebar-account > summary::-webkit-details-marker { display: none; }

.sidebar-account-trigger {
    display: flex; align-items: center; gap: 10px;
    min-height: 44px; padding: 6px 8px; border-radius: var(--r-md);
    transition: background .12s;
}
.sidebar-account-trigger:hover,
.sidebar-account[open] .sidebar-account-trigger { background: color-mix(in srgb, var(--text-primary) 6%, transparent); }
.sidebar-account-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.sidebar-chevron { width: 16px; height: 16px; stroke: var(--text-faint); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; margin-left: auto; transition: transform .15s; }
.sidebar-account[open] .sidebar-chevron { transform: rotate(180deg); }

.sidebar-account-menu {
    position: absolute; bottom: calc(100% + 6px); left: 0; right: 0;
    background: var(--bg-surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
    padding: 6px;
    display: flex; flex-direction: column; gap: 1px;
    z-index: 20;
    animation: sidebar-menu-in .14s ease;
}
@keyframes sidebar-menu-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
    .sidebar-account-menu { animation: none; }
    .sidebar-chevron { transition: none; }
}
.sidebar-account-menu .nav-item { min-height: 36px; padding: 7px 10px; font-size: 13px; }
.sidebar-account-menu .nav-item + .nav-item { margin-top: 0; }
.sidebar-account-menu .theme-toggle { min-height: 36px; padding: 7px 10px; gap: 10px; line-height: 1.35; font: inherit; font-size: 13px; font-weight: 500; }
.sidebar-account-menu .theme-toggle:hover { background: color-mix(in srgb, var(--text-primary) 6%, transparent); }
.sidebar-account-menu .theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.sidebar-account-menu .theme-toggle svg { width: 18px; height: 18px; stroke-width: 1.75; color: var(--text-faint); }
.sidebar-account-menu .nav-item .nav-item-icon { color: var(--text-faint); }
.sidebar-account-menu .nav-item:hover .nav-item-icon,
.sidebar-account-menu .theme-toggle:hover svg { color: var(--text-secondary); }
.sidebar-menu-value { margin-left: auto; font-size: 12px; font-weight: 500; color: var(--text-faint); white-space: nowrap; }
.sidebar-menu-label {
    display: flex; align-items: center; gap: 10px; padding: 6px 10px 4px;
    font-size: 13px; font-weight: 500; color: var(--text-secondary);
}
.sidebar-menu-label svg { width: 18px; height: 18px; flex-shrink: 0; fill: none; stroke: var(--text-faint); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }

.sidebar-menu-divider { border-top: 1px solid var(--divider); margin: 5px 4px; }

/* ── Language switcher (now lives inside the sidebar account menu) ───── */
.lang-switcher { padding: 4px 0 8px; margin-bottom: 4px; border-bottom: 1px solid var(--border); }
.lang-switcher-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .7px; color: var(--text-faint); margin-bottom: 6px; padding: 0 6px; }
.lang-buttons { display: flex; gap: 4px; }
.lang-btn { padding: 3px 9px; border: 1px solid var(--border); border-radius: 4px; font-size: 11px; font-weight: 600; background: var(--bg-surface); cursor: pointer; color: var(--text-muted); transition: all .15s; line-height: 1.6; }
.lang-btn:hover { border-color: var(--accent-strong); color: var(--accent-strong); }
.lang-btn.active { background: var(--accent-strong); border-color: var(--accent-strong); color: white; }
.lang-select {
    width: 100%; padding: 6px 10px;
    border: 1px solid var(--border); border-radius: 6px;
    font-size: 12px; font-weight: 500; color: var(--text-secondary);
    background: var(--bg-surface); cursor: pointer;
}
.lang-select:focus { outline: none; border-color: var(--accent-strong); box-shadow: 0 0 0 3px var(--accent-ring); }
/* Account-menu language row: the select spans the menu width, under its "Language" label */
.sidebar-account-menu .lang-switcher { padding: 0 6px 4px; margin: 0; border-bottom: none; }
.sidebar-account-menu .lang-switcher .ss-wrap { width: 100%; }
.sidebar-account-menu .lang-switcher .ss-trigger { width: 100%; height: 34px; }
.sidebar-account-menu .lang-switcher .ss-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ── Searchable select (Components/SearchableSelect.vue) ──────────────────
   A type-to-filter dropdown over a hidden native <select> (kept for name=/form wiring).
   data-columns / :columns sets the options grid width per instance. ── */
.ss-wrap { position: relative; display: inline-block; width: 100%; }
.ss-native.ss-enhanced { position: absolute; opacity: 0; pointer-events: none; width: 1px; height: 1px; }

.ss-trigger {
    width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
    text-align: left; font-family: inherit; cursor: pointer;
    padding: 8px 10px; border: 1px solid var(--border-strong); border-radius: var(--r-md);
    font-size: 13px; font-weight: 500; color: var(--text-primary); background: var(--bg-surface);
    transition: border-color .15s, box-shadow .15s, background-color .15s;
}
.ss-trigger:hover:not(:disabled) { border-color: color-mix(in srgb, var(--text-faint) 55%, var(--border-strong)); }
.ss-trigger:focus { outline: none; }
.ss-trigger:focus-visible, .ss-trigger.open { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
.ss-trigger:disabled { cursor: not-allowed; background: var(--bg-subtle); color: var(--text-muted); }
.ss-trigger:disabled .ss-chevron { opacity: .5; }
.ss-trigger-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ss-chevron { width: 14px; height: 14px; flex-shrink: 0; stroke: var(--text-faint); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform .15s; }
.ss-trigger.open .ss-chevron { transform: rotate(180deg); stroke: var(--accent-text); }

/* position:fixed + JS-computed top/bottom/left/right in viewport px (positionPanel()) — lets the
   panel escape a parent .card's overflow:hidden instead of having its options cut off. */
.ss-panel {
    position: fixed; z-index: 1000;
    max-width: 90vw;
    background: var(--bg-surface); border: 1px solid var(--border-strong); border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
    padding: 6px;
    display: flex; flex-direction: column; gap: 6px;
}
.ss-panel[hidden] { display: none; }

.ss-search-wrap { position: relative; }
.ss-search-icon {
    position: absolute; left: 9px; top: 50%; transform: translateY(-50%); width: 14px; height: 14px; pointer-events: none;
    fill: none; stroke: var(--text-faint); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
/* `.ss-panel` prefix: outranks the Forms section's input[type="text"] rule. */
.ss-panel .ss-search {
    width: 100%; height: 34px; padding: 0 10px 0 30px; border: 1px solid var(--border); border-radius: var(--r-md);
    font-size: 13px; font-family: inherit; color: var(--text-primary); background: var(--bg-surface-alt);
    outline: none; transition: border-color .15s, box-shadow .15s;
}
.ss-panel .ss-search::placeholder { color: var(--text-faint); }
.ss-panel .ss-search:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }

.ss-options {
    display: grid; grid-template-columns: repeat(var(--ss-cols, 1), 1fr);
    gap: 1px; max-height: 280px; overflow-y: auto; overscroll-behavior: contain; /* JS sets the real cap per-open */
}
.ss-option {
    display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; overflow: hidden; min-height: 32px; text-align: left; padding: 6px 9px; border-radius: var(--r-sm);
    border: none; background: none; cursor: pointer; font-family: inherit;
    font-size: 13px; font-weight: 500; color: var(--text-secondary);
    white-space: nowrap;
    transition: background-color .1s, color .1s;
}
.ss-option-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ss-check { width: 14px; height: 14px; flex-shrink: 0; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.ss-option[hidden] { display: none; }
.ss-option:hover, .ss-option.highlighted { background: var(--bg-subtle); color: var(--text-primary); }
.ss-option.highlighted { box-shadow: inset 0 0 0 1px var(--border-strong); }
.ss-option.active { background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }
.ss-option.active.highlighted { box-shadow: inset 0 0 0 1px var(--accent-ring); }
.ss-empty { padding: 12px 9px; font-size: 12.5px; color: var(--text-faint); text-align: center; }
.ss-empty[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
    .ss-trigger, .ss-chevron, .ss-search, .ss-option { transition: none; }
}

/* Compact variant for inline controls (e.g. the account-menu language select) */
.sidebar-account-menu .ss-wrap { width: auto; }
.sidebar-account-menu .ss-trigger { width: auto; height: 32px; padding: 0 10px; border-radius: 8px; font-size: 12.5px; }

/* ── Portal switcher — segmented control in the sidebar (spec §4.2) ──── */
.portal-switcher {
    display: flex; gap: 2px; padding: 3px;
    background: var(--bg-subtle); border: 1px solid var(--border); border-radius: var(--r-md);
    flex-shrink: 0;
}
/* flex 1 1 auto: options share the width by label length, so a long label (Thai, Burmese, German)
   takes the room a short one doesn't need before anything truncates (full text in `title`). */
.portal-switcher-option {
    flex: 1 1 auto; min-width: 0;
    display: flex; align-items: center; justify-content: center; gap: 5px;
    min-height: 30px; padding: 5px 6px; border-radius: 7px;
    font-size: 12px; font-weight: 500; line-height: 1.3; color: var(--text-muted);
    text-decoration: none; transition: background .12s, color .12s;
}
.portal-switcher-option:hover { color: var(--text-primary); background: color-mix(in srgb, var(--text-primary) 6%, transparent); text-decoration: none; }
.portal-switcher-option:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.portal-switcher-option.active {
    background: var(--accent-soft); color: var(--text-primary); font-weight: 600;
    box-shadow: inset 0 0 0 1px var(--accent-ring);
}
.portal-switcher-label {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.portal-switcher-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.portal-switcher-option.active .portal-switcher-dot { box-shadow: 0 0 6px currentColor; }
/* "you also have a live session there" marker on another portal's option */
.portal-switcher-live { width: 5px; height: 5px; border-radius: 50%; background: var(--success); flex-shrink: 0; }

/* ── Main content ─────────────────────────────────────────────────────── */
.app-main { flex: 1; overflow-y: auto; min-width: 0; }
.app-main:focus { outline: none; } /* focus target of the skip link, not a control */

/* Agent portal flash (AgentLayout has no .page; PortalShell puts the flash above the content) */
.flash-wrap { padding: 0 16px; flex-shrink: 0; }
.flash-wrap .flash { margin: 8px 0 0; }

/* Banner slot of the shell (PortalShell #banner), e.g. MerchantLayout's impersonation notice */
.shell-banner {
    position: sticky; top: 0; z-index: 9;
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px 16px;
    padding: 10px 24px;
    background: var(--warning-bg); color: var(--warning-text);
    border-bottom: 1px solid var(--warning-border);
    font-size: 13px; line-height: 1.45;
}
.shell-banner-text { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1 1 260px; font-weight: 500; }
.shell-banner-icon {
    width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
    display: grid; place-items: center;
    background: color-mix(in srgb, var(--warning-strong-icon) 18%, transparent); color: var(--warning-strong-icon);
}
.shell-banner-icon svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.shell-banner form { margin: 0; flex-shrink: 0; }
.shell-banner-btn {
    background: var(--bg-surface); color: var(--text-primary); border: 1px solid var(--warning-border);
    min-height: 32px; gap: 6px;
}
.shell-banner-btn:hover { background: var(--bg-surface-alt); border-color: var(--warning-text-soft); }
.shell-banner-btn:focus-visible { outline: 2px solid var(--warning-text-soft); outline-offset: 2px; }
.shell-banner-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
/* Visually hidden, still read by screen readers (live regions / extra labels in the shell) */
.shell-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Page transition (PortalShell.vue's <Transition name="page-jump">): sidebar navigation
   (Vue page component swap) fades + lifts the new page in instead of a hard, instant cut.
   mode="out-in" so the old page finishes leaving before the new one enters — no overlap, no
   layout jump, and short enough (160ms) to still feel snappy, not sluggish. Global (not
   scoped) because Vue applies these classes to the actual page component's root element,
   which only carries that page's own scope id, not PortalShell's. */
.page-jump-enter-active, .page-jump-leave-active { transition: opacity .16s ease, transform .16s ease; }
.page-jump-enter-from { opacity: 0; transform: translateY(8px); }
.page-jump-leave-to { opacity: 0; transform: translateY(-8px); }
@media (prefers-reduced-motion: reduce) {
    .page-jump-enter-active, .page-jump-leave-active { transition: none; }
}

/* display:flex + min-height lets an individual page opt a row into flex:1 to fill the
   rest of the viewport (e.g. a chat message list) — plain block children are unaffected,
   since column-direction stretch is just their normal full-width block behavior anyway. */
.page { padding: 28px 24px; display: flex; flex-direction: column; min-height: 100%; }
.page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; gap: 12px; }
.page-title  { font-size: 22px; font-weight: 600; letter-spacing: -.02em; color: var(--text-primary); }
.page-eyebrow {
    font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: .07em; text-transform: uppercase;
    color: var(--text-faint); margin-bottom: 4px;
}
.page-subtitle { font-size: 13.5px; color: var(--text-muted); margin-top: 4px; max-width: 68ch; line-height: 1.5; }
.section-gap { margin-top: 24px; }

/* ── Empty state (EmptyState.vue) — the one shared "nothing here yet" block ── */
.empty-state {
    display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
    gap: 6px; padding: 48px 24px; color: var(--text-muted);
}
.empty-state-icon {
    width: 48px; height: 48px; border-radius: var(--r-xl); display: grid; place-items: center; margin-bottom: 6px;
    background: var(--accent-soft); color: var(--accent-text); border: 1px solid var(--accent-ring);
}
.empty-state-icon svg { width: 22px; height: 22px; }
.empty-state-title { font-size: 14.5px; font-weight: 600; color: var(--text-primary); }
.empty-state-hint { font-size: 13px; color: var(--text-muted); max-width: 42ch; line-height: 1.5; }
.empty-state-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 10px; }
.empty-state-compact { padding: 24px 16px; gap: 4px; }
.empty-state-compact .empty-state-icon { width: 36px; height: 36px; border-radius: var(--r-lg); margin-bottom: 4px; }
.empty-state-compact .empty-state-icon svg { width: 18px; height: 18px; }
.empty-state-compact .empty-state-title { font-size: 13.5px; }

/* Agent portal: flex-column main area, so content wraps in .chats-wrap instead of .page.
   display:flex + min-height mirrors .page — lets an individual page opt a row into flex:1
   to fill the rest of the viewport (e.g. a chat message list). dashboard.blade.php uses its
   own .workspace instead of .chats-wrap, so it's unaffected by this. */
.chats-wrap { flex: 1; overflow-y: auto; padding: 24px; display: flex; flex-direction: column; min-height: 0; }

/* ── Flash messages ───────────────────────────────────────────────────── */
/* Typed flashes get a leading icon (CSS mask in currentColor, absolutely placed so mixed inline
   content keeps flowing normally). A plain .flash or a page's own variant gets no icon. */
.flash { position: relative; padding: 11px 16px; border-radius: var(--r-lg); margin-bottom: 20px; font-size: 13px; font-weight: 500; line-height: 1.45; overflow-wrap: anywhere; }
.flash-success, .flash-error, .flash-warning, .flash-info { padding-left: 40px; }
.flash-success::before, .flash-error::before, .flash-warning::before, .flash-info::before {
    content: ""; position: absolute; left: 14px; top: 12.5px; width: 16px; height: 16px;
    background-color: currentColor;
    -webkit-mask: var(--flash-icon) center / 16px 16px no-repeat; mask: var(--flash-icon) center / 16px 16px no-repeat;
}
.flash-success { background: var(--success-bg); color: var(--success-text); border: 1px solid var(--success-border);
    --flash-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 11.08V12a10 10 0 1 1-5.93-9.14M22 4 12 14.01l-3-3'/%3E%3C/svg%3E"); }
.flash-error   { background: var(--danger-bg); color: var(--danger-text); border: 1px solid var(--danger-border);
    --flash-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%3E%3C/svg%3E"); }
.flash-warning { background: var(--warning-bg); color: var(--warning-text); border: 1px solid var(--warning-border);
    --flash-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0zM12 9v4M12 17h.01'/%3E%3C/svg%3E"); }
.flash-info    { background: var(--info-bg); color: var(--info-text); border: 1px solid var(--info-border);
    --flash-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 16v-4M12 8h.01'/%3E%3C/svg%3E"); }

/* ── Toasts (Utils/toast.js showToast) ─────────────────────────────────
   One stacked region bottom-right (bottom, full width on phones); each toast is a raised surface
   card with a tinted type icon. --toast-tone is the type colour (or the caller's own colour). */
.toast-region {
    position: fixed; right: 20px; bottom: 20px; z-index: 10000;
    display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
    width: min(380px, calc(100vw - 32px)); pointer-events: none;
}
.toast {
    --toast-tone: var(--text-muted);
    pointer-events: auto; display: flex; align-items: flex-start; gap: 10px; max-width: 100%;
    padding: 10px 8px 10px 12px; border-radius: var(--r-lg);
    background: var(--bg-surface); color: var(--text-primary); border: 1px solid var(--border-strong);
    box-shadow: var(--shadow-lg); font-size: 13px; font-weight: 500; line-height: 1.45;
    transition: opacity .2s ease, transform .2s var(--ease-out);
}
.toast-entering { opacity: 0; transform: translateY(8px); }
.toast-leaving  { opacity: 0; transform: translateY(4px); }
.toast-success { --toast-tone: var(--success); }
.toast-error   { --toast-tone: var(--danger); }
.toast-warning { --toast-tone: var(--warning-text-soft); }
.toast-info    { --toast-tone: var(--info-text); }
.toast-icon {
    flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
    color: var(--toast-tone); background: color-mix(in srgb, var(--toast-tone) 16%, transparent);
}
.toast-icon svg { width: 14px; height: 14px; }
.toast-msg { flex: 1; min-width: 0; padding-top: 1.5px; overflow-wrap: anywhere; }
.toast-close {
    flex-shrink: 0; width: 24px; height: 24px; display: grid; place-items: center; margin-left: 2px;
    border: none; background: none; border-radius: var(--r-sm); color: var(--text-faint); cursor: pointer;
    transition: background-color var(--dur-fast), color var(--dur-fast);
}
.toast-close:hover { background: var(--bg-subtle); color: var(--text-primary); }
.toast-close:focus-visible { outline: var(--focus-outline); outline-offset: 0; }
.toast-close svg { width: 14px; height: 14px; }
@media (max-width: 560px) {
    .toast-region { left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); width: auto; align-items: stretch; }
}

/* ── Cards / panels (spec §4.1) ──────────────────────────────────────── */
.card { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--r-2xl); box-shadow: var(--shadow-sm); overflow: hidden; }
.card-header { padding: 16px 20px; border-bottom: 1px solid var(--divider); display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.card-title  { font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--text-primary); }
/* Card.vue `subtitle` / `description`: title + one helpful line, stacked */
.card-heading  { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.card-subtitle, .card-desc { font-size: 12.5px; font-weight: 400; line-height: 1.45; color: var(--text-muted); }
/* .card-desc: same look for pages that put the line straight under their own .card-title */
.card-desc { margin-top: 2px; }
.card-heading > .card-desc { margin-top: 0; }
/* Card.vue #actions slot: right side of the header */
.card-actions  { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex-shrink: 0; margin-left: auto; }
.card-body   { padding: 20px; }
.card-footer {
    display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap;
    padding: 14px 20px; border-top: 1px solid var(--divider); background: var(--bg-surface-alt);
    /* own bottom radius: the shell sets .card { overflow: visible } on phones, so no clipping there */
    border-radius: 0 0 calc(var(--r-2xl) - 1px) calc(var(--r-2xl) - 1px);
}
@media (max-width: 480px) {
    .card-header { padding: 14px 16px; }
    .card-body   { padding: 16px; }
    .card-footer { padding: 12px 16px; }
}

/* ── Tables (spec §4.9) ───────────────────────────────────────────────── */
table { width: 100%; border-collapse: collapse; }
th {
    text-align: left; padding: 10px 18px;
    font-family: var(--font-mono); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .06em;
    color: var(--text-faint); background: var(--bg-surface-alt); border-bottom: 1px solid var(--divider);
}
td { padding: 11px 18px; border-bottom: 1px solid var(--divider); vertical-align: middle; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: color-mix(in srgb, var(--text-primary) 3.5%, transparent); }
.empty-row td { text-align: center; padding: 28px; color: var(--text-faint); font-size: 13px; }
.num { font-variant-numeric: tabular-nums; text-align: right; }

/* ── Badges ───────────────────────────────────────────────────────────── */
.badge        { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: var(--r-pill); font-size: 11px; font-weight: 600; line-height: 16px; }
/* Semantic names are aliases of the colour names (Badge.vue `color`). */
.badge-green,  .badge-success { background: var(--success-bg); color: var(--success-text); }
.badge-gray,   .badge-neutral { background: var(--bg-subtle); color: var(--text-muted); box-shadow: inset 0 0 0 1px var(--border); }
.badge-blue,   .badge-accent  { background: var(--accent-tint); color: var(--accent-deep); }
.badge-orange { background: var(--orange-bg); color: var(--orange-text); }
.badge-red,    .badge-danger  { background: var(--danger-bg); color: var(--danger-text); }
.badge-yellow, .badge-warning { background: var(--warning-bg-hover); color: var(--warning-text); }
.badge-info   { background: var(--info-bg); color: var(--info-text); }
/* Badge.vue `dot`: a leading status dot in the badge's own colour */
.badge-dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }

/* ── Buttons (spec §4.4) ─────────────────────────────────────────────── */
/* Every variant shares one box: 1px border (transparent where the variant has none) so all
   variants of a size are the same height — md 36px, sm 28px (lg 42px); phones get ≥36px targets.
   A plain `.btn` (no variant) is the neutral "secondary" button; `.btn-secondary` is its alias. */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    min-height: 36px; padding: 8px 14px;
    border: 1px solid var(--border-strong); border-radius: var(--r-md);
    background: var(--bg-surface); color: var(--text-primary); box-shadow: var(--shadow-xs);
    font-family: inherit; font-size: 13px; font-weight: 500; line-height: 18px;
    cursor: pointer; text-decoration: none; white-space: nowrap; -webkit-user-select: none; user-select: none;
    transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease,
                box-shadow var(--dur) ease, opacity var(--dur-fast) ease, transform .1s ease;
}
.btn:hover   { background: color-mix(in srgb, var(--text-primary) 5%, var(--bg-surface)); text-decoration: none; }
.btn:active  { transform: scale(.98); }
.btn:focus-visible { outline: var(--focus-outline); outline-offset: 2px; }
.btn > svg:not([width]) { width: 16px; height: 16px; flex-shrink: 0; }
.btn-secondary { background: var(--bg-surface); color: var(--text-primary); border-color: var(--border-strong); }
/* Primary uses a light-on-dark pill rather than a flat accent fill: the spec's accent hues
   (violet/emerald/amber) don't have enough luminance contrast against white text to pass
   AA at button weight, so the spec itself uses this inverted style for Primary and reserves
   the gradient+white treatment (.btn-accent) for a single high-emphasis action per portal. */
.btn-primary { background: var(--text-primary); color: var(--bg-page); border-color: var(--text-primary); font-weight: 600; }
.btn-primary:hover {
    background: color-mix(in srgb, var(--text-primary) 86%, var(--bg-page)); border-color: transparent;
    box-shadow: 0 0 16px color-mix(in srgb, var(--accent) 35%, transparent);
}
.btn-accent  { background: linear-gradient(var(--logo-gradient)); color: white; border-color: transparent; box-shadow: 0 0 18px color-mix(in srgb, var(--accent) 40%, transparent); }
.btn-accent:hover { background: linear-gradient(var(--logo-gradient)); filter: brightness(1.06); box-shadow: 0 0 22px color-mix(in srgb, var(--accent) 50%, transparent); }
.btn-danger  { background: var(--danger-solid); color: white; border-color: var(--danger-solid); }
.btn-danger:hover { background: color-mix(in srgb, var(--danger-solid) 86%, black); border-color: transparent; }
/* Quieter destructive action (e.g. a row's Delete): tinted, turns solid-ish on hover */
.btn-danger-soft { background: var(--danger-bg); color: var(--danger-text); border-color: var(--danger-border); box-shadow: none; }
.btn-danger-soft:hover { background: color-mix(in srgb, var(--danger) 20%, var(--bg-surface)); color: var(--danger-text); }
.btn-ghost   { background: transparent; color: var(--text-muted); border-color: var(--border-strong); box-shadow: none; }
.btn-ghost:hover { background: color-mix(in srgb, var(--text-primary) 5%, transparent); color: var(--text-primary); opacity: 1; }
.btn-sm { min-height: 28px; padding: 4px 10px; gap: 4px; font-size: 12px; line-height: 18px; }
.btn-sm > svg:not([width]) { width: 14px; height: 14px; }
.btn-lg { min-height: 42px; padding: 10px 18px; font-size: 14px; line-height: 20px; }
.btn-block { display: flex; width: 100%; }
/* Disabled (native :disabled, or .disabled / aria-disabled on a link-button): visual only */
.btn:disabled, .btn.disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; box-shadow: none; transform: none; filter: none; }
/* Btn.vue `loading`: spinner + aria-busy; stays readable rather than faded */
.btn-loading, .btn-loading:disabled { cursor: progress; opacity: .8; }
.btn-spinner {
    width: 14px; height: 14px; flex-shrink: 0; border-radius: 50%;
    border: 2px solid currentColor; border-right-color: transparent; animation: btn-spin .7s linear infinite;
}
.btn-sm .btn-spinner { width: 12px; height: 12px; }
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* Ghost icon-only button (spec §4.4) */
.btn-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: var(--r-md);
    background: transparent; color: var(--text-faint); border: none; cursor: pointer;
    transition: background-color var(--dur-fast), color var(--dur-fast);
}
.btn-icon:hover, .btn-icon[aria-expanded="true"], .row-menu[open] > summary.btn-icon {
    background: color-mix(in srgb, var(--text-primary) 7%, transparent); color: var(--text-primary);
}
.btn-icon:focus-visible { outline: var(--focus-outline); outline-offset: 1px; }
.btn-icon:disabled { opacity: .45; cursor: not-allowed; }
.btn-icon svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 768px) {
    .btn { min-height: 40px; }
    .btn-sm { min-height: 36px; }
    .btn-icon { width: 36px; height: 36px; }
}

/* Row "⋯" menu (spec §1 principle 5 / §4.9: delete lives behind a row's ⋯ menu, never a bare
   button in the row). Promoted from a page-local pattern (Admin/Merchants/Index.vue) to shared
   so any list page can opt in with plain markup — no Vue component needed:
     <details class="row-menu"><summary class="btn-icon" aria-label="…">⋯</summary>
       <div class="row-menu-panel">
         <AppLink class="row-menu-item">Edit</AppLink>
         <button class="row-menu-item row-menu-item--danger">Delete</button>
       </div>
     </details>
   Dismiss on outside click / Escape: add a page-level listener closing open .row-menu[open]
   elements, same as Admin/Merchants/Index.vue does — not baked in here since <details> has no
   built-in "close on outside click". */
.row-menu { position: relative; }
.row-menu > summary { list-style: none; cursor: pointer; }
.row-menu > summary::-webkit-details-marker { display: none; }
.row-menu-panel {
    position: absolute; right: 0; top: calc(100% + 4px); z-index: 20;
    background: var(--bg-surface); border: 1px solid var(--border-strong); border-radius: var(--r-lg);
    box-shadow: var(--shadow-lg); padding: 6px; min-width: 160px; display: flex; flex-direction: column; gap: 2px;
}
.row-menu-item {
    display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: var(--r-sm);
    font-size: 13px; color: var(--text-secondary); text-decoration: none; background: none; border: none;
    cursor: pointer; text-align: left; width: 100%; font-family: inherit;
}
.row-menu-item:hover { background: color-mix(in srgb, var(--text-primary) 6%, transparent); color: var(--text-primary); text-decoration: none; }
.row-menu-item:focus-visible { outline: var(--focus-outline); outline-offset: -2px; }
.row-menu-item--danger { color: var(--danger); }
.row-menu-item--danger:hover { background: var(--danger-bg); color: var(--danger-text); }

/* ── Segmented control (periods, inbox tabs, portal-switcher sibling) ──
   spec §4.5 — same shape as .portal-switcher but for in-page filters ─── */
.segmented {
    display: inline-flex; gap: 2px; padding: 3px; background: var(--bg-subtle); border: 1px solid var(--border); border-radius: var(--r-md);
    max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.segmented-option {
    padding: 7px 14px; border-radius: 7px; border: none; background: none; cursor: pointer;
    font-size: 12.5px; font-weight: 500; color: var(--text-faint); font-family: inherit;
    transition: background .12s, color .12s; white-space: nowrap;
}
.segmented-option:hover { color: var(--text-primary); }
.segmented-option:focus-visible { outline: var(--focus-outline); outline-offset: -2px; }
.segmented-option.active { background: var(--accent-soft); color: var(--text-primary); font-weight: 600; box-shadow: inset 0 0 0 1px var(--accent-ring); }

/* ── Filter chip (spec §4.6) ──────────────────────────────────────────── */
.filter-chip {
    display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px;
    border-radius: var(--r-pill); font-size: 13px; font-weight: 500;
    background: transparent; border: 1px solid var(--border-strong); color: var(--text-secondary);
    cursor: pointer; transition: background .12s, color .12s, border-color .12s;
}
.filter-chip:hover { color: var(--text-primary); background: color-mix(in srgb, var(--text-primary) 4%, transparent); }
.filter-chip:focus-visible { outline: var(--focus-outline); outline-offset: 2px; }
.filter-chip.active { background: var(--accent-soft); border-color: var(--accent-ring); color: var(--text-primary); }
.filter-chip-count { font-family: var(--font-mono); opacity: .8; }

/* ── Status dot (spec §4.7) ──────────────────────────────────────────── */
.status-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; display: inline-block; }
.status-dot.on { background: var(--success); box-shadow: 0 0 8px color-mix(in srgb, var(--success) 70%, transparent); animation: status-pulse 2s ease-in-out infinite; }
.status-dot.off  { background: var(--text-faint); }
.status-dot.warn { background: var(--warning-text-soft); }
.status-dot.bad  { background: var(--danger); }
@media (prefers-reduced-motion: reduce) { .status-dot.on { animation: none; } }
@keyframes status-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ── Stat tile (spec §4.8) ───────────────────────────────────────────── */
/* Chart series for the AI / human-agent split. --series-* are the identity hues; the human mark
   is drawn one oklab step darker (derived from the token, not a new hex) so it clears 3:1 on the
   light surface and sits inside the dark-mode lightness band — validated with the dataviz palette
   checks in both themes. Marks only: labels and values always wear text tokens. */
:root { --viz-bot: var(--series-bot); --viz-human: color-mix(in oklab, var(--series-human) 92%, black); }
/* Neutral "neither" mark (e.g. unresolved chats): recedes behind the identity hues, legend carries the label. */
:root { --viz-none: #a3a8b2; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --viz-none: #5a5770; } }
:root[data-theme="dark"] { --viz-none: #5a5770; }

.stat-grid  { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-bottom: 24px; }
.stat-card  { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--shadow-sm); padding: 16px 18px; min-width: 0; }
.stat-label {
    font-family: var(--font-mono); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .06em;
    color: var(--text-faint);
}
/* Proportional figures: a lone big number looks loose with tabular digits (columns keep .num). */
.stat-value { font-size: 26px; font-weight: 600; letter-spacing: -.02em; line-height: 1.2; color: var(--text-primary); margin-top: 6px; }
.stat-value-of { font-size: 13px; font-weight: 500; letter-spacing: 0; color: var(--text-faint); }
.stat-icon  { width: 38px; height: 38px; border-radius: var(--r-md); display: flex; align-items: center; justify-content: center; margin-bottom: 12px; }
.stat-icon svg { width: 18px; height: 18px; fill: none; stroke: white; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Label row with a small tinted icon on the right (StatCard `icon` prop) */
.stat-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; min-width: 0; }
.stat-head .stat-label { padding-top: 3px; min-width: 0; }
.stat-icon--soft { width: 30px; height: 30px; margin: -4px -4px 0 0; flex-shrink: 0; border-radius: var(--r-md); background: var(--accent-soft); color: var(--accent-text); }
.stat-icon--soft svg { width: 16px; height: 16px; stroke: currentColor; }
.stat-caption { margin-top: 4px; font-size: 12px; line-height: 1.45; color: var(--text-muted); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
.stat-caption svg { width: 13px; height: 13px; flex-shrink: 0; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Tone: the number needs attention (always paired with a caption saying why) */
.stat-card--warning { background: var(--warning-bg); border-color: var(--warning-border); }
.stat-card--warning .stat-label, .stat-card--warning .stat-caption { color: var(--warning-text); }
.stat-card--warning .stat-icon--soft { background: var(--warning-bg-hover); color: var(--warning-text); }
.stat-card--danger { background: var(--danger-bg); border-color: var(--danger-border); }
.stat-card--danger .stat-label, .stat-card--danger .stat-caption { color: var(--danger-text); }
.stat-card--danger .stat-icon--soft { background: var(--danger-bg); color: var(--danger-text); }
.stat-card--success .stat-icon--soft { background: var(--success-bg); color: var(--success-text); }

/* Ring variant: 44px SVG ring with a label beside it */
.stat-ring-row { display: flex; align-items: center; gap: 12px; }
.stat-ring { flex-shrink: 0; transform: rotate(-90deg); }
.stat-ring-track { fill: none; stroke: var(--border); stroke-width: 5; }
.stat-ring-value { fill: none; stroke-width: 5; stroke-linecap: round; }

/* Bar variant: a thin stacked composition bar under the number */
.stat-bar { height: 5px; border-radius: var(--r-pill); background: var(--bg-subtle); overflow: hidden; margin-top: 10px; display: flex; }
.stat-bar-fill { height: 100%; border-radius: var(--r-pill); background: linear-gradient(var(--logo-gradient)); }
/* Multi-segment: a 2px gap keeps neighbouring colours apart; segments shrink to fit around it */
.stat-bar--segmented { gap: 2px; }
.stat-bar-seg { flex-shrink: 1; min-width: 2px; }
.stat-bar-seg:first-child { border-radius: var(--r-pill) 0 0 var(--r-pill); }
.stat-bar-seg:last-child { border-radius: 0 var(--r-pill) var(--r-pill) 0; }
.stat-bar-seg:only-child { border-radius: var(--r-pill); }

/* StatGrid :cols="3" / "2" — three or two tiles per row on desktop (the shell's breakpoints still apply below) */
@media (min-width: 769px) { .stat-grid.stat-grid--cols3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 769px) { .stat-grid.stat-grid--cols2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* StatGrid :min-cols="2" — keep two tiles per row on phones (the shell's ≤480px rule makes it 1) */
@media (max-width: 480px) {
    .stat-grid.stat-grid--min2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .stat-grid--min2 .stat-card { padding: 14px; }
    .stat-grid--min2 .stat-value { font-size: 22px; }
}

/* ── Modal ────────────────────────────────────────────────────────────── */
.modal-overlay {
    display: none; position: fixed; inset: 0; z-index: 900; padding: 24px 16px;
    background: var(--overlay-bg); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    align-items: center; justify-content: center;
}
.modal-overlay.open { display: flex; }
/* Header and footer stay put; only the body scrolls when the content is tall. */
.modal {
    display: flex; flex-direction: column; overflow: hidden;
    background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--r-xl);
    width: 500px; max-width: 100%; max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px);
    box-shadow: var(--shadow-md);
}
.modal:focus { outline: none; }
.modal-sm { width: 400px; }
.modal-lg { width: 720px; }
.modal-xl { width: 960px; }
@keyframes modal-in { from { opacity: 0; transform: translateY(-8px) scale(.98); } to { opacity: 1; transform: none; } }
.modal-header { flex-shrink: 0; padding: 16px 20px; border-bottom: 1px solid var(--divider); display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.modal-heading { min-width: 0; display: flex; flex-direction: column; gap: 3px; padding-top: 4px; }
.modal-title  { font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--text-primary); }
.modal-description { font-size: 12.5px; line-height: 1.45; color: var(--text-muted); }
.modal-close  {
    flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin: 0 -8px 0 0;
    background: none; border: none; font-size: 20px; line-height: 1; cursor: pointer; color: var(--text-faint); padding: 0; border-radius: var(--r-md);
    transition: background-color var(--dur-fast), color var(--dur-fast);
}
.modal-close:hover { color: var(--text-primary); background: color-mix(in srgb, var(--text-primary) 7%, transparent); }
.modal-close:focus-visible { outline: var(--focus-outline); outline-offset: 0; }
.modal-close svg { width: 18px; height: 18px; }
.modal-body   { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 14px; }
.modal-footer { flex-shrink: 0; padding: 14px 20px; border-top: 1px solid var(--divider); background: var(--bg-surface-alt); display: flex; justify-content: flex-end; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Modal.vue <Transition name="kit-modal">: backdrop fades, dialog rises in */
.kit-modal-enter-active, .kit-modal-leave-active { transition: opacity var(--dur) ease; }
.kit-modal-enter-active .modal, .kit-modal-leave-active .modal { transition: transform var(--dur) var(--ease-out), opacity var(--dur) ease; }
.kit-modal-leave-active, .kit-modal-leave-active .modal { transition-duration: .14s; }
.kit-modal-enter-from, .kit-modal-leave-to { opacity: 0; }
.kit-modal-enter-from .modal, .kit-modal-leave-to .modal { opacity: 0; transform: translateY(8px) scale(.98); }
/* Phones: the dialog becomes a sheet anchored to the bottom edge, footer buttons share the row */
@media (max-width: 560px) {
    .modal-overlay { align-items: flex-end; padding: 12px 0 0; }
    .modal {
        width: 100%; max-height: calc(100dvh - 12px); border-radius: var(--r-xl) var(--r-xl) 0 0;
        border-bottom: none; padding-bottom: env(safe-area-inset-bottom, 0px);
    }
    .modal-header { padding: 14px 16px; }
    .modal-body   { padding: 16px; }
    .modal-footer { padding: 12px 16px; }
    .modal-footer > .btn { flex: 1 1 0; }
    .kit-modal-enter-from .modal, .kit-modal-leave-to .modal { transform: translateY(24px); }
}

/* ── Chat bubbles (Agent / Merchant conversations — spec §4.10) ───────
   .bubble-bot uses the fixed violet "AI data" colour in every portal;
   .bubble-agent uses the current portal's accent (amber on Agent, etc). ── */
.bubble-customer, .bubble-bot, .bubble-agent {
    max-width: 70%; padding: 10px 14px; border-radius: 14px; line-height: 1.45; font-size: 13.5px;
}
.bubble-customer { background: var(--bg-surface-alt); border: 1px solid var(--border); border-radius: 14px 14px 14px 4px; color: var(--text-primary); }
.bubble-bot      { background: color-mix(in srgb, var(--series-bot) 12%, transparent); border: 1px solid color-mix(in srgb, var(--series-bot) 35%, transparent); border-radius: 14px 14px 4px 14px; color: var(--text-primary); margin-left: auto; }
.bubble-agent    { background: var(--accent-soft); border: 1px solid var(--accent-ring); border-radius: 14px 14px 4px 14px; color: var(--text-primary); margin-left: auto; }
.bubble-meta     { font-size: 11px; color: var(--text-faint); margin-top: 3px; }
.bubble-meta.bot   { color: var(--series-bot); }
.bubble-meta.agent { color: var(--accent-text); }
.bubble-system { text-align: center; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--accent-text); margin: 10px 0; }

/* Transcript building blocks shared by Components/Chat (LiveMessage on the agent dashboard,
   TranscriptMessage on both chat-detail pages), so every conversation reads the same:
     .chat-row             one message block; --right (bot / agent), --center (system)
     .chat-row--cont       follow-up of the same sender: tighter gap, no meta line, flatter
                           corner on the sender's side (the list's gap is 10px → 4px)
     .chat-meta            "name · AI · time" line above the first bubble of a group
     .chat-bubble--visitor neutral surface, left
     .chat-bubble--bot     fixed violet "AI data" tint (every portal), right
     .chat-bubble--agent   current portal accent (amber on Agent …), right
     .chat-bubble--colleague  another agent / the merchant: accent outline on a neutral fill
     .chat-system          centred mono caption between fading rules (claimed, closed …)
     .chat-day             sticky "Today / Yesterday / date" pill between days
     .chat-faq             "answered from FAQ" chip; .chat-suggestions inside a bot bubble
     .chat-media           image / video attachment (no bubble chrome) */
.chat-row { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.chat-row--right { align-items: flex-end; }
.chat-row--center { align-items: center; }
.chat-row--cont { margin-top: -6px; }
.chat-meta {
    display: flex; align-items: center; flex-wrap: wrap; gap: 0 5px; max-width: 85%;
    margin: 0 4px 4px; font-size: 11px; line-height: 1.4; color: var(--text-faint); font-variant-numeric: tabular-nums;
}
.chat-meta-name { font-weight: 600; color: var(--text-secondary); }
.chat-meta--bot .chat-meta-name { color: var(--series-bot); }
.chat-meta--agent .chat-meta-name { color: var(--accent-text); }
.chat-meta-sep { opacity: .7; }
.chat-ai-tag { display: inline-flex; align-items: center; gap: 3px; color: var(--series-bot); font-weight: 600; }
.chat-ai-tag svg, .chat-faq svg { width: 10px; height: 10px; fill: currentColor; flex-shrink: 0; }
.chat-bubble {
    max-width: min(70%, 560px); padding: 9px 13px; border-radius: 16px; border: 1px solid transparent;
    font-size: 13.5px; line-height: 1.5; color: var(--text-primary);
    white-space: pre-line; word-break: break-word; overflow-wrap: anywhere;
}
.chat-bubble a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.chat-bubble--visitor { background: var(--bg-surface); border-color: var(--border); border-bottom-left-radius: 5px; }
.chat-bubble--bot {
    background: color-mix(in srgb, var(--series-bot) 11%, var(--bg-surface));
    border-color: color-mix(in srgb, var(--series-bot) 30%, transparent); border-bottom-right-radius: 5px;
}
.chat-bubble--agent { background: var(--accent-soft); border-color: var(--accent-ring); border-bottom-right-radius: 5px; }
.chat-bubble--colleague { background: var(--bg-surface); border-color: var(--accent-ring); border-bottom-right-radius: 5px; }
/* Internal note: staff only — dashed warning tint so it never reads as a sent reply. */
.chat-bubble--note { background: var(--warning-bg); border: 1px dashed var(--warning-strong-border); border-bottom-right-radius: 5px; }
.chat-note-tag { display: inline-flex; align-items: center; gap: 3px; color: var(--warning-text-soft); font-weight: 600; }
.chat-note-tag svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
.chat-row--cont .chat-bubble--visitor { border-top-left-radius: 5px; }
.chat-row--cont .chat-bubble--bot,
.chat-row--cont .chat-bubble--agent,
.chat-row--cont .chat-bubble--colleague,
.chat-row--cont .chat-bubble--note { border-top-right-radius: 5px; }
.chat-media { display: block; max-width: min(240px, 70vw); width: 100%; height: auto; border-radius: 12px; border: 1px solid var(--border); background: var(--bg-subtle); }
img.chat-media { cursor: zoom-in; }
.chat-system {
    align-self: stretch; display: flex; align-items: center; justify-content: center; gap: 10px; padding: 2px 0;
    font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: .06em; text-transform: uppercase;
    color: var(--accent-text); text-align: center; white-space: pre-line;
}
.chat-system::before, .chat-system::after {
    content: ''; flex: 1 1 24px; height: 1px; max-width: 120px;
    background: linear-gradient(to right, transparent, color-mix(in srgb, var(--accent-text) 35%, transparent));
}
.chat-system::after { background: linear-gradient(to left, transparent, color-mix(in srgb, var(--accent-text) 35%, transparent)); }
.chat-system a { color: inherit; }
.chat-day { position: sticky; top: 0; z-index: 2; align-self: center; margin: 6px 0 2px; pointer-events: none; }
.chat-day span {
    display: inline-block; padding: 3px 10px; border-radius: var(--r-pill);
    background: var(--bg-surface); border: 1px solid var(--border); box-shadow: var(--shadow-sm);
    font-size: 11px; font-weight: 600; color: var(--text-muted); letter-spacing: .01em;
}
.chat-faq {
    display: inline-flex; align-items: center; gap: 4px; max-width: 75%; margin: 0 0 4px; padding: 2px 9px;
    background: color-mix(in srgb, var(--series-bot) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--series-bot) 28%, transparent); border-radius: var(--r-pill);
    font-size: 11px; font-weight: 500; color: var(--series-bot);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-faq > span, .chat-faq > a { overflow: hidden; text-overflow: ellipsis; color: inherit; }
.chat-faq > a { text-decoration: underline; }
.chat-suggestions { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; white-space: normal; }
.chat-suggestions > div { padding: 7px 10px; border-radius: var(--r-md); background: var(--bg-surface); border: 1px solid var(--border); font-size: 12.5px; }
@media (max-width: 768px) {
    .chat-bubble { max-width: 86%; }
    .chat-meta { max-width: 92%; }
}

/* ── Forms ────────────────────────────────────────────────────────────── */
.form-row   { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.form-group { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 160px; }

/* Styled file input (Components/FileInput.vue): visually-hidden native input + a dashed
   drop-zone box around the "Choose File" button — both the click-to-browse trigger and the
   drag target. Row layout (button, file chip, hint) above the mobile breakpoint; the media
   query in "Responsive breakpoints" stacks them on narrow screens. */
.file-input-group {
    display: flex; flex-direction: row; align-items: center; gap: 10px; flex-wrap: wrap;
    position: relative; width: 100%; box-sizing: border-box; min-width: 0;
    border: 1.5px dashed var(--border-strong); border-radius: var(--r-lg);
    background: var(--bg-surface-alt);
    padding: 12px 14px;
    transition: background-color .12s, border-color .12s;
}
.file-input-group:hover:not(.file-input-disabled) { border-color: color-mix(in srgb, var(--accent) 45%, var(--border-strong)); }
.file-input-native { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }
.file-input-label { margin: 0; color: var(--text-secondary); background: var(--bg-surface); }
.file-input-label svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* Keyboard focus lands on the hidden native input — ring the visible button instead. */
.file-input-group:has(.file-input-native:focus-visible) .file-input-label { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); color: var(--text-primary); }
.file-input-group.file-input-disabled { opacity: .6; }
.file-input-group.file-input-disabled .file-input-label { cursor: not-allowed; }
.file-input-name { font-size: 12px; min-width: 0; }
/* The chosen file: a chip with icon, name (ellipsised) and size. */
.file-input-chip {
    display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
    padding: 4px 10px 4px 8px; border-radius: var(--r-pill);
    background: var(--accent-soft); border: 1px solid var(--accent-ring); color: var(--text-primary);
    font-weight: 500; line-height: 1.3;
}
.file-input-chip svg { width: 14px; height: 14px; flex-shrink: 0; fill: none; stroke: var(--accent-text); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.file-input-chip-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-input-chip-size { flex-shrink: 0; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.file-input-drop-hint { font-size: 12px; color: var(--text-faint); }
/* A file dragged over the box. */
.file-input-group.file-input-dragover { border-color: var(--accent); border-style: solid; background: var(--accent-tint); }
.file-input-group.file-input-dragover .file-input-drop-hint { color: var(--accent-text); font-weight: 600; }
/* A dropped file that doesn't match the input's accepted types (FileInput's rejectDrop()). */
.file-input-group.file-input-rejected { border-color: var(--danger-border); background: var(--danger-bg); }
.file-input-group.file-input-rejected .file-input-drop-hint { color: var(--danger-text); font-weight: 500; }
@media (prefers-reduced-motion: reduce) { .file-input-group { transition: none; } }

label { font-size: 12px; font-weight: 500; line-height: 1.4; color: var(--text-secondary); }

/* Text-like fields and selects share one box: 36px tall (min), same radius, hover + focus ring. */
input[type="text"],
input[type="email"],
input[type="password"],
input[type="date"],
input[type="number"],
input[type="url"],
input[type="tel"],
input[type="time"],
input[type="datetime-local"],
input[type="month"],
input[type="week"],
textarea,
select {
    width: 100%;
    min-height: 36px;
    padding: 8px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    font-size: 13px;
    line-height: 18px;
    font-family: inherit;
    background: var(--bg-surface);
    color: var(--text-primary);
    box-shadow: var(--shadow-xs);
    transition: border-color .15s, box-shadow .15s, background-color .15s;
}
:is(input[type="text"], input[type="email"], input[type="password"], input[type="date"], input[type="number"],
    input[type="url"], input[type="tel"], input[type="time"], input[type="datetime-local"], textarea, select):hover:not(:focus):not(:disabled) {
    border-color: color-mix(in srgb, var(--border-strong) 55%, var(--text-faint));
}
input:focus, textarea:focus, select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--focus-ring);
}
textarea { resize: vertical; min-height: 80px; line-height: 1.5; }
/* Single selects: one chevron in every browser/theme (multi-selects keep the native list box) */
select:not([multiple]):not([size]) {
    -webkit-appearance: none; appearance: none; padding-right: 32px; cursor: pointer;
    background-image: var(--select-chevron); background-repeat: no-repeat; background-position: right 10px center; background-size: 14px 14px;
}
/* Phones: fields match the 40px button height; touch devices get 16px text (no iOS focus zoom) */
@media (max-width: 768px) {
    :is(input[type="text"], input[type="email"], input[type="password"], input[type="date"], input[type="number"],
        input[type="url"], input[type="tel"], input[type="time"], input[type="datetime-local"], select) { min-height: 40px; }
}
@media (max-width: 768px) and (pointer: coarse) {
    :is(input[type="text"], input[type="email"], input[type="password"], input[type="date"], input[type="number"],
        input[type="url"], input[type="tel"], input[type="time"], input[type="datetime-local"], textarea, select) { font-size: 16px; }
}
:is(input, textarea, select):disabled { background-color: var(--bg-subtle); color: var(--text-muted); cursor: not-allowed; box-shadow: none; }
:is(input, textarea)[readonly] { background-color: var(--bg-surface-alt); }
::placeholder { color: color-mix(in srgb, var(--text-faint) 80%, transparent); opacity: 1; }

/* Invalid state: an explicit aria-invalid / .is-invalid, or a form group showing a non-empty
   .field-error (FormGroup.vue `error`, or a page's own <span class="field-error">). */
:is(input, textarea, select)[aria-invalid="true"],
:is(input, textarea, select).is-invalid,
.form-group.is-invalid :is(input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]), textarea, select),
.form-group:has(> .field-error:not(:empty)) :is(input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]), textarea, select) {
    border-color: var(--danger);
}
:is(input, textarea, select)[aria-invalid="true"]:focus,
:is(input, textarea, select).is-invalid:focus,
.form-group.is-invalid :is(input, textarea, select):focus,
.form-group:has(> .field-error:not(:empty)) :is(input, textarea, select):focus {
    border-color: var(--danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 20%, transparent);
}
.field-error { font-size: 12px; line-height: 1.45; color: var(--danger); margin-top: 2px; }
.field-error:empty { display: none; }
.field-error:not(:empty)::before {
    content: ""; display: inline-block; width: 13px; height: 13px; margin-right: 5px; vertical-align: -2px;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Help text under a field (FormGroup.vue `hint`) and the "(optional)" marker next to a label */
.field-hint { font-size: 12px; line-height: 1.45; color: var(--text-muted); }
.field-optional { font-weight: 400; color: var(--text-faint); margin-left: 4px; }

/* Checkboxes / radios use the portal accent (body accent-color); a little larger, pointer cursor */
input[type="checkbox"], input[type="radio"] { width: 16px; height: 16px; cursor: pointer; flex-shrink: 0; }
input[type="checkbox"]:focus, input[type="radio"]:focus { box-shadow: none; }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible { outline: var(--focus-outline); outline-offset: 2px; }
input[type="checkbox"]:disabled, input[type="radio"]:disabled { cursor: not-allowed; }
/* Switch: <input type="checkbox" class="switch"> (add role="switch" for screen readers) */
input[type="checkbox"].switch {
    -webkit-appearance: none; appearance: none; position: relative; flex-shrink: 0; vertical-align: middle;
    width: 34px; height: 20px; margin: 0; border: none; border-radius: var(--r-pill);
    background: color-mix(in srgb, var(--text-faint) 55%, var(--bg-surface));
    transition: background-color var(--dur) ease;
}
input[type="checkbox"].switch::before {
    content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
    background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.3); transition: transform var(--dur) var(--ease-out);
}
input[type="checkbox"].switch:checked { background: var(--accent); }
input[type="checkbox"].switch:checked::before { transform: translateX(14px); }
input[type="checkbox"].switch:disabled { opacity: .5; }

/* ── Password eye toggle ──────────────────────────────────────────────── */
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 40px !important; }
.pw-eye {
    position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
    background: none; border: none; cursor: pointer; border-radius: var(--r-sm);
    color: var(--text-faint); padding: 4px; display: flex; align-items: center;
    transition: background-color var(--dur-fast), color var(--dur-fast);
}
.pw-eye:hover { color: var(--text-secondary); background: color-mix(in srgb, var(--text-primary) 6%, transparent); }
.pw-eye:focus-visible { outline: var(--focus-outline); outline-offset: 0; }
.pw-eye svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ── Code / copy ──────────────────────────────────────────────────────── */
.code-block { background: var(--bg-surface-alt); border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 14px; font-family: var(--font-mono); font-size: 12px; color: var(--text-secondary); word-break: break-all; line-height: 1.6; }
/* CopyButton.vue default look: matches a small ghost button (.btn-sm height) */
.copy-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 4px; min-height: 28px; padding: 4px 10px;
    background: var(--bg-surface); border: 1px solid var(--border-strong); border-radius: var(--r-md);
    font-family: inherit; font-size: 12px; font-weight: 500; line-height: 18px; white-space: nowrap;
    cursor: pointer; color: var(--text-muted);
    transition: background-color var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.copy-btn:hover { background: color-mix(in srgb, var(--text-primary) 5%, var(--bg-surface)); color: var(--text-primary); }
.copy-btn:focus-visible { outline: var(--focus-outline); outline-offset: 2px; }
.copy-btn.is-copied { color: var(--success-text); border-color: var(--success-border); background: var(--success-bg); }
@media (max-width: 768px) { .copy-btn { min-height: 36px; } }

/* ── Pagination ───────────────────────────────────────────────────────── */
/* Components/Pagination.vue (Laravel paginator links) — same look as DataTable.vue's pager. */
.pagination-wrap { padding: 10px 20px; border-top: 1px solid var(--divider); }
.pagination-wrap .pagination { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
.pagination-wrap .page-link {
    display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 32px; padding: 0 10px;
    border: 1px solid transparent; border-radius: var(--r-md); background: transparent;
    font-size: 13px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--text-secondary); text-decoration: none;
    transition: background-color .12s, color .12s, border-color .12s;
}
.pagination-wrap .page-item:first-child .page-link,
.pagination-wrap .page-item:last-child .page-link { border-color: var(--border-strong); color: var(--text-primary); }
.pagination-wrap a.page-link:hover { background: var(--bg-surface-alt); border-color: var(--border-strong); color: var(--text-primary); text-decoration: none; }
.pagination-wrap a.page-link:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
.pagination-wrap .page-item.active .page-link {
    background: var(--accent-soft); border-color: transparent; color: var(--text-primary); font-weight: 600;
    box-shadow: inset 0 0 0 1px var(--accent-ring);
}
.pagination-wrap .page-item.disabled .page-link { color: var(--text-disabled); border-color: var(--divider); cursor: not-allowed; }

/* ── Misc ─────────────────────────────────────────────────────────────── */
.text-muted { color: var(--text-faint); font-size: 12px; }
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }
/* Visually hidden but read by screen readers (e.g. a label for an icon-only control) */
.sr-only, .visually-hidden {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* -- Mobile top bar, sidebar drawer overlay & hamburger toggle (≤768px) -- */
/* PortalShell.vue: the hamburger (#sidebarToggle) lives in a fixed top bar with the workspace
   name, so it never floats over page headers or the agent inbox. Hidden on desktop. */
.mobile-topbar { display: none; }
.mobile-topbar-brand { display: flex; align-items: center; gap: 9px; min-width: 0; flex: 1; }
.mobile-topbar-logo {
    width: 26px; height: 26px; border-radius: 7px; flex-shrink: 0; padding: 4px;
    background: linear-gradient(var(--logo-gradient));
    display: flex; align-items: center; justify-content: center;
}
.mobile-topbar-logo img { width: 100%; height: 100%; object-fit: contain; display: block; filter: brightness(0) invert(1); }
.mobile-topbar-name { font-size: 14px; font-weight: 600; letter-spacing: -.2px; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.mobile-topbar-end { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.mobile-topbar-status {
    display: inline-flex; align-items: center; gap: 2px; padding: 4px 10px 4px 4px; border-radius: var(--r-pill);
    background: var(--success-bg); color: var(--success-text); font-size: 12px; font-weight: 600; white-space: nowrap;
}
.mobile-topbar-status.offline { background: var(--bg-subtle); color: var(--text-muted); }

.sidebar-overlay {
    position: fixed; inset: 0; z-index: 498;
    background: rgba(5,4,9,.48);
    opacity: 0; visibility: hidden;
    transition: opacity .2s ease, visibility 0s linear .2s;
}
.sidebar-overlay.show { opacity: 1; visibility: visible; transition: opacity .2s ease; }

.sidebar-toggle {
    display: flex; flex-shrink: 0; width: 38px; height: 38px; padding: 0;
    align-items: center; justify-content: center;
    background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--r-md);
    color: var(--text-secondary); cursor: pointer; transition: background .12s, border-color .12s;
}
.sidebar-toggle:hover { background: var(--bg-surface-alt); border-color: var(--border-strong); }
.sidebar-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sidebar-toggle svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
@media (prefers-reduced-motion: reduce) {
    .sidebar-overlay, .sidebar-overlay.show, .app-sidebar, .app-sidebar.open { transition: none !important; }
}

/* -- Responsive breakpoints --------------------------------- */
@media (max-width: 768px) {
    /* Shell: fixed top bar + off-canvas drawer (PortalShell.vue) */
    .mobile-topbar {
        display: flex; align-items: center; gap: 10px;
        position: fixed; top: 0; left: 0; right: 0; z-index: 400;
        height: 52px; padding: 0 12px;
        background: var(--bg-surface);
        border-bottom: 1px solid var(--border);
    }

    /* Sidebar becomes an off-canvas drawer; visibility:hidden while closed keeps its links out
       of the tab order (it flips back only after the slide-out finishes). */
    .app-sidebar {
        position: fixed !important;
        width: min(300px, 86vw) !important;
        top: 0; bottom: 0; left: 0;
        z-index: 499;
        transform: translateX(-102%); visibility: hidden;
        transition: transform .24s cubic-bezier(.4,0,.2,1), visibility 0s linear .24s;
        box-shadow: none;
    }
    .app-sidebar.open { transform: none; visibility: visible; box-shadow: 8px 0 32px rgba(0,0,0,.28); transition: transform .24s cubic-bezier(.4,0,.2,1); }
    .sidebar-close { display: inline-flex; }

    /* Main area fills full width; allow vertical scroll. Top padding clears the fixed top bar.
       While the drawer is open the page behind it doesn't scroll. */
    .app-main { overflow-y: auto !important; padding-top: 52px; }
    html.portal-drawer-open .app-main { overflow: hidden !important; }
    .shell-banner { position: relative; padding: 10px 14px; }

    /* Page padding */
    .page { padding: 16px 14px 20px; }
    .page-header { flex-wrap: wrap; gap: 8px; }

    /* Stat grid: 2 columns on tablet */
    .stat-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }

    /* Tables: horizontally scrollable (DataTables lays out its own table, skip it) */
    .card { overflow: visible; }
    table:not(.dataTable) { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }

    /* Chat detail: single column */
    .layout-grid { grid-template-columns: 1fr !important; }

    /* Role columns: stack vertically */
    .roles-columns { flex-direction: column !important; }

    /* Profile columns: stack vertically */
    .profile-columns { flex-direction: column !important; align-items: stretch !important; }
    .profile-columns > div { max-width: none !important; }

    /* Snippet columns: stack vertically */
    .snippet-columns { flex-direction: column !important; }

    /* Form rows (e.g. two fields side by side): stack vertically rather than cramming */
    .form-row { flex-direction: column !important; align-items: stretch !important; }
    .form-row > * { flex: none !important; width: 100% !important; }

    /* Agent workspace: stack vertically */
    .workspace { flex-direction: column !important; overflow: visible !important; }
    .workspace > .sidebar {
        width: 100% !important; max-height: 45vh;
        border-right: none !important; border-bottom: 1px solid var(--border);
    }
    .workspace > .chat-panel { min-height: 50vh; }
}

@media (max-width: 480px) {
    .stat-grid { grid-template-columns: 1fr; }
    .page-header { flex-direction: column; align-items: flex-start; }
    .file-input-group { flex-direction: column; text-align: center; }
}

/* ── DataTables ───────────────────────────────────────────────────────────
   The list kit (Components/DataTable/DataTable.vue) carries its whole look — toolbar,
   search, per-page select, sortable headers, loading bar, empty row, pager — in its own
   scoped <style>. Nothing global here on purpose: the old `!important` toolbar rules would
   override it. ─────────────────────────────────────────────────────────── */
