@flyos/design-system 0.0.1-reserved → 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,231 @@
1
+ // ─── Light Theme (default) ───────────────────────────────────────────────────
2
+ :root,
3
+ html.light-theme {
4
+ color-scheme: light;
5
+
6
+
7
+
8
+ // ── FlyOS platform accent ─────────────────────────────────────────────────
9
+ // Platform-owned accent palette (violet). Theme-agnostic — same values in
10
+ // light and dark. Consumed by shell chrome (launcher tiles, documents
11
+ // editor, agent panel) and inherited by hosted apps that don't bring their
12
+ // own brand accent. App-specific token remaps live in each External App's
13
+ // own remote stylesheet (e.g. Circles' circles-shell-overrides.scss), NOT
14
+ // here.
15
+ // NOTE: --focus-ring is also platform-owned; its authoritative value is the
16
+ // orange declaration next to the window-chrome tokens further down this
17
+ // block (a later declaration in the same block always wins, so a second
18
+ // definition here would be dead code).
19
+ --purple: #9333EA;
20
+
21
+ // ── THE accent knob ────────────────────────────────────────────────────────
22
+ // The one value that defines the platform's accent. Everything else derives from it
23
+ // (--primary-color, --accent-soft, --focus-ring, the fly-context-menu gradient, …), so a tenant
24
+ // or user override is a single write: FlyThemeService.applyAccent('#0aa') re-skins the platform.
25
+ // Never copy this hex elsewhere — a copy silently stops tracking the override.
26
+ --accent: #9333EA;
27
+
28
+ // Alias of --accent, NOT a second brand colour. It was referenced ~163 times across the DS
29
+ // and shell and defined nowhere, so every `var(--primary-color)` silently shipped
30
+ // its orange fallback — that fallback WAS the platform's accent in practice. Defining it
31
+ // here turns all of those purple at once. An app may still scope its own (dashboard-app
32
+ // pins blue); a local override wins inside its subtree, as before.
33
+ --primary-color: var(--accent);
34
+
35
+ // DERIVED, never a copy. A hardcoded rgba(147,51,234,…) here would not follow a runtime
36
+ // accent override (see FlyThemeService.applyAccent) — you would get the new accent with
37
+ // the old tint beside it. Every accent-derived value must color-mix off --accent.
38
+ --accent-soft: color-mix(in srgb, var(--accent) 18%, transparent);
39
+
40
+ // Scrim — deeper veil for drawers / dialogs sitting over translucent glass
41
+ --scrim: rgb(0 0 0 / 50%);
42
+
43
+ // Semantic feedback — bright fg on translucent bg
44
+ --danger: #ff6b6b;
45
+ --danger-bg: rgb(255 59 48 / 20%);
46
+ --danger-line: rgb(255 59 48 / 40%);
47
+ --warning: #FEBC2E;
48
+ --warning-bg: rgb(254 188 46 / 18%);
49
+ --warning-fg: rgb(255 255 255 / 96%);
50
+
51
+ // Decorative accent tokens — platform-owned (consumed by the shell's
52
+ // markdown rendering, agent panel, and thread selector; also inherited by
53
+ // hosted apps for colour-dot ::before content).
54
+ --accent-green: var(--system-green);
55
+ --accent-red: var(--system-red);
56
+ --accent-blue: var(--system-blue);
57
+
58
+ // Semantic status orange (pending / warning dots) — aliases --system-orange like its
59
+ // siblings. It used to hardcode the brand orange #E8732A, which is why 'orange' and
60
+ // 'accent' were the same colour and the brand leaked into status chrome.
61
+ --accent-orange: var(--system-orange);
62
+ --accent-yellow: var(--system-yellow);
63
+ --surface-ground: #f8f9fa;
64
+
65
+ // ── Glass substrate ────────────────────────────────────────────────────────
66
+ // These were near-CLEAR (`--surface-card` was a 10% black wash over 10% white; `--glass-bg`
67
+ // 10% white), which meant light-theme text was composited straight onto the wallpaper
68
+ // photograph. "Light theme" never implied a light backdrop: 22 of the 26 shipped wallpapers
69
+ // sit below 0.15 median luminance, so the real substrate was usually near-black and the
70
+ // theme's dark secondary ink disappeared into it.
71
+
72
+ // They now carry real opacity, in line with the dark theme's long-standing 72%/55%. The
73
+ // window still reads as glass — 72% white lets the wallpaper tint through and the 50px
74
+ // backdrop blur still does its work — but text no longer sits on a bare photo.
75
+ // Contract pinned by `src/app/core/theme/theme-contrast.spec.ts`.
76
+ // `--surface-card` / `--surface-section` are a LIFT on top of the window plate, not a second
77
+ // full substrate — stacking two thick layers is what reads as frosted plastic.
78
+ --surface-section: rgb(255 255 255 / 35%);
79
+ --surface-card: rgb(255 255 255 / 20%);
80
+
81
+ // Opaque surface for floating overlays (popovers, menus, tooltips) that must
82
+ // stay fully legible above content — see the dark theme for the rationale.
83
+ --surface-overlay: #fff;
84
+ --surface-border: rgb(0 0 0 / 6%);
85
+ --surface-hover: rgb(0 0 0 / 4%);
86
+
87
+ // Selected/active row tint — one step stronger than hover. Composited over an opaque panel, so a
88
+ // translucent tint is safe (unlike the glass surfaces above it needs no reduced-transparency pair).
89
+ --surface-active: rgb(0 0 0 / 8%);
90
+
91
+ // Ink is DARK in this theme, at every level. It used to contradict itself — `--text-color`
92
+ // was white while `--text-color-secondary` was dark ink, in the same block — so primary text
93
+ // vanished on light glass and secondary text vanished on a dark wallpaper, simultaneously
94
+ // and for opposite reasons. Both now follow the `--glass-ink-elevated` model below.
95
+ --text-color: rgb(17 24 39 / 92%);
96
+ --text-color-secondary: rgb(17 24 39 / 78%);
97
+ --glass-bg: rgb(255 255 255 / 60%);
98
+ --glass-bg-elevated: rgb(255 255 255 / 88%);
99
+
100
+ // Ink for text sitting ON `--glass-bg-elevated`. This pair was already correct when the rest
101
+ // of the theme was not, so it became the model the `--label-*` / `--text-color-*` families
102
+ // were rebuilt against. It now agrees with them rather than compensating for them; the
103
+ // secondary step is 72% to match `--label-secondary` (65% missed AA on the darkest wallpaper).
104
+ --glass-ink-elevated: rgb(17 24 39 / 92%);
105
+ --glass-ink-elevated-secondary: rgb(17 24 39 / 72%);
106
+ --glass-blur: 24px;
107
+
108
+ // A luminous WHITE edge is invisible against a 72%-white plate — that treatment only worked
109
+ // while the glass was near-clear and backed by a dark photo. A light glass pane takes a
110
+ // dark hairline instead; the white specular highlight below still supplies the glass sheen.
111
+ --glass-border: rgb(17 24 39 / 12%);
112
+ --glass-shadow: 0 8px 40px rgb(0 0 0 / 8%);
113
+ --glass-inner-glow: inset 0 1px 0 rgb(255 255 255 / 50%);
114
+ --card-radius: 16px;
115
+ --card-padding: 20px;
116
+ --card-gap: 14px;
117
+
118
+ // Apps launcher card tokens — matches Figma frosted glass card spec
119
+ --launcher-card-bg: rgb(224 224 224 / 30%);
120
+ --launcher-card-border: rgb(255 255 255 / 40%);
121
+ --launcher-card-blur: 50px;
122
+ --launcher-card-radius: 16px;
123
+ --launcher-card-icon-bg: rgb(255 255 255 / 10%);
124
+ --launcher-card-icon-border: rgb(255 255 255 / 10%);
125
+ --launcher-card-icon-blur: 4px;
126
+
127
+ // The tile paints `--surface-card` inside `--window-bg`, so its ink follows the label family
128
+ // rather than keeping a private white. (`--launcher-card-bg` above has no consumers.)
129
+ --launcher-card-title: var(--label-primary);
130
+ --launcher-card-desc: var(--label-secondary);
131
+
132
+ // Window chrome — light frosted glass similar to Figma spec (soft white plate,
133
+ // strong background blur, subtle luminous border).
134
+ // The app window plate. At 6% this was the single biggest cause of the reported failure:
135
+ // every app's body text was effectively painted on the wallpaper. Raised to match `--glass-bg`.
136
+ --window-bg: rgb(255 255 255 / 60%);
137
+ --window-radius: 24px;
138
+ --window-blur: 24px;
139
+ --window-backdrop-saturate: 175%;
140
+ --window-shadow: 0 28px 96px rgb(0 0 0 / 18%);
141
+ --window-border: rgb(17 24 39 / 10%);
142
+ --window-specular: inset 0 1px 0 rgb(255 255 255 / 30%),
143
+ inset 0 -1px 0 rgb(255 255 255 / 16%);
144
+ --window-content-scrim: transparent;
145
+ --app-content-plate: transparent;
146
+ --titlebar-bg: transparent;
147
+ --titlebar-height: 44px;
148
+ --titlebar-padding: 0 14px;
149
+
150
+ // Backs BOTH the dock and the top Finder bar (`.topbar-glass`), which is why it needs a real
151
+ // substrate: at 15% the bar's labels and icons sat on the wallpaper like everything else.
152
+ --dock-bg: rgb(255 255 255 / 60%);
153
+ --dock-border: rgb(17 24 39 / 12%);
154
+ --dock-blur:50px;
155
+ --menubar-bg: rgb(255 255 255 / 60%);
156
+ --menubar-border: rgb(17 24 39 / 10%);
157
+ --menubar-text: var(--label-primary);
158
+ --menubar-blur: 40px;
159
+ --menubar-radius: 24px;
160
+ --sidebar-bg: rgb(255 255 255 / 60%);
161
+ --sidebar-border: rgb(17 24 39 / 10%);
162
+ --sidebar-width: 60px;
163
+ --sidebar-icon-size: 36px;
164
+ --sidebar-radius: 28px;
165
+ --focus-ring: color-mix(in srgb, var(--accent) 50%, transparent);
166
+
167
+ // Segmented `.vos-btn.selected` / `.active` (Settings theme row, clock, weather, etc.): dark pill on light UI.
168
+ --btn-selected-bg: #111827;
169
+ --btn-selected-text: #fff;
170
+
171
+ // Coherently dark ink, stepping down 92 / 72 / 55. The steps are not free choices: each is
172
+ // the lowest alpha that still clears its WCAG target (4.5 body, 3 tertiary) once composited
173
+ // over the 62-72% white substrate on the DARKEST shipped wallpaper. Lowering any of them
174
+ // re-breaks the theme on `starfield`/`moon`; `theme-contrast.spec.ts` will say so.
175
+ --label-primary: rgb(17 24 39 / 92%);
176
+ --label-secondary: rgb(17 24 39 / 78%);
177
+ --label-tertiary: rgb(17 24 39 / 60%);
178
+ --separator-primary: rgb(0 0 0 / 10%);
179
+ --separator: var(--separator-primary);
180
+ --fill-secondary: #e5e7eb;
181
+ --fill-tertiary: rgb(0 0 0 / 4%);
182
+
183
+ // ── Material glass primitives — light counterparts of the dark theme's set. Only
184
+ // `--material-glass` existed here (and it was opaque `#fff`, i.e. not glass at all); the
185
+ // blur/stroke/specular siblings were dark-only, so any consumer of them rendered unstyled
186
+ // in light mode.
187
+ --material-glass: rgb(255 255 255 / 60%);
188
+ --material-glass-blur: 40px;
189
+ --material-glass-stroke: rgb(17 24 39 / 12%);
190
+ --material-glass-specular: inset 0 1px 0 rgb(255 255 255 / 60%),
191
+ inset 0 -1px 0 rgb(17 24 39 / 4%);
192
+
193
+ // Aliases used by some Business App SCSS (not part of core visionOS tokens).
194
+ --fly-color-surface: #fff;
195
+ --fly-color-surface-alt: #f3f4f6;
196
+ --fly-color-border: #e5e7eb;
197
+ --fly-color-text-muted: rgb(17 24 39 / 55%);
198
+ --fly-color-primary: var(--primary-color);
199
+ --fly-color-primary-hover: var(--primary-hover);
200
+ --fly-color-danger: var(--system-red);
201
+ --fly-shadow-md: 0 4px 12px rgb(0 0 0 / 8%);
202
+ }
203
+
204
+ // ── Reduced-transparency fallback — restore fully opaque / zero-blur values ──
205
+ // The light theme had no such block while its glass was near-clear, because there was
206
+ // nothing meaningful to make opaque. Now that the substrate is real, it needs the same
207
+ // treatment as the dark theme or `prefers-reduced-transparency` users keep the blur.
208
+ @media (prefers-reduced-transparency: reduce) {
209
+ :root,
210
+ html.light-theme {
211
+ --material-glass: #fff;
212
+ --material-glass-blur: 0px;
213
+ --app-content-plate: #f4f5f7;
214
+ --surface-section: #fff;
215
+ --surface-card: #fff;
216
+ --surface-overlay: #fff;
217
+ --glass-bg: #f7f8fa;
218
+ --glass-bg-elevated: #fff;
219
+ --glass-blur: 0px;
220
+ --window-bg: #f7f8fa;
221
+ --window-blur: 0px;
222
+ --window-backdrop-saturate: 100%;
223
+ --dock-bg: #f4f5f7;
224
+ --dock-blur: 0px;
225
+ --menubar-bg: #f7f8fa;
226
+ --menubar-blur: 0px;
227
+ --sidebar-bg: #f4f5f7;
228
+ --launcher-card-bg: #fff;
229
+ --launcher-card-blur: 0px;
230
+ }
231
+ }
@@ -0,0 +1,119 @@
1
+ // ─── visionOS System Colors & Design Tokens ─────────────────────────────────
2
+ :root {
3
+ --system-red: #FF453A;
4
+ --system-orange: #FF9F0A;
5
+ --system-yellow: #FFD60A;
6
+ --system-green: #32D74B;
7
+ --system-mint: #66D4CF;
8
+ --system-teal: #6AC4DC;
9
+ --system-cyan: #5AC8F5;
10
+ --system-blue: #0A84FF;
11
+ --system-indigo: #5E5CE6;
12
+ --system-purple: #BF5AF2;
13
+ --system-pink: #FF375F;
14
+ --system-brown: #AC8E68;
15
+ --system-gray: #98989D;
16
+
17
+ // ── Semantic Status Colors ──
18
+ --status-success: var(--system-green);
19
+ --status-warning: var(--system-orange);
20
+ --status-error: var(--system-red);
21
+ --status-info: var(--system-blue);
22
+ --status-pending: var(--system-yellow);
23
+
24
+ // ── visionOS Typography ──
25
+ // Geist is the primary face (self-hosted, see styles/_geist-fonts.scss).
26
+ // SF Pro / Inter / system fonts remain as fallbacks; the cascade also picks
27
+ // them up for scripts Geist doesn't cover (ar / ur).
28
+ --font-family: 'Geist', 'SF Pro Display', 'SF Pro', 'Inter', -apple-system, blinkmacsystemfont, 'Segoe UI', sans-serif;
29
+ --font-family-mono: 'Geist Mono', ui-monospace, 'SF Mono', menlo, monospace;
30
+ --font-xl-title1: 700 48px/56px var(--font-family);
31
+ --font-xl-title2: 700 38px/46px var(--font-family);
32
+ --font-large-title: 700 29px/38px var(--font-family);
33
+ --font-title1: 700 24px/32px var(--font-family);
34
+ --font-title2: 700 22px/28px var(--font-family);
35
+ --font-title3: 700 19px/24px var(--font-family);
36
+ --font-headline: 700 17px/22px var(--font-family);
37
+ --font-body: 510 17px/22px var(--font-family);
38
+ --font-callout: 590 15px/20px var(--font-family);
39
+ --font-subheadline: 400 15px/20px var(--font-family);
40
+ --font-footnote: 510 13px/18px var(--font-family);
41
+ --font-caption1: 510 12px/16px var(--font-family);
42
+ --font-caption2: 510 12px/16px var(--font-family);
43
+
44
+ // ── visionOS Label Colors ──
45
+ --label-primary: rgb(255 255 255 / 96%);
46
+ --label-secondary: rgb(255 255 255 / 56%);
47
+ --label-tertiary: rgb(255 255 255 / 36%);
48
+
49
+ // ── visionOS Materials ──
50
+ --material-glass: rgb(128 128 128 / 30%);
51
+ --material-glass-blur: 50px;
52
+ --material-glass-stroke: rgb(255 255 255 / 40%);
53
+ --material-glass-specular: inset 0px -0.5px 1px rgb(255 255 255 / 30%),
54
+ inset 0px -0.5px 1px rgb(255 255 255 / 25%),
55
+ inset 1px 1.5px 4px rgb(0 0 0 / 8%),
56
+ inset 1px 1.5px 4px rgb(0 0 0 / 10%);
57
+ --material-recessed-bg: linear-gradient(rgb(208 208 208 / 50%), rgb(208 208 208 / 50%)),
58
+ linear-gradient(rgb(0 0 0 / 10%), rgb(0 0 0 / 10%));
59
+ --material-recessed-shadow: inset 1px 1.5px 4px rgb(0 0 0 / 10%),
60
+ inset 1px 1.5px 4px rgb(0 0 0 / 8%),
61
+ inset 0px -0.5px 1px rgb(255 255 255 / 25%),
62
+ inset 0px -0.5px 1px rgb(255 255 255 / 30%);
63
+ --material-thin: rgb(255 255 255 / 6%);
64
+ --material-regular: rgb(255 255 255 / 12%);
65
+ --material-thick: rgb(255 255 255 / 20%);
66
+ --control-idle: rgb(255 255 255 / 6%);
67
+ --control-hover: rgb(255 255 255 / 12%);
68
+ --control-selected: rgb(255 255 255 / 100%);
69
+ --control-disabled: rgb(255 255 255 / 4%);
70
+ --separator: rgb(255 255 255 / 12%);
71
+ --blur-shadow-small: 0 2px 4px rgb(0 0 0 / 10%);
72
+
73
+ // ── visionOS Button Tokens ──
74
+ --btn-font-weight: 590;
75
+ --btn-symbol-font-weight: 510;
76
+ --btn-radius-capsule: 500px;
77
+ --btn-radius-rect-lg: 16px;
78
+ --btn-radius-rect-sm: 8px;
79
+ --btn-sm-height: 32px;
80
+ --btn-sm-padding: 0 12px;
81
+ --btn-sm-font-size: 15px;
82
+ --btn-sm-line-height: 20px;
83
+ --btn-sm-symbol-size: 17px;
84
+ --btn-sm-gap: 2px;
85
+ --btn-reg-height: 44px;
86
+ --btn-reg-padding: 0 20px;
87
+ --btn-reg-font-size: 17px;
88
+ --btn-reg-line-height: 22px;
89
+ --btn-reg-symbol-size: 19px;
90
+ --btn-reg-gap: 6px;
91
+ --btn-lg-height: 52px;
92
+ --btn-lg-padding: 0 25px;
93
+ --btn-lg-font-size: 19px;
94
+ --btn-lg-line-height: 24px;
95
+ --btn-lg-symbol-size: 22px;
96
+ --btn-lg-gap: 6px;
97
+ --btn-symbol-mini: 28px;
98
+ --btn-symbol-mini-font: 13px;
99
+ --btn-symbol-sm: 36px;
100
+ --btn-symbol-sm-font: 15px;
101
+ --btn-symbol-reg: 44px;
102
+ --btn-symbol-reg-font: 19px;
103
+ --btn-symbol-lg: 52px;
104
+ --btn-symbol-lg-font: 22px;
105
+ --btn-symbol-xl: 60px;
106
+ --btn-symbol-xl-font: 26px;
107
+ --btn-platter-lighten: rgb(255 255 255 / 6%);
108
+ --btn-platter-dodge: rgb(94 94 94 / 18%);
109
+ --btn-hover-grad-white: rgb(255 255 255 / 7%);
110
+ --btn-hover-grad-gray: rgb(94 94 94 / 14%);
111
+ --btn-disabled-lighten: rgb(255 255 255 / 4%);
112
+ --btn-disabled-dodge: rgb(94 94 94 / 7%);
113
+ --btn-disabled-text: rgb(112 112 112 / 50%);
114
+ --btn-selected-bg: rgb(255 255 255 / 96%);
115
+ --btn-selected-text: #000;
116
+ --link-color: #3CD3FE;
117
+ --link-height: 26px;
118
+ --link-font-size: 13px;
119
+ }
@@ -0,0 +1,28 @@
1
+ // visionOS button pseudo-element layers (used by _business-app-buttons.scss).
2
+ // Kept separate from desktop-app glass mixins so Business Apps only pull button-related SCSS.
3
+
4
+ @mixin vos-platter-layers($radius) {
5
+ content: '';
6
+ position: absolute;
7
+ inset: 0;
8
+ border-radius: $radius;
9
+ pointer-events: none;
10
+ background:
11
+ linear-gradient(var(--btn-platter-lighten), var(--btn-platter-lighten)),
12
+ linear-gradient(var(--btn-platter-dodge), var(--btn-platter-dodge));
13
+ background-blend-mode: lighten, color-dodge;
14
+ mix-blend-mode: screen;
15
+ }
16
+
17
+ @mixin vos-disabled-layers($radius) {
18
+ content: '';
19
+ position: absolute;
20
+ inset: 0;
21
+ border-radius: $radius;
22
+ pointer-events: none;
23
+ background:
24
+ linear-gradient(var(--btn-disabled-lighten), var(--btn-disabled-lighten)),
25
+ linear-gradient(var(--btn-disabled-dodge), var(--btn-disabled-dodge));
26
+ background-blend-mode: lighten, color-dodge;
27
+ mix-blend-mode: screen;
28
+ }