/* League Spartan — self-hosted woff2 subsets (served at /CADdy-Hub/fonts). */
/* latin */
@font-face {
    font-family: 'League Spartan';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    size-adjust: 114%;
    src: url('/CADdy-Hub/fonts/league-spartan/latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
    font-family: 'League Spartan';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    size-adjust: 114%;
    src: url('/CADdy-Hub/fonts/league-spartan/latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* vietnamese */
@font-face {
    font-family: 'League Spartan';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    size-adjust: 114%;
    src: url('/CADdy-Hub/fonts/league-spartan/vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

:root {
    /* ---- Brand (caddy-hub blue). Light theme only — body.dark is tuned later. ---- */
    --primary-color: #005CEB;                /* branding / primary action / links / active nav */
    --primary-accent-color: #2E7BEF;         /* lighter primary / hover / accents */
    /* Deepened from #5B6B82 (2026-10 contrast pass): muted text sits on the FILLED gray too (tab counts,
       chips, dropdown placeholders), and #5B6B82 was 4.37:1 there. #526075 is 5.1:1 on --control-bg,
       4.6:1 on --control-hover-bg, 6.1:1 on --panel. Same blue-gray, one step deeper. */
    --secondary-color: #526075;              /* secondary buttons, muted chrome (blue-gray) */
    --secondary-accent-color: #73839B;       /* secondary button hover */
    --other-color: #8b9098;                  /* borders (neutral) */
    /* --background-color is an ALIAS of --canvas now (see "role tokens" below). */
    --sub-background-color: #c9c9cb;         /* panels/cards (neutral gray) */
    --accent-color: #d5d3da;                 /* subtle contrast (neutral gray) */
    --header-color: #0040A3;                 /* headers / table header rows / active-pressed (deep blue) */
    --font-color: #121317;                   /* text */
    --scroll-color: #b9bec6;                 /* scroll bar */
    --input-color: #005CEB;                  /* input focus/outline (matches primary) */
    --shadow: rgba(16, 19, 23, 0.06);        /* flat: barely-there elevation */
    --admin-hours-missing-bg: rgba(250, 224, 120, 0.55);   /* soft yellow flag for controllers missing a standard hour qty */
    --admin-hours-dup-bg: rgba(245, 158, 66, 0.32);        /* soft orange flag for controllers with duplicate hours but no group size */
    --admin-hours-dup-marker: #b25e00;                     /* warning marker text/border for the duplicate-hours flag */

    /* ---- caddy-hub brand extensions (light) ---- */
    --brand-primary-hover: #2E7BEF;
    --brand-active: #0040A3;                 /* pressed / active = header blue */
    --brand-wash: #E1ECFD;                   /* hover/selected wash on neutral surfaces */
    --brand-tint: #7DA8F4;
    --link-color: #005CEB;
    --link-hover-color: #0040A3;
    --focus-ring-color: #005CEB;
    --on-brand-text: #FFFFFF;                /* text/icons on a brand fill */
    --font-family-base: 'League Spartan', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;

    /* ---- NEUTRAL SURFACES (light) — the CADdy-Bid structure, tinted toward the Hub's blue-gray ----
       Bid's app shell is a light gray canvas carrying raised, rounded panels, with "filled" gray
       controls (buttons, inputs, tabs) instead of outlined ones. These are the raw values; the role
       names below (and every legacy name: --surface, --surface-2, --card-bg, --background-color …)
       point at them. styles.md §2 has the table. Text contrast was checked against each:
       --font-color ≥ 14:1 everywhere, --secondary-color ≥ 4.5:1 on every surface and filled control
       including --control-hover-bg, --text-faint ≥ 4.5:1 on --canvas, --panel and --panel-2. */
    --canvas: #E9EDF2;                       /* page background (Bid #e8e8e8, tinted blue-gray) */
    --panel: #F8FAFC;                        /* raised panel: cards, table panels, modals, popovers */
    --panel-2: #EEF2F6;                      /* inset / alt inside a panel: read-only cells, hover, wells */
    --panel-border: #D7DEE7;                 /* the thin edge a panel carries with its shadow */
    --control-bg: #E2E7EE;                   /* filled control at rest: neutral button, input, select, pill tab */
    --control-hover-bg: #D5DCE5;             /* filled control hover */
    --control-active-bg: #C8D1DC;            /* filled control pressed */
    --hairline: #DCE2EA;                     /* thin dividers: row rules, column rules, section rules */
    --hairline-strong: #C3CCD8;              /* a rule that must read at a glance (group band edge, tab row) */
    /* Was #97A6BE (2.1–2.4:1), but .ch-faint and --text-faint carry text people read all over the Hub (job
       numbers, "Page 1 of 3", "from catalog", "No offices", chart ticks). Raised to 4.6:1 on --canvas (the
       darkest surface it sits on) and 5.2:1 on --panel. It is a bluer slate than --secondary-color, and
       placeholders in it still read far lighter than an entered value (--font-color, 17:1). */
    --text-faint: #576B8C;                   /* quiet blue-gray: captions, placeholders, secondary notes */
    /* The brand blue AS TEXT: one step deeper than the #005CEB fill so it also passes on its own washes
       (--brand-wash, --info-bg) over the canvas and on the rail's active item: 6.1:1 on --panel, 4.7:1+ on
       every wash. Fills, borders and focus rings stay --primary-color. */
    --brand-text: #0054D7;
    --btn-primary-bg: #005CEB;               /* primary button fill (white text 5.6:1) */
    --btn-primary-hover-bg: #0040A3;         /* primary button hover: darker, as Bid's buttons do */
    --btn-danger-bg: #B3261E;                /* danger button fill = --danger-color (white text 6.4:1) */
    --btn-danger-hover-bg: #8F1E18;
    --table-head-fg: #0040A3;                /* table header text = --header-color */
    --table-head-rule: #0040A3;              /* the 2px rule under a table header */
    --group-band-bg: #DCE5F1;                /* collapsible group band (Bid's status bar), default tint */
    --group-band-fg: #0040A3;                /* its title (7.2:1) */
    --rail-fg: #2F3A4B;                      /* idle rail icon + label, on the header gray (6.9:1 on --header-bar) */
    /* The header bar, CADdy-Bid's: its --sub-background-color gray (#bfbfc0) tinted to the Hub's
       blue-gray. The icon tiles sit on the bar color and fade to --header-tile-hover-bg on hover. */
    --header-bar: #C2CAD5;
    --header-tile-hover-bg: #5B6B82;         /* Bid hovers its tiles to --secondary-color */
    --menu-border: #73839B;                  /* Bid's options menu edge (--secondary-accent-color) */
    --hsearch-key-edge: #5B6A80;             /* the search box's "/" keycap edge: 3.3:1 on --header-bar (UI parts need 3:1) */
    --menu-hover-bg: #73839B;                /* its item hover (text 4.7:1) */
    --menu-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
    /* Find on page (header-search.js): every match, and the one Enter is on: dark text on amber, 15:1 and 8.6:1. */
    --find-hit-bg: #FCE7A8;
    --find-hit-fg: #121317;
    --find-current-bg: #F59E0B;
    --find-current-fg: #121317;
    --panel-shadow: 0 1px 2px rgba(22, 34, 56, 0.06), 0 3px 12px rgba(22, 34, 56, 0.07);
    --panel-shadow-lg: 0 18px 48px rgba(16, 24, 40, 0.22), 0 2px 6px rgba(16, 24, 40, 0.10);
    --modal-backdrop: rgba(12, 18, 28, 0.45);
    /* Behind a document image (a scanned or uploaded page), white in BOTH themes on purpose: a page
       is paper, not a themed surface, and a transparent screenshot of black text on --surface in the
       dark theme would be unreadable. Not overridden in body.dark. */
    --paper: #ffffff;
    --row-selected-bg: #D2E2FC;
    --zebra-bg: #EEF2F6;

    /* WIP cost-by-family bars: materials reuse success green, labor the brand blue, subs this purple. */
    --family-sub-color: #6B4EA8;
    /* The fourth cost family on Simple WIP: everything that is not labour, material or subcontractor.
       Teal, and deliberately NOT red or amber - red means over budget on these bars and amber reads as
       a warning, while "other" is a neutral bucket that is on most jobs and means nothing is wrong.
       One value for both themes, as --family-sub-color is: mid-teal carries on white and on the dark
       ground alike, and a family color that shifts between themes stops being recognisable. */
    --family-other-color: #14958C;

    /* semantic */
    /* The text colors are one step deeper than the tints' own hue (#1E7F4F / #B25E00 / #005CEB), so a
       label on its tint passes 4.5:1 on --panel, --panel-2 AND --canvas (they were 3.5–4.2:1). The tints
       are unchanged; the hues are the same green, amber and blue. */
    --success-color: #196841; --success-bg: rgba(30, 127, 79, 0.14);
    --warning-color: #954F00; --warning-bg: rgba(245, 158, 66, 0.18);
    --danger-color: #B3261E;  --danger-bg: rgba(179, 38, 30, 0.12);
    --info-color: #0054D7;    --info-bg: rgba(0, 92, 235, 0.10);

    /* requisition rollup + per-line status (see styles.md §status) */
    --status-stock-bg: rgba(91, 107, 130, 0.16);   --status-stock-fg: #3D495C;
    --status-pending-bg: rgba(0, 92, 235, 0.10);    --status-pending-fg: #0040A3;
    --status-ordered-bg: rgba(245, 158, 66, 0.18);  --status-ordered-fg: #954F00;
    --status-received-bg: rgba(125, 168, 244, 0.22);--status-received-fg: #0040A3;
    --status-delivered-bg: rgba(30, 127, 79, 0.16); --status-delivered-fg: #196841;
    --status-cancelled-bg: rgba(179, 38, 30, 0.10); --status-cancelled-fg: #B3261E;

    /* Project section colors */
    --project-status-header-text: var(--font-color);
    --project-status-new-lead-bg: rgba(30, 64, 175, 0.34);
    --project-status-ready-for-pricing-bg: rgba(6, 95, 70, 0.34);
    --project-status-pricing-bg: rgba(146, 64, 14, 0.34);
    --project-status-awaiting-info-bg: rgba(88, 28, 135, 0.34);
    --project-status-ready-for-review-bg: rgba(157, 23, 77, 0.34);
    --project-status-sent-to-sales-bg: rgba(3, 105, 161, 0.34);
    --project-status-sent-to-customer-bg: rgba(22, 101, 52, 0.34);
    --project-status-waiting-on-subs-bg: rgba(180, 83, 9, 0.34);
    --project-status-won-bg: rgba(20, 83, 45, 0.40);
    --project-status-no-bid-bg: rgba(55, 65, 81, 0.38);
    --project-status-lost-bg: rgba(153, 27, 27, 0.38);
    --project-status-on-hold-dead-bg: rgba(31, 41, 55, 0.42);
    --project-status-redesign-bg: rgba(159, 18, 57, 0.36);
    --project-status-re-bid-bg: rgba(67, 56, 202, 0.36);
    --project-status-owner-direct-quote-bg: rgba(15, 118, 110, 0.36);

    /* Pie chart */
    --summary-material-color: #6ab7ff;
    --summary-hours-color: #f5c15c;
    --summary-install-color: #e05bd2;

    /* Categorical chart series — one color per thing being compared (Inventory → Stock value, By
       warehouse). Assigned IN THIS ORDER, never cycled: a seventh series folds into "Other" (a neutral
       token), it never gets a made-up hue. The order is what keeps neighbours apart for color-blind
       readers; it was run through the dataviz palette validator against this theme's canvas
       (--background-color): CVD ΔE ≥ 9.1, normal-vision ΔE ≥ 19.6. Slots 3–5 sit under 3:1 on the light
       canvas, so a chart using them must also carry a legend with names and a table view. */
    --chart-series-1: #2a78d6;
    --chart-series-2: #eb6834;
    --chart-series-3: #1baf7a;
    --chart-series-4: #eda100;
    --chart-series-5: #e87ba4;
    --chart-series-6: #008300;

    /* Look Ahead job colors: twelve hues so a job keeps its own color across the grid drawer, the
       timeline bars and the day chips (lookahead.js hashes the job number into a slot). Light uses the
       deep (700/600) steps under WHITE ink, every one >= 4.8:1 for the ink and >= 4.6:1 against --panel.
       Neighbors alternate cool and warm so adjacent slots never read as the same job. */
    --la-job-1: #0369A1;  --la-job-2: #7C3AED;  --la-job-3: #BE185D;  --la-job-4: #047857;
    --la-job-5: #B45309;  --la-job-6: #DC2626;  --la-job-7: #2563EB;  --la-job-8: #7E22CE;
    --la-job-9: #15803D;  --la-job-10: #C2410C; --la-job-11: #0E7490; --la-job-12: #A21CAF;
    --la-job-ink: #FFFFFF;

    --app-switch-caddy-bg: #6eb471;
    --app-switch-caddy-border: #4CAF50;
    --app-switch-caddy-hover-bg: #4CAF50;
    --app-switch-caddy-hover-border: #66BB6A;

    /* CADdy-Bid's own brand purple, lifted from that app's palette (--primary-color there), so a row
       in the updates feed that came from Bid is recognisably Bid rather than another grey chip.

       Built as a STATUS PILL, mirroring --warning-bg/--warning-color exactly: one translucent tint
       shared by both themes, and a text color per theme. That is what makes the CADdy Bid tag sit
       with Over budget / Approved / Denied instead of looking like a different species of badge. */
    --bid-color: #4f3a63;
    --bid-bg: rgba(108, 85, 132, 0.20);

    /* CSS LINE ICONS (styles.md §6). Each is a Lucide line icon (ISC) in public/icons/line/, used as a
       MASK, never as a picture: the consumer paints it with `background-color: currentColor` (or a color
       token) through `mask: var(--…) no-repeat center / contain`, so one definition serves both themes.
       Declared on :root only: they hold no color, so body.dark has nothing to swap. */
    --calendar-icon: url('/CADdy-Hub/icons/line/calendar.svg');
    --sch-icon-indent: url('/CADdy-Hub/icons/line/indent-increase.svg');
    --sch-icon-outdent: url('/CADdy-Hub/icons/line/indent-decrease.svg');
    --sch-icon-up: url('/CADdy-Hub/icons/line/arrow-up.svg');
    --sch-icon-dup: url('/CADdy-Hub/icons/line/copy.svg');
    --sch-icon-lock: url('/CADdy-Hub/icons/line/lock.svg');
    --sch-icon-unlock: url('/CADdy-Hub/icons/line/lock-open.svg');
    --ico-trash: url('/CADdy-Hub/icons/line/trash-2.svg');
    --ico-filter: url('/CADdy-Hub/icons/line/funnel.svg');
    --ico-like: url('/CADdy-Hub/icons/line/thumbs-up.svg');
    --ico-view: url('/CADdy-Hub/icons/line/eye.svg');
    --ico-updates: url('/CADdy-Hub/icons/line/message-circle-more.svg');

    /* STAGE DIMENSIONS */
    --stage-max-width: 1200px;
    --stage-aspect-ratio: 16/9;

    /* USER RULES */
    user-select: none;
}

body.dark {
    /* Native controls (checkboxes, radios, scrollbars, date chrome) follow the theme too. */
    color-scheme: dark;
    --primary-color: #3B82F6;                /* branding / primary action / links (blue, light-on-dark) */
    --primary-accent-color: #5C97F0;         /* lighter primary / hover */
    --secondary-color: #98A7BB;              /* muted chrome; 4.6:1 on --control-hover-bg (was #8FA0B5, 4.2:1) */
    --secondary-accent-color: #A6B5C8;       /* secondary button hover */
    --other-color: #5a5a64;                  /* borders (neutral) */
    --sub-background-color: #1B1E24;         /* panels (dark) */
    --accent-color: #1B1E24;                 /* subtle contrast (dark) */
    --header-color: #2563EB;                 /* table-header accents / active-pressed (blue) */
    --font-color: #f6f6f8;                   /* text */
    --scroll-color: #3a3a3a;                 /* scroll bar */
    --input-color: #3B82F6;                  /* input focus/outline (matches primary) */
    --shadow: rgba(0, 0, 0, 0.40);
    --admin-hours-missing-bg: rgba(250, 224, 120, 0.14);   /* soft yellow flag for controllers missing a standard hour qty */
    --admin-hours-dup-bg: rgba(245, 158, 66, 0.16);        /* soft orange flag for controllers with duplicate hours but no group size */
    --admin-hours-dup-marker: #e7902f;                     /* warning marker text/border for the duplicate-hours flag */

    /* ---- caddy-hub brand extensions (dark) ---- */
    --brand-primary-hover: #5C97F0;
    --brand-active: #2563EB;                 /* pressed / active */
    --brand-wash: rgba(59, 130, 246, 0.18);  /* hover/selected wash on dark surfaces */
    --brand-tint: #3B82F6;
    --link-color: #6FA2F7;
    --link-hover-color: #9CC0FA;
    --focus-ring-color: #5C97F0;
    --on-brand-text: #FFFFFF;                /* text/icons on a brand fill */

    /* ---- NEUTRAL SURFACES (dark) — Bid's dark: near-black canvas, dark gray panels, tinted blue ---- */
    --canvas: #15181D;
    --panel: #1F2329;
    --panel-2: #262B32;
    --panel-border: rgba(255, 255, 255, 0.07);
    --control-bg: #2B3038;
    --control-hover-bg: #353B45;
    --control-active-bg: #404752;
    --hairline: rgba(255, 255, 255, 0.10);
    --hairline-strong: rgba(255, 255, 255, 0.18);
    --text-faint: #8B98AC;                   /* quiet blue-gray: ≥ 4.5:1 on every dark surface incl. --control-bg (was #7E8CA3) */
    --brand-text: #82AEF8;                   /* the brand blue lightened for text on dark: 7.3:1 on --panel, ≥ 4.7:1 on its washes and the rail's active item */
    --btn-primary-bg: #2563EB;               /* primary button fill (white text 4.6:1; #3B82F6 is only 3.7:1) */
    --btn-primary-hover-bg: #1D4ED8;
    --btn-danger-bg: #C42B22;                /* the dark --danger-color (#F98484) is a TEXT red: white on it is 2.5:1 */
    --btn-danger-hover-bg: #A3241C;
    --table-head-fg: #9DBDF9;                /* light blue header text (8:1 on --panel) */
    --table-head-rule: #3B82F6;
    --group-band-bg: #243245;
    --group-band-fg: #C6D8F7;
    --rail-fg: #C3CDDA;                      /* 8.3:1 on the dark header bar */
    --header-bar: #2B3038;                   /* Bid's dark bar (#2d2d2d), tinted */
    --header-tile-hover-bg: #5B6B82;
    --menu-border: #5A6576;
    --hsearch-key-edge: #7A8799;             /* the "/" keycap edge: 3.6:1 on the dark bar */
    --menu-hover-bg: #4A5566;                /* light text 7:1 */
    --menu-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
    --find-hit-bg: #5C4813;                  /* a dim amber the light text still reads on (8.1:1) */
    --find-hit-fg: #f6f6f8;
    --find-current-bg: #F59E0B;              /* the current match: dark text on amber (8.6:1) */
    --find-current-fg: #121317;
    --panel-shadow: 0 1px 2px rgba(0, 0, 0, 0.40), 0 4px 16px rgba(0, 0, 0, 0.30);
    --panel-shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.60), 0 2px 6px rgba(0, 0, 0, 0.40);
    --modal-backdrop: rgba(0, 0, 0, 0.60);
    --row-selected-bg: rgba(59, 130, 246, 0.28);
    --zebra-bg: rgba(255, 255, 255, 0.03);

    /* semantic (dark) */
    --success-color: #4ADE80; --success-bg: rgba(34, 197, 94, 0.18);
    --warning-color: #FBBF24; --warning-bg: rgba(245, 158, 66, 0.18);
    --danger-color: #F98484;  --danger-bg: rgba(239, 68, 68, 0.18);   /* was #F87171: 4.3:1 on its tint over --panel-2 */
    --info-color: #60A5FA;    --info-bg: rgba(59, 130, 246, 0.16);

    /* requisition rollup + per-line status (dark) */
    --status-stock-bg: rgba(148, 163, 184, 0.18);   --status-stock-fg: #CBD5E1;
    --status-pending-bg: rgba(59, 130, 246, 0.16);   --status-pending-fg: #93C5FD;
    --status-ordered-bg: rgba(245, 158, 66, 0.18);   --status-ordered-fg: #FBBF24;
    --status-received-bg: rgba(125, 168, 244, 0.22); --status-received-fg: #BFD4FB;
    --status-delivered-bg: rgba(34, 197, 94, 0.18);  --status-delivered-fg: #4ADE80;
    --status-cancelled-bg: rgba(239, 68, 68, 0.16);  --status-cancelled-fg: #F98484;

    /* Project section colors */
    --project-status-header-text: var(--font-color);
    --project-status-new-lead-bg: rgba(59, 130, 246, 0.18);
    --project-status-ready-for-pricing-bg: rgba(16, 185, 129, 0.18);
    --project-status-pricing-bg: rgba(245, 158, 11, 0.18);
    --project-status-awaiting-info-bg: rgba(168, 85, 247, 0.18);
    --project-status-ready-for-review-bg: rgba(236, 72, 153, 0.18);
    --project-status-sent-to-sales-bg: rgba(14, 165, 233, 0.18);
    --project-status-sent-to-customer-bg: rgba(34, 197, 94, 0.18);
    --project-status-waiting-on-subs-bg: rgba(251, 191, 36, 0.18);
    --project-status-won-bg: rgba(22, 163, 74, 0.22);
    --project-status-no-bid-bg: rgba(107, 114, 128, 0.20);
    --project-status-lost-bg: rgba(239, 68, 68, 0.20);
    --project-status-on-hold-dead-bg: rgba(75, 85, 99, 0.22);
    --project-status-redesign-bg: rgba(244, 63, 94, 0.18);
    --project-status-re-bid-bg: rgba(99, 102, 241, 0.18);
    --project-status-owner-direct-quote-bg: rgba(20, 184, 166, 0.18);

    /* Pie chart */
    --summary-material-color: #6ab7ff;
    --summary-hours-color: #f5c15c;
    --summary-install-color: #e05bd2;

    /* The same six hues stepped for the dark canvas (validated against #0F1115: CVD ΔE ≥ 8.4, all ≥ 3:1). */
    --chart-series-1: #3987e5;
    --chart-series-2: #d95926;
    --chart-series-3: #199e70;
    --chart-series-4: #c98500;
    --chart-series-5: #d55181;
    --chart-series-6: #008300;

    /* Look Ahead job colors, dark: the bright (400) steps under DARK ink, >= 6.8:1 for the ink and
       >= 5.7:1 against --panel. */
    --la-job-1: #38BDF8;  --la-job-2: #A78BFA;  --la-job-3: #F472B6;  --la-job-4: #34D399;
    --la-job-5: #FBBF24;  --la-job-6: #F87171;  --la-job-7: #60A5FA;  --la-job-8: #C084FC;
    --la-job-9: #4ADE80;  --la-job-10: #FB923C; --la-job-11: #22D3EE; --la-job-12: #E879F9;
    --la-job-ink: #0F1115;

    --app-switch-caddy-bg: #469249;
    --app-switch-caddy-border: #4CAF50;
    --app-switch-caddy-hover-bg: #609f62;
    --app-switch-caddy-hover-border: #66BB6A;

    /* Bid's own dark-mode primary is the light lavender, which is exactly the right text color here
       — the tint stays the same, the text brightens, same as --warning-color does. ~7.8:1 on the
       composited pill. */
    --bid-color: #d9cbe6;

    /* Landing-page screenshots swap to their dark-theme capture. */
    .shot--req-overview .shot-img { content: url("/caddy-hub/images/login/req-overview-dark.png"); }
    .shot--req-list .shot-img     { content: url("/caddy-hub/images/login/req-list-dark.png"); }
    .shot--catalog .shot-img      { content: url("/caddy-hub/images/login/catalog-dark.png"); }
    .shot--tracking .shot-img     { content: url("/caddy-hub/images/login/tracking-dark.png"); }
    .shot--projects .shot-img     { content: url("/caddy-hub/images/login/projects-dark.png"); }
    .shot--inventory .shot-img    { content: url("/caddy-hub/images/login/inventory-dark.png"); }
    .shot--scheduler .shot-img    { content: url("/caddy-hub/images/login/scheduler-dark.png"); }
    .shot--panel-shop .shot-img   { content: url("/caddy-hub/images/login/panel-shop-dark.png"); }
    /* The CADdy-Bid wordmark under the header logo: Bid's own dark art (lavender letters). Two <img>s
       rather than content: url(), because styles.md has logos referenced by <img src>. */
    /* The Hub wordmark, swapped the way Bid swaps its own (#logo-container img -> caddy-bid-dark.png):
       CADdy-Hub-dark-mode.png is CADdy-Hub.png with the lettering and the top arm of the C recolored to
       a light tint of the brand blue (Bid's dark logo does the same in light purple). */
    .ch-header__logo { content: url('/CADdy-Hub/logos/CADdy-Hub-dark-mode.png'); }
    .ch-brand__bidlogo--light { display: none; }
    .ch-brand__bidlogo--dark { display: block; }
    /* The brand kit's dark-mode loading art (tint top / Deep track) for the loaders and spinners. */
    .ch-loader, .wip-overlay__spin { background-image: url('/CADdy-Hub/logos/loading/CADdy-Hub-loader-dark-mode.svg'); }
    .ch-spinner, .chg-btnspin { background-image: url('/CADdy-Hub/logos/loading/CADdy-Hub-spinner-dark-mode.svg'); }
    #screensaver-logo {
        content: url('/caddy/images/logos/CADdy-Bid.png');
    }
    #logo-container img {
        content: url('/caddy/images/logos/caddy-bid-dark.png');
    }
    .app-link-image img {
        content: url('/caddy/images/login/dark desktop main.png')
    }
    .app-switch-banner-logo img {
        content: url('/caddy/images/logos/dark long logo.png');
    }
}

/* ---- ROLE TOKENS + LEGACY ALIASES (both themes) ----------------------------------------------
   Declared on BOTH :root and body.dark on purpose. A custom property that holds var(--x) is resolved
   on the element that declares it and then inherited as the RESULT, so an alias declared on :root
   alone would carry the LIGHT value into body.dark (that is how dark-mode eyebrows and the header bar
   used to stay light-theme blue/white). Re-declaring the aliases on body.dark makes each one resolve
   against the dark raw values above. Add a new alias here, never in one theme block only. */
:root,
body.dark {
    /* legacy names, repointed at the Bid-style roles so existing page CSS shifts with no edit */
    --background-color: var(--canvas);       /* page canvas */
    --surface: var(--panel);                 /* card / panel / popover surface */
    --surface-2: var(--panel-2);             /* alt / hover / read-only inside a panel */
    --card-bg: var(--panel);
    --card-border: var(--panel-border);
    --row-hover-bg: var(--brand-wash);

    /* app shell: the header bar and the left rail */
    --header-bar-bg: var(--header-bar);
    --header-bar-border: var(--hairline);
    --app-header-bg: var(--header-bar-bg);   /* legacy name */
    --app-header-border: var(--header-bar-border);
    /* The rail is the header bar's own gray, so the two read as one L-shaped frame round the page (Bid:
       both are its --sub-background-color). No edge of its own: the canvas next to it is the edge. Hover
       is a lighter wash; the active item is Bid's: a brand border and a lighter (brand) wash. */
    --rail-bg: var(--header-bar);
    --rail-border: var(--header-bar);
    --rail-hover-bg: var(--control-hover-bg);
    --rail-hover-fg: var(--font-color);
    --rail-active-bg: var(--brand-wash);
    --rail-active-fg: var(--brand-text);
    --rail-active-border: var(--primary-color);
    --eyebrow-color: var(--brand-text);      /* uppercase tracked labels */
    --nav-fg: var(--rail-fg);                /* legacy name */
    --nav-fg-active: var(--brand-text);      /* legacy name */
    /* the header search's filter tile: the dot that says a filter is on (Bid's .has-filters::after) */
    --filter-dot-bg: var(--primary-color);
    /* the header search at rest (search-polish): GitHub's quiet bordered box on the bar's gray. The edge is
       Bid's menu edge, the words and the magnifier the rail's own text color (6.9:1 light, 8.3:1 dark on the bar).
       Focused it is a form control on --panel; its panel is a raised --panel card. */
    --hsearch-border: var(--menu-border);
    --hsearch-border-hover: var(--secondary-color);
    --hsearch-fg: var(--rail-fg);
    --hsearch-key-border: var(--hsearch-key-edge);   /* GitHub's outlined "/" key (T1-5) */

    /* pill tabs (.ch-tabs / .ch-tabstrip > .ch-tab) */
    --tab-bg: var(--control-bg);
    --tab-hover-bg: var(--control-hover-bg);
    --tab-active-bg: var(--panel);
    --tab-active-fg: var(--brand-text);
    --tab-active-border: var(--primary-color);

    /* tables */
    --table-head-bg: var(--panel);           /* opaque: the header is sticky */
}

/* The window's own scrollbar belongs to the root element, which theme.js does not mark (it toggles
   body.dark), so the root follows the body. */
:root:has(> body.dark) { color-scheme: dark; }
