/* =========================================================================
   SaaS Platform — Console Design System
   -------------------------------------------------------------------------
   Structure of this file:
     1. Tokens          — the only place raw values live
     2. Reset + type    — base element styles
     3. Primitives      — buttons, fields, badges, chips, alerts
     4. App shell       — topbar, sidebar, content column
     5. Blocks          — page header, cards, stats, tables, meters
     6. Features        — datasets, docs, APIs, integration, chat, detail
     7. Responsive + motion
     8. Website review — the client's status panel and the admin's queue
     9. Client console  — the ChatBIQ design system, scoped to the client shell

   Everything below reads from the token layer, so a theme is a token swap
   (see [data-theme="light"]) rather than a rewrite.
   ========================================================================= */

/* =========================================================================
   1. TOKENS
   ========================================================================= */
:root {
    /* --- Neutral ramp. Slightly blue-cast; pure black reads flat on screens. */
    --n-950: #08090c;
    --n-900: #0c0e13;
    --n-850: #11141a;
    --n-800: #161922;
    --n-750: #1c2029;
    --n-700: #252a35;
    --n-600: #333947;
    --n-500: #4a5162;

    /* --- Brand */
    --brand-700: #6d28d9;
    --brand-600: #7c3aed;
    --brand-500: #8b5cf6;
    --brand-400: #a78bfa;
    --brand-300: #c4b5fd;

    /* --- Status */
    --green-500: #22c55e;
    --green-400: #4ade80;
    --amber-500: #f59e0b;
    --red-500: #ef4444;
    --red-400: #f87171;
    --blue-500: #3b82f6;

    /* --- Semantic surfaces (what components actually reference) */
    --canvas: var(--n-950);
    --surface: var(--n-850);
    --surface-raised: var(--n-800);
    --surface-sunken: var(--n-900);
    --surface-hover: rgba(255, 255, 255, 0.04);
    --surface-active: rgba(255, 255, 255, 0.07);
    --chrome: rgba(10, 12, 16, 0.85);

    /* --- Semantic text */
    --text: #eef0f4;
    --text-strong: #ffffff;
    --text-muted: #a2a9b7;
    --text-subtle: #6d7484;

    /* --- Borders + accents */
    --border: rgba(255, 255, 255, 0.07);
    --border-strong: rgba(255, 255, 255, 0.13);
    --field-bg: rgba(255, 255, 255, 0.035);
    --field-bg-focus: rgba(255, 255, 255, 0.06);
    /* Meter/progress groove. Needs more presence than --surface-active, which
       disappears against a dark card at 6px tall. */
    --track: var(--n-700);

    --accent: var(--brand-500);
    --accent-hover: var(--brand-600);
    --accent-text: #ffffff;
    --accent-soft: rgba(139, 92, 246, 0.14);
    --accent-line: rgba(139, 92, 246, 0.32);
    --on-accent-muted: var(--brand-300);

    --success: var(--green-400);
    --success-soft: rgba(34, 197, 94, 0.13);
    --warning: var(--amber-500);
    --warning-soft: rgba(245, 158, 11, 0.13);
    --danger: var(--red-400);
    --danger-soft: rgba(239, 68, 68, 0.13);
    --info: var(--blue-500);
    --info-soft: rgba(59, 130, 246, 0.13);

    /* --- Spacing: 4px grid. Use these, not ad-hoc rem values. */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-5: 1.25rem;
    --sp-6: 1.5rem;
    --sp-8: 2rem;
    --sp-10: 2.5rem;
    --sp-12: 3rem;

    /* --- Type scale */
    --fs-xs: 0.75rem;
    --fs-sm: 0.8125rem;
    --fs-base: 0.875rem;
    --fs-md: 0.9375rem;
    --fs-lg: 1.0625rem;
    --fs-xl: 1.25rem;
    --fs-2xl: 1.5rem;
    --fs-3xl: 1.875rem;
    --font: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-mono: 'JetBrains Mono', 'Consolas', 'Menlo', monospace;

    /* --- Radii */
    --r-sm: 6px;
    --r-md: 8px;
    --r-lg: 12px;
    --r-xl: 16px;
    --r-full: 999px;

    /* --- Elevation */
    --e-1: 0 1px 2px rgba(0, 0, 0, 0.4);
    --e-2: 0 4px 12px -2px rgba(0, 0, 0, 0.45);
    --e-3: 0 12px 32px -8px rgba(0, 0, 0, 0.6);
    --ring: 0 0 0 3px rgba(139, 92, 246, 0.28);

    /* --- Layout metrics. Referenced by sticky offsets — keep in sync. */
    --topbar-h: 56px;
    --sidebar-w: 260px;
    --sidebar-w-collapsed: 68px;
    /* Wide enough that a 2500px screen reads as margin rather than dead space,
       while still capping line length on an ultrawide. */
    --content-max: 2100px;
    /* Width of the overview's support rail. Also the figure the two-column
       breakpoint below is derived from. */
    --rail-w: 400px;

    /* --- Motion */
    --ease: cubic-bezier(0.4, 0, 0.2, 1);
    --dur-fast: 0.12s;
    --dur: 0.2s;

    /* Back-compat aliases: older markup still references these names. */
    --primary: var(--accent);
    --primary-hover: var(--accent-hover);
    --primary-soft: var(--accent-soft);
    --text-main: var(--text);
    --text-dim: var(--text-subtle);
    --surface-2: var(--surface);
    --surface-solid: var(--surface-raised);
    --input-bg: var(--field-bg);
    --error: var(--danger);
    --error-soft: var(--danger-soft);
    --radius-sm: var(--r-md);
    --radius: var(--r-lg);
    --radius-lg: var(--r-lg);
    --radius-xl: var(--r-xl);
    --shadow: var(--e-2);
    --shadow-lg: var(--e-3);
}

/* Light theme: same components, swapped tokens. Toggled by the topbar button,
   which writes data-theme onto <html> and persists it in localStorage. */
[data-theme="light"] {
    --canvas: #f6f7f9;
    --surface: #ffffff;
    --surface-raised: #ffffff;
    --surface-sunken: #f1f3f6;
    --surface-hover: rgba(15, 23, 42, 0.04);
    --surface-active: rgba(15, 23, 42, 0.07);
    --chrome: rgba(255, 255, 255, 0.88);

    --text: #1b2130;
    --text-strong: #0b0f18;
    --text-muted: #5a6377;
    --text-subtle: #858da0;

    --border: rgba(15, 23, 42, 0.09);
    --border-strong: rgba(15, 23, 42, 0.16);
    --field-bg: #ffffff;
    --field-bg-focus: #ffffff;
    --track: rgba(15, 23, 42, 0.13);

    --accent: var(--brand-600);
    --accent-hover: var(--brand-700);
    --accent-soft: rgba(124, 58, 237, 0.1);
    --accent-line: rgba(124, 58, 237, 0.25);
    --on-accent-muted: var(--brand-700);

    --success: #15803d;
    --success-soft: rgba(34, 197, 94, 0.14);
    --warning: #b45309;
    --warning-soft: rgba(245, 158, 11, 0.16);
    --danger: #b91c1c;
    --danger-soft: rgba(239, 68, 68, 0.12);
    --info: #1d4ed8;
    --info-soft: rgba(59, 130, 246, 0.12);

    --e-1: 0 1px 2px rgba(15, 23, 42, 0.06);
    --e-2: 0 4px 12px -2px rgba(15, 23, 42, 0.1);
    --e-3: 0 12px 32px -8px rgba(15, 23, 42, 0.16);
}

/* =========================================================================
   2. RESET + TYPOGRAPHY
   ========================================================================= */
*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    font-size: 16px;
    scroll-behavior: smooth;
    background: var(--canvas);
}

body {
    font-family: var(--font);
    font-size: var(--fs-base);
    color: var(--text);
    background: var(--canvas);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5,
h6 {
    font-weight: 650;
    line-height: 1.25;
    color: var(--text-strong);
    letter-spacing: -0.015em;
}

h1 {
    font-size: var(--fs-3xl);
}

h2 {
    font-size: var(--fs-2xl);
}

h3 {
    font-size: var(--fs-lg);
}

h4 {
    font-size: var(--fs-md);
}

p {
    line-height: 1.6;
}

.subtitle {
    color: var(--text-muted);
    font-size: var(--fs-base);
}

.text-dim {
    color: var(--text-subtle);
}

.mono,
code,
kbd,
pre {
    font-family: var(--font-mono);
}

a {
    color: var(--accent);
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

a:hover {
    color: var(--accent-hover);
}

::selection {
    background: var(--accent-soft);
    color: var(--text-strong);
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Scrollbars — themed so the dark chrome doesn't get a bright OS scrollbar. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--n-700) transparent;
}

*::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

*::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: var(--r-full);
}

*::-webkit-scrollbar-thumb:hover {
    background: var(--text-subtle);
}

*::-webkit-scrollbar-track {
    background: transparent;
}

/* =========================================================================
   3. PRIMITIVES
   ========================================================================= */

/* --- Buttons ------------------------------------------------------------ */
.btn-primary,
.btn-secondary,
.btn-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding: 0.55rem 0.95rem;
    border-radius: var(--r-md);
    font-family: inherit;
    font-weight: 550;
    font-size: var(--fs-base);
    line-height: 1.3;
    white-space: nowrap;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
        color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.btn-primary svg,
.btn-secondary svg,
.btn-ghost svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.btn-primary {
    background: var(--accent);
    color: var(--accent-text);
    box-shadow: var(--e-1);
}

.btn-primary:hover {
    background: var(--accent-hover);
    color: var(--accent-text);
    box-shadow: var(--e-2);
}

.btn-secondary {
    background: var(--surface-raised);
    color: var(--text);
    border-color: var(--border-strong);
}

.btn-secondary:hover {
    background: var(--surface-active);
    color: var(--text-strong);
    border-color: var(--text-subtle);
}

.btn-ghost {
    background: transparent;
    color: var(--text-muted);
}

.btn-ghost:hover {
    background: var(--surface-hover);
    color: var(--text-strong);
}

.btn-primary:disabled,
.btn-secondary:disabled,
.btn-ghost:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    box-shadow: none;
}

.btn-danger-sm,
.btn-sm {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: 0.3rem 0.6rem;
    font-family: inherit;
    font-size: var(--fs-xs);
    font-weight: 550;
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.btn-danger-sm {
    background: var(--danger-soft);
    color: var(--danger);
    border: 1px solid transparent;
}

.btn-danger-sm:hover {
    background: var(--danger);
    color: #fff;
}

.w-100 {
    width: 100%;
}

/* Icon-only control used in the topbar and for row actions. */
.icon-btn {
    display: inline-grid;
    place-items: center;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border: 1px solid transparent;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.icon-btn:hover {
    background: var(--surface-hover);
    color: var(--text-strong);
}

.icon-btn svg {
    width: 18px;
    height: 18px;
}

/* The theme button swaps its two icons via the hidden attribute. SVG is not in
   the HTML namespace, so this is stated rather than left to the UA stylesheet. */
.icon-btn svg[hidden] {
    display: none;
}

/* --- Fields ------------------------------------------------------------- */
.form-group {
    margin-bottom: var(--sp-4);
    text-align: left;
}

.form-group label,
.field-label,
.embed-label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: var(--fs-sm);
    font-weight: 550;
    color: var(--text-muted);
}

.form-group input,
.form-group select,
.form-group textarea,
.inline-form input,
.detail-form input,
.detail-form select,
.api-form input[type="text"],
.dataset-name-input,
.field-input {
    width: 100%;
    padding: 0.55rem 0.75rem;
    background: var(--field-bg);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    color: var(--text);
    font-family: inherit;
    font-size: var(--fs-base);
    line-height: 1.4;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
        background var(--dur) var(--ease);
}

.form-group input::placeholder,
.inline-form input::placeholder,
.detail-form input::placeholder,
.api-form input[type="text"]::placeholder,
.dataset-name-input::placeholder,
.field-input::placeholder {
    color: var(--text-subtle);
}

.form-group input:hover,
.form-group select:hover,
.inline-form input:hover,
.detail-form input:hover,
.detail-form select:hover,
.dataset-name-input:hover {
    border-color: var(--text-subtle);
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus,
.inline-form input:focus,
.detail-form input:focus,
.detail-form select:focus,
.api-form input[type="text"]:focus,
.dataset-name-input:focus,
.field-input:focus {
    outline: none;
    border-color: var(--accent);
    background: var(--field-bg-focus);
    box-shadow: var(--ring);
}

.form-group input:disabled,
.dataset-name-input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Selects: native arrow removed, replaced with a token-coloured chevron so the
   control matches text inputs in both themes. */
.form-group select,
.detail-form select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.25rem;
    cursor: pointer;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a2a9b7' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 0.65rem center;
    background-size: 15px;
}

/* The popup list is painted by the OS and does not inherit the control's
   background, so it is set explicitly. */
.form-group select option,
.detail-form select option {
    background: var(--surface-raised);
    color: var(--text);
}

.form-group select option:checked {
    background: var(--accent);
    color: #fff;
}

.form-group select option[value=""] {
    color: var(--text-subtle);
}

.form-group input[type="date"],
.detail-form input[type="date"] {
    color-scheme: dark;
}

[data-theme="light"] .form-group input[type="date"],
[data-theme="light"] .detail-form input[type="date"] {
    color-scheme: light;
}

.form-help,
.cap-note {
    display: block;
    margin-top: 0.35rem;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
    line-height: 1.5;
}

.form-help ul {
    margin: 0.35rem 0 0 1rem;
}

.form-error {
    margin-top: 0.35rem;
    font-size: var(--fs-xs);
    font-weight: 500;
    color: var(--danger);
}

.form-actions {
    display: flex;
    gap: var(--sp-3);
    margin-top: var(--sp-5);
    padding-top: var(--sp-5);
    border-top: 1px solid var(--border);
}

.field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: var(--sp-4) var(--sp-5);
}

.field-grid .form-group {
    margin-bottom: 0;
}

.field-grid .full {
    grid-column: 1 / -1;
}

.form-section-title {
    font-size: var(--fs-md);
    font-weight: 600;
    margin-bottom: var(--sp-1);
    color: var(--text-strong);
}

/* Toggle field: label left, switch right, on one row. */
.form-group--toggle {
    display: flex;
    align-items: center;
}

.switch-label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    width: 100%;
    padding: 0.55rem 0.75rem;
    background: var(--field-bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    font-size: var(--fs-base);
    font-weight: 500;
    color: var(--text);
    cursor: pointer;
}

.switch-label input[type="checkbox"] {
    width: 38px;
    height: 21px;
    flex-shrink: 0;
    accent-color: var(--accent);
    cursor: pointer;
}

.form-group--toggle select {
    min-width: 110px;
}

/* File inputs ------------------------------------------------------------ */
.file-row {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-bottom: var(--sp-2);
}

.file-row input[type="file"] {
    flex: 1;
    min-width: 0;
    padding: 0.4rem 0.5rem;
    background: var(--field-bg);
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-md);
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--fs-sm);
    cursor: pointer;
}

.file-row input[type="file"]::file-selector-button {
    margin-right: var(--sp-3);
    padding: 0.35rem 0.75rem;
    background: var(--surface-raised);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    color: var(--text);
    font-family: inherit;
    font-size: var(--fs-xs);
    font-weight: 550;
    cursor: pointer;
    transition: background var(--dur) var(--ease);
}

.file-row input[type="file"]::file-selector-button:hover {
    background: var(--surface-active);
}

.remove-file {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--text-subtle);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    transition: all var(--dur) var(--ease);
}

.remove-file:hover {
    background: var(--danger-soft);
    border-color: transparent;
    color: var(--danger);
}

.add-file-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 0.8rem;
    background: transparent;
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-md);
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--fs-sm);
    font-weight: 550;
    cursor: pointer;
    transition: all var(--dur) var(--ease);
}

.add-file-btn:hover:not(:disabled) {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-soft);
}

/* Kept visible when a plan limit is hit, so the cap is legible rather than
   the control silently vanishing. */
.add-file-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.add-file-btn .plus {
    font-size: 1rem;
    line-height: 1;
}

.cap-note[hidden] {
    display: none;
}

/* --- Badges, chips, pills ----------------------------------------------- */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    border-radius: var(--r-full);
    font-size: var(--fs-xs);
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

.badge::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
}

.badge-completed {
    background: var(--success-soft);
    color: var(--success);
}

.badge-pending {
    background: var(--warning-soft);
    color: var(--warning);
}

.badge-failed {
    background: var(--danger-soft);
    color: var(--danger);
}

/* Refunded is not a failure -- the money moved, and then moved back -- so it
   reads as neutral rather than red. Without this rule the badge inherited no
   colour at all and the status was invisible against the row. */
.badge-refunded {
    background: var(--surface-3, rgba(255, 255, 255, 0.06));
    color: var(--text-muted);
}

.license-chip,
.integration-key {
    display: inline-block;
    padding: 0.2rem 0.5rem;
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    border-radius: var(--r-sm);
    color: var(--on-accent-muted);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    white-space: nowrap;
}

/* A row of read-only state -- a badge, a chip, a muted value -- above a form.
   Wraps rather than overflowing, because the chips carry key prefixes and model
   ids whose length is not ours to control. */
.status-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-3);
    margin-bottom: var(--sp-2);
}

.pkg-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.2rem 0.6rem;
    border-radius: var(--r-full);
    font-size: var(--fs-xs);
    font-weight: 600;
    border: 1px solid transparent;
}

.pkg-pro {
    background: rgba(245, 158, 11, 0.14);
    border-color: rgba(245, 158, 11, 0.4);
    color: var(--amber-500);
    box-shadow: 0 0 10px rgba(245, 158, 11, 0.4);
}

.pkg-standard {
    background: rgba(148, 163, 184, 0.16);
    border-color: rgba(148, 163, 184, 0.4);
    color: #94a3b8;
    box-shadow: 0 0 10px rgba(148, 163, 184, 0.4);
}

.pkg-basic {
    background: rgba(139, 69, 19, 0.14);
    border-color: rgba(139, 69, 19, 0.4);
    color: #8b4513;
    box-shadow: 0 0 10px rgba(139, 69, 19, 0.4);
}

/* The tier an account starts on. Deliberately the quietest chip of the set —
   it marks a state to move out of, so it doesn't compete with the paid tiers. */
.pkg-free {
    background: var(--surface-sunken);
    border-color: var(--border-strong);
    color: var(--text-muted);
}

/* --- Alerts ------------------------------------------------------------- */
.messages {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-6) 0;
}

.alert {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-2);
    padding: 0.7rem 0.95rem;
    border-radius: var(--r-md);
    border: 1px solid transparent;
    border-left-width: 3px;
    font-size: var(--fs-base);
}

.alert-error {
    background: var(--danger-soft);
    border-left-color: var(--danger);
    color: var(--danger);
}

.alert-success {
    background: var(--success-soft);
    border-left-color: var(--success);
    color: var(--success);
}

.alert-info,
.alert-warning {
    background: var(--info-soft);
    border-left-color: var(--info);
    color: var(--info);
}

.alert-warning {
    background: var(--warning-soft);
    border-left-color: var(--warning);
    color: var(--warning);
}

/* =========================================================================
   4. APP SHELL
   ========================================================================= */

/* --- Topbar ------------------------------------------------------------- */
.navbar {
    position: sticky;
    top: 0;
    z-index: 120;
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    height: var(--topbar-h);
    padding: 0 var(--sp-4);
    background: var(--chrome);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--border);
}

.nav-left,
.nav-right {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

.nav-left {
    flex-shrink: 0;
}

.nav-right {
    margin-left: auto;
}

.nav-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: var(--fs-md);
    font-weight: 650;
    letter-spacing: -0.02em;
    color: var(--text-strong);
}

.nav-brand:hover {
    color: var(--text-strong);
}

.brand-mark {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border-radius: var(--r-md);
    background: linear-gradient(140deg, var(--brand-400), var(--brand-600));
    color: #fff;
    font-size: var(--fs-sm);
    font-weight: 700;
    box-shadow: var(--e-1);
}

.brand-mark svg {
    width: 16px;
    height: 16px;
}

/* Divider + current-section label, so the topbar states where you are. */
.nav-context {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-width: 0;
    color: var(--text-subtle);
    font-size: var(--fs-base);
}

.nav-context::before {
    content: "";
    width: 1px;
    height: 18px;
    background: var(--border-strong);
}

.nav-context strong {
    font-weight: 550;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-links {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

.nav-link {
    padding: 0.4rem 0.7rem;
    border-radius: var(--r-md);
    color: var(--text-muted);
    font-size: var(--fs-base);
    font-weight: 500;
    transition: all var(--dur) var(--ease);
}

.nav-link:hover {
    background: var(--surface-hover);
    color: var(--text-strong);
}

.welcome-msg {
    color: var(--text-subtle);
    font-size: var(--fs-sm);
}

/* Sidebar toggle — visible on every width; it collapses the rail on desktop
   and opens the drawer on mobile. */
.sidebar-toggle {
    display: inline-grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border: none;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: all var(--dur) var(--ease);
}

.sidebar-toggle:hover {
    background: var(--surface-hover);
    color: var(--text-strong);
}

.sidebar-toggle svg {
    width: 18px;
    height: 18px;
}

/* --- User menu ---------------------------------------------------------- */
.user-menu {
    position: relative;
}

.user-menu-trigger {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 0.25rem 0.5rem 0.25rem 0.25rem;
    border: 1px solid transparent;
    border-radius: var(--r-full);
    background: transparent;
    color: var(--text);
    font-family: inherit;
    font-size: var(--fs-base);
    cursor: pointer;
    transition: all var(--dur) var(--ease);
}

.user-menu-trigger:hover,
.user-menu.is-open .user-menu-trigger {
    background: var(--surface-hover);
    border-color: var(--border);
}

.user-avatar {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border-radius: 50%;
    background: linear-gradient(140deg, var(--brand-400), var(--brand-600));
    color: #fff;
    font-size: var(--fs-xs);
    font-weight: 650;
    text-transform: uppercase;
}

.user-menu-name {
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}

.user-menu-caret {
    width: 14px;
    height: 14px;
    color: var(--text-subtle);
    transition: transform var(--dur) var(--ease);
}

.user-menu.is-open .user-menu-caret {
    transform: rotate(180deg);
}

.user-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 200;
    min-width: 232px;
    padding: var(--sp-1);
    background: var(--surface-raised);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--e-3);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
        visibility var(--dur) var(--ease);
}

.user-menu.is-open .user-dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.user-dropdown-head {
    padding: var(--sp-3);
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--sp-1);
}

.user-dropdown-head strong {
    display: block;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--text-strong);
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-dropdown-head span {
    display: block;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-dropdown a,
.user-dropdown button {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    padding: 0.5rem 0.65rem;
    border: none;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: all var(--dur-fast) var(--ease);
}

.user-dropdown a:hover,
.user-dropdown button:hover {
    background: var(--surface-hover);
    color: var(--text-strong);
}

.user-dropdown svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.user-dropdown .is-danger:hover {
    background: var(--danger-soft);
    color: var(--danger);
}

.role-chip {
    display: inline-block;
    margin-top: 0.3rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--r-full);
    background: var(--accent-soft);
    color: var(--on-accent-muted);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

/* --- Support notification bell (admin topbar) ---------------------------
   Sits beside the theme toggle. The bell glows while unread client messages
   are outstanding and drops a panel listing who wrote and when — never the
   message text itself. */
.notif {
    position: relative;
}

.notif-trigger {
    position: relative;
}

/* Unread state. The ring is a box-shadow rather than a border so the button
   does not shift by a pixel when it lights up. */
.notif-trigger.has-unread {
    color: var(--accent);
}

.notif-trigger.has-unread::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    animation: notif-glow 2s var(--ease) infinite;
    pointer-events: none;
}

@keyframes notif-glow {
    0%, 100% { box-shadow: 0 0 0 0 var(--accent-line); }
    50% { box-shadow: 0 0 10px 3px var(--accent-line); }
}

/* One-shot pop when a message lands while the page is open, so a second
   message during an already-glowing state is still noticed. */
.notif-trigger.is-pinged svg {
    animation: notif-swing 0.6s var(--ease);
}

@keyframes notif-swing {
    0%, 100% { transform: rotate(0); }
    20% { transform: rotate(-14deg); }
    40% { transform: rotate(11deg); }
    60% { transform: rotate(-7deg); }
    80% { transform: rotate(4deg); }
}

@media (prefers-reduced-motion: reduce) {
    .notif-trigger.has-unread::after,
    .notif-trigger.is-pinged svg {
        animation: none;
    }
    .notif-trigger.has-unread::after {
        box-shadow: 0 0 0 2px var(--accent-line);
    }
}

.notif-badge {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: var(--r-full);
    background: var(--danger);
    color: #fff;
    font-size: 0.625rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
}

.notif-badge[hidden] {
    display: none;
}

/* Mirrors .user-dropdown so both topbar panels open identically. */
.notif-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 200;
    width: 320px;
    max-width: calc(100vw - 2rem);
    padding: var(--sp-1);
    background: var(--surface-raised);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--e-3);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
        visibility var(--dur) var(--ease);
}

.notif.is-open .notif-panel {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.notif-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    padding: var(--sp-3);
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--sp-1);
}

.notif-head strong {
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--text-strong);
}

.notif-clear {
    border: none;
    background: transparent;
    color: var(--accent);
    font-family: inherit;
    font-size: var(--fs-xs);
    font-weight: 600;
    cursor: pointer;
}

.notif-clear:hover {
    text-decoration: underline;
}

.notif-clear[hidden] {
    display: none;
}

/* Bounded so a long backlog scrolls inside the panel instead of running off
   the bottom of the viewport. */
.notif-list {
    max-height: 320px;
    overflow-y: auto;
}

.notif-item {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: 0.5rem 0.65rem;
    border-radius: var(--r-md);
    color: var(--text-muted);
    text-decoration: none;
    transition: background var(--dur-fast) var(--ease);
}

.notif-item:hover {
    background: var(--surface-hover);
}

.notif-avatar {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    border-radius: var(--r-full);
    background: var(--accent-soft);
    color: var(--accent);
    font-size: var(--fs-xs);
    font-weight: 700;
}

.notif-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.notif-text strong {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-strong);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.notif-time {
    font-size: var(--fs-xs);
    color: var(--text-subtle);
}

.notif-empty {
    padding: var(--sp-4) var(--sp-3);
    color: var(--text-subtle);
    font-size: var(--fs-sm);
    text-align: center;
}

/* --- Content column ----------------------------------------------------- */
.container {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    width: 100%;
}

/* --- Shell grid: admin and client panels share one layout --------------- */
.admin-panel,
.client-shell {
    position: relative;
    display: grid;
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
    width: 100%;
    min-height: calc(100vh - var(--topbar-h));
    align-items: stretch;
    transition: grid-template-columns var(--dur) var(--ease);
}

.admin-panel.is-collapsed,
.client-shell.is-collapsed {
    grid-template-columns: var(--sidebar-w-collapsed) minmax(0, 1fr);
}

/* The drawer scrim is a child of the shell grid, so it must be taken out of
   the layout entirely on desktop or it would claim the sidebar's column. It is
   only given a box inside the <=1024px block below. */
.sidebar-scrim {
    display: none;
}

/* --- Sidebar ------------------------------------------------------------ */
.panel-sidebar,
.client-sidebar {
    position: sticky;
    top: var(--topbar-h);
    z-index: 90;
    display: flex;
    flex-direction: column;
    height: calc(100vh - var(--topbar-h));
    padding: var(--sp-4) var(--sp-3);
    background: var(--surface-sunken);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    overflow-x: hidden;
}

.panel-title,
.client-sidebar-header h3,
.nav-group-label {
    padding: 0 var(--sp-3);
    margin-bottom: var(--sp-2);
    font-size: 0.6875rem;
    font-weight: 650;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--text-subtle);
    white-space: nowrap;
}

.client-sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--sp-1);
}

.sidebar-chevron {
    display: none;
}

/* Nav filter — types down the list below it. */
.sidebar-search {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-bottom: var(--sp-3);
    padding: 0.45rem 0.65rem;
    background: var(--field-bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.sidebar-search:focus-within {
    border-color: var(--accent);
    box-shadow: var(--ring);
}

.sidebar-search svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    color: var(--text-subtle);
}

.sidebar-search input {
    flex: 1;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    color: var(--text);
    font-family: inherit;
    font-size: var(--fs-sm);
}

.sidebar-search input::placeholder {
    color: var(--text-subtle);
}

.nav-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: var(--sp-4);
}

.nav-group:last-child {
    margin-bottom: 0;
}

.panel-nav,
.client-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
}

/* One rule drives both panels' nav items — <a> in admin, <button> in client. */
.panel-nav a,
.nav-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    padding: 0.5rem 0.7rem;
    border: none;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.panel-nav a svg,
.nav-item .nav-ic svg,
.nav-item svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.nav-item .nav-ic {
    display: inline-grid;
    place-items: center;
    flex-shrink: 0;
    color: inherit;
}

.nav-item .nav-txt,
.panel-nav a .nav-txt {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.panel-nav a:hover,
.nav-item:hover {
    background: var(--surface-hover);
    color: var(--text-strong);
}

/* A tab the client cannot open until their website is approved. Dimmed and
   badged with a padlock rather than removed: the point is to show what the
   product contains and that approval is what opens it. Still a live button --
   clicking it explains why, which a `disabled` attribute could not do. */
.nav-item.is-locked {
    color: var(--text-subtle);
    opacity: 0.65;
    cursor: not-allowed;
}

.nav-item.is-locked:hover {
    background: transparent;
    color: var(--text-subtle);
}

.nav-item.is-locked .nav-txt::after {
    content: "🔒";
    margin-left: 0.4rem;
    font-size: 0.75em;
    opacity: 0.8;
}

/* ---------------------------------------------------------------------------
   Website review state (client dashboard, Overview tab)
   --------------------------------------------------------------------------- */

.review-state {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-2);
    margin-bottom: var(--sp-4);
    padding: var(--sp-4);
    border: 1px solid var(--border);
    border-left: 3px solid var(--text-subtle);
    border-radius: var(--r-md);
    background: var(--surface-hover);
}

.review-state p {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: 1.6;
}

.review-state--approved { border-left-color: var(--success); }
.review-state--pending  { border-left-color: var(--warning); }
.review-state--rejected { border-left-color: var(--danger); }

/* Flashed when a client clicks a locked tab, so the answer to "why can't I
   open this" is visibly the thing that just moved. */
.review-state.is-flash {
    animation: review-flash 1.2s var(--ease);
}

@keyframes review-flash {
    0%, 100% { box-shadow: 0 0 0 0 transparent; }
    30%      { box-shadow: 0 0 0 4px var(--warning-soft); }
}

@media (prefers-reduced-motion: reduce) {
    .review-state.is-flash { animation: none; }
}

/* Active state: soft tint + a left rail, rather than a solid violet block —
   it stays legible next to the other items instead of shouting over them. */
.panel-nav a.is-active,
.nav-item.is-active {
    background: var(--accent-soft);
    color: var(--on-accent-muted);
    font-weight: 600;
}

.panel-nav a.is-active::before,
.nav-item.is-active::before {
    content: "";
    position: absolute;
    /* Pulled out by the sidebar's own horizontal padding so the rail sits
       flush against the sidebar edge. Keep in sync with .panel-sidebar. */
    left: calc(-1 * var(--sp-3));
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 18px;
    border-radius: 0 var(--r-full) var(--r-full) 0;
    background: var(--accent);
}

/* Pushes the account block to the bottom of the rail. */
.sidebar-footer {
    margin-top: auto;
    padding-top: var(--sp-3);
    border-top: 1px solid var(--border);
}

.sidebar-user {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-2);
    border-radius: var(--r-md);
    min-width: 0;
}

.sidebar-user .user-avatar {
    width: 30px;
    height: 30px;
}

.sidebar-user-info {
    min-width: 0;
    line-height: 1.35;
}

.sidebar-user-info strong {
    display: block;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-user-info span {
    display: block;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- Collapsed rail ----------------------------------------------------- */
.is-collapsed .panel-sidebar,
.is-collapsed .client-sidebar {
    padding-left: var(--sp-2);
    padding-right: var(--sp-2);
    align-items: stretch;
    /* The icon-only rail is short enough not to scroll, and it has to stop
       clipping so the hover tooltips below can escape its right edge. */
    overflow: visible;
}

.is-collapsed .panel-title,
.is-collapsed .client-sidebar-header,
.is-collapsed .nav-group-label,
.is-collapsed .sidebar-search,
.is-collapsed .nav-txt,
.is-collapsed .sidebar-user-info {
    display: none;
}

.is-collapsed .panel-nav a,
.is-collapsed .nav-item,
.is-collapsed .sidebar-user {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
}

/* Label becomes a hover tooltip once the rail is icon-only. */
.is-collapsed .panel-nav a::after,
.is-collapsed .nav-item::after {
    content: attr(data-label);
    position: absolute;
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%);
    z-index: 150;
    padding: 0.3rem 0.6rem;
    background: var(--surface-raised);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    box-shadow: var(--e-2);
    color: var(--text);
    font-size: var(--fs-xs);
    font-weight: 500;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur) var(--ease);
}

.is-collapsed .panel-nav a:hover::after,
.is-collapsed .nav-item:hover::after {
    opacity: 1;
}

/* --- Main content ------------------------------------------------------- */
.panel-content,
.client-main {
    width: 100%;
    max-width: var(--content-max);
    min-width: 0;
    padding: var(--sp-6) var(--sp-8) var(--sp-10);
}

/* =========================================================================
   5. BLOCKS
   ========================================================================= */

/* --- Page header -------------------------------------------------------- */
.panel-header,
.dashboard-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-bottom: var(--sp-6);
    padding-bottom: var(--sp-4);
    border-bottom: 1px solid var(--border);
}

.panel-header h2,
.dashboard-header h2 {
    font-size: var(--fs-2xl);
    margin-bottom: 0.15rem;
}

.panel-header .subtitle,
.dashboard-header p {
    margin-bottom: 0;
    color: var(--text-muted);
    font-size: var(--fs-base);
}

.panel-header.with-back {
    align-items: flex-start;
}

.page-head-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
}

.back-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: var(--sp-2);
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--text-subtle);
}

.back-link:hover {
    color: var(--text-strong);
}

.header-status {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

/* --- Section heading (inside panes) ------------------------------------- */
.section-heading {
    margin-bottom: var(--sp-4);
}

.section-heading h3 {
    font-size: var(--fs-lg);
    margin-bottom: 0.2rem;
}

.section-heading .subtitle {
    max-width: 68ch;
    font-size: var(--fs-base);
}

/* --- Card surfaces ------------------------------------------------------ */
.website-monitor { max-width: 1100px; }
.website-stage { display: inline-block; padding: .4rem .8rem; border-radius: 2rem; background: rgba(139,92,246,.15); color: var(--text); }
.website-monitor[data-stage="complete"] .website-stage { background: rgba(34,197,94,.15); color: #4ade80; }
.website-monitor[data-stage="unavailable"] .website-stage,
.website-monitor[data-stage="failed"] .website-stage { background: rgba(245,158,11,.15); color: #fbbf24; }
.website-build-steps { display: grid; gap: .7rem; margin: 1.5rem 0; padding: 0; list-style: none; counter-reset: build-step; }
.website-build-steps li { counter-increment: build-step; display: flex; align-items: center; gap: .75rem; color: var(--text-muted); }
.website-build-steps li::before { content: counter(build-step); display: grid; place-items: center; width: 2rem; height: 2rem; flex-shrink: 0; border: 1px solid var(--border); border-radius: 50%; }
.website-build-steps li.is-complete::before { content: '✓'; background: rgba(34,197,94,.15); color: #4ade80; }
.website-build-steps li.is-current { color: var(--text); font-weight: 600; }
.website-build-steps li.is-current::before { border-color: #a78bfa; background: rgba(139,92,246,.2); }
.website-metrics { display: grid; grid-template-columns: repeat(auto-fit,minmax(180px,1fr)); gap: 1rem; margin: 1.5rem 0; }
.website-metrics > div { padding: 1rem; border: 1px solid var(--border); border-radius: var(--r-lg); }
.website-metrics strong, .website-metrics span { display: block; }
.website-metrics strong { font-size: 1.2rem; margin-bottom: .3rem; }
.website-metrics span { color: var(--text-muted); }
.website-notice { padding: 1rem; border-left: 3px solid #fbbf24; background: rgba(245,158,11,.08); margin: 1rem 0; }
.website-actions { display: flex; gap: .75rem; flex-wrap: wrap; margin-top: 1rem; }
.website-actions [hidden], .website-notice[hidden] { display: none; }
.website-monitor > p { margin: .75rem 0; overflow-wrap: anywhere; }
.website-section,
.support-section,
.api-section,
.manage-section,
.datasets-section,
.panel-section,
.chat-panel,
.card-surface {
    margin-bottom: var(--sp-5);
    padding: var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--e-1);
}

.panel-section {
    margin-top: var(--sp-6);
}

.panel-section h3 {
    margin-bottom: var(--sp-4);
}

.manage-section > .subtitle,
.datasets-hint {
    margin-bottom: var(--sp-4);
    color: var(--text-muted);
    font-size: var(--fs-base);
}

.glass-inner {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: var(--sp-5);
}

/* --- Auth cards (register / payment, which share this shell) ------------- */
.auth-container {
    width: 100%;
    max-width: 430px;
    margin: auto;
    padding: var(--sp-8) var(--sp-4);
}

.glass-card {
    padding: var(--sp-8);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-xl);
    box-shadow: var(--e-3);
}

.auth-container .glass-card {
    text-align: center;
}

.auth-form {
    margin-top: var(--sp-6);
    text-align: left;
}

.auth-footer {
    margin-top: var(--sp-5);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--border);
    font-size: var(--fs-base);
    color: var(--text-muted);
}

/* --- Overview layout ----------------------------------------------------
   Narrow screens stack: main column, then the support chat below it. Wide
   screens lift the chat into the gutter beside the main column and pin it, so
   it is reachable without scrolling past everything else. The breakpoint is
   the point where the main column still has room once the rail is taken out. */
.overview-main > *:last-child {
    margin-bottom: 0;
}

/* The section cards pair up once there is room, so a wide main column carries
   two ~800px cards instead of one stretched to 1600px. */
@media (min-width: 1100px) {
    .overview-cards {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--sp-5);
        align-items: start;
    }

    .overview-cards > .website-section {
        margin-bottom: 0;
    }
}

@media (min-width: 1400px) {
    .overview-grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr) var(--rail-w);
        gap: var(--sp-5);
        align-items: start;
    }

    .overview-main {
        min-width: 0;
    }

    .overview-aside {
        position: sticky;
        top: calc(var(--topbar-h) + var(--sp-6));
        display: flex;
        flex-direction: column;
        /* Bounded by the viewport so the thread scrolls internally rather than
           pushing the rail past the fold. */
        max-height: calc(100vh - var(--topbar-h) - var(--sp-10));
    }

    .overview-aside .support-section {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-height: 0;
        margin-bottom: 0;
    }

    .overview-aside .section-heading,
    .overview-aside .chat-form {
        flex-shrink: 0;
    }

    /* Takes whatever height the rail has left over. */
    .overview-aside .chat-thread {
        flex: 1 1 auto;
        min-height: 200px;
        max-height: none;
    }
}

/* --- Stat tiles --------------------------------------------------------- */
.dashboard-stats {
    display: grid;
    /* 240px is the narrowest a horizontal tile reads well at: icon chip, gutter,
       then the label and value. */
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--sp-4);
    margin-bottom: var(--sp-5);
}

/* Horizontal tile: icon chip, then label over value. A wide tile then fills
   across rather than leaving a column of empty space under a short number. */
.stat-card {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--e-1);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
        transform var(--dur) var(--ease);
}

.stat-card:hover {
    border-color: var(--border-strong);
    box-shadow: var(--e-2);
    transform: translateY(-1px);
}

a.stat-card {
    color: inherit;
    text-decoration: none;
}

a.stat-card:hover {
    border-color: var(--accent-line);
}

.stat-ic {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    border-radius: var(--r-md);
    background: var(--accent-soft);
    color: var(--accent);
}

.stat-ic svg {
    width: 19px;
    height: 19px;
}

.stat-body {
    min-width: 0;
}

.stat-card h3 {
    margin-bottom: 0.1rem;
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-subtle);
}

.stat-value {
    font-size: var(--fs-2xl);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.03em;
    color: var(--text-strong);
    font-variant-numeric: tabular-nums;
}

/* Non-numeric stat values (plan name, license) need to sit at text size. */
.free-tier {
    font-size: var(--fs-xl);
    color: var(--brand-400);
}

/* An identifier rather than a figure — monospace, and sized to fit. */
.stat-value--code {
    font-family: var(--font-mono);
    font-size: var(--fs-md);
    font-weight: 600;
    letter-spacing: 0.02em;
    word-break: break-all;
}

[data-theme="light"] .free-tier {
    color: var(--brand-600);
}

.dashboard-actions {
    display: flex;
    gap: var(--sp-3);
    flex-wrap: wrap;
    margin-top: var(--sp-2);
}

/* --- Data tables -------------------------------------------------------- */
.table-wrap {
    width: 100%;
    overflow-x: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--e-1);
}

/* Toolbar sits above the table inside the same card. */
.table-toolbar {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--border);
}

.table-toolbar .sidebar-search {
    margin-bottom: 0;
    min-width: 240px;
    flex: 0 1 320px;
}

.table-count {
    margin-left: auto;
    font-size: var(--fs-sm);
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}

.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-base);
}

.data-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 0.65rem var(--sp-4);
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--border);
    color: var(--text-subtle);
    font-size: var(--fs-xs);
    font-weight: 650;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-align: left;
    white-space: nowrap;
}

.data-table tbody td {
    padding: 0.7rem var(--sp-4);
    border-bottom: 1px solid var(--border);
    color: var(--text-muted);
    vertical-align: middle;
}

.data-table tbody tr {
    transition: background var(--dur-fast) var(--ease);
}

.data-table tbody tr:hover {
    background: var(--surface-hover);
}

.data-table tbody tr:last-child td {
    border-bottom: none;
}

/* First column carries the row's identity, so it gets text weight. */
.data-table tbody td:first-child {
    color: var(--text);
    font-weight: 500;
}

.empty-row {
    padding: var(--sp-10) var(--sp-4) !important;
    text-align: center;
    color: var(--text-subtle);
}

/* Secondary line under a table cell's main value — a client's name beneath
   their email, where both belong in one column without a second header. */
.cell-sub {
    margin-top: 0.15rem;
    font-size: var(--fs-sm);
    color: var(--text-muted);
}

/* The storage meter inside a table cell. The standalone .meter is sized for a
   card and carries a bottom margin that would misalign the row; this drops the
   margin and constrains the width so a long "1.2 MB / 500 MB" label cannot
   stretch the column. */
.meter--cell {
    margin-bottom: 0;
    min-width: 130px;
}

.meter--cell .meter-head {
    margin-bottom: 0.3rem;
    font-size: var(--fs-xs);
}

.meter--cell .meter-track {
    height: 6px;
}

.client-link {
    font-weight: 550;
    color: var(--accent);
}

.client-link:hover {
    text-decoration: underline;
}

.table-link {
    display: inline-block;
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
    color: var(--text-muted);
}

.table-link:hover {
    color: var(--accent);
}

/* --- Empty state -------------------------------------------------------- */
.empty-state,
.chat-empty {
    padding: var(--sp-8) var(--sp-4);
    text-align: center;
    color: var(--text-subtle);
    font-size: var(--fs-base);
}

.empty-state svg {
    width: 32px;
    height: 32px;
    margin-bottom: var(--sp-3);
    color: var(--text-subtle);
    opacity: 0.6;
}

/* --- Meters + plan panel ------------------------------------------------ */
/* Flat by default — it already sits inside a card, and a second bordered box
   around it reads as a box in a box. The locked variant below opts back in,
   because there it is a call to action rather than a grouping. */
.plan-usage {
    padding: 0;
}

.plan-usage-head {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    margin-bottom: var(--sp-4);
    padding-bottom: var(--sp-3);
    border-bottom: 1px solid var(--border);
}

.plan-price {
    font-size: var(--fs-md);
    font-weight: 650;
    color: var(--text-strong);
}

.plan-valid {
    margin-left: auto;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
}

.plan-left {
    color: var(--text-subtle);
    font-weight: 400;
}

.plan-usage .summary-meta {
    margin-top: var(--sp-4);
}

.meter {
    margin-bottom: var(--sp-2);
}

.meter-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    margin-bottom: 0.4rem;
    font-size: var(--fs-sm);
    color: var(--text-muted);
}

.meter-head strong {
    font-weight: 600;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.meter-track {
    height: 8px;
    background: var(--track);
    border-radius: var(--r-full);
    overflow: hidden;
}

.meter-fill {
    height: 100%;
    /* A near-zero percentage still has to read as "a little", not as empty. */
    min-width: 6px;
    border-radius: var(--r-full);
    background: linear-gradient(90deg, var(--brand-500), var(--brand-400));
    transition: width 0.6s var(--ease);
}

/* Nearly out of storage — warn before the upload is rejected. */
.meter-fill.is-full {
    background: linear-gradient(90deg, var(--red-500), var(--amber-500));
}

/* No live subscription: the panel explains why instead of showing meters. */
.plan-usage--locked {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    padding: var(--sp-4);
    background: var(--surface-sunken);
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-md);
}

.plan-locked-msg {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-base);
}

/* Off-screen but still announced, for icons that carry meaning no text
   repeats. Not `display:none`, which would drop it from the accessibility
   tree along with the visual. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* --- Locked dashboard ---------------------------------------------------
   The entire page a client sees when they have no live plan. There is no
   workspace behind it to peek at — the dashboard view renders this template
   *instead of* the workspace one, so this is the whole screen and it is
   centred as such rather than laid out as a panel among others. */
.locked-shell {
    display: grid;
    place-items: center;
    /* Fills the viewport below the topbar so the card sits optically centred
       rather than clinging to the top of a mostly-empty page. */
    min-height: calc(100vh - var(--topbar-h) - var(--sp-8));
    padding: var(--sp-8) var(--sp-4);
}

.locked-card {
    width: 100%;
    max-width: 520px;
    padding: var(--sp-8);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-xl);
    box-shadow: var(--e-3);
    text-align: center;
}

.locked-ic {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin: 0 auto var(--sp-5);
    border-radius: var(--r-full);
    background: var(--accent-soft);
    color: var(--on-accent-muted);
}

.locked-ic svg {
    width: 26px;
    height: 26px;
}

.locked-card h1 {
    margin-bottom: var(--sp-3);
    font-size: var(--fs-xl);
    font-weight: 650;
    color: var(--text-strong);
}

.locked-card .pkg-chip {
    margin-bottom: var(--sp-3);
}

.locked-lead {
    margin-bottom: var(--sp-5);
    color: var(--text-muted);
    font-size: var(--fs-md);
    line-height: 1.6;
}

/* Reassurance for an expired client, and the start date for a pending one —
   secondary to the pitch above it, so it sits below the call to action. */
.locked-note {
    margin-top: var(--sp-4);
    color: var(--text-muted);
    font-size: var(--fs-base);
    line-height: 1.6;
}

.locked-cta {
    display: inline-block;
    padding: 0.7rem 1.6rem;
    font-size: var(--fs-md);
}

@media (max-width: 600px) {
    .locked-card {
        padding: var(--sp-6) var(--sp-5);
    }

    .locked-cta {
        display: block;
    }
}

/* --- Definition lists --------------------------------------------------- */
.summary-meta {
    list-style: none;
}

.summary-meta li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: 0.55rem 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-base);
}

.summary-meta li:last-child {
    border-bottom: none;
}

.summary-meta span {
    flex-shrink: 0;
    color: var(--text-subtle);
}

.summary-meta strong {
    font-weight: 550;
    color: var(--text);
    text-align: right;
    word-break: break-word;
}

.summary-meta .mono {
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
}

/* =========================================================================
   6. FEATURES
   ========================================================================= */

/* --- Website verification + license ------------------------------------- */
.inline-form {
    display: flex;
    gap: var(--sp-3);
    flex-wrap: wrap;
    align-items: center;
}

/* Capped: a URL field stretched to the full width of a wide card looks like a
   mistake, and the extra room buys no legibility. */
.inline-form input {
    flex: 1 1 260px;
    min-width: 0;
    max-width: 560px;
}

.inline-form .btn-primary,
.inline-form .btn-secondary {
    flex-shrink: 0;
}

.verified-url {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
    margin-top: var(--sp-4);
    word-break: break-all;
}

.verified-url a {
    font-size: var(--fs-base);
}

.license-card {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-top: var(--sp-4);
    padding: var(--sp-4);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    border-radius: var(--r-md);
}

.license-label {
    font-size: var(--fs-xs);
    font-weight: 650;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.license-value {
    font-family: var(--font-mono);
    font-size: var(--fs-md);
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--on-accent-muted);
    word-break: break-all;
}

.btn-copy {
    margin-left: auto;
    padding: 0.35rem 0.75rem;
    font-size: var(--fs-xs);
}

/* --- Client detail ------------------------------------------------------ */
.detail-grid {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    gap: var(--sp-5);
    align-items: start;
    margin-bottom: var(--sp-5);
}

.detail-summary {
    padding: var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--e-1);
    text-align: center;
}

.avatar {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    margin: 0 auto var(--sp-3);
    border-radius: 50%;
    background: linear-gradient(140deg, var(--brand-400), var(--brand-600));
    color: #fff;
    font-size: var(--fs-xl);
    font-weight: 650;
}

.summary-name {
    font-size: var(--fs-lg);
    font-weight: 650;
    color: var(--text-strong);
}

.summary-email {
    margin-bottom: var(--sp-4);
    font-size: var(--fs-sm);
    color: var(--text-subtle);
    word-break: break-all;
}

.detail-form {
    padding: var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--e-1);
}

.detail-form .form-section-title {
    margin-bottom: var(--sp-4);
    padding-bottom: var(--sp-3);
    border-bottom: 1px solid var(--border);
}

/* --- Datasets + documents ---------------------------------------------- */
.section-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    width: 100%;
    padding: 0;
    border: none;
    background: transparent;
    color: inherit;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.section-toggle:hover h3 {
    color: var(--accent);
}

.section-toggle h3 {
    font-size: var(--fs-lg);
    transition: color var(--dur) var(--ease);
}

.section-toggle .subtitle {
    margin-top: 0.15rem;
}

.chevron {
    flex-shrink: 0;
    color: var(--text-subtle);
    transition: transform var(--dur) var(--ease);
}

.chevron.is-open {
    transform: rotate(180deg);
}

.datasets-body {
    margin-top: var(--sp-4);
}

.dataset-card {
    margin-bottom: var(--sp-3);
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    overflow: hidden;
}

.dataset-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding: var(--sp-3) var(--sp-4);
    background: var(--surface-hover);
    border-bottom: 1px solid var(--border);
}

.dataset-head strong {
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--text-strong);
}

.dataset-head span {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    font-size: var(--fs-xs);
    color: var(--text-subtle);
}

.inline-delete {
    display: inline-flex;
}

.doc-list {
    list-style: none;
}

.doc-list li {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: 0.55rem var(--sp-4);
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-sm);
}

.doc-list li:last-child {
    border-bottom: none;
}

.doc-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text);
    font-weight: 500;
}

.doc-name:hover {
    color: var(--accent);
}

.doc-size {
    margin-left: auto;
    flex-shrink: 0;
    color: var(--text-subtle);
    font-size: var(--fs-xs);
    font-variant-numeric: tabular-nums;
}

.doc-type {
    flex-shrink: 0;
    width: 42px;
    padding: 0.15rem 0;
    border-radius: var(--r-sm);
    text-align: center;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    background: var(--surface-active);
    color: var(--text-muted);
}

.doc-pdf {
    background: var(--danger-soft);
    color: var(--danger);
}

.doc-csv {
    background: var(--success-soft);
    color: var(--success);
}

/* .doc covers legacy Word uploads, which the upload form still accepts. */
.doc-doc,
.doc-docx {
    background: var(--info-soft);
    color: var(--info);
}

/* Per-document index state. */
.doc-status {
    flex-shrink: 0;
    padding: 0.12rem 0.5rem;
    border-radius: var(--r-full);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.doc-status-uploaded {
    background: var(--surface-active);
    color: var(--text-subtle);
}

.doc-status-processing {
    background: var(--accent-soft);
    color: var(--on-accent-muted);
}

.doc-status-indexed {
    background: var(--success-soft);
    color: var(--success);
}

.doc-status-failed {
    background: var(--danger-soft);
    color: var(--danger);
}

/* --- Upload forms ------------------------------------------------------- */
.dataset-form,
.api-form,
.logo-form {
    margin-top: var(--sp-4);
    padding: var(--sp-4);
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
}

.dataset-name-input {
    margin-bottom: var(--sp-3);
}

.dataset-form-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    margin-top: var(--sp-3);
}

.dataset-form-actions .btn-primary {
    margin-left: auto;
}

/* --- Website APIs ------------------------------------------------------- */
.api-list {
    list-style: none;
    margin-bottom: var(--sp-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    overflow: hidden;
}

.api-list li {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding: 0.65rem var(--sp-4);
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-sm);
}

.api-list li:last-child {
    border-bottom: none;
}

.api-list .api-ic {
    display: inline-grid;
    place-items: center;
    flex-shrink: 0;
    color: var(--text-subtle);
}

.api-list .api-ic svg {
    width: 16px;
    height: 16px;
}

.api-url {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
}

.api-url:hover {
    color: var(--accent);
}

/* The badge takes over pushing the row's trailing items to the right. */
.api-list .api-badge {
    margin-left: auto;
    flex-shrink: 0;
    padding: 0.15rem 0.5rem;
    border-radius: var(--r-full);
    background: var(--surface-active);
    color: var(--text-subtle);
    font-size: 0.6875rem;
    font-weight: 600;
}

.api-list .api-badge--ok {
    background: var(--success-soft);
    color: var(--success);
}

.api-list .api-badge--fail {
    background: var(--danger-soft);
    color: var(--danger);
}

.api-date {
    flex-shrink: 0;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
}

.api-list .api-badge + .api-date {
    margin-left: 0;
}

.api-links {
    flex: 1 1 100%;
    margin-top: var(--sp-2);
}

.api-links summary {
    font-size: var(--fs-xs);
    color: var(--text-subtle);
    cursor: pointer;
}

.api-links summary:hover {
    color: var(--accent);
}

.api-links form {
    display: flex;
    gap: var(--sp-2);
    flex-wrap: wrap;
    margin-top: var(--sp-2);
}

.api-links label {
    font-size: var(--fs-xs);
    color: var(--text-muted);
}

.api-links .hint {
    font-size: var(--fs-xs);
    color: var(--text-subtle);
}

.api-links input {
    flex: 1 1 240px;
    padding: 0.4rem 0.6rem;
    background: var(--field-bg);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    color: var(--text);
    font-family: inherit;
    font-size: var(--fs-sm);
}

.api-links input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--ring);
}

.api-links code {
    padding: 0.1rem 0.3rem;
    background: var(--surface-active);
    border-radius: var(--r-sm);
    font-size: var(--fs-xs);
}

/* --- Logo pane ---------------------------------------------------------- */
.logo-preview {
    display: grid;
    place-items: center;
    min-height: 150px;
    margin-bottom: var(--sp-4);
    padding: var(--sp-5);
    background: var(--surface-sunken);
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-md);
}

.logo-preview img {
    max-width: 200px;
    max-height: 110px;
    object-fit: contain;
}

.logo-placeholder {
    color: var(--text-subtle);
    font-size: var(--fs-base);
}

.logo-form .file-row {
    margin-bottom: var(--sp-3);
}

.logo-remove-form {
    margin-top: var(--sp-2);
}

/* --- Integration -------------------------------------------------------- */
.integration-row {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    flex-wrap: wrap;
    padding: 0.65rem 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-base);
}

.integration-key-label {
    min-width: 130px;
    color: var(--text-subtle);
    font-size: var(--fs-sm);
}

.embed-label {
    margin-top: var(--sp-5);
}

.embed-code {
    padding: var(--sp-4);
    margin-bottom: var(--sp-3);
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    color: var(--brand-300);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    line-height: 1.65;
    white-space: pre-wrap;
    word-break: break-all;
    overflow-x: auto;
}

[data-theme="light"] .embed-code {
    color: var(--brand-700);
}

.embed-help {
    margin-top: var(--sp-3);
    max-width: 70ch;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: 1.65;
}

.embed-help code {
    padding: 0.1rem 0.3rem;
    background: var(--surface-active);
    border-radius: var(--r-sm);
    font-size: var(--fs-xs);
}

.embed-help strong {
    color: var(--text);
}

/* --- Reindex panel ------------------------------------------------------ */
.reindex-panel {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-top: var(--sp-4);
    padding: var(--sp-4);
    background: var(--surface-sunken);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
}

.reindex-copy {
    flex: 1 1 320px;
}

.reindex-copy strong {
    display: block;
    margin-bottom: 0.2rem;
    color: var(--text-strong);
}

.reindex-copy .subtitle {
    margin: 0;
    font-size: var(--fs-sm);
}

.reindex-copy code {
    padding: 0.1rem 0.35rem;
    background: var(--accent-soft);
    border-radius: var(--r-sm);
    color: var(--on-accent-muted);
    font-size: var(--fs-xs);
}

.reindex-panel button[disabled] {
    opacity: 0.6;
    cursor: progress;
}

/* --- Danger zone -------------------------------------------------------- */
.danger-zone {
    border-color: var(--danger) !important;
}

.danger-zone .form-section-title {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    color: var(--danger);
}

.danger-zone .subtitle {
    max-width: 70ch;
    margin-bottom: var(--sp-4);
}

.btn-danger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding: 0.55rem 0.95rem;
    border: 1px solid var(--danger);
    border-radius: var(--r-md);
    background: transparent;
    color: var(--danger);
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: 550;
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.btn-danger:hover {
    background: var(--danger);
    color: #fff;
}

.btn-danger svg {
    width: 16px;
    height: 16px;
}

/* --- Support chat ------------------------------------------------------- */
.chat-panel .form-section-title {
    margin-bottom: var(--sp-4);
}

.chat-thread {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    max-height: 380px;
    margin-bottom: var(--sp-4);
    padding: var(--sp-4);
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    overflow-y: auto;
}

.chat-message {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    max-width: 76%;
    align-self: flex-start;
    align-items: flex-start;
}

.chat-message.is-me {
    align-self: flex-end;
    align-items: flex-end;
}

/* Lifted off the sunken thread rather than sitting level with it — at
   --surface-raised the received bubbles were near-invisible against it. */
.chat-bubble {
    padding: 0.5rem 0.8rem;
    background: var(--surface-active);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    border-bottom-left-radius: var(--r-sm);
    color: var(--text);
    font-size: var(--fs-base);
    line-height: 1.5;
    word-break: break-word;
}

.chat-message.is-me .chat-bubble {
    background: var(--accent);
    border-color: transparent;
    color: #fff;
    border-bottom-left-radius: var(--r-lg);
    border-bottom-right-radius: var(--r-sm);
}

.chat-meta {
    padding: 0 0.25rem;
    font-size: 0.6875rem;
    color: var(--text-subtle);
    opacity: 0.75;
}

.chat-form {
    display: flex;
    align-items: flex-end;
    gap: var(--sp-3);
}

.chat-form textarea {
    flex: 1;
    min-width: 0;
    min-height: 44px;
    max-height: 160px;
    padding: 0.6rem 0.8rem;
    background: var(--field-bg);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    color: var(--text);
    font-family: inherit;
    font-size: var(--fs-base);
    line-height: 1.5;
    resize: vertical;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.chat-form textarea::placeholder {
    color: var(--text-subtle);
}

.chat-form textarea:focus {
    outline: none;
    border-color: var(--accent);
    background: var(--field-bg-focus);
    box-shadow: var(--ring);
}

.chat-form .btn-primary {
    flex-shrink: 0;
}

/* Tab panes -------------------------------------------------------------- */
.tab-pane[hidden] {
    display: none;
}

/* =========================================================================
   7. RESPONSIVE
   ========================================================================= */

/* Below this width the sidebar becomes an overlay drawer rather than a
   column, so the content keeps the full viewport. */
@media (max-width: 1024px) {
    .admin-panel,
    .client-shell,
    .admin-panel.is-collapsed,
    .client-shell.is-collapsed {
        grid-template-columns: minmax(0, 1fr);
    }

    .panel-sidebar,
    .client-sidebar {
        position: fixed;
        top: var(--topbar-h);
        left: 0;
        z-index: 130;
        width: var(--sidebar-w);
        height: calc(100vh - var(--topbar-h));
        transform: translateX(-100%);
        box-shadow: var(--e-3);
        transition: transform var(--dur) var(--ease);
    }

    /* On mobile the toggle opens the drawer instead of collapsing the rail,
       so the collapsed-rail rules must not apply here. */
    .is-collapsed .panel-sidebar,
    .is-collapsed .client-sidebar {
        transform: translateX(0);
        padding: var(--sp-4) var(--sp-3);
        /* Full-height drawer with labels, so it scrolls again — the desktop
           rail's overflow:visible must not leak down here. */
        overflow-y: auto;
        overflow-x: hidden;
    }

    .is-collapsed .panel-title,
    .is-collapsed .client-sidebar-header,
    .is-collapsed .nav-group-label,
    .is-collapsed .sidebar-search,
    .is-collapsed .nav-txt,
    .is-collapsed .sidebar-user-info {
        display: revert;
    }

    .is-collapsed .client-sidebar-header {
        display: flex;
    }

    .is-collapsed .sidebar-search {
        display: flex;
    }

    .is-collapsed .panel-nav a,
    .is-collapsed .nav-item,
    .is-collapsed .sidebar-user {
        justify-content: flex-start;
        padding-left: 0.7rem;
        padding-right: 0.7rem;
    }

    .is-collapsed .panel-nav a::after,
    .is-collapsed .nav-item::after {
        content: none;
    }

    .sidebar-scrim {
        display: block;
        position: fixed;
        inset: var(--topbar-h) 0 0 0;
        z-index: 125;
        background: rgba(0, 0, 0, 0.5);
        opacity: 0;
        visibility: hidden;
        transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
    }

    .is-collapsed .sidebar-scrim {
        opacity: 1;
        visibility: visible;
    }

    .panel-content,
    .client-main {
        padding: var(--sp-5) var(--sp-5) var(--sp-8);
    }

    .detail-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 768px) {
    .nav-context,
    .user-menu-name,
    .welcome-msg {
        display: none;
    }

    .panel-content,
    .client-main {
        padding: var(--sp-4) var(--sp-4) var(--sp-8);
    }

    .dashboard-stats {
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
        gap: var(--sp-3);
    }

    .panel-header,
    .dashboard-header {
        margin-bottom: var(--sp-5);
    }

    .field-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .data-table {
        font-size: var(--fs-sm);
    }

    .data-table thead th,
    .data-table tbody td {
        padding: 0.6rem var(--sp-3);
    }

    .table-toolbar .sidebar-search {
        flex: 1 1 100%;
        min-width: 0;
    }

    .license-card,
    .plan-usage--locked {
        flex-direction: column;
        align-items: flex-start;
    }

    .btn-copy {
        margin-left: 0;
    }
}

@media (max-width: 480px) {
    :root {
        --fs-3xl: 1.6rem;
        --fs-2xl: 1.35rem;
    }

    .dashboard-stats {
        grid-template-columns: minmax(0, 1fr);
    }

    .dashboard-actions,
    .form-actions,
    .chat-form {
        flex-direction: column;
        align-items: stretch;
    }

    .form-actions .btn-primary,
    .form-actions .btn-secondary,
    .chat-form .btn-primary {
        width: 100%;
    }

    .dataset-form-actions .btn-primary {
        margin-left: 0;
        width: 100%;
    }

    .chat-message {
        max-width: 90%;
    }

    .summary-meta li {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.15rem;
    }

    .summary-meta strong {
        text-align: left;
    }
}

/* =========================================================================
   8. MOTION
   ========================================================================= */
.gsap-hidden {
    visibility: hidden;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}



/* =========================================================================
   8. FEATURE: WEBSITE REVIEW
   -------------------------------------------------------------------------
   One decision, two views of it: the client's status panel on the dashboard
   and the admin's review queue. They are styled together and share a visual
   language on purpose — the pill-shaped input, the four status tones and the
   same word for each state — so a support call about "the amber one" means
   the same thing on both screens.

   The four tones map to the four values of User.website_status:
     unsubmitted -> info      pending  -> warning
     approved    -> success   rejected -> danger
   ========================================================================= */

/* -------------------------------------------------------------------------
   Shared: status tones
   -------------------------------------------------------------------------
   Set on the wrapper and read by everything inside it, so a state's colour is
   declared once instead of being repeated on the icon, the rail and the pill.
   --------------------------------------------------------------------- */
/* "none" is what User.website_status actually holds before a submission; the
   template's |default filter never fires on it because it is a truthy string.
   Both names are matched so the tone survives either spelling. */
.state-none,
.state-unsubmitted {
    --tone: var(--info);
    --tone-soft: var(--info-soft);
}

.state-pending {
    --tone: var(--warning);
    --tone-soft: var(--warning-soft);
}

.state-approved {
    --tone: var(--success);
    --tone-soft: var(--success-soft);
}

.state-rejected {
    --tone: var(--danger);
    --tone-soft: var(--danger-soft);
}


/* =========================================================================
   CLIENT SIDE — the status panel on the dashboard
   ========================================================================= */

/* The card carries a tinted rail down its leading edge rather than a coloured
   border all round: at four states a full outline turns the panel into a
   warning box even when the news is good. */
.premium-status-card {
    position: relative;
    overflow: hidden;
    margin-bottom: var(--sp-6);
    padding: var(--sp-6);
    padding-left: calc(var(--sp-6) + 3px);
    background: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--e-1);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.premium-status-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 3px;
    background: var(--tone, var(--accent));
}

.premium-status-card:hover {
    border-color: var(--border-strong);
    box-shadow: var(--e-2);
}

/* Only the good state gets a wash. It is a reward for having got through
   review, and putting one behind the rejected state would decorate bad news. */
.premium-status-card.state-approved {
    background:
        radial-gradient(130% 150% at 0% 0%, var(--success-soft) 0%, transparent 55%),
        var(--surface-raised);
}

/* --- Heading row -------------------------------------------------------- */
.status-header {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-bottom: var(--sp-3);
}

.status-icon-box {
    position: relative;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    border-radius: var(--r-md);
    background: var(--tone-soft, var(--accent-soft));
    color: var(--tone, var(--accent));
}

.status-icon-box svg {
    width: 22px;
    height: 22px;
}

/* A quiet ring that breathes while a review is open. It is the one animated
   thing on the panel: the client's question here is "is anything happening?",
   and a completely still page answers it badly. */
.status-icon-box.pending::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--r-md);
    animation: reviewPulse 2.4s var(--ease) infinite;
    color: var(--warning);
}

.status-header h3 {
    margin: 0;
    font-size: var(--fs-lg);
    font-weight: 650;
    letter-spacing: -0.01em;
    color: var(--text-strong);
}

.premium-status-card p {
    max-width: 64ch;
    margin-bottom: var(--sp-5);
    color: var(--text-muted);
    font-size: var(--fs-base);
    line-height: 1.65;
}

/* --- Progress tracker ---------------------------------------------------
   Three steps, all three always shown. A client whose review is open wants to
   know what is left, and a tracker that renders only the step reached cannot
   tell them. The rejected state replaces the last step rather than hiding it,
   so the path still reads left to right. */
.review-steps {
    display: flex;
    align-items: flex-start;
    margin: 0 0 var(--sp-5);
    padding: 0;
    list-style: none;
}

.review-steps li {
    position: relative;
    flex: 1;
    min-width: 0;
    padding-top: 30px;
    text-align: center;
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--text-subtle);
}

/* The connector, drawn on the step to the right of each gap so the first step
   has none, and stopping at the half-widths either side of the two dots. */
.review-steps li::before {
    content: "";
    position: absolute;
    top: 10px;
    right: 50%;
    left: -50%;
    height: 2px;
    background: var(--border-strong);
}

.review-steps li:first-child::before {
    display: none;
}

.review-steps li::after {
    content: "";
    position: absolute;
    top: 4px;
    left: 50%;
    width: 14px;
    height: 14px;
    margin-left: -7px;
    border: 2px solid var(--border-strong);
    border-radius: 50%;
    background: var(--surface-raised);
}

/* Steps already behind the client. */
.review-steps li.is-done {
    color: var(--text-muted);
}

.review-steps li.is-done::after {
    border-color: var(--success);
    background: var(--success);
}

.review-steps li.is-done::before,
.review-steps li.is-current::before {
    background: var(--success);
}

/* Where they are now — filled in the state's own tone and ringed, so it reads
   as the live step rather than one more completed one. */
.review-steps li.is-current {
    color: var(--text-strong);
}

.review-steps li.is-current::after {
    border-color: var(--tone, var(--accent));
    background: var(--tone, var(--accent));
    box-shadow: 0 0 0 4px var(--tone-soft, var(--accent-soft));
}

.review-steps li.is-failed {
    color: var(--danger);
}

.review-steps li.is-failed::before {
    background: var(--danger);
}

.review-steps li.is-failed::after {
    border-color: var(--danger);
    background: var(--danger);
    box-shadow: 0 0 0 4px var(--danger-soft);
}

.review-step-note {
    display: block;
    margin-top: 0.15rem;
    font-size: var(--fs-xs);
    font-weight: 500;
    color: var(--text-subtle);
}

/* --- The URL field ------------------------------------------------------
   A single pill rather than a field and a detached button: there is one thing
   to do on this panel, and splitting it into two controls makes the client
   hunt for which one submits. */
.premium-inline-form {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    max-width: 520px;
    padding: 4px 4px 4px var(--sp-3);
    background: var(--field-bg);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-full);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.premium-inline-form:focus-within {
    border-color: var(--accent);
    box-shadow: var(--ring);
}

.premium-inline-form > svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--text-subtle);
}

.premium-inline-form input[type="url"] {
    flex: 1;
    min-width: 0;
    padding: 0.55rem 0.25rem;
    background: transparent;
    border: none;
    box-shadow: none;
    outline: none;
    color: var(--text);
    font-size: var(--fs-base);
}

.premium-inline-form input[type="url"]:focus {
    border: none;
    box-shadow: none;
}

.premium-inline-form .btn-primary {
    flex-shrink: 0;
    padding: 0.55rem 1.15rem;
    border-radius: var(--r-full);
    font-size: var(--fs-sm);
    box-shadow: none;
}

.premium-form-hint {
    margin: var(--sp-2) 0 0;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
}

/* The URL as submitted, echoed back so the client can check what we are
   actually reviewing — a typo here is the commonest reason a review fails. */
.verified-url {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
    margin-top: var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    word-break: break-all;
}

.verified-url svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    color: var(--text-subtle);
}

.verified-url a {
    font-size: var(--fs-base);
    font-weight: 550;
}

.verified-url .subtitle {
    margin: 0 0 0 auto;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
    white-space: nowrap;
}

/* The reviewer's words, quoted rather than paraphrased. Toned on the edge so a
   client scanning the panel finds the reason without reading the prose. */
.review-reason {
    margin: 0 0 var(--sp-5);
    padding: var(--sp-3) var(--sp-4);
    background: var(--tone-soft, var(--danger-soft));
    border-left: 3px solid var(--tone, var(--danger));
    border-radius: 0 var(--r-md) var(--r-md) 0;
    color: var(--text);
    font-size: var(--fs-base);
    line-height: 1.6;
}

.review-reason strong {
    display: block;
    margin-bottom: 0.15rem;
    color: var(--tone, var(--danger));
    font-size: var(--fs-xs);
    font-weight: 650;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

@media (max-width: 560px) {
    .premium-status-card {
        padding: var(--sp-5);
        padding-left: calc(var(--sp-5) + 3px);
    }

    /* Stacked, because three labels across a phone truncate to nothing. The
       connector turns vertical so the sequence still reads. */
    .review-steps {
        flex-direction: column;
        align-items: stretch;
        gap: var(--sp-3);
    }

    .review-steps li {
        padding: 0 0 0 var(--sp-6);
        text-align: left;
    }

    .review-steps li::after {
        top: 2px;
        left: 0;
        margin-left: 0;
    }

    .review-steps li::before {
        top: -0.75rem;
        left: 6px;
        right: auto;
        width: 2px;
        height: 0.75rem;
    }

    .premium-inline-form {
        flex-wrap: wrap;
        border-radius: var(--r-lg);
    }

    .premium-inline-form .btn-primary {
        width: 100%;
    }

    .verified-url .subtitle {
        margin-left: 0;
    }
}

/* --- Locked page: a rejected client -------------------------------------
   Same card, different tone. A rejected client is not being sold to, so the
   purple lock chip would be the wrong note to open on. */
.locked-card.is-rejected .locked-ic {
    background: var(--danger-soft);
    color: var(--danger);
}

.locked-card .review-reason {
    margin: var(--sp-5) 0 0;
    text-align: left;
}


/* =========================================================================
   ADMIN SIDE — the review queue
   ========================================================================= */

/* --- The queue ----------------------------------------------------------
   The page opens straight on the rows. There is no strip of counts above it:
   the queue is short enough to read, the waiting pill on each row already says
   how bad the backlog is, and a tile reading "0" is the loudest thing on a
   screen that has nothing to report. */

/* Rows are taller here than in the other tables: each one carries a form, and
   a decision that refunds money should not be a 28px-high click target. */
.review-queue .data-table tbody td {
    padding: var(--sp-4);
    vertical-align: middle;
}

/* Marks the row being worked on. A left rail rather than the lift the other
   tables use — a row containing a focused text field must not move under the
   cursor while it is being typed into.

   The rail is painted on the first cell, not on the row: under
   border-collapse a <tr>'s own box-shadow is not rendered at all in Chrome. */
.review-queue .data-table tbody td:first-child {
    box-shadow: inset 0 0 0 0 var(--warning);
    transition: box-shadow var(--dur) var(--ease);
}

.review-queue .data-table tbody tr:hover,
.review-queue .data-table tbody tr:focus-within {
    background: var(--surface-hover);
}

.review-queue .data-table tbody tr:hover td:first-child,
.review-queue .data-table tbody tr:focus-within td:first-child {
    box-shadow: inset 3px 0 0 0 var(--warning);
}

/* Client identity: avatar, name, email. One column, because the name and the
   address are the same fact, and a second header for the second line would
   push the decision controls off a laptop screen. */
.queue-client {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-width: 0;
}

.queue-client .user-avatar {
    width: 32px;
    height: 32px;
    font-size: var(--fs-sm);
}

.queue-client-body {
    min-width: 0;
}

/* The submitted URL, which is the thing actually under review — given more
   presence than a table link elsewhere, and marked as leaving the panel. */
.queue-site {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    max-width: 320px;
    color: var(--text);
    font-size: var(--fs-base);
    font-weight: 500;
}

.queue-site svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    color: var(--text-subtle);
    transition: color var(--dur) var(--ease);
}

.queue-site span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.queue-site:hover,
.queue-site:hover svg {
    color: var(--accent);
}

/* --- Waiting time -------------------------------------------------------
   The queue's own service level, as a pill that changes tone the longer a
   client waits. The exact timestamp stays underneath: the pill is for triaging
   the queue, the timestamp for answering "when exactly?". */
.wait-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.2rem 0.6rem;
    border-radius: var(--r-full);
    background: var(--surface-active);
    color: var(--text-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    white-space: nowrap;
}

.wait-pill::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
}

.wait-pill.is-warn {
    background: var(--warning-soft);
    color: var(--warning);
}

.wait-pill.is-late {
    background: var(--danger-soft);
    color: var(--danger);
}

/* Only the overdue ones move. If every pill blinked, none would read as
   urgent. */
.wait-pill.is-late::before {
    animation: reviewPulse 2s var(--ease) infinite;
}

.wait-exact {
    margin-top: 0.3rem;
    font-size: var(--fs-xs);
    color: var(--text-subtle);
    white-space: nowrap;
}

/* --- The decision -------------------------------------------------------
   Approve is one button. Reject is a reason and a button joined into a single
   control, because a rejection refunds money and emails the client, and the
   reason is the part of it they will actually read. The box is inline rather
   than behind a modal on purpose: a reason that has to be revealed first is a
   reason that gets left blank. */
.review-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
}

.review-actions form {
    margin: 0;
}

.btn-approve {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.45rem 0.9rem;
    background: var(--success-soft);
    border: 1px solid transparent;
    border-radius: var(--r-full);
    color: var(--success);
    font-size: var(--fs-sm);
    font-weight: 650;
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
        border-color var(--dur) var(--ease);
}

.btn-approve svg {
    width: 14px;
    height: 14px;
}

.btn-approve:hover {
    background: var(--green-500);
    color: #fff;
}

.btn-approve:focus-visible {
    outline: none;
    border-color: var(--success);
    box-shadow: 0 0 0 3px var(--success-soft);
}

/* Reason box and reject button as one shell. The shell is neutral until it is
   touched and turns danger-toned on focus — the admin is told what they are
   about to do at the moment they start doing it, not before. */
.reject-group {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    padding: 3px;
    background: var(--field-bg);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-full);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.reject-group:focus-within {
    border-color: var(--danger);
    box-shadow: 0 0 0 3px var(--danger-soft);
}

.review-note-input {
    width: 170px;
    padding: 0.35rem 0.7rem;
    background: transparent;
    border: none;
    box-shadow: none;
    outline: none;
    color: var(--text);
    font-size: var(--fs-sm);
    transition: width var(--dur) var(--ease);
}

.review-note-input:focus {
    width: 250px;
    border: none;
    box-shadow: none;
}

.review-note-input::placeholder {
    color: var(--text-subtle);
}

.btn-reject {
    flex-shrink: 0;
    padding: 0.35rem 0.85rem;
    background: transparent;
    border: none;
    border-radius: var(--r-full);
    color: var(--danger);
    font-size: var(--fs-sm);
    font-weight: 650;
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.btn-reject:hover {
    background: var(--red-500);
    color: #fff;
}

.btn-reject:focus-visible {
    outline: none;
    background: var(--danger-soft);
}

/* On a client's own page there is a full column to work in rather than a table
   cell, so the reason field is given room to show a whole sentence. */
.review-actions--wide {
    align-items: flex-start;
    margin-top: var(--sp-5);
}

.review-actions--wide .reject-group {
    flex: 1 1 340px;
}

.review-actions--wide .review-note-input,
.review-actions--wide .review-note-input:focus {
    width: 100%;
    min-width: 0;
}

/* The same card as the client's, dropped into a .manage-section that already
   supplies the surrounding padding and heading. */
.review-detail-card {
    margin-top: var(--sp-4);
    margin-bottom: 0;
}

.review-detail-card .summary-meta {
    margin-bottom: 0;
}

.review-detail-card .premium-form-hint {
    margin-top: var(--sp-3);
}

/* Below this the five columns cannot hold a text field as well, so the
   decision stacks instead of being squeezed. */
@media (max-width: 1180px) {
    .review-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .reject-group {
        min-width: 240px;
    }

    .review-note-input,
    .review-note-input:focus {
        width: 100%;
        min-width: 0;
    }
}

/* --- Empty and no-match states ------------------------------------------
   The cleared queue is rendered instead of the table, not inside it: a header
   row above an empty body reads as a page that failed to load rather than as
   a queue with nothing in it. */
.queue-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--sp-12) var(--sp-6);
    text-align: center;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
}

.queue-empty-ic {
    display: grid;
    place-items: center;
    width: 64px;
    height: 64px;
    margin-bottom: var(--sp-4);
    border-radius: 50%;
    background: var(--tone-soft, var(--success-soft));
    color: var(--tone, var(--success));
}

.queue-empty-ic svg {
    width: 28px;
    height: 28px;
}

.queue-empty h3 {
    margin-bottom: var(--sp-2);
    font-size: var(--fs-lg);
    font-weight: 650;
    color: var(--text-strong);
}

.queue-empty p {
    max-width: 44ch;
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-base);
    line-height: 1.6;
}

/* A filter that matches nothing, which is a different thing from an empty
   queue: the rows still exist, so this stays inside the table under the
   header and toolbar that produced it. */
.no-match-row td {
    padding: var(--sp-10) var(--sp-4) !important;
    text-align: center;
    color: var(--text-subtle);
}

/* --- Recently reviewed --------------------------------------------------
   Here so an admin can see what they just did — and catch a mistaken
   rejection while the client is still on the phone about it. */
.queue-log {
    margin-top: var(--sp-6);
}

.queue-log-head {
    display: flex;
    align-items: baseline;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding: var(--sp-4);
    border-bottom: 1px solid var(--border);
}

.queue-log-head h3 {
    margin: 0;
    font-size: var(--fs-md);
    font-weight: 650;
    color: var(--text-strong);
}

.queue-log-head .subtitle {
    margin: 0;
    font-size: var(--fs-sm);
    color: var(--text-subtle);
}

/* A reason can run to 500 characters. Clamped to two lines with the full text
   on hover, so one verbose rejection cannot make every row in the log tall. */
.log-reason {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    max-width: 320px;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: 1.5;
}

/* Pulses outward from whatever it is on, in that element's own colour. Used by
   the pending icon and the overdue wait pill. */
@keyframes reviewPulse {
    0% { box-shadow: 0 0 0 0 currentColor; opacity: 0.9; }
    70% { box-shadow: 0 0 0 7px transparent; opacity: 0.4; }
    100% { box-shadow: 0 0 0 0 transparent; opacity: 0.9; }
}


/* ==========================================================================
   Checkout and billing
   ==========================================================================
   The plan card on the client's dashboard, the receipt list under it, and the
   gateway references in the admin panel's payment tables. The checkout page
   itself borrows the marketing pricing cards wholesale (marketing.css) and
   adds only .is-current below.
   ========================================================================== */

/* "Renew or change plan", sitting with the plan chip and validity date. Styled
   as a quiet link rather than a button: it shares a row with status
   information, and a primary button there would read as the thing to do next
   for a client whose plan is running perfectly well. */
.plan-manage-link {
    margin-left: auto;
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--accent);
    text-decoration: none;
    white-space: nowrap;
}

.plan-manage-link:hover {
    text-decoration: underline;
}

.plan-payments {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.plan-payments h4 {
    margin: 0 0 0.6rem;
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}

.payment-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Four columns that stay aligned down the list, with the description taking
   the slack. Grid rather than flex so the amounts line up as a column the eye
   can total, which is the one thing a receipt list has to do. */
.payment-row {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    gap: 0.75rem;
    align-items: center;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-sm);
}

.payment-row:last-child {
    border-bottom: 0;
}

.payment-date {
    color: var(--text-muted);
    white-space: nowrap;
}

.payment-what {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.payment-amount {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    white-space: nowrap;
}

@media (max-width: 560px) {
    /* Two rows rather than four cramped columns: the date and status pair up
       under the description and amount. */
    .payment-row {
        grid-template-columns: 1fr auto;
        row-gap: 0.25rem;
    }
}

/* Gateway ids in the admin tables. Monospaced and dimmed -- they are there to
   be copied into the Razorpay dashboard, not read. */
.txn-refs code {
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    color: var(--text-muted);
    word-break: break-all;
}

.txn-method {
    margin-left: 0.4rem;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

/* The reason a payment failed, or what a refund actually did. Wraps, unlike
   everything else in these cells, because it is a sentence. */
.txn-note {
    margin-top: 0.2rem;
    max-width: 22rem;
    font-size: var(--fs-xs);
    line-height: 1.4;
    color: var(--text-muted);
    white-space: normal;
}

/* The tier the client is already on, marked on the checkout page. Uses the
   accent line rather than the featured card's full treatment so it reads as
   "this is yours" next to, and not competing with, "most popular". */
.mk-price-card.is-current {
    border-color: var(--accent-line);
    box-shadow: 0 0 0 1px var(--accent-line);
}

/* =========================================================================
   9. CLIENT CONSOLE — ChatBIQ design system
   -------------------------------------------------------------------------
   The client panel is drawn from the ChatBIQ Figma file (node 3:3636 and the
   dashboard frames beside it). Everything here is scoped to
   body.client-console, which client_base.html sets, so the admin console
   (body.admin-console) keeps the dark system above untouched — the two shells
   share class names, so an unscoped change would move both.

   Values come from the file's own variables (Inter 35/24/18/16/14/12 and the
   #0752E0 / #333 / #666 / #F8F9FB palette). Where the dashboard frame and the
   client-detail frame disagreed on a size, the shared variable won.
   ========================================================================= */

body.client-console {
    /* --- Palette. The design is light; the sidebar is the one dark surface. */
    --canvas: #f8f9fb;
    --surface: #ffffff;
    --surface-raised: #ffffff;
    --surface-sunken: #f8f9fb;
    --surface-hover: #f1f3f6;
    --surface-active: #edf0f4;
    --chrome: #ffffff;

    --text: #333333;
    --text-strong: #333333;
    --text-muted: #666666;
    --text-subtle: #667085;

    --border: #e3e8ef;
    --border-strong: #d6dde8;
    --field-bg: #ffffff;
    --field-bg-focus: #ffffff;
    --track: #edf0f4;

    --accent: #0752e0;
    --accent-hover: #0646c2;
    --accent-text: #ffffff;
    --accent-soft: #f0f6fe;
    --accent-line: #c7dcfb;
    --on-accent-muted: #aec8f6;

    --success: #23864d;
    --success-soft: #eaf8ef;
    --warning: #ae6818;
    --warning-soft: #fff6e8;
    --danger: #d34242;
    --danger-soft: #fff5f5;
    --info: #0752e0;
    --info-soft: #f0f6fe;

    /* The design is flat: cards are separated by a 1px border, not a shadow. */
    --e-1: none;
    --e-2: none;
    --e-3: 0 8px 24px -12px rgba(16, 24, 40, 0.18);
    --ring: 0 0 0 3px rgba(7, 82, 224, 0.16);

    /* --- Type scale: the file's seven text variables, in order. */
    --fs-xs: 0.75rem;       /* 12 / 18  small label   */
    --fs-sm: 0.875rem;      /* 14 / 22  caption       */
    --fs-base: 1rem;        /* 16 / 24  small body    */
    --fs-md: 1rem;          /* 16 / 24  button        */
    --fs-lg: 1.125rem;      /* 18 / 26  icon heading  */
    --fs-xl: 1.25rem;       /* 20       — unchanged   */
    --fs-2xl: 1.5rem;       /* 24 / 32  card title    */
    --fs-3xl: 2.1875rem;    /* 35 / 43  hero heading  */
    --font-mono: 'Roboto Mono', 'JetBrains Mono', Consolas, Menlo, monospace;

    /* --- Radii: 14 cards, 8 controls, 100 pills. */
    --r-sm: 6px;
    --r-md: 8px;
    --r-lg: 14px;
    --r-xl: 14px;

    /* --- Layout metrics measured off the 1920 frame. */
    --topbar-h: 80px;
    --sidebar-w: 382px;
    --content-max: 1538px;
    --card-pad: 28px;
    --card-gap: 24px;

    background: var(--canvas);
    color: var(--text);
    font-size: var(--fs-base);
    line-height: 1.5;
}

/* Dark remains available through the topbar toggle; without the attribute the
   console renders light, which is how the design is drawn. */
[data-theme="dark"] body.client-console {
    --canvas: #0f1117;
    --surface: #161922;
    --surface-raised: #1c2029;
    --surface-sunken: #11141a;
    --surface-hover: rgba(255, 255, 255, 0.04);
    --surface-active: rgba(255, 255, 255, 0.07);
    --chrome: #11141a;

    --text: #eef0f4;
    --text-strong: #ffffff;
    --text-muted: #a2a9b7;
    --text-subtle: #6d7484;

    --border: rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.14);
    --field-bg: rgba(255, 255, 255, 0.035);
    --field-bg-focus: rgba(255, 255, 255, 0.06);
    --track: #252a35;

    --accent: #3b82f6;
    --accent-hover: #2f6fe0;
    --accent-soft: rgba(59, 130, 246, 0.14);
    --accent-line: rgba(59, 130, 246, 0.32);

    --success: #4ade80;
    --success-soft: rgba(34, 197, 94, 0.13);
    --warning: #f59e0b;
    --warning-soft: rgba(245, 158, 11, 0.13);
    --danger: #f87171;
    --danger-soft: rgba(239, 68, 68, 0.13);
}

/* --- Topbar: 80px, opaque white, hairline rule ------------------------- */
body.client-console .navbar {
    background: var(--chrome);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 0 24px;
    border-bottom: 1px solid var(--border);
}

body.client-console .nav-context strong {
    font-size: var(--fs-base);
    font-weight: 400;
    color: var(--text-muted);
}

/* --- Sidebar: the one dark surface, 382px wide, 24px gutter ------------ */
body.client-console .client-sidebar {
    padding: 30px 24px;
    background: #1a1632;
    border-right: none;
    gap: 0;
}

body.client-console .client-sidebar-header h3,
body.client-console .nav-group-label {
    padding: 0;
    margin-bottom: 30px;
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: 18px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #aaa7b8;
}

/* The search sits on the dark rail, so it cannot take the light --field-bg
   and --border the rest of the console now uses. */
body.client-console .sidebar-search {
    margin-bottom: 30px;
    padding: 10px 14px;
    background: #231f3d;
    border-color: #353448;
}

body.client-console .sidebar-search:focus-within {
    border-color: #0752e0;
    box-shadow: 0 0 0 3px rgba(7, 82, 224, 0.26);
}

/* Sized by its wrapper, so it opts out of the 48px field rule below. */
body.client-console .sidebar-search input[type="text"] {
    min-height: 0;
    padding: 0;
    background: transparent;
    border: none;
    font-size: var(--fs-sm);
    line-height: 22px;
    color: #ffffff;
}

body.client-console .sidebar-search input::placeholder {
    color: #aaa7b8;
}

body.client-console .sidebar-search svg {
    color: #aaa7b8;
}

/* Inactive items are 40px; the selected one is a taller 62px filled block. */
body.client-console .client-nav {
    display: flex;
    flex-direction: column;
    gap: 30px;
}

body.client-console .nav-item {
    min-height: 40px;
    padding: 0 12px;
    gap: 12px;
    border-radius: var(--r-md);
    font-size: var(--fs-base);
    font-weight: 500;
    line-height: 22px;
    color: #ffffff;
}

body.client-console .nav-item svg,
body.client-console .nav-item .nav-ic svg {
    width: 20px;
    height: 20px;
}

body.client-console .nav-item:hover {
    background: #353448;
    color: #ffffff;
}

body.client-console .nav-item.is-active,
body.client-console .nav-item[aria-selected="true"] {
    min-height: 62px;
    background: linear-gradient(90deg, #0752e0 0%, #1a3fb8 100%);
    color: #ffffff;
}

body.client-console .nav-item.is-locked,
body.client-console .nav-item.is-locked:hover {
    color: #aaa7b8;
    background: transparent;
}

/* --- Sidebar account card ---------------------------------------------- */
body.client-console .sidebar-footer {
    margin-top: auto;
    padding-top: 13px;
    border-top: 1px solid #353448;
}

body.client-console .sidebar-user {
    gap: 20px;
    padding: 0 8px;
}

/* The design draws every avatar as a flat blue disc, not the brand gradient. */
body.client-console .user-avatar {
    width: 32px;
    height: 32px;
    background: #0752e0;
    color: #ffffff;
    font-size: var(--fs-sm);
    font-weight: 500;
}

body.client-console .sidebar-user-info strong {
    font-size: var(--fs-base);
    font-weight: 500;
    line-height: 22px;
    color: #ffffff;
}

body.client-console .sidebar-user-info span {
    font-size: var(--fs-sm);
    line-height: 22px;
    color: #aaa7b8;
}

/* --- Content column: 40px gutter --------------------------------------- */
body.client-console .client-main {
    padding: 40px;
}

/* --- Page header: 35/43 title, 16/24 description, hairline rule -------- */
body.client-console .panel-header,
body.client-console .dashboard-header {
    gap: 24px;
    margin-bottom: 24px;
    padding-bottom: 24px;
    border-bottom: 1px solid var(--border);
}

body.client-console .panel-header h2,
body.client-console .dashboard-header h2 {
    margin-bottom: 12px;
    font-size: var(--fs-3xl);
    font-weight: 700;
    line-height: 43px;
    letter-spacing: -0.01em;
    color: var(--text);
}

body.client-console .panel-header .subtitle,
body.client-console .dashboard-header p {
    font-size: var(--fs-base);
    line-height: 24px;
    color: var(--text-muted);
}

/* --- Cards: white, 1px #e3e8ef, 14px radius, 28px padding, 24px apart -- */
body.client-console .website-section,
body.client-console .support-section,
body.client-console .api-section,
body.client-console .manage-section,
body.client-console .datasets-section,
body.client-console .panel-section,
body.client-console .chat-panel,
body.client-console .card-surface {
    margin-bottom: var(--card-gap);
    padding: var(--card-pad);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: none;
}

body.client-console .section-heading {
    margin-bottom: 24px;
}

body.client-console .section-heading h3 {
    margin-bottom: 6px;
    font-size: var(--fs-2xl);
    font-weight: 600;
    line-height: 32px;
    color: var(--text);
}

body.client-console .section-heading .subtitle {
    font-size: var(--fs-base);
    line-height: 24px;
    color: var(--text-muted);
}

/* --- Stat tiles: 120px tall, 42px icon chip, 26/34 value --------------- */
body.client-console .dashboard-stats {
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 25px;
    margin-bottom: var(--card-gap);
}

body.client-console .stat-card {
    display: flex;
    align-items: center;
    gap: 16px;
    min-height: 120px;
    padding: 20px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: none;
}

body.client-console .stat-ic {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    flex-shrink: 0;
    background: var(--accent-soft);
    border-radius: 10px;
    color: var(--accent);
}

body.client-console .stat-ic svg {
    width: 20px;
    height: 20px;
}

/* The tile label is an h3 in the markup. Matching a bare span here would
   instead catch the package chip that sits inside .stat-value. */
body.client-console .stat-body h3,
body.client-console .stat-body .stat-label {
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: 18px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

body.client-console .stat-value {
    font-size: 1.625rem;
    font-weight: 700;
    line-height: 34px;
    color: var(--text);
}

/* Licence keys are long enough to wrap a tile three ways at 16px. The design
   sets them a notch down, in the mono face, and lets them break anywhere. */
body.client-console .stat-value--code {
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    font-weight: 500;
    line-height: 22px;
    overflow-wrap: anywhere;
}

/* --- Controls: 44px buttons, 48px fields, 8px radius ------------------- */
body.client-console .btn-primary,
body.client-console .btn-secondary,
body.client-console .btn-ghost {
    min-height: 44px;
    padding: 0 16px;
    gap: 8px;
    border-radius: var(--r-md);
    font-size: var(--fs-md);
    font-weight: 500;
    line-height: 24px;
}

body.client-console .btn-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-text);
    box-shadow: none;
}

body.client-console .btn-primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    box-shadow: none;
}

body.client-console .btn-secondary {
    background: var(--surface);
    border-color: var(--border);
    color: var(--text);
}

body.client-console .btn-secondary:hover {
    background: var(--surface-hover);
}

body.client-console input[type="text"],
body.client-console input[type="email"],
body.client-console input[type="url"],
body.client-console input[type="tel"],
body.client-console input[type="password"],
body.client-console input[type="date"],
body.client-console select,
body.client-console textarea {
    min-height: 48px;
    padding: 12px 14px;
    background: var(--field-bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    font-size: var(--fs-base);
    line-height: 24px;
    color: var(--text);
}

body.client-console textarea {
    min-height: 96px;
}

body.client-console input::placeholder,
body.client-console textarea::placeholder {
    color: var(--text-subtle);
}

body.client-console label,
body.client-console .field-label {
    font-size: var(--fs-base);
    font-weight: 400;
    line-height: 22px;
    color: var(--text);
}

/* --- Pills: 100px radius, 10/4 padding, 12/18 label -------------------- */
body.client-console .badge,
body.client-console .pkg-chip,
body.client-console .api-badge {
    gap: 6px;
    padding: 4px 10px;
    border-radius: 100px;
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: 18px;
}

/* --- Meters: 6px groove, fully rounded --------------------------------- */
body.client-console .meter-track {
    height: 6px;
    background: var(--track);
    border-radius: 100px;
}

body.client-console .meter-fill {
    border-radius: 100px;
    background: var(--accent);
}

body.client-console .meter-fill.is-full {
    background: var(--danger);
}

body.client-console .meter-head {
    font-size: var(--fs-base);
    line-height: 22px;
    color: var(--text);
}

/* --- Tables: 44px head, 68px rows, 18px cell gutter -------------------- */
body.client-console table {
    width: 100%;
    border-collapse: collapse;
}

body.client-console thead th {
    height: 44px;
    padding: 0 18px;
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: 18px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    text-align: left;
}

body.client-console tbody td {
    height: 68px;
    padding: 0 18px;
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-sm);
    line-height: 22px;
    color: var(--text);
}

body.client-console tbody tr:last-child td {
    border-bottom: none;
}

/* --- Chat: blue bubbles for the client's own messages ------------------ */
body.client-console .chat-thread {
    padding: 22px;
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
}

body.client-console .chat-bubble {
    padding: 10px 16px;
    background: var(--surface-active);
    border-radius: var(--r-lg);
    font-size: var(--fs-base);
    line-height: 24px;
    color: var(--text);
}

body.client-console .chat-message.is-me .chat-bubble {
    background: var(--accent);
    color: var(--accent-text);
}

body.client-console .chat-meta {
    margin-top: 10px;
    font-size: var(--fs-xs);
    line-height: 18px;
    color: var(--text-muted);
}

body.client-console .chat-form input[type="text"] {
    min-height: 56px;
}

/* --- Dataset + document rows: 58px, hairline separated ----------------- */
body.client-console .dataset-card {
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: none;
    overflow: hidden;
}

body.client-console .dataset-head,
body.client-console .file-row {
    min-height: 58px;
    padding: 0 18px;
    gap: 12px;
}

body.client-console .doc-name,
body.client-console .dataset-head strong {
    font-size: var(--fs-base);
    line-height: 24px;
    color: var(--text);
}

body.client-console .doc-size,
body.client-console .summary-meta,
body.client-console .api-date,
body.client-console .cap-note {
    font-size: var(--fs-sm);
    line-height: 22px;
    color: var(--text-muted);
}

/* The endpoint URL is the one place the design sets a monospace face. */
body.client-console .api-url {
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    line-height: 24px;
    color: var(--text);
    word-break: break-word;
}

/* --- Responsive -------------------------------------------------------- */
/* The block above is measured off the 1920 frame and outranks the shared
   responsive rules in section 7, so the client console restates them here at
   its own specificity. The design has no small-screen artboard; these keep its
   proportions while letting the layout fit a phone. */

@media (max-width: 1024px) {
    /* 382px is a desktop rail measurement. As an overlay drawer it has to fit
       the viewport, so it caps rather than running off the screen. */
    body.client-console .client-sidebar {
        width: min(var(--sidebar-w), 86vw);
        padding: 24px 20px;
    }

    body.client-console .client-main {
        padding: 20px 20px 32px;
    }

    body.client-console .client-nav {
        gap: 12px;
    }

    body.client-console .nav-item.is-active {
        min-height: 48px;
    }
}

@media (max-width: 768px) {
    body.client-console .client-main {
        padding: 16px 16px 32px;
    }

    /* 35px is the frame's hero size; on a phone it wraps the page title to
       three lines, so it steps down one notch. */
    body.client-console .panel-header h2,
    body.client-console .dashboard-header h2 {
        font-size: 1.75rem;
        line-height: 36px;
        margin-bottom: 8px;
    }

    body.client-console .panel-header,
    body.client-console .dashboard-header {
        margin-bottom: 20px;
        padding-bottom: 20px;
    }

    body.client-console .website-section,
    body.client-console .support-section,
    body.client-console .api-section,
    body.client-console .manage-section,
    body.client-console .datasets-section,
    body.client-console .panel-section,
    body.client-console .chat-panel,
    body.client-console .card-surface {
        padding: 20px;
        margin-bottom: 16px;
    }

    body.client-console .section-heading h3 {
        font-size: 1.25rem;
        line-height: 28px;
    }

    body.client-console .dashboard-stats {
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
        gap: 12px;
    }

    body.client-console .stat-card {
        min-height: 96px;
        padding: 16px;
        gap: 12px;
    }

    body.client-console .stat-ic {
        width: 36px;
        height: 36px;
    }

    body.client-console .stat-value {
        font-size: 1.375rem;
        line-height: 28px;
    }

    /* A 68px row and an 18px gutter do not fit five columns on a phone; the
       table scrolls sideways instead of crushing its cells. */
    body.client-console .api-section table,
    body.client-console .panel-section table {
        display: block;
        overflow-x: auto;
        white-space: nowrap;
    }

    body.client-console thead th,
    body.client-console tbody td {
        padding: 0 12px;
    }

    body.client-console tbody td {
        height: 56px;
    }
}

/* --- Overview workspace, per frame 3:3636 -------------------------------
   The frame's "Account workspace" is 1458 wide: the support chat takes 1021
   on the left, the account rail 413 on the right, 24 between them. The
   template used to do the reverse (cards left, a 400px chat rail right), so
   the markup was reordered to match and these rules carry the proportions.
   Everything below the workspace is full width, as the frame stacks it. */

body.client-console {
    --rail-w: 413px;
}

@media (min-width: 1400px) {
    body.client-console .overview-grid {
        gap: 24px;
        align-items: stretch;
    }

    /* The rail is a sibling card of the chat in the frame, the same height as
       it, so it no longer pins itself to the viewport. */
    body.client-console .overview-aside {
        position: static;
        top: auto;
        max-height: none;
        display: block;
    }

    body.client-console .overview-main,
    body.client-console .overview-aside {
        min-width: 0;
    }

    body.client-console .overview-main > .support-section,
    body.client-console .overview-aside > .website-section {
        height: 100%;
        margin-bottom: 0;
    }
}

/* --- Support chat: 620px thread, 56px composer -------------------------- */
body.client-console .overview-main > .support-section {
    display: flex;
    flex-direction: column;
}

body.client-console .overview-main > .support-section .chat-thread {
    flex: 1 1 auto;
    min-height: 320px;
    max-height: 620px;
    margin-bottom: 24px;
}

body.client-console .overview-main > .support-section .chat-form {
    display: flex;
    gap: 16px;
    align-items: center;
    flex-shrink: 0;
}

body.client-console .overview-main > .support-section .chat-form textarea,
body.client-console .overview-main > .support-section .chat-form input[type="text"] {
    flex: 1 1 auto;
    min-height: 56px;
}

/* --- Account rail: 42px rows, label left, value right ------------------- */
body.client-console .overview-aside .summary-meta li {
    align-items: center;
    gap: 16px;
    min-height: 42px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-base);
    line-height: 22px;
}

body.client-console .overview-aside .summary-meta span {
    color: var(--text-muted);
    font-weight: 400;
}

body.client-console .overview-aside .summary-meta strong {
    color: var(--text);
    font-weight: 500;
    text-align: right;
}

/* --- Below the workspace the frame stacks sections full width ----------- */
body.client-console .overview-grid ~ .website-section {
    margin-bottom: var(--card-gap);
}

@media (max-width: 1399px) {
    /* Without the two-column workspace the chat returns to a sane height. */
    body.client-console .overview-main > .support-section .chat-thread {
        max-height: 420px;
    }
}
