@telepath-computer/television 0.1.206 → 0.1.209

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.
Files changed (43) hide show
  1. package/dist/canonical/v1/components.js +1 -258
  2. package/dist/canonical/v1/styles.css +372 -312
  3. package/dist/cli.cjs +3749 -3629
  4. package/dist/onboarding/README.md +17 -12
  5. package/dist/onboarding/business-ops/about.html +4 -8
  6. package/dist/onboarding/business-ops/retention-vs-releases.html +0 -9
  7. package/dist/onboarding/business-ops/revenue-vs-goals.html +0 -11
  8. package/dist/onboarding/onboarding-channels.json +114 -0
  9. package/dist/onboarding/productivity/about.html +4 -8
  10. package/dist/onboarding/productivity/company-todos/index.html +0 -3
  11. package/dist/onboarding/productivity/company-todos/task.css +3 -3
  12. package/dist/onboarding/productivity/company-todos/task.js +1 -4
  13. package/dist/onboarding/productivity/meeting-prep.html +0 -7
  14. package/dist/onboarding/productivity/priorities-today.html +0 -7
  15. package/dist/onboarding/productivity/todays-calendar/calendar.js +327 -643
  16. package/dist/onboarding/productivity/todays-calendar/index.html +0 -4
  17. package/dist/onboarding/research/about.html +5 -9
  18. package/dist/onboarding/research/open-model-research.html +0 -9
  19. package/dist/onboarding/research/todays-news.html +3 -10
  20. package/dist/onboarding/tv-guide/welcome/index.html +5 -5
  21. package/dist/skills/television/SKILL.md +180 -136
  22. package/dist/skills/tv-calendar/calendar.js +327 -643
  23. package/dist/skills/tv-tasks/SKILL.md +10 -9
  24. package/dist/skills/tv-tasks/task.css +5 -6
  25. package/dist/skills/tv-tasks/task.js +2 -5
  26. package/dist/skills/tv-theme/SKILL.md +293 -193
  27. package/dist/views/artifact-missing/index.html +125 -60
  28. package/dist/views/markdown/index.html +22 -45
  29. package/dist/web/assets/artifact-bridge-BXDhGuL-.js +1 -0
  30. package/dist/web/assets/{artifactMissing-DY3nzD0p.js → artifactMissing-9rcTXhkH.js} +1 -1
  31. package/dist/web/assets/main-Blg8fuaV.css +1 -0
  32. package/dist/web/assets/main-Dlb0E5A4.js +594 -0
  33. package/dist/web/assets/{urlUnsupported-B2K6eB7H.js → urlUnsupported-kgq7Zh2V.js} +1 -1
  34. package/dist/web/index.html +4 -3
  35. package/dist/web/views/artifact-missing/index.html +125 -60
  36. package/dist/web/views/url-unsupported/index.html +127 -74
  37. package/package.json +2 -2
  38. package/dist/onboarding/onboarding-screens.json +0 -167
  39. package/dist/skills/tv-calendar/THIRD-PARTY-NOTICES.txt +0 -36
  40. package/dist/web/assets/artifact-bridge-BhiFDvPj.js +0 -1
  41. package/dist/web/assets/main-5017mprd.css +0 -1
  42. package/dist/web/assets/main-DdeZRdEy.js +0 -865
  43. /package/dist/canonical/v1/fonts/{Hind-Variable.woff2 → Hind-Variable.933e9900.woff2} +0 -0
@@ -32,245 +32,345 @@ The split matters because Television's token surface evolves across releases. A
32
32
 
33
33
  ## Styling surface
34
34
 
35
- Television's CSS has two layers: a **token contract** (semantic colors, palettes, scales) and a **component structure** (the chrome surfaces and content surfaces those tokens compose into). Themes work primarily by overriding tokens; targeted selector rules are escape hatches when the tokens can't fully express a design intent.
35
+ A Television theme is one CSS overlay delivered to two consumers:
36
36
 
37
- ### What you're skinning
37
+ - Artifacts receive it after the canonical v1 stylesheet at `/canonical/v1/styles.css`.
38
+ - The browser application fetches the same `theme.css` and adopts it after its bundled styles.
38
39
 
39
- Television is a single-screen-at-a-time display for AI-generated artifacts. The structural pieces:
40
+ Canonical artifact styling is the stable public contract. The redesigned browser chrome also receives the overlay, but complete chrome appearance is a later theming milestone; some token or selector overrides may have no visible effect there. Verify every chrome-specific rule in the running application rather than assuming artifact coverage proves it.
40
41
 
41
- - **The app shell.** A single window that always shows one active screen. There's no home page; the active screen is the page.
42
- - **`<screen-select>`** — a top-edge or corner control listing available screens; lets the user switch.
43
- - **`<command-panel>`** — persistent chrome that floats over content (bottom or corner). Hosts global commands and command panel input/content. Uses paper material in dark tone by default.
44
- - **`<screen-view>` → `<layout-view>`** — page container holding the scrollable canvas where artifact cards live.
45
- - **`<artifact-view>`** — each artifact card. Glass-material title bar wrapping a paper-material content surface (the artifact's rendered HTML, in an iframe).
46
- - **Popovers, dropdowns, modals** — paper-material panels for transient and modal UI.
42
+ Themes have two tools:
47
43
 
48
- ### The material / tone / level system
44
+ - Override custom properties on `:root` for system-wide choices such as type, spacing, color, and selection.
45
+ - Add narrowly targeted selector rules for a specific surface. Put a purpose comment above each such rule so the intent survives a future re-render against a changed application structure.
49
46
 
50
- Three orthogonal attributes describe every UI surface:
47
+ ### Canonical token snapshot
51
48
 
52
- - **`material="paper" | "glass"`** `paper` is opaque ("this is the content, read me"); `glass` is translucent with a backdrop-filter blur ("I'm chrome over content, peek through me"). Themes affect both: paper surfaces show your `--color-surface`; glass surfaces blend it with what's behind.
53
- - **`tone="light" | "dark"`** — flips three things on every descendant of the surface: body text color (descendants inherit a light foreground when `tone="dark"`), hairline edge color, and the overlay hover/active tokens. Anything using `currentColor` (icons, tints, `color: inherit` headings) flips automatically. This is what makes dark mode work without per-component overrides.
54
- - **`level="1" | "2" | "overlay"`** — shadow stack only. `1` = small drop-shadow (popovers, dropdowns), `2` = lifted card (artifact bodies), `overlay` = no shadow (persistent chrome bonded to viewport, like the command panel).
55
-
56
- If you want a dark theme: set `color-scheme: dark` and rely on the existing `[tone="dark"]` rules in `materials.css` to flip foregrounds across descendants — you don't need to override every component.
57
-
58
- ### The token contract
59
-
60
- Two source files in `packages/ui/styles/`:
61
-
62
- - **`tokens.css`** — palette and scales. Raw values: `--neutral-50` through `--neutral-950`, color palettes (`--red-*`, `--blue-*`, etc.), `--alpha-50` through `--alpha-950`, `--tint-50` through `--tint-950`, type scale (`--text-base`, `--text-sm`, `--text-lg`), spacing (`--space-2`, `--space-4`, `--space-6`, `--space-8`, `--space-10`, `--space-12`, `--space-16`, `--space-20`, `--space-24`, `--space-32`, `--space-48`, `--space-64`), radii (`--radius-4` through `--radius-full`), control heights (`--control-height-xs/sm/md`), shadows (`--shadow-hairline`, `--shadow-control`), fonts (`--font-sans`, `--font-mono`, `--font-brand`).
63
- - **`theme.css`** — semantic mappings most themes override.
64
-
65
- Current `theme.css` content as of this skill build (always read live source for the latest — see below):
49
+ The following build-time snapshot comes from Television's canonical foundation sources. It is useful for orientation, while the running server remains authoritative for the version being themed.
66
50
 
67
51
  ```css
52
+ /* colors.css */
68
53
  :root {
69
- --color-bg: var(--neutral-50);
70
- --color-bg-muted: var(--neutral-100);
71
- --color-surface: var(--white);
72
- --color-surface-muted: var(--neutral-100);
73
- --color-interactive: var(--neutral-200);
74
- --color-interactive-hover: var(--neutral-300);
75
-
76
- /* Borders use alpha so the same hairline reads on light, dark, or
77
- image bgs without needing a tone-aware swap. */
78
- --color-border: rgba(0, 0, 0, 0.10);
79
- --color-border-muted: rgba(0, 0, 0, 0.06);
80
-
54
+ /* Colors */
55
+ --black: #000000;
56
+ --white: #ffffff;
57
+
58
+ /* Neutral */
59
+ --neutral-50: oklch(98.5% 0 none);
60
+ --neutral-100: oklch(97% 0 none);
61
+ --neutral-200: oklch(92.2% 0 none);
62
+ --neutral-300: oklch(87% 0 none);
63
+ --neutral-400: oklch(70.8% 0 none);
64
+ --neutral-500: oklch(55.6% 0 none);
65
+ --neutral-600: oklch(43.9% 0 none);
66
+ --neutral-700: oklch(37.1% 0 none);
67
+ --neutral-800: oklch(26.9% 0 none);
68
+ --neutral-900: oklch(20.5% 0 none);
69
+ --neutral-950: oklch(14.5% 0 none);
70
+
71
+ /* Alpha */
72
+ --alpha-50: 4%;
73
+ --alpha-100: 8%;
74
+ --alpha-200: 15%;
75
+ --alpha-300: 22%;
76
+ --alpha-400: 30%;
77
+ --alpha-500: 40%;
78
+ --alpha-600: 50%;
79
+ --alpha-700: 65%;
80
+ --alpha-800: 80%;
81
+ --alpha-900: 90%;
82
+ --alpha-950: 95%;
83
+
84
+ /* Blue */
85
+ --blue-50: oklch(0.97 0.014 254.604);
86
+ --blue-100: oklch(0.932 0.032 255.585);
87
+ --blue-200: oklch(0.882 0.059 254.128);
88
+ --blue-300: oklch(0.809 0.105 251.813);
89
+ --blue-400: oklch(0.707 0.165 254.624);
90
+ --blue-500: oklch(0.623 0.214 259.815);
91
+ --blue-600: oklch(0.546 0.245 262.881);
92
+ --blue-700: oklch(0.488 0.243 264.376);
93
+ --blue-800: oklch(0.424 0.199 265.638);
94
+ --blue-900: oklch(0.379 0.146 265.522);
95
+
96
+ /* Red — the destructive and error hue: a press that destroys, a rejected
97
+ token, a failure line. Tailwind's red, like the blue. */
98
+ --red-50: oklch(0.971 0.013 17.38);
99
+ --red-100: oklch(0.936 0.032 17.717);
100
+ --red-200: oklch(0.885 0.062 18.334);
101
+ --red-300: oklch(0.808 0.114 19.571);
102
+ --red-400: oklch(0.704 0.191 22.216);
103
+ --red-500: oklch(0.637 0.237 25.331);
104
+ --red-600: oklch(0.577 0.245 27.325);
105
+ --red-700: oklch(0.505 0.213 27.518);
106
+ --red-800: oklch(0.444 0.177 26.899);
107
+ --red-900: oklch(0.396 0.141 25.723);
108
+
109
+ /* Yellow — the attention color: worn by things that need noticing exactly
110
+ while they apply (the update bell), never for emphasis, which is the key
111
+ color's job. */
112
+ --yellow-50: oklch(0.987 0.026 102.212);
113
+ --yellow-100: oklch(0.973 0.071 103.193);
114
+ --yellow-200: oklch(0.945 0.129 101.54);
115
+ --yellow-300: oklch(0.905 0.182 98.111);
116
+ --yellow-400: oklch(0.852 0.199 91.936);
117
+ --yellow-500: oklch(0.795 0.184 86.047);
118
+ --yellow-600: oklch(0.681 0.162 75.834);
119
+ --yellow-700: oklch(0.554 0.135 66.442);
120
+ --yellow-800: oklch(0.476 0.114 61.907);
121
+ --yellow-900: oklch(0.421 0.095 57.708);
122
+ --yellow-950: oklch(0.286 0.066 53.813);
123
+
124
+ /* Green, orange, purple — accent ramps. Tailwind's values, like the
125
+ blue. */
126
+ --green-50: oklch(0.982 0.018 155.826);
127
+ --green-100: oklch(0.962 0.044 156.743);
128
+ --green-200: oklch(0.925 0.084 155.995);
129
+ --green-300: oklch(0.871 0.15 154.449);
130
+ --green-400: oklch(0.792 0.209 151.711);
131
+ --green-500: oklch(0.723 0.219 149.579);
132
+ --green-600: oklch(0.627 0.194 149.214);
133
+ --green-700: oklch(0.527 0.154 150.069);
134
+ --green-800: oklch(0.448 0.119 151.328);
135
+ --green-900: oklch(0.393 0.095 152.535);
136
+
137
+ --orange-50: oklch(0.98 0.016 73.684);
138
+ --orange-100: oklch(0.954 0.038 75.164);
139
+ --orange-200: oklch(0.901 0.076 70.697);
140
+ --orange-300: oklch(0.837 0.128 66.29);
141
+ --orange-400: oklch(0.75 0.183 55.934);
142
+ --orange-500: oklch(0.705 0.213 47.604);
143
+ --orange-600: oklch(0.646 0.222 41.116);
144
+ --orange-700: oklch(0.553 0.195 38.402);
145
+ --orange-800: oklch(0.47 0.157 37.304);
146
+ --orange-900: oklch(0.408 0.123 38.172);
147
+
148
+ --purple-50: oklch(0.977 0.014 308.299);
149
+ --purple-100: oklch(0.946 0.033 307.174);
150
+ --purple-200: oklch(0.902 0.063 306.703);
151
+ --purple-300: oklch(0.827 0.119 306.383);
152
+ --purple-400: oklch(0.714 0.203 305.504);
153
+ --purple-500: oklch(0.627 0.265 303.9);
154
+ --purple-600: oklch(0.558 0.288 302.321);
155
+ --purple-700: oklch(0.496 0.265 301.924);
156
+ --purple-800: oklch(0.438 0.218 303.724);
157
+ --purple-900: oklch(0.381 0.176 304.987);
158
+
159
+ /* Tint */
160
+ --tint-50: color-mix(in srgb, currentColor var(--alpha-50), transparent);
161
+ --tint-100: color-mix(in srgb, currentColor var(--alpha-100), transparent);
162
+ --tint-200: color-mix(in srgb, currentColor var(--alpha-200), transparent);
163
+ --tint-300: color-mix(in srgb, currentColor var(--alpha-300), transparent);
164
+ --tint-400: color-mix(in srgb, currentColor var(--alpha-400), transparent);
165
+ --tint-500: color-mix(in srgb, currentColor var(--alpha-500), transparent);
166
+ --tint-600: color-mix(in srgb, currentColor var(--alpha-600), transparent);
167
+ --tint-700: color-mix(in srgb, currentColor var(--alpha-700), transparent);
168
+ --tint-800: color-mix(in srgb, currentColor var(--alpha-800), transparent);
169
+ --tint-900: color-mix(in srgb, currentColor var(--alpha-900), transparent);
170
+ --tint-950: color-mix(in srgb, currentColor var(--alpha-950), transparent);
171
+
172
+ /* Color roles — what a color is for, resolved onto the ramps above. */
81
173
  --color-text: var(--neutral-900);
82
174
  --color-text-muted: var(--neutral-500);
175
+ /* The interface's key color — what carries emphasis and marks the thing
176
+ you are on. Selection reads as this rather than as a heavier grey, so
177
+ "hovered" and "selected" differ in hue, not just in weight. */
178
+ --color-primary: var(--blue-600);
179
+ /* A fill and the text that survives on it are a pair. Naming the foreground
180
+ keeps the contrast a stated decision rather than something each use site
181
+ guesses at — white on blue-500 measures 3.76:1 and fails AA at body size. */
182
+ --color-on-primary: var(--white);
183
+ --color-selected: var(--color-primary);
184
+ /* What the app's own content sits on, behind the surfaces it holds. Darker
185
+ than those surfaces rather than lighter, so a white one reads as lifted
186
+ off it — a gap of background is how the app shows where its own chrome
187
+ ends and something it is holding begins. */
188
+ --color-background: var(--neutral-200);
189
+ /* The ground of a document or artifact the app holds. Surface vocabulary
190
+ belongs to that held content; the chrome's own ground stays
191
+ --color-background. */
192
+ --color-surface: var(--white);
193
+ /* A quiet region within a held surface: distinct without reading as a
194
+ second layer of app chrome. */
195
+ --color-surface-muted: var(--neutral-100);
196
+ /* The ordinary seam between surface regions. Ten percent is deliberate:
197
+ the alpha ramp's neighbouring steps are too faint and too strong. */
198
+ --color-border: rgb(0 0 0 / 10%);
199
+ /* A repeated or subordinate seam should organize without boxing things in;
200
+ six percent stays below the ordinary border without disappearing. */
201
+ --color-border-muted: rgb(0 0 0 / 6%);
202
+ /* A link follows its surrounding text unless a theme gives it an accent. */
83
203
  --color-link: inherit;
84
- --color-focus-ring: var(--neutral-500);
85
- --color-overlay-backdrop: rgb(0 0 0 / 0.5);
86
- --color-highlight: rgb(255 255 255 / 0.5);
87
- --color-primary: var(--blue-500);
204
+ /* The destructive and error role. */
88
205
  --color-danger: var(--red-600);
206
+ /* The affirmative and completed-state role. */
207
+ --color-success: var(--green-600);
208
+ /* The caution and warning role. */
209
+ --color-warning: var(--orange-600);
89
210
 
90
211
  color-scheme: light;
91
212
  }
92
- ```
93
213
 
94
- `color-scheme: dark` flips OS-level chrome (scrollbars, form controls) — set it for dark themes so native widgets don't fight the look.
95
-
96
- ### Reading the live token surface
97
-
98
- The block above is a build-time snapshot. **For any nontrivial theme, also read the actual `tokens.css` and `theme.css` files at authoring time** to catch additions/renames/removals since this skill was last built.
214
+ /* text.css */
215
+ :root {
216
+ /* Type */
217
+ /* The base the steps below compute from. */
218
+ --text-base: 14px;
219
+ --text-sm: round(calc(var(--text-md) / var(--text-scale)), 1px);
220
+ --text-md: var(--text-base);
221
+ --text-lg: round(calc(var(--text-md) * var(--text-scale)), 1px);
222
+ --text-xl: round(calc(var(--text-lg) * var(--text-scale)), 1px);
223
+ --text-2xl: round(calc(var(--text-xl) * var(--text-scale)), 1px);
224
+ --text-3xl: 24px;
225
+ --text-4xl: 30px;
226
+ --text-scale: 1.125;
227
+ --leading-base: 1.5;
228
+
229
+ /* Fonts */
230
+ --font-sans: "Hind", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
231
+ --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
232
+ --font-weight-normal: 400;
233
+ --font-weight-medium: 500;
234
+ --font-weight-body: var(--font-weight-medium);
235
+ --font-weight-semibold: 600;
236
+ }
99
237
 
100
- Preferred fetch from a running Television server:
238
+ /* spacing.css */
239
+ :root {
240
+ /* Spacing */
241
+ --space-2: 2px;
242
+ --space-4: 4px;
243
+ --space-6: 6px;
244
+ --space-8: 8px;
245
+ --space-10: 10px;
246
+ --space-12: 12px;
247
+ --space-16: 16px;
248
+ --space-20: 20px;
249
+ --space-24: 24px;
250
+ --space-32: 32px;
251
+ --space-48: 48px;
252
+ --space-64: 64px;
253
+
254
+ /* Radius */
255
+ --radius-4: 4px;
256
+ --radius-6: 6px;
257
+ --radius-8: 8px;
258
+ --radius-12: 12px;
259
+ --radius-16: 16px;
260
+ --radius-24: 24px;
261
+ --radius-full: 9999px; /* pill — fully rounded ends at any element size */
262
+ }
101
263
 
102
- ```bash
103
- # Default local server URL is http://localhost:32848
104
- curl http://localhost:32848/canonical/v1/styles.css | head -300
264
+ /* shadows.css */
265
+ :root {
266
+ /* The elevation a floating panel lifts off the page with: a broad soft
267
+ throw and a tight contact shadow. A role, not a ramp — there is one
268
+ elevation in the system; a scale grows if more appear. */
269
+ --shadow-panel:
270
+ 0 8px 24px rgba(0, 0, 0, 0.12),
271
+ 0 2px 8px rgba(0, 0, 0, 0.06);
272
+ }
105
273
  ```
106
274
 
107
- The bundled canonical stylesheet inlines both `tokens.css` and `theme.css`. If you're talking to a non-default server, get the URL from `tv state` or from the connection the user is targeting.
108
-
109
- Alternative — from a Television source checkout:
275
+ For nontrivial work, read the complete live canonical stylesheet:
110
276
 
111
277
  ```bash
112
- cat <television-checkout>/packages/ui/styles/tokens.css <television-checkout>/packages/ui/styles/theme.css
278
+ # The default local server URL is http://localhost:32848.
279
+ curl http://localhost:32848/canonical/v1/styles.css
113
280
  ```
114
281
 
115
- ### Tokens vs. selectors pick the right tool
116
-
117
- Themes have two complementary tools:
118
-
119
- - **Override semantic tokens on `:root`** when you want a change to propagate everywhere it's relevant — every paper surface, every body text, every focus ring. One token edit, system-wide effect. Use this for the look's foundations: backgrounds, foregrounds, primary accents, border weights.
120
- - **Override specific selectors** when the intent is local to a surface — the command panel input gets a special background, the artifact title bar uses a custom font, the layout canvas gets a subtle background image. Selectors give surgical control; tokens can't always express what a design wants.
121
-
122
- Both are first-class. A typical theme uses tokens for ~80% of its effect and selector-level rules for the rest. Don't avoid selectors out of orthodoxy; use them where they fit.
123
-
124
- The one rule for selector-level rules: **comment them with their purpose.** When Television's component structure shifts in a future release, the comment is what lets an agent re-author the rule against the new structure. Without the comment, a stale selector is just dead CSS — nobody knows what it was for.
125
-
126
- ## Surface-by-surface guidance
127
-
128
- A theme that touches `:root` tokens will affect every surface listed below. The notes here describe what each surface consumes so you know which tokens drive which look — useful for predicting how a token change will land.
129
-
130
- ### App background and wallpaper
131
-
132
- `<television-app>` is the root surface — the thing that fills the window. Out of the box it shows a bundled wallpaper image with a fallback background color. Two app-level tokens control this layer:
282
+ For another server, run `tv status`, read `serverURL` from its JSON output, and fetch `<serverURL>/canonical/v1/styles.css`.
133
283
 
134
- - **`--app-bg`** base background color, defaulting to `var(--color-bg)`. Shows through wherever `--app-wallpaper` is transparent or set to `none`.
135
- - **`--app-wallpaper`** — the `background-image` value, defaulting to the bundled wallpaper `url(...)`. Set this to `none` to remove the wallpaper (so `--app-bg` shows), or to a `url(...)` (typically pointing at a theme asset) to use a custom wallpaper.
284
+ From a Television checkout, the authored canonical foundation lives under `specs/ui/foundation/`; `colors.css`, `text.css`, `spacing.css`, and `shadows.css` define its custom properties, while `prose.css` shows how artifact documents consume them.
136
285
 
137
- Theme levers:
286
+ `color-scheme: dark` controls browser-native widgets such as scrollbars and form controls. Set it when the theme uses a dark ground.
138
287
 
139
- - Want a flat colored background? `:root { --app-wallpaper: none; }` and override `--color-bg` (or `--app-bg` directly for finer control).
140
- - Want a custom wallpaper? `:root { --app-wallpaper: url(my-bg.jpg); }` where `my-bg.jpg` is in the theme's `resources/` folder (the server will rewrite the relative URL).
141
- - The default-look bundled wallpaper is `packages/web/src/assets/wallpapers/clouds.jpg` — themes don't import or reference it; they replace the variable.
288
+ ## Current browser chrome structure
142
289
 
143
- ### Buttons
290
+ Use this map only for chrome-specific rules and verify the result in the running version:
144
291
 
145
- Television has three button stories: variant-styled buttons, ghost buttons (chromeless overlay hover), and bespoke chrome-button shapes (close buttons, breadcrumbs, etc.).
292
+ - **`#app`** fills the window. Its `.app-sidebar` and `.app-main` children hold the sidebar and the main stage.
293
+ - **`.sidebar`** is the permanent channel list. `.channel[aria-current]` is the selected channel; `.sidebar-foot` holds channel creation.
294
+ - **`.top-bar`** holds stage navigation controls.
295
+ - **`.stage`** is the artifact-page viewport. `.filmstrip` contains `.page` entries, and `.page[selected]` is the selected page.
296
+ - **`.artifact-frame`** is the white document frame. `.artifact-content` holds the document and `.artifact-title-bar` is the quiet lower title band.
297
+ - **Popovers and dialogs** use ordinary `[popover]` and `dialog` elements with the application foundation's panel treatment.
146
298
 
147
- What each consumes:
299
+ These selectors are current implementation structure, not canonical artifact API. A theme skill should retain the visual purpose of each selector rule so an agent can map that purpose onto the running structure when re-rendering.
148
300
 
149
- - **Default `<button>`** — `--color-text` (text), `--color-interactive` (resting bg), `--color-interactive-hover` (hover bg), `--control-height-md` (28px outer height), `--shadow-control` (subtle drop shadow on resting state).
150
- - **`<button variant="ghost">`** — fully chromeless, no fill. Hover/active backgrounds use `--color-overlay-hover` / `--color-overlay-active` (semantic overlay tokens that auto-flip with the surface's `tone`). The transparent-chrome auto-tone watcher (`packages/ui/utils/button-tone.ts`) samples `[variant="ghost"]`, `[variant="glass"]`, and `[material="glass"]` when they create a new tone boundary; nested transparent chrome inherits an ancestor `tone` unless it explicitly declares its own.
151
- - **`<button variant="primary">`** — emphasis button. Fills with `--color-primary` for the bg, `--white` for text.
152
- - **Icon-only buttons** — `<button icon-only>` becomes a square at `--control-height-md` per side.
301
+ ## Surface guidance
153
302
 
154
- Theme levers:
303
+ ### Application and stage ground
155
304
 
156
- - Adjust `--color-interactive` / `--color-interactive-hover` for default-button affordance.
157
- - Adjust `--color-overlay-hover` / `--color-overlay-active` to change ghost-button hover intensity (these also affect dropdown items and other chromeless overlays).
158
- - Adjust `--color-primary` for emphasis-button fills.
159
- - Don't set `cursor: pointer` on buttons — there's a global rule in `elements.css` that sets `cursor: default` to match the macOS-native feel.
305
+ `--color-background` is the main redesigned chrome ground behind stage pages. The sidebar and artifact frame use `--white` as their authored surface. Global text uses `--color-text` and `--color-text-muted`.
160
306
 
161
- ### Artifact title bars
307
+ A theme can establish its broad palette with current role tokens:
162
308
 
163
- The chrome strip at the top of each `<artifact-view>` card. Uses **glass** material (translucent + backdrop-blur). Tone is sampled from the artifact content beneath it, so the title bar adapts: a dark-content artifact gets `tone="dark"` and a light-foreground title; a light-content artifact gets the inverse.
164
-
165
- What it consumes:
166
-
167
- - The glass tint (which composites against the artifact body) — driven by `materials.css` rules referencing the alpha scale and current surface tone.
168
- - `--color-text` / `--color-text-muted` for the title text and any sub-text.
169
- - `--color-border` for the hairline rim around the glass surface.
170
-
171
- Theme levers:
172
-
173
- - Adjust `--color-border` to change the title bar's edge weight.
174
- - Adjust the title's font weight or letter spacing via selector-level rules on `artifact-view > header` if the design needs a non-token change (comment the rule with purpose).
175
-
176
- ### Command panel — input + content
177
-
178
- `<command-panel>` is the persistent chrome at the bottom (or corner) of the app. It hosts the command panel input (typically a textarea) and command panel content above it. By default uses **paper** material in **dark** tone, **`level="overlay"`** (no shadow — it's bonded to the viewport).
179
-
180
- What it consumes:
181
-
182
- - The paper-dark surface — a near-black opaque fill defined by `materials.css` reading from the `[tone="dark"]` overrides of `--color-surface` and related tokens.
183
- - `--color-text` (descendants inherit, but with `tone="dark"` flipping descendants to a light foreground).
184
- - `--color-text-muted` for secondary text in the stream (timestamps, system messages).
185
- - `--color-border` / `--color-border-muted` for separators between messages.
186
- - The input's textarea consumes `--color-interactive` (background) and `--color-border` (rim).
187
-
188
- Theme levers:
189
-
190
- - Override the dark-tone surface color: target `[tone="dark"]` in your theme and set `--color-surface` (or set it on `command-panel` directly with a purpose comment).
191
- - Adjust message-stream separator weight via `--color-border-muted`.
192
- - Adjust the command panel input's affordance via `--color-interactive`.
193
- - For dramatic looks (a saturated command panel background, a textured command panel surface), target `command-panel` directly with a purpose comment.
194
-
195
- ### Popovers and dropdowns
196
-
197
- Anchored panels for menus and inline forms. Paper material, light tone typically, `level="1"` (small drop-shadow). Dismiss on outside click.
198
-
199
- What they consume:
200
-
201
- - `--color-surface` (paper fill).
202
- - `--color-border` (hairline rim).
203
- - `--color-text` (label text), `--color-text-muted` (secondary labels).
204
- - `--color-overlay-hover` / `--color-overlay-active` for hover/active states on individual items (these are *also* used by ghost buttons, so changing them affects both surfaces — usually fine, since the relationship is semantic).
205
- - `--shadow-control` for the drop shadow (defined as a soft 2-layer shadow).
206
-
207
- Theme levers:
208
-
209
- - Surface color via `--color-surface`.
210
- - Hairline rim via `--color-border`.
211
- - The overlay-hover token controls both popover-item and ghost-button hover; usually move them together.
212
-
213
- ### Modal sheets
214
-
215
- Full-screen overlays for blocking flows. Paper material, larger than popovers, no specific level (often `level="2"`).
216
-
217
- What they consume:
218
-
219
- - `--color-surface` (fill).
220
- - `--color-overlay-backdrop` for the scrim behind the modal (the dark veil over the rest of the app while the modal is open).
221
- - All the popover tokens for internal elements.
309
+ ```css
310
+ :root {
311
+ --color-background: var(--neutral-900);
312
+ --color-text: var(--neutral-100);
313
+ --color-text-muted: var(--neutral-400);
314
+ --color-primary: var(--blue-400);
315
+ --color-selected: var(--color-primary);
316
+ --color-on-primary: var(--white);
317
+ color-scheme: dark;
318
+ }
319
+ ```
222
320
 
223
- Theme levers:
321
+ Changing `--white` has a wider meaning than changing a role token: canonical artifacts and several chrome surfaces use it directly. Prefer semantic roles where they express the intent, and visually inspect any raw-palette override.
224
322
 
225
- - The scrim via `--color-overlay-backdrop`.
226
- - The modal surface via `--color-surface`.
323
+ ### Sidebar
227
324
 
228
- ### Layout canvas
325
+ The selected channel uses `--color-selected` with `--color-on-primary`; group labels use `--color-text-muted`; the sidebar ground is `--white`. Local texture or typography needs a purpose-commented selector rule:
229
326
 
230
- The scrollable area inside `<screen-view>` where artifact cards live. Has its own scroll position and pan/zoom semantics.
327
+ ```css
328
+ /* Keep the channel list visually distinct from the stage with a warm paper ground. */
329
+ .sidebar {
330
+ background: #fffaf0;
331
+ }
332
+ ```
231
333
 
232
- What it consumes:
334
+ ### Stage pages and artifact frames
233
335
 
234
- - `--color-bg` for the canvas background (the "page" surface).
235
- - `--color-bg-muted` if the canvas distinguishes content areas (e.g. gutter regions vs. card region).
236
- - `--color-border-muted` for any grid lines, if a future debug mode shows them.
336
+ `.stage` consumes `--color-background`. A selected artifact is the `.page[selected]` entry. The frame itself is `.artifact-frame` with an inset `.artifact-content` and lower `.artifact-title-bar`.
237
337
 
238
- Theme levers:
338
+ ```css
339
+ /* Give the selected document's lower title band a quiet orientation tint. */
340
+ .page[selected] > .artifact-frame .artifact-title-bar {
341
+ background: color-mix(in srgb, var(--color-primary) 8%, transparent);
342
+ }
343
+ ```
239
344
 
240
- - `--color-bg` is the highest-leverage single token in any theme it determines the page's overall feel.
241
- - `--color-bg-muted` for related secondary surfaces.
345
+ The artifact document renders inside its own iframe. Style the document through canonical tokens or document markup; a chrome selector cannot cross the iframe boundary.
242
346
 
243
- ### Bare HTML in artifacts
347
+ ### Popovers and dialogs
244
348
 
245
- Artifact content is HTML rendered inside an iframe. The iframe links `/canonical/v1/styles.css`, which the server composes from the canonical bundle plus your active theme. So everything below works in artifacts the same way it does in the app chrome.
349
+ Application popovers and dialogs share a white panel ground, radius, and `--shadow-panel`. Canonical artifact controls have their own public component and bare-element rules in the live stylesheet. Keep an app-chrome selector scoped when the change should not affect artifact documents.
246
350
 
247
- Default styling for bare tags is in `packages/ui/styles/elements.css`:
351
+ ### Artifact documents
248
352
 
249
- - `<body>` uses `--color-bg` background, `--color-text` text, `--font-sans` family.
250
- - `<h1>`–`<h6>` use `--font-brand` (often the same as `--font-sans` unless overridden), with the type scale tokens (`--text-base`, `--text-lg`, `--text-xl`) and `--color-text` for color.
251
- - `<a>` uses `--color-link` (defaults to `inherit` — links read in the body color unless a theme sets otherwise).
252
- - `<code>` and `<pre>` use `--font-mono`, `--color-bg-muted` for the background, `--color-text` for content.
253
- - Form controls (`<input>`, `<textarea>`, `<select>`) consume `--control-height-md`, `--color-interactive`, `--color-border`, `--color-focus-ring`.
353
+ Artifacts load the canonical stylesheet plus the active theme. The canonical foundation provides:
254
354
 
255
- Theme levers:
355
+ - palette and role properties such as `--neutral-*`, `--blue-*`, `--color-text`, `--color-text-muted`, `--color-primary`, and `--color-background`;
356
+ - typography properties such as `--font-sans`, `--font-mono`, `--text-*`, and `--font-weight-*`;
357
+ - spacing and radius properties such as `--space-*` and `--radius-*`;
358
+ - `--shadow-panel`;
359
+ - semantic bare-HTML prose and the canonical v1 components.
256
360
 
257
- - The same `:root` tokens that drive the app chrome drive bare HTML there's no separate "artifact theme."
258
- - For a theme with a distinctive link color (e.g. a brand accent), set `--color-link: <value>`.
259
- - For a theme with a custom code/pre font, override `--font-mono`.
361
+ Read the live stylesheet before using a property not present in the snapshot. Theme CSS may also include `@font-face`, media queries, and rules for authored artifact markup.
260
362
 
261
- ## What's in scope for a theme
363
+ ## Theme contents
262
364
 
263
- - CSS custom properties on `:root` — the primary tool.
264
- - `@font-face` declarations for custom typography (font files in the skill's `resources/` folder; reference relatively from `theme.css`, e.g. `url(MyFont.woff2)` — the render step copies them into the theme folder).
265
- - Background images, decorative images (same path — `resources/` in the skill, copied alongside `theme.css`).
266
- - `@media (prefers-color-scheme: dark)` blocks if the theme should react to OS-level light/dark.
267
- - Selector-level rules **with purpose comments** for design intent the tokens can't fully express.
365
+ A theme may contain:
268
366
 
269
- ## What's out of scope
367
+ - CSS custom-property overrides;
368
+ - `@font-face` declarations, with files stored beside `theme.css`;
369
+ - background and decorative images stored beside `theme.css`;
370
+ - `@media` blocks;
371
+ - purpose-commented selector rules.
270
372
 
271
- - JavaScript hooks themes are static styling assets.
272
- - Theme manifests with metadata beyond the SKILL.md.
273
- - Multiple variants within one theme (a theme is one look; if you want a dark variant of a light theme, that's a separate theme).
373
+ Themes are static CSS assets. They do not provide JavaScript hooks or a metadata manifest, and one theme name resolves to one `theme.css` overlay.
274
374
 
275
375
  ## Workflow
276
376
 
@@ -288,11 +388,11 @@ Theme authoring has two phases. **Iterate first** — work directly on `theme.cs
288
388
 
289
389
  ```css
290
390
  /*
291
- * Active artifact title bar gets a faint warm tint as a quiet "you are here"
292
- * cue design wanted on-screen orientation without a heavier indicator.
391
+ * Give the selected document's lower title band a faint warm tint as a
392
+ * quiet orientation cue without adding a heavier indicator.
293
393
  */
294
- [data-active] > .artifact-title {
295
- background: color-mix(in srgb, var(--color-text) 4%, transparent);
394
+ .page[selected] > .artifact-frame .artifact-title-bar {
395
+ background: color-mix(in srgb, var(--color-primary) 8%, transparent);
296
396
  }
297
397
  ```
298
398
 
@@ -316,7 +416,7 @@ The SKILL.md should have:
316
416
  - **Design choices.** Bulleted list of decisions with rationale. E.g. *"Background is near-black to evoke low-light comfort"*, *"Primary accent is muted teal — saturated enough to read on dark, restrained enough not to scream."*
317
417
  - **Style overrides.** Copy the contents of the iterated `theme.css`, comments and all. The purpose comments you wrote during iteration are what make the theme re-renderable.
318
418
  - **Assets.** List of files in `resources/`, what each is, what `theme.css` rule references it. Copy the assets from the live theme folder into `resources/`.
319
- - **Render instructions.** A short section telling future invocations how to render this skill: "fetch the live Television token surface (`/canonical/v1/styles.css` or `<checkout>/packages/ui/styles/{tokens,theme}.css`); map this skill's Intent + Design choices + Style overrides onto the current surface; emit `<storagePath>/themes/<name>/theme.css` and copy `resources/*` to `<storagePath>/themes/<name>/`."
419
+ - **Render instructions.** A short section telling future invocations how to render this skill: "fetch the live Television token surface from `/canonical/v1/styles.css` or read `<checkout>/specs/ui/foundation/{colors,text,spacing,shadows,prose}.css`; inspect the running browser structure for chrome selectors; map this skill's Intent + Design choices + Style overrides onto the current surface; emit `<storagePath>/themes/<name>/theme.css` and copy `resources/*` to `<storagePath>/themes/<name>/`."
320
420
 
321
421
  Once exported, the iterated `<storagePath>/themes/<name>/` folder and the skill should be in sync. Future edits should happen in both — update `theme.css` for the live feedback loop, update the skill's **Style overrides** section in lockstep so the durable record stays current. If they drift, the skill is the source of truth.
322
422
 
@@ -327,9 +427,9 @@ When Television's token surface or component structure changes (new tokens added
327
427
  Recovery procedure (the theme skill makes this possible):
328
428
 
329
429
  1. **Read the current Television surface:**
330
- - Running server: `curl http://localhost:32848/canonical/v1/styles.css | head -300` (or substitute the actual server URL from `tv state`).
331
- - Or, from a checkout: `cat <television-checkout>/packages/ui/styles/{tokens,theme}.css`.
332
- 2. **Read the theme's skill** — especially the **Intent**, **Design choices**, and the *comments* in the **Style overrides** section. The comments are what let you re-author selector-level rules: even if `.artifact-title` no longer exists, the comment "*active card gets a faint warm tint as a 'you are here' cue*" tells you what to target with whatever selector achieves that intent on the new version.
430
+ - Running server: `curl http://localhost:32848/canonical/v1/styles.css` (or run `tv status`, read `serverURL`, and fetch `<serverURL>/canonical/v1/styles.css`).
431
+ - Or, from a checkout: read `specs/ui/foundation/{colors,text,spacing,shadows,prose}.css` for the canonical artifact contract and the current files under `packages/web/src/{elements,views}/` for any browser-chrome selector rules.
432
+ 2. **Read the theme's skill** — especially the **Intent**, **Design choices**, and the *comments* in the **Style overrides** section. The comments are what let you re-author selector-level rules: even if `.artifact-title-bar` is absent in the running version, the comment "*selected document's lower title band gets a faint warm tint as an orientation cue*" tells you what current selector should carry that intent.
333
433
  3. **Map the original intent onto the new surface.** Token overrides that reference tokens still present transfer directly. Renamed tokens get re-mapped. New semantic tokens added to Television may need to be set to fit the theme's vibe. Selector-level rules get re-expressed against the new structure.
334
434
  4. **Update the skill's Style overrides section** with the revised rules (keep the purpose comments updated).
335
435
  5. **Re-render**: write the updated CSS to `<storagePath>/themes/<name>/theme.css` and re-copy any new/changed assets from `resources/`.