/* ============================================================
   CSS Custom Properties — Design Token System
   ============================================================
   Tier 1: Primitive palette (raw colors by name)
   Tier 2: Semantic tokens (named by purpose)
   Tier 3: Component tokens (specific UI roles)
   ============================================================ */

:root {
    /* --- Tier 1: Primitive Palette --- */
    --gray-950: #1B1D21;
    --gray-900: #1F2228;
    --gray-850: #262A30;
    --gray-800: #2E333A;
    --gray-750: #353B42;
    --gray-700: #3F4650;
    --gray-650: #3F4E5A;
    --gray-600: #4D5966;
    --gray-500: #5A6672;
    --gray-400: #8A9199;
    --gray-300: #A8B0B8;
    --gray-200: #C8CDD3;
    --gray-100: #D5DAE0;
    --gray-50: #ECEEF1;
    --white: #ffffff;
    --black: #000000;

    --teal-500: #8AA4BF;
    --teal-900: #1B2B3A;
    --blue-600: #4A6F8A;
    --blue-500: #5B7E98;
    --blue-400: #B0C8DB;
    --red-500: #B35A5E;
    --red-400: #C59A96;
    --orange-400: #B89A82;
    --green-500: #6A9B7E;
    --green-400: #7DB892;
    --yellow-500: #D4B870;
    --amber-500: #C49A5C;
    --amber-400: #DFAE6E;
    --amber-700: #8A6A2F;
    --purple-500: #8A7EB5;

    /* --- Tier 2: Semantic Tokens --- */

    /* Backgrounds */
    --color-bg-primary: var(--gray-900);
    --color-bg-surface: var(--gray-850);
    --color-bg-elevated: var(--gray-800);
    --color-bg-input: var(--gray-700);
    --color-bg-inset: var(--gray-900);
    --color-bg-overlay: rgba(0, 0, 0, 0.5);

    /* Text */
    --color-text-primary: var(--gray-100);
    --color-text-secondary: var(--gray-200);
    --color-text-tertiary: var(--gray-300);
    --color-text-muted: var(--gray-400);
    --color-text-faint: var(--gray-500);
    --color-text-heading: var(--blue-400);
    --color-text-on-accent: #1B2B3A;
    --color-text-on-surface: var(--gray-100);

    /* Borders */
    --color-border: var(--gray-650);
    --color-border-subtle: var(--gray-750);
    --color-border-strong: var(--gray-500);

    /* Interactive */
    --color-accent: var(--teal-500);
    --color-info: var(--blue-500);
    --color-success: var(--green-500);
    --color-success-light: var(--green-400);
    --color-danger: var(--red-500);
    --color-danger-soft: var(--red-400);
    --color-warning: var(--amber-500);
    /* Amber for text that has to be READ, not just noticed. --color-warning is
       tuned for borders, dots and glows; at body size on a page background it
       is too low-contrast to read comfortably, in the light theme especially. */
    --color-warning-text: var(--amber-400);
    --color-save: var(--orange-400);
    --color-purple: var(--purple-500);
    --color-gold: var(--yellow-500);
    --color-link: var(--teal-500);
    --color-link-hover: var(--white);

    /* Study set viz (Define Study modal coverage/sample mosaic) */
    --study-viz-included: var(--green-500);
    --study-viz-included-pulse: var(--green-400);
    --study-viz-included-text: var(--gray-50);
    --study-viz-eligible-bg: var(--gray-750);
    --study-viz-outframe-bg: var(--gray-900);
    --study-viz-border: var(--color-border);
    --study-viz-divider: var(--color-border-subtle);
    --study-viz-label-text: var(--gray-50);
    --study-viz-label-halo: var(--gray-900);

    /* Shadows */
    --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.2);
    --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.4);

    /* Typography — Font Families */
    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace;

    /* Typography — Size Scale */
    --text-hero: 2.25rem;
    --text-h2:   1.5rem;
    --text-h3:   1.2rem;
    --text-body: 1rem;
    --text-sm:   0.875rem;
    --text-xs:   0.75rem;
    --text-xxs:  0.625rem;

    /* Typography — Weight Scale */
    --weight-normal:   400;
    --weight-medium:   500;
    --weight-semibold: 600;
    --weight-bold:     700;

    /* Typography — Line Height */
    --leading-tight:   1.2;
    --leading-normal:  1.5;
    --leading-relaxed: 1.65;

    /* Typography — Letter Spacing */
    --tracking-tight:  -0.025em;
    --tracking-normal: 0;
    --tracking-wide:   0.025em;

    /* --- Tier 3: Component Tokens --- */

    /* Buttons */
    --btn-primary-bg: var(--color-accent);
    --btn-primary-text: var(--color-text-on-accent);
    --btn-danger-bg: var(--color-danger-soft);
    --btn-danger-text: var(--color-text-on-accent);
    --btn-save-bg: var(--color-save);
    --btn-save-text: var(--color-text-on-accent);
    --btn-state-bg: var(--color-success);
    --btn-state-text: var(--color-text-on-accent);
    --btn-discreet-bg: var(--gray-650);
    --btn-discreet-text: var(--color-text-primary);
    --btn-discreet-border: var(--gray-500);
    --btn-discreet-hover: var(--gray-600);
    --btn-discreet-active: var(--gray-800);

    /* Tab navigation */
    --tab-bg: inherit;
    --tab-text: var(--color-text-primary);
    --tab-hover-bg: var(--gray-650);
    --tab-active-bg: var(--color-bg-primary);
    --tab-active-text: var(--white);
    --tab-active-border: var(--color-accent);
    --tab-border: var(--color-border);

    /* Inputs */
    --input-bg: var(--color-bg-input);
    --input-border: var(--color-border);
    --input-text: var(--color-text-primary);

    /* Panels */
    --panel-bg: var(--color-bg-surface);
    --panel-border: var(--color-border);

    /* Tables */
    --table-header-bg: var(--color-bg-elevated);
    --table-row-hover: #282D34;
    --table-row-selected: var(--teal-900);
    --table-border: var(--color-border);

    /* Chips / Filter pills */
    --chip-bg: var(--gray-650);
    --chip-border: var(--gray-500);
    --chip-text: var(--white);
    --chip-selected-bg: var(--color-info);
    --chip-selected-border: #7A9AB5;
    --chip-selected-text: var(--white);

    /* Status indicators — one convention everywhere: green = running,
       blue = standing by (idle/queued/stopping), amber = last run didn't
       work, red = critical fault (couldn't start / aborted).
       Deliberately vivid signal colors, outside the muted UI palette:
       an indicator lamp should read at a glance. */
    --status-idle: #0033FF;
    --status-running: #00C853;
    --status-stopped: #0033FF;
    --status-warn: #FFB300;
    --status-error: #FF1E1E;

    /* Modal */
    --modal-bg: var(--color-bg-surface);
    --modal-border: var(--color-accent);
    --modal-text: var(--color-text-primary);
    --modal-overlay: var(--color-bg-overlay);

    /* Progress */
    --progress-bg: var(--color-bg-input);
    --progress-fill: rgba(106, 155, 126, 0.45);
    --progress-text: rgba(255, 255, 255, 0.74);

    /* Slider (noUiSlider) */
    --slider-track: var(--gray-750);
    --slider-connect: var(--color-accent);
    --slider-handle: var(--white);

    /* Control bar (shared across tabs) */
    --control-bar-bg: var(--color-bg-surface);
    --control-bar-border: var(--color-border);
    --control-bar-text: var(--gray-50);
    --control-bar-label: var(--gray-50);
    --control-bar-info: var(--gray-400);

    /* Select dropdowns (within control bars) */
    --select-bg: var(--color-bg-input);
    --select-border: var(--gray-500);
    --select-text: var(--white);

    /* Sections (collapsible) */
    --section-bg: var(--color-bg-surface);
    --section-border: var(--color-border);

    /* Cards */
    --card-bg: var(--color-bg-surface);
    --card-border: var(--color-border);

    /* Tooltip */
    --tooltip-bg: var(--gray-750);
    --tooltip-text: var(--white);
    --tooltip-border: var(--gray-500);

    /* Plotly / chart overrides */
    --chart-bg: var(--color-bg-primary);
    --chart-text: var(--color-text-primary);
    --chart-grid: var(--gray-650);
    --chart-zeroline: var(--gray-400);
    --chart-grid-line: rgba(255, 255, 255, 0.06);
    --chart-overlay-line: rgba(255, 255, 255, 0.12);
    --chart-annotation-text: rgba(255, 255, 255, 0.4);
    --chart-regression-line: rgba(255, 255, 255, 0.5);
    --chart-heatmap-mid: var(--gray-900);
    --chart-badge-bg: rgba(0, 0, 0, 0.7);

    /* Accent variants for data-specific uses */
    --color-slice1: #6A9B7E;
    --color-slice2: #5B7E98;
    --color-significance: var(--yellow-500);

    /* Trend badge colors */
    --trend-rising-bg: rgba(138, 164, 191, 0.15);
    --trend-rising-border: rgba(138, 164, 191, 0.5);
    --trend-falling-bg: rgba(197, 154, 150, 0.15);
    --trend-falling-border: rgba(197, 154, 150, 0.5);
    --trend-spikes-bg: rgba(184, 154, 130, 0.15);
    --trend-spikes-border: rgba(184, 154, 130, 0.5);
    --trend-breaks-bg: rgba(91, 126, 152, 0.15);
    --trend-breaks-border: rgba(91, 126, 152, 0.5);
    --trend-volatile-bg: rgba(138, 126, 181, 0.15);
    --trend-volatile-border: rgba(138, 126, 181, 0.5);
    --trend-stable-bg: rgba(120, 120, 120, 0.2);
}


/* ============================================================
   Light Theme
   ============================================================ */

[data-theme="light"] {
    --color-bg-primary: #F4F6F7;
    --color-bg-surface: #ffffff;
    --color-bg-elevated: #E9ECEF;
    --color-bg-input: #ffffff;
    --color-bg-inset: #EEF1F3;
    --color-bg-overlay: rgba(0, 0, 0, 0.3);

    --color-text-primary: #1e1e1e;
    --color-text-secondary: #2B3137;
    --color-text-tertiary: #4D5966;
    --color-text-muted: #6B7580;
    --color-text-faint: #8A9199;
    --color-text-heading: #4A6F8A;
    --color-text-on-accent: #ffffff;
    --color-text-on-surface: #1e1e1e;

    --color-border: #CED3D9;
    --color-border-subtle: #DDE1E6;
    --color-border-strong: #ACB3BB;

    --color-accent: #5B7E98;
    --color-info: #4A6F8A;
    --color-success: #4E8A64;
    --color-success-light: #6A9B7E;
    --color-danger: #A3535A;
    --color-danger-soft: #B35A5E;
    --color-warning: #A88A4E;
    --color-warning-text: var(--amber-700);
    --color-save: #9A7E66;
    --color-link: #5B7E98;
    --color-link-hover: #3D5A72;

    /* Study set viz overrides (light) */
    --study-viz-eligible-bg: var(--gray-50);
    --study-viz-outframe-bg: var(--gray-100);
    --study-viz-label-text: var(--gray-900);
    --study-viz-label-halo: var(--white);

    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
    --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.12);
    --shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.15);

    --btn-primary-bg: var(--color-accent);
    --btn-primary-text: var(--white);
    --btn-danger-bg: var(--color-danger);
    --btn-danger-text: var(--white);
    --btn-save-bg: var(--color-save);
    --btn-save-text: var(--white);
    --btn-state-bg: var(--color-success);
    --btn-state-text: var(--white);
    --btn-discreet-bg: #E9ECEF;
    --btn-discreet-text: #2B3137;
    --btn-discreet-border: #BFC5CC;
    --btn-discreet-hover: #DDE1E6;
    --btn-discreet-active: #CED3D9;

    --tab-hover-bg: #DDE1E6;
    --tab-active-bg: #ffffff;
    --tab-active-text: #1e1e1e;
    --tab-active-border: var(--color-accent);

    --input-bg: var(--color-bg-input);
    --input-border: var(--color-border);
    --input-text: var(--color-text-primary);

    --panel-bg: var(--color-bg-surface);
    --panel-border: var(--color-border);

    --table-header-bg: #E9ECEF;
    --table-row-hover: #F0F2F4;
    --table-row-selected: #D5E0EA;
    --table-border: var(--color-border);

    --chip-bg: #E9ECEF;
    --chip-border: #BFC5CC;
    --chip-text: #2B3137;
    --chip-selected-bg: var(--color-info);
    --chip-selected-border: #4A6F8A;
    --chip-selected-text: var(--white);

    /* Same vivid signal colors as dark mode — indicator lamps, not palette. */
    --status-idle: #0033FF;
    --status-running: #00B24A;
    --status-stopped: #0033FF;
    --status-warn: #F5A300;
    --status-error: #EE1111;

    --modal-bg: var(--color-bg-surface);
    --modal-border: var(--color-accent);
    --modal-text: var(--color-text-primary);

    --progress-bg: #DDE1E6;
    --progress-fill: rgba(78, 138, 100, 0.35);
    --progress-text: rgba(0, 0, 0, 0.7);

    --slider-track: #CED3D9;
    --slider-connect: var(--color-accent);
    --slider-handle: var(--white);

    --control-bar-bg: var(--color-bg-surface);
    --control-bar-border: var(--color-border);
    --control-bar-text: #2B3137;
    --control-bar-label: #2B3137;
    --control-bar-info: #6B7580;

    --select-bg: var(--color-bg-input);
    --select-border: var(--color-border);
    --select-text: #1e1e1e;

    --card-bg: var(--color-bg-surface);
    --card-border: var(--color-border);

    --tooltip-bg: #2B3137;
    --tooltip-text: var(--white);
    --tooltip-border: #4D5966;

    --chart-bg: var(--color-bg-surface);
    --chart-text: #2B3137;
    --chart-grid: #DDE1E6;
    --chart-zeroline: #ACB3BB;
    --chart-grid-line: rgba(0, 0, 0, 0.08);
    --chart-overlay-line: rgba(0, 0, 0, 0.10);
    --chart-annotation-text: rgba(0, 0, 0, 0.45);
    --chart-regression-line: rgba(0, 0, 0, 0.4);
    --chart-heatmap-mid: var(--color-bg-primary);
    --chart-badge-bg: rgba(0, 0, 0, 0.65);

    --color-slice1: #4E8A64;
    --color-slice2: #4A6F8A;

    /* Trend badge colors */
    --trend-rising-bg: rgba(138, 164, 191, 0.2);
    --trend-rising-border: rgba(138, 164, 191, 0.5);
    --trend-falling-bg: rgba(197, 154, 150, 0.2);
    --trend-falling-border: rgba(197, 154, 150, 0.5);
    --trend-spikes-bg: rgba(184, 154, 130, 0.2);
    --trend-spikes-border: rgba(184, 154, 130, 0.5);
    --trend-breaks-bg: rgba(91, 126, 152, 0.2);
    --trend-breaks-border: rgba(91, 126, 152, 0.5);
    --trend-volatile-bg: rgba(138, 126, 181, 0.2);
    --trend-volatile-border: rgba(138, 126, 181, 0.5);
    --trend-stable-bg: rgba(120, 120, 120, 0.25);
}

@media (prefers-color-scheme: light) {
    :root:not([data-theme]) {
        /* Uncomment block below to auto-detect OS preference: */
        /* (Intentionally left empty — opt-in only via data-theme attribute) */
    }
}


/* ============================================================
   Global Reset & Base
   ============================================================ */

* {
    box-sizing: border-box;
}

body {
    font-family: var(--font-sans);
    line-height: var(--leading-normal);
    background: var(--color-bg-primary);
    color: var(--color-text-primary);
    margin: 0;
    padding: 20px;
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Focus visible for accessibility */
:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

a {
    color: var(--color-link);
}

a:hover {
    color: var(--color-link-hover);
}


/* ============================================================
   Typography Utilities
   ============================================================ */

/* Size utilities */
.text-hero   { font-size: var(--text-hero); line-height: var(--leading-tight); letter-spacing: var(--tracking-tight); }
.text-h2     { font-size: var(--text-h2);   line-height: var(--leading-tight); }
.text-h3     { font-size: var(--text-h3);   line-height: var(--leading-tight); }
.text-body   { font-size: var(--text-body); line-height: var(--leading-normal); }
.text-sm     { font-size: var(--text-sm);   line-height: var(--leading-normal); }
.text-xs     { font-size: var(--text-xs);   line-height: var(--leading-normal); }
.text-xxs    { font-size: var(--text-xxs);  line-height: var(--leading-normal); }

/* Weight utilities */
.font-normal   { font-weight: var(--weight-normal); }
.font-medium   { font-weight: var(--weight-medium); }
.font-semibold { font-weight: var(--weight-semibold); }
.font-bold     { font-weight: var(--weight-bold); }

/* Family utilities */
.font-sans { font-family: var(--font-sans); }
.font-mono { font-family: var(--font-mono); }

/* Style utilities */
.italic    { font-style: italic; }
.uppercase { text-transform: uppercase; letter-spacing: var(--tracking-wide); }

/* Prose (long-form reading) */
.prose { line-height: var(--leading-relaxed); }

/* Data display: tabular numbers for aligned columns */
.tabular-nums { font-variant-numeric: tabular-nums; }


/* ============================================================
   Layout: Tabs
   ============================================================ */

.tab-nav {
    display: flex;
    flex: 0 0 auto;
    background: var(--color-bg-surface);
    margin-bottom: 0;
    border-bottom: 1px solid var(--color-border);
}

.tab-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

.tab-pane {
    display: none;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}

.tab-pane.active {
    display: flex;
}

#data_management,
#admin,
#my_stuff {
    flex-direction: row;
    overflow: hidden;
}

/* Data Management Sidebar Sub-Page Navigation */
.dm-sidebar {
    width: 200px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--color-border-subtle);
    background-color: var(--color-bg-surface);
    padding-top: 8px;
    overflow-y: auto;
}

.dm-sidebar-item {
    padding: 10px 16px;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--color-text-secondary);
    cursor: pointer;
    border-left: 3px solid transparent;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    user-select: none;
}

.dm-sidebar-item:hover {
    background: var(--tab-hover-bg);
    color: var(--color-text-primary);
}

.dm-sidebar-item.active {
    background: var(--tab-active-bg);
    color: var(--tab-active-text);
    border-left-color: var(--tab-active-border);
    font-weight: var(--weight-bold);
}

/* "A process this page owns is running" — one per sidebar item, shown by
   main.js updateDmSidebarSpinners(). Same spinner as the header task badge. */
.dm-sidebar-spinner {
    margin-left: 6px;
    vertical-align: middle;
}

/* Non-clickable section header between sidebar item groups */
.dm-sidebar-group {
    padding: 11px 16px 3px 16px;
    margin-top: 2px;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-secondary);
    border-top: 1px solid var(--color-border-subtle);
    user-select: none;
}

.dm-sidebar-group:first-child {
    padding-top: 10px;
    margin-top: 0;
    border-top: none;
}

.dm-content {
    flex: 1;
    overflow-y: auto;
    padding: 20px;
    min-width: 0;
}

.dm-page {
    display: none;
}

.dm-page.active {
    display: block;
}

.tab-button {
    background: var(--tab-bg);
    border: none;
    outline: none;
    cursor: pointer;
    padding: 10px 20px;
    color: var(--tab-text);
    transition: 0.3s;
    font-size: var(--text-body);
    border-right: 1px solid var(--color-border);
}

.tab-button:hover {
    background: var(--tab-hover-bg);
}

.tab-button.active {
    background: var(--tab-active-bg);
    border-bottom: 2px solid var(--tab-active-border);
    color: var(--tab-active-text);
    font-weight: var(--weight-bold);
}

.tab-button:disabled,
.tab-button.is-disabled {
    cursor: not-allowed;
    opacity: 0.4;
    background: var(--tab-bg);
}

.tab-button:disabled:hover,
.tab-button.is-disabled:hover {
    background: var(--tab-bg);
}


/* ============================================================
   Layout: Container & Panels
   ============================================================ */

.container {
    display: flex;
    gap: 20px;
    flex: 1;
    min-height: 0;
}

.panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    padding: 10px;
    border-radius: 5px;
    min-height: 200px;
}

.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    flex: 0 0 auto;
}

.controls {
    display: flex;
    gap: 10px;
    align-items: center;
}


/* ============================================================
   Typography
   ============================================================ */

h2 {
    margin: 0;
    font-size: var(--text-h3);
    color: var(--color-text-heading);
}


/* ============================================================
   Form Elements
   ============================================================ */

textarea {
    flex: 1;
    background: var(--color-bg-inset);
    border: 1px solid var(--color-border);
    color: var(--color-text-primary);
    font-family: var(--font-mono);
    padding: 10px;
    font-size: var(--text-sm);
    resize: none;
    min-height: 150px;
    display: block;
    width: 100%;
}

input[type="text"],
input[type="password"],
input[type="number"] {
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-text);
    padding: 5px;
    border-radius: 3px;
}

/* Hide native number-input spinners. The up/down arrows waste width and we
   use number inputs for batch sizes / counts where freely typing is the norm. */
input[type="number"] {
    -moz-appearance: textfield;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

select,
.dropdown {
    background: var(--select-bg);
    border: 1px solid var(--select-border);
    color: var(--select-text);
    padding: 5px;
    border-radius: 3px;
}

.control-input {
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-text);
    padding: 5px;
    border-radius: 3px;
}


/* ============================================================
   Buttons
   ============================================================ */

button {
    cursor: pointer;
    padding: 5px 15px;
    border: none;
    border-radius: 3px;
    font-weight: var(--weight-bold);
}

.btn-start,
.btn-primary {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-text);
}

.btn-stop {
    background: var(--btn-danger-bg);
    color: var(--btn-danger-text);
}

.btn-running {
    background: var(--color-warning);
    color: var(--color-bg-primary);
    border: none;
    border-radius: 6px;
    cursor: default;
    pointer-events: none;
    padding: 6px 12px;
    font-weight: var(--weight-semibold);
    animation: btn-running-pulse 1.5s ease-in-out infinite;
}

@keyframes btn-running-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.6; }
}

.btn-save,
.btn-secondary {
    background: var(--btn-discreet-bg);
    color: var(--btn-discreet-text);
    border: 1px solid var(--btn-discreet-border);
}

.btn-danger {
    background: var(--btn-danger-bg);
    color: var(--btn-danger-text);
}

.collection-table {
    min-width: 100%;
    width: max-content;
    border-collapse: collapse;
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.collection-table .edit-activity-item {
    border-bottom: 1px solid var(--chart-grid);
    cursor: pointer;
}

.collection-table .edit-activity-item:hover {
    background: var(--color-bg-input);
}

.collection-table .collection-hidden {
    opacity: 0.5;
    color: var(--color-text-muted);
}

/* A study row mid-save or mid-refresh. The data cells dim to show the row is
   not clickable; the Action cell keeps full opacity so its status message
   stays readable — dimming the whole row is what used to wash it out. */
.study-row-busy > td {
    opacity: 0.45;
}

.study-row-busy > td:last-child {
    opacity: 1;
}

/* Live status text in the studies table's Action column. Inherits the table's
   font size so it sits on the same line as the rest of the row. */
.study-row-status {
    color: var(--color-warning-text);
    white-space: nowrap;
}

.ingest-card {
    background: var(--color-bg-elevated);
    color: var(--color-text-primary);
    padding: 15px;
    border-radius: 4px;
    border: 1px solid var(--color-border-strong);
    flex: 1;
    min-width: 300px;
    margin-bottom: 10px;
}

.upload-modal-overlay {
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: var(--modal-overlay);
    backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
}

.upload-modal {
    background: var(--modal-bg);
    border: 1px solid var(--modal-border);
    border-radius: 8px;
    padding: 24px;
    width: min(520px, 90vw);
    max-height: 85vh;
    overflow-y: auto;
    box-shadow: var(--shadow-md);
    color: var(--modal-text);
}

.tag-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--color-bg-input);
    color: var(--color-text-primary);
    border: 1px solid var(--color-border-strong);
    border-radius: 4px;
    padding: 2px 8px;
    font-size: var(--text-xs);
}

.tag-chip .remove-tag {
    cursor: pointer;
    color: var(--color-text-tertiary);
    font-weight: var(--weight-bold);
    line-height: 1;
}

.tag-chip .remove-tag:hover {
    color: var(--color-danger);
}

.tag-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-strong);
    border-radius: 4px;
    max-height: 150px;
    overflow-y: auto;
    z-index: 10;
    box-shadow: var(--shadow-md);
}

.tag-suggestion-item {
    padding: 6px 10px;
    cursor: pointer;
    font-size: var(--text-sm);
    color: var(--color-text-primary);
}

.tag-suggestion-item:hover {
    background: var(--color-bg-hover);
}

/* Action is needed (e.g. new enrichment data awaiting Consolidate & Refresh):
   a strong amber pulse so the state is unmissable at a glance. */
@keyframes stale-pulse-glow {
    0%, 100% { box-shadow: 0 0 4px var(--color-warning); }
    50% { box-shadow: 0 0 14px var(--color-warning); }
}

.btn-has-pending {
    border: 2px solid var(--color-warning) !important;
    animation: stale-pulse-glow 1.6s ease-in-out infinite;
}

/* Amber pulsing dot on a sidebar item that needs attention (e.g. Refresh
   Caches when new enrichment data awaits consolidation). */
@keyframes stale-dot-pulse {
    0%, 100% { opacity: 0.45; }
    50% { opacity: 1; }
}

.sidebar-stale-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--color-warning);
    margin-left: 6px;
    vertical-align: middle;
    animation: stale-dot-pulse 1.6s ease-in-out infinite;
}

/* Armed state for the Consolidate & Refresh button — gentle blue pulse
   so it's clearly "waiting to fire" but not alarming. */
@keyframes armed-pulse-glow {
    0%, 100% {
        box-shadow: 0 0 4px var(--color-primary, #4a9eff);
        transform: scale(1);
    }
    50% {
        box-shadow: 0 0 14px var(--color-primary, #4a9eff);
        transform: scale(1.02);
    }
}

.btn-armed-pulse {
    background: var(--color-primary, #4a9eff) !important;
    color: var(--btn-primary-text, white) !important;
    border: 1px solid var(--color-primary, #4a9eff) !important;
    animation: armed-pulse-glow 1.6s ease-in-out infinite;
}

.btn-armed-pulse:hover {
    opacity: 0.92;
}

/* Consolidate → downstream refresh pipeline step list (Data Management →
   Enrichment). Status is conveyed by a coloured dot; all colours are semantic
   tokens so both themes resolve. */
/* Dataset Assembly worker cards: one full-width column, in pipeline order. The
   cards used to share rows in a wrapping flex row, which made the dispatch
   order read as a grid and left the progress bars at arbitrary widths. */
.refresh-card-stack {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.refresh-card {
    background: var(--section-bg);
    padding: 15px;
    border-radius: 4px;
    border: 1px solid var(--color-border);
    width: 100%;
}

/* The "Rebuild Downstream Datasets" box wrapping those cards — same chrome as
   the Consolidate card above it on the Dataset Assembly page. */
.refresh-group {
    background: var(--section-bg);
    padding: 15px;
    border-radius: 4px;
    border: 1px solid var(--color-border);
    margin-bottom: 20px;
}

/* Inside the group the cards would sit on the box's own background, so lift
   them a shade to keep each one readable as a separate card. */
.refresh-group .refresh-card {
    background: var(--color-bg-elevated);
}

.pipeline-steps {
    padding: 10px;
    background: var(--section-bg);
    border: 1px solid var(--color-border);
    border-radius: 4px;
}

.pipeline-step {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 0;
}

.pipeline-step-dot {
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--color-text-tertiary);
}

.pipeline-step-label {
    flex: 0 0 auto;
    color: var(--color-text-primary);
}

.pipeline-step-state {
    flex: 0 0 auto;
    color: var(--color-text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.pipeline-step-detail {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-text-secondary);
}

/* Same convention as the worker status lights: green = running/succeeded,
   blue = standing by (queued/pending), red = failed, grey = not part of
   this run. */
.pipeline-step--success .pipeline-step-dot { background: var(--status-running); }
.pipeline-step--failed .pipeline-step-dot { background: var(--status-error); }
.pipeline-step--queued .pipeline-step-dot {
    background: var(--status-idle);
    animation: pipeline-dot-pulse 1.4s ease-in-out infinite;
}
.pipeline-step--pending .pipeline-step-dot { background: var(--status-idle); }
.pipeline-step--skipped { opacity: 0.55; }
.pipeline-step--skipped .pipeline-step-dot { background: var(--color-text-tertiary); }

.pipeline-step--running .pipeline-step-dot {
    background: var(--status-running);
    animation: pipeline-dot-pulse 1.4s ease-in-out infinite;
}

@keyframes pipeline-dot-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.4; transform: scale(0.7); }
}

/* Per-platform cookie-status pill on the enrichment scraper cards. A colored dot
   + short label; the full message/age/expiry rides in the .meta-tooltip. Colors
   come from semantic tokens so both light and dark themes are covered. */
.cookie-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 1px 8px;
    border-radius: 10px;
    border: 1px solid var(--color-border);
    color: var(--color-text-tertiary);
    font-size: var(--text-xxs);
    font-weight: var(--weight-semibold);
    white-space: nowrap;
    cursor: help;
}

/* The pill is also a .meta-tooltip, whose dotted underline is declared later in
   this file and would otherwise win — this compound selector overrides it so the
   pill text stays clean. */
.cookie-pill.meta-tooltip { text-decoration: none; }

.cookie-pill::before {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--color-text-tertiary);
}

.cookie-pill--ok { color: var(--color-success-light); border-color: var(--color-success); }
.cookie-pill--ok::before { background: var(--color-success); }

.cookie-pill--warn { color: var(--color-warning); border-color: var(--color-warning); }
.cookie-pill--warn::before { background: var(--color-warning); }

.cookie-pill--bad { color: var(--color-danger-soft); border-color: var(--color-danger); }
.cookie-pill--bad::before { background: var(--color-danger); }

.cookie-pill--unknown { color: var(--color-text-tertiary); border-color: var(--color-border); }
.cookie-pill--unknown::before { background: var(--color-text-tertiary); }

/* Persistent scraper alert banner on an enrichment scraper card (raised by the
   worker when a platform's scraper looks systematically broken, e.g. a
   permanent-failure storm). Outline style: a danger border + danger text on the
   card's own background keeps it readable in both themes without a dedicated
   danger-surface token. */
.scraper-alert {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin: 0 0 12px 0;
    padding: 8px 12px;
    border: 1px solid var(--color-danger);
    border-left: 4px solid var(--color-danger);
    border-radius: 4px;
}

.scraper-alert .scraper-alert-text {
    color: var(--color-danger-soft);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

/* Same shape as .scraper-alert, in the warning colour: an unconfigured
   optional service is a setup state to act on, not a failure to alarm at. */
.config-notice {
    display: block;
    margin: 0 0 12px 0;
    padding: 8px 12px;
    border: 1px solid var(--color-warning);
    border-left: 4px solid var(--color-warning);
    border-radius: 4px;
}

.config-notice .config-notice-text {
    color: var(--color-warning);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

.action-btn {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    padding: 6px 12px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-weight: var(--weight-medium);
}

.action-btn:hover {
    opacity: 0.9;
}

.action-btn:disabled {
    opacity: 0.35;
    cursor: default;
    pointer-events: none;
}

/* Variant classes must win over the `.action-btn` primary background above,
   which appears later in source order than the .btn-* block. Without these
   explicit overrides, `class="action-btn btn-danger"` renders primary-blue. */
.action-btn.btn-danger {
    background: var(--btn-danger-bg);
    color: var(--btn-danger-text);
}
.action-btn.btn-secondary,
.action-btn.btn-save {
    background: var(--btn-discreet-bg);
    color: var(--btn-discreet-text);
    border: 1px solid var(--btn-discreet-border);
}

/* Segmented toggle control (e.g. Scatter/Heatmap, Distribution/Compare) */
.toggle-group {
    display: inline-flex;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid var(--color-border-strong);
}

.toggle-group .toggle-option {
    padding: 5px 14px;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    cursor: pointer;
    border: none;
    background: var(--color-bg-input);
    color: var(--color-text-tertiary);
    transition: background 0.15s, color 0.15s;
}

.toggle-group .toggle-option:not(:last-child) {
    border-right: 1px solid var(--color-border-strong);
}

.toggle-group .toggle-option.active {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    font-weight: var(--weight-semibold);
}

.btn-discreet {
    background: var(--btn-discreet-bg);
    color: var(--btn-discreet-text);
    padding: 5px 10px;
    font-size: var(--text-sm);
    border: 1px solid var(--btn-discreet-border);
    transition: background 0.2s;
}

/* Compact row-action button (table "Actions" cells, result-card actions).
   Declared AFTER .btn-discreet so it wins on source order — .btn-discreet sets
   its own font-size, which would otherwise beat a `.text-xs` utility class of
   equal specificity and make View/Edit render larger than their neighbours.
   The transparent border keeps every variant the same box height: .btn-discreet
   and .btn-save carry a 1px border, .btn-primary and .btn-danger do not. */
.btn-compact {
    padding: 4px 10px;
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    font-weight: var(--weight-semibold);
    border: 1px solid transparent;
}

.btn-discreet.btn-compact,
.btn-save.btn-compact,
.btn-secondary.btn-compact {
    border-color: var(--btn-discreet-border);
}

.btn-discreet:hover {
    background: var(--btn-discreet-hover);
}

.btn-discreet:active {
    background: var(--btn-discreet-active);
}

.btn-discreet:disabled {
    opacity: 0.35;
    cursor: default;
}

/* Sticky depressed state for toggle-style row buttons (e.g. the Versions
   page's View buttons while their snapshot is shown below the table). */
.btn-discreet.btn-pressed,
.btn-discreet.btn-pressed:hover {
    background: var(--btn-discreet-active);
    box-shadow: inset var(--shadow-sm);
}

/* Non-interactive "this row holds the state" button (Versions page: the row
   that is Preferred / Active; Contracts page: the active contract). Filled
   green so the current selection stands out clearly from the surrounding
   action buttons; the label states the fact ("✓ Preferred" / "✓ Active"). */
.btn-state {
    pointer-events: none;
    cursor: default;
    background: var(--btn-state-bg);
    color: var(--btn-state-text);
    font-weight: var(--weight-bold);
    border: 1px solid transparent;
}

/* Row-action buttons whose label swaps with state ("Prefer" → "Preferred",
   "Activate" → "Active"): fixed width so the swap doesn't reflow the row.
   Sized to the longest label (the armed "Prefer — sure?"). */
.btn-row-fixed {
    width: 110px;
    padding-left: 0;
    padding-right: 0;
    text-align: center;
}

/* Small pill marking what a table row IS (e.g. the active or built-in
   contract) — informational, never interactive. */
.row-badge {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 9px;
    border: 1px solid var(--color-border);
    color: var(--color-text-muted);
    white-space: nowrap;
}

.row-badge-active {
    border-color: var(--color-success);
    color: var(--color-success);
}


/* ============================================================
   Status Indicators
   ============================================================ */

.status-indicator {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    display: inline-block;
    background: var(--status-idle);
    margin-right: 5px;
}

/* Green + pulse: the worker is actively doing something. */
.status-running {
    background: var(--status-running);
    box-shadow: 0 0 5px var(--status-running);
    animation: btn-running-pulse 1.5s ease-in-out infinite;
}

/* Blue: standing by — idle after a clean run (or never run). */
.status-stopped,
.status-completed {
    background: var(--status-stopped);
}

/* Blue + pulse: waiting — on the worker to wind down, or on capacity. */
.status-stopping {
    background: var(--status-idle);
    box-shadow: 0 0 5px var(--status-idle);
    animation: btn-running-pulse 1.5s ease-in-out infinite;
}

/* A forked pipeline leaf that was dispatched but not yet picked up by a worker.
   Distinct from running so the card reads "queued", not "in progress". */
.status-queued {
    background: var(--status-idle);
    box-shadow: 0 0 5px var(--status-idle);
    animation: btn-running-pulse 1.5s ease-in-out infinite;
}

/* Amber: idle, but the last run didn't work. */
.status-warn {
    background: var(--status-warn);
}

/* Red: critical — the task failed to start (e.g. dropped by a 429). */
.status-failed,
.status-error {
    background: var(--status-error);
    box-shadow: 0 0 5px var(--status-error);
}

.tiny-text {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    white-space: nowrap;
}


/* ============================================================
   Progress Bar
   ============================================================ */

.progress-container {
    background: var(--progress-bg);
    height: 20px;
    border-radius: 3px;
    margin: 10px 0;
    overflow: hidden;
    position: relative;
    flex: 0 0 auto;
}

.progress-bar {
    background: var(--progress-fill);
    height: 100%;
    width: 0%;
    transition: width 0.5s ease;
}

.progress-text {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    text-align: center;
    color: var(--progress-text);
    font-size: var(--text-xs);
    line-height: 20px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Streaming log feed for the Async Annotator card (replaces its progress bar). */
.batch-log-feed {
    margin: 10px 0;
    max-height: 96px;
    overflow-y: auto;
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-subtle);
    border-radius: 4px;
    padding: 8px 10px;
    font-family: var(--font-mono);
    line-height: var(--leading-normal);
    color: var(--color-text-secondary);
    white-space: pre-wrap;
    word-break: break-word;
}


/* ============================================================
   noUiSlider Overrides
   ============================================================ */

.noUi-target {
    background: var(--slider-track);
    border: none;
    box-shadow: none;
    height: 4px;
    margin: 15px 0 10px 0;
}

.noUi-connect {
    background: var(--slider-connect);
}

.noUi-horizontal .noUi-handle {
    height: 8px;
    width: 8px;
    top: -2px;
    right: -4px;
    border-radius: 50%;
    background: var(--slider-handle);
    border: none;
    box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
    cursor: grab;
    outline: none;
}

.noUi-handle:before,
.noUi-handle:after {
    display: none !important;
}

.noUi-tooltip {
    display: none;
}

.noUi-active {
    cursor: grabbing;
    background: var(--slider-handle);
    transform: scale(1.2);
}


/* ============================================================
   Video Analysis Slider Markers (extra_data indicators)
   ============================================================ */

#viewer-slider-wrap {
    position: relative;
}

#viewer-slider-markers {
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 0;
    transform: translateY(-50%);
}

.slider-extra-bin {
    position: absolute;
    bottom: 50%;
    background: var(--color-warning);
    border-radius: 1px 1px 0 0;
    pointer-events: auto;
    cursor: default;
}

/* Scrub chip: the activity timestamp of the video under the slider thumb.
   `left` is set from JS to follow the thumb; the translate centres it there. */
#viewer-slider-ts {
    position: absolute;
    top: 100%;
    transform: translateX(-50%);
    margin-top: 2px;
    padding: 2px 6px;
    white-space: nowrap;
    pointer-events: none;
    z-index: 3;
    border-radius: 4px;
    background: var(--tooltip-bg);
    color: var(--tooltip-text);
    border: 1px solid var(--tooltip-border);
    box-shadow: var(--shadow-sm);
}


/* ============================================================
   Modal
   ============================================================ */

.modal {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: var(--modal-overlay);
    backdrop-filter: blur(2px);
}

.modal-content {
    background-color: var(--modal-bg);
    margin: 15% auto;
    padding: 20px;
    border: 1px solid var(--modal-border);
    width: 50%;
    color: var(--modal-text);
    border-radius: 8px;
    box-shadow: var(--shadow-md);
    position: relative;
    font-size: var(--text-h3);
    line-height: var(--leading-relaxed);
}

.close-button,
.close {
    color: var(--color-text-tertiary);
    float: right;
    font-size: var(--text-h2);
    font-weight: var(--weight-bold);
    cursor: pointer;
    position: absolute;
    top: 5px;
    right: 15px;
}

.close-button:hover,
.close-button:focus,
.close:hover,
.close:focus {
    color: var(--white);
    text-decoration: none;
    cursor: pointer;
}


/* ============================================================
   Help Icon
   ============================================================ */

.help-icon {
    font-size: var(--text-h3);
    color: var(--color-accent);
    cursor: pointer;
    background: transparent;
    border: 1px solid var(--color-accent);
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    margin-left: 10px;
}

.help-icon:hover {
    background: var(--color-accent);
    color: var(--color-text-on-accent);
}


/* Global help button — sits on the right side of the main tab navigation. */
.global-help-btn {
    margin-left: auto;
    margin-right: 18px;
    align-self: center;
    flex-shrink: 0;
}


/* ============================================================
   Control Bar (shared across tabs)
   ============================================================ */

.control-bar {
    display: flex;
    align-items: center;
    padding: 10px;
    background-color: var(--control-bar-bg);
    margin-bottom: 20px;
    border-bottom: 1px solid var(--control-bar-border);
}

.control-bar h3 {
    margin: 0;
    color: var(--control-bar-text);
    font-size: var(--text-body);
}

.control-bar label {
    font-weight: var(--weight-bold);
    color: var(--control-bar-label);
}

.control-bar .dropdown {
    width: 300px;
    padding: 5px;
    background: var(--select-bg);
    border: 1px solid var(--select-border);
    color: var(--select-text);
}


/* ============================================================
   Section (collapsible blocks used in data_management, admin)
   ============================================================ */


.section-header {
    padding: 20px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    user-select: none;
}


/* ============================================================
   Cards
   ============================================================ */

.panel-card {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    padding: 15px;
    box-shadow: var(--shadow-sm);
}


/* ============================================================
   Tables
   ============================================================ */


.detail-row > td {
    overflow: hidden;
}


/* ============================================================
   Chips / Filter Pills
   ============================================================ */

.chip {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 4px;
    font-size: var(--text-sm);
    cursor: pointer;
    background: var(--chip-bg);
    border: 1px solid var(--chip-border);
    color: var(--chip-text);
    transition: all 0.15s;
}

.chip.selected,
.chip.active {
    background: var(--chip-selected-bg);
    border-color: var(--chip-selected-border);
    color: var(--chip-selected-text);
}


/* ============================================================
   Tooltip
   ============================================================ */

.meta-tooltip {
    position: relative;
    cursor: help;
    text-decoration: underline dotted var(--color-text-muted);
}

button.meta-tooltip {
    cursor: pointer;
    text-decoration: none;
}

button.meta-tooltip:disabled {
    cursor: not-allowed;
}

.meta-tooltip::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: 100%;
    left: 0;
    background: var(--tooltip-bg);
    color: var(--tooltip-text);
    padding: 6px 8px;
    border-radius: 4px;
    font-size: var(--text-xs);
    font-weight: var(--weight-normal);
    line-height: var(--leading-normal);
    white-space: pre-wrap;
    max-width: 280px;
    width: max-content;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
    z-index: 1000;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
    border: 1px solid var(--tooltip-border);
}

.meta-tooltip:hover {
    z-index: 1000;
}

.meta-tooltip:hover::after {
    opacity: 1;
    bottom: 110%;
}

/* Modifier: render the tooltip below the trigger instead of above. Use on
   buttons that sit near the top of an overflow-hidden container, where an
   upward tooltip would be clipped. */
.meta-tooltip.tooltip-below::after {
    bottom: auto;
    top: 100%;
}

.meta-tooltip.tooltip-below:hover::after {
    bottom: auto;
    top: 110%;
}

/* Modifier: anchor the tooltip to the trigger's right edge (extends leftward).
   Pairs with .tooltip-below for elements at the top-right of a container. */
.meta-tooltip.tooltip-right-anchored::after {
    left: auto;
    right: 0;
}

/* Modifier: a wider box for tooltips carrying a paragraph rather than a label.
   The default 280px turns an explanation into a tall narrow column. */
.meta-tooltip.tooltip-wide::after {
    max-width: 420px;
}

/* The (i) affordance next to a card title. Reveals what a worker does on hover
   or focus; keeps the title line uncluttered. */
.card-info {
    margin-left: 5px;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-normal);
}

.card-info.meta-tooltip {
    text-decoration: none;
    cursor: help;
}

.card-info:hover,
.card-info:focus-visible {
    color: var(--color-text-secondary);
}

/* floating_tooltip.js re-homes every tooltip onto #fyp-tooltip so it can escape
   clipping ancestors (the scrolling details panel, the overflow-hidden tab
   panes). It stamps this class on <html> once loaded; the ::after rendering
   above stays as the no-JS fallback and is suppressed here so only one tooltip
   is ever drawn. Keep the two visually identical. */
html.fyp-floating-tooltips .meta-tooltip::after {
    display: none;
}

#fyp-tooltip {
    position: fixed;
    top: -9999px;
    left: -9999px;
    background: var(--tooltip-bg);
    color: var(--tooltip-text);
    padding: 6px 8px;
    border-radius: 4px;
    font-size: var(--text-xs);
    font-weight: var(--weight-normal);
    line-height: var(--leading-normal);
    white-space: pre-wrap;
    max-width: 280px;
    width: max-content;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
    z-index: 4000;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
    border: 1px solid var(--tooltip-border);
}

#fyp-tooltip.is-visible {
    opacity: 1;
}

/* Mirrors .meta-tooltip.tooltip-wide — floating_tooltip.js copies the modifier
   onto the shared element, so the two renderings stay identical. */
#fyp-tooltip.tooltip-wide {
    max-width: 420px;
}


/* ============================================================
   Custom ribbon tooltip (Timelines)
   Plotly's built-in tooltip can't render multi-line content inside
   a 50px-tall ribbon, so we draw our own positioned to the cursor.
   ============================================================ */

/* Hide Plotly's built-in hover label inside ribbons — we render our own. */
[id^="ribbon-"] .hoverlayer {
    display: none !important;
}

.ribbon-tooltip {
    position: fixed;
    display: none;
    z-index: 1000;
    pointer-events: none;
    background: var(--tooltip-bg);
    color: var(--tooltip-text);
    border: 1px solid var(--tooltip-border);
    border-radius: 4px;
    padding: 6px 10px;
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
    max-width: 260px;
}

.ribbon-tooltip-title {
    font-weight: var(--weight-semibold);
    margin-bottom: 3px;
}

.ribbon-tooltip-line {
    color: var(--tooltip-text);
}

.ribbon-tooltip-badge {
    color: var(--tooltip-text);
    margin-top: 2px;
}


/* ============================================================
   Timelines — shared time-window (zoom) control in the control bar
   ============================================================ */

.timelines-zoom-control {
    display: flex;
    align-items: center;
    color: var(--color-text-muted);
    white-space: nowrap;
}

.timelines-zoom-hint {
    color: var(--color-text-faint);
}

.timelines-zoom-window {
    display: flex;
    align-items: center;
    gap: 6px;
}

.timelines-zoom-window .font-medium {
    color: var(--color-text-primary);
}


/* ============================================================
   Plotly modebar — themed colors, fade in only on chart hover
   ============================================================ */

.timeline-chart-wrapper .modebar {
    opacity: 0;
    transition: opacity 0.15s ease;
}

.timeline-chart-wrapper:hover .modebar {
    opacity: 1;
}

.timeline-chart-wrapper .modebar-btn .icon path {
    fill: var(--color-text-faint) !important;
}

.timeline-chart-wrapper .modebar-btn:hover .icon path,
.timeline-chart-wrapper .modebar-btn.active .icon path {
    fill: var(--color-text-secondary) !important;
}


/* ============================================================
   Chart type badge (Timelines)
   ============================================================ */

.chart-type-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: var(--text-xxs);
    font-weight: var(--weight-medium);
    font-family: var(--font-sans);
    letter-spacing: 0.02em;
    background: var(--chip-bg);
    border: 1px solid var(--chip-border);
    color: var(--color-text-secondary);
    text-decoration: none;
    cursor: help;
    user-select: none;
    white-space: nowrap;
}

.chart-type-badge.meta-tooltip {
    text-decoration: none;
}


/* ============================================================
   Collections Tab Styles (moved from inline)
   ============================================================ */

.pe-edit-activity-section {
    padding: 10px 20px;
}

.pe-container {
    display: flex;
    gap: 20px;
    padding: 0 20px 20px 20px;
    height: calc(100vh - 370px);
    overflow: hidden;
}

.pe-main {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.stats-table {
    width: 100%;
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

.stats-table td {
    padding: 4px;
    border-bottom: 1px solid var(--color-border);
    color: var(--color-text-primary);
}

.stats-table td:last-child {
    text-align: right;
    font-weight: var(--weight-bold);
}


.hidden {
    display: none;
}

.helper-text {
    font-size: var(--text-sm);
    color: var(--color-text-tertiary);
    margin-bottom: 15px;
}

.strips-container {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.strip-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.strip-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
}

.strip-label {
    font-weight: var(--weight-semibold);
    font-size: var(--text-sm);
    color: var(--color-text-primary);
}

.strip-right-info {
    display: flex;
    align-items: baseline;
    gap: 8px;
}

.strip-selected-value {
    font-size: var(--text-xs);
    color: var(--color-accent);
    font-weight: var(--weight-medium);
}

.strip-percentile-badge {
    font-size: var(--text-xs);
    color: var(--color-danger);
    font-weight: var(--weight-semibold);
    background: rgba(179, 90, 94, 0.15);
    padding: 1px 5px;
    border-radius: 3px;
    min-width: 28px;
    text-align: center;
}

.strip-swarm {
    width: 100%;
    height: 44px;
    display: block;
}

.strip-axis {
    display: flex;
    justify-content: space-between;
    font-size: var(--text-xxs);
    color: var(--color-text-faint);
    margin-top: 0;
}


/* ============================================================
   Timelines Tab Styles (moved from inline)
   ============================================================ */

.stats-section {
    margin-top: 15px;
}

.stats-list {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: var(--text-sm);
}

.stats-list li {
    display: flex;
    justify-content: space-between;
    padding: 4px 0;
    border-bottom: 1px solid var(--color-border);
}

.stat-label {
    color: var(--color-text-secondary);
}

.timelines-info-icon-wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.timelines-info-icon-wrapper:hover svg {
    stroke: var(--color-text-primary);
}

.timelines-info-tooltip {
    display: none;
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-strong);
    border-radius: 6px;
    padding: 12px 16px;
    min-width: 340px;
    max-width: 450px;
    box-shadow: var(--shadow-lg);
    margin-top: 6px;
}

.timelines-info-icon-wrapper:hover .timelines-info-tooltip {
    display: block;
}

/* Timelines — hover effects for interactive elements */
.filter-chip {
    transition: opacity 0.15s, transform 0.15s;
}

.filter-chip:hover {
    opacity: 1 !important;
    transform: scale(1.08);
}

#timelines-sidebar-toggle,
#explore-sidebar-toggle,
#explore-sidebar-toggle-2,
#va-left-toggle,
#va-right-toggle {
    transition: background 0.15s;
    border-radius: 4px;
}

#timelines-sidebar-toggle:hover,
#explore-sidebar-toggle:hover,
#explore-sidebar-toggle-2:hover,
#va-left-toggle:hover,
#va-right-toggle:hover {
    background: var(--color-bg-elevated) !important;
}

#timelines-sidebar-toggle:hover svg,
#explore-sidebar-toggle:hover svg,
#explore-sidebar-toggle-2:hover svg,
#va-left-toggle:hover svg,
#va-right-toggle:hover svg {
    stroke: var(--color-text-primary);
}

#timelines-charts-container button[id^="findings-toggle-"] {
    transition: background 0.15s, border-color 0.15s;
}

#timelines-charts-container button[id^="findings-toggle-"]:hover {
    background: var(--color-bg-hover) !important;
    border-color: var(--color-text-tertiary) !important;
}


/* ============================================================
   Video Analysis Tab Styles (moved from inline)
   ============================================================ */

/* When nav-controls wraps to its own row, expand to full width so buttons centre */
#video_analysis .nav-controls {
    flex-grow: 1;
}

#viewer-metadata {
    display: block;
}

#viewer-metadata tbody {
    display: block;
}

#viewer-metadata tr.detail-section-header {
    display: block;
    cursor: pointer;
    background: var(--color-border);
}

#viewer-metadata tr.detail-section-header td {
    display: block;
    padding: 8px 10px;
    font-weight: var(--weight-bold);
    color: var(--color-text-primary);
    border-bottom: none;
}

#viewer-metadata tr.detail-row {
    display: flex;
    flex-wrap: wrap;
    padding: 6px 10px;
    border-bottom: 1px solid var(--color-border-subtle);
}

#viewer-metadata tr.detail-row:hover {
    background: var(--table-row-hover);
}

#viewer-metadata tr.detail-row td.detail-key {
    flex: 0 0 100%;
    padding: 0 0 2px 0;
    font-weight: var(--weight-bold);
    color: var(--color-text-tertiary);
    font-size: var(--text-xs);
    border-bottom: none;
    word-break: break-word;
}

#viewer-metadata tr.detail-row td.detail-val {
    flex: 0 0 100%;
    padding: 0;
    color: var(--color-text-secondary);
    border-bottom: none;
    word-break: break-word;
}

#viewer-metadata tr.detail-display-id {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 10px;
    background: var(--color-border-subtle);
}

#viewer-metadata tr.detail-display-id td {
    padding: 0;
    border-bottom: none;
}

/* Drill-down notice bar (Video Analysis): message on the left, dismiss on the
   right. Hidden with display:none, so the flex layout only applies when shown. */
#viewer-drilldown-notice {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 8px 15px;
    background: var(--color-bg-elevated);
    border-bottom: 1px solid var(--color-border-subtle);
    color: var(--color-text-muted);
}

#viewer-drilldown-notice .viewer-notice-text {
    flex: 1 1 auto;
}

#viewer-drilldown-notice .viewer-notice-close {
    flex: 0 0 auto;
    background: none;
    border: none;
    padding: 0 4px;
    line-height: 1;
    cursor: pointer;
    color: var(--color-text-muted);
    font-size: var(--text-h3);
}

#viewer-drilldown-notice .viewer-notice-close:hover {
    color: var(--color-text-primary);
}


/* ============================================================
   Data Management Styles (moved from inline)
   ============================================================ */

.form-group-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.form-group-row label {
    flex: 1;
    text-align: left;
    margin-right: 15px;
    color: var(--color-text-secondary);
}

.form-group-row .control-input {
    flex: 1;
    max-width: 50%;
    text-align: right;
}


/* ============================================================
   Auth Pages (login / signup shared styles)
   ============================================================ */

.auth-container {
    display: flex;
    height: 100vh;
    overflow: hidden;
    background-color: var(--color-bg-primary);
    color: var(--color-text-primary);
}

.auth-sidebar {
    width: 400px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--color-border-subtle);
    background-color: var(--color-bg-surface);
    overflow-y: auto;
}

.auth-content {
    flex: 1;
    padding: 40px 60px;
    overflow-y: auto;
    background-color: var(--color-bg-primary);
    position: relative;
}

.auth-form-container {
    padding: 30px 20px;
    border-bottom: 1px solid var(--color-border-subtle);
}

.auth-form {
    display: flex;
    flex-direction: column;
    gap: 15px;
}

.auth-form label {
    display: block;
    margin-bottom: 5px;
    color: var(--color-text-tertiary);
}

.auth-form input[type="text"],
.auth-form input[type="password"] {
    width: 100%;
    padding: 10px;
    border-radius: 4px;
    border: 1px solid var(--color-border);
    background: var(--color-bg-input);
    color: var(--input-text);
}

.auth-submit-btn {
    background: var(--color-info);
    color: var(--white);
    border: none;
    padding: 12px;
    border-radius: 4px;
    cursor: pointer;
    font-weight: var(--weight-bold);
    margin-top: 10px;
}

.auth-submit-btn:hover {
    opacity: 0.9;
}

.auth-flash-info {
    background: rgba(91, 126, 152, 0.15);
    border: 1px solid var(--color-info);
    color: var(--color-info);
    padding: 10px;
    border-radius: 4px;
    margin-bottom: 20px;
    text-align: center;
}

.auth-flash-error {
    background: rgba(179, 90, 94, 0.15);
    border: 1px solid var(--color-danger);
    color: var(--color-danger);
    padding: 10px;
    border-radius: 4px;
    margin-bottom: 20px;
    text-align: center;
}


/* ============================================================
   Home Page Styles
   ============================================================ */


.widget-box {
    padding: 20px;
    border-bottom: 1px solid var(--color-border-subtle);
}

.widget-box h3 {
    margin-top: 0;
    color: var(--color-text-primary);
    font-size: var(--text-body);
    margin-bottom: 15px;
}

.slack-updates {
    background: var(--color-bg-inset);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    padding: 10px;
    max-height: 400px;
    overflow-y: auto;
}

.slack-message {
    padding: 10px;
    border-bottom: 1px solid var(--color-border-subtle);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

.slack-message strong {
    color: var(--color-accent);
}

.slack-message span {
    color: var(--color-text-secondary);
}

.slack-message .timestamp {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    margin-top: 4px;
}

.note-callout {
    background: var(--color-bg-surface);
    border-left: 4px solid var(--color-save);
    padding: 15px 20px;
    border-radius: 0 4px 4px 0;
    margin-bottom: 15px;
}

.note-callout p {
    margin: 0;
    line-height: var(--leading-relaxed);
    color: var(--color-text-secondary);
}

.hero-title {
    color: var(--color-accent);
    margin-bottom: 20px;
    font-size: var(--text-hero);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-tight);
    text-align: center;
}

.hero-subtitle {
    font-size: var(--text-body);
    line-height: var(--leading-relaxed);
    color: var(--color-text-primary);
    margin-bottom: 40px;
    text-align: center;
}


/* ============================================================
   Auth Header (index.html)
   ============================================================ */

.auth-header {
    display: flex;
    align-items: center;
    padding: 18px 24px;
    background: var(--color-bg-primary);
}

#global-study-select {
    margin-left: 16px;
    max-width: 220px;
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    color: var(--color-text-primary);
}

.auth-header-user {
    margin-left: auto;
    color: var(--color-text-secondary);
}

.global-tasks-badge {
    margin-left: auto;
    margin-right: 12px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 12px;
    background: var(--color-bg-tertiary);
    color: var(--status-running);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    cursor: default;
    user-select: none;
}

.global-tasks-spinner {
    width: 12px;
    height: 12px;
    border: 2px solid var(--color-border);
    border-top-color: var(--status-running);
    border-radius: 50%;
    animation: global-spin 0.8s linear infinite;
}

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

.global-tasks-count {
    font-variant-numeric: tabular-nums;
}

.app-brand {
    font-family: 'DM Sans', var(--font-sans);
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--color-text-primary);
    text-decoration: none;
    cursor: pointer;
    transition: opacity 0.15s ease;
}

.app-brand:hover {
    opacity: 0.8;
}


/* ============================================================
   Utility Classes
   ============================================================ */

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

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

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

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

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

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

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

.bg-surface {
    background: var(--color-bg-surface);
}

.bg-elevated {
    background: var(--color-bg-elevated);
}

.bg-inset {
    background: var(--color-bg-inset);
}

.border-default {
    border: 1px solid var(--color-border);
}

.border-subtle {
    border-bottom: 1px solid var(--color-border-subtle);
}


/* ============================================================
   Loading Animation (Pacman)
   ============================================================ */

.fun-loader-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 30px;
}

.fun-loader {
    display: inline-block;
    position: relative;
    width: 80px;
    height: 80px;
}

.fun-loader div {
    position: absolute;
    border-radius: 50%;
    animation-timing-function: cubic-bezier(0, 1, 1, 0);
}

.fun-loader div:nth-child(1) {
    width: 80px;
    height: 80px;
    top: 0;
    left: 0;
    background: var(--color-gold);
    clip-path: polygon(0 0, 100% 0, 100% 50%, 0 50%);
    transform-origin: 50% 50%;
    animation: pacman-top 0.5s infinite alternate ease-in-out;
    z-index: 1;
}

.fun-loader div:nth-child(2) {
    width: 80px;
    height: 80px;
    top: 0;
    left: 0;
    background: var(--color-gold);
    clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0 100%);
    transform-origin: 50% 50%;
    animation: pacman-bottom 0.5s infinite alternate ease-in-out;
    z-index: 1;
}

.fun-loader div:nth-child(3),
.fun-loader div:nth-child(4),
.fun-loader div:nth-child(5) {
    width: 15px;
    height: 15px;
    background: var(--color-text-primary);
    top: 32.5px;
    left: 90px;
    animation: pacman-food 1.5s infinite linear;
    z-index: 0;
    opacity: 0;
}

.fun-loader div:nth-child(3) {
    animation-delay: 0s;
}
.fun-loader div:nth-child(4) {
    animation-delay: 0.5s;
}
.fun-loader div:nth-child(5) {
    animation-delay: 1.0s;
}

@keyframes pacman-top {
    0% { transform: rotate(-35deg); }
    100% { transform: rotate(0deg); }
}

@keyframes pacman-bottom {
    0% { transform: rotate(35deg); }
    100% { transform: rotate(0deg); }
}

@keyframes pacman-food {
    0% {
        transform: translateX(0);
        opacity: 1;
    }
    100% {
        transform: translateX(-60px);
        opacity: 0;
    }
}

.loading-text {
    margin-top: 15px;
    color: var(--color-gold);
    font-family: var(--font-mono);
    font-weight: var(--weight-bold);
    font-size: var(--text-h3);
    animation: pulse-text 1s infinite alternate;
}

@keyframes pulse-text {
    from { opacity: 0.7; }
    to { opacity: 1; }
}

/* Explanatory notice shown in place of the video player when an item has no
   downloaded media (e.g. YouTube long-form past the download duration cap). */
.viewer-video-notice {
    max-width: 360px;
    margin: 0 auto;
    padding: 24px;
    text-align: center;
    color: var(--color-text-muted);
    font-size: var(--text-body);
    line-height: var(--leading-relaxed);
}


/* ============================================================
   Accessibility: Reduced Motion
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}


/* ── Filter section headers ── */
.filter-section-header {
    background: var(--color-border);
    transition: background 0.2s;
}

.filter-section-header.has-active-filter {
    background: var(--color-accent);
    color: var(--btn-primary-text) !important;
}

.filter-sort-toggle {
    background: none;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    color: var(--color-text-muted);
    cursor: pointer;
    font-size: var(--text-xs);
    font-family: var(--font-mono);
    line-height: 1;
    padding: 2px 5px;
    transition: color 0.15s, border-color 0.15s;
    flex-shrink: 0;
}
.filter-sort-toggle:hover {
    color: var(--color-text-primary);
    border-color: var(--color-text-muted);
}

/* ── Per-variable value search (capped filter dropdowns) ── */
.filter-value-search-wrap {
    margin: 4px 0;
}
.filter-value-search {
    width: 100%;
    box-sizing: border-box;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 4px;
    color: var(--color-text-primary);
    font-family: var(--font-sans);
    padding: 3px 6px;
}
.filter-value-search::placeholder {
    color: var(--color-text-faint);
}
.filter-value-search-status {
    color: var(--color-text-faint);
    padding: 2px 2px 0;
}
.filter-checkbox-item--pinned {
    border-left: 2px solid var(--color-accent);
    padding-left: 3px;
}
/* Hides items whose inline display:flex would defeat the hidden attribute. */
.fvs-hidden {
    display: none !important;
}


/* ── Explore chart drill-down affordance ── */
#explorer-v2-stats .js-plotly-plot .bars .point path,
#explorer-v2-stats .js-plotly-plot .trace.bars path {
    cursor: pointer !important;
}

#explorer-v2-stats .drill-hint {
    opacity: 0;
    transition: opacity 0.2s;
}

#explorer-v2-stats .stats-card:hover .drill-hint {
    opacity: 1;
}


/* ── Correlations tab layout ── */
.corr-status {
    color: var(--control-bar-info);
}

/* Single compact control bar (Timelines layout): every control on one row,
   small type, abbreviated labels, narrow inputs. */
.corr-control-bar {
    flex-wrap: wrap;
    gap: 10px;
    padding: 5px 10px;
    font-size: var(--text-xs);
}

.corr-control-bar label {
    font-weight: var(--weight-normal);
}

.corr-control-bar .dropdown {
    width: auto;
    padding: 2px 4px;
    font-size: var(--text-xs);
}

.corr-view-toggle .toggle-option {
    padding: 3px 10px;
    font-size: var(--text-xs);
}

.corr-scatter-controls {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}

.corr-control-label {
    color: var(--control-bar-label);
    margin-right: 0;
}

/* Fixed widths, and scoped to the bar so they outrank `.control-bar .dropdown`
   (width: 300px): a <select> otherwise auto-sizes to its longest option, which
   pushed the bar onto a second row. Full variable names stay readable in the
   open dropdown and in the axis titles. */
.corr-control-bar .corr-select {
    width: 150px;
}

.corr-control-bar .corr-select-narrow {
    width: 105px;
}

.corr-checkbox-group {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--color-text-muted);
    cursor: pointer;
    user-select: none;
}

.corr-checkbox-group input[type="checkbox"] {
    margin: 0;
    cursor: pointer;
}

/* Sized to sit flush with the selects on the same row. .btn-discreet sets its
   own font-size, so the size has to be restated here rather than left to the
   .text-xxs utility class. */
.corr-control-bar .corr-control-disabled {
    opacity: 0.45;
}

.corr-control-disabled input {
    cursor: not-allowed;
}

.corr-bar-button {
    padding: 2px 8px;
    font-size: var(--text-xxs);
    line-height: 1.4;
}

/* Status / errors only - pushed right so it never shifts the knobs, which all
   read left-to-right. */
.corr-bar-status {
    margin-left: auto;
}

/* Observation count sits in the corner of the plot/table it describes. */
.corr-plot-wrap {
    position: relative;
    flex: 1 1 auto;
    min-height: 460px;
    display: flex;
    flex-direction: column;
}

.corr-obs-badge {
    position: absolute;
    top: 6px;
    left: 12px;
    z-index: 2;
    color: var(--color-text-tertiary);
    pointer-events: none;
}

/* The app shell locks body scrolling, so a fixed `height: calc(100vh - 180px)`
   clipped the x-axis title and the caption outright on shorter viewports
   (Chrome with a bookmarks bar). The tab now scrolls internally instead: the
   plot keeps a workable minimum size and anything past the fold is reachable. */
.corr-main {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    gap: 20px;
}

.corr-viz-panel {
    flex: 1;
    min-width: 0;
    min-height: calc(100vh - 200px);
    display: flex;
    flex-direction: column;
    padding: 0;
}

.corr-plot {
    flex: 1 1 auto;
    min-height: 0;
}

.corr-banner {
    padding: 6px 12px;
    font-size: var(--text-xs);
    color: var(--color-text-secondary);
    background: var(--color-bg-elevated);
    border-bottom: 1px solid var(--color-border-subtle);
}

.corr-banner-warn {
    color: var(--color-text-primary);
    border-left: 3px solid var(--color-warning);
}

/* One size for the whole caption: it used to mix --text-sm with inline
   .text-xs spans, so a single sentence changed size mid-paragraph. */
.corr-caption {
    padding: 8px 14px;
    font-size: var(--text-xs);
    color: var(--color-text-secondary);
    background: var(--color-bg-elevated);
    border-top: 1px solid var(--color-border-subtle);
    line-height: var(--leading-normal);
}

.corr-caption .text-xs,
.corr-caption .text-sm {
    font-size: inherit;
}

/* Sortable Group-differences headers. */
.corr-stats-table th.corr-sortable {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
    color: var(--color-text-muted);
}

.corr-stats-table th.corr-sortable:hover {
    color: var(--color-text-primary);
}

.corr-stats-table th.corr-sorted {
    color: var(--color-text-primary);
}

.corr-caption .corr-caption-warning {
    color: var(--color-warning);
}

/* The caption strip now sits ABOVE the plot (highlight text + explainer),
   so its divider flips from a top border to a bottom border. */
.corr-caption.corr-topbar {
    border-top: none;
    border-bottom: 1px solid var(--color-border-subtle);
}

/* "What is this?" toggle after the highlight text (and per group-diff table) */
.corr-explainer-toggle,
.corr-table-explainer-toggle a {
    color: var(--color-link);
    text-decoration: none;
    white-space: nowrap;
}

.corr-explainer-toggle:hover,
.corr-table-explainer-toggle a:hover {
    text-decoration: underline;
}

.corr-table-explainer-toggle {
    margin: 0 0 6px;
    font-size: var(--text-xs);
}

/* Collapsed-by-default explanatory copy (per view and per table). Full
   width on purpose — a capped column looked odd beside a much wider plot. */
.corr-explainer-body {
    margin-top: 8px;
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
}

.corr-explainer-body p {
    margin: 0 0 8px;
}

.corr-explainer-body p:last-child {
    margin-bottom: 0;
}

.corr-table-wrap .corr-table-explainer {
    margin: 0 0 10px;
    padding: 8px 12px;
    background: var(--color-bg-elevated);
    border-left: 3px solid var(--color-border-strong);
}

.corr-table-wrap {
    overflow: auto;
    padding: 12px 16px;
    height: 100%;
}

.corr-table-wrap h3 {
    margin: 16px 0 8px;
}

/* Group-differences panels: each of the two question-panels is a bordered
   section so their separation is unmistakable. */
.corr-table-wrap .corr-panel {
    margin: 0 0 24px;
    padding: 2px 16px 14px;
    border: 1px solid var(--color-border-subtle);
    border-radius: 6px;
}

.corr-table-wrap .corr-panel-title {
    margin: 14px 0 4px;
}

.corr-table-wrap .corr-panel-intro {
    margin: 0 0 8px;
    color: var(--color-text-secondary);
}

/* Combined "Key findings" report at the top of the Group-differences page */
.corr-table-wrap .corr-report {
    margin: 4px 0 20px;
    padding: 10px 14px;
    background: var(--color-bg-elevated);
    border-left: 3px solid var(--color-accent);
    color: var(--color-text-primary);
}

.corr-report .corr-report-title {
    margin-bottom: 4px;
}

.corr-report ul {
    margin: 0;
    padding-left: 18px;
}

.corr-report li {
    margin: 3px 0;
    line-height: var(--leading-normal);
}

/* On-demand AI interpretation inside the Key findings box */
.corr-report .corr-interp-actions {
    margin: 8px 0 0;
}

.corr-report .corr-interp {
    margin: 8px 0 0;
    padding-top: 8px;
    border-top: 1px solid var(--color-border-subtle);
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
}

.corr-report .corr-interp-loading,
.corr-report .corr-interp-disclaimer {
    margin: 6px 0 0;
    color: var(--color-text-tertiary);
}

.corr-report .corr-interp-error {
    margin: 6px 0 0;
    color: var(--color-warning);
}

/* Dagger marking a comparison nested in collections (hover for the caveat) */
.corr-nested-badge {
    color: var(--color-warning);
    cursor: help;
    font-weight: var(--weight-semibold);
}

.corr-table-wrap .collection-table th {
    text-align: left;
    padding: 4px 10px;
    border-bottom: 1px solid var(--color-border-strong);
    color: var(--color-text-secondary);
}

.corr-table-wrap .collection-table td {
    padding: 3px 10px;
}


/* ── Correlations scatter drill-down affordance ── */
#pca-plot .js-plotly-plot .scatterlayer .trace .points path,
#pca-plot .scatterlayer .trace .points path {
    cursor: pointer !important;
}

/* ── Drill-down confirmation popup ── */
.drilldown-overlay {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--modal-overlay);
    backdrop-filter: blur(3px);
    opacity: 0;
    transition: opacity 0.2s ease;
}

.drilldown-overlay.visible {
    opacity: 1;
}

.drilldown-card {
    background: var(--modal-bg);
    border: 1px solid var(--modal-border);
    border-radius: 12px;
    padding: 24px 28px;
    max-width: 420px;
    width: 90%;
    box-shadow: var(--shadow-md);
    color: var(--modal-text);
    transform: translateY(8px) scale(0.97);
    transition: transform 0.2s ease;
}

.drilldown-overlay.visible .drilldown-card {
    transform: translateY(0) scale(1);
}

.drilldown-header {
    display: flex;
    align-items: center;
    gap: 10px;
}

.drilldown-icon {
    font-size: var(--text-h2);
    line-height: 1;
}

.drilldown-filter-preview {
    display: flex;
    align-items: center;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    padding: 8px 14px;
}

.drilldown-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
}

.drilldown-actions .btn {
    padding: 8px 20px;
    border-radius: 6px;
    cursor: pointer;
    font-size: var(--text-body);
    font-weight: var(--weight-medium);
    font-family: var(--font-sans);
    border: none;
    transition: opacity 0.15s;
}

.drilldown-actions .btn:hover {
    opacity: 0.85;
}


/* ── Stop confirmation overlay ── */
.stop-confirm-overlay {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--modal-overlay);
    backdrop-filter: blur(3px);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.stop-confirm-overlay.visible {
    pointer-events: auto;
    opacity: 1;
}

.stop-confirm-card {
    background: var(--modal-bg);
    border: 1px solid var(--modal-border);
    border-radius: 12px;
    padding: 24px 28px;
    max-width: 380px;
    width: 90%;
    box-shadow: var(--shadow-md);
    color: var(--modal-text);
    transform: translateY(8px) scale(0.97);
    transition: transform 0.2s ease;
}

.stop-confirm-overlay.visible .stop-confirm-card {
    transform: translateY(0) scale(1);
}


/* ── Log modal ── */
.log-modal-card {
    background: var(--modal-bg);
    border: 1px solid var(--modal-border);
    border-radius: 12px;
    padding: 24px 28px;
    max-width: 900px;
    width: 90%;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    box-shadow: var(--shadow-md);
    color: var(--modal-text);
    transform: translateY(8px) scale(0.97);
    transition: transform 0.2s ease;
}

.log-modal-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    flex-wrap: wrap;
}

.log-modal-toolbar #log-modal-run {
    flex: 1 1 260px;
    min-width: 0;
}

.log-modal-toolbar #log-modal-filter {
    flex: 0 1 180px;
    min-width: 0;
}

.stop-confirm-overlay.visible .log-modal-card {
    transform: translateY(0) scale(1);
}

.log-modal-body {
    flex: 1;
    overflow-y: auto;
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-subtle);
    border-radius: 4px;
    padding: 10px;
    white-space: pre-wrap;
    word-break: break-word;
    line-height: 1.4;
    min-height: 300px;
}


/* ── View log link ── */
.view-log-link {
    text-decoration: none;
    color: var(--color-text-tertiary);
    opacity: 0.7;
    transition: opacity 0.15s;
    cursor: pointer;
}

.view-log-link:hover {
    opacity: 1;
    text-decoration: underline;
}

/* Cross-browser thin, discreet scrollbars (matches macOS overlay feel on Windows/Linux) */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--color-border-strong) transparent;
}

*::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

*::-webkit-scrollbar-track {
    background: transparent;
}

*::-webkit-scrollbar-thumb {
    background-color: var(--color-border);
    border-radius: 8px;
    border: 2px solid transparent;
    background-clip: padding-box;
}

*::-webkit-scrollbar-thumb:hover {
    background-color: var(--color-border-strong);
    border: 2px solid transparent;
    background-clip: padding-box;
}

*::-webkit-scrollbar-corner {
    background: transparent;
}

/* Scrollable panels whose content must be discoverable: force the scrollbar
   gutter and thumb to stay visible instead of the overlay/hidden default
   (e.g. the human-test variable list — hidden rows were being missed). */
.always-scroll {
    overflow-y: scroll;
    scrollbar-width: thin;
    scrollbar-color: var(--color-border) var(--color-bg-elevated);
}

.always-scroll::-webkit-scrollbar-track {
    background: var(--color-bg-elevated);
    border-radius: 8px;
}

.always-scroll::-webkit-scrollbar-thumb {
    background-color: var(--color-border-strong);
}


/* ============================================================
   Small-screen responsive layer
   (single breakpoint at 860px — see DEVELOPING.md / plan)
   ============================================================ */

/* Base utilities (apply at all widths) */
.mobile-only { display: none; }

.nav-toggle {
    display: none;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--tab-text);
    font-size: 22px;
    line-height: 1;
    padding: 10px 16px;
    align-items: center;
    justify-content: center;
}

.nav-toggle:hover {
    background: var(--tab-hover-bg);
}

.tab-nav-drawer {
    display: contents;
}

.current-tab-label {
    display: none;
    align-items: center;
    font-family: var(--font-sans);
    font-size: var(--text-body);
    font-weight: var(--weight-semibold);
    color: var(--color-text-primary);
    padding: 0 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.responsive-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 90;
}

.responsive-backdrop.is-visible {
    display: block;
}

.mobile-drawer-trigger {
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    color: var(--color-text-primary);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    padding: 6px 12px;
    border-radius: 4px;
    cursor: pointer;
}

.mobile-drawer-trigger:hover {
    background: var(--tab-hover-bg);
}

/* Two-level mobile nav: sub-page list under a top-level tab.
   Hidden at all widths by default; revealed inside the mobile breakpoint. */
.tab-subnav {
    display: none;
}

@media (max-width: 860px) {
    /* ----- Utility visibility ----- */
    .mobile-only { display: inline-flex; }

    /* ----- Header: wrap so study dropdown gets its own row ----- */
    .auth-header {
        flex-wrap: wrap;
        padding: 10px 14px;
        gap: 8px;
        row-gap: 8px;
    }

    .app-brand {
        font-size: 1.15rem;
        flex: 0 0 auto;
    }

    #global-study-select {
        order: 99;
        flex: 1 1 100%;
        margin-left: 0;
        max-width: none;
    }

    .auth-header-user {
        margin-left: auto;
        font-size: var(--text-xs);
    }

    .global-tasks-badge {
        margin-left: 0;
    }

    /* ----- Tab nav → hamburger drawer ----- */
    .tab-nav {
        position: relative;
        padding: 0;
        align-items: center;
    }

    .nav-toggle {
        display: inline-flex;
    }

    .current-tab-label {
        display: inline-flex;
        flex: 1 1 auto;
    }

    /* Hide the desktop sidebar/details toggles inside tab control bars */
    .desktop-only-toggle {
        display: none !important;
    }

    .tab-nav-drawer {
        display: flex;
        flex-direction: column;
        position: fixed;
        top: 0;
        left: 0;
        width: min(78vw, 300px);
        max-width: 320px;
        height: 100%;
        background: var(--color-bg-surface);
        border-right: 1px solid var(--color-border);
        z-index: 100;
        padding-top: 16px;
        overflow-y: auto;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: var(--shadow-lg);
    }

    .tab-nav.is-open .tab-nav-drawer {
        transform: translateX(0);
    }

    .tab-nav-drawer .tab-button {
        border-right: none;
        border-bottom: 1px solid var(--color-border-subtle);
        text-align: left;
        width: 100%;
        padding: 14px 18px;
    }

    /* ----- Side panels → fixed slide-in drawers ----- */
    [data-mobile-drawer] {
        position: fixed !important;
        top: 0;
        bottom: 0;
        width: min(85vw, 340px) !important;
        max-width: 340px !important;
        flex: 0 0 auto !important;
        z-index: 100;
        background: var(--color-bg-surface);
        transition: transform 0.2s ease;
        box-shadow: var(--shadow-lg);
        overflow-y: auto;
        display: flex !important;
        flex-direction: column !important;
        height: 100% !important;
    }

    [data-mobile-drawer="left"] {
        left: 0;
        right: auto;
        transform: translateX(-100%);
    }

    [data-mobile-drawer="right"] {
        right: 0;
        left: auto;
        transform: translateX(100%);
    }

    [data-mobile-drawer].is-open {
        transform: translateX(0);
    }

    /* Make container rows reflow so panel removal collapses to full-width content */
    #explore .container,
    #correlations .corr-main,
    #video_analysis .container {
        flex-direction: column !important;
        height: auto !important;
        min-height: calc(100vh - 200px);
    }

    /* Slice 2 mobile drawer visibility is controlled by JS (setExplorerV2SliceMode) */

    /* Data Management / Admin / My stuff: sidebar becomes a left drawer */
    #data_management,
    #admin,
    #my_stuff {
        flex-direction: column !important;
    }

    /* The desktop sub-page sidebar is replaced by the two-level main drawer
       on small screens. Keep the markup (for desktop) but hide it. */
    .dm-sidebar {
        display: none !important;
    }

    .dm-content {
        padding: 14px;
    }

    /* ----- Two-level main nav: chevron + nested sub-pages ----- */
    .tab-nav-drawer .tab-button.has-subpages {
        position: relative;
        padding-right: 40px;
    }

    .tab-nav-drawer .tab-button.has-subpages::after {
        content: '\203A';
        position: absolute;
        right: 16px;
        top: 50%;
        font-size: 1.4em;
        line-height: 1;
        color: var(--color-text-secondary);
        transform: translateY(-50%) rotate(0deg);
        transform-origin: center center;
        transition: transform 0.15s ease, color 0.15s ease;
        pointer-events: none;
    }

    .tab-nav-drawer .tab-button.has-subpages.is-expanded::after {
        transform: translateY(-50%) rotate(90deg);
        color: var(--color-text-primary);
    }

    .tab-subnav {
        display: flex;
        flex-direction: column;
        list-style: none;
        margin: 0;
        padding: 0;
        background: var(--color-bg-primary);
        border-bottom: 1px solid var(--color-border-subtle);
    }

    .tab-subnav[hidden] {
        display: none;
    }

    .tab-subnav-item {
        padding: 12px 18px 12px 36px;
        font-size: var(--text-sm);
        font-weight: var(--weight-medium);
        color: var(--color-text-secondary);
        cursor: pointer;
        border-left: 3px solid transparent;
        transition: background 0.15s, color 0.15s, border-color 0.15s;
        user-select: none;
    }

    .tab-subnav-item:hover {
        background: var(--tab-hover-bg);
        color: var(--color-text-primary);
    }

    .tab-subnav-item.active {
        background: var(--tab-active-bg);
        color: var(--tab-active-text);
        border-left-color: var(--tab-active-border);
        font-weight: var(--weight-bold);
    }

    /* Non-clickable section header inside the two-level drawer (mirrors
       the desktop .dm-sidebar-group). */
    .tab-subnav-group {
        padding: 10px 18px 3px 28px;
        font-size: var(--text-xs);
        font-weight: var(--weight-bold);
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--color-text-secondary);
        border-top: 1px solid var(--color-border-subtle);
        user-select: none;
        pointer-events: none;
    }

    .tab-subnav-group:first-child {
        border-top: none;
        padding-top: 8px;
    }

    /* ----- Modals: shrink to fit viewport ----- */
    .modal-content,
    .stop-confirm-card {
        max-width: min(92vw, 480px) !important;
        width: auto !important;
        margin: 16px auto;
        max-height: 90vh;
        overflow-y: auto;
    }

    #tagging-modal > div {
        width: min(92vw, 480px) !important;
        max-height: 90vh;
        overflow-y: auto;
    }

    /* ----- Tables: scroll horizontally rather than break layout ----- */
    .dm-content table,
    #home table,
    #my_studies table,
    #admin table {
        display: block;
        overflow-x: auto;
        max-width: 100%;
    }

    /* ----- Tab content: prevent horizontal layout-break ----- */
    .tab-pane {
        overflow-x: hidden;
    }

    /* ----- Login page: stack sidebar (form) above content ----- */
    .auth-container {
        flex-direction: column;
        height: auto;
        min-height: 100vh;
        overflow: visible;
    }

    .auth-sidebar {
        width: 100%;
        border-right: none;
        border-bottom: 1px solid var(--color-border-subtle);
        overflow-y: visible;
    }

    .auth-content {
        padding: 24px 18px;
        overflow-y: visible;
    }

    .auth-form-container {
        padding: 24px 18px;
    }

    /* ----- Home tab + auth content: smaller hero on small screens ----- */
    .hero-title {
        font-size: var(--text-h2);
        margin-bottom: 14px;
    }

    .hero-subtitle {
        font-size: var(--text-body);
        margin-bottom: 24px;
    }

    #home > div {
        padding: 18px 14px !important;
    }

    #home img,
    .auth-content img {
        max-width: 100% !important;
        height: auto;
    }

    /* Header brand can be tightened further on very narrow phones */
}

@media (max-width: 420px) {
    .app-brand {
        font-size: 1rem;
    }

    .auth-header {
        padding: 8px 10px;
    }

    /* Signup page: relax fixed paddings on very narrow phones */
    body > .container > div[style*="max-width: 400px"] {
        padding: 24px 18px !important;
    }
}

/* ===== Define Study modal: date-range control + chart edge handles ===== */
.study-date-input {
    width: 140px;
    padding: 2px 4px;
    font-variant-numeric: tabular-nums;
}

.study-date-step {
    padding: 1px 6px;
    line-height: var(--leading-tight);
    font-size: var(--text-xs);
    cursor: pointer;
}

.study-date-reset {
    padding: 2px 8px;
    cursor: pointer;
}

.study-date-step:disabled,
.study-date-reset:disabled {
    opacity: 0.45;
    cursor: default;
}

/* Draggable window edges over the daily-activities chart. The element is a wide
   invisible hit area; only the centered rule is painted. */
.study-range-handle {
    position: absolute;
    width: 13px;
    margin-left: -6px;
    cursor: ew-resize;
    z-index: 30;
    touch-action: none;
}

.study-range-handle__rule {
    position: absolute;
    left: 6px;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--color-accent);
    opacity: 0.75;
}

.study-range-handle__grip {
    position: absolute;
    left: 2px;
    top: -1px;
    width: 9px;
    height: 9px;
    border-radius: 2px;
    background: var(--color-accent);
}

.study-range-handle:hover .study-range-handle__rule,
.study-daily-chart-wrap.dragging-range .study-range-handle__rule {
    opacity: 1;
    width: 2px;
}

/* Suppress text selection and hover cursors across the page while dragging an edge. */
body.study-range-dragging {
    cursor: ew-resize;
    user-select: none;
}

/* ===== Define Study modal: video coverage / sample mosaic ===== */
.study-set-viz-empty {
    color: var(--color-text-tertiary);
    padding: 12px;
    border: 1px dashed var(--color-border);
    border-radius: 4px;
    background: var(--color-bg-surface);
}

.study-viz__main {
    display: flex;
    align-items: stretch;
    gap: 0;
}

.study-viz__help.meta-tooltip {
    text-decoration: none;
    cursor: help;
    color: var(--color-text-muted);
    margin-left: 5px;
}

.study-viz__help.meta-tooltip:hover {
    color: var(--color-text-secondary);
}

/* Vertical "what is this?" sitting right against the mosaic. */
.study-viz__help--side.meta-tooltip {
    writing-mode: vertical-rl;
    text-orientation: mixed;
    margin-left: 0;
    padding: 0 0 0 1px;
    display: flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    text-decoration: underline dotted var(--color-text-muted);
}

/* Keep the tooltip copy horizontal even though the trigger reads vertically. */
.study-viz__help--side::after {
    writing-mode: horizontal-tb;
    text-orientation: mixed;
}

.study-viz__box {
    display: flex;
    flex: 1 1 auto;
    height: 84px;
    border: 1px solid var(--study-viz-border);
    border-radius: 4px;
    background: var(--study-viz-eligible-bg);
}

.study-viz__col {
    position: relative;
    height: 100%;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--study-viz-eligible-bg);
    border-right: 3px solid var(--color-border-strong);
    box-sizing: border-box;
    text-decoration: none;
    cursor: help;
}

.study-viz__col:last-child {
    border-right: none;
}

.study-viz__col:first-child {
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
}

.study-viz__col:last-child {
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
}

.study-viz__col--outframe {
    background: var(--study-viz-outframe-bg);
}

.study-viz__fill {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--study-viz-included);
    animation: study-viz-pulse 2s ease-in-out infinite;
}

.study-viz__col:first-child .study-viz__fill {
    border-bottom-left-radius: 4px;
}

.study-viz__col:last-child .study-viz__fill {
    border-bottom-right-radius: 4px;
}

@keyframes study-viz-pulse {
    0%, 100% { background: var(--study-viz-included); }
    50% { background: var(--study-viz-included-pulse); }
}

@media (prefers-reduced-motion: reduce) {
    .study-viz__fill { animation: none; }
}

/* Column label sits centred inside the field; the count is in the tooltip. */
.study-viz__collabel-in {
    position: relative;
    z-index: 1;
    padding: 0 2px;
    color: var(--study-viz-label-text);
    white-space: nowrap;
    text-align: center;
    pointer-events: none;
    text-shadow: 0 1px 2px var(--study-viz-label-halo), 0 0 2px var(--study-viz-label-halo);
}

/* Too narrow for horizontal text — rotate the label like a Plotly axis tick. */
.study-viz__col--vlabel .study-viz__collabel-in {
    writing-mode: vertical-rl;
    text-orientation: mixed;
}

.study-viz__col--tinylabel .study-viz__collabel-in {
    transform: scale(0.78);
    transform-origin: center;
}

.study-viz__headline {
    margin-top: 8px;
    color: var(--color-text-primary);
    font-variant-numeric: tabular-nums;
}

.study-viz__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 6px;
    color: var(--color-text-secondary);
}

.study-viz__seeded-note {
    margin-top: 6px;
    color: var(--color-text-tertiary);
    font-style: italic;
}

.study-viz__legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.study-viz__swatch {
    width: 12px;
    height: 12px;
    border-radius: 2px;
    display: inline-block;
    border: 1px solid var(--study-viz-divider);
    box-sizing: border-box;
}

.study-viz__swatch--included { background: var(--study-viz-included); }
.study-viz__swatch--eligible { background: var(--study-viz-eligible-bg); }
.study-viz__swatch--outframe { background: var(--study-viz-outframe-bg); }


/* ============================================================
   Public Mini-Site (landing / about / guide / faq)
   Semantic tokens only — light theme works with no overrides.
   ============================================================ */

/* The global body rule locks the SPA shell to the viewport
   (height:100vh; overflow:hidden; padding:20px). Public pages are ordinary
   scrolling documents, so undo that when a public page is present. */
body:has(.public-page) {
    height: auto;
    overflow: visible;
    padding: 0;
    display: block;
}

.public-page {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--color-bg-primary);
    color: var(--color-text-primary);
}

/* ----- Header ----- */

.public-header {
    position: sticky;
    top: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 14px 28px;
    background: var(--color-bg-surface);
    border-bottom: 1px solid var(--color-border-subtle);
}

.public-wordmark {
    font-family: var(--font-sans);
    font-size: var(--text-h3);
    font-weight: var(--weight-bold);
    color: var(--color-accent);
    text-decoration: none;
    white-space: nowrap;
}

.public-nav {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
}

.public-nav-link {
    color: var(--color-text-secondary);
    text-decoration: none;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    padding: 6px 12px;
    border-radius: 6px;
}

.public-nav-link:hover {
    color: var(--color-text-primary);
    background: var(--color-bg-elevated);
}

.public-nav-link.active {
    color: var(--color-accent);
}

.public-nav-actions {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-left: 14px;
}

/* Anchor-friendly sizing for btn-primary/.btn-discreet used as links. */
.public-cta {
    display: inline-block;
    padding: 9px 18px;
    border-radius: 6px;
    border: none;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    text-decoration: none;
    cursor: pointer;
    text-align: center;
}

.public-nav-toggle {
    display: none;
    background: none;
    border: none;
    color: var(--color-text-primary);
    font-size: var(--text-h3);
    cursor: pointer;
    margin-left: auto;
    padding: 2px 8px;
}

/* ----- Page body ----- */

.public-main {
    flex: 1;
    width: 100%;
    max-width: 1060px;
    margin: 0 auto;
    padding: 30px 28px 70px;
}

.landing-hero {
    text-align: center;
    padding: 40px 0 20px;
}

.landing-hero-img {
    max-width: 420px;
    width: 100%;
    height: auto;
    margin-bottom: 26px;
}

.landing-hero-sub {
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}

.landing-hero-ctas {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 6px;
}

/* ----- Video-mosaic hero (about page) -----
   A grid of opening frames from real corpus videos. The point is the mass and
   the variety, so the cells stay small and the gradient frame ties it to the
   public palette. Regenerate with scripts/make_video_grid_hero.py. */

.hero-mosaic {
    margin: 34px 0 0;
}

.hero-mosaic__frame {
    padding: 3px;
    border-radius: 16px;
    background: var(--fyr-grad);
    line-height: 0;
}

.hero-mosaic img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 13px;
}

/* On a phone the full grid shrinks to visual noise; crop it instead so the
   cells that do show stay readable. */
@media (max-width: 640px) {
    .hero-mosaic img {
        height: 230px;
        object-fit: cover;
    }
}

.landing-section {
    margin-top: 60px;
}

/* Anchor targets (audience cards jump here): keep the heading clear of the
   sticky public header when the browser scrolls to the fragment. */
.landing-section[id] {
    scroll-margin-top: 80px;
}

.landing-section-title {
    color: var(--color-text-heading);
    margin-bottom: 14px;
}

.landing-section-intro {
    color: var(--color-text-secondary);
    max-width: 720px;
    margin-bottom: 26px;
}

/* ----- Feature cards ----- */

.feature-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px;
}

.feature-card {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 10px;
    padding: 22px;
}

.feature-card h3 {
    margin: 0 0 8px;
    color: var(--color-text-primary);
}

.feature-card p {
    margin: 0;
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
}

.feature-card-icon {
    font-size: var(--text-h2);
    color: var(--color-accent);
    margin-bottom: 10px;
    line-height: 1;
}

/* Icon images inside feature-card-icon (about page cards). */
.feature-card-img {
    height: 36px;
    width: auto;
    display: block;
}

/* ----- Public mini-site accent palette -----
   The app is colorful (category ribbons, semantic map); these accents bring a
   taste of that to the public pages without touching the app theme tokens. */

.public-page {
    --fyr-pink: #ec4899;
    --fyr-orange: #f97316;
    --fyr-teal: #0d9488;
    --fyr-violet: #8b5cf6;
    --fyr-grad: linear-gradient(100deg, var(--fyr-pink), var(--fyr-orange) 35%, var(--fyr-teal) 70%, var(--fyr-violet));
}

.hero-title--gradient {
    background: var(--fyr-grad);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* Scroll-reveal: hidden state only applies once JS has signalled it will run
   (html.js-reveal), so the pages work fully without JavaScript. */
.js-reveal .reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.6s ease, transform 0.6s ease;
}

.js-reveal .reveal.is-visible {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .js-reveal .reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* ----- Image / logo placeholders (swapped for real assets later) ----- */

.img-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 220px;
    padding: 20px;
    border: 2px dashed var(--color-border-strong);
    border-radius: 14px;
    background: color-mix(in srgb, var(--color-bg-surface) 88%, var(--fyr-teal));
}

.img-placeholder span {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    max-width: 320px;
}

.img-placeholder--pink { background: color-mix(in srgb, var(--color-bg-surface) 90%, var(--fyr-pink)); }
.img-placeholder--orange { background: color-mix(in srgb, var(--color-bg-surface) 90%, var(--fyr-orange)); }
.img-placeholder--teal { background: color-mix(in srgb, var(--color-bg-surface) 90%, var(--fyr-teal)); }
.img-placeholder--violet { background: color-mix(in srgb, var(--color-bg-surface) 90%, var(--fyr-violet)); }

.img-placeholder--wide {
    min-height: 260px;
}

.logo-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 14px;
    margin-top: 26px;
}

.logo-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 72px;
    padding: 10px;
    border: 2px dashed var(--color-border-subtle);
    border-radius: 10px;
    background: var(--color-bg-surface);
}

.logo-placeholder span {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    text-align: center;
}

/* ----- Story rows (participate page: short chunk + image, alternating) ----- */

.story-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 40px;
    align-items: center;
    margin-bottom: 56px;
}

.story-row--flip .story-row__text {
    order: 2;
}

.story-row--flip .story-row__media {
    order: 1;
}

.story-row__text h2 {
    margin: 0 0 10px;
    color: var(--color-text-primary);
}

.story-row__text .prose {
    color: var(--color-text-secondary);
}

.story-row__eyebrow {
    display: inline-block;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 4px 12px;
    border-radius: 999px;
    margin-bottom: 12px;
    color: #fff;
}

.story-row__media {
    position: relative;
}

.story-row__media img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 14px;
}

/* Transparency label overlaid on AI-generated imagery. */
.ai-image-tag {
    position: absolute;
    top: 10px;
    right: 10px;
    font-size: var(--text-xs);
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    pointer-events: none;
}

.story-row__eyebrow--pink { background: var(--fyr-pink); }
.story-row__eyebrow--orange { background: var(--fyr-orange); }
.story-row__eyebrow--teal { background: var(--fyr-teal); }
.story-row__eyebrow--violet { background: var(--fyr-violet); }

@media (max-width: 760px) {
    .story-row {
        grid-template-columns: 1fr;
        gap: 18px;
        margin-bottom: 44px;
    }

    .story-row--flip .story-row__text {
        order: 1;
    }

    .story-row--flip .story-row__media {
        order: 2;
    }
}

/* ----- Audience cards (landing "What would you like to do?") ----- */

.audience-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 18px;
}

.audience-card {
    display: block;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 10px;
    padding: 22px;
    color: inherit;
    text-decoration: none;
    transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.audience-card:hover {
    border-color: var(--color-accent);
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
    text-decoration: none;
}

.audience-card h3 {
    margin: 0 0 8px;
    color: var(--color-text-primary);
}

.audience-card p {
    margin: 0;
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
}

.audience-card__eyebrow {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-accent);
    margin-bottom: 10px;
}

.audience-card__cta {
    margin-top: 14px;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--color-accent);
}

/* Per-card accent: colored top bar, matching eyebrow/CTA, tinted hover. */
.audience-card--pink,
.audience-card--teal,
.audience-card--violet {
    border-top: 4px solid var(--color-accent);
}

.audience-card--pink { border-top-color: var(--fyr-pink); }
.audience-card--teal { border-top-color: var(--fyr-teal); }
.audience-card--violet { border-top-color: var(--fyr-violet); }

.audience-card--pink .audience-card__eyebrow,
.audience-card--pink .audience-card__cta { color: var(--fyr-pink); }
.audience-card--teal .audience-card__eyebrow,
.audience-card--teal .audience-card__cta { color: var(--fyr-teal); }
.audience-card--violet .audience-card__eyebrow,
.audience-card--violet .audience-card__cta { color: var(--fyr-violet); }

.audience-card--pink:hover { border-color: var(--fyr-pink); }
.audience-card--teal:hover { border-color: var(--fyr-teal); }
.audience-card--violet:hover { border-color: var(--fyr-violet); }

/* Colored feature-card variants (about page: research questions + streams). */
.feature-card--pink { border-top: 4px solid var(--fyr-pink); }
.feature-card--orange { border-top: 4px solid var(--fyr-orange); }
.feature-card--teal { border-top: 4px solid var(--fyr-teal); }
.feature-card--violet { border-top: 4px solid var(--fyr-violet); }

/* ----- Feature tour rows (text + screenshot) ----- */

.feature-row {
    display: grid;
    grid-template-columns: minmax(240px, 2fr) 3fr;
    gap: 30px;
    align-items: center;
    margin-top: 42px;
}

.feature-row:nth-child(odd) .feature-row-text {
    order: 2;
}

.feature-row-text h3 {
    margin: 0 0 8px;
    color: var(--color-text-primary);
}

.feature-row-text .prose {
    color: var(--color-text-secondary);
    margin: 0;
}

.screenshot-frame {
    margin: 0;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    padding: 8px;
    box-shadow: var(--shadow-md);
}

.screenshot-frame img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 6px;
}

.screenshot-frame figcaption {
    padding: 8px 6px 2px;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    text-align: center;
}

/* When a screenshot asset is missing (not yet captured), hide the broken
   image and show a tasteful placeholder instead of a broken-image icon. */
.screenshot-frame--pending img {
    display: none;
}

.screenshot-frame--pending::before {
    content: "Screenshot coming soon";
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 16 / 10;
    border-radius: 6px;
    background: var(--color-bg-inset);
    border: 1px dashed var(--color-border);
    color: var(--color-text-faint);
    font-size: var(--text-sm);
}

/* ----- CTA band ----- */

.landing-cta-band {
    text-align: center;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 12px;
    padding: 40px 28px;
}

.participate-cta-note {
    color: var(--color-text-muted);
    margin-top: 12px;
}

.landing-cta-band h2 {
    margin-top: 0;
    color: var(--color-text-heading);
}

.landing-cta-band .prose {
    color: var(--color-text-secondary);
    max-width: 620px;
    margin: 0 auto 22px;
}

/* ----- Step list (guide) ----- */

.step-list {
    counter-reset: step;
    list-style: none;
    padding: 0;
    margin: 0;
    max-width: 760px;
}

.step-list li {
    counter-increment: step;
    position: relative;
    padding: 0 0 22px 52px;
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
}

.step-list li strong {
    color: var(--color-text-primary);
}

.step-list li::before {
    content: counter(step);
    position: absolute;
    left: 0;
    top: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    color: var(--color-accent);
    font-weight: var(--weight-bold);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ----- Guide tab list + tips ----- */

.guide-tab-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 16px;
}

.guide-tab-item {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 10px;
    padding: 18px 20px;
}

.guide-tab-item h3 {
    margin: 0 0 6px;
    color: var(--color-text-primary);
}

.guide-tab-item p {
    margin: 0;
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
}

.guide-tips {
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
    padding-left: 22px;
    margin: 0 0 22px;
}

.guide-tips li {
    margin-bottom: 8px;
}

.guide-tips strong {
    color: var(--color-text-primary);
}

/* ----- Team cards (about) ----- */

.team-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 14px;
}

.team-card {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 10px;
    padding: 16px 18px;
}

.team-card-photo {
    width: 84px;
    height: 84px;
    object-fit: cover;
    border-radius: 50%;
    margin-bottom: 12px;
    border: 1px solid var(--color-border-subtle);
}

.team-card-bio {
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
    margin: 8px 0 0;
}

.team-card-name {
    font-weight: var(--weight-semibold);
    color: var(--color-text-primary);
}

.team-card-role {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    margin-top: 3px;
}

.team-card-inst {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    margin-top: 6px;
}

/* ----- FAQ accordion (native details/summary) ----- */

.faq-accordion {
    max-width: 760px;
    margin-left: auto;
    margin-right: auto;
}

.faq-accordion details {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 10px;
    margin-bottom: 12px;
    overflow: hidden;
}

.faq-accordion summary {
    cursor: pointer;
    padding: 16px 20px;
    font-weight: var(--weight-semibold);
    color: var(--color-text-primary);
    list-style: none;
    position: relative;
    padding-right: 44px;
}

.faq-accordion summary::-webkit-details-marker {
    display: none;
}

.faq-accordion summary::after {
    content: "+";
    position: absolute;
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-accent);
    font-size: var(--text-h3);
    line-height: 1;
}

.faq-accordion details[open] summary::after {
    content: "−";
}

.faq-accordion details p {
    margin: 0;
    padding: 0 20px 18px;
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
}

/* ----- Auth pages (login / signup) on the public layout ----- */

.auth-page-card {
    max-width: 420px;
    margin: 40px auto 0;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    box-shadow: var(--shadow-md);
    overflow: hidden;
}

.auth-page-card .auth-form-container {
    border-bottom: none;
    padding: 30px 28px;
}

.auth-card-title {
    margin: 0 0 20px;
    color: var(--color-text-primary);
    text-align: center;
}

.auth-card-footer {
    text-align: center;
    margin-top: 15px;
}

/* ----- Landing: hero image + login card above the main title ----- */

.landing-login-hero {
    display: grid;
    grid-template-columns: 1.7fr 1fr;
    align-items: center;
    gap: 36px;
    padding-top: 24px;
}

.landing-login-hero__media {
    margin: 0;
}

.landing-login-hero__media img {
    display: block;
    width: 100%;
    height: auto;
}

.landing-login-hero__card {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    box-shadow: var(--shadow-md);
}

.landing-login-hero__card.auth-form-container {
    border-bottom: 1px solid var(--color-border);
    padding: 26px 24px;
}

@media (max-width: 860px) {
    .landing-login-hero {
        grid-template-columns: 1fr;
        gap: 24px;
        padding-top: 10px;
    }

    .landing-login-hero__card {
        max-width: 420px;
        width: 100%;
        margin: 0 auto;
    }
}

/* ----- Footer ----- */

.public-footer {
    border-top: 1px solid var(--color-border-subtle);
    background: var(--color-bg-surface);
    padding: 36px 28px 22px;
    margin-top: 40px;
}

.public-footer-inner {
    max-width: 1060px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    gap: 30px;
}

.public-footer-title {
    font-weight: var(--weight-semibold);
    color: var(--color-text-primary);
    margin-bottom: 10px;
}

.public-footer-col p {
    color: var(--color-text-muted);
    line-height: var(--leading-relaxed);
    margin: 0 0 10px;
}

.public-footer-link {
    display: block;
    color: var(--color-text-secondary);
    text-decoration: none;
    font-size: var(--text-sm);
    margin-bottom: 7px;
}

.public-footer-link:hover {
    color: var(--color-accent);
}

.public-footer-legal {
    max-width: 1060px;
    margin: 26px auto 0;
    padding-top: 16px;
    border-top: 1px solid var(--color-border-subtle);
    color: var(--color-text-faint);
    text-align: center;
}

/* ----- Public mini-site: responsive ----- */

@media (max-width: 860px) {
    .public-nav-toggle {
        display: block;
    }

    .public-nav {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: stretch;
        background: var(--color-bg-surface);
        border-bottom: 1px solid var(--color-border-subtle);
        padding: 10px 16px 16px;
        gap: 4px;
    }

    .public-nav.open {
        display: flex;
    }

    .public-nav-actions {
        margin-left: 0;
        margin-top: 8px;
        justify-content: flex-start;
        flex-wrap: wrap;
    }

    .feature-row,
    .feature-row:nth-child(odd) {
        grid-template-columns: 1fr;
        gap: 14px;
    }

    .feature-row:nth-child(odd) .feature-row-text {
        order: 0;
    }

    .public-footer-inner {
        grid-template-columns: 1fr;
        gap: 22px;
    }

    .landing-hero {
        padding-top: 20px;
    }

    .landing-section {
        margin-top: 44px;
    }

    .public-main {
        padding: 20px 18px 50px;
    }
}


/* ============================================================
   Public Mini-Site — researcher narrative components
   (kicker, pull-quote, comparison, can/can't)
   Semantic tokens only.
   ============================================================ */

.kicker {
    display: inline-block;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide, 0.08em);
    text-transform: uppercase;
    color: var(--color-accent);
    margin-bottom: 14px;
}

/* Standalone researcher CTA button between hero and pipeline */
.researcher-cta-inline {
    text-align: center;
    margin-top: 44px;
}

/* "What is data donation?" link under the hero subtitle */
.hero-donation-link {
    text-align: center;
    margin: 4px 0 0;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
}

/* Wider hero lead for the problem statement */
.landing-hero-lead {
    max-width: 720px;
    margin: 18px auto 0;
    font-size: var(--text-body);
    line-height: var(--leading-relaxed);
    color: var(--color-text-secondary);
    text-align: center;
}

/* Big pull-quote for the thesis */
.pullquote {
    max-width: 820px;
    margin: 0 auto;
    text-align: center;
}

.pullquote blockquote {
    margin: 0 0 18px;
    font-size: var(--text-h2);
    line-height: var(--leading-tight);
    font-weight: var(--weight-semibold);
    color: var(--color-text-heading);
}

.pullquote .pullquote-answer {
    font-size: var(--text-body);
    line-height: var(--leading-relaxed);
    color: var(--color-text-secondary);
    margin: 0 auto;
    max-width: 640px;
}

.pullquote .pullquote-answer strong {
    color: var(--color-text-primary);
}

/* Two-column comparison (donated feeds vs platform libraries) */
.compare-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
    margin-top: 24px;
}

.compare-col {
    border-radius: 12px;
    padding: 24px;
    border: 1px solid var(--color-border-subtle);
    background: var(--color-bg-surface);
}

.compare-col--accent {
    border-color: var(--color-accent);
    background: var(--color-bg-elevated);
}

.compare-col h3 {
    margin: 0 0 4px;
    color: var(--color-text-primary);
}

.compare-col .compare-sub {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    margin: 0 0 16px;
}

.compare-col ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.compare-col li {
    position: relative;
    padding: 6px 0 6px 22px;
    color: var(--color-text-secondary);
    line-height: var(--leading-normal);
}

.compare-col li::before {
    content: "—";
    position: absolute;
    left: 0;
    color: var(--color-text-faint);
}

.compare-col--accent li::before {
    content: "→";
    color: var(--color-accent);
}

/* Can / can't tell us cards */
.canuse-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
    margin-top: 24px;
}

.canuse-card {
    border-radius: 12px;
    padding: 24px;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
}

.canuse-head {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: var(--weight-semibold);
    margin-bottom: 14px;
    color: var(--color-text-primary);
}

.canuse-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    line-height: 1;
}

.canuse-badge--yes {
    background: color-mix(in srgb, var(--color-success) 20%, transparent);
    color: var(--color-success);
}

.canuse-badge--no {
    background: color-mix(in srgb, var(--color-danger) 20%, transparent);
    color: var(--color-danger);
}

.canuse-card ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.canuse-card li {
    position: relative;
    padding: 6px 0 6px 24px;
    color: var(--color-text-secondary);
    line-height: var(--leading-normal);
}

.canuse-card--yes li::before {
    content: "✓";
    position: absolute;
    left: 0;
    color: var(--color-success);
    font-weight: var(--weight-bold);
}

.canuse-card--no li::before {
    content: "✕";
    position: absolute;
    left: 0;
    color: var(--color-danger);
    font-weight: var(--weight-bold);
}

/* Burden cards punchline */
.landing-punchline {
    margin-top: 22px;
    text-align: center;
    font-size: var(--text-body);
    font-weight: var(--weight-semibold);
    color: var(--color-text-primary);
}

/* Infrastructure note strip */
.infra-note {
    margin-top: 26px;
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
}

.infra-chip {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 999px;
    padding: 8px 16px;
}

.infra-chip strong {
    color: var(--color-text-primary);
}

@media (max-width: 860px) {
    .compare-grid,
    .canuse-grid {
        grid-template-columns: 1fr;
    }

    .pullquote blockquote {
        font-size: var(--text-h3);
    }
}


/* ============================================================
   "See it in action" — the five pipeline steps (Ingest…Share)
   as a tabbed stepper. A row of numbered step-pills is both the
   pipeline summary and the tab navigation; only the selected
   stage's panel is shown below. CSS-only tabs: hidden radio
   inputs drive pill state and panel visibility, so the component
   needs no JS on either the public landing page or the app shell.
   ============================================================ */

.see-tabs {
    margin-top: 22px;
}

/* Visually hidden but focusable, so keyboard users can arrow
   between steps via the radio group. */
.see-tabs__input {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.see-tabs__pills {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 14px;
}

.see-tab-pill {
    position: relative;
    display: block;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: 12px;
    padding: 22px 16px;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.see-tab-pill:hover {
    border-color: var(--color-border);
}

.see-tab-pill__num {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--color-accent);
    color: var(--btn-primary-text, #fff);
    font-weight: var(--weight-bold);
    margin-bottom: 12px;
}

.see-tab-pill__title {
    display: block;
    margin-bottom: 6px;
    color: var(--color-text-primary);
    font-size: var(--text-body);
}

.see-tab-pill__desc {
    display: block;
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    line-height: var(--leading-normal);
}

/* Connector arrows between pills (desktop only) */
.see-tab-pill:not(:last-child)::after {
    content: "→";
    position: absolute;
    right: -12px;
    top: 34px;
    transform: translateX(50%);
    color: var(--color-text-faint);
    z-index: 1;
}

/* Selected pill */
#see-tab-ingest:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-ingest"],
#see-tab-enrich:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-enrich"],
#see-tab-annotate:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-annotate"],
#see-tab-analyse:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-analyse"],
#see-tab-share:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-share"] {
    border-color: var(--color-accent);
    background: var(--color-bg-elevated, var(--color-bg-surface));
}

/* Forward keyboard focus from the hidden radio to its pill */
#see-tab-ingest:focus-visible ~ .see-tabs__pills .see-tab-pill[for="see-tab-ingest"],
#see-tab-enrich:focus-visible ~ .see-tabs__pills .see-tab-pill[for="see-tab-enrich"],
#see-tab-annotate:focus-visible ~ .see-tabs__pills .see-tab-pill[for="see-tab-annotate"],
#see-tab-analyse:focus-visible ~ .see-tabs__pills .see-tab-pill[for="see-tab-analyse"],
#see-tab-share:focus-visible ~ .see-tabs__pills .see-tab-pill[for="see-tab-share"] {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Panels: only the selected stage's content is shown */
.see-panel {
    display: none;
    margin-top: 26px;
}

#see-tab-ingest:checked ~ .see-panels #see-panel-ingest,
#see-tab-enrich:checked ~ .see-panels #see-panel-enrich,
#see-tab-annotate:checked ~ .see-panels #see-panel-annotate,
#see-tab-analyse:checked ~ .see-panels #see-panel-analyse,
#see-tab-share:checked ~ .see-panels #see-panel-share {
    display: block;
}

.see-panel__lead {
    color: var(--color-text-secondary);
    line-height: var(--leading-relaxed);
    margin: 0 0 8px;
    max-width: 760px;
}

/* Reuse .feature-row inside a panel, but keep the image always on the
   right (cancel the alternating order used by the flat tour) and tighten
   the vertical rhythm. */
.see-panel .feature-row {
    margin-top: 20px;
    align-items: start;
}

.see-panel .feature-row .feature-row-text {
    order: 0;
}

.see-panel .feature-row .feature-row-text .prose {
    margin: 0;
}

/* Small screens: stacked pills break the tab metaphor, so the stepper
   degrades into a linear walkthrough — every panel is shown, interleaved
   directly after its own pill, and the reader steps forward by scrolling.
   The wrappers are flattened with display:contents so pills and panels
   become siblings that can interleave via flex order. */
@media (max-width: 860px) {
    .see-tabs {
        display: flex;
        flex-direction: column;
        gap: 26px;
    }

    .see-tabs__pills,
    .see-panels {
        display: contents;
    }

    .see-tab-pill {
        cursor: default;
        pointer-events: none;
    }

    .see-tab-pill:not(:last-child)::after {
        content: none;
    }

    .see-tab-pill[for="see-tab-ingest"]   { order: 1; }
    #see-panel-ingest                     { order: 2; }
    .see-tab-pill[for="see-tab-enrich"]   { order: 3; }
    #see-panel-enrich                     { order: 4; }
    .see-tab-pill[for="see-tab-annotate"] { order: 5; }
    #see-panel-annotate                   { order: 6; }
    .see-tab-pill[for="see-tab-analyse"]  { order: 7; }
    #see-panel-analyse                    { order: 8; }
    .see-tab-pill[for="see-tab-share"]    { order: 9; }
    #see-panel-share                      { order: 10; }

    .see-panel {
        display: block;
        margin-top: 0;
    }

    /* No selection on mobile — neutralize the selected/focus pill state */
    #see-tab-ingest:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-ingest"],
    #see-tab-enrich:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-enrich"],
    #see-tab-annotate:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-annotate"],
    #see-tab-analyse:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-analyse"],
    #see-tab-share:checked ~ .see-tabs__pills .see-tab-pill[for="see-tab-share"] {
        border-color: var(--color-border-subtle);
        background: var(--color-bg-surface);
        outline: none;
    }
}


/* ============================================================
   Sessions tab — session list, strip, episode inspector
   ============================================================ */

.sess-row {
    padding: 8px 14px;
    border-bottom: 1px solid var(--color-border-subtle);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.sess-row:hover { background: var(--color-bg-elevated); }

.sess-row.active {
    background: var(--color-bg-elevated);
    border-left: 3px solid var(--color-accent);
    padding-left: 11px;
}

.sess-row-top {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
}

.sess-row-metrics {
    display: flex;
    gap: 12px;
    align-items: center;
    color: var(--color-text-tertiary);
}

/* Thin horizontal coverage bar inside a list row */
.sess-cov-bar {
    width: 64px;
    height: 6px;
    border-radius: 3px;
    background: var(--color-border-subtle);
    overflow: hidden;
    display: inline-block;
    vertical-align: middle;
}

.sess-cov-fill {
    display: block;
    height: 100%;
    background: var(--color-accent);
}

/* Episode selector chips */
.sess-chip {
    padding: 5px 10px;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    background: var(--color-bg-surface);
    cursor: pointer;
    display: inline-flex;
    flex-direction: column;
    gap: 2px;
}

.sess-chip:hover { background: var(--color-bg-elevated); }

.sess-chip.active {
    border-color: var(--color-accent);
    background: var(--color-bg-elevated);
}

.sess-badge {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 3px;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-subtle);
    color: var(--color-text-secondary);
}

/* A run whose videos are all by one creator — the donor sat on one account
   rather than being served a topic assembled across creators. */
.sess-solo-creator {
    color: var(--color-warning);
}

/* Off-theme videos a binge tolerated — never hidden, so a long binge cannot
   present itself as an unbroken run. */
.sess-skipped {
    color: var(--color-text-muted);
}

/* The within-binge trend line, on its own row under the binge's metrics. */
.sess-trend {
    display: block;
    margin-top: 3px;
    color: var(--color-text-muted);
}

/* Horizontally-scrollable row of episode member cards */
.sess-cards-row {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    padding: 6px 2px 10px 2px;
}

.sess-card {
    flex: 0 0 190px;
    width: 190px;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background: var(--color-bg-surface);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.sess-card.highlight { border-color: var(--color-accent); }

.sess-card-media {
    position: relative;
    width: 100%;
    height: 280px;
    background: var(--color-bg-elevated);
    display: flex;
    align-items: center;
    justify-content: center;
}

.sess-card-media video {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: var(--color-bg-elevated);
}

.sess-card-play {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--color-text-secondary);
    background: transparent;
    border: none;
}

.sess-card-play span {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--shadow-sm);
}

.sess-card-meta {
    padding: 7px 9px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.sess-card-story {
    color: var(--color-text-tertiary);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Full play-sequence table rows */
.sess-play-row { border-bottom: 1px solid var(--color-border-subtle); }
.sess-play-row td { padding: 3px 8px; vertical-align: top; }
.sess-play-row.in-episode { background: var(--color-bg-elevated); }


/* Session list as a real table: sticky always-visible header, sortable
   columns, row selection mirroring the old .sess-row states. */
.sess-table {
    width: 100%;
    border-collapse: collapse;
}

.sess-table th {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--table-header-bg);
    color: var(--color-text-secondary);
    text-align: left;
    padding: 6px 10px;
    border-bottom: 1px solid var(--color-border);
    white-space: nowrap;
    user-select: none;
}

.sess-table th.sortable { cursor: pointer; }
.sess-table th.sortable:hover { color: var(--color-text-primary); }
.sess-table th.sorted { color: var(--color-text-primary); }

.sess-table td {
    padding: 6px 10px;
    border-bottom: 1px solid var(--color-border-subtle);
    vertical-align: middle;
}

.sess-table tbody tr { cursor: pointer; }
.sess-table tbody tr:hover { background: var(--color-bg-elevated); }

.sess-table tbody tr.active {
    background: var(--color-bg-elevated);
    box-shadow: inset 3px 0 0 var(--color-accent);
}

/* Collapsible range-filter panel above the session table */
.sess-filters {
    border-bottom: 1px solid var(--color-border-subtle);
    background: var(--color-bg-elevated);
}

.sess-filters-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 5px 14px 5px 8px;
}

/* flex:1 + text-align:left — the whole header strip left of "Clear" is the
   toggle's hit area, so the label and the empty space beside it collapse the
   panel too, not just the caret glyph. */
.sess-filters-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
    padding: 4px 6px;
    background: none;
    border: none;
    text-align: left;
    color: var(--color-text-secondary);
    font-family: var(--font-sans);
    cursor: pointer;
}

.sess-filters-toggle:hover { color: var(--color-text-primary); }

.sess-filters-toggle:hover .sess-filters-caret { color: var(--color-text-primary); }

/* Sized above the button's own text-xs: at the label's size the glyph reads
   as punctuation rather than as the control it is. */
.sess-filters-caret {
    display: inline-block;
    width: 14px;
    font-size: var(--text-sm);
    line-height: 1;
    color: var(--color-text-tertiary);
}

.sess-filters-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 18px;
    padding: 2px 14px 10px;
}

.sess-filter-row { min-width: 0; }

.sess-filter-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 1px;
}

.sess-filter-label { color: var(--color-text-tertiary); }

.sess-filter-val {
    color: var(--color-text-muted);
    white-space: nowrap;
}

.sess-filter-val.is-active {
    color: var(--color-accent);
    font-weight: var(--weight-medium);
}

/* Dual-handle slider: two stacked native range inputs over one shared track.
   The inputs are transparent (track hidden) and click-through except for
   their thumbs; the visible track + selected-range fill are separate divs. */
.sess-dual-range {
    position: relative;
    height: 18px;
}

.sess-dual-track,
.sess-dual-fill {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    height: 4px;
    border-radius: 2px;
    pointer-events: none;
}

.sess-dual-track {
    left: 0;
    right: 0;
    background: var(--color-border);
}

.sess-dual-fill { background: var(--color-accent); }

.sess-dual-range input[type="range"] {
    position: absolute;
    inset: 0;
    width: 100%;
    margin: 0;
    background: none;
    -webkit-appearance: none;
    appearance: none;
    pointer-events: none;
}

.sess-dual-range input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    pointer-events: auto;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--color-text-secondary);
    border: 2px solid var(--color-bg-elevated);
    box-shadow: 0 0 0 1px var(--color-border);
    cursor: ew-resize;
}

.sess-dual-range input[type="range"]::-moz-range-thumb {
    pointer-events: auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-text-secondary);
    border: 2px solid var(--color-bg-elevated);
    box-shadow: 0 0 0 1px var(--color-border);
    cursor: ew-resize;
}

.sess-dual-range input[type="range"]::-webkit-slider-thumb:hover,
.sess-dual-range input[type="range"]:focus::-webkit-slider-thumb {
    background: var(--color-accent);
}

.sess-dual-range input[type="range"]::-moz-range-thumb:hover,
.sess-dual-range input[type="range"]:focus::-moz-range-thumb {
    background: var(--color-accent);
}

.sess-dual-range input[type="range"]::-moz-range-track { background: none; }

/* Free-text session search: lives in the filter panel header area, outside
   the rebuildable slider grid. */
.sess-search-wrap { padding: 0 14px 8px; }

.sess-search {
    width: 100%;
    padding: 5px 9px;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    background: var(--color-bg-primary);
    color: var(--color-text-primary);
    font-family: var(--font-sans);
}

.sess-search::placeholder { color: var(--color-text-muted); }

.sess-search:focus {
    outline: none;
    border-color: var(--color-accent);
}

.sess-search:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* The "session max of variable" filter row's picker + binges-only knob */
.sess-varmax-controls {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 2px 0 4px;
}

.sess-varmax-select {
    flex: 1;
    min-width: 0;
    padding: 3px 6px;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    background: var(--color-bg-primary);
    color: var(--color-text-primary);
    font-family: var(--font-sans);
}

.sess-varmax-scope {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--color-text-tertiary);
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
}

.sess-varmax-scope input { accent-color: var(--color-accent); cursor: pointer; }

.sess-varmax-scope:has(input:disabled) {
    opacity: 0.5;
    cursor: not-allowed;
}

.sess-varmax-scope:has(input:checked) { color: var(--color-accent); }

/* Binge card + its collapsible min/max panel stack in one column */
.sess-seq-wrap {
    display: flex;
    flex-direction: column;
}

.sess-seq-wrap .sess-chip { width: 100%; }

/* The "▸ (more info)" toggle inside a card / the detail header */
.sess-more-toggle {
    color: var(--color-text-muted);
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
}

.sess-more-toggle:hover { color: var(--color-text-secondary); }

.sess-more-caret { display: inline-block; }

/* Collapsed-by-default per-variable min/max list (label + range columns) */
.sess-minmax {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 1px 10px;
    padding: 6px 10px 8px;
    border: 1px solid var(--color-border-subtle);
    border-top: none;
    border-radius: 0 0 4px 4px;
    background: var(--color-bg-elevated);
    color: var(--color-text-tertiary);
}

.sess-minmax-label { color: var(--color-text-muted); }

/* Clickable variable names inside the min/max panels — they toggle the
   session line plot above the strip. */
.sess-varplot-link { cursor: pointer; }

.sess-varplot-link:hover {
    color: var(--color-text-secondary);
    text-decoration: underline;
}

.sess-varplot-link.is-plotted { color: var(--color-accent); }

/* The per-variable line plot above the session strip */
.sess-varplot {
    padding: 4px 0 2px;
    border-bottom: 1px dashed var(--color-border-subtle);
    margin-bottom: 4px;
}

.sess-varplot-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    margin-bottom: 2px;
}

.sess-varplot-close { padding: 0 6px; line-height: 1.2; }

.sess-minmax-title {
    color: var(--color-text-secondary);
    font-weight: var(--weight-medium);
    padding-bottom: 2px;
}

/* Pagination footer under the session table */
.sess-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 14px;
    border-top: 1px solid var(--color-border-subtle);
}


/* Low-entropy sequence chips: dashed border mirrors the dashed strip bands. */
.sess-chip--seq { border-style: dashed; }
.sess-chip--seq.active {
    border-color: var(--color-text-secondary);
    border-style: dashed;
}


/* Sequence selector entries (stacked column of binge / low-entropy cards)
   + the shared single-video player pane. */
.sess-seq-entry {
    width: 100%;
    text-align: left;
    align-items: flex-start;
}

.sess-player-pane {
    border: 1px solid var(--color-border-subtle);
    border-radius: 6px;
    background: var(--color-bg-surface);
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.sess-player-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
}

.sess-player-nav {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.sess-player-media {
    height: 420px;
    background: var(--color-bg-elevated);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.sess-player-media video {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: var(--color-bg-elevated);
}

.sess-player-meta {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.sess-meta-row {
    display: flex;
    gap: 10px;
    align-items: baseline;
}

.sess-meta-label {
    flex: 0 0 90px;
    color: var(--color-text-tertiary);
}


/* Context steps in the sequence player: unmistakably NOT part of the sequence. */
.sess-player-pane.is-context {
    border-style: dashed;
    border-color: var(--color-warning);
}

.sess-context-banner {
    padding: 6px 10px;
    border: 1px dashed var(--color-warning);
    border-radius: 4px;
    color: var(--color-warning);
    background: var(--color-bg-elevated);
}

/* Off-theme steps: plays inside the sequence's span that the detector
   skipped — shown while stepping, but flagged as not part of it. Same idea
   as the context treatment, deliberately distinct (dotted, info colour). */
.sess-player-pane.is-offtheme {
    border-style: dotted;
    border-color: var(--color-info);
}

.sess-offtheme-banner {
    padding: 6px 10px;
    border: 1px dotted var(--color-info);
    border-radius: 4px;
    color: var(--color-info);
    background: var(--color-bg-elevated);
}


/* ============================================================
   Semantic Space
   ============================================================ */

/* ── Disclosure link (collection-trajectory controls) ── */
.ss-disclosure {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: transparent;
    border: none;
    padding: 2px 0;
    color: var(--color-accent);
    font-family: var(--font-sans);
    cursor: pointer;
}

.ss-disclosure:hover {
    text-decoration: underline;
}

.ss-disclosure-caret {
    display: inline-block;
    transition: transform 0.15s ease;
}

.ss-disclosure[aria-expanded="true"] .ss-disclosure-caret {
    transform: rotate(90deg);
}

/* The disclosed row's layout lives here rather than inline: an inline
   `display` wins over the `hidden` attribute, so the row would stay visible
   while collapsed. */
.ss-traj-controls {
    display: flex;
    gap: 18px;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--color-border-subtle);
}

.ss-traj-controls[hidden] {
    display: none;
}


/* ── Focus-niche picker (search + sort combobox) ── */
.ss-niche-picker {
    position: relative;
    display: inline-block;
}

.ss-niche-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-width: 230px;
    max-width: 330px;
    padding: 5px 8px;
    background: var(--select-bg);
    border: 1px solid var(--select-border);
    border-radius: 3px;
    color: var(--select-text);
    font-family: var(--font-sans);
    text-align: left;
    cursor: pointer;
}

.ss-niche-trigger:hover {
    border-color: var(--color-accent);
}

#ss-niche-trigger-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ss-niche-caret {
    color: var(--color-text-tertiary);
    flex: 0 0 auto;
}

/* Clearing the focus is a one-click affordance rather than "reopen the list
   and pick the placeholder" — hidden entirely while nothing is focused. */
.ss-niche-clear {
    width: 22px;
    height: 22px;
    line-height: 1;
    padding: 0;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: 3px;
    color: var(--color-text-tertiary);
    font-size: var(--text-body);
    cursor: pointer;
}

.ss-niche-clear:hover {
    color: var(--color-text-primary);
    border-color: var(--color-accent);
}

.ss-niche-panel {
    position: absolute;
    z-index: 900;
    top: calc(100% + 4px);
    left: 0;
    width: 360px;
    max-width: 80vw;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 4px;
    box-shadow: var(--shadow-md);
    overflow: hidden;
}

.ss-niche-panel[hidden] {
    display: none;
}

.ss-niche-panel-head {
    display: flex;
    gap: 6px;
    align-items: center;
    padding: 8px;
    border-bottom: 1px solid var(--color-border-subtle);
    background: var(--color-bg-elevated);
}

.ss-niche-search {
    flex: 1 1 auto;
    min-width: 0;
    padding: 5px 8px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-radius: 3px;
    color: var(--input-text);
    font-family: var(--font-sans);
}

.ss-niche-search::placeholder {
    color: var(--color-text-muted);
}

/* Tall enough that the list reads as a list rather than a top-N preview. A
   fixed 320px showed ~10 of several hundred niches, and macOS overlay
   scrollbars paint nothing until you already scroll — so the remainder was
   invisible AND unadvertised. The viewport-relative height plus the count line
   below fix both halves of that. */
.ss-niche-list {
    max-height: min(52vh, 480px);
    overflow-y: auto;
}

/* Says how many niches are in the list and, when it overflows, that there are
   more below — the affordance the hidden scrollbar does not provide. */
.ss-niche-count {
    padding: 5px 10px;
    border-top: 1px solid var(--color-border-subtle);
    background: var(--color-bg-elevated);
    color: var(--color-text-muted);
}

.ss-niche-option {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    padding: 5px 10px;
    cursor: pointer;
    color: var(--color-text-primary);
}

.ss-niche-option:hover,
.ss-niche-option.is-active {
    background: var(--table-row-hover);
}

.ss-niche-option.is-selected {
    color: var(--color-accent);
}

.ss-niche-option-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ss-niche-option-meta {
    flex: 0 0 auto;
    color: var(--color-text-tertiary);
    white-space: nowrap;
}

.ss-niche-empty {
    padding: 10px;
    color: var(--color-text-muted);
}

/* The map's click dialog offers three actions where the shared drill-down card
   was built for two, so it needs the extra width to keep them on one row. */
.ss-point-dialog-card {
    max-width: 580px;
}


/* Each measured neighbour in the detail bar is a control, not just a name:
   clicking one offers the same two moves as clicking a dot on the map. */
.ss-niche-link {
    padding: 0;
    background: none;
    border: none;
    font: inherit;
    color: var(--color-accent);
    cursor: pointer;
}

.ss-niche-link:hover,
.ss-niche-link:focus-visible {
    text-decoration: underline;
}


/* ── "Show me where they are" pulse control, beside Closest niches ── */
.ss-flash-btn {
    margin-left: 4px;
    padding: 0 5px;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: 3px;
    color: var(--color-text-tertiary);
    line-height: 1.5;
    cursor: pointer;
}

.ss-flash-btn:hover {
    color: var(--color-accent);
    border-color: var(--color-accent);
}
