@justai/cuts 0.138.0 → 0.139.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/src/ground.css CHANGED
@@ -27,139 +27,135 @@
27
27
  * checks the tokens statically, but only a bare-page render proves it.
28
28
  */
29
29
 
30
- @layer justai.tokens, justai.base, justai.ground;
30
+ :where(:root) {
31
+ /* skeleton — mirrors @justai/ui tokens.css, pinned equal by the harness */
32
+ --fs-2xs: 0.76rem;
33
+ --fs-xs: 0.84rem;
34
+ --fs-sm: 0.92rem;
35
+ --fs-base: 1rem;
36
+ --fs-md: 1.13rem;
37
+ --fs-lg: 1.32rem;
38
+ --fs-xl: 1.6rem;
31
39
 
32
- @layer justai.ground {
33
- :where(:root) {
34
- /* skeleton — mirrors @justai/ui tokens.css, pinned equal by the harness */
35
- --fs-2xs: 0.76rem;
36
- --fs-xs: 0.84rem;
37
- --fs-sm: 0.92rem;
38
- --fs-base: 1rem;
39
- --fs-md: 1.13rem;
40
- --fs-lg: 1.32rem;
41
- --fs-xl: 1.6rem;
40
+ --radius-sm: 10px;
41
+ --radius-md: 14px;
42
+ --radius-lg: 20px;
43
+ --radius-pill: 999px;
42
44
 
43
- --radius-sm: 10px;
44
- --radius-md: 14px;
45
- --radius-lg: 20px;
46
- --radius-pill: 999px;
45
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
46
+ --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
47
47
 
48
- --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
49
- --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
48
+ /* ground — the fleet-neutral defaults for the colour contract (dark first: the fleet's default scheme) */
49
+ --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", system-ui, sans-serif;
50
+ --bg: #0a0c10;
51
+ --text: #f2f4f8;
52
+ --text-dim: #9aa3b2;
53
+ --border: rgba(255, 255, 255, 0.1);
54
+ --surface: rgba(255, 255, 255, 0.04);
55
+ --surface-2: rgba(255, 255, 255, 0.07);
56
+ --accent: #0a84ff;
57
+ /* THE INK ON A FILLED ACCENT. Every persona already declares this — the template writes it from
58
+ the accent's own `color.on` — but no cut had rendered a filled accent button until <Preroll>'s
59
+ play surface, so it had never needed a ground and did not have one. It arrives with the same
60
+ lesson the card tokens above carry: a token is not grounded because the fleet defines it, it is
61
+ grounded because THIS package does. The value pairs with the `--accent` on the line above and
62
+ is not scheme-aware, because that accent is not either.
63
+ A persona whose accent is pale — a yellow, an orange — must override it, and every one of them
64
+ already does; white ink on a #f5a623 button is the failure this token exists to prevent. */
65
+ --accent-on: #ffffff;
66
+ /* THE ecosystem's destructive red — Apple's system red, and one of it. Written here rather than
67
+ in each component because a confirmation sheet and a Sign Out row saying "this ends something"
68
+ in two different reds is exactly the drift the ConfirmSheet's own header warns about. It is
69
+ scheme-aware: Apple lightens red on dark backgrounds (#FF453A) and deepens it on light
70
+ (#FF3B30), and a single value would read wrong on one of them. */
71
+ --danger: #ff453a;
50
72
 
51
- /* ground — the fleet-neutral defaults for the colour contract (dark first: the fleet's default scheme) */
52
- --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", system-ui, sans-serif;
53
- --bg: #0a0c10;
54
- --text: #f2f4f8;
55
- --text-dim: #9aa3b2;
56
- --border: rgba(255, 255, 255, 0.1);
57
- --surface: rgba(255, 255, 255, 0.04);
58
- --surface-2: rgba(255, 255, 255, 0.07);
59
- --accent: #0a84ff;
60
- /* THE INK ON A FILLED ACCENT. Every persona already declares this — the template writes it from
61
- the accent's own `color.on` — but no cut had rendered a filled accent button until <Preroll>'s
62
- play surface, so it had never needed a ground and did not have one. It arrives with the same
63
- lesson the card tokens above carry: a token is not grounded because the fleet defines it, it is
64
- grounded because THIS package does. The value pairs with the `--accent` on the line above and
65
- is not scheme-aware, because that accent is not either.
66
- A persona whose accent is pale — a yellow, an orange — must override it, and every one of them
67
- already does; white ink on a #f5a623 button is the failure this token exists to prevent. */
68
- --accent-on: #ffffff;
69
- /* THE ecosystem's destructive red — Apple's system red, and one of it. Written here rather than
70
- in each component because a confirmation sheet and a Sign Out row saying "this ends something"
71
- in two different reds is exactly the drift the ConfirmSheet's own header warns about. It is
72
- scheme-aware: Apple lightens red on dark backgrounds (#FF453A) and deepens it on light
73
- (#FF3B30), and a single value would read wrong on one of them. */
74
- --danger: #ff453a;
73
+ /* THE CARD — a storefront tile's own surface, and the reason it is here rather than in the apex
74
+ that used to own it. The Catalogue moved into this package the day pin.games became real, and
75
+ it arrived consuming four tokens that had stayed behind in app.zone's stylesheet. Nothing broke
76
+ on app.zone, which still grounds them; the harness caught it anyway, and the founder put the
77
+ stake in the ground in one line: *why would pin.games have shadowless cards — whatever I see on
78
+ app.zone, that is it.* These are app.zone's own values, read rather than redesigned, so the
79
+ second storefront is the first one. */
80
+ --card-bg: rgba(28, 28, 34, 0.55);
81
+ --card-blur: blur(30px) saturate(1.6);
82
+ --card-shadow-hover: 0 2px 6px rgba(0, 0, 0, 0.4), 0 12px 28px -14px rgba(0, 0, 0, 0.55);
75
83
 
76
- /* THE CARD — a storefront tile's own surface, and the reason it is here rather than in the apex
77
- that used to own it. The Catalogue moved into this package the day pin.games became real, and
78
- it arrived consuming four tokens that had stayed behind in app.zone's stylesheet. Nothing broke
79
- on app.zone, which still grounds them; the harness caught it anyway, and the founder put the
80
- stake in the ground in one line: *why would pin.games have shadowless cards — whatever I see on
81
- app.zone, that is it.* These are app.zone's own values, read rather than redesigned, so the
82
- second storefront is the first one. */
83
- --card-bg: rgba(28, 28, 34, 0.55);
84
- --card-blur: blur(30px) saturate(1.6);
85
- --card-shadow-hover: 0 2px 6px rgba(0, 0, 0, 0.4), 0 12px 28px -14px rgba(0, 0, 0, 0.55);
86
-
87
- /* ── ELEVATION — mirrors @justai/ui tokens.css, and the tokens spec holds the two identical ──
88
- *
89
- * queries: box shadow token · which shadow · the panel looks detached · drop shadow standard ·
90
- * golge standardi · card shadow vs sheet shadow
91
- *
92
- * THE VALUES WERE ALREADY HERE, under one name and one meaning: `--card-shadow`, described as
93
- * "a storefront tile's own surface". Measured across the live fleet on 2026-08-20 they turned out
94
- * to be the shadow of EVERY resting surface — app.zone's catalogue cards, qr's type buttons,
95
- * calculator's panel, all byte-identical — so the name was narrower than the fact, and a persona
96
- * building its own kernel panel had nothing to reach for and invented one. The one that produced
97
- * the ruling had invented a MODAL's: twice the opacity, 3.7× the blur, and in dark deeper than
98
- * the fleet's actual modal.
99
- *
100
- * So the scale is named by ELEVATION — how far off the page a thing is — and the catalogue's own
101
- * token now reads from it rather than restating it. `--card-shadow` stays because live personas
102
- * consume it; it is an alias now, not a second definition.
103
- *
104
- * The law: **nothing that is not a sheet may exceed `--shadow-card`, and no shadow is coloured.**
105
- * A tinted shadow is a glow, a glow is a light source, and this ground has one sun and no lamps. */
106
- --shadow-card: 0 1px 2px 0 rgba(0, 0, 0, 0.32);
107
- --shadow-bar: 0 2px 12px -2px rgba(0, 0, 0, 0.55);
108
- --shadow-sheet: 0 18px 40px -20px rgba(0, 0, 0, 0.45);
109
- --card-shadow: var(--shadow-card);
110
- }
84
+ /* ── ELEVATION — mirrors @justai/ui tokens.css, and the tokens spec holds the two identical ──
85
+ *
86
+ * queries: box shadow token · which shadow · the panel looks detached · drop shadow standard ·
87
+ * golge standardi · card shadow vs sheet shadow
88
+ *
89
+ * THE VALUES WERE ALREADY HERE, under one name and one meaning: `--card-shadow`, described as
90
+ * "a storefront tile's own surface". Measured across the live fleet on 2026-08-20 they turned out
91
+ * to be the shadow of EVERY resting surface — app.zone's catalogue cards, qr's type buttons,
92
+ * calculator's panel, all byte-identical — so the name was narrower than the fact, and a persona
93
+ * building its own kernel panel had nothing to reach for and invented one. The one that produced
94
+ * the ruling had invented a MODAL's: twice the opacity, 3.7× the blur, and in dark deeper than
95
+ * the fleet's actual modal.
96
+ *
97
+ * So the scale is named by ELEVATION — how far off the page a thing is — and the catalogue's own
98
+ * token now reads from it rather than restating it. `--card-shadow` stays because live personas
99
+ * consume it; it is an alias now, not a second definition.
100
+ *
101
+ * The law: **nothing that is not a sheet may exceed `--shadow-card`, and no shadow is coloured.**
102
+ * A tinted shadow is a glow, a glow is a light source, and this ground has one sun and no lamps. */
103
+ --shadow-card: 0 1px 2px 0 rgba(0, 0, 0, 0.32);
104
+ --shadow-bar: 0 2px 12px -2px rgba(0, 0, 0, 0.55);
105
+ --shadow-sheet: 0 18px 40px -20px rgba(0, 0, 0, 0.45);
106
+ --card-shadow: var(--shadow-card);
107
+ }
111
108
 
112
- /* queries: force dark while playing · theme switch · data-theme dark · stage theme
113
- * THE GUARD IS THE FLEET'S OWN IDIOM — time's wall wrote it first: *"data-theme wins over the media
114
- * query in both directions."* A light-system visitor whose page carries data-theme="dark" gets the
115
- * dark theme this file already ships; removing the attribute returns them to auto. The stage
116
- * protocol is the first caster (a game playing = dark), and any future manual theme switch gets
117
- * this seam for free. */
118
- @media (prefers-color-scheme: light) {
119
- :where(:root:not([data-theme="dark"])) {
120
- --bg: #f6f7f9;
121
- --text: #0a0c10;
122
- --text-dim: #5b6472;
123
- --border: rgba(0, 0, 0, 0.08);
124
- --surface: rgba(255, 255, 255, 0.7);
125
- --surface-2: rgba(0, 0, 0, 0.05);
126
- --danger: #ff3b30;
109
+ /* queries: force dark while playing · theme switch · data-theme dark · stage theme
110
+ * THE GUARD IS THE FLEET'S OWN IDIOM — time's wall wrote it first: *"data-theme wins over the media
111
+ * query in both directions."* A light-system visitor whose page carries data-theme="dark" gets the
112
+ * dark theme this file already ships; removing the attribute returns them to auto. The stage
113
+ * protocol is the first caster (a game playing = dark), and any future manual theme switch gets
114
+ * this seam for free. */
115
+ @media (prefers-color-scheme: light) {
116
+ :where(:root:not([data-theme="dark"])) {
117
+ --bg: #f6f7f9;
118
+ --text: #0a0c10;
119
+ --text-dim: #5b6472;
120
+ --border: rgba(0, 0, 0, 0.08);
121
+ --surface: rgba(255, 255, 255, 0.7);
122
+ --surface-2: rgba(0, 0, 0, 0.05);
123
+ --danger: #ff3b30;
127
124
 
128
- /* Light is not the dark card with a different fill: the blur goes away entirely. A frosted
129
- panel over a pale page reads as a smudge, so app.zone drops it and pays the shadow instead. */
130
- --card-bg: #fff;
131
- --card-blur: none;
132
- --card-shadow-hover: 0 2px 4px rgba(16, 24, 40, 0.06), 0 12px 26px -8px rgba(16, 24, 40, 0.15);
125
+ /* Light is not the dark card with a different fill: the blur goes away entirely. A frosted
126
+ panel over a pale page reads as a smudge, so app.zone drops it and pays the shadow instead. */
127
+ --card-bg: #fff;
128
+ --card-blur: none;
129
+ --card-shadow-hover: 0 2px 4px rgba(16, 24, 40, 0.06), 0 12px 26px -8px rgba(16, 24, 40, 0.15);
133
130
 
134
- /* Light needs TWO layers where dark needs one: on a near-white ground a single ambient blur
135
- reads as dirt, so the pair is a 1px contact line that seats the object plus a wide, faint
136
- ambient. `--card-shadow` inherits its alias from the block above and needs no line here. */
137
- --shadow-card: 0 1px 2px 0 rgba(16, 24, 40, 0.05), 0 4px 12px -4px rgba(16, 24, 40, 0.1);
138
- --shadow-bar: 0 1px 2px rgba(16, 24, 40, 0.06), 0 8px 20px -8px rgba(16, 24, 40, 0.16);
139
- --shadow-sheet: 0 18px 40px -20px rgba(0, 0, 0, 0.45);
140
- }
131
+ /* Light needs TWO layers where dark needs one: on a near-white ground a single ambient blur
132
+ reads as dirt, so the pair is a 1px contact line that seats the object plus a wide, faint
133
+ ambient. `--card-shadow` inherits its alias from the block above and needs no line here. */
134
+ --shadow-card: 0 1px 2px 0 rgba(16, 24, 40, 0.05), 0 4px 12px -4px rgba(16, 24, 40, 0.1);
135
+ --shadow-bar: 0 1px 2px rgba(16, 24, 40, 0.06), 0 8px 20px -8px rgba(16, 24, 40, 0.16);
136
+ --shadow-sheet: 0 18px 40px -20px rgba(0, 0, 0, 0.45);
141
137
  }
138
+ }
142
139
 
143
- /* The page's ground — margin reset, the fleet's type baseline, and the page colour ON :where(html),
144
- * NEVER on body. Learned live, fleet-wide, within a day: personas paint their dot-grid on html and
145
- * leave body's background UNDECLARED — relying on the web's default transparency structurally, not
146
- * by declaration. Zero specificity beats a declaration that exists; it still fills one that never
147
- * did. A body background from the ground, with the fleet's `body{height:100%}`, painted an opaque
148
- * viewport-tall box over the top of every grid — dots gone at the top, reappearing where body ends.
149
- * The founder saw it before any instrument did. The rule that survives: THE GROUND MAY ONLY SUPPLY
150
- * WHAT A BARE PAGE LACKS ON ELEMENTS CONSUMERS DECLARE — html's background is declared by every
151
- * persona (they win); body's transparency is load-bearing and stays untouched. */
152
- /* What the shell takes above the kernel — see @justai/ui base.css, which measures it. Ground only:
153
- `:where()` is specificity zero, so a consumer that ships the shell always wins, and a surface that
154
- ships no shell still lands its cuts clear of a sticky bar instead of under one. */
155
- :where(:root) { --shell-top: 78px; }
140
+ /* The page's ground — margin reset, the fleet's type baseline, and the page colour ON :where(html),
141
+ * NEVER on body. Learned live, fleet-wide, within a day: personas paint their dot-grid on html and
142
+ * leave body's background UNDECLARED — relying on the web's default transparency structurally, not
143
+ * by declaration. Zero specificity beats a declaration that exists; it still fills one that never
144
+ * did. A body background from the ground, with the fleet's `body{height:100%}`, painted an opaque
145
+ * viewport-tall box over the top of every grid — dots gone at the top, reappearing where body ends.
146
+ * The founder saw it before any instrument did. The rule that survives: THE GROUND MAY ONLY SUPPLY
147
+ * WHAT A BARE PAGE LACKS ON ELEMENTS CONSUMERS DECLARE — html's background is declared by every
148
+ * persona (they win); body's transparency is load-bearing and stays untouched. */
149
+ /* What the shell takes above the kernel — see @justai/ui base.css, which measures it. Ground only:
150
+ `:where()` is specificity zero, so a consumer that ships the shell always wins, and a surface that
151
+ ships no shell still lands its cuts clear of a sticky bar instead of under one. */
152
+ :where(:root) { --shell-top: 78px; }
156
153
 
157
- :where(html) {
158
- background: var(--bg);
159
- }
160
- :where(body) {
161
- margin: 0;
162
- color: var(--text);
163
- font: 1rem/1.5 var(--font);
164
- }
154
+ :where(html) {
155
+ background: var(--bg);
156
+ }
157
+ :where(body) {
158
+ margin: 0;
159
+ color: var(--text);
160
+ font: 1rem/1.5 var(--font);
165
161
  }