@lovett/ui 0.0.1
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/README.md +28 -0
- package/package.json +53 -0
- package/src/accordion.tsx +153 -0
- package/src/atoms.tsx +197 -0
- package/src/badge.tsx +91 -0
- package/src/brand-logo-tile.tsx +200 -0
- package/src/bulk-action-bar.tsx +104 -0
- package/src/button-group.tsx +46 -0
- package/src/button.tsx +93 -0
- package/src/calculator-shell-v2.tsx +380 -0
- package/src/calculator-shell.tsx +310 -0
- package/src/card.tsx +369 -0
- package/src/checkbox.tsx +114 -0
- package/src/chip-nav.tsx +347 -0
- package/src/choropleth.tsx +62 -0
- package/src/code-block.tsx +235 -0
- package/src/completion-ring.tsx +119 -0
- package/src/copy-field.tsx +169 -0
- package/src/data-grid/column-options-menu.tsx +127 -0
- package/src/data-grid/data-grid.tsx +391 -0
- package/src/data-grid/drawer-panel.tsx +146 -0
- package/src/data-grid/index.ts +29 -0
- package/src/data-grid/sortable-parts.tsx +215 -0
- package/src/data-grid/table-body.tsx +238 -0
- package/src/data-grid/table-elements.tsx +135 -0
- package/src/data-grid/table-header.tsx +95 -0
- package/src/data-grid/table-overlays.tsx +78 -0
- package/src/data-grid/table-parts.tsx +15 -0
- package/src/data-grid/table-summary-footer.tsx +101 -0
- package/src/data-grid/table-view.tsx +176 -0
- package/src/data-grid/types.ts +141 -0
- package/src/data-grid/use-grid-columns.ts +311 -0
- package/src/data-grid/use-grid-editing.ts +154 -0
- package/src/device-frame.tsx +274 -0
- package/src/dropdown-button.tsx +221 -0
- package/src/dropdown-menu.tsx +450 -0
- package/src/empty-state.tsx +85 -0
- package/src/file-upload/file-drop-zone.tsx +156 -0
- package/src/file-upload/file-preview-grid.tsx +39 -0
- package/src/file-upload/file-preview-item.tsx +175 -0
- package/src/file-upload/file-thumbnail.tsx +98 -0
- package/src/file-upload/file-upload-button.tsx +95 -0
- package/src/file-upload/index.ts +13 -0
- package/src/file-upload/use-file-upload.ts +371 -0
- package/src/filter-bar.tsx +125 -0
- package/src/filter-dropdown.tsx +289 -0
- package/src/floating-drawer.tsx +420 -0
- package/src/folder-card.tsx +188 -0
- package/src/folder-tree-picker.tsx +511 -0
- package/src/format.ts +117 -0
- package/src/frame-stack.tsx +73 -0
- package/src/hero-form-card.tsx +471 -0
- package/src/index.ts +372 -0
- package/src/input.tsx +130 -0
- package/src/kbd.tsx +41 -0
- package/src/lib/layout.ts +22 -0
- package/src/lib/utils.ts +6 -0
- package/src/markdown.tsx +214 -0
- package/src/menu-button.tsx +142 -0
- package/src/meta-previews/CreativeMedia.tsx +119 -0
- package/src/meta-previews/InstagramExplorePreview.tsx +340 -0
- package/src/meta-previews/InstagramFeedCarousel.tsx +245 -0
- package/src/meta-previews/InstagramFeedPreview.tsx +259 -0
- package/src/meta-previews/MetaFeedCarousel.tsx +228 -0
- package/src/meta-previews/MetaFeedPreview.tsx +294 -0
- package/src/meta-previews/MetaInstreamPreview.tsx +135 -0
- package/src/meta-previews/MetaMessengerPreview.tsx +795 -0
- package/src/meta-previews/MetaReelPreview.tsx +750 -0
- package/src/meta-previews/MetaRightColumnPreview.tsx +245 -0
- package/src/meta-previews/MetaSearchPreview.tsx +113 -0
- package/src/meta-previews/MetaStoryPreview.tsx +1132 -0
- package/src/meta-previews/ProfileAvatar.tsx +79 -0
- package/src/meta-previews/defaults.ts +27 -0
- package/src/meta-previews/index.ts +37 -0
- package/src/meta-previews/types.ts +219 -0
- package/src/metric-card.tsx +117 -0
- package/src/modal.tsx +131 -0
- package/src/option-tile.tsx +252 -0
- package/src/page-hero.tsx +78 -0
- package/src/page-shell.tsx +440 -0
- package/src/pagination.tsx +86 -0
- package/src/pill-button.tsx +103 -0
- package/src/profile-section.tsx +389 -0
- package/src/progress-bar.tsx +84 -0
- package/src/radio.tsx +172 -0
- package/src/range-slider.tsx +161 -0
- package/src/resizable.tsx +282 -0
- package/src/search-bar.tsx +81 -0
- package/src/segmented-pill.tsx +143 -0
- package/src/shell.tsx +464 -0
- package/src/slider.tsx +107 -0
- package/src/sortable-table.tsx +198 -0
- package/src/sortable.tsx +137 -0
- package/src/stat-row.tsx +132 -0
- package/src/stats-grid.tsx +38 -0
- package/src/step-loader.tsx +141 -0
- package/src/styles.css +562 -0
- package/src/tabs.tsx +143 -0
- package/src/tag-chip-input.tsx +394 -0
- package/src/textarea.tsx +39 -0
- package/src/toast.tsx +59 -0
- package/src/tokens.css +579 -0
package/src/tokens.css
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @lovett/ui — design tokens
|
|
3
|
+
*
|
|
4
|
+
* Ported from brand-ai-extension/webapp/src/index.css
|
|
5
|
+
* tag : v-pre-workspace-intake-phase1
|
|
6
|
+
* sha : 172dd010fee808bcd03795119ba888206da5bafd
|
|
7
|
+
*
|
|
8
|
+
* Note: in the source repo, tokens live in `webapp/src/index.css`. PRD §7.2
|
|
9
|
+
* still references `webapp/src/styles/tokens.css` — that path does not exist
|
|
10
|
+
* in source. Flagged in Phase 1 completion report as a PRD-correction.
|
|
11
|
+
*
|
|
12
|
+
* This file contains ONLY token declarations (`:root` + `[data-theme="light"]`).
|
|
13
|
+
* Component CSS utilities the primitives consume (`.ds-card-surface`,
|
|
14
|
+
* `.btn`, `.input-shell`, etc.) live in `./styles.css`.
|
|
15
|
+
*
|
|
16
|
+
* Token discipline (CLAUDE.md §4 is the human-readable source of truth;
|
|
17
|
+
* `packages/eslint-config/index.js` mirrors the internal list for ESLint
|
|
18
|
+
* enforcement; ADR-008 Decision 7 makes these three a hard-gate parity check).
|
|
19
|
+
*
|
|
20
|
+
* PUBLIC tokens (apps may use freely):
|
|
21
|
+
* • Brand: --accent, --accent-hover, --accent-muted,
|
|
22
|
+
* --accent-subtle, --accent-glow
|
|
23
|
+
* • Hierarchy: --hierarchy-red, --hierarchy-red-dark,
|
|
24
|
+
* --hierarchy-red-darkest, --hierarchy-red-shadow,
|
|
25
|
+
* --hierarchy-outline, --hierarchy-slate,
|
|
26
|
+
* --hierarchy-on-base
|
|
27
|
+
* (theme-INDEPENDENT; fixed in both themes because
|
|
28
|
+
* the hierarchy SVG overlay sits on an always-light
|
|
29
|
+
* OSM basemap regardless of UI theme)
|
|
30
|
+
* • Text: --foreground, --text-secondary, --text-tertiary,
|
|
31
|
+
* --text-muted, --muted-foreground
|
|
32
|
+
* • Semantic: --success(-bg), --warning(-bg), --info(-bg),
|
|
33
|
+
* --destructive(-foreground)
|
|
34
|
+
* • Folder: --folder-red/amber/emerald/teal/blue/violet/pink/
|
|
35
|
+
* slate/ink (categorical palette for folder accents)
|
|
36
|
+
* • Spacing: --space-1…12 (4 / 8 / 12 / 16 / 20 / 24 / 32 / 40 / 48)
|
|
37
|
+
* • Radius: --radius-xs/sm/md/lg/xl/2xl/full, --radius (legacy)
|
|
38
|
+
* • Motion: --ease-out, --ease-spring, --ease-in-out,
|
|
39
|
+
* --dur-fast, --dur-base, --dur-slow,
|
|
40
|
+
* --transition, --transition-slow (legacy)
|
|
41
|
+
* • Controls: --ctrl-sm/md/lg (32 / 40 / 48 — Button/Input heights)
|
|
42
|
+
* • Focus: --ring-focus, --ring-error
|
|
43
|
+
* • Shadow: --shadow-sm/md/lg/xl/2xl, --shadow-glow
|
|
44
|
+
* • Visual utilities (generic, not surface-specific):
|
|
45
|
+
* --border, --border-strong (divider / separator lines)
|
|
46
|
+
* --surface-overlay, --surface-overlay-soft/strong/stronger
|
|
47
|
+
* (hover backgrounds, badge fills)
|
|
48
|
+
* --surface-on-accent (thumb / knob surface on accent-
|
|
49
|
+
* colored backgrounds — switches,
|
|
50
|
+
* sliders, badges-on-accent)
|
|
51
|
+
* --muted (muted fill for ghost UI)
|
|
52
|
+
* --header-height (sticky AppHeader height — referenced
|
|
53
|
+
* by sticky chip bars; same value lives
|
|
54
|
+
* in src/lib/layout.ts for JS callsites)
|
|
55
|
+
* --section-scroll-offset (in-page anchor scroll-margin)
|
|
56
|
+
* --prose-narrow, --prose-wide (reading-width caps)
|
|
57
|
+
* --inset-highlight (top-edge highlight strip; tokenized to
|
|
58
|
+
* avoid copy-pasting the rgba into many
|
|
59
|
+
* boxShadow strings)
|
|
60
|
+
* --font-sans (default font stack)
|
|
61
|
+
*
|
|
62
|
+
* INTERNAL tokens (primitives only — ESLint-enforced):
|
|
63
|
+
* • Background / surface tokens consumed by specific primitives:
|
|
64
|
+
* --background, --bg-card, --bg-card-hover, --bg-surface,
|
|
65
|
+
* --bg-elevated, --bg-input, --bg-input-hover, --page-bg,
|
|
66
|
+
* --main-content-bg, --main-content-border, --card, --card-foreground,
|
|
67
|
+
* --popover, --popover-foreground, --canvas-placement-bg
|
|
68
|
+
* • <Card> internals: --border-card, --card-foot-bg,
|
|
69
|
+
* --card-shadow-rest, --card-shadow-hover,
|
|
70
|
+
* --card-frame-bg, --tray-bg, --tray-inset, --radius-tray
|
|
71
|
+
* • <Input> internals: --border-input, --input
|
|
72
|
+
* • <Modal> internals: --modal-overlay
|
|
73
|
+
* • Sidebar internals (only <Sidebar/> reads these): --sidebar-bg,
|
|
74
|
+
* --sidebar-surface, --sidebar-surface-hover, --sidebar-surface-active,
|
|
75
|
+
* --sidebar-text, --sidebar-text-bright, --sidebar-text-dim,
|
|
76
|
+
* --sidebar-border, --sidebar-section-label, --sidebar-rail,
|
|
77
|
+
* --sidebar-width, --sidebar-collapsed-width
|
|
78
|
+
* • Toast internals (only <Toaster/> reads these): --toast-bg,
|
|
79
|
+
* --toast-text, --toast-border
|
|
80
|
+
* • shadcn legacy aliases primitives may still rely on:
|
|
81
|
+
* --secondary, --secondary-foreground
|
|
82
|
+
* • Legacy brand aliases kept working for existing pages:
|
|
83
|
+
* --primary, --primary-hover, --primary-foreground, --ring
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
:root {
|
|
87
|
+
/* ============================================================
|
|
88
|
+
BRAND ACCENT (red) — PUBLIC
|
|
89
|
+
============================================================ */
|
|
90
|
+
--accent: 207 14 15;
|
|
91
|
+
--accent-hover: 227 26 27;
|
|
92
|
+
--accent-muted: 207 14 15 / 0.12;
|
|
93
|
+
--accent-subtle: 207 14 15 / 0.06;
|
|
94
|
+
--accent-glow: 207 14 15 / 0.25;
|
|
95
|
+
|
|
96
|
+
/* ============================================================
|
|
97
|
+
HIERARCHY MAP PALETTE — PUBLIC, theme-INDEPENDENT.
|
|
98
|
+
The hierarchy SVG overlay sits on top of an always-light OSM
|
|
99
|
+
basemap regardless of UI theme. These tokens are fixed in both
|
|
100
|
+
light and dark mode so the overlay reads consistently. Sourced
|
|
101
|
+
from zip-search src/index.css:95-211 (hierarchy block).
|
|
102
|
+
============================================================ */
|
|
103
|
+
|
|
104
|
+
/* Brand-red ladder — used by state pills, stacked NE callouts,
|
|
105
|
+
drilled-state outlines, connector lines, hover/selected states. */
|
|
106
|
+
--hierarchy-red: 231 12 7; /* primary fill */
|
|
107
|
+
--hierarchy-red-dark: 184 9 5; /* hover fill, selected stroke */
|
|
108
|
+
--hierarchy-red-darkest: 139 7 4; /* selected fill */
|
|
109
|
+
--hierarchy-red-shadow: 75 3 2; /* near-black; selected stacked-pill stroke */
|
|
110
|
+
|
|
111
|
+
/* Slate ladder — default outlines + context-state polygon + label fills. */
|
|
112
|
+
--hierarchy-outline: 71 85 105; /* slate-600; default outline stroke */
|
|
113
|
+
--hierarchy-slate: 100 116 139; /* slate-500; context-state polygon + label fill */
|
|
114
|
+
|
|
115
|
+
/* White triplet — for the translucent default state-polygon fill. */
|
|
116
|
+
--hierarchy-on-base: 255 255 255;
|
|
117
|
+
|
|
118
|
+
/* Legacy brand aliases — kept working for existing primitive code paths.
|
|
119
|
+
INTERNAL: lenses/routes/components should use --accent / --foreground. */
|
|
120
|
+
--primary: var(--accent);
|
|
121
|
+
--primary-hover: var(--accent-hover);
|
|
122
|
+
--primary-foreground: 255 255 255;
|
|
123
|
+
--ring: var(--accent);
|
|
124
|
+
|
|
125
|
+
/* ============================================================
|
|
126
|
+
DARK THEME SURFACES — INTERNAL (primitives only)
|
|
127
|
+
============================================================ */
|
|
128
|
+
--background: 9 9 11;
|
|
129
|
+
--foreground: 244 244 245;
|
|
130
|
+
--bg-surface: 17 17 19;
|
|
131
|
+
--bg-elevated: 24 24 27;
|
|
132
|
+
--bg-card: 20 20 22;
|
|
133
|
+
--bg-card-hover: 26 26 29;
|
|
134
|
+
--bg-input: 15 15 17;
|
|
135
|
+
|
|
136
|
+
--card: 20 20 22;
|
|
137
|
+
--card-foreground: 244 244 245;
|
|
138
|
+
--popover: 24 24 27;
|
|
139
|
+
--popover-foreground: 244 244 245;
|
|
140
|
+
|
|
141
|
+
--muted: 39 39 42;
|
|
142
|
+
--muted-foreground: 161 161 170;
|
|
143
|
+
--text-secondary: 161 161 170;
|
|
144
|
+
--text-tertiary: 113 113 122;
|
|
145
|
+
--text-muted: 82 82 91;
|
|
146
|
+
|
|
147
|
+
--secondary: 39 39 42;
|
|
148
|
+
--secondary-foreground: 244 244 245;
|
|
149
|
+
|
|
150
|
+
--border: 255 255 255 / 0.08;
|
|
151
|
+
--border-strong: 255 255 255 / 0.14;
|
|
152
|
+
--input: 39 39 42;
|
|
153
|
+
|
|
154
|
+
/* Semantic — PUBLIC */
|
|
155
|
+
--success: 16 185 129;
|
|
156
|
+
--success-bg: 16 185 129 / 0.12;
|
|
157
|
+
--warning: 245 158 11;
|
|
158
|
+
--warning-bg: 245 158 11 / 0.12;
|
|
159
|
+
--info: 59 130 246;
|
|
160
|
+
--info-bg: 59 130 246 / 0.12;
|
|
161
|
+
--destructive: 239 68 68;
|
|
162
|
+
--destructive-foreground: 255 255 255;
|
|
163
|
+
|
|
164
|
+
/* Folder palette — PUBLIC. Categorical accents for Asset folders
|
|
165
|
+
(ADR-035). Tuned brighter here so they read on near-black cards;
|
|
166
|
+
the light theme block below carries darker, more saturated values.
|
|
167
|
+
Folders store a colour KEY ('red' | 'amber' | …), never a hex. */
|
|
168
|
+
--folder-red: 239 68 68;
|
|
169
|
+
--folder-amber: 245 158 11;
|
|
170
|
+
--folder-emerald: 16 185 129;
|
|
171
|
+
--folder-teal: 20 184 166;
|
|
172
|
+
--folder-blue: 59 130 246;
|
|
173
|
+
--folder-violet: 139 92 246;
|
|
174
|
+
--folder-pink: 236 72 153;
|
|
175
|
+
--folder-slate: 148 163 184;
|
|
176
|
+
--folder-ink: 203 213 225;
|
|
177
|
+
|
|
178
|
+
/* ============================================================
|
|
179
|
+
SIDEBAR — INTERNAL (only <Sidebar/> reads these)
|
|
180
|
+
============================================================ */
|
|
181
|
+
--sidebar-bg: 10 10 11;
|
|
182
|
+
--sidebar-surface: 255 255 255 / 0.04;
|
|
183
|
+
--sidebar-surface-hover: 255 255 255 / 0.08;
|
|
184
|
+
--sidebar-surface-active: 207 14 15 / 0.15;
|
|
185
|
+
--sidebar-text: 161 161 170;
|
|
186
|
+
--sidebar-text-bright: 244 244 245;
|
|
187
|
+
--sidebar-text-dim: 113 113 122;
|
|
188
|
+
--sidebar-border: 255 255 255 / 0.06;
|
|
189
|
+
--sidebar-section-label: 82 82 91;
|
|
190
|
+
--sidebar-rail: 255 255 255 / 0.08;
|
|
191
|
+
--sidebar-width: 260px;
|
|
192
|
+
--sidebar-collapsed-width: 56px;
|
|
193
|
+
|
|
194
|
+
/* ============================================================
|
|
195
|
+
LAYOUT — PUBLIC (generic visual utilities)
|
|
196
|
+
============================================================ */
|
|
197
|
+
--header-height: 56px;
|
|
198
|
+
--section-scroll-offset: 120px;
|
|
199
|
+
--prose-narrow: 32.5rem;
|
|
200
|
+
--prose-wide: 42rem;
|
|
201
|
+
--inset-highlight: 255 255 255 / 0.05;
|
|
202
|
+
|
|
203
|
+
/* Bullet primitives — PUBLIC (generic visual utilities).
|
|
204
|
+
Used by atoms.ListItem + lens bullet markers (e.g. value-section).
|
|
205
|
+
`--bullet-offset-y` is the marginTop needed to optically center a
|
|
206
|
+
`--bullet-size` dot against a line of `text-[13px]` body copy with
|
|
207
|
+
line-height 1.5. If a future callsite needs a different alignment
|
|
208
|
+
(e.g. larger text, looser leading), override `marginTop` per-callsite
|
|
209
|
+
rather than introducing a per-context token. */
|
|
210
|
+
--bullet-size: 5px;
|
|
211
|
+
--bullet-offset-y: 7px;
|
|
212
|
+
|
|
213
|
+
/* Recessed card footer strip — INTERNAL (<Card.Foot>) */
|
|
214
|
+
--card-foot-bg: 255 255 255 / 0.025;
|
|
215
|
+
|
|
216
|
+
/* Card surface — INTERNAL (<Card>) */
|
|
217
|
+
--border-card: 255 255 255 / 0.08;
|
|
218
|
+
--card-shadow-rest:
|
|
219
|
+
0 1px 2px rgb(0 0 0 / 0.20);
|
|
220
|
+
--card-shadow-hover:
|
|
221
|
+
0 4px 12px rgb(0 0 0 / 0.28);
|
|
222
|
+
|
|
223
|
+
/* Card-tray — INTERNAL (<Card.Tray>) */
|
|
224
|
+
--tray-bg: 24 24 27;
|
|
225
|
+
--tray-inset: 10px;
|
|
226
|
+
--radius-tray: var(--radius-md);
|
|
227
|
+
|
|
228
|
+
/* Card frame — INTERNAL (outer .ds-card-surface bg in framed mode) */
|
|
229
|
+
--card-frame-bg: 20 20 22;
|
|
230
|
+
|
|
231
|
+
/* ============================================================
|
|
232
|
+
CALCULATOR SHELL v2 — INTERNAL (ADR-076 D7). Consumed only by
|
|
233
|
+
the v2 primitives (CalculatorShellV2 header, StatRow tiles) and
|
|
234
|
+
the recessed .ds-card-tray. rgb triples / shadow lists, no hex.
|
|
235
|
+
============================================================ */
|
|
236
|
+
/* Near-black brand surface — v2 header + StatRow tiles. The only
|
|
237
|
+
heavy-black surface in the kit (ADR-076 D4); black is reserved
|
|
238
|
+
for the header and StatRow tiles, nowhere else. The prototype's
|
|
239
|
+
#0a0a0b hex is non-compliant, so this is an rgb triple. */
|
|
240
|
+
--brand-ink: 0 0 0;
|
|
241
|
+
/* v2 shell card elevation — multi-layer drop shadow + top-edge
|
|
242
|
+
inner highlight (the "read depth as quality" ladder). */
|
|
243
|
+
--shell-shadow:
|
|
244
|
+
inset 0 1px 0 rgb(255 255 255 / 0.05),
|
|
245
|
+
0 4px 12px rgb(0 0 0 / 0.35),
|
|
246
|
+
0 16px 48px rgb(0 0 0 / 0.45);
|
|
247
|
+
/* Recessed-tray shadow — the bright inner tray reads as inset. */
|
|
248
|
+
--tray-shadow: inset 0 1px 2px rgb(0 0 0 / 0.18);
|
|
249
|
+
|
|
250
|
+
/* ============================================================
|
|
251
|
+
MAIN CONTENT AREA — INTERNAL (layout primitives only)
|
|
252
|
+
============================================================ */
|
|
253
|
+
--main-content-bg: 10 10 11;
|
|
254
|
+
--main-content-border: 255 255 255 / 0.08;
|
|
255
|
+
|
|
256
|
+
/* ============================================================
|
|
257
|
+
RADIUS SCALE — PUBLIC
|
|
258
|
+
============================================================ */
|
|
259
|
+
--radius-sm: 8px;
|
|
260
|
+
--radius-md: 12px;
|
|
261
|
+
--radius-lg: 16px;
|
|
262
|
+
--radius-xl: 20px;
|
|
263
|
+
--radius-2xl: 24px;
|
|
264
|
+
--radius-full: 9999px;
|
|
265
|
+
--radius: 0.5rem; /* legacy alias */
|
|
266
|
+
|
|
267
|
+
/* ============================================================
|
|
268
|
+
SHADOWS — PUBLIC
|
|
269
|
+
============================================================ */
|
|
270
|
+
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
|
|
271
|
+
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
272
|
+
--shadow-lg: 0 8px 25px rgba(0, 0, 0, 0.35);
|
|
273
|
+
--shadow-glow: 0 0 20px rgb(207 14 15 / 0.25);
|
|
274
|
+
|
|
275
|
+
/* Transitions — PUBLIC (legacy bundled motion; --dur and --ease are preferred). */
|
|
276
|
+
--transition: 200ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
277
|
+
--transition-slow: 300ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
278
|
+
|
|
279
|
+
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
280
|
+
|
|
281
|
+
/* Monospace stack — added 2026-05-18 per ADR-023 D17.
|
|
282
|
+
* JetBrains Mono is loaded from Google Fonts in apps/<app>/index.html
|
|
283
|
+
* (added per pre-batch coordination commit). Falls back to platform
|
|
284
|
+
* monospaces if the @font-face fails. Used by tabular numeric data
|
|
285
|
+
* in keywords table (Phase 8), SEMSpec ad-strength / CPC / search
|
|
286
|
+
* volume columns (Phase 12), and any other tabular-data surfaces.
|
|
287
|
+
* Consume via Tailwind `font-mono` utility (resolves to this stack). */
|
|
288
|
+
--font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
|
|
289
|
+
|
|
290
|
+
/* ============================================================
|
|
291
|
+
LIGHT-MODE-READY ADDITIONS (dark values; light overrides below)
|
|
292
|
+
============================================================ */
|
|
293
|
+
--surface-overlay-soft: 255 255 255 / 0.04;
|
|
294
|
+
--surface-overlay: 255 255 255 / 0.06;
|
|
295
|
+
--surface-overlay-strong: 255 255 255 / 0.10;
|
|
296
|
+
--surface-overlay-stronger: 255 255 255 / 0.16;
|
|
297
|
+
|
|
298
|
+
--page-bg: 5 5 6;
|
|
299
|
+
--bg-input-hover: 19 19 22;
|
|
300
|
+
--modal-overlay: 0 0 0 / 0.65;
|
|
301
|
+
|
|
302
|
+
/* `--surface-on-accent` — PUBLIC (Phase Sidebar-E MIN-1, ADR-049).
|
|
303
|
+
* The "thumb on a colored track" surface: switch thumbs, slider
|
|
304
|
+
* knobs, badge fills sitting on accent-colored backgrounds. Both
|
|
305
|
+
* themes default to pure white because thumbs read as white against
|
|
306
|
+
* red accents in either light or dark mode — the alternative is a
|
|
307
|
+
* theme-aware off-white that buys nothing. Kept as a public token
|
|
308
|
+
* (rather than a raw `white` literal) so the boundary lint can
|
|
309
|
+
* enforce it and so a future redesign can re-tune both themes from
|
|
310
|
+
* one place. Consumers wrap as `rgb(var(--surface-on-accent))`. */
|
|
311
|
+
--surface-on-accent: 255 255 255;
|
|
312
|
+
|
|
313
|
+
--border-input: 255 255 255 / 0.10;
|
|
314
|
+
|
|
315
|
+
--shadow-xl: 0 16px 40px rgb(0 0 0 / 0.55);
|
|
316
|
+
--shadow-2xl: 0 24px 60px rgb(0 0 0 / 0.60);
|
|
317
|
+
|
|
318
|
+
--ring-focus: 0 0 0 3px rgb(207 14 15 / 0.25);
|
|
319
|
+
--ring-error: 0 0 0 3px rgb(239 68 68 / 0.25);
|
|
320
|
+
|
|
321
|
+
--radius-xs: 6px;
|
|
322
|
+
|
|
323
|
+
--ctrl-sm: 32px;
|
|
324
|
+
--ctrl-md: 40px;
|
|
325
|
+
--ctrl-lg: 48px;
|
|
326
|
+
|
|
327
|
+
/* Spacing scale (4px base) — PUBLIC */
|
|
328
|
+
--space-1: 4px;
|
|
329
|
+
--space-2: 8px;
|
|
330
|
+
--space-3: 12px;
|
|
331
|
+
--space-4: 16px;
|
|
332
|
+
--space-5: 20px;
|
|
333
|
+
--space-6: 24px;
|
|
334
|
+
--space-8: 32px;
|
|
335
|
+
--space-10: 40px;
|
|
336
|
+
--space-12: 48px;
|
|
337
|
+
|
|
338
|
+
/* Motion — PUBLIC */
|
|
339
|
+
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
340
|
+
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
341
|
+
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
|
342
|
+
--dur-fast: 140ms;
|
|
343
|
+
--dur-base: 240ms;
|
|
344
|
+
--dur-slow: 420ms;
|
|
345
|
+
|
|
346
|
+
/* Toast — INTERNAL (only <Toaster/> reads these) */
|
|
347
|
+
--toast-bg: 17 17 19;
|
|
348
|
+
--toast-text: 244 244 245;
|
|
349
|
+
--toast-border: 255 255 255 / 0.10;
|
|
350
|
+
|
|
351
|
+
/* Canvas placement bg — INTERNAL (placement primitive) */
|
|
352
|
+
--canvas-placement-bg: 17 17 19;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* ============================================================
|
|
356
|
+
LIGHT THEME OVERRIDES
|
|
357
|
+
Only the flip + re-tune tokens land here; sidebar / toast /
|
|
358
|
+
radii / spacing / motion all stay invariant on :root.
|
|
359
|
+
|
|
360
|
+
THREE-MODE SYSTEM (2026-05-26): three values for data-theme:
|
|
361
|
+
dark — :root defaults (everything dark)
|
|
362
|
+
light — full light theme (this block + sidebar light overrides)
|
|
363
|
+
combo — light surfaces + DARK sidebar
|
|
364
|
+
"combo" inherits the dark --sidebar-* from :root by NOT redeclaring
|
|
365
|
+
them. The shared light surface tokens are gathered under the
|
|
366
|
+
combined `[data-theme="light"], [data-theme="combo"]` selector
|
|
367
|
+
below; the --sidebar-* overrides sit in a `[data-theme="light"]`-
|
|
368
|
+
only block immediately after.
|
|
369
|
+
============================================================ */
|
|
370
|
+
[data-theme="light"], [data-theme="combo"] {
|
|
371
|
+
/* Brand accent — base stays, hover darkens, glow softens */
|
|
372
|
+
--accent-hover: 178 8 9;
|
|
373
|
+
--accent-muted: 207 14 15 / 0.10;
|
|
374
|
+
--accent-subtle: 207 14 15 / 0.05;
|
|
375
|
+
--accent-glow: 207 14 15 / 0.20;
|
|
376
|
+
|
|
377
|
+
/* Light-mode neutral palette (2026-05-18, iteration 2) — owner
|
|
378
|
+
* iterated from "kill the steel undertone" → "still too gray; push
|
|
379
|
+
* as close to pure #FFF without quite touching it." Page surface is
|
|
380
|
+
* now 254/254/254 (one unit shy of pure white, perfectly neutral).
|
|
381
|
+
* Cards stay 255 — fill delta is just 1 unit, so card chrome leans
|
|
382
|
+
* almost entirely on --border-card (0.07). If cards visually
|
|
383
|
+
* disappear, bump --border-card. Hover/muted/input-hover stay
|
|
384
|
+
* darker on purpose so state changes remain visible. */
|
|
385
|
+
--background: 254 254 254;
|
|
386
|
+
--foreground: 17 17 19;
|
|
387
|
+
--bg-surface: 254 254 254;
|
|
388
|
+
--bg-elevated: 255 255 255;
|
|
389
|
+
--bg-card: 255 255 255;
|
|
390
|
+
--bg-card-hover: 244 244 244;
|
|
391
|
+
--bg-input: 255 255 255;
|
|
392
|
+
--bg-input-hover: 253 253 253;
|
|
393
|
+
|
|
394
|
+
--card: 255 255 255;
|
|
395
|
+
--card-foreground: 17 17 19;
|
|
396
|
+
--popover: 255 255 255;
|
|
397
|
+
--popover-foreground: 17 17 19;
|
|
398
|
+
|
|
399
|
+
--muted: 245 245 245;
|
|
400
|
+
--muted-foreground: 82 82 91;
|
|
401
|
+
--text-secondary: 82 82 91;
|
|
402
|
+
/* --text-tertiary stays from :root */
|
|
403
|
+
--text-muted: 161 161 170;
|
|
404
|
+
|
|
405
|
+
--secondary: 244 244 245;
|
|
406
|
+
--secondary-foreground: 17 17 19;
|
|
407
|
+
|
|
408
|
+
--border: 0 0 0 / 0.12;
|
|
409
|
+
--border-strong: 0 0 0 / 0.20;
|
|
410
|
+
/* Bumped from 0.16 → 0.22 — inputs on a white --bg-input (above) sitting
|
|
411
|
+
* inside a Card (--bg-card = 255 / same as input) need a stronger border
|
|
412
|
+
* to delineate. The 0.16 value worked when --bg-input was slate-tinted; on
|
|
413
|
+
* white-on-white the prior border was too subtle. */
|
|
414
|
+
--border-input: 0 0 0 / 0.22;
|
|
415
|
+
--input: 244 244 245;
|
|
416
|
+
|
|
417
|
+
--success: 5 150 105;
|
|
418
|
+
--success-bg: 5 150 105 / 0.10;
|
|
419
|
+
/* `--warning` and the folder palette are intentionally split out
|
|
420
|
+
to a `[data-theme="light"]`-only block below — combo mode keeps
|
|
421
|
+
the brighter `:root` values so group-card colors stay readable
|
|
422
|
+
against the dark `--sidebar-bg` it inherits. */
|
|
423
|
+
--info: 37 99 235;
|
|
424
|
+
--info-bg: 37 99 235 / 0.10;
|
|
425
|
+
--destructive: 220 38 38;
|
|
426
|
+
|
|
427
|
+
--surface-overlay-soft: 0 0 0 / 0.03;
|
|
428
|
+
--surface-overlay: 0 0 0 / 0.05;
|
|
429
|
+
--surface-overlay-strong: 0 0 0 / 0.08;
|
|
430
|
+
--surface-overlay-stronger: 0 0 0 / 0.12;
|
|
431
|
+
|
|
432
|
+
--page-bg: 254 254 254;
|
|
433
|
+
--modal-overlay: 0 0 0 / 0.40;
|
|
434
|
+
/* `--surface-on-accent` stays white in light mode too — see :root
|
|
435
|
+
* comment. Declared here for symmetry / future-proofing. */
|
|
436
|
+
--surface-on-accent: 255 255 255;
|
|
437
|
+
|
|
438
|
+
--shadow-sm: 0 1px 2px rgb(0 0 0 / 0.06);
|
|
439
|
+
--shadow-md: 0 4px 12px rgb(0 0 0 / 0.08);
|
|
440
|
+
--shadow-lg: 0 8px 25px rgb(0 0 0 / 0.10);
|
|
441
|
+
--shadow-xl: 0 16px 40px rgb(0 0 0 / 0.12);
|
|
442
|
+
--shadow-2xl: 0 24px 60px rgb(0 0 0 / 0.16);
|
|
443
|
+
--shadow-glow: 0 0 20px rgb(207 14 15 / 0.20);
|
|
444
|
+
|
|
445
|
+
--ring-focus: 0 0 0 3px rgb(207 14 15 / 0.20);
|
|
446
|
+
--ring-error: 0 0 0 3px rgb(220 38 38 / 0.18);
|
|
447
|
+
|
|
448
|
+
/* Match --page-bg (254/254/254). Was 241/245/249 (slate) — that's
|
|
449
|
+
* what was actually painting "the steely background" the owner
|
|
450
|
+
* flagged; --page-bg is the body, but MainLayout's content area
|
|
451
|
+
* paints with this token. Both must move together. */
|
|
452
|
+
--main-content-bg: 254 254 254;
|
|
453
|
+
--main-content-border: 0 0 0 / 0.10;
|
|
454
|
+
|
|
455
|
+
--canvas-placement-bg: 241 245 249;
|
|
456
|
+
|
|
457
|
+
--card-foot-bg: 248 250 252;
|
|
458
|
+
|
|
459
|
+
--tray-bg: 255 255 255;
|
|
460
|
+
|
|
461
|
+
--card-frame-bg: 248 250 252;
|
|
462
|
+
|
|
463
|
+
/* Calculator Shell v2 — light overrides (ADR-076 D7). */
|
|
464
|
+
--brand-ink: 20 20 23;
|
|
465
|
+
--shell-shadow:
|
|
466
|
+
inset 0 1px 0 rgb(255 255 255 / 0.8),
|
|
467
|
+
0 2px 6px rgb(0 0 0 / 0.06),
|
|
468
|
+
0 16px 40px rgb(0 0 0 / 0.10);
|
|
469
|
+
--tray-shadow: inset 0 1px 2px rgb(0 0 0 / 0.04);
|
|
470
|
+
|
|
471
|
+
/* Bumped from 0.07 → 0.12 (matches public --border) — when --page-bg
|
|
472
|
+
* moved to 254 (near-white) and --bg-card stayed 255, cards lost their
|
|
473
|
+
* fill-contrast affordance. The border now does the visual work, same
|
|
474
|
+
* opacity as Button secondary border (the "Generate from URL" look the
|
|
475
|
+
* owner called the gold standard). */
|
|
476
|
+
--border-card: 0 0 0 / 0.12;
|
|
477
|
+
--card-shadow-rest:
|
|
478
|
+
inset 0 1px 0 rgb(255 255 255 / 0.7),
|
|
479
|
+
0 1px 2px rgb(0 0 0 / 0.06),
|
|
480
|
+
0 4px 10px rgb(0 0 0 / 0.06);
|
|
481
|
+
--card-shadow-hover:
|
|
482
|
+
inset 0 1px 0 rgb(255 255 255 / 0.7),
|
|
483
|
+
0 2px 4px rgb(0 0 0 / 0.07),
|
|
484
|
+
0 8px 24px rgb(0 0 0 / 0.09);
|
|
485
|
+
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/* ============================================================
|
|
489
|
+
SIDEBAR — INTERNAL (only <Sidebar/> reads these)
|
|
490
|
+
Light-theme overrides — Phase Sidebar-E (ADR-049 D7 + Phase E).
|
|
491
|
+
The rail should still read as a "distinct surface" from
|
|
492
|
+
--main-content-bg in light mode, just inverted: a slightly-
|
|
493
|
+
tinted light background with darker borders + text. Values
|
|
494
|
+
below were tuned against the dark-theme reference:
|
|
495
|
+
dark --sidebar-bg = 10 10 11 (near-black)
|
|
496
|
+
dark --sidebar-border = white/0.06 (faint white hairline)
|
|
497
|
+
Light analogue:
|
|
498
|
+
--sidebar-bg = 244 244 248 (cool off-white, one step
|
|
499
|
+
darker than --bg-card so
|
|
500
|
+
the rail still reads as
|
|
501
|
+
a step DOWN from --main-
|
|
502
|
+
content-bg's 254/254/254)
|
|
503
|
+
--sidebar-border = 0/0.10 (matches public --border)
|
|
504
|
+
`--sidebar-text*` and `--sidebar-surface-*` track the public
|
|
505
|
+
text + overlay scale in the same direction as the dark values,
|
|
506
|
+
just polarity-flipped.
|
|
507
|
+
|
|
508
|
+
This block is `[data-theme="light"]`-ONLY — `combo` mode keeps
|
|
509
|
+
the dark `--sidebar-*` values from :root so the sidebar stays
|
|
510
|
+
dark even though the rest of the shell is light.
|
|
511
|
+
============================================================ */
|
|
512
|
+
[data-theme="light"] {
|
|
513
|
+
--sidebar-bg: 244 244 248;
|
|
514
|
+
--sidebar-surface: 0 0 0 / 0.04;
|
|
515
|
+
--sidebar-surface-hover: 0 0 0 / 0.08;
|
|
516
|
+
--sidebar-surface-active: 207 14 15 / 0.10;
|
|
517
|
+
--sidebar-text: 82 82 91;
|
|
518
|
+
--sidebar-text-bright: 17 17 19;
|
|
519
|
+
--sidebar-text-dim: 113 113 122;
|
|
520
|
+
--sidebar-border: 0 0 0 / 0.10;
|
|
521
|
+
--sidebar-section-label: 113 113 122;
|
|
522
|
+
--sidebar-rail: 0 0 0 / 0.08;
|
|
523
|
+
|
|
524
|
+
/* ============================================================
|
|
525
|
+
SEMANTIC + FOLDER PALETTE — light-only overrides.
|
|
526
|
+
Owner directive 2026-05-27: combo mode (dark sidebar + light
|
|
527
|
+
shell) was rendering group cards in the rail with the
|
|
528
|
+
light-mode darker/saturated folder palette painted on a still-
|
|
529
|
+
dark --sidebar-bg → low contrast, hard to see the category
|
|
530
|
+
color. Splitting these out so combo inherits the brighter
|
|
531
|
+
`:root` values (designed for dark substrate) keeps the rail
|
|
532
|
+
readable. Trade-off: in combo mode, asset folders rendering on
|
|
533
|
+
the light main-content area use the brighter `:root` tokens
|
|
534
|
+
too — they read slightly less optimal on white but stay
|
|
535
|
+
visible. Sidebar visibility is the primary affordance in combo.
|
|
536
|
+
============================================================ */
|
|
537
|
+
--warning: 217 119 6;
|
|
538
|
+
--warning-bg: 217 119 6 / 0.10;
|
|
539
|
+
--folder-red: 207 14 15;
|
|
540
|
+
--folder-amber: 217 119 6;
|
|
541
|
+
--folder-emerald: 5 150 105;
|
|
542
|
+
--folder-teal: 13 148 136;
|
|
543
|
+
--folder-blue: 29 78 216;
|
|
544
|
+
--folder-violet: 124 58 237;
|
|
545
|
+
--folder-pink: 219 39 119;
|
|
546
|
+
--folder-slate: 71 85 105;
|
|
547
|
+
--folder-ink: 15 23 42;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/* ============================================================
|
|
551
|
+
META-PREVIEW PLATFORM-CHROME TOKENS (theme-INDEPENDENT)
|
|
552
|
+
------------------------------------------------------------
|
|
553
|
+
The `@lovett/ui/meta-previews` renderers reproduce real
|
|
554
|
+
Facebook / Instagram / Messenger UI, which is always-light
|
|
555
|
+
regardless of the workspace theme — exactly like the
|
|
556
|
+
`--hierarchy-*` palette above. They consume these as inline
|
|
557
|
+
`var(--color-*)` values (full colours, NOT rgb-triplets), so
|
|
558
|
+
they live as plain custom properties here rather than in the
|
|
559
|
+
light/dark theme blocks.
|
|
560
|
+
|
|
561
|
+
Promotion gap fix (ADR-060 D12 follow-through): the renderers
|
|
562
|
+
referenced `var(--color-surface-50/100/200)` + a `meta-blue`
|
|
563
|
+
colour that were never defined when the previews were promoted
|
|
564
|
+
out of the prototype (docs/prototype/meta/preview-package). The
|
|
565
|
+
values below are the prototype's Tailwind-config colours (see
|
|
566
|
+
the package README "Tailwind config" block), restoring pixel
|
|
567
|
+
fidelity. `--color-meta-ink` is the always-dark preview-surface
|
|
568
|
+
base text (formerly the lens-local `--mc-fb-text`).
|
|
569
|
+
|
|
570
|
+
These are platform-chrome and exempt substrate (packages/ui),
|
|
571
|
+
so the hex literals are permitted here and nowhere in apps/.
|
|
572
|
+
============================================================ */
|
|
573
|
+
:root {
|
|
574
|
+
--color-meta-blue: #1877f2;
|
|
575
|
+
--color-meta-ink: #050505;
|
|
576
|
+
--color-surface-50: #fafafa;
|
|
577
|
+
--color-surface-100: #f4f4f5;
|
|
578
|
+
--color-surface-200: #e4e4e7;
|
|
579
|
+
}
|