:root {
    /* ===== Primitive Tokens (from React app color system) ===== */

    --black-10: rgba(0, 0, 0, 0.1);
    --black-20: rgba(0, 0, 0, 0.2);
    --black-30: rgba(0, 0, 0, 0.3);
    --black-40: rgba(0, 0, 0, 0.4);
    --black-50: rgba(0, 0, 0, 0.5);
    --black-60: rgba(0, 0, 0, 0.6);
    --black-70: rgba(0, 0, 0, 0.7);
    --black-80: rgba(0, 0, 0, 0.8);
    --black-90: rgba(0, 0, 0, 0.9);
    --black-100: rgba(0, 0, 0, 1);

    --white-10: rgba(255, 255, 255, 0.1);
    --white-20: rgba(255, 255, 255, 0.2);
    --white-30: rgba(255, 255, 255, 0.3);
    --white-40: rgba(255, 255, 255, 0.4);
    --white-50: rgba(255, 255, 255, 0.5);
    --white-60: rgba(255, 255, 255, 0.6);
    --white-70: rgba(255, 255, 255, 0.7);
    --white-80: rgba(255, 255, 255, 0.8);
    --white-90: rgba(255, 255, 255, 0.9);
    --white-100: rgba(255, 255, 255, 1);

    --blue-10: #f2f7ff;
    --blue-20: #e5f0ff;
    --blue-30: #c2dcff;
    --blue-40: #75b1ff;
    --blue-50: #308aff;
    --blue-60: #0a69fa;
    --blue-70: #0050c7;
    --blue-80: #003c94;
    --blue-90: #042961;
    --blue-100: #021026;

    --gray-10: #f4f6f7;
    --gray-20: #e6e9eb;
    --gray-30: #daddde;
    --gray-40: #c1c4c6;
    --gray-50: #898d8f;
    --gray-60: #6e7375;
    --gray-70: #53575a;
    --gray-80: #2f3133;
    --gray-90: #1f2224;
    --gray-100: #131214;

    --green-10: #e8faf0;
    --green-20: #d7f5e5;
    --green-30: #9bebbf;
    --green-40: #51c285;
    --green-50: #23a15d;
    --green-60: #008557;
    --green-70: #006341;
    --green-80: #0d4f2b;
    --green-90: #05381d;
    --green-100: #021f10;

    --yellow-10: #fff9e6;
    --yellow-20: #ffefb3;
    --yellow-30: #ffd84d;
    --yellow-40: #ed9b16;
    --yellow-50: #d67507;
    --yellow-60: #b26205;
    --yellow-70: #824b0d;
    --yellow-80: #663c0c;
    --yellow-90: #4d2b05;
    --yellow-100: #331c03;

    --red-10: #fff3f0;
    --red-20: #ffe9e3;
    --red-30: #ffcec2;
    --red-40: #ff9175;
    --red-50: #ff5226;
    --red-60: #db340b;
    --red-70: #ad1d00;
    --red-80: #8a1700;
    --red-90: #611000;
    --red-100: #290800;

    --lavender-10: #f6f5ff;
    --lavender-20: #f0edff;
    --lavender-30: #dbd4ff;
    --lavender-40: #b4a6ff;
    --lavender-50: #907aff;
    --lavender-60: #7257ff;
    --lavender-70: #5336e2;
    --lavender-80: #34228f;
    --lavender-90: #291f61;
    --lavender-100: #130d33;

    --flame-10: #fef0eb;
    --flame-20: #fcd2c2;
    --flame-30: #fab59a;
    --flame-40: #f79771;
    --flame-50: #f57948;
    --flame-60: #f46a34;
    --flame-70: #c3552a;
    --flame-80: #92401f;
    --flame-90: #622a15;
    --flame-100: #31150a;

    --fog-10: #fefeff;
    --fog-20: #fcfcfe;
    --fog-30: #f9f9fd;
    --fog-40: #f7f7fb;
    --fog-50: #f5f5fa;
    --fog-60: #f3f4f9;
    --fog-70: #bcbcc0;
    --fog-80: #88888b;
    --fog-90: #575759;
    --fog-100: #2b2b2c;

    --charcoal-10: #e8e8e9;
    --charcoal-20: #bbbbbc;
    --charcoal-30: #8d8d90;
    --charcoal-40: #5f5f64;
    --charcoal-50: #323237;
    --charcoal-60: #1b1b21;
    --charcoal-70: #16161a;
    --charcoal-80: #101014;
    --charcoal-90: #08080a;
    --charcoal-100: #000000;

    --chartreuse-10: #fdfff0;
    --chartreuse-20: #fbfed1;
    --chartreuse-30: #f9feb4;
    --chartreuse-40: #f9feb4;
    --chartreuse-50: #f4fd7f;
    --chartreuse-60: #f2fd72;
    --chartreuse-70: #bbc359;
    --chartreuse-80: #878d42;
    --chartreuse-90: #878d42;
    --chartreuse-100: #2b2c18;

    --bougainvillea-10: #f9effa;
    --bougainvillea-20: #edcff0;
    --bougainvillea-30: #e2afe6;
    --bougainvillea-40: #d68edc;
    --bougainvillea-50: #ca6ed2;
    --bougainvillea-60: #c45ecd;
    --bougainvillea-70: #9d4ba4;
    --bougainvillea-80: #76387b;
    --bougainvillea-90: #4e2652;
    --bougainvillea-100: #271329;

    --bermuda-10: #f6fefc;
    --bermuda-20: #e3fbf6;
    --bermuda-30: #d0f8f1;
    --bermuda-40: #bdf5eb;
    --bermuda-50: #aaf2e5;
    --bermuda-60: #a0f1e2;
    --bermuda-70: #80c1b5;
    --bermuda-80: #609188;
    --bermuda-90: #40605a;
    --bermuda-100: #20302d;

    --wisteria-10: #f6f8ff;
    --wisteria-20: #e4e9fe;
    --wisteria-30: #d2dafe;
    --wisteria-40: #c0cbfd;
    --wisteria-50: #aebcfc;
    --wisteria-60: #a5b4fc;
    --wisteria-70: #8490ca;
    --wisteria-80: #636c97;
    --wisteria-90: #424865;
    --wisteria-100: #212432;

    --mist-10: #fdfdff;
    --mist-20: #f8f9ff;
    --mist-30: #f4f6ff;
    --mist-40: #f0f2ff;
    --mist-50: #ebeeff;
    --mist-60: #e9ecff;
    --mist-70: #babdcc;
    --mist-80: #8c8e99;
    --mist-90: #5d5e66;
    --mist-100: #2f2f33;

    --pacific-10: #e9eaf0;
    --pacific-20: #bebfd1;
    --pacific-30: #9394b3;
    --pacific-40: #676994;
    --pacific-50: #3c3e75;
    --pacific-60: #262966;
    --pacific-70: #1e2152;
    --pacific-80: #17193d;
    --pacific-90: #0f1029;
    --pacific-100: #080814;

    /* ===== Paper Design System Primitives (2026-04-29) =====
       Warm cream-based surface system. The semantic surface/ink/line tokens
       below resolve to these values, and they are overridden by the
       body[data-surface] modes at the bottom of this file. */
    --paper:          #fefefc;
    --paper-2:        #f2f0ec;
    --card:           #ffffff;
    --ink:            #2c2f3a;
    --ink-2:          #4a4e5a;
    --muted:          #6f6c63;
    --muted-2:        #79766d;
    --line:           #e4e5e9;
    --line-2:         #d2d4db;
    /* .list-table row dividers: same as --line by default, but redefined on
       dark surfaces below to something less contrasty than --line reads
       against a very dark page. */
    --list-table-line: var(--line);

    --primary:        #6762c0;
    --primary-ink:    #3f378a;
    --primary-tint:   #eceaf6;
    --primary-tint-2: #c6c2eb;
    --primary-ring:   rgba(103, 98, 192, 0.22);

    --danger: #8f3a2d;
    --danger-bg: #f3d8d0;
    --danger-line: #e3c0b6;
    --ok: #1f6b39;
    --ok-bg: #eaf5ec;
    --ok-line: #cde3d2;
    --warn: #8f5a14;
    --warn-bg: #f5ecd8;
    --warn-line: #e3d2a4;

    /* CodeMirror merge-addon (theme/js-snippet audit diff views) chunk
       highlights — not danger/warn/ok, just the addon's own 3-way (left-only /
       right-only / both-sides) diff scheme. Light values match the vendored
       merge.css defaults; dark equivalents live in body[data-surface="dark"]
       below. */
    --diff-r-bg: #ffffe0;
    --diff-r-line: #ee8;
    --diff-l-bg: #eef;
    --diff-l-line: #88e;
    --diff-both-bg: #dfd;
    --diff-both-line: #4e4;

    /* ===== Semantic Tokens ===== */

    /* Surfaces */
    --bg-page: var(--paper);
    --bg-surface: var(--card);
    --bg-surface-raised: var(--card);
    --bg-subtle: var(--paper-2);
    --bg-muted: var(--paper-2);
    --bg-warning: var(--red-60);
    --bg-warning-hover: var(--red-70);

    /* Static previews used by the Appearance tone picker. These intentionally
       remain fixed so each tile represents its destination surface. */
    --appearance-tone-day: #f2f0ec;
    --appearance-tone-day-bar: #e4e1db;
    --appearance-tone-afternoon: #f7f7fb;
    --appearance-tone-afternoon-bar: #e3e4ea;
    --appearance-tone-evening: #323237;
    --appearance-tone-evening-bar: #5f5f64;
    --appearance-tone-midnight: #101014;
    --appearance-tone-midnight-bar: #323237;

    /* Flat panels: on light surfaces this matches the normal panel card fill
       (--bg-surface), so .panel--flat-dark looks identical to a plain .panel.
       Overridden in body[data-surface="dark"] below to --bg-page, so on dark
       surfaces the panel blends into the page instead of boxing in a second,
       barely-distinguishable dark card. --panel-flat-control-bg is the
       companion --control-bg-color value, flipped so inputs still contrast
       against whichever fill the panel ends up with. */
    --panel-bg-flat: var(--bg-surface);
    --panel-flat-control-bg: var(--bg-page);

    /* Text */
    --fg-default: var(--ink);
    --fg-muted: var(--muted);
    --fg-subtle: var(--muted-2);
    --fg-on-accent: #ffffff;

    /* Links */
    --link-fg: #33507a;
    --link-fg-hover: #253c5e;

    /* Borders */
    --border-default: var(--line);
    --border-subtle: var(--line);
    --border-strong: var(--line-2);

    /* Interactive / Accent — resolves to the paper-system primary purple. */
    --accent-primary: var(--primary);
    --accent-hover: var(--primary-ink);
    --accent-subtle: var(--primary-tint);
    --accent-soft: var(--accent-subtle);
    --accent-muted: var(--primary-tint-2);
    /* Text color for "accent-on-accent-tint" patterns (selected chips,
       active sidebar, badges, pagination, etc.). Equals --accent-primary
       in light mode (works fine on light tints) but is lifted in dark mode
       (overridden in the dark-surface block) so text doesn't share a hue
       with the dark accent-tinted background. */
    --accent-on-tint: var(--accent-primary);

    /* Semantic status */
    --color-success: var(--ok);
    --color-success-bg: var(--ok-bg);
    --color-error: var(--danger);
    --color-error-bg: var(--danger-bg);
    --color-warning: var(--warn);
    --color-warning-bg: var(--warn-bg);
    --color-info: var(--primary);
    --color-info-bg: var(--primary-tint);
    --success-primary: var(--color-success);
    --success-soft: var(--color-success-bg);
    --danger-primary: var(--color-error);
    --danger-soft: var(--color-error-bg);

    /* Chart series (categorical) — Google Charts in dashlets. Seven hue
       families (lavender, flame, cyan, gold, rose, blue, green) × three
       lightness bands. Slots 1-7 are the mids, 8-14 the high-contrast second
       band, 15-21 the low-contrast overflow band (pies past 14 slices only,
       always with a legend). Light uses shades as the second band, dark uses
       tints — see the body[data-surface="dark"] block. Cyan, gold and rose
       (and the two dark steps #e75e26 / #b08e10) are chart-only hues, not
       brand primitives. The ORDER is the colorblind-safety mechanism
       (validated with the dataviz validator: adjacent CVD ΔE ≥ 11, normal-
       vision ΔE ≥ 20, slots 1-14, both modes) — never reorder or insert,
       only append. Mirrored in PHP by uiChartPaletteTokens() in functions.php;
       Tests/Unit/helpers/UiChartPaletteTest keeps the two in sync. Series
       colors deliberately do NOT follow the user accent; only the GeoChart
       heat ramp does. */
    --chart-1:  #726bea;
    --chart-2:  #f46a34;
    --chart-3:  #0aa2c9;
    --chart-4:  #c9a200;
    --chart-5:  #e5397e;
    --chart-6:  #0050c7;
    --chart-7:  #23a15d;
    --chart-8:  #92401f;
    --chart-9:  #007fa3;
    --chart-10: #8a6e03;
    --chart-11: #5336e2;
    --chart-12: #008557;
    --chart-13: #0a69fa;
    --chart-14: #b6005b;
    --chart-15: #f79771;
    --chart-16: #4bc8f0;
    --chart-17: #ebc341;
    --chart-18: #b4a6ff;
    --chart-19: #51c285;
    --chart-20: #308aff;
    --chart-21: #fd79a3;

    /* Chart status colors — for series that MEAN good/bad (Invitations
       statuses). Fixed per meaning, never assigned by rank. Literal hex on
       purpose: uiChartStatusTokens() in functions.php mirrors these and the
       unit test parses them. */
    --chart-status-good:    #23a15d;
    --chart-status-bad:     #db340b;
    --chart-status-info:    #0050c7;
    --chart-status-pending: #d67507;
    --chart-status-neutral: #898d8f;

    /* External brand colors — third-party logos/glyphs that need to render
       in their canonical brand hue (not Swoogo accent). Add new entries
       sparingly and only for marks that genuinely need their own color. */
    --brand-google: #4285f4;

    /* Interactive state overlays */
    --state-hover: rgba(0, 0, 0, 0.04);
    --state-active: rgba(0, 0, 0, 0.07);
    --state-selected: var(--primary-tint);
    --state-disabled-opacity: 0.5;

    /* Selection / toggle */
    --color-selected: var(--blue-60);
    --color-selected-bg: var(--blue-10);

    /* ===== Component Tokens ===== */
    --panel-radius: var(--radius-lg);
    --panel-border: var(--border-default);
    --panel-padding: var(--space-6);
    --panel-heading-padding: var(--space-3) var(--space-6);
    --input-height: var(--space-10);
    --input-radius: var(--radius-md);
    --input-border: var(--border-default);
    --input-padding: var(--space-2) var(--space-3);
    --btn-height: var(--space-9);
    --btn-radius: var(--radius-md);
    --btn-padding: 0 var(--space-4);

    /* ===== Border Radius ===== */
    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 8px;
    --radius-xl: 12px;
    --radius-full: 9999px;

    /* ===== Shadows (warm-tinted, tightened to match the paper surface) ===== */
    --shadow-xs: 0 1px 1px rgba(72, 60, 50, 0.05);
    --shadow-sm: 0 1px 2px rgba(72, 60, 50, 0.07), 0 1px 1px rgba(50, 40, 32, 0.05);
    --shadow-md: 0 2px 4px rgba(72, 60, 50, 0.07), 0 1px 2px rgba(50, 40, 32, 0.05);
    --shadow-lg: 0 4px 10px rgba(72, 60, 50, 0.09), 0 2px 4px rgba(50, 40, 32, 0.06);
    --shadow-xl: 0 10px 24px rgba(72, 60, 50, 0.10), 0 4px 10px rgba(50, 40, 32, 0.05);
    --shadow-inner: inset 0 1px 2px rgba(50, 40, 32, 0.06);
    /* Surface-agnostic card shadow — use instead of raw --shadow-sm on cards */
    --shadow-card:       var(--shadow-sm);
    --shadow-card-hover: var(--shadow-md);

    --shadow-left-navbar: 6px 0 14px -12px rgba(20, 28, 46, .14);
    --shadow-top-navbar: 0 6px 18px 0 rgba(20, 28, 46, .04);
    /* Edge shadow under a sticky subpage head once it locks (.is-stuck). */
    --shadow-subpage-stuck: 0 4px 6px -4px rgba(50, 50, 93, 0.18);

    /* ===== Design Spec Shadows - with dark overrides ===== */
    --sh-sm: 0 1px 0 rgba(44,47,58,.04), 0 1px 2px rgba(44,47,58,.04);
    --sh-md: 0 4px 12px -2px rgba(44,47,58,.06), 0 2px 4px -1px rgba(44,47,58,.04);
    --sh-lg: 0 12px 32px -8px rgba(44,47,58,.14), 0 0 0 1px rgba(44,47,58,.04);
    --sh-drawer: -12px 0 28px -12px rgba(23, 22, 19, .18);

    /* ===== Spacing (4px base grid, Tailwind convention) ===== */
    --space-0: 2px;
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-7: 28px;
    --space-8: 32px;
    --space-9: 36px;
    --space-10: 40px;
    --space-12: 48px;

    /* ===== Typography ===== */
    --font-family: 'Inter', system-ui, -apple-system, sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    --font-size-badge: 10px;
    --font-size-label: 11.5px;
    --font-size-xs: 12px;
    --font-size-btn: 13px;
    --font-size-input: 13px;
    --font-size-toggle: 13px;
    --font-size-segmented: 13px;
    --line-height-xs: 16px;
    --font-size-sm: 14px;
    --line-height-sm: 20px;
    --font-size-base: 14px;
    --line-height-base: 20px;
    --font-size-lg: 16px;
    --line-height-lg: 24px;
    --font-size-xl: 20px;
    --line-height-xl: 28px;
    --font-size-2xl: 24px;
    --line-height-2xl: 32px;
    --font-size-3xl: 32px;
    --line-height-3xl: 36px;
    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;
    --letter-space-label: .12em;
    --letter-spacing-badge: .14rem;

    /* ===== Focus Ring ===== */
    --ring-color: var(--primary-ring);
    --focus-ring: 0 0 0 3px var(--ring-color);

    /* ===== Transitions ===== */
    --transition-fast: 150ms ease;
    --transition-normal: 200ms ease;
    --transition-slow: 300ms ease;

    /* ===== Overlays ===== */
    --overlay-bg: rgba(0, 0, 0, 0.4);
    --overlay-blur: 4px;

    /* ===== Syntax highlighting (highlight.js "tomorrow" theme) =====
       web/plugins/highlight/styles/tomorrow.css is a vendored, light-only
       theme with hardcoded hex colors and a white .hljs background — it
       can't sense the page's surface mode. These tokens restate its palette
       so components.css can re-point every .hljs-* rule per surface (used by
       the SAML "View IDP Metadata" dialog, the only current hljs consumer). */
    --hljs-bg: #ffffff;
    --hljs-fg: #4d4d4c;
    --hljs-comment: #8e908c;
    --hljs-tag: #c82829;
    --hljs-number: #f5871f;
    --hljs-attribute: #eab700;
    --hljs-string: #718c00;
    --hljs-title: #4271ae;
    --hljs-keyword: #8959a8;

    /* ===== CKEditor 4 =====
       The moono-lisa toolbar icons are a dark sprite sheet that vanishes on
       dark paper — invert + hue-rotate them only in dark (see the dark block).
       The dialog close-X bakes its fill into an SVG data-URL, so it needs a
       light (#484848) and dark (#f4f5f7, below) variant rather than currentColor. */
    --cke-icon-filter: none;
    --cke-dialog-close-icon: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='%23484848' d='M12.7 4.71a1 1 0 0 0-1.41 0L8 8 4.71 4.71a1 1 0 1 0-1.41 1.41L6.59 9.41 3.3 12.7a1 1 0 1 0 1.41 1.41L8 10.83l3.29 3.29a1 1 0 1 0 1.41-1.41L9.41 9.41l3.29-3.29a1 1 0 0 0 0-1.41z'/%3E%3C/svg%3E");

    /* Native <select> caret (.new-ui-select). Baked SVG fill can't use
       currentColor, so it flips via this token — muted ink in light, muted
       gray in the dark block below. */
    --select-chevron-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236f6c63' d='M10.293 3.293 6 7.586 1.707 3.293A1 1 0 0 0 .293 4.707l5 5a1 1 0 0 0 1.414 0l5-5a1 1 0 1 0-1.414-1.414Z'/%3E%3C/svg%3E");

    /* Dropdown-search plugin's magnifier icon (web/plugins/dropdown-search)
       bakes its stroke into an SVG data-URL — flip via this token like the
       select chevron above. */
    --search-icon-image: url("data:image/svg+xml,%3Csvg%20width%3D'14'%20height%3D'14'%20viewBox%3D'0%200%2014%2014'%20fill%3D'none'%20xmlns%3D'http%3A//www.w3.org/2000/svg'%3E%3Cpath%20fill-rule%3D'evenodd'%20clip-rule%3D'evenodd'%20d%3D'M6.33333%201.5C3.66396%201.5%201.5%203.66396%201.5%206.33333C1.5%209.00271%203.66396%2011.1667%206.33333%2011.1667C9.00271%2011.1667%2011.1667%209.00271%2011.1667%206.33333C11.1667%203.66396%209.00271%201.5%206.33333%201.5ZM0.5%206.33333C0.5%203.11167%203.11167%200.5%206.33333%200.5C9.55499%200.5%2012.1667%203.11167%2012.1667%206.33333C12.1667%207.76415%2011.6515%209.07465%2010.7966%2010.0895L13.3536%2012.6464C13.5488%2012.8417%2013.5488%2013.1583%2013.3536%2013.3536C13.1583%2013.5488%2012.8417%2013.5488%2012.6464%2013.3536L10.0895%2010.7966C9.07465%2011.6515%207.76415%2012.1667%206.33333%2012.1667C3.11167%2012.1667%200.5%209.55499%200.5%206.33333Z'%20fill%3D'%236f6c63'/%3E%3C/svg%3E");

    /* jQuery-UI datepicker chrome (web/plugins/datepicker/date-input.css)
       bakes its prev/next chevrons and month/year caret into SVG data-URLs
       with a fixed #6E7375 stroke/fill. These light variants are byte-for-byte
       the plugin's own icons; the dark block below swaps in --muted (#bdc1cb)
       variants. Consumed by the datepicker surface-tokenization rules in
       components.css. */
    --dp-prev-icon: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"14\" viewBox=\"0 0 13 14\" fill=\"none\"><path d=\"M8.65556 12.8499C8.36884 12.8498 8.09389 12.7267 7.89118 12.5075L3.56655 7.83326C3.36386 7.61412 3.25 7.31694 3.25 7.00708C3.25 6.69722 3.36386 6.40005 3.56655 6.18091L7.89118 1.50665C7.99091 1.39504 8.11021 1.30602 8.24212 1.24477C8.37402 1.18353 8.51589 1.15129 8.65945 1.14995C8.803 1.1486 8.94537 1.17816 9.07824 1.23692C9.21111 1.29568 9.33182 1.38245 9.43334 1.49217C9.53485 1.60189 9.61513 1.73236 9.66949 1.87597C9.72385 2.01958 9.75121 2.17346 9.74996 2.32862C9.74871 2.48378 9.71889 2.63712 9.66222 2.77969C9.60556 2.92226 9.5232 3.0512 9.41994 3.159L5.85968 7.00708L9.41994 10.8552C9.57109 11.0186 9.67402 11.2268 9.71572 11.4534C9.75742 11.6801 9.73601 11.915 9.6542 12.1285C9.57239 12.342 9.43385 12.5245 9.25609 12.6529C9.07834 12.7813 8.86936 12.8499 8.65556 12.8499Z\" fill=\"%236E7375\"/></svg>");
    --dp-next-icon: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"14\" viewBox=\"0 0 13 14\" fill=\"none\"><path d=\"M4.34444 12.8499C4.13064 12.8499 3.92166 12.7813 3.74391 12.6529C3.56615 12.5245 3.42761 12.342 3.3458 12.1285C3.26399 11.915 3.24258 11.6801 3.28428 11.4534C3.32598 11.2268 3.42891 11.0186 3.58007 10.8552L7.14032 7.00708L3.58007 3.159C3.4768 3.0512 3.39444 2.92226 3.33778 2.77969C3.28111 2.63712 3.25129 2.48378 3.25004 2.32862C3.24879 2.17346 3.27615 2.01958 3.33051 1.87597C3.38487 1.73236 3.46515 1.60189 3.56666 1.49217C3.66818 1.38245 3.78889 1.29568 3.92176 1.23692C4.05463 1.17816 4.197 1.1486 4.34055 1.14995C4.48411 1.15129 4.62598 1.18353 4.75788 1.24477C4.88979 1.30602 5.00909 1.39504 5.10882 1.50665L9.43345 6.18091C9.63614 6.40005 9.75 6.69722 9.75 7.00708C9.75 7.31694 9.63614 7.61412 9.43345 7.83326L5.10882 12.5075C4.90611 12.7267 4.63116 12.8498 4.34444 12.8499Z\" fill=\"%236E7375\"/></svg>");
    --dp-caret-icon: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"25\" height=\"24\" viewBox=\"0 0 25 24\" fill=\"none\"><g opacity=\"0.3\"><path d=\"M8.25 9.75L12.5 14.25L16.75 9.75\" stroke=\"%236E7375\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g></svg>");
}

/* ===== Semantic-token re-declaration on body =====
   Per the CSS Custom Properties spec, var() inside a custom-property value
   IS substituted at the element that consumes the property — so a :root
   declaration of `--bg-page: var(--paper)` will pick up an overridden
   `--paper` from body[data-surface="dark"] automatically. This re-declaration
   is therefore not strictly required for surface-mode switching to work.
   It's kept as a defensive belt-and-braces layer: any non-spec-conformant
   browser quirks (or future regression in our token graph) are caught here,
   and it makes the "semantic tokens follow the paper system" relationship
   visible at body level, alongside the surface overrides themselves. If you
   remove this block, verify Morning ↔ Afternoon ↔ Evening still flips
   correctly across the browsers we support. */
body {
    /* Tells the browser which native-control theme to render (checkboxes,
       <select>, scrollbars, and the <input type="color"> picker popup). */
    color-scheme: light;

    --bg-page: var(--paper);
    --bg-surface: var(--card);
    --bg-surface-raised: var(--card);
    --bg-subtle: var(--paper-2);
    --bg-muted: var(--paper-2);

    --fg-default: var(--ink);
    --fg-muted: var(--muted);
    --fg-subtle: var(--muted-2);

    --border-default: var(--line);
    --border-subtle: var(--line);
    --border-strong: var(--line-2);

    /* Preserve the original locked checkbox in light themes; lift it in dark. */
    --selection-disabled-bg: var(--paper-2);
    --selection-disabled-border: var(--line);

    --accent-primary: var(--primary);
    --accent-hover: var(--primary-ink);
    --accent-subtle: var(--primary-tint);
    --accent-soft: var(--accent-subtle);
    --accent-muted: var(--primary-tint-2);
    --accent-on-tint: var(--accent-primary);
    /* Opaque accent chip (tinted icon buttons): equals the tint pair in
       light mode, but stays OPAQUE in dark mode (the dark --primary-tint*
       are translucent by design) — redefined in the dark block below.
       Declared on body, not :root: substitution happens where a custom
       property is declared, and the accent system is re-derived here. */
    --accent-chip-bg: var(--accent-subtle);
    --accent-chip-bg-hover: var(--accent-muted);
    --accent-chip-border: var(--accent-muted);

    --state-selected: var(--primary-tint);
    --ring-color: var(--primary-ring);
    --focus-ring: 0 0 0 3px var(--ring-color);

    --panel-border: var(--border-default);
    --input-border: var(--border-default);

    --color-success: var(--ok);
    --color-success-bg: var(--ok-bg);
    --color-error: var(--danger);
    --color-error-bg: var(--danger-bg);
    --color-warning: var(--warn);
    --color-warning-bg: var(--warn-bg);
    --color-info: var(--primary);
    --color-info-bg: var(--primary-tint);
    --success-primary: var(--color-success);
    --success-soft: var(--color-success-bg);
    --danger-primary: var(--color-error);
    --danger-soft: var(--color-error-bg);
}

/* ===== Surface Modes =====
   Two orthogonal axes drive four named modes:
       data-surface = light | dark   (lightness)
       data-tone    = warm  | cool   (temperature)
       Morning = light+warm (the :root defaults below)   Afternoon = light+cool
       Evening = dark+warm  (the base dark block below)   Midnight  = dark+cool
   :root is Morning. These overrides re-point only the paper-system primitives so
   semantic tokens automatically follow. */

body[data-surface="light"][data-tone="cool"] {
    --paper:   #fcfcfd;
    --paper-2: #eef0f3;
    --card:    #ffffff;
    --line:    #dde0e5;
    --line-2:  #c9cdd4;
}

/* Evening (dark+warm) base — shared by Midnight (dark+cool) below. */
body[data-surface="dark"] {
    color-scheme: dark;

    --paper:   #16181f;
    --paper-2: #1f2229;
    --card:    #22252e;
    /* Cool gray ink family. The guide used the same cool hues; we keep the
       muted tones lifted significantly above the guide's #8d919c / #6b6f7a
       because on dark paper those gave <5:1 contrast for eyebrow labels,
       table headers, and timestamps. Lifted to ~9:1 / ~5.5:1 so the
       hierarchy stays quiet but unmistakably legible. */
    --ink:     #f4f5f7;
    --ink-2:   #c2c6cf;
    --muted:   #bdc1cb;
    --muted-2: #8e929e;
    --line:    #2c2f3a;
    --line-2:  #484b54;
    --selection-disabled-bg: color-mix(in srgb, var(--muted-2) 40%, var(--card));
    --selection-disabled-border: var(--muted-2);
    /* --line reads too bright as a row divider against dark paper (Evening/
       Midnight) — fall back to --paper-2 so .list-table's row hairlines stay
       subtle instead of standing out. */
    --list-table-line: var(--paper-2);

    /* Material state layers invert on dark paper: a black overlay is invisible,
       so use a light (white) overlay for hover/active states. */
    --state-hover:  rgba(255, 255, 255, 0.06);
    --state-active: rgba(255, 255, 255, 0.10);

    /* Chart series — same slot order as the light block. On dark paper the
       shades fall under 3:1, so the second band (8-14) becomes the tints and
       the shades move to the overflow band (15-21). Slots 3, 5, 7 are shared.
       Validated against both dark cards (#22252e Evening, #10131a Midnight). */
    --chart-1:  #907aff;
    --chart-2:  #e75e26;
    --chart-4:  #b08e10;
    --chart-6:  #0a69fa;
    --chart-8:  #b4a6ff;
    --chart-9:  #51c285;
    --chart-10: #308aff;
    --chart-11: #f79771;
    --chart-12: #4bc8f0;
    --chart-13: #ebc341;
    --chart-14: #fd79a3;
    --chart-15: #92401f;
    --chart-16: #007fa3;
    --chart-17: #8a6e03;
    --chart-18: #5336e2;
    --chart-19: #008557;
    --chart-20: #0050c7;
    --chart-21: #b6005b;

    --chart-status-bad:     #ff5226;
    --chart-status-info:    #0a69fa;
    --chart-status-pending: #ed9b16;
    --chart-status-neutral: #c1c4c6;

    --danger: #f0a193;
    --danger-bg: rgba(240,161,147,.14);
    --danger-line: rgba(240,161,147,.38);
    --ok: #7dd49a;
    --ok-bg: rgba(125,212,154,.16);
    --ok-line: rgba(125,212,154,.38);
    --warn: #e8b86a;
    --warn-bg: rgba(232,184,106,.16);
    --warn-line: rgba(232,184,106,.38);

    /* Same pale merge-addon washes as :root, traded for low-opacity tints so
       they read as a highlight instead of a glaring pale box on dark paper. */
    --diff-r-bg: rgba(232, 214, 46, 0.14);
    --diff-r-line: rgba(232, 214, 46, 0.45);
    --diff-l-bg: rgba(107, 140, 255, 0.16);
    --diff-l-line: rgba(107, 140, 255, 0.5);
    --diff-both-bg: rgba(90, 210, 130, 0.16);
    --diff-both-line: rgba(90, 210, 130, 0.5);

    --primary-tint:   rgba(103, 98, 192, 0.18);
    --primary-tint-2: rgba(103, 98, 192, 0.32);
    /* 30% read as a faint halo against the dark card paper — bump to 50%
       so the focus ring carries clear identity as the active accent. */
    --primary-ring:   rgba(103, 98, 192, 0.50);
    /* Opaque equivalents of the translucent tints, flattened over the card
       tone. color-mix from --primary so amber/custom accents follow. */
    --accent-chip-bg: color-mix(in srgb, var(--primary) 20%, var(--card));
    --accent-chip-bg-hover: color-mix(in srgb, var(--primary) 32%, var(--card));
    --accent-chip-border: color-mix(in srgb, var(--primary) 42%, var(--card));

    --color-success-bg: rgba(47, 138, 77, 0.18);
    --color-warning-bg: rgba(192, 122, 31, 0.18);
    --color-error-bg:   rgba(176, 74, 58, 0.18);
    /* Info alerts were missing a dark-surface tint, so they kept the light
       --blue-10 background and never adapted (e.g. the clone-event notice).
       Match the soft-tint treatment of the other three semantic alerts. */
    --color-info-bg:    rgba(10, 105, 250, 0.18);

    /* In dark mode the spec's --line (#2c2f3a) is only ~10 luma points
       lighter than --card (#22252e), so card edges nearly disappear. Bump
       the panel/input border to --line-2 (#3a3d48) for visible card
       definition. Generic --border-default stays at --line so non-card
       dividers (table rows, form section breaks) keep their quiet weight. */
    --panel-border: var(--line-2);
    --input-border: var(--line-2);

    /* Flat panels drop their fill to the page paper on dark surfaces (see
       :root) — the dark --card and --paper are close enough in value that a
       filled panel reads as a redundant box-within-a-box, so pages that
       opt into .panel--flat-dark blend flush with the page here. Controls
       inside flip to the card fill so they still read against the flat
       page background. */
    --panel-bg-flat: var(--bg-page);
    --panel-flat-control-bg: var(--bg-surface);

    /* Lift text-on-tint accents so they stand out from the same-hue tint
       background. 50/50 mix with white reads as a clearly lighter shade
       of the accent across purple, amber, and custom. */
    --accent-on-tint: color-mix(in srgb, var(--primary), white 50%);

    /* Links — near-paper blue-slate, lifted to stay AA on the dark surface. */
    --link-fg: #9fb8d8;
    --link-fg-hover: #c2d5ec;

    /* Card lift in dark mode. The default --shadow-sm / --shadow-md use
       rgba(50,50,93,...) tuned for light surfaces and disappear on dark
       paper. These compose an inset top-edge highlight (simulates a raised
       surface catching light from above) plus a soft dark drop shadow on
       hover for grounding. Used by .session-row and any other card that
       needs visible depth on dark surfaces. */
    --shadow-card-dark:       inset 0 1px 0 rgba(255, 255, 255, 0.04);
    --shadow-card-dark-hover: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 4px 12px rgba(0, 0, 0, 0.3);
    --shadow-card:       var(--shadow-card-dark);
    --shadow-card-hover: var(--shadow-card-dark-hover);

    /* Skeleton shimmer: the light gradient's --gray-10 highlight reads as a
       glitchy strobe sweeping the dark sidebar — swap to a soft translucent
       sheen over the dark card. */
    --skeleton-base: rgba(255, 255, 255, 0.03);
    --skeleton-highlight: rgba(255, 255, 255, 0.1);

    /* Inset wells: lift the overlay/border slightly so the box reads on dark. */
    --inset-overlay: rgba(255, 255, 255, 0.03);
    --inset-overlay-border: rgba(255, 255, 255, 0.08);

    /* SVG icon tokens that bake ink/muted hex in data-URLs — pre-set to the
       cool gray family so the merge with ui-refresh/data-attribute-cleanup
       (PR #1865) resolves to the correct values and not the old warm cream. */
    --form-section-label-fg: #8e929e;
    --select-chevron-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23bdc1cb' d='M10.293 3.293 6 7.586 1.707 3.293A1 1 0 0 0 .293 4.707l5 5a1 1 0 0 0 1.414 0l5-5a1 1 0 1 0-1.414-1.414Z'/%3E%3C/svg%3E");
    --search-icon-image: url("data:image/svg+xml,%3Csvg%20width%3D'14'%20height%3D'14'%20viewBox%3D'0%200%2014%2014'%20fill%3D'none'%20xmlns%3D'http%3A//www.w3.org/2000/svg'%3E%3Cpath%20fill-rule%3D'evenodd'%20clip-rule%3D'evenodd'%20d%3D'M6.33333%201.5C3.66396%201.5%201.5%203.66396%201.5%206.33333C1.5%209.00271%203.66396%2011.1667%206.33333%2011.1667C9.00271%2011.1667%2011.1667%209.00271%2011.1667%206.33333C11.1667%203.66396%209.00271%201.5%206.33333%201.5ZM0.5%206.33333C0.5%203.11167%203.11167%200.5%206.33333%200.5C9.55499%200.5%2012.1667%203.11167%2012.1667%206.33333C12.1667%207.76415%2011.6515%209.07465%2010.7966%2010.0895L13.3536%2012.6464C13.5488%2012.8417%2013.5488%2013.1583%2013.3536%2013.3536C13.1583%2013.5488%2012.8417%2013.5488%2012.6464%2013.3536L10.0895%2010.7966C9.07465%2011.6515%207.76415%2012.1667%206.33333%2012.1667C3.11167%2012.1667%200.5%209.55499%200.5%206.33333Z'%20fill%3D'%23bdc1cb'/%3E%3C/svg%3E");
    --cke-dialog-close-icon: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='%23f4f5f7' d='M12.7 4.71a1 1 0 0 0-1.41 0L8 8 4.71 4.71a1 1 0 1 0-1.41 1.41L6.59 9.41 3.3 12.7a1 1 0 1 0 1.41 1.41L8 10.83l3.29 3.29a1 1 0 1 0 1.41-1.41L9.41 9.41l3.29-3.29a1 1 0 0 0 0-1.41z'/%3E%3C/svg%3E");
    /* Toolbar icon sprite is dark glyphs — invert onto dark paper. */
    --cke-icon-filter: invert(0.85) hue-rotate(180deg);
    --dp-prev-icon: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"14\" viewBox=\"0 0 13 14\" fill=\"none\"><path d=\"M8.65556 12.8499C8.36884 12.8498 8.09389 12.7267 7.89118 12.5075L3.56655 7.83326C3.36386 7.61412 3.25 7.31694 3.25 7.00708C3.25 6.69722 3.36386 6.40005 3.56655 6.18091L7.89118 1.50665C7.99091 1.39504 8.11021 1.30602 8.24212 1.24477C8.37402 1.18353 8.51589 1.15129 8.65945 1.14995C8.803 1.1486 8.94537 1.17816 9.07824 1.23692C9.21111 1.29568 9.33182 1.38245 9.43334 1.49217C9.53485 1.60189 9.61513 1.73236 9.66949 1.87597C9.72385 2.01958 9.75121 2.17346 9.74996 2.32862C9.74871 2.48378 9.71889 2.63712 9.66222 2.77969C9.60556 2.92226 9.5232 3.0512 9.41994 3.159L5.85968 7.00708L9.41994 10.8552C9.57109 11.0186 9.67402 11.2268 9.71572 11.4534C9.75742 11.6801 9.73601 11.915 9.6542 12.1285C9.57239 12.342 9.43385 12.5245 9.25609 12.6529C9.07834 12.7813 8.86936 12.8499 8.65556 12.8499Z\" fill=\"%23bdc1cb\"/></svg>");
    --dp-next-icon: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"14\" viewBox=\"0 0 13 14\" fill=\"none\"><path d=\"M4.34444 12.8499C4.13064 12.8499 3.92166 12.7813 3.74391 12.6529C3.56615 12.5245 3.42761 12.342 3.3458 12.1285C3.26399 11.915 3.24258 11.6801 3.28428 11.4534C3.32598 11.2268 3.42891 11.0186 3.58007 10.8552L7.14032 7.00708L3.58007 3.159C3.4768 3.0512 3.39444 2.92226 3.33778 2.77969C3.28111 2.63712 3.25129 2.48378 3.25004 2.32862C3.24879 2.17346 3.27615 2.01958 3.33051 1.87597C3.38487 1.73236 3.46515 1.60189 3.56666 1.49217C3.66818 1.38245 3.78889 1.29568 3.92176 1.23692C4.05463 1.17816 4.197 1.1486 4.34055 1.14995C4.48411 1.15129 4.62598 1.18353 4.75788 1.24477C4.88979 1.30602 5.00909 1.39504 5.10882 1.50665L9.43345 6.18091C9.63614 6.40005 9.75 6.69722 9.75 7.00708C9.75 7.31694 9.63614 7.61412 9.43345 7.83326L5.10882 12.5075C4.90611 12.7267 4.63116 12.8498 4.34444 12.8499Z\" fill=\"%23bdc1cb\"/></svg>");
    --dp-caret-icon: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"25\" height=\"24\" viewBox=\"0 0 25 24\" fill=\"none\"><path d=\"M8.25 9.75L12.5 14.25L16.75 9.75\" stroke=\"%23bdc1cb\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>");

    /* Lift primary-ink so accent hover/active states are visible on dark paper. */
    --primary-ink:    #c6c2eb;

    /* Syntax highlighting — the vendored "tomorrow" theme's light palette
       swapped for dark-surface equivalents pulled from the existing semantic
       set, so the IDP Metadata dialog's XML dump stays legible on dark paper
       instead of showing through the vendor CSS's hardcoded white background. */
    --hljs-bg: var(--bg-page);
    --hljs-fg: var(--fg-default);
    --hljs-comment: var(--muted);
    --hljs-tag: var(--danger);
    --hljs-number: #f2a765;
    --hljs-attribute: var(--warn);
    --hljs-string: var(--ok);
    --hljs-title: var(--link-fg);
    --hljs-keyword: var(--primary-ink);

    --sh-sm: 0 1px 0 rgba(0,0,0,.4), 0 1px 2px rgba(0,0,0,.3);
    --sh-md: 0 4px 14px -2px rgba(0,0,0,.5), 0 2px 4px -1px rgba(0,0,0,.35);
    --sh-lg: 0 16px 40px -8px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.06);
    --sh-drawer: -16px 0 32px -12px rgba(0, 0, 0, .55);
    --shadow-left-navbar: 6px 0 14px -12px rgba(255, 255, 255, .08);
    --shadow-top-navbar: 0 6px 18px 0 rgba(255, 255, 255, .04);
    /* Blue-tinted light shadow is invisible on dark paper — deepen to black. */
    --shadow-subpage-stuck: 0 4px 6px -4px rgba(0, 0, 0, 0.45);
}

/* Bootstrap 3 fixes the document root at 10px, which blocks Chrome's font-size
   preference from reaching rem units. Restrict the reset to the refreshed UI so
   legacy pages, including the refresh opt-in modal, retain their current scale. */
html:has(body.ui-refresh) {
    font-size: revert;
    --font-size-badge: 0.625rem;
    --font-size-label: 0.71875rem;
    --font-size-xs: 0.75rem;
    --font-size-btn: 0.8125rem;
    --font-size-input: 0.8125rem;
    --font-size-toggle: 0.8125rem;
    --font-size-segmented: 0.8125rem;
    --line-height-xs: 1rem;
    --font-size-sm: 0.875rem;
    --line-height-sm: 1.25rem;
    --font-size-base: 0.875rem;
    --line-height-base: 1.25rem;
    --font-size-lg: 1rem;
    --line-height-lg: 1.5rem;
    --font-size-xl: 1.25rem;
    --line-height-xl: 1.75rem;
    --font-size-2xl: 1.5rem;
    --line-height-2xl: 2rem;
    --font-size-3xl: 2rem;
    --line-height-3xl: 2.25rem;
}

/* Midnight (dark+cool) — keeps data-surface="dark" so every dark-mode override
   (chips, buttons, contrast fixes) is inherited from the Evening base; only
   deepens the surface/line primitives. */
body[data-surface="dark"][data-tone="cool"] {
    --paper:   #050608;
    --paper-2: #0c0e12;
    --card:    #10131a;
    --line:    #1b1e27;
    --line-2:  #272b36;
}

/* Keep the refreshed default accent out of legacy pages. The UI-refresh asset
   can load while the feature flag is available but the user has not opted in. */
body.ui-refresh {
    --primary:      #726bea;
    --primary-ring: rgba(114, 107, 234, 0.22);
}
body.ui-refresh[data-surface="dark"] {
    --primary-tint:   rgba(114, 107, 234, 0.18);
    --primary-tint-2: rgba(114, 107, 234, 0.32);
    --primary-ring:   rgba(114, 107, 234, 0.50);
}

/* ===== Accent Modes =====
   Override only the four primary tokens + the derived ring. Everything
   else (surfaces, ink, semantic) stays. Set via <body data-accent="amber">
   or "custom". The default UI-refresh purple is defined above. */

body.ui-refresh[data-accent="amber"] {
    --primary:        #f46a34;
    --primary-ink:    #8e3f0f;
    --primary-tint:   #fbeadd;
    --primary-tint-2: #f3c8a7;
    --primary-ring:   rgba(244, 106, 52, 0.22);
}
body.ui-refresh[data-accent="amber"][data-surface="dark"] {
    --primary-tint:   rgba(244, 106, 52, 0.22);
    --primary-tint-2: rgba(244, 106, 52, 0.42);
    --primary-ink:    #f3c8a7;
    --primary-ring:   rgba(244, 106, 52, 0.50);
}

/* Custom — the four derived tokens are computed from --user-accent (set
   inline on <body> by the picker) using color-mix(). Percentages are tuned
   so an arbitrary hex looks reasonable across the palette without hand
   tuning per color. The dark variant uses transparent alphas instead of
   solid mixes so the tint reads as glow rather than washed-out paper. */
body.ui-refresh[data-accent="custom"] {
    --primary:        var(--user-accent, #726bea);
    --primary-ink:    color-mix(in srgb, var(--user-accent, #726bea), black 22%);
    --primary-tint:   color-mix(in srgb, var(--user-accent, #726bea) 12%, var(--paper));
    --primary-tint-2: color-mix(in srgb, var(--user-accent, #726bea) 28%, var(--paper));
    --primary-ring:   color-mix(in srgb, var(--user-accent, #726bea) 22%, transparent);
}
body.ui-refresh[data-accent="custom"][data-surface="dark"] {
    --primary-tint:   color-mix(in srgb, var(--user-accent, #726bea) 18%, transparent);
    --primary-tint-2: color-mix(in srgb, var(--user-accent, #726bea) 42%, transparent);
    --primary-ink:    color-mix(in srgb, var(--user-accent, #726bea), white 25%);
    /* See note on default-dark --primary-ring — bumped for visibility. */
    --primary-ring:   color-mix(in srgb, var(--user-accent, #726bea) 50%, transparent);
}
