@syncedco/flow 0.3.0 → 0.3.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/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ ## 0.3.1 - 2026-06-13
4
+
5
+ - Fix mobile app drawer scrolling by giving the drawer sidebar a viewport block size.
6
+ - Vertically center `.sf-tab` contents.
7
+ - Improve built-in dark theme token coverage for primary, state, soft, ring, and glow tokens.
8
+ - Make `.sf-filter-bar` alignment token-configurable with a centered default.
9
+ - Add a status-chip dot opt-out with `data-dot="false"` and `sf-status--label`.
10
+ - Add reduced-motion safeguards for hover lift and marquee animation.
11
+ - Add public `--sf-z-*` stacking tokens for header, backdrop, drawer, overlay, toast, sticky, and skip-link layers.
12
+ - Reframe positioning copy from "AI-native" to "AI-friendly".
13
+ - Document the global theme config scope and the project-CSS pattern for advanced theme matrices.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Synced Flow
2
2
 
3
- AI-native fluid CSS design system for brand-consistent websites, agency builds,
3
+ AI-friendly fluid CSS design system for brand-consistent websites, agency builds,
4
4
  and modern frontend projects.
5
5
 
6
6
  Synced Flow gives developers and AI coding agents a shared styling contract:
@@ -58,6 +58,7 @@ documentation, and recipes.
58
58
  Useful project files:
59
59
 
60
60
  - [Contributing](CONTRIBUTING.md)
61
+ - [Changelog](CHANGELOG.md)
61
62
  - [Security policy](SECURITY.md)
62
63
  - [Code of conduct](CODE_OF_CONDUCT.md)
63
64
  - [Support](SUPPORT.md)
package/components.css CHANGED
@@ -432,6 +432,16 @@
432
432
  to { transform: translateX(-50%); }
433
433
  }
434
434
 
435
+ @media (prefers-reduced-motion: reduce) {
436
+ :where(.sf-button:hover, .sf-card--interactive:hover) {
437
+ transform: none;
438
+ }
439
+
440
+ .sf-marquee__track {
441
+ animation: none;
442
+ }
443
+ }
444
+
435
445
  .sf-command-list {
436
446
  display: grid;
437
447
  font-family: var(--sf-font-mono);
@@ -837,7 +847,7 @@
837
847
  }
838
848
 
839
849
  .sf-filter-bar {
840
- align-items: end;
850
+ align-items: var(--sf-filter-bar-align, center);
841
851
  background: var(--sf-colour-surface);
842
852
  border: 1px solid var(--sf-colour-border);
843
853
  border-radius: var(--sf-radius-panel);
@@ -984,6 +994,10 @@
984
994
  inline-size: .42em;
985
995
  }
986
996
 
997
+ :where(.sf-status[data-dot="false"], .sf-status--label)::before {
998
+ content: none;
999
+ }
1000
+
987
1001
  .sf-status[data-tone="success"] {
988
1002
  --sf-status-bg: var(--sf-colour-success-soft);
989
1003
  --sf-status-border: color-mix(in oklch, var(--sf-colour-success) 34%, transparent);
@@ -1418,6 +1432,7 @@
1418
1432
  :where(.sf-popover, .sf-menu-popover, .sf-tooltip, .sf-toast, .sf-banner, .sf-drawer):popover-open {
1419
1433
  display: grid;
1420
1434
  gap: var(--sf-space-xs);
1435
+ z-index: var(--sf-z-overlay);
1421
1436
  }
1422
1437
 
1423
1438
  .sf-popover {
@@ -1489,7 +1504,7 @@
1489
1504
  inset-block-start: var(--sf-space-s);
1490
1505
  inset-inline-end: var(--sf-space-s);
1491
1506
  position: fixed;
1492
- z-index: 50;
1507
+ z-index: var(--sf-z-toast);
1493
1508
  }
1494
1509
 
1495
1510
  .sf-banner {
@@ -1604,6 +1619,7 @@
1604
1619
  }
1605
1620
 
1606
1621
  .sf-tab {
1622
+ align-items: center;
1607
1623
  border-block-end: 0.125rem solid transparent;
1608
1624
  border-radius: var(--sf-radius-full);
1609
1625
  color: var(--sf-colour-muted);
@@ -0,0 +1,113 @@
1
+ # Synced Flow Audit — June 2026 (v0.3.0)
2
+
3
+ Independent audit of `@syncedco/flow` at v0.3.0 (`a8a1f68`), run across three
4
+ passes: product coherence (claims vs shipped), CSS quality, and tooling/release
5
+ engineering. Findings are grounded in the source and in real consumer feedback
6
+ from the Synced CRM (`synced-crm`, the first production app consumer).
7
+
8
+ ## Verdict
9
+
10
+ Flow delivers its **original model (websites/agency) almost completely** and
11
+ the **engineering discipline behind it impressively**. It falls short in three
12
+ places: **app-tier depth**, **advanced theming scope**, and a few product
13
+ positioning/docs gaps. It is a real, well-built system, and the positioning now
14
+ fits better as AI-friendly / agent-ready.
15
+
16
+ | Dimension | Rating | Summary |
17
+ |---|---|---|
18
+ | Fluid foundation (tokens, scales, layout) | ✅ Excellent | Genuine Utopia-style fluidity; modern CSS (layers, oklch, logical props, container queries); clean layer hygiene |
19
+ | Website/agency coverage | ✅ ~90% | Everything claimed ships; agency-ready without custom CSS |
20
+ | Tooling & release engineering | ✅ Excellent | 14 tested CLI commands, guardrails (size budgets, zero-dep, px policy), 40/40 tests, automated tag-driven publishing |
21
+ | App/SaaS tier (0.2–0.3) | ⚠️ ~60% | Real scaffolding (proven by the CRM) but thin; consumers carry 20–40% custom CSS |
22
+ | Dark mode | ✅ Patched after audit | `.sf-theme-dark` now overrides primary/status/soft/ring/glow tokens rather than inheriting light-tuned values |
23
+ | Theming config | ✅ Documented boundary | Config handles global light/dark token themes; advanced per-surface/multi-variant theming belongs in project CSS token scopes |
24
+ | AI positioning | ✅ Reframed | Positioning now uses AI-friendly / agent-ready language for the shipped CLI, skill, and agent guidance |
25
+ | Docs | ⚠️ Improving | Website docs thorough; CHANGELOG and theming-scope docs added; app-tier docs can still mature |
26
+
27
+ ## Confirmed bugs (found by the CRM, verified in source)
28
+
29
+ 1. **Drawer can't scroll** — fixed after audit by adding `block-size: 100dvh`
30
+ to `.sf-app-shell[data-mobile="drawer"] .sf-app-sidebar`, giving the
31
+ existing `overflow: auto` a real viewport-height scroll container.
32
+ 2. **`.sf-tab` not vertically centred** — fixed after audit with
33
+ `align-items: center`.
34
+ 3. **`.sf-filter-bar` `align-items: end`** — fixed after audit with
35
+ `align-items: var(--sf-filter-bar-align, center)`, preserving a project
36
+ escape hatch without adding a new component variant.
37
+ 4. **`.sf-status` dot is mandatory** — fixed after audit with
38
+ `data-dot="false"` and `sf-status--label` opt-outs.
39
+
40
+ ## Higher-severity findings the CRM did NOT hit
41
+
42
+ These mattered because no consumer had exercised them yet. They are now patched
43
+ or documented, but should still be validated in the next real consumer.
44
+
45
+ 5. **Dark mode token coverage is critically incomplete** — fixed after audit
46
+ for the shipped base theme by adding dark-mode primary, state, soft, ring,
47
+ and glow token overrides.
48
+ 6. **Z-index scale is compressed and undocumented** — fixed after audit with
49
+ public `--sf-z-*` tokens wired into header, backdrop, drawer, overlay, toast,
50
+ sticky, and skip-link layers.
51
+ 7. **Missing `prefers-reduced-motion` guards** — fixed after audit for
52
+ `.sf-button:hover`, `.sf-card--interactive:hover`, and the marquee track.
53
+
54
+ ## Theming model limitation (real, undocumented)
55
+
56
+ Config supports global light + `darkColours` + per-preset overrides. It does
57
+ not try to express per-surface / multi-variant theming (e.g. `[data-theme]` ×
58
+ `[data-surface]` matrices, per-tenant white-label, density-by-context). That is
59
+ a legitimate design choice for Synced Flow's scope, and `config-reference.md`
60
+ now documents the hand-written token-scope pattern for advanced cases.
61
+
62
+ ## AI-Friendly Positioning
63
+
64
+ What ships is real and good: `catalog --json`, `suggest`, `pattern`, `recipe`,
65
+ `lint`, `doctor`, a packaged skill, and `agents install` for 8 targets. The
66
+ project now describes this as **AI-friendly** and agent-readable tooling rather
67
+ than implying runtime AI integration.
68
+
69
+ ## App-tier coverage gaps (from real CRM adoption)
70
+
71
+ Shipped and adopted: app-shell, data-table, empty-state, filter-bar, status
72
+ chips, tabs, toast skin, form field shells. Still missing for production app
73
+ work (CRM kept custom or deferred): combobox/searchable select, pagination
74
+ depth (page size, jump-to-page), modal-with-form as a primitive (not just a
75
+ pattern), bulk-actions toolbar, multi-step/wizard, skeleton loading compounds,
76
+ sticky-header + horizontal-scroll tables. Kanban/timesheet/invoice-doc are
77
+ deliberately consumer-specific and out of scope.
78
+
79
+ ## Strengths (keep doing)
80
+
81
+ - Real fluidity; modern CSS; excellent cascade-layer hygiene.
82
+ - Tooling/release engineering is the strongest area: guardrails enforce
83
+ zero-dependency, per-layer gzip size budgets, layer order, and a raw-px
84
+ policy; 40/40 tests pass; tag-driven OIDC publishing; complete exports map.
85
+ - CLI catalog currently in sync with shipped CSS (verified) — though by hand.
86
+ - AI agent guidance (skill + `agents install`) is current with 0.3.0 primitives.
87
+
88
+ ## Recommended roadmap
89
+
90
+ **0.3.1 — bug patch (small, soon):**
91
+ 1. Drawer viewport scroll container. ✅
92
+ 2. `.sf-tab` `align-items: center`. ✅
93
+ 3. `.sf-filter-bar` tokenized alignment with centered default. ✅
94
+ 4. `.sf-status` dot opt-out. ✅
95
+ 5. `prefers-reduced-motion` guards on hover transforms + marquee. ✅
96
+
97
+ **0.4.0 — structural gaps:**
98
+ 6. Continue dark-mode validation with a real consumer using Flow's built-in
99
+ theme selectors.
100
+ 7. Begin app-tier depth: combobox, pagination, modal-with-form, bulk-actions —
101
+ prioritised by what the CRM had to keep custom.
102
+
103
+ **Docs / positioning / CI (cheap, high-trust):**
104
+ 8. CI: smoke-build the examples; add a test asserting the CLI catalog matches
105
+ the shipped CSS (in sync today only by hand); consider a CSS parse/lint and
106
+ a small visual-regression pass.
107
+
108
+ ## Meta-observation
109
+
110
+ The four bugs the CRM surfaced are exactly the class only a real consumer finds
111
+ — the proving-ground loop is working as intended. The most useful next
112
+ validation step is getting a second consumer, or the CRM itself, onto Flow's
113
+ built-in dark mode and app primitives before 1.0.
@@ -79,3 +79,30 @@ theme: {
79
79
  },
80
80
  }
81
81
  ```
82
+
83
+ ## Theme Scope
84
+
85
+ The config theme model is intentionally global. Use `theme.colours` for the
86
+ default token set and `theme.darkColours` for `.sf-theme-dark` /
87
+ `[data-sf-theme="dark"]` overrides. This covers the common site or app case:
88
+ one brand token set, with an optional dark-mode token set.
89
+
90
+ Synced Flow does not try to encode every theme matrix in config. If a project
91
+ needs per-tenant branding, `[data-surface]` variants, density-by-context, or
92
+ other multi-axis theme rules, keep the reusable defaults in config and write
93
+ the extra token scopes in project CSS:
94
+
95
+ ```css
96
+ [data-tenant="acme"] {
97
+ --sf-colour-primary: oklch(62% 0.19 252);
98
+ --sf-colour-primary-hover: oklch(56% 0.19 252);
99
+ }
100
+
101
+ [data-surface="inset"] {
102
+ --sf-colour-surface: var(--sf-colour-surface-inset);
103
+ --sf-card-padding: var(--sf-space-s);
104
+ }
105
+ ```
106
+
107
+ Use this pattern for deliberate product theming. Avoid scattering one-off
108
+ colour values through page components when a value can live in a token scope.
@@ -17,6 +17,7 @@ Use the `--sf-*` variables as the stable CSS foundation.
17
17
  | App colour | `--sf-colour-surface-hover`, `--sf-colour-surface-raised-2`, `--sf-colour-border-subtle`, `--sf-colour-backdrop` | App surfaces, hover states, subtle dividers, and overlays. |
18
18
  | Categorical colour | `--sf-colour-categorical-1` ... `--sf-colour-categorical-6` | Charts, stages, labels, and recurring data accents. |
19
19
  | State | `--sf-colour-success`, `--sf-colour-warning`, `--sf-colour-danger`, `--sf-colour-info` | Feedback and notices. |
20
+ | Z-index | `--sf-z-header`, `--sf-z-backdrop`, `--sf-z-drawer`, `--sf-z-overlay`, `--sf-z-toast` | Shared stacking slots for app chrome, drawers, popovers, and feedback. |
20
21
  | Motion | `--sf-duration-fast`, `--sf-duration-normal`, `--sf-ease-standard` | Consistent transitions. |
21
22
  | Component | `--sf-button-*`, `--sf-card-*`, `--sf-input-*`, `--sf-alert-*` | Reusable component defaults. |
22
23
  | Accessibility | `:focus-visible`, `:target`, `[aria-invalid]`, `[aria-current]`, `[aria-expanded]`, `[aria-selected]`, `[aria-busy]`, `[aria-disabled]` | Visible native and ARIA states. |
package/docs/tokens.md CHANGED
@@ -86,6 +86,8 @@ The generated core includes enough semantic variables for common website UI:
86
86
  - structure: `--sf-colour-border-subtle`, `--sf-colour-border`,
87
87
  `--sf-colour-border-strong`, `--sf-colour-backdrop`,
88
88
  `--sf-radius-control`, `--sf-radius-panel`, `--sf-shadow-*`
89
+ - stacking: `--sf-z-sticky`, `--sf-z-header`, `--sf-z-backdrop`,
90
+ `--sf-z-drawer`, `--sf-z-overlay`, `--sf-z-toast`, `--sf-z-skip-link`
89
91
  - data accents: `--sf-colour-categorical-1` through
90
92
  `--sf-colour-categorical-6`
91
93
 
@@ -22,7 +22,7 @@ Synced Flow is designed to reduce the number of styling decisions made from scra
22
22
 
23
23
  Synced Flow is not trying to be a Tailwind clone, a Bootstrap replacement, or a React component library.
24
24
 
25
- It is an AI-native fluid CSS design system for brand-consistent websites and agency builds.
25
+ It is an AI-friendly fluid CSS design system for brand-consistent websites and agency builds.
26
26
 
27
27
  Use it when you want:
28
28
 
package/layout.css CHANGED
@@ -116,7 +116,7 @@
116
116
  justify-content: space-between;
117
117
  min-block-size: var(--sf-app-header-height);
118
118
  padding-inline: var(--sf-space-s-m);
119
- z-index: 20;
119
+ z-index: var(--sf-z-header);
120
120
  }
121
121
 
122
122
  .sf-app-shell[data-layout~="fixed-header"] {
@@ -199,6 +199,7 @@
199
199
  }
200
200
 
201
201
  .sf-app-shell[data-mobile="drawer"] .sf-app-sidebar {
202
+ block-size: 100dvh;
202
203
  box-shadow: var(--sf-shadow-xl);
203
204
  inline-size: min(18rem, calc(100vw - var(--sf-space-l)));
204
205
  inset-block: 0;
@@ -207,7 +208,7 @@
207
208
  min-block-size: 100dvh;
208
209
  position: fixed;
209
210
  transform: translateX(-100%);
210
- z-index: 30;
211
+ z-index: var(--sf-z-drawer);
211
212
  }
212
213
 
213
214
  .sf-app-shell[data-mobile="drawer"][data-sidebar-open="true"] .sf-app-sidebar {
@@ -219,7 +220,7 @@
219
220
  display: block;
220
221
  inset: 0;
221
222
  position: fixed;
222
- z-index: 25;
223
+ z-index: var(--sf-z-backdrop);
223
224
  }
224
225
  }
225
226
 
@@ -363,7 +364,7 @@
363
364
  .sf-sticky-top {
364
365
  position: sticky;
365
366
  inset-block-start: var(--sf-sticky-offset, 0);
366
- z-index: var(--sf-sticky-z, 20);
367
+ z-index: var(--sf-sticky-z, var(--sf-z-sticky));
367
368
  }
368
369
 
369
370
  .sf-media-object {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@syncedco/flow",
3
- "version": "0.3.0",
4
- "description": "AI-native fluid CSS design system for brand-consistent websites and agency builds.",
3
+ "version": "0.3.1",
4
+ "description": "AI-friendly fluid CSS design system for brand-consistent websites and agency builds.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.2.2",
7
7
  "license": "MIT",
@@ -63,6 +63,7 @@
63
63
  "examples",
64
64
  "skills",
65
65
  "src",
66
+ "CHANGELOG.md",
66
67
  "CODE_OF_CONDUCT.md",
67
68
  "CONTRIBUTING.md",
68
69
  "LICENSE",
package/styles.css CHANGED
@@ -150,6 +150,13 @@
150
150
  --sf-shadow-xl: 0 1.75rem 4rem oklch(0% 0 0 / 0.18);
151
151
  --sf-shadow-inset: inset 0 0 0 1px var(--sf-colour-border);
152
152
  --sf-shadow-glow: 0 0 2rem oklch(68% 0.18 44 / 0.24);
153
+ --sf-z-sticky: 20;
154
+ --sf-z-header: 20;
155
+ --sf-z-backdrop: 25;
156
+ --sf-z-drawer: 30;
157
+ --sf-z-overlay: 40;
158
+ --sf-z-toast: 50;
159
+ --sf-z-skip-link: 999;
153
160
  --sf-duration-fast: 150ms;
154
161
  --sf-duration-normal: 220ms;
155
162
  --sf-duration-slow: 360ms;
@@ -210,8 +217,27 @@
210
217
  --sf-colour-border: oklch(100% 0 0 / 0.14);
211
218
  --sf-colour-border-strong: oklch(100% 0 0 / 0.24);
212
219
  --sf-colour-backdrop: oklch(0% 0 0 / 0.64);
220
+ --sf-colour-primary: var(--sf-colour-orange-500);
221
+ --sf-colour-primary-hover: oklch(80% 0.14 50);
222
+ --sf-colour-primary-foreground: var(--sf-colour-neutral-950);
223
+ --sf-colour-primary-soft: oklch(74% 0.17 48 / 0.18);
224
+ --sf-colour-primary-soft-border: oklch(74% 0.17 48 / 0.34);
213
225
  --sf-colour-link: var(--sf-colour-orange-500);
214
226
  --sf-colour-link-hover: oklch(80% 0.14 50);
227
+ --sf-colour-success: oklch(72% 0.13 150);
228
+ --sf-colour-success-foreground: var(--sf-colour-neutral-950);
229
+ --sf-colour-success-soft: oklch(72% 0.13 150 / 0.16);
230
+ --sf-colour-warning: oklch(84% 0.15 82);
231
+ --sf-colour-warning-foreground: var(--sf-colour-neutral-950);
232
+ --sf-colour-warning-soft: oklch(84% 0.15 82 / 0.18);
233
+ --sf-colour-danger: oklch(70% 0.18 28);
234
+ --sf-colour-danger-foreground: var(--sf-colour-neutral-950);
235
+ --sf-colour-danger-soft: oklch(70% 0.18 28 / 0.16);
236
+ --sf-colour-info: oklch(76% 0.12 205);
237
+ --sf-colour-info-foreground: var(--sf-colour-neutral-950);
238
+ --sf-colour-info-soft: oklch(76% 0.12 205 / 0.16);
239
+ --sf-colour-ring: var(--sf-colour-orange-500);
240
+ --sf-shadow-glow: 0 0 2rem oklch(74% 0.17 48 / 0.18);
215
241
  }
216
242
  @layer reset {
217
243
  *, *::before, *::after { box-sizing: border-box; }
@@ -438,7 +464,7 @@
438
464
  justify-content: space-between;
439
465
  min-block-size: var(--sf-app-header-height);
440
466
  padding-inline: var(--sf-space-s-m);
441
- z-index: 20;
467
+ z-index: var(--sf-z-header);
442
468
  }
443
469
 
444
470
  .sf-app-shell[data-layout~="fixed-header"] {
@@ -521,6 +547,7 @@
521
547
  }
522
548
 
523
549
  .sf-app-shell[data-mobile="drawer"] .sf-app-sidebar {
550
+ block-size: 100dvh;
524
551
  box-shadow: var(--sf-shadow-xl);
525
552
  inline-size: min(18rem, calc(100vw - var(--sf-space-l)));
526
553
  inset-block: 0;
@@ -529,7 +556,7 @@
529
556
  min-block-size: 100dvh;
530
557
  position: fixed;
531
558
  transform: translateX(-100%);
532
- z-index: 30;
559
+ z-index: var(--sf-z-drawer);
533
560
  }
534
561
 
535
562
  .sf-app-shell[data-mobile="drawer"][data-sidebar-open="true"] .sf-app-sidebar {
@@ -541,7 +568,7 @@
541
568
  display: block;
542
569
  inset: 0;
543
570
  position: fixed;
544
- z-index: 25;
571
+ z-index: var(--sf-z-backdrop);
545
572
  }
546
573
  }
547
574
 
@@ -685,7 +712,7 @@
685
712
  .sf-sticky-top {
686
713
  position: sticky;
687
714
  inset-block-start: var(--sf-sticky-offset, 0);
688
- z-index: var(--sf-sticky-z, 20);
715
+ z-index: var(--sf-sticky-z, var(--sf-z-sticky));
689
716
  }
690
717
 
691
718
  .sf-media-object {
@@ -1206,6 +1233,16 @@
1206
1233
  to { transform: translateX(-50%); }
1207
1234
  }
1208
1235
 
1236
+ @media (prefers-reduced-motion: reduce) {
1237
+ :where(.sf-button:hover, .sf-card--interactive:hover) {
1238
+ transform: none;
1239
+ }
1240
+
1241
+ .sf-marquee__track {
1242
+ animation: none;
1243
+ }
1244
+ }
1245
+
1209
1246
  .sf-command-list {
1210
1247
  display: grid;
1211
1248
  font-family: var(--sf-font-mono);
@@ -1611,7 +1648,7 @@
1611
1648
  }
1612
1649
 
1613
1650
  .sf-filter-bar {
1614
- align-items: end;
1651
+ align-items: var(--sf-filter-bar-align, center);
1615
1652
  background: var(--sf-colour-surface);
1616
1653
  border: 1px solid var(--sf-colour-border);
1617
1654
  border-radius: var(--sf-radius-panel);
@@ -1758,6 +1795,10 @@
1758
1795
  inline-size: .42em;
1759
1796
  }
1760
1797
 
1798
+ :where(.sf-status[data-dot="false"], .sf-status--label)::before {
1799
+ content: none;
1800
+ }
1801
+
1761
1802
  .sf-status[data-tone="success"] {
1762
1803
  --sf-status-bg: var(--sf-colour-success-soft);
1763
1804
  --sf-status-border: color-mix(in oklch, var(--sf-colour-success) 34%, transparent);
@@ -2192,6 +2233,7 @@
2192
2233
  :where(.sf-popover, .sf-menu-popover, .sf-tooltip, .sf-toast, .sf-banner, .sf-drawer):popover-open {
2193
2234
  display: grid;
2194
2235
  gap: var(--sf-space-xs);
2236
+ z-index: var(--sf-z-overlay);
2195
2237
  }
2196
2238
 
2197
2239
  .sf-popover {
@@ -2263,7 +2305,7 @@
2263
2305
  inset-block-start: var(--sf-space-s);
2264
2306
  inset-inline-end: var(--sf-space-s);
2265
2307
  position: fixed;
2266
- z-index: 50;
2308
+ z-index: var(--sf-z-toast);
2267
2309
  }
2268
2310
 
2269
2311
  .sf-banner {
@@ -2378,6 +2420,7 @@
2378
2420
  }
2379
2421
 
2380
2422
  .sf-tab {
2423
+ align-items: center;
2381
2424
  border-block-end: 0.125rem solid transparent;
2382
2425
  border-radius: var(--sf-radius-full);
2383
2426
  color: var(--sf-colour-muted);
@@ -2656,7 +2699,7 @@
2656
2699
  text-decoration: none;
2657
2700
  transform: translateY(calc(-100% - var(--sf-space-m)));
2658
2701
  transition: opacity var(--sf-duration-fast) var(--sf-ease-standard), transform var(--sf-duration-fast) var(--sf-ease-standard);
2659
- z-index: 999;
2702
+ z-index: var(--sf-z-skip-link);
2660
2703
  }
2661
2704
 
2662
2705
  .sf-skip-link:focus-visible {
package/tokens.css CHANGED
@@ -150,6 +150,13 @@
150
150
  --sf-shadow-xl: 0 1.75rem 4rem oklch(0% 0 0 / 0.18);
151
151
  --sf-shadow-inset: inset 0 0 0 1px var(--sf-colour-border);
152
152
  --sf-shadow-glow: 0 0 2rem oklch(68% 0.18 44 / 0.24);
153
+ --sf-z-sticky: 20;
154
+ --sf-z-header: 20;
155
+ --sf-z-backdrop: 25;
156
+ --sf-z-drawer: 30;
157
+ --sf-z-overlay: 40;
158
+ --sf-z-toast: 50;
159
+ --sf-z-skip-link: 999;
153
160
  --sf-duration-fast: 150ms;
154
161
  --sf-duration-normal: 220ms;
155
162
  --sf-duration-slow: 360ms;
@@ -210,6 +217,25 @@
210
217
  --sf-colour-border: oklch(100% 0 0 / 0.14);
211
218
  --sf-colour-border-strong: oklch(100% 0 0 / 0.24);
212
219
  --sf-colour-backdrop: oklch(0% 0 0 / 0.64);
220
+ --sf-colour-primary: var(--sf-colour-orange-500);
221
+ --sf-colour-primary-hover: oklch(80% 0.14 50);
222
+ --sf-colour-primary-foreground: var(--sf-colour-neutral-950);
223
+ --sf-colour-primary-soft: oklch(74% 0.17 48 / 0.18);
224
+ --sf-colour-primary-soft-border: oklch(74% 0.17 48 / 0.34);
213
225
  --sf-colour-link: var(--sf-colour-orange-500);
214
226
  --sf-colour-link-hover: oklch(80% 0.14 50);
227
+ --sf-colour-success: oklch(72% 0.13 150);
228
+ --sf-colour-success-foreground: var(--sf-colour-neutral-950);
229
+ --sf-colour-success-soft: oklch(72% 0.13 150 / 0.16);
230
+ --sf-colour-warning: oklch(84% 0.15 82);
231
+ --sf-colour-warning-foreground: var(--sf-colour-neutral-950);
232
+ --sf-colour-warning-soft: oklch(84% 0.15 82 / 0.18);
233
+ --sf-colour-danger: oklch(70% 0.18 28);
234
+ --sf-colour-danger-foreground: var(--sf-colour-neutral-950);
235
+ --sf-colour-danger-soft: oklch(70% 0.18 28 / 0.16);
236
+ --sf-colour-info: oklch(76% 0.12 205);
237
+ --sf-colour-info-foreground: var(--sf-colour-neutral-950);
238
+ --sf-colour-info-soft: oklch(76% 0.12 205 / 0.16);
239
+ --sf-colour-ring: var(--sf-colour-orange-500);
240
+ --sf-shadow-glow: 0 0 2rem oklch(74% 0.17 48 / 0.18);
215
241
  }
package/utilities.css CHANGED
@@ -145,7 +145,7 @@
145
145
  text-decoration: none;
146
146
  transform: translateY(calc(-100% - var(--sf-space-m)));
147
147
  transition: opacity var(--sf-duration-fast) var(--sf-ease-standard), transform var(--sf-duration-fast) var(--sf-ease-standard);
148
- z-index: 999;
148
+ z-index: var(--sf-z-skip-link);
149
149
  }
150
150
 
151
151
  .sf-skip-link:focus-visible {