@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.
package/README.md ADDED
@@ -0,0 +1,332 @@
1
+ # notify-ds
2
+
3
+ Design system for **Qu Notify** — the restaurant analytics mobile app by [Qu](https://qubeyond.com). Contains tokens, components, fonts, icons, screenshots, and brand assets.
4
+
5
+ **For AI design agents:** Read `constraints.md` first, then `screen-anatomy.md`, then come back here for the API surface. Those two files are load-bearing.
6
+
7
+ ---
8
+
9
+ ## What's in this repo
10
+
11
+ ```
12
+ notify-ds/
13
+ ├── tokens.json ← W3C DTCG format. Single source of truth for all values.
14
+ ├── tokens.css ← CSS custom properties. Import this in any HTML/CSS project.
15
+ ├── tailwind.config.js ← Tailwind v3 preset. Use as a preset in consuming projects.
16
+ ├── constraints.md ← Hard never/always rules. Read before building any UI.
17
+ ├── screen-anatomy.md ← Every screen decomposed spatially. Read before building any screen.
18
+ ├── CHANGELOG.md ← Decision log — why things are the way they are.
19
+ ├── components/ ← React/TypeScript components
20
+ │ ├── index.ts ← Barrel export (single import surface)
21
+ │ ├── button.tsx
22
+ │ ├── input.tsx
23
+ │ ├── checkbox.tsx
24
+ │ ├── radio.tsx
25
+ │ ├── toggle.tsx
26
+ │ ├── selector.tsx
27
+ │ ├── tabs.tsx
28
+ │ ├── switcher.tsx
29
+ │ ├── bottom-nav.tsx
30
+ │ ├── badge.tsx
31
+ │ └── metric-tile.tsx
32
+ ├── assets/
33
+ │ ├── logo-notify-lockup.svg
34
+ │ ├── logo-qu.svg
35
+ │ ├── logo-q-mark.svg
36
+ │ └── icons/ ← SVG stroke icons, one file per icon
37
+ ├── fonts/ ← Zilla Slab TTF (all weights). Inter + Red Hat Text via Google Fonts.
38
+ └── screenshots/ ← 27 production app screenshots, named descriptively
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Product context
44
+
45
+ **Qu Notify** is an iOS-first mobile app used by restaurant franchisees, group managers, and store managers to monitor real-time sales, labor, and kitchen performance. It is checked multiple times daily — it is a utility, not an experience. Clarity and data density take priority over decoration.
46
+
47
+ **Primary screens:** Splash → Sign In → Dashboard (Sales/Labor/Store/Product tabs) → Metric detail → Menu overlay → Check Search → Tills → Kitchen Intelligence
48
+
49
+ **Users:** Franchisees, group managers, store managers
50
+
51
+ **Data shown:** Net Sales, Checks, Average Check, Payments, Gross Sales, Discounts, Cash, Tills (Open/Closed/Reconciled), Voids, Service Charges, Labor, Speed of Service, Kitchen fulfillment times
52
+
53
+ ---
54
+
55
+ ## Quick start
56
+
57
+ ### As a Tailwind preset
58
+
59
+ ```js
60
+ // tailwind.config.js
61
+ const notifyPreset = require('notify-ds/tailwind')
62
+ module.exports = {
63
+ presets: [notifyPreset],
64
+ content: ['./src/**/*.{ts,tsx,html}'],
65
+ }
66
+ ```
67
+
68
+ ### CSS custom properties
69
+
70
+ ```css
71
+ /* In your global CSS */
72
+ @import 'notify-ds/tokens.css';
73
+ ```
74
+
75
+ ### React components
76
+
77
+ ```tsx
78
+ import { Button, MetricTile, TabBar, InputField } from 'notify-ds/components'
79
+
80
+ // Dashboard tile
81
+ <MetricTile label="Net Sales" value="$345.58" trend={11.8} trendLabel="vs yesterday" />
82
+
83
+ // Primary CTA
84
+ <Button variant="primary" size="lg">Sign In</Button>
85
+
86
+ // Tab bar
87
+ <TabBar tabs={["Sales", "Labor", "Store", "Product"]} value={tab} onValueChange={setTab} />
88
+ ```
89
+
90
+ ### Tokens (raw JSON)
91
+
92
+ ```js
93
+ const tokens = require('notify-ds/tokens')
94
+ const techBlue = tokens.primitive.color.brand['tech-blue'].$value // "#40CCF2"
95
+ ```
96
+
97
+ ### Inline SVG icons
98
+
99
+ ```html
100
+ <!-- Direct reference -->
101
+ <img src="node_modules/notify-ds/assets/icons/search.svg" />
102
+
103
+ <!-- Or import and inline (recommended) -->
104
+ import SearchIcon from 'notify-ds/assets/icons/search.svg'
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Design fundamentals
110
+
111
+ ### Colors (key values)
112
+
113
+ | Token | Value | Usage |
114
+ |---|---|---|
115
+ | `primitive.color.brand.tech-blue` | `#40CCF2` | Primary CTA buttons, input focus border, context selectors, checkbox on-state, toggle on-state |
116
+ | `primitive.color.brand.teal` | `#339FB8` | Secondary button outline/text, link text, action labels, check numbers |
117
+ | `primitive.color.neutral.black` | `#000000` | Primary text, **tab/nav selected fill** |
118
+ | `primitive.color.neutral.white` | `#FFFFFF` | Card backgrounds, text on dark fills |
119
+ | `primitive.color.neutral.gray-50` | `#F4F4F4` | App screen background (never white at page level) |
120
+ | `primitive.color.neutral.gray-100` | `#DEDEDE` | Tab bar container, switcher container, inactive button bg |
121
+ | `primitive.color.brand.red` | `#EF2149` | Error borders, error text, required asterisk, toast bg |
122
+
123
+ **Critical:** `#40CCF2` (cyan) is the CTA button color. `#000000` (black) is the selected tab/nav color. These are separate roles and must not be swapped.
124
+
125
+ ### Typography
126
+
127
+ | Family | Role | Usage |
128
+ |---|---|---|
129
+ | **Inter** | Primary | Body text, data labels, metric values, captions |
130
+ | **Red Hat Text** | Secondary | Page headers, input labels, button labels, section titles |
131
+ | **Zilla Slab** | Display | Splash screen, H2 display headings, pull quotes only |
132
+
133
+ Google Fonts import:
134
+ ```html
135
+ <link rel="preconnect" href="https://fonts.googleapis.com">
136
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Red+Hat+Text:wght@400;500;600;700&family=Red+Hat+Display:wght@400;500;600;700&display=swap" rel="stylesheet">
137
+ ```
138
+
139
+ Zilla Slab TTF files are in `fonts/` for local use.
140
+
141
+ ### Shapes
142
+
143
+ - **Inputs:** Always `border-radius: 9999px` (full pill). No exceptions.
144
+ - **Buttons:** Always `border-radius: 9999px` (full pill). No exceptions.
145
+ - **Metric tiles:** `border-radius: 16px`
146
+ - **Modals:** `border-radius: 24px`
147
+ - **Bottom nav:** `border-radius: 60px`
148
+ - **Tab bar container:** `border-radius: 9999px`
149
+ - **Switcher container:** `border-radius: 8px` (not pill — this distinguishes it from TabBar)
150
+
151
+ ### Disabled states
152
+
153
+ Always `opacity: 0.5` on the entire component. Never a color swap. The component's current fill/stroke colors remain intact underneath the opacity reduction.
154
+
155
+ ---
156
+
157
+ ## Component API
158
+
159
+ ### Button
160
+
161
+ ```tsx
162
+ <Button
163
+ variant="primary" // primary | secondary | tertiary | link
164
+ size="md" // xsm | sm | md | lg
165
+ state="active" // active | inactive
166
+ iconOnly={false}
167
+ disabled={false}
168
+ >
169
+ Sign In
170
+ </Button>
171
+
172
+ <IconButton variant="primary" size="md"><SearchIcon /></IconButton>
173
+ ```
174
+
175
+ ### InputField
176
+
177
+ ```tsx
178
+ <InputField
179
+ type="default" // default | password | search
180
+ label="Username"
181
+ required
182
+ placeholder="you@example.com"
183
+ state="normal" // normal | active | filled | error | disabled | readonly
184
+ errorMessage="Invalid email"
185
+ helperText="We'll never share your email"
186
+ />
187
+ ```
188
+
189
+ ### Checkbox / Radio / Toggle
190
+
191
+ ```tsx
192
+ <Checkbox label="Remember me" defaultChecked />
193
+ <Checkbox label="Select all" indeterminate />
194
+
195
+ <RadioGroup name="period" value={val} onChange={setVal} label="Time period">
196
+ <Radio value="day" label="Day" />
197
+ <Radio value="week" label="Week" />
198
+ <Radio value="month" label="Month" />
199
+ </RadioGroup>
200
+
201
+ <Toggle label="Enable notifications" checked={on} onChange={setOn} />
202
+ ```
203
+
204
+ ### Selector
205
+
206
+ ```tsx
207
+ <Selector label="All Stores" variant="primary" state="active" open={isOpen} />
208
+ <Selector label="This Week" variant="secondary" state="active" />
209
+ <SelectorGroup>
210
+ <Selector label="StoreName" icon={<StoreIcon />} />
211
+ <Selector label="01/06/26" icon={<CalendarIcon />} />
212
+ </SelectorGroup>
213
+ ```
214
+
215
+ ### TabBar
216
+
217
+ ```tsx
218
+ <TabBar
219
+ tabs={["Sales", "Labor", "Store", "Product"]}
220
+ value={activeTab}
221
+ onValueChange={setActiveTab}
222
+ />
223
+ // With content panels:
224
+ <TabPanels value={activeTab}>
225
+ <TabPanel value="Sales"><SalesView /></TabPanel>
226
+ <TabPanel value="Labor"><LaborView /></TabPanel>
227
+ </TabPanels>
228
+ ```
229
+
230
+ ### Switcher
231
+
232
+ ```tsx
233
+ <Switcher
234
+ segments={["Day", "Week", "Month"]}
235
+ defaultValue="Week"
236
+ onValueChange={setPeriod}
237
+ />
238
+ // With icon segments:
239
+ <Switcher segments={[{value:"list", label:"List", icon:<ListIcon/>}, ...]} />
240
+ ```
241
+
242
+ ### BottomNav
243
+
244
+ ```tsx
245
+ <BottomNavContainer>
246
+ <BottomNav
247
+ items={[
248
+ { value: "dashboard", label: "Dashboard", icon: <DashboardIcon /> },
249
+ { value: "inventory", label: "Inventory", icon: <BoxIcon />, badge: 3 },
250
+ { value: "menu", label: "Menu", icon: <MenuIcon /> },
251
+ ]}
252
+ value={activeRoute}
253
+ onValueChange={(v) => router.push(v)}
254
+ />
255
+ </BottomNavContainer>
256
+ ```
257
+
258
+ `BottomNavContainer` positions the nav as `fixed bottom-6 left-1/2 -translate-x-1/2`.
259
+
260
+ ### MetricTile
261
+
262
+ ```tsx
263
+ <MetricTile
264
+ label="Net Sales"
265
+ value="$345.58"
266
+ trend={11.8}
267
+ trendLabel="vs yesterday"
268
+ />
269
+
270
+ <MetricTileGrid cols={2}>
271
+ <MetricTile label="Net Sales" value="$345.58" trend={11.8} />
272
+ <MetricTile label="Checks" value="11" trend={18.1} />
273
+ <MetricTile label="Avg Check" value="$33.86" trend={7.7} />
274
+ <MetricTile label="Gross Sales" value="$368.40" trend={11.4} />
275
+ </MetricTileGrid>
276
+
277
+ // Loading state:
278
+ <MetricTile label="Net Sales" value="" trend={0} loading />
279
+ ```
280
+
281
+ ### Badge / TrendBadge
282
+
283
+ ```tsx
284
+ <Badge variant="success">Open</Badge>
285
+ <Badge variant="error">Closed</Badge>
286
+ <Badge variant="brand">NEW</Badge>
287
+
288
+ // Auto-picks color from sign:
289
+ <TrendBadge value={11.8} /> // → green "+11.8%"
290
+ <TrendBadge value={-5.6} /> // → red "−5.6%"
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Screenshots
296
+
297
+ 27 production screenshots in `screenshots/`. Key ones for design reference:
298
+
299
+ | File | Shows |
300
+ |---|---|
301
+ | `sales-dashboard.png` | Full dashboard, metric tile grid, context bar, tab bar, bottom nav |
302
+ | `sign-in.png` | Auth screen, input field states, primary button, "Powered by" footer |
303
+ | `menu-overlay.png` | Bottom sheet, dark scrim, menu structure, "NEW" badge |
304
+ | `net-sales.png` | Detail screen, line chart, selected table row, back navigation |
305
+ | `check-search.png` | Check cards, teal check numbers, section headers |
306
+ | `dashboard-store-kitchen.png` | Nested tab bars, data table, teal action link |
307
+ | `open-tills.png` | Empty state pattern, 3-tab bar |
308
+ | `enable-face-id.png` | Modal overlay pattern |
309
+ | `loading.png` | Splash screen, brand illustration treatment |
310
+ | `dashboard-loading-error-with-toast.png` | Error state, toast pattern |
311
+
312
+ ---
313
+
314
+ ## Voice & copy
315
+
316
+ - **Direct and factual.** No marketing copy in UI. "Net Sales" not "Your earnings today."
317
+ - **Metric-first.** Lead with the number; context follows.
318
+ - **Sentence case** for all UI copy. ALL CAPS only for `NOTIFY` wordmark and section category labels (`KITCHEN`, `NETWORK`).
319
+ - **No emoji. Ever.**
320
+ - **Present tense** for states: "Sign in to continue", "No Tills Found", "Something Went Wrong".
321
+ - **Button labels are definitive:** "Sign In", "Refresh", "Enable Face ID" — no ellipsis, no "ing" forms.
322
+ - **Error toast copy (production):** "Ooops, we are having problems"
323
+
324
+ ---
325
+
326
+ ## Known gaps (v1.0.0)
327
+
328
+ - Toast component (anatomy in `screen-anatomy.md`)
329
+ - Data table component (anatomy in `screen-anatomy.md`)
330
+ - Kitchen Intelligence screen components (dark surface, 72px score, day-part switcher)
331
+ - Chart components (recommend Recharts with cyan/gray color scheme)
332
+ - Dark mode token set
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="26.667" height="26.667" viewBox="0 0 26.667 26.667" fill="none">
2
+ <path d="M 26.667 13.333 L 25.333 13.333 C 25.333 19.961 19.961 25.333 13.333 25.333 L 13.333 26.667 L 13.333 28 C 21.434 28 28 21.434 28 13.333 L 26.667 13.333 Z M 13.333 26.667 L 13.333 25.333 C 6.706 25.333 1.333 19.961 1.333 13.333 L 0 13.333 L -1.333 13.333 C -1.333 21.434 5.233 28 13.333 28 L 13.333 26.667 Z M 0 13.333 L 1.333 13.333 C 1.333 6.706 6.706 1.333 13.333 1.333 L 13.333 0 L 13.333 -1.333 C 5.233 -1.333 -1.333 5.233 -1.333 13.333 L 0 13.333 Z M 13.333 0 L 13.333 1.333 C 19.961 1.333 25.333 6.706 25.333 13.333 L 26.667 13.333 L 28 13.333 C 28 5.233 21.434 -1.333 13.333 -1.333 L 13.333 0 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="4.613" height="1.329" viewBox="0 0 4.613 1.329" fill="none">
2
+ <path d="M 5.767 0.669 C 6.136 0.032 5.919 -0.784 5.282 -1.153 C 4.645 -1.523 3.829 -1.306 3.46 -0.669 L 4.613 0 L 5.767 0.669 Z M 3.638 0.973 L 2.972 -0.183 L 2.972 -0.183 L 3.638 0.973 Z M 0.976 0.973 L 1.641 -0.183 L 1.641 -0.183 L 0.976 0.973 Z M 1.153 -0.669 C 0.784 -1.306 -0.032 -1.523 -0.669 -1.153 C -1.306 -0.784 -1.523 0.032 -1.153 0.669 L 0 0 L 1.153 -0.669 Z M 4.613 0 L 3.46 -0.669 C 3.343 -0.467 3.175 -0.299 2.972 -0.183 L 3.638 0.973 L 4.303 2.128 C 4.91 1.778 5.415 1.275 5.767 0.669 L 4.613 0 Z M 3.638 0.973 L 2.972 -0.183 C 2.77 -0.066 2.54 -0.005 2.307 -0.005 L 2.307 1.329 L 2.307 2.662 C 3.008 2.662 3.696 2.478 4.303 2.128 L 3.638 0.973 Z M 2.307 1.329 L 2.307 -0.005 C 2.073 -0.005 1.844 -0.066 1.641 -0.183 L 0.976 0.973 L 0.31 2.128 C 0.917 2.478 1.606 2.662 2.307 2.662 L 2.307 1.329 Z M 0.976 0.973 L 1.641 -0.183 C 1.439 -0.299 1.271 -0.467 1.153 -0.669 L 0 0 L -1.153 0.669 C -0.802 1.275 -0.297 1.778 0.31 2.128 L 0.976 0.973 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="20" viewBox="0 0 24 20" fill="none">
2
+ <path d="M 17.657 2.343 L 16.714 3.286 L 16.714 3.286 L 17.657 2.343 Z M 0 20 L -0.74 18.891 C -1.228 19.217 -1.446 19.824 -1.276 20.386 C -1.106 20.949 -0.588 21.333 0 21.333 L 0 20 Z M 24 20 L 24 21.333 C 24.588 21.333 25.106 20.949 25.276 20.386 C 25.446 19.824 25.228 19.217 24.74 18.891 L 24 20 Z M 20 8 L 21.333 8 C 21.333 5.525 20.35 3.151 18.6 1.4 L 17.657 2.343 L 16.714 3.286 C 17.964 4.536 18.667 6.232 18.667 8 L 20 8 Z M 17.657 2.343 L 18.6 1.4 C 16.849 -0.35 14.475 -1.333 12 -1.333 L 12 0 L 12 1.333 C 13.768 1.333 15.464 2.036 16.714 3.286 L 17.657 2.343 Z M 12 0 L 12 -1.333 C 9.525 -1.333 7.151 -0.35 5.4 1.4 L 6.343 2.343 L 7.286 3.286 C 8.536 2.036 10.232 1.333 12 1.333 L 12 0 Z M 6.343 2.343 L 5.4 1.4 C 3.65 3.151 2.667 5.525 2.667 8 L 4 8 L 5.333 8 C 5.333 6.232 6.036 4.536 7.286 3.286 L 6.343 2.343 Z M 4 8 L 2.667 8 C 2.667 12.47 1.711 15.246 0.829 16.862 C 0.387 17.673 -0.044 18.205 -0.343 18.521 C -0.493 18.679 -0.611 18.784 -0.682 18.843 C -0.717 18.872 -0.741 18.891 -0.751 18.898 C -0.756 18.902 -0.758 18.903 -0.756 18.902 C -0.755 18.901 -0.754 18.9 -0.751 18.898 C -0.749 18.897 -0.748 18.896 -0.746 18.895 C -0.745 18.894 -0.744 18.894 -0.743 18.893 C -0.742 18.892 -0.742 18.892 -0.741 18.892 C -0.74 18.891 -0.74 18.891 0 20 C 0.74 21.109 0.74 21.109 0.741 21.108 C 0.742 21.108 0.743 21.107 0.743 21.107 C 0.745 21.106 0.746 21.105 0.747 21.104 C 0.75 21.102 0.753 21.1 0.757 21.098 C 0.763 21.093 0.771 21.088 0.779 21.082 C 0.796 21.07 0.817 21.055 0.841 21.037 C 0.889 21.001 0.952 20.953 1.025 20.891 C 1.173 20.768 1.368 20.592 1.593 20.354 C 2.044 19.879 2.613 19.161 3.171 18.138 C 4.289 16.087 5.333 12.863 5.333 8 L 4 8 Z M 0 20 L 0 21.333 L 24 21.333 L 24 20 L 24 18.667 L 0 18.667 L 0 20 Z M 24 20 C 24.74 18.891 24.74 18.891 24.741 18.892 C 24.742 18.892 24.742 18.892 24.743 18.893 C 24.744 18.894 24.745 18.894 24.746 18.895 C 24.748 18.896 24.749 18.897 24.751 18.898 C 24.754 18.9 24.755 18.901 24.756 18.902 C 24.758 18.903 24.756 18.902 24.751 18.898 C 24.741 18.891 24.717 18.872 24.682 18.843 C 24.611 18.784 24.493 18.679 24.343 18.521 C 24.044 18.205 23.613 17.673 23.171 16.862 C 22.289 15.246 21.333 12.47 21.333 8 L 20 8 L 18.667 8 C 18.667 12.863 19.711 16.087 20.829 18.138 C 21.387 19.161 21.956 19.879 22.407 20.354 C 22.632 20.592 22.827 20.768 22.975 20.891 C 23.048 20.953 23.111 21.001 23.159 21.037 C 23.183 21.055 23.204 21.07 23.221 21.082 C 23.229 21.088 23.237 21.093 23.243 21.098 C 23.247 21.1 23.25 21.102 23.253 21.104 C 23.254 21.105 23.255 21.106 23.257 21.107 C 23.257 21.107 23.258 21.108 23.259 21.108 C 23.26 21.109 23.26 21.109 24 20 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="26.667" height="24" viewBox="0 0 26.667 24" fill="none">
2
+ <path d="M 26.667 0 L 27.685 0.861 C 28.02 0.465 28.095 -0.09 27.876 -0.561 C 27.658 -1.032 27.186 -1.333 26.667 -1.333 L 26.667 0 Z M 0 0 L 0 -1.333 C -0.519 -1.333 -0.991 -1.032 -1.209 -0.561 C -1.428 -0.09 -1.353 0.465 -1.018 0.861 L 0 0 Z M 10.667 12.613 L 12 12.613 C 12 12.298 11.888 11.993 11.685 11.752 L 10.667 12.613 Z M 10.667 21.333 L 9.333 21.333 C 9.333 21.838 9.619 22.3 10.07 22.526 L 10.667 21.333 Z M 16 24 L 15.404 25.193 C 15.817 25.399 16.308 25.377 16.701 25.134 C 17.094 24.891 17.333 24.462 17.333 24 L 16 24 Z M 16 12.613 L 14.982 11.752 C 14.778 11.993 14.667 12.298 14.667 12.613 L 16 12.613 Z M 26.667 0 L 26.667 -1.333 L 0 -1.333 L 0 0 L 0 1.333 L 26.667 1.333 L 26.667 0 Z M 0 0 L -1.018 0.861 L 9.649 13.474 L 10.667 12.613 L 11.685 11.752 L 1.018 -0.861 L 0 0 Z M 10.667 12.613 L 9.333 12.613 L 9.333 21.333 L 10.667 21.333 L 12 21.333 L 12 12.613 L 10.667 12.613 Z M 10.667 21.333 L 10.07 22.526 L 15.404 25.193 L 16 24 L 16.596 22.807 L 11.263 20.141 L 10.667 21.333 Z M 16 24 L 17.333 24 L 17.333 12.613 L 16 12.613 L 14.667 12.613 L 14.667 24 L 16 24 Z M 16 12.613 L 17.018 13.474 L 27.685 0.861 L 26.667 0 L 25.649 -0.861 L 14.982 11.752 L 16 12.613 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="26.667" height="26.667" viewBox="0 0 26.667 26.667" fill="none">
2
+ <path d="M 26.667 13.333 L 25.333 13.333 C 25.333 19.961 19.961 25.333 13.333 25.333 L 13.333 26.667 L 13.333 28 C 21.434 28 28 21.434 28 13.333 L 26.667 13.333 Z M 13.333 26.667 L 13.333 25.333 C 6.706 25.333 1.333 19.961 1.333 13.333 L 0 13.333 L -1.333 13.333 C -1.333 21.434 5.233 28 13.333 28 L 13.333 26.667 Z M 0 13.333 L 1.333 13.333 C 1.333 6.706 6.706 1.333 13.333 1.333 L 13.333 0 L 13.333 -1.333 C 5.233 -1.333 -1.333 5.233 -1.333 13.333 L 0 13.333 Z M 13.333 0 L 13.333 1.333 C 19.961 1.333 25.333 6.706 25.333 13.333 L 26.667 13.333 L 28 13.333 C 28 5.233 21.434 -1.333 13.333 -1.333 L 13.333 0 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="8" height="5.333" viewBox="0 0 8 5.333" fill="none">
2
+ <path d="M 0.943 1.724 C 0.422 1.203 -0.422 1.203 -0.943 1.724 C -1.464 2.245 -1.464 3.089 -0.943 3.609 L 0 2.667 L 0.943 1.724 Z M 2.667 5.333 L 1.724 6.276 C 2.245 6.797 3.089 6.797 3.609 6.276 L 2.667 5.333 Z M 8.943 0.943 C 9.464 0.422 9.464 -0.422 8.943 -0.943 C 8.422 -1.464 7.578 -1.464 7.057 -0.943 L 8 0 L 8.943 0.943 Z M 0 2.667 L -0.943 3.609 L 1.724 6.276 L 2.667 5.333 L 3.609 4.391 L 0.943 1.724 L 0 2.667 Z M 2.667 5.333 L 3.609 6.276 L 8.943 0.943 L 8 0 L 7.057 -0.943 L 1.724 4.391 L 2.667 5.333 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="21.333" height="14.667" viewBox="0 0 21.333 14.667" fill="none">
2
+ <path d="M 22.276 0.943 C 22.797 0.422 22.797 -0.422 22.276 -0.943 C 21.755 -1.464 20.911 -1.464 20.391 -0.943 L 21.333 0 L 22.276 0.943 Z M 6.667 14.667 L 5.724 15.609 C 6.245 16.13 7.089 16.13 7.609 15.609 L 6.667 14.667 Z M 0.943 7.057 C 0.422 6.536 -0.422 6.536 -0.943 7.057 C -1.464 7.578 -1.464 8.422 -0.943 8.943 L 0 8 L 0.943 7.057 Z M 21.333 0 L 20.391 -0.943 L 5.724 13.724 L 6.667 14.667 L 7.609 15.609 L 22.276 0.943 L 21.333 0 Z M 6.667 14.667 L 7.609 13.724 L 0.943 7.057 L 0 8 L -0.943 8.943 L 5.724 15.609 L 6.667 14.667 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="21.333" height="21.333" viewBox="0 0 21.333 21.333" fill="none">
2
+ <path d="M 21.333 10.667 L 20 10.667 C 20 15.821 15.821 20 10.667 20 L 10.667 21.333 L 10.667 22.667 C 17.294 22.667 22.667 17.294 22.667 10.667 L 21.333 10.667 Z M 10.667 21.333 L 10.667 20 C 5.512 20 1.333 15.821 1.333 10.667 L 0 10.667 L -1.333 10.667 C -1.333 17.294 4.039 22.667 10.667 22.667 L 10.667 21.333 Z M 0 10.667 L 1.333 10.667 C 1.333 5.512 5.512 1.333 10.667 1.333 L 10.667 0 L 10.667 -1.333 C 4.039 -1.333 -1.333 4.039 -1.333 10.667 L 0 10.667 Z M 10.667 0 L 10.667 1.333 C 15.821 1.333 20 5.512 20 10.667 L 21.333 10.667 L 22.667 10.667 C 22.667 4.039 17.294 -1.333 10.667 -1.333 L 10.667 0 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="8" height="5.333" viewBox="0 0 8 5.333" fill="none">
2
+ <path d="M 0.943 1.724 C 0.422 1.203 -0.422 1.203 -0.943 1.724 C -1.464 2.245 -1.464 3.089 -0.943 3.609 L 0 2.667 L 0.943 1.724 Z M 2.667 5.333 L 1.724 6.276 C 2.245 6.797 3.089 6.797 3.609 6.276 L 2.667 5.333 Z M 8.943 0.943 C 9.464 0.422 9.464 -0.422 8.943 -0.943 C 8.422 -1.464 7.578 -1.464 7.057 -0.943 L 8 0 L 8.943 0.943 Z M 0 2.667 L -0.943 3.609 L 1.724 6.276 L 2.667 5.333 L 3.609 4.391 L 0.943 1.724 L 0 2.667 Z M 2.667 5.333 L 3.609 6.276 L 8.943 0.943 L 8 0 L 7.057 -0.943 L 1.724 4.391 L 2.667 5.333 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="29.333" height="16" viewBox="0 0 29.333 16" fill="none">
2
+ <path d="M 28.391 16.943 C 28.911 17.464 29.755 17.464 30.276 16.943 C 30.797 16.422 30.797 15.578 30.276 15.057 L 29.333 16 L 28.391 16.943 Z M 16.667 3.333 L 17.609 2.391 C 17.089 1.87 16.245 1.87 15.724 2.391 L 16.667 3.333 Z M 10 10 L 9.057 10.943 C 9.578 11.464 10.422 11.464 10.943 10.943 L 10 10 Z M 0.943 -0.943 C 0.422 -1.464 -0.422 -1.464 -0.943 -0.943 C -1.464 -0.422 -1.464 0.422 -0.943 0.943 L 0 0 L 0.943 -0.943 Z M 29.333 16 L 30.276 15.057 L 17.609 2.391 L 16.667 3.333 L 15.724 4.276 L 28.391 16.943 L 29.333 16 Z M 16.667 3.333 L 15.724 2.391 L 9.057 9.057 L 10 10 L 10.943 10.943 L 17.609 4.276 L 16.667 3.333 Z M 10 10 L 10.943 9.057 L 0.943 -0.943 L 0 0 L -0.943 0.943 L 9.057 10.943 L 10 10 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="29.333" height="16" viewBox="0 0 29.333 16" fill="none">
2
+ <path d="M 30.276 0.943 C 30.797 0.422 30.797 -0.422 30.276 -0.943 C 29.755 -1.464 28.911 -1.464 28.391 -0.943 L 29.333 0 L 30.276 0.943 Z M 16.667 12.667 L 15.724 13.609 C 16.245 14.13 17.089 14.13 17.609 13.609 L 16.667 12.667 Z M 10 6 L 10.943 5.057 C 10.422 4.536 9.578 4.536 9.057 5.057 L 10 6 Z M -0.943 15.057 C -1.464 15.578 -1.464 16.422 -0.943 16.943 C -0.422 17.464 0.422 17.464 0.943 16.943 L 0 16 L -0.943 15.057 Z M 29.333 0 L 28.391 -0.943 L 15.724 11.724 L 16.667 12.667 L 17.609 13.609 L 30.276 0.943 L 29.333 0 Z M 16.667 12.667 L 17.609 11.724 L 10.943 5.057 L 10 6 L 9.057 6.943 L 15.724 13.609 L 16.667 12.667 Z M 10 6 L 9.057 5.057 L -0.943 15.057 L 0 16 L 0.943 16.943 L 10.943 6.943 L 10 6 Z" fill="currentColor" fill-rule="nonzero"></path>
3
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 40" width="200" height="40" fill="none">
2
+
3
+ <g transform="translate(0, 4) scale(1.16)">
4
+ <path d="M13.1486 18.1501H13.1373C11.8028 18.1501 10.5496 17.633 9.60346 16.6914C8.65509 15.7476 8.13122 14.4898 8.12671 13.1531C8.12445 11.8141 8.64154 10.5563 9.5854 9.60796C10.5293 8.65733 11.787 8.13572 13.126 8.13121H13.1373C14.4695 8.13121 15.725 8.65055 16.6711 9.5899C17.6195 10.5338 18.1433 11.7915 18.1456 13.1305C18.1501 14.4695 17.6308 15.7272 16.6869 16.6756C15.7431 17.6217 14.4876 18.1478 13.1486 18.1501ZM26.2768 13.1079C26.2678 9.59893 24.8949 6.3022 22.4088 3.82739C19.9204 1.35259 16.6056 -0.0067489 13.1079 2.51968e-05C9.59895 0.0067993 6.30447 1.38194 3.82741 3.86804C1.35035 6.35639 -0.00898741 9.65764 4.47226e-05 13.1689C0.00681882 16.6779 1.38196 19.9746 3.86806 22.4494C6.34738 24.9197 9.63733 26.2768 13.1373 26.2768H13.1689C14.0992 26.2745 15.0115 26.1752 15.9011 25.9855C18.3353 29.0541 22.0926 30.9667 26.1955 30.9735V22.8446C25.0258 22.8423 23.9329 22.4313 23.0681 21.7381C25.1478 19.3423 26.2836 16.3143 26.2768 13.1079Z" fill="black"></path>
5
+ </g>
6
+
7
+ <text x="34" y="34" font-family="&#39;Red Hat Display&#39;, &#39;Red Hat Text&#39;, sans-serif" font-weight="900" font-size="36" fill="black">u</text>
8
+
9
+ <line x1="68" y1="6" x2="68" y2="34" stroke="#DEDEDE" stroke-width="1.5"></line>
10
+
11
+ <text x="76" y="33" font-family="&#39;Red Hat Text&#39;, sans-serif" font-weight="400" font-size="28" letter-spacing="3" fill="black">NOTIFY</text>
12
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26.28 30.97" width="26.28" height="30.97" fill="none">
2
+ <path d="M13.1486 18.1501H13.1373C11.8028 18.1501 10.5496 17.633 9.60346 16.6914C8.65509 15.7476 8.13122 14.4898 8.12671 13.1531C8.12445 11.8141 8.64154 10.5563 9.5854 9.60796C10.5293 8.65733 11.787 8.13572 13.126 8.13121H13.1373C14.4695 8.13121 15.725 8.65055 16.6711 9.5899C17.6195 10.5338 18.1433 11.7915 18.1456 13.1305C18.1501 14.4695 17.6308 15.7272 16.6869 16.6756C15.7431 17.6217 14.4876 18.1478 13.1486 18.1501ZM26.2768 13.1079C26.2678 9.59893 24.8949 6.3022 22.4088 3.82739C19.9204 1.35259 16.6056 -0.0067489 13.1079 2.51968e-05C9.59895 0.0067993 6.30447 1.38194 3.82741 3.86804C1.35035 6.35639 -0.00898741 9.65764 4.47226e-05 13.1689C0.00681882 16.6779 1.38196 19.9746 3.86806 22.4494C6.34738 24.9197 9.63733 26.2768 13.1373 26.2768H13.1689C14.0992 26.2745 15.0115 26.1752 15.9011 25.9855C18.3353 29.0541 22.0926 30.9667 26.1955 30.9735V22.8446C25.0258 22.8423 23.9329 22.4313 23.0681 21.7381C25.1478 19.3423 26.2836 16.3143 26.2768 13.1079Z" fill="currentColor"></path>
3
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="52" height="31" viewBox="0 0 52 31" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M13.1486 18.1501H13.1373C11.8028 18.1501 10.5496 17.633 9.60346 16.6914C8.65509 15.7476 8.13122 14.4898 8.12671 13.1531C8.12445 11.8141 8.64154 10.5563 9.5854 9.60796C10.5293 8.65733 11.787 8.13572 13.126 8.13121H13.1373C14.4695 8.13121 15.725 8.65055 16.6711 9.5899C17.6195 10.5338 18.1433 11.7915 18.1456 13.1305C18.1501 14.4695 17.6308 15.7272 16.6869 16.6756C15.7431 17.6217 14.4876 18.1478 13.1486 18.1501ZM26.2768 13.1079C26.2678 9.59893 24.8949 6.3022 22.4088 3.82739C19.9204 1.35259 16.6056 -0.0067489 13.1079 2.51968e-05C9.59895 0.0067993 6.30447 1.38194 3.82741 3.86804C1.35035 6.35639 -0.00898741 9.65764 4.47226e-05 13.1689C0.00681882 16.6779 1.38196 19.9746 3.86806 22.4494C6.34738 24.9197 9.63733 26.2768 13.1373 26.2768H13.1689C14.0992 26.2745 15.0115 26.1752 15.9011 25.9855C18.3353 29.0541 22.0926 30.9667 26.1955 30.9735V22.8446C25.0258 22.8423 23.9329 22.4313 23.0681 21.7381C25.1478 19.3423 26.2836 16.3143 26.2768 13.1079Z" fill="currentColor"></path>
3
+ <path d="M40.218 26.2158C33.7216 26.2158 28.4355 20.932 28.4355 14.4356V10.5654H36.5645V14.4356C36.5645 16.4475 38.2038 18.0891 40.218 18.0891C41.1934 18.0891 42.1125 17.7098 42.8034 17.0188C43.4921 16.3279 43.8715 15.4111 43.8715 14.4334V10.5654H52.0004V14.4311C52.0004 17.5788 50.7743 20.5368 48.5501 22.7633C46.3259 24.9897 43.3657 26.2158 40.2202 26.2158H40.218Z" fill="currentColor"></path>
4
+ <path d="M51.9873 0.428978H28.4473V8.12436H51.9873V0.428978Z" fill="#41CCF2"></path>
5
+ </svg>
package/constraints.md ADDED
@@ -0,0 +1,114 @@
1
+ # Qu Notify — Hard Design Constraints
2
+
3
+ Rules extracted directly from production screenshots. Two lists: things that are **never** done, and things that are **always** done. These override everything else, including README prose.
4
+
5
+ ---
6
+
7
+ ## NEVER
8
+
9
+ ### Color
10
+ - **Never use cyan (#40CCF2) as a large background fill.** It is a pill/stroke/accent color only. The app background is always `#F4F4F4`, cards `#FFFFFF`.
11
+ - **Never use cyan text on a dark background for body copy.** Cyan text only appears on white/light surfaces (links, active teal-variant labels).
12
+ - **Never change the disabled state by swapping colors.** Disabled = `opacity: 0.5` on the entire component. The component's own colors stay intact underneath.
13
+ - **Never use brand-red (#EF2149) for anything other than errors, error borders, and the "Claimed" data status.** It is not a general accent.
14
+
15
+ ### Typography
16
+ - **No emoji, anywhere.** Not in buttons, labels, tiles, toasts, empty states, or body copy. Zero.
17
+ - **Never sentence-case the wordmark.** The product name is always `NOTIFY` (all-caps). The company name is `QU` or `Qu` — never `qu` or `notify`.
18
+ - **Never use Zilla Slab for body copy or UI labels.** It is display-only (onboarding headlines, pull quotes, splash screen).
19
+ - **Never left-align a centered-title screen header.** Detail screens (Net Sales, Check Search, Tills, etc.) have a centered title with a back chevron left.
20
+
21
+ ### Inputs & Forms
22
+ - **Never use a rectangular input field.** All input fields are full-radius pills (`border-radius: 9999px`).
23
+ - **Never show a required field asterisk in gray.** The asterisk is always brand-red (#EF2149).
24
+ - **Never use the error color for the label text.** The label stays black; only the border, helper text, and right icon flip to red on error.
25
+
26
+ ### Buttons
27
+ - **Never use a rectangular button.** All buttons are full-radius pills.
28
+ - **Never make the primary button black.** Black is the nav/tab selected-state color. The primary CTA button is cyan (#40CCF2).
29
+ - **Never put an outline on a primary button.** Primary = solid fill only.
30
+
31
+ ### Navigation & Layout
32
+ - **Never show bottom nav on authentication screens** (Sign In, 2-Step, Reset Password, Choose Password, Enable Face ID, Splash).
33
+ - **Never show bottom nav on detail/drill-down screens** (Net Sales, Check detail, Tills detail, Thanksgiving Feast, etc.). Bottom nav is dashboard-level only.
34
+ - **Never use the bottom nav for more than 3 items** — Dashboard, Inventory, Menu.
35
+ - **Never stack two context-selector bars.** The store + date selectors always appear on a single line separated by a bullet `•`.
36
+
37
+ ### Icons
38
+ - **Never use icon fonts.** SVG only — stroke style, rounded caps and joins.
39
+ - **Never fill a stroke icon** (except when used as an illustration element on the splash screen).
40
+
41
+ ### Copy
42
+ - **Never write marketing copy in the app.** All copy is operational and direct. "Net Sales" not "Your earnings today".
43
+ - **Never use first-person in UI labels.** "Sign in to continue", not "Let's get you signed in".
44
+ - **Never use ellipsis (...) in button labels.** Buttons are always definitive: "Sign In", "Refresh", "Enable Face ID", "Continue".
45
+
46
+ ---
47
+
48
+ ## ALWAYS
49
+
50
+ ### Color
51
+ - **App background:** `#F4F4F4` (gray-50). Never white at the page level.
52
+ - **Card/tile background:** `#FFFFFF`. Always white, no tinted card backgrounds.
53
+ - **Primary CTA button fill:** `#40CCF2` (Tech Blue/cyan).
54
+ - **Selected tab / nav item fill:** `#000000` (black).
55
+ - **Context selectors (store + date pills):** Always cyan fill, regardless of page.
56
+ - **Active input border:** Cyan (#40CCF2), 1.5px, pill shape.
57
+ - **Error input border:** Brand-red (#EF2149), 1.5px.
58
+ - **Toast bar (error):** Brand-red fill, white text, full-radius pill, fixed bottom.
59
+ - **Teal (#339FB8):** Secondary interactive — link text, secondary button outline/text, action labels ("Fulfilment", "Quantity"), check numbers in Check Search.
60
+
61
+ ### Typography
62
+ - **Header font:** Red Hat Text — section labels, input labels, button labels, menu items.
63
+ - **Body / data font:** Inter — all metric values, table data, body copy, captions.
64
+ - **Label casing:** Title Case for page headers and section titles. ALL CAPS for the product wordmark (NOTIFY). Sentence case for everything else (button labels, helper text, body).
65
+ - **Metric values:** Inter SemiBold, 24px minimum on dashboard tiles.
66
+ - **Version string:** Always shown on auth screens. Format: `Version 3.6.222-build. 1483`.
67
+
68
+ ### Inputs
69
+ - **Always pill-shaped** (`border-radius: 9999px`).
70
+ - **Always show a label above the field** (not a placeholder-as-label pattern).
71
+ - **Always show the eye icon** on password fields for show/hide toggle.
72
+ - **Always show `*Required Fields`** footnote below the form when required fields exist.
73
+
74
+ ### Buttons
75
+ - **Always pill-shaped.** No exceptions.
76
+ - **Disabled button:** Full opacity of the normal state, but `opacity: 0.5` on the component — the cyan fill remains visible underneath.
77
+ - **Primary CTA always centered** on auth/modal screens. Dashboard actions can be left-aligned.
78
+
79
+ ### Navigation
80
+ - **Always show the QU NOTIFY lockup** top-left on authenticated screens.
81
+ - **Always show the bell icon** top-right on authenticated screens (with red dot when notifications exist).
82
+ - **Context bar (store + date) always appears** below the header on all authenticated data screens.
83
+ - **Back navigation:** Left-chevron icon only (no text) on data detail screens. Text link "< Back to [screen]" on auth sub-screens (Two-Step, Reset Password).
84
+ - **Bottom nav always shows all 3 items** even when one is active. Never hide inactive items.
85
+ - **Bottom nav selected item:** Black pill behind icon + label, white icon + Semi Bold label. Unselected: gray icon + Regular label.
86
+
87
+ ### Cards & Tiles
88
+ - **Always 16px border-radius** on metric tiles.
89
+ - **Always `box-shadow: 0 4px 4px rgba(0,0,0,0.06)`** on metric tiles and cards.
90
+ - **Never a visible border** on cards — shadow only provides the elevation.
91
+
92
+ ### Empty States
93
+ - **Always show a gray stroke icon** (not brand-colored) above the empty-state message.
94
+ - **Message format:** "No [Thing] Found" — noun-first, sentence case.
95
+
96
+ ### Error States
97
+ - **In-page error:** Cyan info-circle icon, centered copy ("Something Went Wrong / Try Refreshing"), cyan "Refresh" button.
98
+ - **Toast error:** Red pill, "Ooops, we are having problems" — this is the actual production copy.
99
+
100
+ ### Modals / Sheets
101
+ - **Dark scrim behind modals:** `rgba(8,8,8,0.8)`.
102
+ - **Modal card:** White, `border-radius: 24px` minimum, centered.
103
+ - **Bottom sheet (menu):** Slides up from bottom, white, `border-radius: 60px` top corners, drag handle at top.
104
+
105
+ ### Table / List Patterns
106
+ - **Active/selected row highlight:** Cyan fill (`#40CCF2`) row background with black text.
107
+ - **Chevron `>`** on every tappable row.
108
+ - **Column headers** right-aligned for numeric columns, left-aligned for name columns.
109
+ - **Section action links** (e.g. "Fulfilment", "Quantity") always teal, right-aligned.
110
+
111
+ ### Spacing
112
+ - **Minimum tap target:** 44×44px (iOS HIG).
113
+ - **Screen horizontal padding:** 16px left/right (matches `--space-lg`).
114
+ - **Card grid gap:** 12px between tiles (`--space-xs` to `--space-sm`).