@putdotio/design 1.3.0 → 1.4.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/system/README.md CHANGED
@@ -18,8 +18,18 @@ project root/
18
18
 
19
19
  ## Fonts
20
20
 
21
- Preview pages load the public put.io font CSS from `static.put.io`: GT America,
22
- GT America Mono, and Berkeley Mono. Do not commit font files here.
21
+ Preview pages load the public put.io font CSS from `static.put.io` (the same
22
+ source as the product), so the design system always matches production. Do not
23
+ commit font files here. Each HTML file links three stylesheets in `<head>`:
24
+
25
+ ```html
26
+ <link rel="stylesheet" href="https://static.put.io/fonts/gt-america/standard/font.css">
27
+ <link rel="stylesheet" href="https://static.put.io/fonts/gt-america/mono/font.css">
28
+ <link rel="stylesheet" href="https://static.put.io/fonts/berkeley-mono/variable/font.css">
29
+ ```
30
+
31
+ Canonical weight mapping (matches the brand font host):
32
+ `100 ultra-light · 200 thin · 300 light · 400 regular · 500 medium · 700 bold · 900 black`
23
33
 
24
34
  ## Using tokens
25
35
 
@@ -33,10 +43,17 @@ The canonical source is DTCG-compatible JSON in [`../tokens`](../tokens). This
33
43
  site stylesheet (`system/tokens.css`) and the package stylesheet
34
44
  (`dist/css/tokens.css`, exported as `@putdotio/design/css`) are generated from
35
45
  the same source. Guide and component CSS should consume custom properties rather
36
- than hard-coded palette values. Brand yellow is emitted as
37
- `var(--yellow-solid)`; its CSS token value is `hsl(44.7, 97.9%, 63.1%)`, the
38
- hsl form of canonical `#FDCE45`. Primary hover feedback uses
39
- `--yellow-solid-hover`, exposed to consumers as `--button-primary-bg-hover`.
46
+ than hard-coded palette values. Brand yellow is `var(--yellow-solid)` —
47
+ canonical `#FDCE45`; the emitted hsl form is pinned in
48
+ [`../DESIGN.md`](../DESIGN.md) front-matter, and the `--yellow-solid-hover` →
49
+ `--button-primary-bg-hover` derivation is specified in the repo's
50
+ `docs/DISTRIBUTION.md`.
51
+
52
+ Stacking and breakpoints are tokenized (`--z-*`, `--bp-*`) and the root
53
+ font-size is responsive; the canonical values live in
54
+ [`../DESIGN.md`](../DESIGN.md) (Layout & Spacing, Typography). Guide-specific
55
+ rule: CSS media queries can't read custom properties, so write the literal px
56
+ in `@media` and keep it in sync with the `--bp-*` token.
40
57
 
41
58
  Web package consumers import the package CSS export:
42
59
 
@@ -44,7 +61,7 @@ Web package consumers import the package CSS export:
44
61
  @import "@putdotio/design/css";
45
62
  ```
46
63
 
47
- For **TV preview cards**, also load `preview/tv-shell.css` — it adds the `.tv`, `.topnav`, `.scr`, glass tiers, and player chrome on top of the tokens. This is preview-only support CSS; platform repos implement TV components in their native UI stacks:
64
+ For **TV preview cards**, also load `preview/tv-shell.css` — it adds the `.tv`, `.topnav`, `.scr`, glass tiers, and player chrome on top of the tokens. Every component selector is scoped under `.tv`, so the file is safe to bundle globally without bleeding into web components. This is preview-only support CSS; platform repos implement TV components in their native UI stacks:
48
65
 
49
66
  ```html
50
67
  <link rel="stylesheet" href="./tokens.css">
@@ -53,24 +70,81 @@ For **TV preview cards**, also load `preview/tv-shell.css` — it adds the `.tv`
53
70
 
54
71
  ## Core rules
55
72
 
56
- - **Yellow `#FDCE45` is the brand fill in both modes.** Use it for primary CTAs, folder icons, button/nav/TV focus rings (at 35% alpha), and progress bars. Use `--yellow-solid-hover` / `--button-primary-bg-hover` for CTA hover feedback, `--primary-foreground` for labels on yellow, and `--yellow-text-secondary` for yellow text on light backgrounds.
73
+ - **Yellow `#FDCE45` is the brand constant at rest** — full rule and approved uses in [`../DESIGN.md`](../DESIGN.md) (Colors). Guide specifics: `--yellow-solid-hover` (`#F3C435`) is the hover peer with its own canonical hex in both modes, and focus rings use the yellow at 35% alpha (`--shadow-focus-color`).
74
+ - **Yellow as text on light needs `--yellow-text-secondary`** (≈5:1, AA) — the brand `--yellow-solid` is fill-only on light backgrounds.
75
+ - **Labels on yellow** use `--primary-foreground` (`hsl(38, 65%, 10%)` — warm dark, never pure black). Passes AA on the yellow fill without feeling "hard."
57
76
  - **Icons: Phosphor-style inline SVG.** No emoji, ever.
58
- - **One design, two modes.** Light and dark are the same markup and components with different token values. Toggle `.dark` on `<html>`; do not fork the page or rebuild a light-specific copy.
59
- - **Fields stay quiet.** Use `--field-bg`, `--field-border`, and `--field-ring` for text entry. Invalid fields use `aria-invalid="true"` with red border/text only, never a red fill.
60
- - **Panels are shared.** Use `--panel-bg`, `--panel-border`, `--panel-radius`, and `--panel-shadow` for raised cards and auth-style shells instead of screen-specific variables.
77
+ - **One design, two modes.** Light and dark are the same markup and components with different token values. Toggle `.dark` on `<html>`; do not fork the page or rebuild a light-specific copy. Components must consume semantic tokens (`--bg`, `--text`, `--border`, `--accent`, …), not raw `#hex` or `hsl()`.
78
+ - **Fields and panels use the shared aliases** (`--field-*`, `--panel-*`) — full rules, including the `aria-invalid` red-border-only requirement, in [`../DESIGN.md`](../DESIGN.md) (Components).
61
79
  - **Content-agnostic.** put.io doesn't know what the user's files are. Never parse `The.Wire.S03E04.1080p.mkv` into `The Wire`. Raw filenames only. See the root [`DESIGN.md`](../DESIGN.md) for the full principle.
62
80
 
63
81
  ## Theme System
64
82
 
65
- The guide owns the theme toggle. It stores `putio-ds-theme` in `localStorage`,
66
- updates `html.dark`, and broadcasts the current mode to embedded preview iframes.
67
- Standalone preview pages read the same storage key before paint. A URL query
68
- (`?theme=light` or `?theme=dark`) can override the preview mode for screenshots.
83
+ The guide (`design-system.html`) owns the theme toggle. It writes
84
+ `putio-ds-theme` to `localStorage`, updates `html.dark`, and broadcasts
85
+ `{type:'__theme', theme}` to every embedded preview iframe via `postMessage`,
86
+ so embeds flip live without reloading. Each preview's inline bootstrap reads
87
+ the same storage key on standalone open, and `preview/_resize.js` listens for
88
+ the parent broadcast when embedded. A URL query (`?theme=light` or
89
+ `?theme=dark`) overrides both — useful for screenshots.
69
90
 
70
91
  Fixed-mode previews opt out with `<html data-theme-lock="dark">`. This is only
71
- for product mockups whose visual language is intrinsically one mode, such as TV
72
- and mobile shell specimens. Component previews should stay token-driven and work
73
- in both modes.
92
+ for product mockups whose visual language is intrinsically one mode — TV's
93
+ translucent glass material and on-video player chrome can't render on a light
94
+ surface, so `tv-*.html`, `mobile-shell.html`, and `components-player-web.html`
95
+ are locked. Locked previews ignore both `localStorage` and parent broadcasts.
96
+ If you write a new component preview, you almost certainly don't want the
97
+ lock — let the tokens do the work and your specimen will render correctly in
98
+ both modes.
99
+
100
+ ## shadcn / Base UI interop
101
+
102
+ The token layer ships a name-alias bridge so external component libraries that
103
+ read canonical shadcn token names theme correctly without renaming. Drop in a
104
+ shadcn/ui block, install a Base UI component, paste a Tailwind preset — they
105
+ resolve against our values via the aliases. Always alias, never duplicate, so
106
+ the two name systems can't drift.
107
+
108
+ | shadcn name | put.io target |
109
+ | --- | --- |
110
+ | `--primary` / `--primary-foreground` | `--yellow-solid` / `var(--primary-foreground)` (warm dark) |
111
+ | `--destructive` / `--destructive-foreground` | `--red-solid` / `var(--destructive-foreground)` (= `#fff`) |
112
+ | `--success` / `--success-foreground` | `--green-solid` / `var(--success-foreground)` (= `#fff`) |
113
+ | `--muted` / `--muted-foreground` | `--bg-secondary` / `--text-secondary` |
114
+ | `--accent` / `--accent-foreground` | `--component-bg` / `--text` |
115
+ | `--card` / `--card-foreground` | `--component-bg` / `--text` |
116
+ | `--popover` / `--popover-foreground` | `--component-bg` / `--text` |
117
+ | `--input` | `--border` |
118
+ | `--ring` | `--shadow-focus-color` |
119
+ | `--background` / `--foreground` | `--bg` / `--text` |
120
+
121
+ The foreground tokens (`--primary-foreground`, `--destructive-foreground`,
122
+ `--success-foreground`) encode the mode-safe inverse pair — always read these
123
+ instead of writing literal `#000` / `#fff` on a solid surface.
124
+
125
+ Use whichever name reads cleaner in context. Our own components prefer the long
126
+ descriptive names (`--component-bg-hover`, `--yellow-text-secondary`) because
127
+ they describe the role exactly. shadcn-imported code prefers the short names.
128
+
129
+ ### State via `data-state`, not class flags
130
+
131
+ Base UI / headless primitives set
132
+ `data-state="open|closed|checked|unchecked|active|completed|pending|loading"`
133
+ on the DOM. Our components target those same attribute values in CSS — see the
134
+ wizard step bar in `components-form-layouts.html`
135
+ (`.step[data-state="completed"]`) and the menu/table cards. Prefer `data-state`
136
+ over inventing class flags (`.is-active`, `.on`, `.current`) so the same DOM
137
+ contract works whether the controlling code is React, Vue, vanilla JS, or
138
+ hand-written HTML, and so devtools can read the component's state at a glance.
139
+
140
+ ### Compound parts via `data-slot`
141
+
142
+ shadcn marks parts of compound components with `data-slot="card-header"`,
143
+ `data-slot="card-title"`, etc. We do the same on the folder picker
144
+ (`data-slot="modal" / "modal-header" / "modal-body" / "modal-footer"`) and the
145
+ auth card in `components-form-layouts.html` (`data-slot="auth" / "auth-header"
146
+ / "auth-body"`). This lets external CSS tweak one part without inventing
147
+ nested class chains.
74
148
 
75
149
  ## Design variants
76
150
 
@@ -85,4 +159,4 @@ Four documented type stacks — pick one per surface:
85
159
 
86
160
  ## Preview cards
87
161
 
88
- Open `system/design-system.html` for the full index. Each card renders a single concept against the actual tokens; treat it as the visual spec.
162
+ Open `system/design-system.html` for the full index. Each card renders a single concept against the actual tokens — read it like a spec.
@@ -215,6 +215,28 @@
215
215
  }
216
216
  },
217
217
  "info": {
218
+ "background": {
219
+ "$type": "color",
220
+ "$value": "{color.neutral.light.solid}",
221
+ "$description": "Neutral solid command background in light mode.",
222
+ "$extensions": {
223
+ "putio": {
224
+ "cssName": "button-info-bg",
225
+ "mode": "light"
226
+ }
227
+ }
228
+ },
229
+ "backgroundDark": {
230
+ "$type": "color",
231
+ "$value": "{color.neutral.dark.solid}",
232
+ "$description": "Neutral solid command background in dark mode.",
233
+ "$extensions": {
234
+ "putio": {
235
+ "cssName": "button-info-bg",
236
+ "mode": "dark"
237
+ }
238
+ }
239
+ },
218
240
  "backgroundHover": {
219
241
  "$type": "color",
220
242
  "$value": "{color.neutral.light.solidHover}",
@@ -236,6 +258,96 @@
236
258
  "mode": "dark"
237
259
  }
238
260
  }
261
+ },
262
+ "foreground": {
263
+ "$type": "color",
264
+ "$value": "{component.alias.solidForeground}",
265
+ "$description": "Label on the neutral solid — mode-aware for AA contrast on the gray fill.",
266
+ "$extensions": {
267
+ "putio": {
268
+ "cssName": "button-info-fg",
269
+ "mode": "light"
270
+ }
271
+ }
272
+ },
273
+ "foregroundDark": {
274
+ "$type": "color",
275
+ "$value": "{component.alias.solidForegroundDark}",
276
+ "$description": "Label on the neutral solid in dark mode.",
277
+ "$extensions": {
278
+ "putio": {
279
+ "cssName": "button-info-fg",
280
+ "mode": "dark"
281
+ }
282
+ }
283
+ }
284
+ },
285
+ "default": {
286
+ "background": {
287
+ "$type": "color",
288
+ "$value": "{color.neutral.light.componentBg}",
289
+ "$description": "Quiet default button fill in light mode.",
290
+ "$extensions": {
291
+ "putio": {
292
+ "cssName": "button-default-bg",
293
+ "mode": "light"
294
+ }
295
+ }
296
+ },
297
+ "backgroundDark": {
298
+ "$type": "color",
299
+ "$value": "{color.neutral.dark.componentBg}",
300
+ "$description": "Quiet default button fill in dark mode.",
301
+ "$extensions": {
302
+ "putio": {
303
+ "cssName": "button-default-bg",
304
+ "mode": "dark"
305
+ }
306
+ }
307
+ },
308
+ "backgroundHover": {
309
+ "$type": "color",
310
+ "$value": "{color.neutral.light.componentBgHover}",
311
+ "$description": "Default button hover fill in light mode.",
312
+ "$extensions": {
313
+ "putio": {
314
+ "cssName": "button-default-bg-hover",
315
+ "mode": "light"
316
+ }
317
+ }
318
+ },
319
+ "backgroundHoverDark": {
320
+ "$type": "color",
321
+ "$value": "{color.neutral.dark.componentBgHover}",
322
+ "$description": "Default button hover fill in dark mode.",
323
+ "$extensions": {
324
+ "putio": {
325
+ "cssName": "button-default-bg-hover",
326
+ "mode": "dark"
327
+ }
328
+ }
329
+ },
330
+ "foreground": {
331
+ "$type": "color",
332
+ "$value": "{color.neutral.light.text}",
333
+ "$description": "Default button label in light mode.",
334
+ "$extensions": {
335
+ "putio": {
336
+ "cssName": "button-default-fg",
337
+ "mode": "light"
338
+ }
339
+ }
340
+ },
341
+ "foregroundDark": {
342
+ "$type": "color",
343
+ "$value": "{color.neutral.dark.text}",
344
+ "$description": "Default button label in dark mode.",
345
+ "$extensions": {
346
+ "putio": {
347
+ "cssName": "button-default-fg",
348
+ "mode": "dark"
349
+ }
350
+ }
239
351
  }
240
352
  }
241
353
  },
@@ -3,7 +3,7 @@ html {
3
3
  background: var(--html-bg);
4
4
  color: var(--text);
5
5
  font-family: var(--font-sans);
6
- font-size: 15px; /* 14–15 responsive base, per app convention */
6
+ font-size: 14px; /* app.put.io root: fontSize ["14px","14px","15px"] — 15px at ≥ --bp-lg (media query below) */
7
7
  line-height: var(--lh-normal);
8
8
  -webkit-font-smoothing: antialiased;
9
9
  -moz-osx-font-smoothing: grayscale;
@@ -15,6 +15,13 @@ body {
15
15
  margin: 0;
16
16
  }
17
17
 
18
+ /* Root steps up on desktop, matching app.put.io's responsive base.
19
+ 14px/15px literals must stay in sync with --bp-lg (media queries
20
+ can't read custom properties). */
21
+ @media (min-width: 1280px) {
22
+ html { font-size: 15px; }
23
+ }
24
+
18
25
  /* -- Semantic type ------------------------------------------------- */
19
26
 
20
27
  .h-display, h1.display {
@@ -36,7 +43,7 @@ body {
36
43
 
37
44
  h1, .h1 {
38
45
  font-family: var(--font-sans);
39
- font-size: var(--fs-3xl);
46
+ font-size: var(--fs-xl);
40
47
  font-weight: var(--fw-bold);
41
48
  line-height: var(--lh-tight);
42
49
  letter-spacing: var(--tracking-tight);
@@ -45,7 +52,7 @@ h1, .h1 {
45
52
 
46
53
  h2, .h2 {
47
54
  font-family: var(--font-sans);
48
- font-size: var(--fs-2xl);
55
+ font-size: var(--fs-lg);
49
56
  font-weight: var(--fw-bold);
50
57
  line-height: var(--lh-tight);
51
58
  margin: 0 0 var(--space-3);
@@ -53,7 +60,7 @@ h2, .h2 {
53
60
 
54
61
  h3, .h3 {
55
62
  font-family: var(--font-sans);
56
- font-size: var(--fs-xl);
63
+ font-size: var(--fs-md);
57
64
  font-weight: var(--fw-medium);
58
65
  line-height: var(--lh-snug);
59
66
  margin: 0 0 var(--space-2);
@@ -61,7 +68,7 @@ h3, .h3 {
61
68
 
62
69
  h4, .h4 {
63
70
  font-family: var(--font-sans);
64
- font-size: var(--fs-lg);
71
+ font-size: var(--fs-base);
65
72
  font-weight: var(--fw-medium);
66
73
  line-height: var(--lh-snug);
67
74
  margin: 0 0 var(--space-2);
@@ -82,26 +89,26 @@ p, .body {
82
89
  }
83
90
 
84
91
  .lead {
85
- font-size: var(--fs-lg);
92
+ font-size: var(--fs-md);
86
93
  font-weight: var(--fw-regular);
87
94
  line-height: var(--lh-normal);
88
95
  color: var(--text-secondary);
89
96
  }
90
97
 
91
98
  small, .caption {
92
- font-size: var(--fs-xs);
99
+ font-size: var(--fs-sm); /* production caption = fontSize 0 */
93
100
  color: var(--text-secondary);
94
101
  }
95
102
 
96
103
  .label {
97
- font-size: var(--fs-sm);
104
+ font-size: var(--fs-base); /* production label = fontSize 1, medium */
98
105
  font-weight: var(--fw-medium);
99
106
  color: var(--text);
100
107
  }
101
108
 
102
109
  .button-text {
103
110
  font-weight: var(--fw-medium);
104
- font-size: var(--fs-base);
111
+ font-size: var(--fs-sm); /* production button = fontSize 0 */
105
112
  letter-spacing: 0;
106
113
  }
107
114
 
@@ -120,16 +127,6 @@ a {
120
127
  }
121
128
  a:hover { text-decoration-color: currentColor; }
122
129
 
123
- /* -- Component-role aliases --------------------------------------- */
124
- /* Button default + info variants — live aliases; the DTCG layer doesn't define these two. */
125
- :root {
126
- --button-default-bg: var(--component-bg);
127
- --button-default-bg-hover: var(--component-bg-hover);
128
- --button-default-fg: var(--text);
129
- --button-info-bg: var(--solid);
130
- --button-info-fg: var(--solid-foreground);
131
- }
132
-
133
130
  /* -- Utility classes ---------------------------------------------- */
134
131
  .fg-1 { color: var(--text); }
135
132
  .fg-2 { color: var(--text-secondary); }
@@ -141,3 +138,16 @@ a:hover { text-decoration-color: currentColor; }
141
138
  .bg-2 { background: var(--bg-secondary); }
142
139
  .bg-component { background: var(--component-bg); }
143
140
  .bg-yellow { background: var(--yellow-solid); color: var(--primary-foreground); }
141
+
142
+ /* -- Reduced motion ------------------------------------------------ */
143
+ /* Honor the OS "reduce motion" setting: collapse transitions/animations
144
+ to near-instant and stop looping/auto-scrolling effects. Components
145
+ should not rely on motion to convey state. */
146
+ @media (prefers-reduced-motion: reduce) {
147
+ *, *::before, *::after {
148
+ animation-duration: 0.01ms !important;
149
+ animation-iteration-count: 1 !important;
150
+ transition-duration: 0.01ms !important;
151
+ scroll-behavior: auto !important;
152
+ }
153
+ }
@@ -30,7 +30,8 @@
30
30
  },
31
31
  "color": {
32
32
  "$type": "color",
33
- "$value": "hsl(0, 0%, 78.0%)",
33
+ "$value": "{elevation.shadowColor}",
34
+ "$description": "Compat name kept for existing web consumers — alias of elevation.shadowColor so the two can never drift.",
34
35
  "$extensions": {
35
36
  "putio": {
36
37
  "cssName": "shadow",
@@ -110,7 +111,7 @@
110
111
  },
111
112
  "display": {
112
113
  "$type": "fontFamily",
113
- "$value": "\"GT America\", sans-serif",
114
+ "$value": "{typography.fontFamily.sans}",
114
115
  "$extensions": {
115
116
  "putio": {
116
117
  "cssName": "font-display",
@@ -132,7 +133,7 @@
132
133
  },
133
134
  "mono": {
134
135
  "$type": "fontFamily",
135
- "$value": "\"Berkeley Mono\", \"GT America Mono\", monospace",
136
+ "$value": "\"Berkeley Mono\", {typography.fontFamily.uiMono}",
136
137
  "$extensions": {
137
138
  "putio": {
138
139
  "cssName": "font-mono",
@@ -156,7 +157,8 @@
156
157
  },
157
158
  "sm": {
158
159
  "$type": "dimension",
159
- "$value": "0.8125rem",
160
+ "$value": "0.875rem",
161
+ "$description": "Caption and button labels — production fontSize 0.",
160
162
  "$extensions": {
161
163
  "putio": {
162
164
  "cssName": "fs-sm",
@@ -167,7 +169,8 @@
167
169
  },
168
170
  "base": {
169
171
  "$type": "dimension",
170
- "$value": "0.875rem",
172
+ "$value": "1rem",
173
+ "$description": "Body, labels, inputs — production fontSize 1; equals the responsive root (14px, 15px at >= breakpoint.lg).",
171
174
  "$extensions": {
172
175
  "putio": {
173
176
  "cssName": "fs-base",
@@ -178,7 +181,8 @@
178
181
  },
179
182
  "md": {
180
183
  "$type": "dimension",
181
- "$value": "1rem",
184
+ "$value": "1.125rem",
185
+ "$description": "Subheading.",
182
186
  "$extensions": {
183
187
  "putio": {
184
188
  "cssName": "fs-md",
@@ -189,7 +193,8 @@
189
193
  },
190
194
  "lg": {
191
195
  "$type": "dimension",
192
- "$value": "1.125rem",
196
+ "$value": "1.5rem",
197
+ "$description": "Heading.",
193
198
  "$extensions": {
194
199
  "putio": {
195
200
  "cssName": "fs-lg",
@@ -200,7 +205,8 @@
200
205
  },
201
206
  "xl": {
202
207
  "$type": "dimension",
203
- "$value": "1.5rem",
208
+ "$value": "2rem",
209
+ "$description": "Page title.",
204
210
  "$extensions": {
205
211
  "putio": {
206
212
  "cssName": "fs-xl",
@@ -211,7 +217,8 @@
211
217
  },
212
218
  "2xl": {
213
219
  "$type": "dimension",
214
- "$value": "2rem",
220
+ "$value": "48px",
221
+ "$description": "Fixed display tier — does not scale with the responsive root.",
215
222
  "$extensions": {
216
223
  "putio": {
217
224
  "cssName": "fs-2xl",
@@ -222,7 +229,8 @@
222
229
  },
223
230
  "3xl": {
224
231
  "$type": "dimension",
225
- "$value": "3rem",
232
+ "$value": "64px",
233
+ "$description": "Fixed display tier — does not scale with the responsive root.",
226
234
  "$extensions": {
227
235
  "putio": {
228
236
  "cssName": "fs-3xl",
@@ -233,7 +241,8 @@
233
241
  },
234
242
  "4xl": {
235
243
  "$type": "dimension",
236
- "$value": "4rem",
244
+ "$value": "{typography.fontSize.3xl}",
245
+ "$description": "Compatibility alias for the former 4xl tier; new surfaces should use fontSize.3xl or fontSize.display.",
237
246
  "$extensions": {
238
247
  "putio": {
239
248
  "cssName": "fs-4xl",
@@ -244,7 +253,8 @@
244
253
  },
245
254
  "display": {
246
255
  "$type": "dimension",
247
- "$value": "6rem",
256
+ "$value": "96px",
257
+ "$description": "Fixed display tier for brand display moments.",
248
258
  "$extensions": {
249
259
  "putio": {
250
260
  "cssName": "fs-display",
@@ -624,5 +634,108 @@
624
634
  }
625
635
  }
626
636
  }
637
+ },
638
+ "z": {
639
+ "$description": "Stacking scale. Gapped for platform chrome — never invent z-index numbers in apps.",
640
+ "dropdown": {
641
+ "$type": "number",
642
+ "$value": 1000,
643
+ "$extensions": {
644
+ "putio": {
645
+ "cssName": "z-dropdown",
646
+ "mode": "global",
647
+ "category": "other",
648
+ "figma": false
649
+ }
650
+ }
651
+ },
652
+ "sticky": {
653
+ "$type": "number",
654
+ "$value": 1100,
655
+ "$extensions": {
656
+ "putio": {
657
+ "cssName": "z-sticky",
658
+ "mode": "global",
659
+ "category": "other",
660
+ "figma": false
661
+ }
662
+ }
663
+ },
664
+ "modal": {
665
+ "$type": "number",
666
+ "$value": 1300,
667
+ "$extensions": {
668
+ "putio": {
669
+ "cssName": "z-modal",
670
+ "mode": "global",
671
+ "category": "other",
672
+ "figma": false
673
+ }
674
+ }
675
+ },
676
+ "notification": {
677
+ "$type": "number",
678
+ "$value": 1400,
679
+ "$extensions": {
680
+ "putio": {
681
+ "cssName": "z-notification",
682
+ "mode": "global",
683
+ "category": "other",
684
+ "figma": false
685
+ }
686
+ }
687
+ },
688
+ "tooltip": {
689
+ "$type": "number",
690
+ "$value": 1500,
691
+ "$extensions": {
692
+ "putio": {
693
+ "cssName": "z-tooltip",
694
+ "mode": "global",
695
+ "category": "other",
696
+ "figma": false
697
+ }
698
+ }
699
+ }
700
+ },
701
+ "breakpoint": {
702
+ "$description": "Responsive breakpoints, lifted from app.put.io's BREAKPOINTS. Generator-facing: CSS media queries cannot read custom properties, so emitters bind these as Tailwind screens, StyleX consts, or documented literals.",
703
+ "sm": {
704
+ "$type": "dimension",
705
+ "$value": "640px",
706
+ "$extensions": {
707
+ "putio": {
708
+ "cssName": "bp-sm",
709
+ "mode": "global",
710
+ "category": "other",
711
+ "figma": false
712
+ }
713
+ }
714
+ },
715
+ "md": {
716
+ "$type": "dimension",
717
+ "$value": "768px",
718
+ "$extensions": {
719
+ "putio": {
720
+ "cssName": "bp-md",
721
+ "mode": "global",
722
+ "category": "other",
723
+ "figma": false
724
+ }
725
+ }
726
+ },
727
+ "lg": {
728
+ "$type": "dimension",
729
+ "$value": "1280px",
730
+ "$description": "The root font-size steps from 14px to 15px at this width.",
731
+ "$extensions": {
732
+ "putio": {
733
+ "cssName": "bp-lg",
734
+ "mode": "global",
735
+ "category": "other",
736
+ "figma": false
737
+ }
738
+ }
739
+ }
627
740
  }
628
741
  }