@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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Design tokens (CSS modules)
|
|
2
|
+
|
|
3
|
+
Structural split of the former monolithic `globals.css`. **No token values were changed** — only file boundaries.
|
|
4
|
+
|
|
5
|
+
| File | Contents |
|
|
6
|
+
|------|----------|
|
|
7
|
+
| `tailwind-bridge.css` | `@theme inline` (Tailwind v4 color/radius map), `html[data-text-size]` |
|
|
8
|
+
| `base.css` | `:root` light defaults, `.dark` semantic overrides |
|
|
9
|
+
| `themes.css` | `.theme-one`, `.theme-prism`, `.theme-assessment`, `.theme-custom`, secondary panel paint |
|
|
10
|
+
| `high-contrast.css` | `data-contrast`, `prefers-contrast`, `forced-colors` |
|
|
11
|
+
| `layers.css` | `@layer base`, `@layer utilities`, global cursor rule |
|
|
12
|
+
|
|
13
|
+
**Entry points:** `../globals.css` (Tailwind + tokens), `../theme.css` (tokens only for apps that import Tailwind separately).
|
|
14
|
+
|
|
15
|
+
**App wiring:** `apps/web/app/globals.css` imports Tailwind, `@source`, variants, then these files via `../../../packages/ui/src/tokens/…`.
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
:root — Exxat One · Light Mode (brand hue 286.1)
|
|
3
|
+
All contrast ratios verified against oklch(1 0 0) white background.
|
|
4
|
+
========================================================================== */
|
|
5
|
+
:root {
|
|
6
|
+
/* font-size intentionally NOT overridden here.
|
|
7
|
+
Shadcn components assume 1rem = 16px (browser default).
|
|
8
|
+
Overriding to 87.5% / 14px breaks rem-based spacing on all devices,
|
|
9
|
+
and compounds incorrectly at Windows 150% system zoom.
|
|
10
|
+
If a compact 14px density is needed, apply it at the component/page level
|
|
11
|
+
via a scoped class, not globally on :root. */
|
|
12
|
+
/* Minimum readable UI copy: 11px (`text-xs` / --text-xs). Do not use smaller arbitrary sizes. */
|
|
13
|
+
|
|
14
|
+
/* ── Layout ─────────────────────────────────────────────────── */
|
|
15
|
+
/* SiteHeader / breadcrumb height. Mirrored on the SidebarProvider for
|
|
16
|
+
descendants; declared here too so JS that reads from documentElement
|
|
17
|
+
(e.g. DataTable sticky-head offset) can resolve it. Plain px so
|
|
18
|
+
`parseFloat` can read it as a number. Keep in sync with `headerHeight`
|
|
19
|
+
in components/sidebar-shell.tsx (currently `calc(var(--spacing) * 12)` = 48px). */
|
|
20
|
+
--header-height: 48px;
|
|
21
|
+
|
|
22
|
+
/* ── Typography ─────────────────────────────────────────────── */
|
|
23
|
+
/* Ivy Presto loaded via Adobe Fonts Kit wuk5wqn (use.typekit.net) */
|
|
24
|
+
--font-heading: "ivypresto-text";
|
|
25
|
+
|
|
26
|
+
/* ── Brand — Exxat One (hue 286.1) ─────────────────────────── */
|
|
27
|
+
/* Primary surface — requested token */
|
|
28
|
+
--brand-tint: oklch(0.9676 0.016 286.1);
|
|
29
|
+
/* Lighter / darker washes (same hue) for nested UI & hovers */
|
|
30
|
+
--brand-tint-light: oklch(0.993 0.007 286.1);
|
|
31
|
+
--brand-tint-subtle: oklch(0.935 0.024 286.1);
|
|
32
|
+
/* Interactive accent + scale (readable on white; pairs with --brand-tint) */
|
|
33
|
+
--brand-color: oklch(0.50 0.14 286.1);
|
|
34
|
+
--brand-color-light: oklch(0.78 0.09 286.1);
|
|
35
|
+
--brand-color-dark: oklch(0.38 0.11 286.1);
|
|
36
|
+
--brand-color-deep: oklch(0.28 0.085 286.1);
|
|
37
|
+
--brand-foreground: oklch(0.985 0 0);
|
|
38
|
+
/* Fixed swatches for brand picker (Exxat One vs Prism), independent of active theme */
|
|
39
|
+
--brand-preview-one: var(--brand-tint);
|
|
40
|
+
--brand-preview-prism: oklch(0.57 0.24 342);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Ask Leo panel tints (same mixes as the vertical wash). Use for blobs, cards, etc.
|
|
44
|
+
* `--leo-surface-gradient` is the full linear wash on `AskLeoSidebar`.
|
|
45
|
+
*/
|
|
46
|
+
--leo-surface-tint-a: color-mix(in oklch, var(--brand-color) 4%, var(--background));
|
|
47
|
+
--leo-surface-tint-b: color-mix(in oklch, var(--brand-color) 8%, var(--background));
|
|
48
|
+
--leo-surface-gradient: linear-gradient(180deg, var(--leo-surface-tint-a) 0%, var(--leo-surface-tint-b) 100%);
|
|
49
|
+
|
|
50
|
+
/* KeyMetrics `variant="flat"` — no band surface; bottom brand glow only (OKLCH). */
|
|
51
|
+
--key-metrics-flat-cell-bg: transparent;
|
|
52
|
+
--key-metrics-flat-divider: color-mix(in oklch, var(--sidebar-border) 55%, transparent);
|
|
53
|
+
--key-metrics-flat-band-radial: radial-gradient(
|
|
54
|
+
ellipse 120% 68% at 50% 100%,
|
|
55
|
+
color-mix(in oklch, var(--brand-color) 20%, transparent) 0%,
|
|
56
|
+
color-mix(in oklch, var(--brand-color) 8%, transparent) 42%,
|
|
57
|
+
transparent 72%
|
|
58
|
+
);
|
|
59
|
+
--key-metrics-flat-band-shadow: none;
|
|
60
|
+
--key-metrics-card-glow-radial: radial-gradient(
|
|
61
|
+
ellipse 110% 90% at 50% 100%,
|
|
62
|
+
color-mix(in oklch, var(--brand-color) 18%, transparent) 0%,
|
|
63
|
+
transparent 65%
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
/* ── Surfaces ────────────────────────────────────────────────── */
|
|
67
|
+
--background: oklch(1 0 0);
|
|
68
|
+
--foreground: oklch(0.145 0 0); /* ≈ #1A1A1A — 17:1 on white ✓ */
|
|
69
|
+
--card: oklch(1 0 0);
|
|
70
|
+
--card-foreground: oklch(0.145 0 0);
|
|
71
|
+
--popover: oklch(1 0 0);
|
|
72
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
73
|
+
|
|
74
|
+
/* ── Primary ─────────────────────────────────────────────────── */
|
|
75
|
+
/* Default / ghost / solid primary actions — neutral charcoal (style guide) */
|
|
76
|
+
--primary: oklch(0.3457 0.0052 286.13);
|
|
77
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
78
|
+
|
|
79
|
+
/* ── Secondary / Muted / Accent ──────────────────────────────── */
|
|
80
|
+
--secondary: oklch(0.95 0.0058 264.53);
|
|
81
|
+
--secondary-foreground: oklch(0.082 0 0);
|
|
82
|
+
--muted: oklch(0.945 0.002 270);
|
|
83
|
+
--muted-foreground: oklch(0.50 0.012 270); /* 5.5:1 on white ✓ */
|
|
84
|
+
--accent: oklch(0.925 0.005 260);
|
|
85
|
+
--accent-foreground: oklch(0.082 0 0);
|
|
86
|
+
|
|
87
|
+
/* ── Destructive ─────────────────────────────────────────────── */
|
|
88
|
+
/* oklch(0.55 0.22 25) ≈ #C0392B — 5.1:1 on white ✓ */
|
|
89
|
+
--destructive: oklch(0.55 0.22 25);
|
|
90
|
+
--destructive-foreground: oklch(1 0 0);
|
|
91
|
+
|
|
92
|
+
/* ── Borders ─────────────────────────────────────────────────── */
|
|
93
|
+
/* Decorative: cards, dividers — no AA contrast requirement */
|
|
94
|
+
--border: oklch(0.92 0.002 270);
|
|
95
|
+
|
|
96
|
+
/* Form-field boundary — WCAG 1.4.11 requires 3:1 against bg.
|
|
97
|
+
--border-control-3: L=0.62 ≈ #90929A → borderline; use with care.
|
|
98
|
+
--border-control-35: L=0.25 → ≥ 3.5:1 — recommended for inputs. */
|
|
99
|
+
--border-control: oklch(0.82 0.004 270); /* subtle (layout use only) */
|
|
100
|
+
--border-control-3: oklch(0.6196 0.0092 270); /* ≈ 3:1 on white (minimum) */
|
|
101
|
+
--border-control-35: oklch(0.25 0.01 270); /* ≈ 3.5:1+ (recommended) */
|
|
102
|
+
--control-border: var(--border-control-3); /* default form-field border */
|
|
103
|
+
|
|
104
|
+
/* ── Input ───────────────────────────────────────────────────── */
|
|
105
|
+
/* Raised contrast target for control outlines (>= 3.1:1 on white). */
|
|
106
|
+
--input: oklch(0.62 0.01 264.52);
|
|
107
|
+
--input-background: oklch(0.97 0.002 270);
|
|
108
|
+
|
|
109
|
+
/* ── Focus ring ──────────────────────────────────────────────── */
|
|
110
|
+
/* 3:1+ contrast on both light & dark backgrounds (WCAG 2.4.11) */
|
|
111
|
+
--ring: oklch(0.25 0 0);
|
|
112
|
+
|
|
113
|
+
/* ── Charts ──────────────────────────────────────────────────── */
|
|
114
|
+
--chart-1: oklch(0.55 0.22 264.116);
|
|
115
|
+
--chart-2: oklch(0.48 0.15 184.704);
|
|
116
|
+
--chart-3: oklch(0.32 0.08 227.392);
|
|
117
|
+
--chart-4: oklch(0.65 0.18 84.429);
|
|
118
|
+
--chart-5: oklch(0.58 0.18 70.08);
|
|
119
|
+
|
|
120
|
+
/* ── Chip / Badge ────────────────────────────────────────────── */
|
|
121
|
+
/* AA-compliant on white: all ≥ 4.5:1 (WCAG 1.4.3) */
|
|
122
|
+
--chip-1: oklch(0.38 0.18 264); /* indigo */
|
|
123
|
+
--chip-2: oklch(0.35 0.14 184); /* teal */
|
|
124
|
+
--chip-3: oklch(0.32 0.08 227); /* slate */
|
|
125
|
+
--chip-4: oklch(0.42 0.12 84); /* amber */
|
|
126
|
+
--chip-5: oklch(0.42 0.14 70); /* orange */
|
|
127
|
+
--chip-destructive: oklch(0.40 0.18 25); /* red */
|
|
128
|
+
|
|
129
|
+
/* ── Prism promo banner ──────────────────────────────────────── */
|
|
130
|
+
/* Rose hue 343 — used universally regardless of active theme */
|
|
131
|
+
--banner-prism-bg: oklch(0.97 0.02 343);
|
|
132
|
+
|
|
133
|
+
/* ── Sidebar — Exxat One brand tint ───────────────────────────── */
|
|
134
|
+
--sidebar: var(--brand-tint);
|
|
135
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
136
|
+
--sidebar-primary: oklch(0.082 0 0);
|
|
137
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
138
|
+
--sidebar-accent: oklch(0.945 0.025 286.1);
|
|
139
|
+
--sidebar-accent-foreground: oklch(0.3457 0.0052 286.13);
|
|
140
|
+
--sidebar-border: oklch(0.92 0.025 286.1);
|
|
141
|
+
--sidebar-ring: oklch(0.25 0 0);
|
|
142
|
+
/* Nav section titles — ≥4.5:1 vs --sidebar (not vs page white) */
|
|
143
|
+
--sidebar-section-label-foreground: color-mix(in oklch, var(--sidebar-foreground) 58%, var(--sidebar));
|
|
144
|
+
/* Nested secondary rail — elevation 1: brand wash, lighter than `--sidebar` / `--brand-tint`. */
|
|
145
|
+
--secondary-panel-bg: color-mix(in oklch, var(--background) 40%, var(--brand-tint-light) 60%);
|
|
146
|
+
|
|
147
|
+
/* Browser UI (meta theme-color) — aligned with --brand-tint */
|
|
148
|
+
--theme-color-chrome: #f3f2f8;
|
|
149
|
+
|
|
150
|
+
/* ── Border radius ───────────────────────────────────────────── */
|
|
151
|
+
--radius: 0.5rem; /* 8px base */
|
|
152
|
+
|
|
153
|
+
/* ── Density / touch targets ─────────────────────────────────── */
|
|
154
|
+
--scaling: 1;
|
|
155
|
+
--control-height: calc(40px * var(--scaling));
|
|
156
|
+
--control-height-sm: calc(32px * var(--scaling));
|
|
157
|
+
/* WCAG 2.5.5 — minimum 44×44 px touch target (mobile only) */
|
|
158
|
+
--control-height-touch: 44px;
|
|
159
|
+
--control-padding-y: calc(8px * var(--scaling));
|
|
160
|
+
--control-padding-x: calc(12px * var(--scaling));
|
|
161
|
+
--table-row-height: calc(48px * var(--scaling));
|
|
162
|
+
|
|
163
|
+
/* ── Interactive hover (ties to --muted / --accent — theme overrides apply) ─ */
|
|
164
|
+
--interactive-hover: var(--muted);
|
|
165
|
+
--interactive-hover-foreground: var(--foreground);
|
|
166
|
+
--interactive-hover-subtle: color-mix(in oklch, var(--muted) 50%, var(--background));
|
|
167
|
+
--interactive-hover-soft: color-mix(in oklch, var(--muted) 40%, var(--background));
|
|
168
|
+
--interactive-hover-medium: color-mix(in oklch, var(--muted) 60%, var(--background));
|
|
169
|
+
--interactive-hover-strong: color-mix(in oklch, var(--muted) 70%, var(--background));
|
|
170
|
+
--interactive-hover-row: color-mix(in oklch, var(--accent) 50%, var(--background));
|
|
171
|
+
|
|
172
|
+
/* ── DataTable — opaque row/cell surfaces (pinned cells MUST be opaque) ── */
|
|
173
|
+
--dt-row-bg: var(--background);
|
|
174
|
+
--dt-row-hover: oklch(0.972 0.001 270);
|
|
175
|
+
--dt-row-selected: oklch(0.962 0.003 260);
|
|
176
|
+
--dt-row-selected-fg: var(--foreground);
|
|
177
|
+
--dt-header-bg: var(--background);
|
|
178
|
+
--dt-group-bg: oklch(0.972 0.001 270);
|
|
179
|
+
--dt-new-row-bg: oklch(from var(--brand-color) 0.985 0.006 h);
|
|
180
|
+
--dt-new-row-border: var(--brand-color);
|
|
181
|
+
|
|
182
|
+
/* ── Transitions ─────────────────────────────────────────────── */
|
|
183
|
+
--transition-fast: 0.15s ease;
|
|
184
|
+
--transition-normal: 0.25s ease-in-out;
|
|
185
|
+
--transition-colors: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
|
|
186
|
+
|
|
187
|
+
/* ── Shadows ─────────────────────────────────────────────────── */
|
|
188
|
+
--shadow-sm: oklch(0 0 0 / 0.08) 0px 1px 2px 0px;
|
|
189
|
+
--shadow-md: oklch(0 0 0 / 0.08) 0px 2px 4px -1px, oklch(0 0 0 / 0.06) 0px 1px 2px;
|
|
190
|
+
--shadow-lg: oklch(0 0 0 / 0.10) 0px 4px 8px -2px, oklch(0 0 0 / 0.06) 0px 2px 4px;
|
|
191
|
+
|
|
192
|
+
/* ── Sticky column edge fade (data tables) ───────────────────── */
|
|
193
|
+
--sticky-edge-fade: oklch(0 0 0 / 0.08);
|
|
194
|
+
|
|
195
|
+
/* ── Overlay scrim (Sheet / Drawer / Dialog) ─────────────────── */
|
|
196
|
+
/* Softer than raw bg-black/10; follows foreground hue (not pure black) */
|
|
197
|
+
--overlay: color-mix(in oklch, var(--foreground) 5%, transparent);
|
|
198
|
+
|
|
199
|
+
/* ── Avatar initials (table) ───────────────────────────────────── */
|
|
200
|
+
/* Soft brand wash + brand ink — no black fills; ≥4.5:1 on white rows */
|
|
201
|
+
--avatar-initials-bg: color-mix(in oklch, var(--brand-color) 14%, oklch(1 0 0));
|
|
202
|
+
--avatar-initials-fg: var(--brand-color-dark);
|
|
203
|
+
|
|
204
|
+
/* ── KPI insight severity (KeyMetrics) ────────────────────────── */
|
|
205
|
+
--insight-severity-warning-bg: color-mix(in oklch, var(--chart-4) 15%, transparent);
|
|
206
|
+
--insight-severity-warning-fg: color-mix(in oklch, var(--chart-4) 75%, var(--foreground));
|
|
207
|
+
--insight-severity-info-bg: color-mix(in oklch, var(--chart-1) 14%, transparent);
|
|
208
|
+
--insight-severity-info-fg: color-mix(in oklch, var(--chart-1) 75%, var(--foreground));
|
|
209
|
+
|
|
210
|
+
/* ── Tinted icon discs — soft wash (≈14% tint like legacy inline styles); contrast from --chip-* / brand-dark on fg */
|
|
211
|
+
--icon-disc-chart-2-bg: color-mix(in oklch, var(--chart-2) 14%, transparent);
|
|
212
|
+
--icon-disc-chart-2-fg: var(--chip-2);
|
|
213
|
+
--icon-disc-chart-4-bg: color-mix(in oklch, var(--chart-4) 14%, transparent);
|
|
214
|
+
--icon-disc-chart-4-fg: var(--chip-4);
|
|
215
|
+
--icon-disc-brand-bg: color-mix(in oklch, var(--brand-color) 12%, transparent);
|
|
216
|
+
--icon-disc-brand-fg: var(--brand-color-dark);
|
|
217
|
+
--icon-disc-danger-bg: color-mix(in oklch, var(--destructive) 14%, transparent);
|
|
218
|
+
--icon-disc-danger-fg: var(--chip-destructive);
|
|
219
|
+
|
|
220
|
+
/* ── Conditional formatting rule backgrounds (table drawer) ─── */
|
|
221
|
+
--conditional-rule-green: color-mix(in oklch, var(--chart-2) 22%, transparent);
|
|
222
|
+
--conditional-rule-yellow: color-mix(in oklch, var(--chart-4) 30%, transparent);
|
|
223
|
+
--conditional-rule-blue: color-mix(in oklch, var(--chart-1) 22%, transparent);
|
|
224
|
+
--conditional-rule-red: color-mix(in oklch, var(--destructive) 22%, transparent);
|
|
225
|
+
--conditional-rule-purple: color-mix(in oklch, var(--brand-color) 22%, transparent);
|
|
226
|
+
--conditional-rule-orange: color-mix(in oklch, var(--chart-5) 25%, transparent);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* ==========================================================================
|
|
230
|
+
Dark Mode — Exxat One base (neutral surfaces; brand uses --brand-*)
|
|
231
|
+
========================================================================== */
|
|
232
|
+
.dark {
|
|
233
|
+
--sticky-edge-fade: oklch(0 0 0 / 0.32);
|
|
234
|
+
|
|
235
|
+
/* Canvas — charcoal grey (not near-black) */
|
|
236
|
+
--background: oklch(0.20 0.008 270);
|
|
237
|
+
--foreground: oklch(0.985 0 0);
|
|
238
|
+
--card: oklch(0.255 0.008 270);
|
|
239
|
+
--card-foreground: oklch(0.985 0 0);
|
|
240
|
+
--popover: oklch(0.255 0.008 270);
|
|
241
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
242
|
+
--primary: oklch(0.985 0 0);
|
|
243
|
+
--primary-foreground: oklch(0.3457 0.0052 286.13);
|
|
244
|
+
--secondary: oklch(0.31 0.04 270);
|
|
245
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
246
|
+
--muted: oklch(0.31 0.04 270);
|
|
247
|
+
--muted-foreground: oklch(0.72 0.012 270); /* ≥ 4.5:1 on dark bg ✓ */
|
|
248
|
+
--accent: oklch(0.33 0.06 270);
|
|
249
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
250
|
+
--destructive: oklch(0.65 0.20 25); /* brighter for dark bg */
|
|
251
|
+
--destructive-foreground: oklch(0.10 0 0);
|
|
252
|
+
|
|
253
|
+
/* KeyMetrics flat band — no surface; bottom brand glow only (OKLCH). */
|
|
254
|
+
--key-metrics-flat-cell-bg: transparent;
|
|
255
|
+
--key-metrics-flat-divider: color-mix(in oklch, var(--sidebar-border) 55%, transparent);
|
|
256
|
+
--key-metrics-flat-band-radial: radial-gradient(
|
|
257
|
+
ellipse 120% 68% at 50% 100%,
|
|
258
|
+
color-mix(in oklch, var(--brand-color) 26%, transparent) 0%,
|
|
259
|
+
color-mix(in oklch, var(--brand-color) 10%, transparent) 42%,
|
|
260
|
+
transparent 72%
|
|
261
|
+
);
|
|
262
|
+
--key-metrics-flat-band-shadow: none;
|
|
263
|
+
--key-metrics-card-glow-radial: radial-gradient(
|
|
264
|
+
ellipse 110% 90% at 50% 100%,
|
|
265
|
+
color-mix(in oklch, var(--brand-color) 22%, transparent) 0%,
|
|
266
|
+
transparent 62%
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
/* Borders — visible but not washed out on dark surfaces */
|
|
270
|
+
--border: oklch(0.38 0.008 270);
|
|
271
|
+
--border-control: oklch(0.72 0.012 270);
|
|
272
|
+
--border-control-3: oklch(0.78 0.012 270);
|
|
273
|
+
--border-control-35: oklch(0.75 0.012 270);
|
|
274
|
+
--control-border: var(--border-control-3);
|
|
275
|
+
|
|
276
|
+
--input: oklch(0.72 0.012 270);
|
|
277
|
+
--input-background: oklch(0.255 0 0);
|
|
278
|
+
|
|
279
|
+
/* Focus ring — 3:1+ on dark bg */
|
|
280
|
+
--ring: oklch(0.85 0 0);
|
|
281
|
+
|
|
282
|
+
/* Charts — higher lightness for dark surfaces */
|
|
283
|
+
--chart-1: oklch(0.70 0.22 264.376);
|
|
284
|
+
--chart-2: oklch(0.75 0.15 162.48);
|
|
285
|
+
--chart-3: oklch(0.78 0.12 227.392);
|
|
286
|
+
--chart-4: oklch(0.80 0.18 84.429);
|
|
287
|
+
--chart-5: oklch(0.75 0.18 70.08);
|
|
288
|
+
|
|
289
|
+
/* Chips — AA-compliant on dark bg (L raised) */
|
|
290
|
+
--chip-1: oklch(0.72 0.18 264);
|
|
291
|
+
--chip-2: oklch(0.72 0.14 184);
|
|
292
|
+
--chip-3: oklch(0.78 0.12 227);
|
|
293
|
+
--chip-4: oklch(0.78 0.14 84);
|
|
294
|
+
--chip-5: oklch(0.78 0.16 70);
|
|
295
|
+
--chip-destructive: oklch(0.72 0.18 25);
|
|
296
|
+
|
|
297
|
+
/* Tinted icon discs — same soft transparency wash; fg stays readable on dark canvas */
|
|
298
|
+
--icon-disc-chart-2-bg: color-mix(in oklch, var(--chart-2) 14%, transparent);
|
|
299
|
+
--icon-disc-chart-2-fg: color-mix(in oklch, var(--foreground) 10%, var(--chart-2));
|
|
300
|
+
--icon-disc-chart-4-bg: color-mix(in oklch, var(--chart-4) 14%, transparent);
|
|
301
|
+
--icon-disc-chart-4-fg: color-mix(in oklch, var(--foreground) 10%, var(--chart-4));
|
|
302
|
+
--icon-disc-brand-bg: color-mix(in oklch, var(--brand-color) 12%, transparent);
|
|
303
|
+
--icon-disc-brand-fg: color-mix(in oklch, var(--foreground) 8%, var(--brand-color));
|
|
304
|
+
--icon-disc-danger-bg: color-mix(in oklch, var(--destructive) 14%, transparent);
|
|
305
|
+
--icon-disc-danger-fg: color-mix(in oklch, var(--foreground) 8%, var(--destructive));
|
|
306
|
+
|
|
307
|
+
/* Sidebar */
|
|
308
|
+
--sidebar: oklch(0.245 0.015 270);
|
|
309
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
310
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
311
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
312
|
+
--sidebar-accent: oklch(0.30 0.012 270);
|
|
313
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
314
|
+
--sidebar-border: oklch(0.38 0.010 270);
|
|
315
|
+
--sidebar-ring: oklch(0.85 0 0);
|
|
316
|
+
--sidebar-section-label-foreground: color-mix(in oklch, var(--sidebar-foreground) 48%, var(--sidebar));
|
|
317
|
+
/* Nested secondary rail — elevation 1: lift from sidebar (sidebar + card, not light `--brand-tint`). */
|
|
318
|
+
--secondary-panel-bg: color-mix(in oklch, var(--sidebar) 52%, var(--card) 48%);
|
|
319
|
+
--theme-color-chrome: #2f2d36;
|
|
320
|
+
|
|
321
|
+
/* Lifted scrim on dark — white-tinted veil, not heavy black */
|
|
322
|
+
--overlay: color-mix(in oklch, var(--foreground) 10%, transparent);
|
|
323
|
+
|
|
324
|
+
/* Mid lavender chip + light text — no black circle; contrasts on dark table rows */
|
|
325
|
+
--avatar-initials-bg: color-mix(in oklch, var(--brand-color) 38%, oklch(0.40 0.05 286.1));
|
|
326
|
+
--avatar-initials-fg: oklch(0.99 0.01 286.1);
|
|
327
|
+
|
|
328
|
+
/* DataTable — opaque surfaces for dark mode */
|
|
329
|
+
--dt-row-bg: var(--background);
|
|
330
|
+
--dt-row-hover: oklch(0.24 0.01 270);
|
|
331
|
+
--dt-row-selected: oklch(0.27 0.02 270);
|
|
332
|
+
--dt-row-selected-fg: var(--foreground);
|
|
333
|
+
--dt-header-bg: var(--background);
|
|
334
|
+
--dt-group-bg: oklch(0.24 0.01 270);
|
|
335
|
+
--dt-new-row-bg: oklch(from var(--brand-color) 0.22 0.02 h);
|
|
336
|
+
--dt-new-row-border: var(--brand-color);
|
|
337
|
+
}
|