@exxatdesignux/ui 0.2.18 → 0.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/consumer-extras/AGENTS.md +76 -0
- package/consumer-extras/README.md +5 -1
- package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +14 -3
- package/consumer-extras/cursor-skills/exxat-consumer-app/SKILL.md +37 -0
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +21 -6
- package/consumer-extras/cursor-skills/exxat-focused-workflow-page/SKILL.md +57 -0
- package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +4 -2
- package/consumer-extras/patterns/consumer-app-pattern.md +39 -0
- package/consumer-extras/patterns/consumer-upgrade-checklist.md +20 -0
- package/consumer-extras/patterns/data-views-pattern.md +40 -3
- package/consumer-extras/patterns/focused-workflow-page-pattern.md +84 -0
- package/consumer-extras/patterns/shell-surface-elevation-pattern.md +5 -3
- package/package.json +2 -1
- package/src/components/ui/button-group.tsx +81 -0
- package/src/components/ui/button.tsx +4 -4
- package/src/globals.css +7 -1858
- package/src/theme.css +10 -1126
- package/src/tokens/README.md +15 -0
- package/src/tokens/base.css +337 -0
- package/src/tokens/high-contrast.css +1195 -0
- package/src/tokens/layers.css +224 -0
- package/src/tokens/tailwind-bridge.css +118 -0
- package/src/tokens/themes.css +201 -0
- package/template/AGENTS.md +60 -22
- package/template/app/(app)/dashboard/loading.tsx +3 -15
- package/template/app/(app)/dashboard/page.tsx +2 -14
- package/template/app/(app)/data-list/layout.tsx +43 -0
- package/template/app/(app)/data-list/page.tsx +2 -2
- package/template/app/(app)/examples/focused-workflow/page.tsx +5 -0
- package/template/app/(app)/examples/page.tsx +1 -0
- package/template/app/(app)/loading.tsx +1 -18
- package/template/app/(app)/question-bank/find/page.tsx +2 -1
- package/template/app/(app)/question-bank/library/page.tsx +2 -1
- package/template/app/(app)/question-bank/list/page.tsx +2 -1
- package/template/app/(app)/question-bank/new/page.tsx +15 -23
- package/template/app/(app)/question-bank/page.tsx +2 -1
- package/template/app/(app)/settings/page.tsx +4 -5
- package/template/app/globals.css +7 -1964
- package/template/components/app-route-loading.tsx +14 -0
- package/template/components/app-sidebar.tsx +70 -55
- package/template/components/data-views/index.ts +37 -9
- package/template/components/data-views/list-page-calendar-view.tsx +593 -0
- package/template/components/data-views/list-page-connected-view-body.tsx +66 -0
- package/template/components/data-views/list-page-folder-columns-panel.tsx +345 -0
- package/template/components/data-views/list-page-split-hub-chrome.tsx +8 -0
- package/template/components/examples/focused-workflow-showcase.tsx +183 -0
- package/template/components/list-hub-board-view.tsx +68 -0
- package/template/components/list-hub-client.tsx +186 -0
- package/template/components/list-hub-list-view.tsx +36 -0
- package/template/components/list-hub-panel-activator.tsx +8 -0
- package/template/components/list-hub-secondary-nav.tsx +121 -0
- package/template/components/list-hub-table.tsx +336 -0
- package/template/components/new-question-composer.tsx +6 -24
- package/template/components/product-switcher.tsx +3 -2
- package/template/components/question-bank-client.tsx +4 -1
- package/template/components/question-bank-folder-columns-panel.tsx +104 -0
- package/template/components/question-bank-table.tsx +143 -485
- package/template/components/secondary-panel/nav-link-rows.tsx +83 -0
- package/template/components/secondary-panel.tsx +4 -44
- package/template/components/secondary-panels/list-hub-panel.tsx +39 -0
- package/template/components/secondary-panels/question-bank-panel.tsx +39 -0
- package/template/components/secondary-panels/registry.tsx +15 -0
- package/template/components/settings-appearance-card.tsx +3 -2
- package/template/components/settings-client.tsx +59 -15
- package/template/components/settings-form-row.tsx +9 -4
- package/template/components/table-properties/drawer-button.tsx +13 -0
- package/template/components/table-properties/drawer.tsx +65 -4
- package/template/components/templates/focused-workflow-layouts.tsx +448 -0
- package/template/components/templates/focused-workflow-page-template.tsx +69 -0
- package/template/components/templates/list-page.tsx +29 -5
- package/template/components/templates/nested-secondary-panel-shell.tsx +2 -1
- package/template/components/templates/page-loading-shell.tsx +262 -0
- package/template/components/ui/button-group.tsx +1 -0
- package/template/docs/consumer-app-pattern.md +39 -0
- package/template/docs/data-views-pattern.md +40 -3
- package/template/docs/drawer-vs-dialog-pattern.md +3 -1
- package/template/docs/focused-workflow-page-pattern.md +84 -0
- package/template/docs/shell-surface-elevation-pattern.md +5 -3
- package/template/lib/command-menu-search-data.ts +11 -27
- package/template/lib/data-list-display-options.ts +16 -2
- package/template/lib/data-list-view-registry.ts +104 -0
- package/template/lib/data-list-view-surface.ts +15 -1
- package/template/lib/data-list-view.ts +10 -1
- package/template/lib/data-view-dashboard-storage.ts +38 -35
- package/template/lib/hub-connected-view-renderers.ts +58 -0
- package/template/lib/list-hub-nav.ts +121 -0
- package/template/lib/list-hub-supported-views.ts +10 -0
- package/template/lib/list-page-table-properties.ts +3 -7
- package/template/lib/list-status-badges.ts +4 -97
- package/template/lib/mock/list-hub-directory.ts +27 -0
- package/template/lib/mock/list-hub-kpi.ts +27 -0
- package/template/lib/mock/navigation.tsx +1 -0
- package/template/lib/page-loading-variant.ts +40 -0
- package/template/lib/question-bank-supported-views.ts +13 -0
- package/template/lib/table-state-lifecycle.ts +2 -2
- package/template/app/(app)/data-list/[id]/page.tsx +0 -44
- package/template/app/(app)/data-list/new/page.tsx +0 -34
- package/template/components/compliance-board-view.tsx +0 -142
- package/template/components/compliance-client.tsx +0 -92
- package/template/components/compliance-list-view.tsx +0 -54
- package/template/components/compliance-page-header.tsx +0 -89
- package/template/components/compliance-table.tsx +0 -612
- package/template/components/data-view-dashboard-charts-compliance.tsx +0 -963
- package/template/components/data-view-dashboard-charts-team.tsx +0 -971
- package/template/components/data-view-dashboard-charts.tsx +0 -1503
- package/template/components/new-placement-back-btn.tsx +0 -28
- package/template/components/new-placement-form.tsx +0 -1068
- package/template/components/placement-board-card.tsx +0 -262
- package/template/components/placement-detail.tsx +0 -438
- package/template/components/placements-board-view.tsx +0 -404
- package/template/components/placements-client.tsx +0 -252
- package/template/components/placements-list-view.tsx +0 -171
- package/template/components/placements-page-header.tsx +0 -166
- package/template/components/placements-table-cells.test.tsx +0 -22
- package/template/components/placements-table-cells.tsx +0 -173
- package/template/components/placements-table-columns.tsx +0 -640
- package/template/components/placements-table.tsx +0 -1642
- package/template/components/rotations-empty-state.tsx +0 -50
- package/template/components/rotations-panel-activator.tsx +0 -8
- package/template/components/sites-all-client.tsx +0 -154
- package/template/components/sites-board-view.tsx +0 -67
- package/template/components/sites-list-view.tsx +0 -42
- package/template/components/sites-table.tsx +0 -382
- package/template/components/team-board-view.tsx +0 -122
- package/template/components/team-client.tsx +0 -100
- package/template/components/team-list-view.tsx +0 -59
- package/template/components/team-page-header.tsx +0 -92
- package/template/components/team-table.tsx +0 -693
- package/template/lib/data-view-dashboard-placements-layout.ts +0 -215
- package/template/lib/mock/compliance-kpi.ts +0 -61
- package/template/lib/mock/compliance.ts +0 -146
- package/template/lib/mock/placements-kpi.ts +0 -134
- package/template/lib/mock/placements.ts +0 -183
- package/template/lib/mock/sites-directory.ts +0 -16
- package/template/lib/mock/sites-kpi.ts +0 -25
- package/template/lib/mock/team-kpi.ts +0 -60
- package/template/lib/mock/team.ts +0 -118
- package/template/lib/placement-board-card-layout.ts +0 -79
- package/template/lib/placement-lifecycle.ts +0 -5
package/src/globals.css
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
EXXAT DESIGN SYSTEM — globals.css
|
|
3
|
-
|
|
4
|
-
Standard: WCAG 2.1 Level AA
|
|
5
|
-
• Text contrast ≥ 4.5 : 1 (SC 1.4.3)
|
|
6
|
-
• UI control contrast ≥ 3 : 1 (SC 1.4.11)
|
|
7
|
-
• Focus ring ≥ 3 : 1 (SC 2.4.11)
|
|
8
|
-
• Touch targets ≥ 44 × 44 px (SC 2.5.5 / mobile)
|
|
2
|
+
EXXAT DESIGN SYSTEM — globals.css (entry)
|
|
3
|
+
Token modules: ./tokens/*.css — structural split only; values unchanged.
|
|
9
4
|
========================================================================== */
|
|
10
5
|
|
|
11
6
|
@import "tailwindcss";
|
|
12
7
|
@import "tw-animate-css";
|
|
13
|
-
/* Inter is loaded via next/font/google in layout.tsx — no @import needed here */
|
|
14
8
|
|
|
15
9
|
/* RTL layout direction support */
|
|
16
10
|
@custom-variant dark (&:is(.dark *));
|
|
@@ -18,1853 +12,8 @@
|
|
|
18
12
|
/* High-contrast variant — in-app High or Windows (JSON) contrast */
|
|
19
13
|
@custom-variant hc (&:is([data-contrast="high"] *, [data-contrast="windows"] *));
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@
|
|
25
|
-
|
|
26
|
-
--font-heading: "ivypresto-text";
|
|
27
|
-
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
|
|
28
|
-
/* Minimum product text: 11px — use `text-xs` or larger; avoid arbitrary classes below 11px */
|
|
29
|
-
--text-xs: 0.6875rem; /* 11px at 16px root */
|
|
30
|
-
|
|
31
|
-
/* Semantic color map */
|
|
32
|
-
--color-background: var(--background);
|
|
33
|
-
--color-foreground: var(--foreground);
|
|
34
|
-
--color-card: var(--card);
|
|
35
|
-
--color-card-foreground: var(--card-foreground);
|
|
36
|
-
--color-popover: var(--popover);
|
|
37
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
38
|
-
--color-primary: var(--primary);
|
|
39
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
40
|
-
--color-secondary: var(--secondary);
|
|
41
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
42
|
-
--color-muted: var(--muted);
|
|
43
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
44
|
-
--color-accent: var(--accent);
|
|
45
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
46
|
-
--color-destructive: var(--destructive);
|
|
47
|
-
--color-destructive-foreground: var(--destructive-foreground);
|
|
48
|
-
--color-border: var(--border);
|
|
49
|
-
--color-border-control: var(--border-control);
|
|
50
|
-
--color-input: var(--input);
|
|
51
|
-
--color-input-background: var(--input-background);
|
|
52
|
-
--color-ring: var(--ring);
|
|
53
|
-
/* Modal / sheet / drawer scrim */
|
|
54
|
-
--color-overlay: var(--overlay);
|
|
55
|
-
|
|
56
|
-
/* Chart tokens */
|
|
57
|
-
--color-chart-1: var(--chart-1);
|
|
58
|
-
--color-chart-2: var(--chart-2);
|
|
59
|
-
--color-chart-3: var(--chart-3);
|
|
60
|
-
--color-chart-4: var(--chart-4);
|
|
61
|
-
--color-chart-5: var(--chart-5);
|
|
62
|
-
|
|
63
|
-
/* Chip / badge tokens (AA-compliant on light bg: ≥ 4.5:1) */
|
|
64
|
-
--color-chip-1: var(--chip-1);
|
|
65
|
-
--color-chip-2: var(--chip-2);
|
|
66
|
-
--color-chip-3: var(--chip-3);
|
|
67
|
-
--color-chip-4: var(--chip-4);
|
|
68
|
-
--color-chip-5: var(--chip-5);
|
|
69
|
-
--color-chip-destructive: var(--chip-destructive);
|
|
70
|
-
|
|
71
|
-
/* Brand accent + Exxat One tint scale (see :root --brand-*) */
|
|
72
|
-
--color-brand: var(--brand-color);
|
|
73
|
-
--color-brand-dark: var(--brand-color-dark);
|
|
74
|
-
--color-brand-foreground: var(--brand-foreground);
|
|
75
|
-
--color-brand-tint: var(--brand-tint);
|
|
76
|
-
--color-brand-tint-light: var(--brand-tint-light);
|
|
77
|
-
--color-brand-tint-subtle: var(--brand-tint-subtle);
|
|
78
|
-
--color-brand-color-light: var(--brand-color-light);
|
|
79
|
-
--color-brand-deep: var(--brand-color-deep);
|
|
80
|
-
|
|
81
|
-
/* Prism banner highlight */
|
|
82
|
-
--color-banner-prism: var(--banner-prism-bg);
|
|
83
|
-
|
|
84
|
-
/* Sidebar */
|
|
85
|
-
--color-sidebar: var(--sidebar);
|
|
86
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
87
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
88
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
89
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
90
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
91
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
92
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
93
|
-
/* WCAG 1.4.3 — always mixed against real --sidebar (lavender / rose / dark) */
|
|
94
|
-
--color-sidebar-section-label: var(--sidebar-section-label-foreground);
|
|
95
|
-
|
|
96
|
-
/* Interactive hover — single source for ghost controls, lists, table chrome */
|
|
97
|
-
--color-interactive-hover: var(--interactive-hover);
|
|
98
|
-
--color-interactive-hover-foreground: var(--interactive-hover-foreground);
|
|
99
|
-
--color-interactive-hover-subtle: var(--interactive-hover-subtle);
|
|
100
|
-
--color-interactive-hover-soft: var(--interactive-hover-soft);
|
|
101
|
-
--color-interactive-hover-medium: var(--interactive-hover-medium);
|
|
102
|
-
--color-interactive-hover-strong: var(--interactive-hover-strong);
|
|
103
|
-
--color-interactive-hover-row: var(--interactive-hover-row);
|
|
104
|
-
|
|
105
|
-
/* DataTable — opaque surfaces for pinned/sticky cells and row states */
|
|
106
|
-
--color-dt-row-bg: var(--dt-row-bg);
|
|
107
|
-
--color-dt-row-hover: var(--dt-row-hover);
|
|
108
|
-
--color-dt-row-selected: var(--dt-row-selected);
|
|
109
|
-
--color-dt-row-selected-fg: var(--dt-row-selected-fg);
|
|
110
|
-
--color-dt-header-bg: var(--dt-header-bg);
|
|
111
|
-
--color-dt-group-bg: var(--dt-group-bg);
|
|
112
|
-
--color-dt-new-row-bg: var(--dt-new-row-bg);
|
|
113
|
-
--color-dt-new-row-border: var(--dt-new-row-border);
|
|
114
|
-
|
|
115
|
-
/* Border-radius scale (4 px base → 8 px default) */
|
|
116
|
-
--radius-sm: 4px;
|
|
117
|
-
--radius-md: 8px;
|
|
118
|
-
--radius-lg: 12px;
|
|
119
|
-
--radius-xl: 16px;
|
|
120
|
-
--radius-2xl: 20px;
|
|
121
|
-
--radius-3xl: 24px;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/* --------------------------------------------------------------------------
|
|
125
|
-
Text size (Settings → Appearance) — see apps/web app copy for rationale.
|
|
126
|
-
-------------------------------------------------------------------------- */
|
|
127
|
-
html[data-text-size="compact"] {
|
|
128
|
-
font-size: 94%;
|
|
129
|
-
--text-xs: 0.7333rem;
|
|
130
|
-
}
|
|
131
|
-
html[data-text-size="large"] {
|
|
132
|
-
font-size: 112.5%;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/* ==========================================================================
|
|
136
|
-
:root — Exxat One · Light Mode (brand hue 286.1)
|
|
137
|
-
All contrast ratios verified against oklch(1 0 0) white background.
|
|
138
|
-
========================================================================== */
|
|
139
|
-
:root {
|
|
140
|
-
/* font-size intentionally NOT overridden here.
|
|
141
|
-
Shadcn components assume 1rem = 16px (browser default).
|
|
142
|
-
Overriding to 87.5% / 14px breaks rem-based spacing on all devices,
|
|
143
|
-
and compounds incorrectly at Windows 150% system zoom.
|
|
144
|
-
If a compact 14px density is needed, apply it at the component/page level
|
|
145
|
-
via a scoped class, not globally on :root. */
|
|
146
|
-
/* Minimum readable UI copy: 11px (`text-xs` / --text-xs). Do not use smaller arbitrary sizes. */
|
|
147
|
-
|
|
148
|
-
/* ── Typography ─────────────────────────────────────────────── */
|
|
149
|
-
/* Ivy Presto loaded via Adobe Fonts Kit wuk5wqn (use.typekit.net) */
|
|
150
|
-
--font-heading: "ivypresto-text";
|
|
151
|
-
|
|
152
|
-
/* ── Brand — Exxat One (hue 286.1) ─────────────────────────── */
|
|
153
|
-
/* Primary surface — requested token */
|
|
154
|
-
--brand-tint: oklch(0.9676 0.016 286.1);
|
|
155
|
-
/* Lighter / darker washes (same hue) for nested UI & hovers */
|
|
156
|
-
--brand-tint-light: oklch(0.993 0.007 286.1);
|
|
157
|
-
--brand-tint-subtle: oklch(0.935 0.024 286.1);
|
|
158
|
-
/* Interactive accent + scale (readable on white; pairs with --brand-tint) */
|
|
159
|
-
--brand-color: oklch(0.50 0.14 286.1);
|
|
160
|
-
--brand-color-light: oklch(0.78 0.09 286.1);
|
|
161
|
-
--brand-color-dark: oklch(0.38 0.11 286.1);
|
|
162
|
-
--brand-color-deep: oklch(0.28 0.085 286.1);
|
|
163
|
-
--brand-foreground: oklch(0.985 0 0);
|
|
164
|
-
/* Fixed swatches for brand picker (Exxat One vs Prism), independent of active theme */
|
|
165
|
-
--brand-preview-one: var(--brand-tint);
|
|
166
|
-
--brand-preview-prism: oklch(0.57 0.24 342);
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Ask Leo panel tints (same mixes as the vertical wash). Use for blobs, cards, etc.
|
|
170
|
-
* `--leo-surface-gradient` is the full linear wash on `AskLeoSidebar`.
|
|
171
|
-
*/
|
|
172
|
-
--leo-surface-tint-a: color-mix(in oklch, var(--brand-color) 4%, var(--background));
|
|
173
|
-
--leo-surface-tint-b: color-mix(in oklch, var(--brand-color) 8%, var(--background));
|
|
174
|
-
--leo-surface-gradient: linear-gradient(180deg, var(--leo-surface-tint-a) 0%, var(--leo-surface-tint-b) 100%);
|
|
175
|
-
|
|
176
|
-
/* KeyMetrics `variant="flat"` — no band surface; bottom brand glow only (OKLCH). */
|
|
177
|
-
--key-metrics-flat-cell-bg: transparent;
|
|
178
|
-
--key-metrics-flat-divider: color-mix(in oklch, var(--sidebar-border) 55%, transparent);
|
|
179
|
-
--key-metrics-flat-band-radial: radial-gradient(
|
|
180
|
-
ellipse 120% 68% at 50% 100%,
|
|
181
|
-
color-mix(in oklch, var(--brand-color) 20%, transparent) 0%,
|
|
182
|
-
color-mix(in oklch, var(--brand-color) 8%, transparent) 42%,
|
|
183
|
-
transparent 72%
|
|
184
|
-
);
|
|
185
|
-
--key-metrics-flat-band-shadow: none;
|
|
186
|
-
--key-metrics-card-glow-radial: radial-gradient(
|
|
187
|
-
ellipse 110% 90% at 50% 100%,
|
|
188
|
-
color-mix(in oklch, var(--brand-color) 18%, transparent) 0%,
|
|
189
|
-
transparent 65%
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
/* ── Surfaces ────────────────────────────────────────────────── */
|
|
193
|
-
--background: oklch(1 0 0);
|
|
194
|
-
--foreground: oklch(0.145 0 0); /* ≈ #1A1A1A — 17:1 on white ✓ */
|
|
195
|
-
--card: oklch(1 0 0);
|
|
196
|
-
--card-foreground: oklch(0.145 0 0);
|
|
197
|
-
--popover: oklch(1 0 0);
|
|
198
|
-
--popover-foreground: oklch(0.145 0 0);
|
|
199
|
-
|
|
200
|
-
/* ── Primary ─────────────────────────────────────────────────── */
|
|
201
|
-
/* Default / ghost / solid primary actions — neutral charcoal (style guide) */
|
|
202
|
-
--primary: oklch(0.3457 0.0052 286.13);
|
|
203
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
204
|
-
|
|
205
|
-
/* ── Secondary / Muted / Accent ──────────────────────────────── */
|
|
206
|
-
--secondary: oklch(0.95 0.0058 264.53);
|
|
207
|
-
--secondary-foreground: oklch(0.082 0 0);
|
|
208
|
-
--muted: oklch(0.945 0.002 270);
|
|
209
|
-
--muted-foreground: oklch(0.50 0.012 270); /* 5.5:1 on white ✓ */
|
|
210
|
-
--accent: oklch(0.925 0.005 260);
|
|
211
|
-
--accent-foreground: oklch(0.082 0 0);
|
|
212
|
-
|
|
213
|
-
/* ── Destructive ─────────────────────────────────────────────── */
|
|
214
|
-
/* oklch(0.55 0.22 25) ≈ #C0392B — 5.1:1 on white ✓ */
|
|
215
|
-
--destructive: oklch(0.55 0.22 25);
|
|
216
|
-
--destructive-foreground: oklch(1 0 0);
|
|
217
|
-
|
|
218
|
-
/* ── Borders ─────────────────────────────────────────────────── */
|
|
219
|
-
/* Decorative: cards, dividers — no AA contrast requirement */
|
|
220
|
-
--border: oklch(0.92 0.002 270);
|
|
221
|
-
|
|
222
|
-
/* Form-field boundary — WCAG 1.4.11 requires 3:1 against bg.
|
|
223
|
-
--border-control-3: L=0.62 ≈ #90929A → borderline; use with care.
|
|
224
|
-
--border-control-35: L=0.25 → ≥ 3.5:1 — recommended for inputs. */
|
|
225
|
-
--border-control: oklch(0.82 0.004 270); /* subtle (layout use only) */
|
|
226
|
-
--border-control-3: oklch(0.6196 0.0092 270); /* ≈ 3:1 on white (minimum) */
|
|
227
|
-
--border-control-35: oklch(0.25 0.01 270); /* ≈ 3.5:1+ (recommended) */
|
|
228
|
-
--control-border: var(--border-control-3); /* default form-field border */
|
|
229
|
-
|
|
230
|
-
/* ── Input ───────────────────────────────────────────────────── */
|
|
231
|
-
/* 3:1 on white — WCAG 1.4.11 compliant for interactive element borders */
|
|
232
|
-
--input: oklch(0.6694 0.0063 264.52);
|
|
233
|
-
--input-background: oklch(0.97 0.002 270);
|
|
234
|
-
|
|
235
|
-
/* ── Focus ring ──────────────────────────────────────────────── */
|
|
236
|
-
/* 3:1+ contrast on both light & dark backgrounds (WCAG 2.4.11) */
|
|
237
|
-
--ring: oklch(0.25 0 0);
|
|
238
|
-
|
|
239
|
-
/* ── Charts ──────────────────────────────────────────────────── */
|
|
240
|
-
--chart-1: oklch(0.55 0.22 264.116);
|
|
241
|
-
--chart-2: oklch(0.48 0.15 184.704);
|
|
242
|
-
--chart-3: oklch(0.32 0.08 227.392);
|
|
243
|
-
--chart-4: oklch(0.65 0.18 84.429);
|
|
244
|
-
--chart-5: oklch(0.58 0.18 70.08);
|
|
245
|
-
|
|
246
|
-
/* ── Chip / Badge ────────────────────────────────────────────── */
|
|
247
|
-
/* AA-compliant on white: all ≥ 4.5:1 (WCAG 1.4.3) */
|
|
248
|
-
--chip-1: oklch(0.38 0.18 264); /* indigo */
|
|
249
|
-
--chip-2: oklch(0.35 0.14 184); /* teal */
|
|
250
|
-
--chip-3: oklch(0.32 0.08 227); /* slate */
|
|
251
|
-
--chip-4: oklch(0.42 0.12 84); /* amber */
|
|
252
|
-
--chip-5: oklch(0.42 0.14 70); /* orange */
|
|
253
|
-
--chip-destructive: oklch(0.40 0.18 25); /* red */
|
|
254
|
-
|
|
255
|
-
/* ── Prism promo banner ──────────────────────────────────────── */
|
|
256
|
-
/* Rose hue 343 — used universally regardless of active theme */
|
|
257
|
-
--banner-prism-bg: oklch(0.97 0.02 343);
|
|
258
|
-
|
|
259
|
-
/* ── Sidebar — Exxat One brand tint ───────────────────────────── */
|
|
260
|
-
--sidebar: var(--brand-tint);
|
|
261
|
-
--sidebar-foreground: oklch(0.145 0 0);
|
|
262
|
-
--sidebar-primary: oklch(0.082 0 0);
|
|
263
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
264
|
-
--sidebar-accent: oklch(0.945 0.025 286.1);
|
|
265
|
-
--sidebar-accent-foreground: oklch(0.3457 0.0052 286.13);
|
|
266
|
-
--sidebar-border: oklch(0.92 0.025 286.1);
|
|
267
|
-
--sidebar-ring: oklch(0.25 0 0);
|
|
268
|
-
/* Nav section titles — ≥4.5:1 vs --sidebar (not vs page white) */
|
|
269
|
-
--sidebar-section-label-foreground: color-mix(in oklch, var(--sidebar-foreground) 58%, var(--sidebar));
|
|
270
|
-
/* Nested secondary rail — elevation 1: brand wash, lighter than `--brand-tint` / sidebar. */
|
|
271
|
-
--secondary-panel-bg: color-mix(in oklch, var(--background) 40%, var(--brand-tint-light) 60%);
|
|
272
|
-
|
|
273
|
-
/* Browser UI (meta theme-color) — aligned with --brand-tint */
|
|
274
|
-
--theme-color-chrome: #f3f2f8;
|
|
275
|
-
|
|
276
|
-
/* ── Border radius ───────────────────────────────────────────── */
|
|
277
|
-
--radius: 0.5rem; /* 8px base */
|
|
278
|
-
|
|
279
|
-
/* ── Density / touch targets ─────────────────────────────────── */
|
|
280
|
-
--scaling: 1;
|
|
281
|
-
--control-height: calc(40px * var(--scaling));
|
|
282
|
-
--control-height-sm: calc(32px * var(--scaling));
|
|
283
|
-
/* WCAG 2.5.5 — minimum 44×44 px touch target (mobile only) */
|
|
284
|
-
--control-height-touch: 44px;
|
|
285
|
-
--control-padding-y: calc(8px * var(--scaling));
|
|
286
|
-
--control-padding-x: calc(12px * var(--scaling));
|
|
287
|
-
--table-row-height: calc(48px * var(--scaling));
|
|
288
|
-
|
|
289
|
-
/* ── Interactive hover (ties to --muted / --accent — theme overrides apply) ─ */
|
|
290
|
-
--interactive-hover: var(--muted);
|
|
291
|
-
--interactive-hover-foreground: var(--foreground);
|
|
292
|
-
--interactive-hover-subtle: color-mix(in oklch, var(--muted) 50%, var(--background));
|
|
293
|
-
--interactive-hover-soft: color-mix(in oklch, var(--muted) 40%, var(--background));
|
|
294
|
-
--interactive-hover-medium: color-mix(in oklch, var(--muted) 60%, var(--background));
|
|
295
|
-
--interactive-hover-strong: color-mix(in oklch, var(--muted) 70%, var(--background));
|
|
296
|
-
--interactive-hover-row: color-mix(in oklch, var(--accent) 50%, var(--background));
|
|
297
|
-
|
|
298
|
-
/* ── DataTable — opaque row/cell surfaces (pinned cells MUST be opaque) ── */
|
|
299
|
-
--dt-row-bg: var(--background);
|
|
300
|
-
--dt-row-hover: oklch(0.972 0.001 270);
|
|
301
|
-
--dt-row-selected: oklch(0.962 0.003 260);
|
|
302
|
-
--dt-row-selected-fg: var(--foreground);
|
|
303
|
-
--dt-header-bg: var(--background);
|
|
304
|
-
--dt-group-bg: oklch(0.972 0.001 270);
|
|
305
|
-
--dt-new-row-bg: oklch(from var(--brand-color) 0.985 0.006 h);
|
|
306
|
-
--dt-new-row-border: var(--brand-color);
|
|
307
|
-
|
|
308
|
-
/* ── Transitions ─────────────────────────────────────────────── */
|
|
309
|
-
--transition-fast: 0.15s ease;
|
|
310
|
-
--transition-normal: 0.25s ease-in-out;
|
|
311
|
-
--transition-colors: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
|
|
312
|
-
|
|
313
|
-
/* ── Shadows ─────────────────────────────────────────────────── */
|
|
314
|
-
--shadow-sm: oklch(0 0 0 / 0.08) 0px 1px 2px 0px;
|
|
315
|
-
--shadow-md: oklch(0 0 0 / 0.08) 0px 2px 4px -1px, oklch(0 0 0 / 0.06) 0px 1px 2px;
|
|
316
|
-
--shadow-lg: oklch(0 0 0 / 0.10) 0px 4px 8px -2px, oklch(0 0 0 / 0.06) 0px 2px 4px;
|
|
317
|
-
|
|
318
|
-
/* ── Sticky column edge fade (data tables) ───────────────────── */
|
|
319
|
-
--sticky-edge-fade: oklch(0 0 0 / 0.08);
|
|
320
|
-
|
|
321
|
-
/* ── Overlay scrim (Sheet / Drawer / Dialog) ─────────────────── */
|
|
322
|
-
/* Softer than raw bg-black/10; follows foreground hue (not pure black) */
|
|
323
|
-
--overlay: color-mix(in oklch, var(--foreground) 5%, transparent);
|
|
324
|
-
|
|
325
|
-
/* ── Avatar initials (table) ───────────────────────────────────── */
|
|
326
|
-
/* Soft brand wash + brand ink — no black fills; ≥4.5:1 on white rows */
|
|
327
|
-
--avatar-initials-bg: color-mix(in oklch, var(--brand-color) 14%, oklch(1 0 0));
|
|
328
|
-
--avatar-initials-fg: var(--brand-color-dark);
|
|
329
|
-
|
|
330
|
-
/* ── KPI insight severity (KeyMetrics) ────────────────────────── */
|
|
331
|
-
--insight-severity-warning-bg: color-mix(in oklch, var(--chart-4) 15%, transparent);
|
|
332
|
-
--insight-severity-warning-fg: color-mix(in oklch, var(--chart-4) 75%, var(--foreground));
|
|
333
|
-
--insight-severity-info-bg: color-mix(in oklch, var(--chart-1) 14%, transparent);
|
|
334
|
-
--insight-severity-info-fg: color-mix(in oklch, var(--chart-1) 75%, var(--foreground));
|
|
335
|
-
|
|
336
|
-
/* ── Tinted icon discs — soft wash (≈14% tint); contrast from fg tokens */
|
|
337
|
-
--icon-disc-chart-2-bg: color-mix(in oklch, var(--chart-2) 14%, transparent);
|
|
338
|
-
--icon-disc-chart-2-fg: var(--chip-2);
|
|
339
|
-
--icon-disc-chart-4-bg: color-mix(in oklch, var(--chart-4) 14%, transparent);
|
|
340
|
-
--icon-disc-chart-4-fg: var(--chip-4);
|
|
341
|
-
--icon-disc-brand-bg: color-mix(in oklch, var(--brand-color) 12%, transparent);
|
|
342
|
-
--icon-disc-brand-fg: var(--brand-color-dark);
|
|
343
|
-
--icon-disc-danger-bg: color-mix(in oklch, var(--destructive) 14%, transparent);
|
|
344
|
-
--icon-disc-danger-fg: var(--chip-destructive);
|
|
345
|
-
|
|
346
|
-
/* ── Conditional formatting rule backgrounds (table drawer) ─── */
|
|
347
|
-
--conditional-rule-green: color-mix(in oklch, var(--chart-2) 22%, transparent);
|
|
348
|
-
--conditional-rule-yellow: color-mix(in oklch, var(--chart-4) 30%, transparent);
|
|
349
|
-
--conditional-rule-blue: color-mix(in oklch, var(--chart-1) 22%, transparent);
|
|
350
|
-
--conditional-rule-red: color-mix(in oklch, var(--destructive) 22%, transparent);
|
|
351
|
-
--conditional-rule-purple: color-mix(in oklch, var(--brand-color) 22%, transparent);
|
|
352
|
-
--conditional-rule-orange: color-mix(in oklch, var(--chart-5) 25%, transparent);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
/* ==========================================================================
|
|
356
|
-
Dark Mode — Exxat One base (neutral surfaces; brand uses --brand-*)
|
|
357
|
-
========================================================================== */
|
|
358
|
-
.dark {
|
|
359
|
-
--sticky-edge-fade: oklch(0 0 0 / 0.32);
|
|
360
|
-
|
|
361
|
-
/* Canvas — charcoal grey (not near-black) */
|
|
362
|
-
--background: oklch(0.20 0.008 270);
|
|
363
|
-
--foreground: oklch(0.985 0 0);
|
|
364
|
-
--card: oklch(0.255 0.008 270);
|
|
365
|
-
--card-foreground: oklch(0.985 0 0);
|
|
366
|
-
--popover: oklch(0.255 0.008 270);
|
|
367
|
-
--popover-foreground: oklch(0.985 0 0);
|
|
368
|
-
--primary: oklch(0.985 0 0);
|
|
369
|
-
--primary-foreground: oklch(0.3457 0.0052 286.13);
|
|
370
|
-
--secondary: oklch(0.31 0.04 270);
|
|
371
|
-
--secondary-foreground: oklch(0.985 0 0);
|
|
372
|
-
--muted: oklch(0.31 0.04 270);
|
|
373
|
-
--muted-foreground: oklch(0.72 0.012 270); /* ≥ 4.5:1 on dark bg ✓ */
|
|
374
|
-
--accent: oklch(0.33 0.06 270);
|
|
375
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
376
|
-
--destructive: oklch(0.65 0.20 25); /* brighter for dark bg */
|
|
377
|
-
--destructive-foreground: oklch(0.10 0 0);
|
|
378
|
-
|
|
379
|
-
/* KeyMetrics flat band — no surface; bottom brand glow only (OKLCH). */
|
|
380
|
-
--key-metrics-flat-cell-bg: transparent;
|
|
381
|
-
--key-metrics-flat-band-radial: radial-gradient(
|
|
382
|
-
ellipse 120% 68% at 50% 100%,
|
|
383
|
-
color-mix(in oklch, var(--brand-color) 26%, transparent) 0%,
|
|
384
|
-
color-mix(in oklch, var(--brand-color) 10%, transparent) 42%,
|
|
385
|
-
transparent 72%
|
|
386
|
-
);
|
|
387
|
-
--key-metrics-flat-band-shadow: none;
|
|
388
|
-
--key-metrics-card-glow-radial: radial-gradient(
|
|
389
|
-
ellipse 110% 90% at 50% 100%,
|
|
390
|
-
color-mix(in oklch, var(--brand-color) 22%, transparent) 0%,
|
|
391
|
-
transparent 62%
|
|
392
|
-
);
|
|
393
|
-
|
|
394
|
-
/* Borders — visible but not washed out on dark surfaces */
|
|
395
|
-
--border: oklch(0.38 0.008 270);
|
|
396
|
-
--border-control: oklch(0.72 0.012 270);
|
|
397
|
-
--border-control-3: oklch(0.78 0.012 270);
|
|
398
|
-
--border-control-35: oklch(0.75 0.012 270);
|
|
399
|
-
--control-border: var(--border-control-3);
|
|
400
|
-
|
|
401
|
-
--input: oklch(0.72 0.012 270);
|
|
402
|
-
--input-background: oklch(0.255 0 0);
|
|
403
|
-
|
|
404
|
-
/* Focus ring — 3:1+ on dark bg */
|
|
405
|
-
--ring: oklch(0.85 0 0);
|
|
406
|
-
|
|
407
|
-
/* Charts — higher lightness for dark surfaces */
|
|
408
|
-
--chart-1: oklch(0.70 0.22 264.376);
|
|
409
|
-
--chart-2: oklch(0.75 0.15 162.48);
|
|
410
|
-
--chart-3: oklch(0.78 0.12 227.392);
|
|
411
|
-
--chart-4: oklch(0.80 0.18 84.429);
|
|
412
|
-
--chart-5: oklch(0.75 0.18 70.08);
|
|
413
|
-
|
|
414
|
-
/* Chips — AA-compliant on dark bg (L raised) */
|
|
415
|
-
--chip-1: oklch(0.72 0.18 264);
|
|
416
|
-
--chip-2: oklch(0.72 0.14 184);
|
|
417
|
-
--chip-3: oklch(0.78 0.12 227);
|
|
418
|
-
--chip-4: oklch(0.78 0.14 84);
|
|
419
|
-
--chip-5: oklch(0.78 0.16 70);
|
|
420
|
-
--chip-destructive: oklch(0.72 0.18 25);
|
|
421
|
-
|
|
422
|
-
/* Tinted icon discs — same soft transparency wash; fg stays readable on dark canvas */
|
|
423
|
-
--icon-disc-chart-2-bg: color-mix(in oklch, var(--chart-2) 14%, transparent);
|
|
424
|
-
--icon-disc-chart-2-fg: color-mix(in oklch, var(--foreground) 10%, var(--chart-2));
|
|
425
|
-
--icon-disc-chart-4-bg: color-mix(in oklch, var(--chart-4) 14%, transparent);
|
|
426
|
-
--icon-disc-chart-4-fg: color-mix(in oklch, var(--foreground) 10%, var(--chart-4));
|
|
427
|
-
--icon-disc-brand-bg: color-mix(in oklch, var(--brand-color) 12%, transparent);
|
|
428
|
-
--icon-disc-brand-fg: color-mix(in oklch, var(--foreground) 8%, var(--brand-color));
|
|
429
|
-
--icon-disc-danger-bg: color-mix(in oklch, var(--destructive) 14%, transparent);
|
|
430
|
-
--icon-disc-danger-fg: color-mix(in oklch, var(--foreground) 8%, var(--destructive));
|
|
431
|
-
|
|
432
|
-
/* Sidebar */
|
|
433
|
-
--sidebar: oklch(0.245 0.015 270);
|
|
434
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
435
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
436
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
437
|
-
--sidebar-accent: oklch(0.30 0.012 270);
|
|
438
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
439
|
-
--sidebar-border: oklch(0.38 0.010 270);
|
|
440
|
-
--sidebar-ring: oklch(0.85 0 0);
|
|
441
|
-
--sidebar-section-label-foreground: color-mix(in oklch, var(--sidebar-foreground) 48%, var(--sidebar));
|
|
442
|
-
/* Nested secondary rail — elevation 1: brand stack, lifted toward `--card` / page. */
|
|
443
|
-
--secondary-panel-bg: color-mix(in oklch, var(--card) 32%, var(--brand-tint) 68%);
|
|
444
|
-
--theme-color-chrome: #2f2d36;
|
|
445
|
-
|
|
446
|
-
/* Lifted scrim on dark — white-tinted veil, not heavy black */
|
|
447
|
-
--overlay: color-mix(in oklch, var(--foreground) 10%, transparent);
|
|
448
|
-
|
|
449
|
-
/* Mid lavender chip + light text — no black circle; contrasts on dark table rows */
|
|
450
|
-
--avatar-initials-bg: color-mix(in oklch, var(--brand-color) 38%, oklch(0.40 0.05 286.1));
|
|
451
|
-
--avatar-initials-fg: oklch(0.99 0.01 286.1);
|
|
452
|
-
|
|
453
|
-
/* DataTable — opaque surfaces for dark mode */
|
|
454
|
-
--dt-row-bg: var(--background);
|
|
455
|
-
--dt-row-hover: oklch(0.24 0.01 270);
|
|
456
|
-
--dt-row-selected: oklch(0.27 0.02 270);
|
|
457
|
-
--dt-row-selected-fg: var(--foreground);
|
|
458
|
-
--dt-header-bg: var(--background);
|
|
459
|
-
--dt-group-bg: oklch(0.24 0.01 270);
|
|
460
|
-
--dt-new-row-bg: oklch(from var(--brand-color) 0.22 0.02 h);
|
|
461
|
-
--dt-new-row-border: var(--brand-color);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/* ==========================================================================
|
|
465
|
-
Theme: Exxat One · Lavender (explicit — also applied as :root default)
|
|
466
|
-
Usage: <html class="theme-one"> or <html class="theme-lavender">
|
|
467
|
-
========================================================================== */
|
|
468
|
-
.theme-one,
|
|
469
|
-
.theme-lavender {
|
|
470
|
-
--brand-tint: oklch(0.9676 0.016 286.1);
|
|
471
|
-
--brand-tint-light: oklch(0.993 0.007 286.1);
|
|
472
|
-
--brand-tint-subtle: oklch(0.935 0.024 286.1);
|
|
473
|
-
--brand-color: oklch(0.50 0.14 286.1);
|
|
474
|
-
--brand-color-light: oklch(0.78 0.09 286.1);
|
|
475
|
-
--brand-color-dark: oklch(0.38 0.11 286.1);
|
|
476
|
-
--brand-color-deep: oklch(0.28 0.085 286.1);
|
|
477
|
-
--ring: var(--brand-color-dark);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/* Light surfaces only — must NOT override .dark (otherwise muted/accent stay “paper white” in dark mode) */
|
|
481
|
-
.theme-one:not(.dark),
|
|
482
|
-
.theme-lavender:not(.dark) {
|
|
483
|
-
--sidebar: var(--brand-tint);
|
|
484
|
-
--sidebar-accent: oklch(0.945 0.025 286.1);
|
|
485
|
-
--sidebar-border: oklch(0.92 0.025 286.1);
|
|
486
|
-
--secondary: oklch(0.95 0.012 286.1);
|
|
487
|
-
--accent: oklch(0.925 0.015 286.1);
|
|
488
|
-
--muted: oklch(0.945 0.008 286.1);
|
|
489
|
-
--key-metrics-flat-band-radial: radial-gradient(
|
|
490
|
-
ellipse 120% 68% at 50% 100%,
|
|
491
|
-
oklch(0.50 0.14 286.1 / 0.22) 0%,
|
|
492
|
-
oklch(0.50 0.14 286.1 / 0.09) 42%,
|
|
493
|
-
transparent 72%
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
.theme-one.dark,
|
|
498
|
-
.dark.theme-one,
|
|
499
|
-
.theme-lavender.dark,
|
|
500
|
-
.dark.theme-lavender {
|
|
501
|
-
--ring: var(--brand-color);
|
|
502
|
-
--background: oklch(0.20 0.008 286.1);
|
|
503
|
-
--sidebar: oklch(0.245 0.015 286.1);
|
|
504
|
-
--sidebar-accent: oklch(0.30 0.012 286.1);
|
|
505
|
-
--sidebar-border: oklch(0.38 0.010 286.1);
|
|
506
|
-
/* Restore dark surfaces (base .dark is overridden by :not(.dark) rules above when both classes apply) */
|
|
507
|
-
--secondary: oklch(0.31 0.04 286.1);
|
|
508
|
-
--muted: oklch(0.31 0.04 286.1);
|
|
509
|
-
--accent: oklch(0.33 0.06 286.1);
|
|
510
|
-
--key-metrics-flat-band-radial: radial-gradient(
|
|
511
|
-
ellipse 120% 68% at 50% 100%,
|
|
512
|
-
oklch(0.50 0.14 286.1 / 0.28) 0%,
|
|
513
|
-
oklch(0.50 0.14 286.1 / 0.1) 42%,
|
|
514
|
-
transparent 72%
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/* ==========================================================================
|
|
519
|
-
Theme: Exxat Prism · Rose · hue 343
|
|
520
|
-
Usage: <html class="theme-prism"> or <html class="theme-rose">
|
|
521
|
-
========================================================================== */
|
|
522
|
-
.theme-prism,
|
|
523
|
-
.theme-rose {
|
|
524
|
-
--brand-tint: oklch(0.97 0.02 343);
|
|
525
|
-
--brand-tint-light: oklch(0.992 0.01 343);
|
|
526
|
-
--brand-tint-subtle: oklch(0.93 0.028 343);
|
|
527
|
-
--brand-color: oklch(0.57 0.24 342); /* Prism rose */
|
|
528
|
-
--brand-color-light: oklch(0.78 0.14 342);
|
|
529
|
-
--brand-color-dark: oklch(0.42 0.24 342);
|
|
530
|
-
--brand-color-deep: oklch(0.32 0.20 342);
|
|
531
|
-
--ring: var(--brand-color-dark);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
.theme-prism:not(.dark),
|
|
535
|
-
.theme-rose:not(.dark) {
|
|
536
|
-
--sidebar: oklch(0.97 0.02 343);
|
|
537
|
-
--sidebar-accent: oklch(0.945 0.025 343);
|
|
538
|
-
--sidebar-border: oklch(0.92 0.025 343);
|
|
539
|
-
--secondary: oklch(0.95 0.012 343);
|
|
540
|
-
--accent: oklch(0.925 0.015 343);
|
|
541
|
-
--muted: oklch(0.945 0.008 343);
|
|
542
|
-
--banner-prism-bg: oklch(0.97 0.02 343);
|
|
543
|
-
--theme-color-chrome: #fff5f9;
|
|
544
|
-
--key-metrics-flat-band-radial: radial-gradient(
|
|
545
|
-
ellipse 120% 68% at 50% 100%,
|
|
546
|
-
oklch(0.57 0.24 342 / 0.22) 0%,
|
|
547
|
-
oklch(0.57 0.24 342 / 0.09) 42%,
|
|
548
|
-
transparent 72%
|
|
549
|
-
);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
.theme-prism.dark,
|
|
553
|
-
.dark.theme-prism,
|
|
554
|
-
.theme-rose.dark,
|
|
555
|
-
.dark.theme-rose {
|
|
556
|
-
--ring: var(--brand-color);
|
|
557
|
-
--background: oklch(0.20 0.008 342);
|
|
558
|
-
--sidebar: oklch(0.245 0.015 342);
|
|
559
|
-
--sidebar-accent: oklch(0.30 0.012 342);
|
|
560
|
-
--sidebar-border: oklch(0.38 0.010 342);
|
|
561
|
-
--secondary: oklch(0.31 0.04 342);
|
|
562
|
-
--muted: oklch(0.31 0.04 342);
|
|
563
|
-
--accent: oklch(0.33 0.06 342);
|
|
564
|
-
--theme-color-chrome: #2a2428;
|
|
565
|
-
--key-metrics-flat-band-radial: radial-gradient(
|
|
566
|
-
ellipse 120% 68% at 50% 100%,
|
|
567
|
-
oklch(0.57 0.24 342 / 0.28) 0%,
|
|
568
|
-
oklch(0.57 0.24 342 / 0.1) 42%,
|
|
569
|
-
transparent 72%
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
/* ==========================================================================
|
|
574
|
-
HIGH CONTRAST MODE
|
|
575
|
-
──────────────────────────────────────────────────────────────────────────
|
|
576
|
-
Three guiding principles (WCAG 1.4.6 Enhanced + research-backed UX):
|
|
577
|
-
|
|
578
|
-
1. FORCED-COLORS APPROACH
|
|
579
|
-
Strip gradients, shadows, and background images.
|
|
580
|
-
Use borders to define shape and elevation — not fills.
|
|
581
|
-
Limited palette: 4–6 named tokens, nothing decorative.
|
|
582
|
-
|
|
583
|
-
2. DON'T RELY ON COLOR ALONE
|
|
584
|
-
Error/warning states get a thick border AND an icon differentiator.
|
|
585
|
-
Charts and badges use luminance separation (grayscale steps), not hue.
|
|
586
|
-
Interactive state (hover / focus / active) is communicated via outline,
|
|
587
|
-
not background-color change alone.
|
|
588
|
-
|
|
589
|
-
3. DARK MODE ≠ HIGH CONTRAST
|
|
590
|
-
Dark mode = aesthetic; uses subtle greys.
|
|
591
|
-
High-contrast dark = functional; uses near-black grey canvas, pure white
|
|
592
|
-
(#FFF), and a "hot" neon-yellow focus accent for maximum visibility.
|
|
593
|
-
========================================================================== */
|
|
594
|
-
|
|
595
|
-
/* ── Light High Contrast ─────────────────────────────────────────────────── */
|
|
596
|
-
/* Fluent 2 / Microsoft 6-color strategy. */
|
|
597
|
-
/* Highlight = saturated bright brand color (follows theme hue). */
|
|
598
|
-
/* */
|
|
599
|
-
/* Canvas = white */
|
|
600
|
-
/* CanvasText = near-black */
|
|
601
|
-
/* Highlight = saturated dark brand (selected / active / focus) */
|
|
602
|
-
/* HighlightText= white */
|
|
603
|
-
/* GrayText = mid-grey (disabled) */
|
|
604
|
-
/* Error = dark red (destructive only) */
|
|
605
|
-
html[data-contrast="high"]:not(.dark) {
|
|
606
|
-
--hc-highlight: oklch(from var(--brand-color) 0.35 0.30 h);
|
|
607
|
-
--hc-highlight-text: oklch(1 0 0);
|
|
608
|
-
|
|
609
|
-
--background: oklch(1 0 0);
|
|
610
|
-
--foreground: oklch(0.14 0 0);
|
|
611
|
-
--card: oklch(1 0 0);
|
|
612
|
-
--card-foreground: oklch(0.14 0 0);
|
|
613
|
-
--popover: oklch(1 0 0);
|
|
614
|
-
--popover-foreground: oklch(0.14 0 0);
|
|
615
|
-
|
|
616
|
-
--primary: oklch(0.14 0 0);
|
|
617
|
-
--primary-foreground: oklch(1 0 0);
|
|
618
|
-
|
|
619
|
-
--secondary: oklch(1 0 0);
|
|
620
|
-
--secondary-foreground: oklch(0.14 0 0);
|
|
621
|
-
|
|
622
|
-
--muted: oklch(0.94 0 0);
|
|
623
|
-
--muted-foreground: oklch(0.14 0 0);
|
|
624
|
-
|
|
625
|
-
--accent: var(--hc-highlight);
|
|
626
|
-
--accent-foreground: var(--hc-highlight-text);
|
|
627
|
-
|
|
628
|
-
--destructive: oklch(0.45 0.24 25);
|
|
629
|
-
--destructive-foreground: oklch(1 0 0);
|
|
630
|
-
|
|
631
|
-
--border: oklch(0.14 0 0);
|
|
632
|
-
--border-control: oklch(0.14 0 0);
|
|
633
|
-
--border-control-3: oklch(0.14 0 0);
|
|
634
|
-
--border-control-35: oklch(0.14 0 0);
|
|
635
|
-
--control-border: oklch(0.14 0 0);
|
|
636
|
-
|
|
637
|
-
--input: oklch(0.14 0 0);
|
|
638
|
-
--input-background: oklch(1 0 0);
|
|
639
|
-
|
|
640
|
-
--ring: var(--hc-highlight);
|
|
641
|
-
|
|
642
|
-
--sidebar: oklch(1 0 0);
|
|
643
|
-
--sidebar-foreground: oklch(0.14 0 0);
|
|
644
|
-
--sidebar-primary: oklch(0.14 0 0);
|
|
645
|
-
--sidebar-primary-foreground: oklch(1 0 0);
|
|
646
|
-
--sidebar-accent: oklch(0.90 0 0);
|
|
647
|
-
--sidebar-accent-foreground: oklch(0.14 0 0);
|
|
648
|
-
--sidebar-border: oklch(0.14 0 0);
|
|
649
|
-
--sidebar-ring: var(--hc-highlight);
|
|
650
|
-
--sidebar-section-label-foreground: oklch(0.40 0 0);
|
|
651
|
-
|
|
652
|
-
/* Charts — CanvasText (near-black) fill; differentiated by luminance */
|
|
653
|
-
--chart-1: oklch(0.14 0 0);
|
|
654
|
-
--chart-2: oklch(0.35 0 0);
|
|
655
|
-
--chart-3: oklch(0.55 0 0);
|
|
656
|
-
--chart-4: oklch(0.72 0 0);
|
|
657
|
-
--chart-5: oklch(0.86 0 0);
|
|
658
|
-
|
|
659
|
-
/* Chips — uniform foreground; differentiated by label text only */
|
|
660
|
-
--chip-1: oklch(0.14 0 0);
|
|
661
|
-
--chip-2: oklch(0.14 0 0);
|
|
662
|
-
--chip-3: oklch(0.14 0 0);
|
|
663
|
-
--chip-4: oklch(0.14 0 0);
|
|
664
|
-
--chip-5: oklch(0.14 0 0);
|
|
665
|
-
--chip-destructive: oklch(0.45 0.24 25);
|
|
666
|
-
|
|
667
|
-
/* Hover — plain grey shift */
|
|
668
|
-
--interactive-hover: oklch(0.88 0 0);
|
|
669
|
-
--interactive-hover-foreground: oklch(0.14 0 0);
|
|
670
|
-
--interactive-hover-subtle: oklch(0.92 0 0);
|
|
671
|
-
--interactive-hover-soft: oklch(0.92 0 0);
|
|
672
|
-
--interactive-hover-medium: oklch(0.86 0 0);
|
|
673
|
-
--interactive-hover-strong: oklch(0.82 0 0);
|
|
674
|
-
--interactive-hover-row: oklch(0.88 0 0);
|
|
675
|
-
|
|
676
|
-
--overlay: color-mix(in oklch, var(--foreground) 18%, transparent);
|
|
677
|
-
--dt-row-bg: oklch(1 0 0);
|
|
678
|
-
--dt-row-hover: oklch(0.92 0 0);
|
|
679
|
-
--dt-row-selected: var(--accent);
|
|
680
|
-
--dt-row-selected-fg: var(--accent-foreground);
|
|
681
|
-
--dt-header-bg: oklch(1 0 0);
|
|
682
|
-
--dt-group-bg: oklch(0.92 0 0);
|
|
683
|
-
--dt-new-row-bg: oklch(1 0 0);
|
|
684
|
-
--dt-new-row-border: oklch(0.14 0 0);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
/* ── Dark High Contrast ──────────────────────────────────────────────────── */
|
|
688
|
-
/* Same 6-color strategy inverted for dark canvas. */
|
|
689
|
-
/* Highlight = very bright saturated brand (like MS cyan but brand hue). */
|
|
690
|
-
html[data-contrast="high"].dark {
|
|
691
|
-
--hc-highlight: oklch(from var(--brand-color) 0.78 0.30 h);
|
|
692
|
-
--hc-highlight-text: oklch(0.08 0 0);
|
|
693
|
-
|
|
694
|
-
--background: oklch(0.14 0 0);
|
|
695
|
-
--foreground: oklch(0.96 0 0);
|
|
696
|
-
--card: oklch(0.14 0 0);
|
|
697
|
-
--card-foreground: oklch(0.96 0 0);
|
|
698
|
-
--popover: oklch(0.20 0 0);
|
|
699
|
-
--popover-foreground: oklch(0.96 0 0);
|
|
700
|
-
|
|
701
|
-
--primary: oklch(0.96 0 0);
|
|
702
|
-
--primary-foreground: oklch(0.10 0 0);
|
|
703
|
-
|
|
704
|
-
--secondary: oklch(0.14 0 0);
|
|
705
|
-
--secondary-foreground: oklch(0.96 0 0);
|
|
706
|
-
|
|
707
|
-
--muted: oklch(0.22 0 0);
|
|
708
|
-
--muted-foreground: oklch(0.96 0 0);
|
|
709
|
-
|
|
710
|
-
--accent: var(--hc-highlight);
|
|
711
|
-
--accent-foreground: var(--hc-highlight-text);
|
|
712
|
-
|
|
713
|
-
--destructive: oklch(0.72 0.18 18);
|
|
714
|
-
--destructive-foreground: oklch(0.10 0 0);
|
|
715
|
-
|
|
716
|
-
--border: oklch(0.75 0 0);
|
|
717
|
-
--border-control: oklch(0.75 0 0);
|
|
718
|
-
--border-control-3: oklch(0.75 0 0);
|
|
719
|
-
--border-control-35: oklch(0.75 0 0);
|
|
720
|
-
--control-border: oklch(0.75 0 0);
|
|
721
|
-
|
|
722
|
-
--input: oklch(0.75 0 0);
|
|
723
|
-
--input-background: oklch(0.14 0 0);
|
|
724
|
-
|
|
725
|
-
--ring: var(--hc-highlight);
|
|
726
|
-
|
|
727
|
-
--sidebar: oklch(0.14 0 0);
|
|
728
|
-
--sidebar-foreground: oklch(0.96 0 0);
|
|
729
|
-
--sidebar-primary: oklch(0.96 0 0);
|
|
730
|
-
--sidebar-primary-foreground: oklch(0.10 0 0);
|
|
731
|
-
--sidebar-accent: oklch(0.24 0 0);
|
|
732
|
-
--sidebar-accent-foreground: oklch(0.96 0 0);
|
|
733
|
-
--sidebar-border: oklch(0.75 0 0);
|
|
734
|
-
--sidebar-ring: var(--hc-highlight);
|
|
735
|
-
--sidebar-section-label-foreground: oklch(0.65 0 0);
|
|
736
|
-
|
|
737
|
-
/* Charts — CanvasText (white) fill; differentiated by luminance */
|
|
738
|
-
--chart-1: oklch(0.96 0 0);
|
|
739
|
-
--chart-2: oklch(0.75 0 0);
|
|
740
|
-
--chart-3: oklch(0.55 0 0);
|
|
741
|
-
--chart-4: oklch(0.38 0 0);
|
|
742
|
-
--chart-5: oklch(0.22 0 0);
|
|
743
|
-
|
|
744
|
-
/* Chips — uniform foreground; differentiated by label text only */
|
|
745
|
-
--chip-1: oklch(0.96 0 0);
|
|
746
|
-
--chip-2: oklch(0.96 0 0);
|
|
747
|
-
--chip-3: oklch(0.96 0 0);
|
|
748
|
-
--chip-4: oklch(0.96 0 0);
|
|
749
|
-
--chip-5: oklch(0.96 0 0);
|
|
750
|
-
--chip-destructive: oklch(0.72 0.18 18);
|
|
751
|
-
|
|
752
|
-
/* Hover — plain grey shift */
|
|
753
|
-
--interactive-hover: oklch(0.26 0 0);
|
|
754
|
-
--interactive-hover-foreground: oklch(0.96 0 0);
|
|
755
|
-
--interactive-hover-subtle: oklch(0.22 0 0);
|
|
756
|
-
--interactive-hover-soft: oklch(0.22 0 0);
|
|
757
|
-
--interactive-hover-medium: oklch(0.28 0 0);
|
|
758
|
-
--interactive-hover-strong: oklch(0.32 0 0);
|
|
759
|
-
--interactive-hover-row: oklch(0.26 0 0);
|
|
760
|
-
|
|
761
|
-
--overlay: color-mix(in oklch, var(--foreground) 22%, transparent);
|
|
762
|
-
--dt-row-bg: oklch(0.14 0 0);
|
|
763
|
-
--dt-row-hover: oklch(0.22 0 0);
|
|
764
|
-
--dt-row-selected: var(--accent);
|
|
765
|
-
--dt-row-selected-fg: var(--accent-foreground);
|
|
766
|
-
--dt-header-bg: oklch(0.14 0 0);
|
|
767
|
-
--dt-group-bg: oklch(0.22 0 0);
|
|
768
|
-
--dt-new-row-bg: oklch(0.14 0 0);
|
|
769
|
-
--dt-new-row-border: oklch(0.96 0 0);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
/* Override brand tokens in HC so text-brand / bg-brand become HC-safe.
|
|
774
|
-
NOTE: --hc-highlight uses oklch(from var(--brand-color) ...) so we must
|
|
775
|
-
NOT override --brand-color before that resolves. Instead, override
|
|
776
|
-
brand-tint/wash tokens to neutral greys and leave --brand-color for
|
|
777
|
-
the relative-color syntax to consume. Text using text-brand will get
|
|
778
|
-
the saturated HC highlight, which is correct. */
|
|
779
|
-
html:is([data-contrast="high"], [data-contrast="windows"]):not(.dark) {
|
|
780
|
-
--brand-tint: oklch(0.94 0 0);
|
|
781
|
-
--brand-tint-light: oklch(0.97 0 0);
|
|
782
|
-
--brand-tint-subtle: oklch(0.98 0 0);
|
|
783
|
-
}
|
|
784
|
-
html:is([data-contrast="high"], [data-contrast="windows"]).dark {
|
|
785
|
-
--brand-tint: oklch(0.22 0 0);
|
|
786
|
-
--brand-tint-light: oklch(0.18 0 0);
|
|
787
|
-
--brand-tint-subtle: oklch(0.16 0 0);
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
/* ── Structural rules shared by BOTH light and dark HC ──────────────────── */
|
|
791
|
-
/* Pattern 1: "Borders over Fills" — strip decorative chrome */
|
|
792
|
-
html:is([data-contrast="high"], [data-contrast="windows"]) {
|
|
793
|
-
|
|
794
|
-
/* 1a. Remove ALL box-shadows (elevation via outline, not shadow) */
|
|
795
|
-
& * {
|
|
796
|
-
box-shadow: none !important;
|
|
797
|
-
text-shadow: none !important;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
/* 1b. Strip gradient fills from cards; use border to define shape */
|
|
801
|
-
& [data-slot="card"] {
|
|
802
|
-
background-image: none !important;
|
|
803
|
-
border: 2px solid var(--foreground) !important;
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
/* 1c. Thicker borders on all form controls (WCAG 1.4.11: 3:1 UI contrast) */
|
|
807
|
-
& [data-slot="input"],
|
|
808
|
-
& [data-slot="select-trigger"],
|
|
809
|
-
& [data-slot="textarea"],
|
|
810
|
-
& [data-slot="checkbox"],
|
|
811
|
-
& [data-slot="switch"] {
|
|
812
|
-
border-width: 2px !important;
|
|
813
|
-
border-color: var(--foreground) !important;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
/* 1d. Sidebar defined by its edge border, not background colour */
|
|
817
|
-
& [data-slot="sidebar"] {
|
|
818
|
-
border-inline-end: 2px solid var(--sidebar-border) !important;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
/* 1e. Tab list — border not fill */
|
|
822
|
-
& [data-slot="tabs-list"] {
|
|
823
|
-
background-color: transparent !important;
|
|
824
|
-
border: 2px solid var(--foreground) !important;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
/* 1f. Badge / chip — border-based; fill only for destructive */
|
|
828
|
-
& [data-slot="badge"] {
|
|
829
|
-
border-width: 2px !important;
|
|
830
|
-
border-color: var(--foreground) !important;
|
|
831
|
-
background-color: var(--background) !important;
|
|
832
|
-
font-weight: 700 !important;
|
|
833
|
-
box-shadow: none !important;
|
|
834
|
-
outline: none !important;
|
|
835
|
-
color: var(--foreground) !important;
|
|
836
|
-
color: var(--foreground) !important;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
& [data-slot="badge"] * {
|
|
840
|
-
color: var(--foreground) !important;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
/* Sidebar wrapper is positioning-only when it wraps Badge — avoid double border */
|
|
844
|
-
& [data-slot="sidebar-menu-badge"]:has([data-slot="badge"]) {
|
|
845
|
-
border-width: 0 !important;
|
|
846
|
-
background-color: transparent !important;
|
|
847
|
-
box-shadow: none !important;
|
|
848
|
-
outline: none !important;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
& [data-slot="view-toolbar-count"] {
|
|
852
|
-
border-width: 2px !important;
|
|
853
|
-
border-color: currentColor !important;
|
|
854
|
-
background-color: var(--background) !important;
|
|
855
|
-
font-weight: 700 !important;
|
|
856
|
-
color: var(--foreground) !important;
|
|
857
|
-
box-shadow: none !important;
|
|
858
|
-
outline: none !important;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
& [data-slot="sidebar-menu-badge"]:not(:has([data-slot="badge"])) {
|
|
862
|
-
border-width: 2px !important;
|
|
863
|
-
border-color: currentColor !important;
|
|
864
|
-
background-color: var(--background) !important;
|
|
865
|
-
font-weight: 700 !important;
|
|
866
|
-
color: var(--foreground) !important;
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
/* Segmented tab buttons: global HC button border + count pill border = double ring */
|
|
870
|
-
& button[data-slot="view-segmented-item"] {
|
|
871
|
-
border-width: 0 !important;
|
|
872
|
-
border-color: transparent !important;
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
/* Radix Tabs — active state must not rely on muted fill / pseudo underline only */
|
|
876
|
-
& [data-slot="tabs-trigger"] {
|
|
877
|
-
color: var(--foreground) !important;
|
|
878
|
-
opacity: 1 !important;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
& [data-slot="tabs-trigger"][data-state="active"] {
|
|
882
|
-
background-color: var(--accent) !important;
|
|
883
|
-
color: var(--accent-foreground) !important;
|
|
884
|
-
outline: none !important;
|
|
885
|
-
font-weight: 600 !important;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
/* KPI strip + chart card mini-metrics — force readable copy (muted grays fail in HC) */
|
|
889
|
-
& [data-slot="key-metrics"] :where(span, p, button, a, i, label, div) {
|
|
890
|
-
color: var(--foreground) !important;
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
& [data-slot="key-metrics"] :where(svg) {
|
|
894
|
-
color: var(--foreground) !important;
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
/* List / menu rows — highlighted row uses Highlight brand color */
|
|
898
|
-
& [data-slot="dropdown-menu-item"][data-highlighted],
|
|
899
|
-
& [data-slot="dropdown-menu-checkbox-item"][data-highlighted],
|
|
900
|
-
& [data-slot="dropdown-menu-radio-item"][data-highlighted],
|
|
901
|
-
& [data-slot="dropdown-menu-sub-trigger"][data-highlighted],
|
|
902
|
-
& [data-slot="select-item"][data-highlighted],
|
|
903
|
-
& [data-slot="command-item"][data-selected],
|
|
904
|
-
& [data-slot="command-item"][aria-selected="true"] {
|
|
905
|
-
background-color: var(--accent) !important;
|
|
906
|
-
color: var(--accent-foreground) !important;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
& [data-slot="dropdown-menu-item"][data-highlighted] *,
|
|
910
|
-
& [data-slot="dropdown-menu-checkbox-item"][data-highlighted] *,
|
|
911
|
-
& [data-slot="dropdown-menu-radio-item"][data-highlighted] *,
|
|
912
|
-
& [data-slot="dropdown-menu-sub-trigger"][data-highlighted] *,
|
|
913
|
-
& [data-slot="select-item"][data-highlighted] *,
|
|
914
|
-
& [data-slot="command-item"][data-selected] *,
|
|
915
|
-
& [data-slot="command-item"][aria-selected="true"] * {
|
|
916
|
-
color: var(--accent-foreground) !important;
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
/* List hub views toolbar + segmented radiogroup (not Radix Tabs / tabs-list) */
|
|
920
|
-
& [data-slot="view-segmented-toolbar"] {
|
|
921
|
-
background-color: transparent !important;
|
|
922
|
-
border: 2px solid var(--foreground) !important;
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
& [data-slot="view-segmented-item"][aria-pressed="true"],
|
|
926
|
-
& [data-slot="view-segmented-item"][aria-checked="true"] {
|
|
927
|
-
outline: 2px solid currentColor !important;
|
|
928
|
-
outline-offset: -2px !important;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
/* Floating surfaces — portal menus, popovers, sheets, dialogs */
|
|
932
|
-
& [data-slot="dropdown-menu-content"],
|
|
933
|
-
& [data-slot="dropdown-menu-sub-content"],
|
|
934
|
-
& [data-slot="popover-content"],
|
|
935
|
-
& [data-slot="select-content"],
|
|
936
|
-
& [data-slot="dialog-content"],
|
|
937
|
-
& [data-slot="sheet-content"],
|
|
938
|
-
& [data-slot="drawer-content"] {
|
|
939
|
-
border: 2px solid var(--foreground) !important;
|
|
940
|
-
background-color: var(--background) !important;
|
|
941
|
-
color: var(--foreground) !important;
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
& [data-slot="command"] {
|
|
945
|
-
background-color: var(--background) !important;
|
|
946
|
-
color: var(--foreground) !important;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
/* Strip conditional-formatting inline bg from table cells in HC */
|
|
950
|
-
& td[style*="background"] {
|
|
951
|
-
background: var(--dt-row-bg) !important;
|
|
952
|
-
}
|
|
953
|
-
& td.pinned-cell {
|
|
954
|
-
background-color: var(--dt-row-bg) !important;
|
|
955
|
-
}
|
|
956
|
-
& tr:hover td.pinned-cell,
|
|
957
|
-
& tr:hover td {
|
|
958
|
-
background-color: var(--dt-row-hover) !important;
|
|
959
|
-
}
|
|
960
|
-
& tr[data-state="selected"] td.pinned-cell,
|
|
961
|
-
& tr[data-state="selected"] td {
|
|
962
|
-
background-color: var(--dt-row-selected) !important;
|
|
963
|
-
color: var(--dt-row-selected-fg) !important;
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
/* Table selected rows — Highlight brand color (like MS Teams selection) */
|
|
967
|
-
& tr[data-state="selected"] {
|
|
968
|
-
background-color: var(--dt-row-selected) !important;
|
|
969
|
-
color: var(--dt-row-selected-fg) !important;
|
|
970
|
-
}
|
|
971
|
-
& tr[data-state="selected"] *:not([data-slot="checkbox"] *):not([data-slot="badge"] *):not([data-slot="checkbox"]):not([data-slot="badge"]) {
|
|
972
|
-
color: var(--accent-foreground) !important;
|
|
973
|
-
}
|
|
974
|
-
& tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"],
|
|
975
|
-
& tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] {
|
|
976
|
-
background-color: var(--accent-foreground) !important;
|
|
977
|
-
border-color: var(--accent-foreground) !important;
|
|
978
|
-
color: var(--accent) !important;
|
|
979
|
-
}
|
|
980
|
-
& tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"] *,
|
|
981
|
-
& tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] * {
|
|
982
|
-
color: var(--accent) !important;
|
|
983
|
-
}
|
|
984
|
-
& tr[data-state="selected"] [data-slot="badge"] {
|
|
985
|
-
background-color: var(--accent-foreground) !important;
|
|
986
|
-
color: var(--accent) !important;
|
|
987
|
-
border-color: var(--accent-foreground) !important;
|
|
988
|
-
}
|
|
989
|
-
& tr[data-state="selected"] [data-slot="badge"] * {
|
|
990
|
-
color: var(--accent) !important;
|
|
991
|
-
}
|
|
992
|
-
& tr[data-state="selected"] [data-slot="checkbox"]:not([data-state="checked"]):not([data-state="indeterminate"]) {
|
|
993
|
-
background-color: var(--accent) !important;
|
|
994
|
-
border-color: var(--accent-foreground) !important;
|
|
995
|
-
color: var(--accent-foreground) !important;
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
/* ── Pattern 2: Stronger focus ring (WCAG 2.4.11 / 2.4.12) ── */
|
|
999
|
-
& :focus-visible {
|
|
1000
|
-
outline: 3px solid var(--ring) !important;
|
|
1001
|
-
outline-offset: 3px !important;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
/* ── Pattern 2: Error state — thick border + no colour-only signal ── */
|
|
1005
|
-
& [aria-invalid="true"],
|
|
1006
|
-
& [data-invalid] {
|
|
1007
|
-
border-width: 3px !important;
|
|
1008
|
-
border-color: var(--destructive) !important;
|
|
1009
|
-
/* Downstream: pair with a ⚠ icon in the component for non-colour signal */
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
/* ── Pattern 3: Active nav / toggle items — Highlight brand fill ── */
|
|
1013
|
-
& [data-slot="sidebar-menu-button"][data-active="true"] {
|
|
1014
|
-
background-color: var(--accent) !important;
|
|
1015
|
-
color: var(--accent-foreground) !important;
|
|
1016
|
-
outline: none !important;
|
|
1017
|
-
}
|
|
1018
|
-
& [data-slot="sidebar-menu-button"][data-active="true"] * {
|
|
1019
|
-
color: var(--accent-foreground) !important;
|
|
1020
|
-
}
|
|
1021
|
-
& [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"],
|
|
1022
|
-
& [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] {
|
|
1023
|
-
background-color: var(--accent-foreground) !important;
|
|
1024
|
-
color: var(--accent) !important;
|
|
1025
|
-
border-color: var(--accent-foreground) !important;
|
|
1026
|
-
}
|
|
1027
|
-
& [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"] *,
|
|
1028
|
-
& [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] * {
|
|
1029
|
-
color: var(--accent) !important;
|
|
1030
|
-
}
|
|
1031
|
-
& [data-slot="toggle-group-item"][data-state="on"] {
|
|
1032
|
-
outline: 2px solid var(--accent) !important;
|
|
1033
|
-
outline-offset: -2px !important;
|
|
1034
|
-
background-color: var(--accent) !important;
|
|
1035
|
-
color: var(--accent-foreground) !important;
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
/* ── Pattern 3b: Checked checkboxes — Highlight brand fill ── */
|
|
1039
|
-
& [data-slot="checkbox"][data-state="checked"],
|
|
1040
|
-
& [data-slot="checkbox"][data-state="indeterminate"] {
|
|
1041
|
-
background-color: var(--accent) !important;
|
|
1042
|
-
border-color: var(--accent) !important;
|
|
1043
|
-
color: var(--accent-foreground) !important;
|
|
1044
|
-
}
|
|
1045
|
-
& [data-slot="checkbox"][data-state="checked"] *,
|
|
1046
|
-
& [data-slot="checkbox"][data-state="indeterminate"] * {
|
|
1047
|
-
color: var(--accent-foreground) !important;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
/* ── Pattern 3c: Checked radio buttons — Highlight brand fill ── */
|
|
1051
|
-
& [data-slot="radio-group-item"][data-state="checked"] {
|
|
1052
|
-
background-color: var(--accent) !important;
|
|
1053
|
-
border-color: var(--accent) !important;
|
|
1054
|
-
color: var(--accent-foreground) !important;
|
|
1055
|
-
}
|
|
1056
|
-
& [data-slot="radio-group-item"][data-state="checked"] [data-slot="radio-group-indicator"] span {
|
|
1057
|
-
background-color: var(--accent-foreground) !important;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
/* ── Pattern 3d: Toggle on state — Highlight brand fill ── */
|
|
1061
|
-
& [data-slot="toggle"][data-state="on"] {
|
|
1062
|
-
background-color: var(--accent) !important;
|
|
1063
|
-
color: var(--accent-foreground) !important;
|
|
1064
|
-
border: 2px solid var(--accent) !important;
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
/* ── Pattern 3e: Switch (toggle-switch) — visible track + knob ── */
|
|
1068
|
-
& [role="switch"] {
|
|
1069
|
-
border: 2px solid var(--foreground) !important;
|
|
1070
|
-
background-color: var(--background) !important;
|
|
1071
|
-
}
|
|
1072
|
-
& [role="switch"][aria-checked="true"] {
|
|
1073
|
-
background-color: var(--accent) !important;
|
|
1074
|
-
border-color: var(--accent) !important;
|
|
1075
|
-
}
|
|
1076
|
-
& [role="switch"] > span {
|
|
1077
|
-
background-color: var(--foreground) !important;
|
|
1078
|
-
}
|
|
1079
|
-
& [role="switch"][aria-checked="true"] > span {
|
|
1080
|
-
background-color: var(--accent-foreground) !important;
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
/* ── Pattern 3f: Select / dropdown item focus — accent is too subtle;
|
|
1084
|
-
force visible inverted selection for keyboard focus (CSS :focus).
|
|
1085
|
-
data-highlighted is already handled above; this catches native focus. ── */
|
|
1086
|
-
& [data-slot="select-item"]:focus,
|
|
1087
|
-
& [data-slot="dropdown-menu-item"]:focus,
|
|
1088
|
-
& [data-slot="dropdown-menu-checkbox-item"]:focus,
|
|
1089
|
-
& [data-slot="dropdown-menu-radio-item"]:focus,
|
|
1090
|
-
& [data-slot="dropdown-menu-sub-trigger"]:focus {
|
|
1091
|
-
background-color: var(--foreground) !important;
|
|
1092
|
-
color: var(--background) !important;
|
|
1093
|
-
}
|
|
1094
|
-
& [data-slot="select-item"]:focus *,
|
|
1095
|
-
& [data-slot="dropdown-menu-item"]:focus *,
|
|
1096
|
-
& [data-slot="dropdown-menu-checkbox-item"]:focus *,
|
|
1097
|
-
& [data-slot="dropdown-menu-radio-item"]:focus *,
|
|
1098
|
-
& [data-slot="dropdown-menu-sub-trigger"]:focus * {
|
|
1099
|
-
color: var(--background) !important;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
/* ── Pattern 3g: Dropdown check / radio indicator — inherit from parent ── */
|
|
1103
|
-
& [data-slot="dropdown-menu-checkbox-item"][data-state="checked"],
|
|
1104
|
-
& [data-slot="dropdown-menu-radio-item"][data-state="checked"] {
|
|
1105
|
-
font-weight: 700 !important;
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
/* ── Pattern 4: Board cards — border-defined, no decorative fills ── */
|
|
1109
|
-
& [data-slot="board-card"] {
|
|
1110
|
-
border: 2px solid var(--foreground) !important;
|
|
1111
|
-
background-image: none !important;
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
/* ── Pattern 6: List hub status badges — border not fill ── */
|
|
1115
|
-
& [data-slot="list-hub-status-badge"] {
|
|
1116
|
-
border: 2px solid var(--foreground) !important;
|
|
1117
|
-
background-color: var(--background) !important;
|
|
1118
|
-
font-weight: 700 !important;
|
|
1119
|
-
color: var(--foreground) !important;
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
/* ── Pattern 7: Insight cards — border-based, strip gradient bg ── */
|
|
1123
|
-
& [aria-label="Insight"],
|
|
1124
|
-
& [data-slot="insight-card"] {
|
|
1125
|
-
border: 2px solid var(--foreground) !important;
|
|
1126
|
-
background-image: none !important;
|
|
1127
|
-
background: var(--background) !important;
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
/* ── Pattern 8: Coach marks — strong border + readable text ── */
|
|
1131
|
-
& [data-slot="coach-mark"] {
|
|
1132
|
-
border: 2px solid var(--foreground) !important;
|
|
1133
|
-
background: var(--background) !important;
|
|
1134
|
-
background-color: var(--background) !important;
|
|
1135
|
-
color: var(--foreground) !important;
|
|
1136
|
-
background-image: none !important;
|
|
1137
|
-
opacity: 1 !important;
|
|
1138
|
-
}
|
|
1139
|
-
& [data-slot="coach-mark"] *:not(button):not(button *) {
|
|
1140
|
-
color: var(--foreground) !important;
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
/* ── Pattern 9: Avatars — border-defined, strip blend modes, force contrast ── */
|
|
1144
|
-
& [data-slot="avatar"] {
|
|
1145
|
-
border: 2px solid var(--foreground) !important;
|
|
1146
|
-
}
|
|
1147
|
-
& [data-slot="avatar"]::after {
|
|
1148
|
-
display: none !important;
|
|
1149
|
-
}
|
|
1150
|
-
& [data-slot="avatar-fallback"] {
|
|
1151
|
-
background-color: var(--background) !important;
|
|
1152
|
-
color: var(--foreground) !important;
|
|
1153
|
-
}
|
|
1154
|
-
& tr[data-state="selected"] [data-slot="avatar"] {
|
|
1155
|
-
border-color: var(--accent-foreground) !important;
|
|
1156
|
-
}
|
|
1157
|
-
& tr[data-state="selected"] [data-slot="avatar-fallback"] {
|
|
1158
|
-
background-color: var(--accent-foreground) !important;
|
|
1159
|
-
color: var(--accent) !important;
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
/* ── Pattern 10: Breadcrumbs — ensure separators are visible ── */
|
|
1163
|
-
& [data-slot="breadcrumb-separator"] {
|
|
1164
|
-
color: var(--foreground) !important;
|
|
1165
|
-
}
|
|
1166
|
-
& [data-slot="breadcrumb-link"] {
|
|
1167
|
-
color: var(--foreground) !important;
|
|
1168
|
-
text-decoration: underline !important;
|
|
1169
|
-
}
|
|
1170
|
-
& [data-slot="breadcrumb-page"] {
|
|
1171
|
-
color: var(--foreground) !important;
|
|
1172
|
-
font-weight: 700 !important;
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
/* ── Pattern 11: Tooltip / popover arrow — match border ── */
|
|
1176
|
-
& [data-slot="tooltip-content"] {
|
|
1177
|
-
border: 2px solid var(--foreground) !important;
|
|
1178
|
-
background-color: var(--background) !important;
|
|
1179
|
-
color: var(--foreground) !important;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
/* ── Pattern 12: Separator — visible in HC ── */
|
|
1183
|
-
& [data-slot="separator"] {
|
|
1184
|
-
background-color: var(--foreground) !important;
|
|
1185
|
-
opacity: 1 !important;
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
/* ── Pattern 13: Strip ALL hardcoded Tailwind palette colors ──────────── */
|
|
1189
|
-
/* Banners, board columns, status pills, placement badges, etc. use */
|
|
1190
|
-
/* hardcoded emerald/amber/blue/red/slate/yellow classes. In HC these */
|
|
1191
|
-
/* MUST collapse to foreground text + border. Strip bg fills, force */
|
|
1192
|
-
/* foreground text. (Microsoft HC: no semantic colors except error.) */
|
|
1193
|
-
|
|
1194
|
-
/* Banner variants (info/warning/error/success) — border + text only */
|
|
1195
|
-
& [data-slot="banner"],
|
|
1196
|
-
& [data-slot="local-banner"] {
|
|
1197
|
-
background-color: var(--background) !important;
|
|
1198
|
-
background-image: none !important;
|
|
1199
|
-
border: 2px solid var(--foreground) !important;
|
|
1200
|
-
color: var(--foreground) !important;
|
|
1201
|
-
}
|
|
1202
|
-
& [data-slot="banner"] *,
|
|
1203
|
-
& [data-slot="local-banner"] * {
|
|
1204
|
-
color: var(--foreground) !important;
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
/* Chart containers — add border between series, strip vivid fills */
|
|
1208
|
-
& .recharts-bar-rectangle,
|
|
1209
|
-
& .recharts-funnel-trapezoid {
|
|
1210
|
-
stroke: var(--background) !important;
|
|
1211
|
-
stroke-width: 2 !important;
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
/* Progress bars — container gets border, indicator uses foreground */
|
|
1215
|
-
& [role="progressbar"] {
|
|
1216
|
-
border: 1px solid var(--foreground) !important;
|
|
1217
|
-
background-color: var(--background) !important;
|
|
1218
|
-
}
|
|
1219
|
-
& [role="progressbar"] > * {
|
|
1220
|
-
background-color: var(--foreground) !important;
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
/* Generic: any element using Tailwind color utility that escapes tokens.
|
|
1224
|
-
Force all text to foreground in the HC subtree except already-handled
|
|
1225
|
-
inverted contexts (selected rows, highlighted items, buttons). */
|
|
1226
|
-
& [class*="text-emerald"],
|
|
1227
|
-
& [class*="text-amber"],
|
|
1228
|
-
& [class*="text-red-"],
|
|
1229
|
-
& [class*="text-blue-"],
|
|
1230
|
-
& [class*="text-green-"],
|
|
1231
|
-
& [class*="text-yellow-"],
|
|
1232
|
-
& [class*="text-slate-"],
|
|
1233
|
-
& [class*="text-orange-"],
|
|
1234
|
-
& [class*="text-pink-"],
|
|
1235
|
-
& [class*="text-purple-"] {
|
|
1236
|
-
color: var(--foreground) !important;
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
/* Brand-colored text/bg — map to HC highlight instead of foreground so
|
|
1240
|
-
brand accent remains visually distinct (Ask Leo icon, product tints) */
|
|
1241
|
-
& [class*="text-brand"] {
|
|
1242
|
-
color: var(--accent) !important;
|
|
1243
|
-
}
|
|
1244
|
-
& [class*="bg-brand"]:not([data-slot="coach-mark"]) {
|
|
1245
|
-
background-color: var(--background) !important;
|
|
1246
|
-
}
|
|
1247
|
-
& [class*="border-brand"] {
|
|
1248
|
-
border-color: var(--foreground) !important;
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
& [class*="bg-emerald"],
|
|
1252
|
-
& [class*="bg-amber"],
|
|
1253
|
-
& [class*="bg-red-"],
|
|
1254
|
-
& [class*="bg-blue-"],
|
|
1255
|
-
& [class*="bg-green-"],
|
|
1256
|
-
& [class*="bg-yellow-"],
|
|
1257
|
-
& [class*="bg-slate-"],
|
|
1258
|
-
& [class*="bg-orange-"],
|
|
1259
|
-
& [class*="bg-pink-"],
|
|
1260
|
-
& [class*="bg-purple-"] {
|
|
1261
|
-
background-color: var(--background) !important;
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
& [class*="border-emerald"],
|
|
1265
|
-
& [class*="border-amber"],
|
|
1266
|
-
& [class*="border-red-"],
|
|
1267
|
-
& [class*="border-blue-"],
|
|
1268
|
-
& [class*="border-green-"],
|
|
1269
|
-
& [class*="border-yellow-"],
|
|
1270
|
-
& [class*="border-slate-"],
|
|
1271
|
-
& [class*="border-orange-"],
|
|
1272
|
-
& [class*="border-pink-"],
|
|
1273
|
-
& [class*="border-purple-"] {
|
|
1274
|
-
border-color: var(--foreground) !important;
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
/* ── OS-level "Increase Contrast" — macOS / iOS / Android ───────────────── */
|
|
1279
|
-
@media (prefers-contrast: more) {
|
|
1280
|
-
:root:not([data-contrast="off"]):not([data-contrast="windows"]) {
|
|
1281
|
-
--foreground: oklch(0.06 0 0);
|
|
1282
|
-
--muted-foreground: oklch(0.10 0 0);
|
|
1283
|
-
--border: oklch(0.10 0 0);
|
|
1284
|
-
--border-control: oklch(0.06 0 0);
|
|
1285
|
-
--border-control-35: oklch(0.06 0 0);
|
|
1286
|
-
--border-control-3: oklch(0.06 0 0);
|
|
1287
|
-
--ring: oklch(0.06 0 0);
|
|
1288
|
-
}
|
|
1289
|
-
.dark:not([data-contrast="off"]):not([data-contrast="windows"]) {
|
|
1290
|
-
--foreground: oklch(1 0 0);
|
|
1291
|
-
--muted-foreground: oklch(0.88 0 0);
|
|
1292
|
-
--border: oklch(1 0 0);
|
|
1293
|
-
--border-control: oklch(0.88 0 0);
|
|
1294
|
-
--border-control-35: oklch(0.88 0 0);
|
|
1295
|
-
--border-control-3: oklch(0.88 0 0);
|
|
1296
|
-
--ring: oklch(0.97 0.19 110); /* neon yellow on dark */
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
/* ── Windows Forced Colors (High Contrast Mode in OS) ───────────────────── */
|
|
1301
|
-
/* When `forced-colors: active`, Windows REPLACES our colours entirely. */
|
|
1302
|
-
/* Our job: map semantic roles to system palette keywords so the OS */
|
|
1303
|
-
/* colouring makes sense, and ensure borders/outlines remain visible. */
|
|
1304
|
-
@media (forced-colors: active) {
|
|
1305
|
-
:root {
|
|
1306
|
-
--border: CanvasText;
|
|
1307
|
-
--border-control: CanvasText;
|
|
1308
|
-
--border-control-35: CanvasText;
|
|
1309
|
-
--border-control-3: CanvasText;
|
|
1310
|
-
--ring: Highlight;
|
|
1311
|
-
--destructive: LinkText;
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
/* Always show a 2px outline so focus is forced-color-safe */
|
|
1315
|
-
:focus-visible {
|
|
1316
|
-
outline: 2px solid Highlight !important;
|
|
1317
|
-
outline-offset: 2px !important;
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
body {
|
|
1321
|
-
background-color: Canvas;
|
|
1322
|
-
color: CanvasText;
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
|
-
a { color: LinkText; }
|
|
1326
|
-
button { border: 1px solid ButtonText !important; }
|
|
1327
|
-
|
|
1328
|
-
/* Cards: OS strips bg fills — add explicit border so shape is preserved */
|
|
1329
|
-
[data-slot="card"],
|
|
1330
|
-
.card {
|
|
1331
|
-
border: 2px solid CanvasText !important;
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
/* Sidebar edge */
|
|
1335
|
-
[data-slot="sidebar"] {
|
|
1336
|
-
border-inline-end: 2px solid CanvasText !important;
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
/* Wrapper-only sidebar badge (no inner Badge) — rare; keep single ring */
|
|
1340
|
-
[data-slot="sidebar-menu-badge"]:not(:has([data-slot="badge"])) {
|
|
1341
|
-
border: 2px solid CanvasText !important;
|
|
1342
|
-
background-color: Canvas !important;
|
|
1343
|
-
color: CanvasText !important;
|
|
1344
|
-
outline: none !important;
|
|
1345
|
-
box-shadow: none !important;
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
/* Positioning shell around <Badge/> or <StatusBadge/> — do not draw a second ring */
|
|
1349
|
-
[data-slot="sidebar-menu-badge"]:has([data-slot="badge"]),
|
|
1350
|
-
[data-slot="sidebar-menu-badge"]:has([data-slot="status-badge"]) {
|
|
1351
|
-
border: none !important;
|
|
1352
|
-
background: transparent !important;
|
|
1353
|
-
outline: none !important;
|
|
1354
|
-
box-shadow: none !important;
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
[data-slot="badge"],
|
|
1358
|
-
[data-slot="status-badge"],
|
|
1359
|
-
[data-slot="view-toolbar-count"] {
|
|
1360
|
-
border: 2px solid CanvasText !important;
|
|
1361
|
-
background-color: Canvas !important;
|
|
1362
|
-
color: CanvasText !important;
|
|
1363
|
-
outline: none !important;
|
|
1364
|
-
box-shadow: none !important;
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
[data-slot="badge"] *,
|
|
1368
|
-
[data-slot="status-badge"] *,
|
|
1369
|
-
[data-slot="view-toolbar-count"] * {
|
|
1370
|
-
color: CanvasText !important;
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
/* Avoid button chrome + inner count pill = double border */
|
|
1374
|
-
button[data-slot="view-segmented-item"] {
|
|
1375
|
-
border: none !important;
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
/* Radix Tabs (ChartCard, library, etc.) — gray inactive + invisible active in OS HC */
|
|
1379
|
-
[data-slot="tabs-list"] {
|
|
1380
|
-
border: 2px solid CanvasText !important;
|
|
1381
|
-
background-color: transparent !important;
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
|
-
[data-slot="tabs-trigger"] {
|
|
1385
|
-
color: CanvasText !important;
|
|
1386
|
-
background-color: transparent !important;
|
|
1387
|
-
opacity: 1 !important;
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
[data-slot="tabs-trigger"][data-state="active"] {
|
|
1391
|
-
background-color: Highlight !important;
|
|
1392
|
-
color: HighlightText !important;
|
|
1393
|
-
outline: none !important;
|
|
1394
|
-
font-weight: 600 !important;
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
/* Key metrics strip — labels/values/trend icons must not stay muted */
|
|
1398
|
-
[data-slot="key-metrics"] :where(span, p, button, a, i, label, div) {
|
|
1399
|
-
color: CanvasText !important;
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
/* Menu / select / command palette — accent fill is often low-contrast in forced mode */
|
|
1403
|
-
[data-slot="dropdown-menu-item"][data-highlighted]:not([data-disabled]),
|
|
1404
|
-
[data-slot="dropdown-menu-checkbox-item"][data-highlighted]:not([data-disabled]),
|
|
1405
|
-
[data-slot="dropdown-menu-radio-item"][data-highlighted]:not([data-disabled]),
|
|
1406
|
-
[data-slot="dropdown-menu-sub-trigger"][data-highlighted]:not([data-disabled]),
|
|
1407
|
-
[data-slot="select-item"][data-highlighted]:not([data-disabled]),
|
|
1408
|
-
/* cmdk sets data-selected="false" on every row — [data-selected] matches all; use ="true" only */
|
|
1409
|
-
[data-slot="command-item"][data-selected="true"]:not([data-disabled]),
|
|
1410
|
-
[data-slot="command-item"][aria-selected="true"]:not([data-disabled]) {
|
|
1411
|
-
background-color: Highlight !important;
|
|
1412
|
-
color: HighlightText !important;
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
[data-slot="dropdown-menu-item"][data-highlighted] *,
|
|
1416
|
-
[data-slot="dropdown-menu-checkbox-item"][data-highlighted] *,
|
|
1417
|
-
[data-slot="dropdown-menu-radio-item"][data-highlighted] *,
|
|
1418
|
-
[data-slot="dropdown-menu-sub-trigger"][data-highlighted] *,
|
|
1419
|
-
[data-slot="select-item"][data-highlighted] *,
|
|
1420
|
-
[data-slot="command-item"][data-selected="true"] *,
|
|
1421
|
-
[data-slot="command-item"][aria-selected="true"] * {
|
|
1422
|
-
color: HighlightText !important;
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
/* Views toolbar (list hubs) + segmented radiogroup — selection via outline, not fill */
|
|
1426
|
-
[data-slot="view-segmented-toolbar"] {
|
|
1427
|
-
border: 2px solid CanvasText !important;
|
|
1428
|
-
background: transparent !important;
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
[data-slot="view-segmented-item"] {
|
|
1432
|
-
color: CanvasText !important;
|
|
1433
|
-
background: transparent !important;
|
|
1434
|
-
}
|
|
1435
|
-
|
|
1436
|
-
[data-slot="view-segmented-item"][aria-pressed="true"],
|
|
1437
|
-
[data-slot="view-segmented-item"][aria-checked="true"] {
|
|
1438
|
-
background-color: Highlight !important;
|
|
1439
|
-
color: HighlightText !important;
|
|
1440
|
-
outline: none !important;
|
|
1441
|
-
}
|
|
1442
|
-
|
|
1443
|
-
/* Sidebar active item — Highlight brand fill (like MS Teams) */
|
|
1444
|
-
[data-slot="sidebar-menu-button"][data-active="true"] {
|
|
1445
|
-
background-color: Highlight !important;
|
|
1446
|
-
color: HighlightText !important;
|
|
1447
|
-
outline: none !important;
|
|
1448
|
-
}
|
|
1449
|
-
[data-slot="sidebar-menu-button"][data-active="true"] * {
|
|
1450
|
-
color: HighlightText !important;
|
|
1451
|
-
}
|
|
1452
|
-
[data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"],
|
|
1453
|
-
[data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] {
|
|
1454
|
-
background-color: HighlightText !important;
|
|
1455
|
-
color: Highlight !important;
|
|
1456
|
-
border-color: HighlightText !important;
|
|
1457
|
-
}
|
|
1458
|
-
[data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"] *,
|
|
1459
|
-
[data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] * {
|
|
1460
|
-
color: Highlight !important;
|
|
1461
|
-
}
|
|
1462
|
-
|
|
1463
|
-
/* Strip conditional-formatting inline bg in forced-colors */
|
|
1464
|
-
td[style*="background"] {
|
|
1465
|
-
background: Canvas !important;
|
|
1466
|
-
}
|
|
1467
|
-
td.pinned-cell {
|
|
1468
|
-
background-color: Canvas !important;
|
|
1469
|
-
}
|
|
1470
|
-
tr:hover td,
|
|
1471
|
-
tr:hover td.pinned-cell {
|
|
1472
|
-
background-color: Highlight !important;
|
|
1473
|
-
color: HighlightText !important;
|
|
1474
|
-
}
|
|
1475
|
-
|
|
1476
|
-
/* Table selected rows — Highlight brand fill */
|
|
1477
|
-
tr[data-state="selected"] {
|
|
1478
|
-
background-color: Highlight !important;
|
|
1479
|
-
color: HighlightText !important;
|
|
1480
|
-
}
|
|
1481
|
-
tr[data-state="selected"] td {
|
|
1482
|
-
background: Highlight !important;
|
|
1483
|
-
background-color: Highlight !important;
|
|
1484
|
-
color: HighlightText !important;
|
|
1485
|
-
}
|
|
1486
|
-
tr[data-state="selected"] *:not([data-slot="checkbox"] *):not([data-slot="badge"] *):not([data-slot="checkbox"]):not([data-slot="badge"]) {
|
|
1487
|
-
color: HighlightText !important;
|
|
1488
|
-
}
|
|
1489
|
-
tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"],
|
|
1490
|
-
tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] {
|
|
1491
|
-
background-color: HighlightText !important;
|
|
1492
|
-
border-color: HighlightText !important;
|
|
1493
|
-
color: Highlight !important;
|
|
1494
|
-
}
|
|
1495
|
-
tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"] *,
|
|
1496
|
-
tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] * {
|
|
1497
|
-
color: Highlight !important;
|
|
1498
|
-
}
|
|
1499
|
-
tr[data-state="selected"] [data-slot="checkbox"]:not([data-state="checked"]):not([data-state="indeterminate"]) {
|
|
1500
|
-
background-color: Highlight !important;
|
|
1501
|
-
border-color: HighlightText !important;
|
|
1502
|
-
color: HighlightText !important;
|
|
1503
|
-
}
|
|
1504
|
-
tr[data-state="selected"] [data-slot="badge"] {
|
|
1505
|
-
background-color: HighlightText !important;
|
|
1506
|
-
color: Highlight !important;
|
|
1507
|
-
border-color: HighlightText !important;
|
|
1508
|
-
}
|
|
1509
|
-
tr[data-state="selected"] [data-slot="badge"] * {
|
|
1510
|
-
color: Highlight !important;
|
|
1511
|
-
}
|
|
1512
|
-
tr[data-state="selected"] [data-slot="avatar"] {
|
|
1513
|
-
border-color: HighlightText !important;
|
|
1514
|
-
}
|
|
1515
|
-
tr[data-state="selected"] [data-slot="avatar-fallback"] {
|
|
1516
|
-
background-color: HighlightText !important;
|
|
1517
|
-
color: Highlight !important;
|
|
1518
|
-
}
|
|
1519
|
-
[data-slot="badge"] {
|
|
1520
|
-
background-color: Canvas !important;
|
|
1521
|
-
border-color: CanvasText !important;
|
|
1522
|
-
color: CanvasText !important;
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
[data-slot="checkbox"][data-state="checked"] *,
|
|
1526
|
-
[data-slot="checkbox"][data-state="indeterminate"] * {
|
|
1527
|
-
color: HighlightText !important;
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
[data-slot="avatar"] {
|
|
1531
|
-
border: 2px solid CanvasText !important;
|
|
1532
|
-
}
|
|
1533
|
-
[data-slot="avatar"]::after {
|
|
1534
|
-
display: none !important;
|
|
1535
|
-
}
|
|
1536
|
-
[data-slot="avatar-fallback"] {
|
|
1537
|
-
background-color: Canvas !important;
|
|
1538
|
-
color: CanvasText !important;
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
|
-
/* Checked checkboxes / radios — Highlight brand fill */
|
|
1542
|
-
[data-slot="checkbox"][data-state="checked"],
|
|
1543
|
-
[data-slot="checkbox"][data-state="indeterminate"] {
|
|
1544
|
-
background-color: Highlight !important;
|
|
1545
|
-
border-color: Highlight !important;
|
|
1546
|
-
color: HighlightText !important;
|
|
1547
|
-
}
|
|
1548
|
-
[data-slot="radio-group-item"][data-state="checked"] {
|
|
1549
|
-
background-color: Highlight !important;
|
|
1550
|
-
border-color: Highlight !important;
|
|
1551
|
-
}
|
|
1552
|
-
[data-slot="radio-group-item"][data-state="checked"] [data-slot="radio-group-indicator"] span {
|
|
1553
|
-
background-color: HighlightText !important;
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
/* Switch ON — Highlight fill */
|
|
1557
|
-
[role="switch"][aria-checked="true"] {
|
|
1558
|
-
background-color: Highlight !important;
|
|
1559
|
-
border-color: Highlight !important;
|
|
1560
|
-
}
|
|
1561
|
-
[role="switch"][aria-checked="true"] > span {
|
|
1562
|
-
background-color: HighlightText !important;
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
/* Toggle ON — Highlight fill */
|
|
1566
|
-
[data-slot="toggle"][data-state="on"],
|
|
1567
|
-
[data-slot="toggle-group-item"][data-state="on"] {
|
|
1568
|
-
background-color: Highlight !important;
|
|
1569
|
-
color: HighlightText !important;
|
|
1570
|
-
border-color: Highlight !important;
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
/* Progress bars — bordered track with CanvasText fill */
|
|
1574
|
-
[role="progressbar"] {
|
|
1575
|
-
border: 1px solid CanvasText !important;
|
|
1576
|
-
background-color: Canvas !important;
|
|
1577
|
-
}
|
|
1578
|
-
[role="progressbar"] > * {
|
|
1579
|
-
background-color: CanvasText !important;
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
/* Portal overlays — explicit Canvas pairing (OS often strips popover fills) */
|
|
1583
|
-
[data-slot="dropdown-menu-content"],
|
|
1584
|
-
[data-slot="dropdown-menu-sub-content"],
|
|
1585
|
-
[data-slot="popover-content"],
|
|
1586
|
-
[data-slot="select-content"],
|
|
1587
|
-
[data-slot="dialog-content"],
|
|
1588
|
-
[data-slot="sheet-content"],
|
|
1589
|
-
[data-slot="drawer-content"] {
|
|
1590
|
-
border: 2px solid CanvasText !important;
|
|
1591
|
-
background-color: Canvas !important;
|
|
1592
|
-
color: CanvasText !important;
|
|
1593
|
-
}
|
|
1594
|
-
|
|
1595
|
-
[data-slot="command"] {
|
|
1596
|
-
background-color: Canvas !important;
|
|
1597
|
-
color: CanvasText !important;
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
/* Board cards — border-defined shape when fills are stripped */
|
|
1601
|
-
[data-slot="board-card"] {
|
|
1602
|
-
border: 2px solid CanvasText !important;
|
|
1603
|
-
background-color: Canvas !important;
|
|
1604
|
-
color: CanvasText !important;
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
/* List hub status badges — border-only, text readable */
|
|
1608
|
-
[data-slot="list-hub-status-badge"] {
|
|
1609
|
-
border: 2px solid CanvasText !important;
|
|
1610
|
-
background-color: Canvas !important;
|
|
1611
|
-
color: CanvasText !important;
|
|
1612
|
-
font-weight: 700 !important;
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
/* Insight cards — strip gradient, add border */
|
|
1616
|
-
[aria-label="Insight"],
|
|
1617
|
-
[data-slot="insight-card"] {
|
|
1618
|
-
border: 2px solid CanvasText !important;
|
|
1619
|
-
background: Canvas !important;
|
|
1620
|
-
color: CanvasText !important;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
/* Coach marks / guided tours */
|
|
1624
|
-
[data-slot="coach-mark"] {
|
|
1625
|
-
border: 2px solid CanvasText !important;
|
|
1626
|
-
background-color: Canvas !important;
|
|
1627
|
-
color: CanvasText !important;
|
|
1628
|
-
}
|
|
1629
|
-
[data-slot="coach-mark"] * {
|
|
1630
|
-
color: CanvasText !important;
|
|
1631
|
-
}
|
|
1632
|
-
|
|
1633
|
-
/* Avatars — thicken existing ::after ring */
|
|
1634
|
-
[data-slot="avatar"]::after {
|
|
1635
|
-
border-width: 2px !important;
|
|
1636
|
-
border-color: CanvasText !important;
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
/* Breadcrumbs */
|
|
1640
|
-
[data-slot="breadcrumb-separator"] {
|
|
1641
|
-
color: CanvasText !important;
|
|
1642
|
-
}
|
|
1643
|
-
[data-slot="breadcrumb-link"] {
|
|
1644
|
-
color: LinkText !important;
|
|
1645
|
-
}
|
|
1646
|
-
[data-slot="breadcrumb-page"] {
|
|
1647
|
-
color: CanvasText !important;
|
|
1648
|
-
font-weight: 700 !important;
|
|
1649
|
-
}
|
|
1650
|
-
|
|
1651
|
-
/* Tooltip */
|
|
1652
|
-
[data-slot="tooltip-content"] {
|
|
1653
|
-
border: 2px solid CanvasText !important;
|
|
1654
|
-
background-color: Canvas !important;
|
|
1655
|
-
color: CanvasText !important;
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
/* Export drawer */
|
|
1659
|
-
[data-slot="export-drawer"] {
|
|
1660
|
-
border: 2px solid CanvasText !important;
|
|
1661
|
-
background-color: Canvas !important;
|
|
1662
|
-
color: CanvasText !important;
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
|
-
/* Separators */
|
|
1666
|
-
[data-slot="separator"] {
|
|
1667
|
-
background-color: CanvasText !important;
|
|
1668
|
-
opacity: 1 !important;
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
/* Charts — forced-colors strips SVG fills; add stroke as fallback */
|
|
1672
|
-
svg path, svg rect, svg circle {
|
|
1673
|
-
forced-color-adjust: none;
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
/* Recharts radial bars, lines, and area — explicit stroke fallbacks */
|
|
1677
|
-
.recharts-radial-bar-sector,
|
|
1678
|
-
.recharts-line-curve,
|
|
1679
|
-
.recharts-area-curve {
|
|
1680
|
-
forced-color-adjust: none;
|
|
1681
|
-
stroke: CanvasText !important;
|
|
1682
|
-
}
|
|
1683
|
-
|
|
1684
|
-
.recharts-radial-bar-background-sector {
|
|
1685
|
-
forced-color-adjust: none;
|
|
1686
|
-
fill: Canvas !important;
|
|
1687
|
-
stroke: GrayText !important;
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
.recharts-cartesian-axis-tick-value {
|
|
1691
|
-
fill: CanvasText !important;
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
|
-
.recharts-cartesian-grid line {
|
|
1695
|
-
stroke: GrayText !important;
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
.recharts-legend-item-text {
|
|
1699
|
-
color: CanvasText !important;
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
|
-
.recharts-tooltip-wrapper {
|
|
1703
|
-
border: 2px solid CanvasText !important;
|
|
1704
|
-
background-color: Canvas !important;
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
|
|
1708
|
-
/* ==========================================================================
|
|
1709
|
-
Base layer — global element defaults with AA focus management
|
|
1710
|
-
========================================================================== */
|
|
1711
|
-
@layer base {
|
|
1712
|
-
/* Reset + border-color default */
|
|
1713
|
-
*, *::before, *::after {
|
|
1714
|
-
@apply border-border;
|
|
1715
|
-
box-sizing: border-box;
|
|
1716
|
-
}
|
|
1717
|
-
|
|
1718
|
-
/* Body — outer canvas matches sidebar; main column uses bg-background (white in light) */
|
|
1719
|
-
body {
|
|
1720
|
-
@apply bg-sidebar text-foreground antialiased;
|
|
1721
|
-
font-family: var(--font-sans);
|
|
1722
|
-
/* 14px baseline on body. 1rem stays = 16px so all shadcn rem-based
|
|
1723
|
-
layout (spacing, heights, radii) is unaffected at any zoom level. */
|
|
1724
|
-
font-size: 0.875rem;
|
|
1725
|
-
line-height: 1.5;
|
|
1726
|
-
/* Font smoothing: see apps/web/app/globals.css body block (macOS-only effect; Windows ClearType unchanged). */
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
html {
|
|
1730
|
-
@apply font-sans;
|
|
1731
|
-
color-scheme: light;
|
|
1732
|
-
/* Match sidebar canvas (body) on overscroll */
|
|
1733
|
-
background-color: var(--sidebar);
|
|
1734
|
-
}
|
|
1735
|
-
|
|
1736
|
-
html.dark {
|
|
1737
|
-
color-scheme: dark;
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
/* ── Focus management (WCAG 2.4.11 / 2.4.7) ──────────────────── */
|
|
1741
|
-
/* Visible on keyboard navigation only; hidden for mouse users */
|
|
1742
|
-
:focus-visible {
|
|
1743
|
-
outline: 2px solid var(--ring);
|
|
1744
|
-
outline-offset: 2px;
|
|
1745
|
-
border-radius: var(--radius-sm, 4px);
|
|
1746
|
-
}
|
|
1747
|
-
|
|
1748
|
-
/* Suppress outline for mouse/touch (Safari workaround) */
|
|
1749
|
-
:focus:not(:focus-visible) {
|
|
1750
|
-
outline: none;
|
|
1751
|
-
}
|
|
1752
|
-
|
|
1753
|
-
/* ── Reduced motion (WCAG 2.3.3) ────────────────────────────── */
|
|
1754
|
-
@media (prefers-reduced-motion: reduce) {
|
|
1755
|
-
*, *::before, *::after {
|
|
1756
|
-
animation-duration: 0.01ms !important;
|
|
1757
|
-
animation-iteration-count: 1 !important;
|
|
1758
|
-
transition-duration: 0.01ms !important;
|
|
1759
|
-
scroll-behavior: auto !important;
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
/* ── Touch targets (WCAG 2.5.5) ─────────────────────────────── */
|
|
1764
|
-
/* Applied via utility: min-h-[var(--control-height-touch)] */
|
|
1765
|
-
/* Global touch-target baseline for interactive elements on mobile */
|
|
1766
|
-
@media (max-width: 767px) {
|
|
1767
|
-
button,
|
|
1768
|
-
[role="button"],
|
|
1769
|
-
[role="checkbox"],
|
|
1770
|
-
[role="radio"],
|
|
1771
|
-
[role="switch"],
|
|
1772
|
-
[role="menuitem"],
|
|
1773
|
-
[role="tab"],
|
|
1774
|
-
a {
|
|
1775
|
-
min-height: var(--control-height-touch, 44px);
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
|
|
1779
|
-
/* ── Heading hierarchy ───────────────────────────────────────── */
|
|
1780
|
-
/* Ivy Presto (font-heading) applied ONLY via explicit class/inline style
|
|
1781
|
-
on PageHeader <h1>. All other headings use Inter (font-sans). */
|
|
1782
|
-
h1, h2, h3, h4, h5, h6 {
|
|
1783
|
-
font-family: var(--font-sans);
|
|
1784
|
-
font-weight: 600;
|
|
1785
|
-
line-height: 1.25;
|
|
1786
|
-
color: var(--foreground);
|
|
1787
|
-
}
|
|
1788
|
-
|
|
1789
|
-
/* ── Skip to main content (WCAG 2.4.1) ─────────────────────── */
|
|
1790
|
-
.skip-to-content {
|
|
1791
|
-
position: absolute;
|
|
1792
|
-
left: -9999px;
|
|
1793
|
-
top: auto;
|
|
1794
|
-
width: 1px;
|
|
1795
|
-
height: 1px;
|
|
1796
|
-
overflow: hidden;
|
|
1797
|
-
z-index: 9999;
|
|
1798
|
-
}
|
|
1799
|
-
|
|
1800
|
-
.skip-to-content:focus {
|
|
1801
|
-
position: fixed;
|
|
1802
|
-
top: 0;
|
|
1803
|
-
left: 0;
|
|
1804
|
-
width: auto;
|
|
1805
|
-
height: auto;
|
|
1806
|
-
padding: 0.75rem 1.25rem;
|
|
1807
|
-
background: var(--background);
|
|
1808
|
-
color: var(--foreground);
|
|
1809
|
-
border: 2px solid var(--ring);
|
|
1810
|
-
border-radius: var(--radius-md);
|
|
1811
|
-
font-weight: 600;
|
|
1812
|
-
font-size: 1rem;
|
|
1813
|
-
z-index: 9999;
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
|
|
1817
|
-
/* ==========================================================================
|
|
1818
|
-
Utility layer — design-system helpers
|
|
1819
|
-
========================================================================== */
|
|
1820
|
-
@layer utilities {
|
|
1821
|
-
/* Visually hidden but accessible to screen readers (WCAG 1.3.1) */
|
|
1822
|
-
.sr-only {
|
|
1823
|
-
position: absolute;
|
|
1824
|
-
width: 1px;
|
|
1825
|
-
height: 1px;
|
|
1826
|
-
padding: 0;
|
|
1827
|
-
margin: -1px;
|
|
1828
|
-
overflow: hidden;
|
|
1829
|
-
clip: rect(0, 0, 0, 0);
|
|
1830
|
-
white-space: nowrap;
|
|
1831
|
-
border-width: 0;
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
/* AA-safe muted text — use instead of text-muted-foreground on light bg */
|
|
1835
|
-
.text-aa-muted {
|
|
1836
|
-
color: oklch(0.50 0.012 270); /* 5.5:1 on white ✓ */
|
|
1837
|
-
}
|
|
1838
|
-
|
|
1839
|
-
/* Touch-target wrapper for icon buttons (mobile only) */
|
|
1840
|
-
.touch-target {
|
|
1841
|
-
min-height: var(--control-height-touch, 44px);
|
|
1842
|
-
min-width: var(--control-height-touch, 44px);
|
|
1843
|
-
display: inline-flex;
|
|
1844
|
-
align-items: center;
|
|
1845
|
-
justify-content: center;
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
@media (min-width: 768px) {
|
|
1849
|
-
.touch-target {
|
|
1850
|
-
min-height: unset;
|
|
1851
|
-
min-width: unset;
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
|
-
/* Form field border — use --control-border (3:1 minimum) */
|
|
1856
|
-
.field-border {
|
|
1857
|
-
border-color: var(--control-border);
|
|
1858
|
-
}
|
|
1859
|
-
|
|
1860
|
-
/* Exxat Prism highlight banner */
|
|
1861
|
-
.banner-prism {
|
|
1862
|
-
background-color: var(--banner-prism-bg);
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
/* After all @layer rules: win over Tailwind preflight / layer merge so real controls show a pointer. */
|
|
1867
|
-
button:not(:disabled):not([disabled]),
|
|
1868
|
-
[role="button"]:not([aria-disabled="true"]):not([data-disabled]) {
|
|
1869
|
-
cursor: pointer;
|
|
1870
|
-
}
|
|
15
|
+
@import "./tokens/tailwind-bridge.css";
|
|
16
|
+
@import "./tokens/base.css";
|
|
17
|
+
@import "./tokens/themes.css";
|
|
18
|
+
@import "./tokens/high-contrast.css";
|
|
19
|
+
@import "./tokens/layers.css";
|