@david-richard/notify-ds 1.0.0

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.
@@ -0,0 +1,486 @@
1
+ # Qu Notify — Screen Anatomy
2
+
3
+ Spatial composition of every major screen. Each entry describes regions (top → bottom), components in each region, layout rules, and copy patterns. Intended as a blueprint — read this before building any new screen.
4
+
5
+ Screenshots live in `/screenshots/`. Filenames are referenced inline.
6
+
7
+ ---
8
+
9
+ ## Global Layout Shell (all authenticated screens)
10
+
11
+ ```
12
+ ┌─────────────────────────────────────┐
13
+ │ STATUS BAR (iOS system) │ h: ~44px, system-rendered
14
+ ├─────────────────────────────────────┤
15
+ │ APP HEADER │ h: 56px, white bg
16
+ │ [QU NOTIFY lockup] [Bell icon] │
17
+ ├─────────────────────────────────────┤
18
+ │ CONTEXT BAR │ h: 48px, white bg
19
+ │ [Store Selector] • [Date Selector] │ both cyan pills, bullet separator
20
+ ├─────────────────────────────────────┤
21
+ │ │
22
+ │ PAGE CONTENT │ flex-1, gray-50 (#F4F4F4) bg
23
+ │ │
24
+ ├─────────────────────────────────────┤
25
+ │ BOTTOM NAV (dashboard screens only)│ floating glass pill, h: 72px
26
+ │ [Dashboard] [Inventory] [Menu] │ fixed, bottom: 24px, centered
27
+ └─────────────────────────────────────┘
28
+ ```
29
+
30
+ **App Header:**
31
+ - Left: QU NOTIFY logo lockup (Q-mark + NOTIFY wordmark). See `assets/logo-notify-lockup.svg`.
32
+ - Right: Bell icon (24px). Red dot badge when notifications exist.
33
+ - Background: white. No border — the context bar below creates visual separation.
34
+
35
+ **Context Bar:**
36
+ - Two `Selector` components (Primary variant, Active state).
37
+ - Left: Store selector with store icon. Label shows store name or "StoreName" / "13 Stores".
38
+ - Right: Date selector with calendar icon. Label shows formatted date (e.g. "01/06/26").
39
+ - Separated by a bullet `•` character in gray, vertically centered.
40
+ - Both selectors are cyan fill. This is the only place cyan appears as a persistent element.
41
+
42
+ ---
43
+
44
+ ## Authentication Screens
45
+
46
+ ### Splash / Loading Screen
47
+ `screenshots/loading.png`
48
+
49
+ Full-bleed illustrated screen shown on app launch.
50
+
51
+ ```
52
+ ┌─────────────────────────────────────┐
53
+ │ STATUS BAR (white text, dark bg) │
54
+ ├─────────────────────────────────────┤
55
+ │ │
56
+ │ ILLUSTRATION FIELD │ black background
57
+ │ Food line-art scattered │ brand-red + white + cyan stroke
58
+ │ (burger, hotdog, donut, etc.) │
59
+ │ │
60
+ │ ┌──────────────────────────────┐ │
61
+ │ │ BRAND CARD (brand-red bg) │ │ centered, tilted ~5°
62
+ │ │ [cyan burger illustration] │ │
63
+ │ └──────────────────────────────┘ │
64
+ │ │
65
+ │ [Qi NOTIFY wordmark] │ white, centered
66
+ │ │
67
+ ├─────────────────────────────────────┤
68
+ │ Version 3.6.222-build. 1483 │ gray, centered, 12px
69
+ └─────────────────────────────────────┘
70
+ ```
71
+
72
+ Copy: none (wordmark only). No buttons.
73
+
74
+ ---
75
+
76
+ ### Sign In
77
+ `screenshots/sign-in.png`, `screenshots/sign-in-empty.png`
78
+
79
+ ```
80
+ ┌─────────────────────────────────────┐
81
+ │ STATUS BAR │
82
+ ├─────────────────────────────────────┤
83
+ │ "Sign In to" │ Inter Regular 18px, left
84
+ │ [QU NOTIFY logo — full lockup] │ large, left-aligned
85
+ │ │ ~48px height
86
+ ├─────────────────────────────────────┤
87
+ │ "Sign in to continue" │ gray caption, left
88
+ │ │
89
+ │ USERNAME* label │ Red Hat Text Medium 18px
90
+ │ [pill input — default/filled] │ full width
91
+ │ │
92
+ │ PASSWORD* label │
93
+ │ [pill input — password + eye icon] │ active = cyan border
94
+ │ │
95
+ │ [Forgot Password?] │ teal link text, right-aligned
96
+ │ │
97
+ │ *Required Fields │ gray 12px, left
98
+ │ │
99
+ │ [Sign In] │ cyan pill button, centered
100
+ │ │
101
+ │ (spacer — flexible) │
102
+ │ │
103
+ │ "Powered by" + QU mark │ gray, centered, 12px
104
+ │ Version 3.6.222-build. 1483 │ gray, centered, 12px
105
+ └─────────────────────────────────────┘
106
+ ```
107
+
108
+ Copy patterns:
109
+ - Heading: "Sign In to" (sentence case) + large logo
110
+ - Helper: "Sign in to continue"
111
+ - Button: "Sign In"
112
+ - Link: "Forgot Password?"
113
+ - Footer: "Powered by" + wordmark + version
114
+
115
+ ---
116
+
117
+ ### Two-Step Verification
118
+ `screenshots/two-step-verification.png`
119
+
120
+ ```
121
+ ┌─────────────────────────────────────┐
122
+ │ STATUS BAR │
123
+ ├─────────────────────────────────────┤
124
+ │ < Back to sign in │ teal link, left, with chevron
125
+ ├─────────────────────────────────────┤
126
+ │ "Two Step Verification" │ Inter Bold ~26px, left
127
+ │ │
128
+ │ [body copy — 2 lines] │ gray, 16px
129
+ │ "Enter the 6-digit security code │
130
+ │ from your authenticator app" │
131
+ │ │
132
+ │ CODE* label │
133
+ │ [pill input — number, empty] │
134
+ │ │
135
+ │ *Required Field │ gray 12px
136
+ │ │
137
+ │ [Continue] │ cyan pill, centered
138
+ │ │ (lighter = disabled when empty)
139
+ │ │
140
+ │ "Having trouble signing in? │ gray, centered
141
+ │ Contact Support" │ "Contact Support" = teal link
142
+ │ │
143
+ │ (spacer) │
144
+ │ │
145
+ │ "Powered by" + QU + version │
146
+ └─────────────────────────────────────┘
147
+ ```
148
+
149
+ ---
150
+
151
+ ### Reset Password / Choose New Password
152
+ `screenshots/reset-password.png`, `screenshots/choose-new-password.png`, `screenshots/choose-new-password-with-toast.png`
153
+
154
+ Same structural template as Sign In. Differences:
155
+ - Heading: "Reset Password" or "Choose New Password"
156
+ - Single or two password inputs (new + confirm)
157
+ - Toast variant shows a green or red pill at bottom on success/error
158
+
159
+ ---
160
+
161
+ ### Enable Face ID (Modal)
162
+ `screenshots/enable-face-id.png`
163
+
164
+ Appears as an overlay on top of the Sign In screen (blurred behind).
165
+
166
+ ```
167
+ ┌─────────────────────────────────────┐
168
+ │ SCRIM (rgba(8,8,8,0.8)) │ full screen behind modal
169
+ │ │
170
+ │ ┌───────────────────────────┐ │
171
+ │ │ MODAL CARD │ │ white, border-radius: 24px
172
+ │ │ │ │ centered horizontally + vertically
173
+ │ │ [Face ID icon] │ │ ~48px, centered
174
+ │ │ │ │
175
+ │ │ "Enable Face ID" │ │ Inter Bold 20px, centered
176
+ │ │ │ │
177
+ │ │ [body copy] │ │ gray 14px, centered, 2 lines
178
+ │ │ "Enable Face ID for │ │
179
+ │ │ faster, more secure │ │
180
+ │ │ access to Notify." │ │
181
+ │ │ │ │
182
+ │ │ [Enable Face ID] │ │ cyan pill button, full width
183
+ │ │ │ │
184
+ │ │ [Do it later] │ │ teal underline link, centered
185
+ │ └───────────────────────────┘ │
186
+ │ │
187
+ └─────────────────────────────────────┘
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Dashboard Screen
193
+
194
+ ### Sales Tab (primary view)
195
+ `screenshots/sales-dashboard.png`
196
+
197
+ ```
198
+ [Global Shell: Header + Context Bar]
199
+ ├─────────────────────────────────────┤
200
+ │ TAB BAR │ h: ~40px
201
+ │ [Sales] [Labor] [Store] [Product] │ 4 tabs, Sales selected (black pill)
202
+ │ │ gray-100 container pill
203
+ ├─────────────────────────────────────┤
204
+ │ METRIC TILE GRID │ 2 columns, 12px gap, 16px h-padding
205
+ │ │
206
+ │ [Net Sales tile] [Checks tile] │ white card, 16px radius, shadow
207
+ │ $345.58 11 │ label 12px gray, value 24px semibold
208
+ │ $304.78 ↑+11.8% 9 ↑+18.1% │ comparison + TrendBadge
209
+ │ │
210
+ │ [Payments tile] [Avg Check tile] │
211
+ │ [Gross Sales] [Discounts] │
212
+ │ [Cash] [Tills tile] │ Tills has text list: Open/Closed/Reconciled
213
+ │ [Voids] [Svc Charges] │
214
+ │ │
215
+ │ (scrollable) │
216
+ ├─────────────────────────────────────┤
217
+ │ [BOTTOM NAV] │ Dashboard selected
218
+ └─────────────────────────────────────┘
219
+ ```
220
+
221
+ Tile anatomy (standard):
222
+ ```
223
+ ┌──────────────────────┐
224
+ │ Label text > │ label: Inter Regular 12px, gray; chevron: gray
225
+ │ │
226
+ │ $345.58 │ value: Inter SemiBold 24px, black
227
+ │ │
228
+ │ $304.78 ↑ +11.8% │ comparison: 12px gray; TrendBadge: green/red pill
229
+ └──────────────────────┘
230
+ ```
231
+
232
+ Tills tile (special — no single value, shows status list):
233
+ ```
234
+ │ Tills > │
235
+ │ │
236
+ │ Open: 0 │ Inter Regular 14px, black
237
+ │ Closed: 1 │
238
+ │ Reconciled: 0 │
239
+ ```
240
+
241
+ ---
242
+
243
+ ### Store Tab — Kitchen sub-tab (table view)
244
+ `screenshots/dashboard-store-kitchen.png`
245
+
246
+ ```
247
+ [Global Shell]
248
+ ├─────────────────────────────────────┤
249
+ │ PRIMARY TAB BAR │ Store selected
250
+ │ [Sales] [Labor] [Store] [Product] │
251
+ ├─────────────────────────────────────┤
252
+ │ SECONDARY TAB BAR │ h: ~40px
253
+ │ [Productivity] [Network] [Kitchen] │ Kitchen selected (black pill)
254
+ ├─────────────────────────────────────┤
255
+ │ SUB-SECTION FILTER │ right-aligned
256
+ │ "Fulfilment" │ teal text, 14px
257
+ ├─────────────────────────────────────┤
258
+ │ TABLE HEADER │ Inter Medium 14px, gray
259
+ │ Store ↓ Avg Time Orders │ Sort indicator on active column
260
+ ├─────────────────────────────────────┤
261
+ │ TABLE ROWS │ divider between rows
262
+ │ Store Name > 00:00:00 0 │ row: 48px min-height
263
+ │ Store Name > 00:02:29 16 │ chevron on left of data cols
264
+ │ ... │
265
+ └─────────────────────────────────────┘
266
+ ```
267
+
268
+ Two nested tab bars is a real pattern in this app — primary (Sales/Labor/Store/Product) + secondary (Productivity/Network/Kitchen). Secondary bar is same pill pattern, smaller font, but still same black-selected / gray-100-container style.
269
+
270
+ ---
271
+
272
+ ### Loading / Error State
273
+ `screenshots/dashboard-loading-error.png`, `screenshots/dashboard-loading-error-with-toast.png`
274
+
275
+ Replaces the metric grid:
276
+ ```
277
+ ├─────────────────────────────────────┤
278
+ │ │
279
+ │ (vertical center) │
280
+ │ │
281
+ │ [Info circle icon — cyan] │ 32px, centered
282
+ │ │
283
+ │ Something Went Wrong │ Inter Regular 16px, gray, centered
284
+ │ Try Refreshing │
285
+ │ │
286
+ │ [Refresh] │ cyan pill button, centered
287
+ │ │
288
+ └─────────────────────────────────────┘
289
+ ```
290
+
291
+ Toast (error only) — fixed at bottom above safe area:
292
+ ```
293
+ ┌─────────────────────────────────────┐
294
+ │ Ooops, we are having problems │ brand-red bg, white text, 16px
295
+ │ │ full-width pill, h: ~52px
296
+ └─────────────────────────────────────┘
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Detail / Drill-Down Screens
302
+
303
+ ### Metric Detail (e.g. Net Sales)
304
+ `screenshots/net-sales.png`
305
+
306
+ ```
307
+ [Status Bar]
308
+ ├─────────────────────────────────────┤
309
+ │ < Net Sales │ back chevron left, centered title
310
+ │ │ Inter Medium 17px
311
+ ├─────────────────────────────────────┤
312
+ │ [Context Bar — store + date] │
313
+ ├─────────────────────────────────────┤
314
+ │ CHART SECTION │ white card
315
+ │ │
316
+ │ "Net Sales by hour" │ Inter Bold 16px, centered
317
+ │ [export icon] │ right-aligned, teal
318
+ │ │
319
+ │ [Legend] │
320
+ │ ● Today (cyan) ● Previous Day (gray)
321
+ │ │
322
+ │ [Line chart] │ cyan line = today, gray = previous
323
+ │ Y: $0–$1,500 X: 12AM–12AM │
324
+ │ │
325
+ ├─────────────────────────────────────┤
326
+ │ DATA TABLE │
327
+ │ │
328
+ │ Hour Today Previous Day % │ header row
329
+ │ ─────────────────────────────── │
330
+ │ 12am–1am $0.00 $0.00 0.0 │ normal row
331
+ │ 12am–1am $0.00 $0.00 0.0 │ SELECTED ROW: cyan bg, black text
332
+ │ 12am–1am $0.00 $0.00 0.0 │
333
+ │ ... │ (scrollable)
334
+ └─────────────────────────────────────┘
335
+ ```
336
+
337
+ No bottom nav on this screen.
338
+
339
+ ---
340
+
341
+ ### Check Search
342
+ `screenshots/check-search.png`
343
+
344
+ ```
345
+ [Status Bar]
346
+ ├─────────────────────────────────────┤
347
+ │ < Check Search │ back + centered title
348
+ ├─────────────────────────────────────┤
349
+ │ TOTALS SECTION │
350
+ │ "Totals" [Filters icon] │ section label + teal action
351
+ │ │
352
+ │ [Check Count tile] [Net Sales tile]│ 2-col, white cards, 16px radius
353
+ │ 8,013 $88,984 │
354
+ │ │
355
+ ├─────────────────────────────────────┤
356
+ │ CHECKS SECTION │
357
+ │ "Checks" [Share icon] │ section label + teal action
358
+ │ │
359
+ │ CHECK CARD ───────────────────── │ white card, 16px radius
360
+ │ [receipt icon] 20149 > 04/20 10:49│ check#: teal bold; timestamp: gray
361
+ │ 📍 Rosa's Cafe 28 │
362
+ │ 👤 Castaneda, Alexis │
363
+ │ │
364
+ │ OC: In Store OC: Drive Thru │ inline labels, gray
365
+ │ │
366
+ │ Net Sales $11.15 │ label left, value right, bold
367
+ │ Discounts $0.00 │
368
+ │ Refunds $0.00 │
369
+ │ Removed Items — │
370
+ │ Returned Items 0 │
371
+ │ Voids 4 │
372
+ │ ─────────────────────────────── │
373
+ │ │
374
+ │ CHECK CARD ───────────────────── │ next check
375
+ │ ... │
376
+ └─────────────────────────────────────┘
377
+ ```
378
+
379
+ Note: check number is always teal and bold — it functions as a primary link/identifier.
380
+
381
+ ---
382
+
383
+ ### Tills (with Tab Bar)
384
+ `screenshots/open-tills.png`, `screenshots/closed-tills.png`, `screenshots/reconciled-tills.png`
385
+
386
+ ```
387
+ [Status Bar]
388
+ ├─────────────────────────────────────┤
389
+ │ < Tills │
390
+ ├─────────────────────────────────────┤
391
+ │ [Context Bar] │
392
+ ├─────────────────────────────────────┤
393
+ │ TAB BAR │
394
+ │ [Open] [Closed] [Reconciled] │ 3-tab, Open selected
395
+ ├─────────────────────────────────────┤
396
+ │ │
397
+ │ EMPTY STATE (when no data) │
398
+ │ │
399
+ │ [Box-with-X icon — gray stroke] │ 48px, centered
400
+ │ "No Tills Found" │ gray, 16px, centered
401
+ │ │
402
+ └─────────────────────────────────────┘
403
+ ```
404
+
405
+ ---
406
+
407
+ ### Product Detail (e.g. Thanksgiving Feast)
408
+ `screenshots/thanksgiving-feast.png`
409
+
410
+ ```
411
+ [Status Bar]
412
+ ├─────────────────────────────────────┤
413
+ │ < Thanksgiving Feast │ centered title
414
+ ├─────────────────────────────────────┤
415
+ │ TAB BAR │
416
+ │ [Prices] [Checks] │ 2-tab
417
+ ├─────────────────────────────────────┤
418
+ │ "1 Price for Thanksgiving Feast" │ Inter Regular 14px, gray, left
419
+ │ ↑ Quantity│ teal sort link, right-aligned, with arrow
420
+ ├─────────────────────────────────────┤
421
+ │ DATA CARD │ white, 16px radius
422
+ │ Claimed Price │
423
+ │ [brand-red label] [black label] │
424
+ │ 2,260 $25.95 │ values: large, semibold
425
+ └─────────────────────────────────────┘
426
+ ```
427
+
428
+ "Claimed" label uses brand-red (#EF2149) as a status color — not a badge, just colored text. This is the only use of red as a non-error label.
429
+
430
+ ---
431
+
432
+ ## Menu Overlay (Bottom Sheet)
433
+ `screenshots/menu-overlay.png`
434
+
435
+ Triggered by "Menu" in the bottom nav. Slides up over existing content.
436
+
437
+ ```
438
+ [Blurred/scrimmed background — rgba(8,8,8,0.8)]
439
+ ├─────────────────────────────────────┤
440
+ │ DRAG HANDLE │ gray pill, centered, ~4×40px
441
+ │ │
442
+ │ TOOLS SECTION │
443
+ │ "Tools" │ Inter SemiBold 14px, white
444
+ │ │
445
+ │ Kitchen Intelligence [NEW] │ white 16px; "NEW" = cyan pill badge
446
+ │ Settings │ white 16px
447
+ │ Forecast │ white 16px
448
+ │ Digital Channels │ white 16px
449
+ │ Check Search │ white 16px
450
+ │ │
451
+ │ SUPPORT SECTION │
452
+ │ "Support" │ Inter SemiBold 14px, white
453
+ │ │
454
+ │ Analyze │ white 16px
455
+ │ Product Tour │ white 16px
456
+ │ │
457
+ │ ───────────────────────────────── │ divider
458
+ │ │
459
+ │ Log Out │ white, underlined — link style
460
+ │ │
461
+ │ Version 3.6.222 │ gray, 12px, centered
462
+ └─────────────────────────────────────┘
463
+ ```
464
+
465
+ Sheet background: dark (near-black, not pure black). Text: white. Section headers: SemiBold. Items: Regular. No icons on menu items (except "NEW" badge on Kitchen Intelligence).
466
+
467
+ ---
468
+
469
+ ## Component Inventory by Screen
470
+
471
+ | Component | Screens it appears in |
472
+ |---|---|
473
+ | `InputField` (default) | sign-in, two-step-verification, reset-password, choose-new-password |
474
+ | `InputField` (password) | sign-in, choose-new-password |
475
+ | `Button` (primary) | sign-in, enable-face-id, two-step-verification, reset-password, dashboard-loading-error |
476
+ | `Button` (link) | sign-in (Forgot Password), two-step-verification (Contact Support), menu-overlay (Log Out) |
477
+ | `Selector` (primary) | All authenticated screens (store + date context bar) |
478
+ | `TabBar` | sales-dashboard (4-tab), dashboard-store-kitchen (3-tab secondary), open-tills (3-tab), thanksgiving-feast (2-tab) |
479
+ | `MetricTile` | sales-dashboard (primary grid), check-search (totals) |
480
+ | `Badge` (trend) | All metric tiles with % change |
481
+ | `Badge` (brand) | menu-overlay (NEW on Kitchen Intelligence) |
482
+ | `BottomNav` | All dashboard-level screens |
483
+ | Modal | enable-face-id |
484
+ | Toast | dashboard-loading-error-with-toast, choose-new-password-with-toast |
485
+ | Empty state | open-tills, dashboard-loading-error |
486
+ | Table / list | net-sales (data table), dashboard-store-kitchen (store list), check-search (check cards) |
@@ -0,0 +1,180 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+
3
+ /**
4
+ * Qu Notify — Tailwind CSS v3 configuration
5
+ *
6
+ * Derived directly from tokens.json. All values are hard-coded here
7
+ * (not referencing CSS variables) so Tailwind can generate utility classes
8
+ * at build time. The CSS custom-properties version lives in tokens.css for
9
+ * runtime theming and non-Tailwind contexts.
10
+ *
11
+ * Usage:
12
+ * // tailwind.config.js in consuming project:
13
+ * const notifyPreset = require('notify-ds/tailwind.config')
14
+ * module.exports = { presets: [notifyPreset], content: [...] }
15
+ */
16
+
17
+ module.exports = {
18
+ theme: {
19
+ extend: {
20
+
21
+ // ── Colors ──────────────────────────────────────────────────────────────
22
+ colors: {
23
+ // Primitives — brand
24
+ brand: {
25
+ 'tech-blue': '#40CCF2',
26
+ 'teal': '#339FB8',
27
+ 'red': '#EF2149',
28
+ 'confidence': '#B4002F',
29
+ 'stable-blue': '#0D2A4B',
30
+ 'quick-serve': '#E4ECEF',
31
+ 'gray-300': '#6B7280',
32
+ },
33
+
34
+ // Primitives — neutral
35
+ neutral: {
36
+ 'black': '#000000',
37
+ 'white': '#FFFFFF',
38
+ 'gray-50': '#F4F4F4',
39
+ 'gray-100':'#DEDEDE',
40
+ 'gray-200':'#C9C9C9',
41
+ 'gray-400':'#B1B1B1',
42
+ },
43
+
44
+ // Primitives — accents
45
+ accent: {
46
+ 'green': '#16A34A',
47
+ 'green-soft': '#B3F5D1',
48
+ 'blue': '#2F80ED',
49
+ 'blue-soft': '#BEDBFF',
50
+ 'red-soft': '#FFC9C9',
51
+ 'yellow': '#EDC948',
52
+ 'yellow-soft': '#FFF085',
53
+ 'orange': '#FA6A0A',
54
+ 'orange-soft': '#EAC1C3',
55
+ },
56
+
57
+ // Semantic
58
+ primary: '#40CCF2',
59
+ 'primary-fg': '#000000',
60
+ secondary: '#339FB8',
61
+ 'nav-selected': '#000000',
62
+ inactive: '#DEDEDE',
63
+ 'inactive-fg': '#6B7280',
64
+ destructive: '#EF2149',
65
+ success: '#16A34A',
66
+ 'success-soft': '#B3F5D1',
67
+ warning: '#EDC948',
68
+ 'warning-soft': '#FFF085',
69
+ error: '#EF2149',
70
+ 'error-soft': '#FFC9C9',
71
+ alert: '#FA6A0A',
72
+ 'alert-soft': '#EAC1C3',
73
+ info: '#2F80ED',
74
+ 'info-soft': '#BEDBFF',
75
+ link: '#2F80ED',
76
+ },
77
+
78
+ // ── Typography ──────────────────────────────────────────────────────────
79
+ fontFamily: {
80
+ primary: ['Inter', 'system-ui', 'sans-serif'],
81
+ secondary: ['Red Hat Text', 'Red Hat Display', 'system-ui', 'sans-serif'],
82
+ display: ['Zilla Slab', 'Georgia', 'serif'],
83
+ system: ['-apple-system', 'SF Pro', 'system-ui', 'sans-serif'],
84
+ },
85
+
86
+ fontSize: {
87
+ '2xs': ['10px', { lineHeight: '14px' }],
88
+ xs: ['12px', { lineHeight: '16px' }],
89
+ sm: ['14px', { lineHeight: '18px' }],
90
+ md: ['16px', { lineHeight: '22px' }],
91
+ lg: ['18px', { lineHeight: '24px' }],
92
+ xl: ['20px', { lineHeight: '26px' }],
93
+ '2xl': ['24px', { lineHeight: '30px' }],
94
+ '3xl': ['26px', { lineHeight: '32px' }],
95
+ '4xl': ['30px', { lineHeight: '36px' }],
96
+ '5xl': ['34px', { lineHeight: '40px' }],
97
+ '6xl': ['40px', { lineHeight: '48px' }],
98
+ '7xl': ['72px', { lineHeight: '80px' }],
99
+ },
100
+
101
+ fontWeight: {
102
+ light: '300',
103
+ normal: '400',
104
+ medium: '500',
105
+ semibold: '600',
106
+ bold: '700',
107
+ extrabold: '800',
108
+ },
109
+
110
+ // ── Spacing ─────────────────────────────────────────────────────────────
111
+ spacing: {
112
+ xs: '4px',
113
+ sm: '8px',
114
+ md: '10px',
115
+ lg: '16px',
116
+ xl: '18px',
117
+ '2xl':'22px',
118
+ '3xl':'24px',
119
+ '4xl':'26px',
120
+ '5xl':'30px',
121
+ '6xl':'40px',
122
+ '7xl':'48px',
123
+ '8xl':'60px',
124
+ },
125
+
126
+ // ── Border radius ───────────────────────────────────────────────────────
127
+ borderRadius: {
128
+ xs: '2px',
129
+ sm: '4px',
130
+ md: '6px',
131
+ lg: '8px',
132
+ xl: '12px',
133
+ '2xl':'16px',
134
+ '3xl':'24px',
135
+ menu: '60px',
136
+ full: '9999px',
137
+ },
138
+
139
+ // ── Shadows ─────────────────────────────────────────────────────────────
140
+ boxShadow: {
141
+ card: '0px 4px 4px 0px rgba(0,0,0,0.06)',
142
+ nav: '0px 4px 4px 0px rgba(0,0,0,0.14)',
143
+ modal: '0px 4px 4px 0px rgba(0,0,0,0.25)',
144
+ },
145
+
146
+ // ── Transitions ─────────────────────────────────────────────────────────
147
+ transitionDuration: {
148
+ fast: '120ms',
149
+ medium: '180ms',
150
+ },
151
+
152
+ transitionTimingFunction: {
153
+ standard: 'cubic-bezier(0.2, 0, 0, 1)',
154
+ },
155
+
156
+ // ── Component geometry constants ────────────────────────────────────────
157
+ height: {
158
+ 'btn-xsm': '24px',
159
+ 'btn-sm': '32px',
160
+ 'btn-md': '40px',
161
+ 'btn-lg': '48px',
162
+ 'input': '48px',
163
+ 'nav': '72px',
164
+ 'tab-bar': '40px',
165
+ },
166
+
167
+ maxWidth: {
168
+ 'phone': '402px',
169
+ 'nav': '360px',
170
+ },
171
+
172
+ // ── Opacity ──────────────────────────────────────────────────────────────
173
+ opacity: {
174
+ disabled: '0.5',
175
+ },
176
+ },
177
+ },
178
+
179
+ plugins: [],
180
+ }