@bongos/core 1.19.445 → 1.19.447
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/.bongos-core.json +67 -47
- package/docs/copy-inventory.md +354 -352
- package/docs/copy-registry.json +406 -388
- package/docs/module-api-changelog.md +4 -0
- package/modules/hall-ui/public/atlas.html +1 -2
- package/modules/hall-ui/public/collab.html +1 -2
- package/modules/hall-ui/public/copy-desk.css +11 -11
- package/modules/hall-ui/public/copy-desk.html +1 -2
- package/modules/hall-ui/public/diagrams.html +1 -2
- package/modules/hall-ui/public/drachmae.html +1 -2
- package/modules/hall-ui/public/gate.html +1 -2
- package/modules/hall-ui/public/goals.html +1 -2
- package/modules/hall-ui/public/government.html +1 -2
- package/modules/hall-ui/public/harbor.html +1 -2
- package/modules/hall-ui/public/idea.html +1 -2
- package/modules/hall-ui/public/ideas.css +6 -8
- package/modules/hall-ui/public/ideas.html +1 -2
- package/modules/hall-ui/public/index.html +3 -4
- package/modules/hall-ui/public/index.states.json +17 -0
- package/modules/hall-ui/public/modules.html +1 -2
- package/modules/hall-ui/public/my-projects.html +1 -2
- package/modules/hall-ui/public/not-ready.html +1 -2
- package/modules/hall-ui/public/pair.html +1 -2
- package/modules/hall-ui/public/people.html +1 -2
- package/modules/hall-ui/public/primer.html +1 -2
- package/modules/hall-ui/public/profile.html +1 -2
- package/modules/hall-ui/public/ranks.html +1 -2
- package/modules/hall-ui/public/roadmap.html +1 -2
- package/modules/hall-ui/public/scouting.html +1 -2
- package/modules/hall-ui/public/sessions.html +1 -2
- package/modules/hall-ui/public/settings.html +1 -2
- package/modules/hall-ui/public/shell.js +35 -2
- package/modules/hall-ui/public/style.css +1023 -455
- package/modules/hall-ui/public/task.html +1 -2
- package/modules/hall-ui/public/watch.css +1 -1
- package/modules/hall-ui/public/watch.html +1 -2
- package/modules/hall-ui/public/work.css +226 -100
- package/modules/hall-ui/public/work.html +15 -4
- package/modules/hall-ui/public/work.js +1 -1
- package/modules/hall-ui/public/work.states.json +19 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +1 -1
- package/tests/hall_board_world.mjs +153 -0
- package/tests/hall_tokens.mjs +371 -0
|
@@ -1,132 +1,323 @@
|
|
|
1
|
-
/* builders hall — the vanilla Cloud Bongos dashboard shell (task 1723)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
/* builders hall — the vanilla Cloud Bongos dashboard shell (task 1723), rebuilt
|
|
2
|
+
into the chrome world by task 1003303 (goal 1000081).
|
|
3
|
+
|
|
4
|
+
THE WORLD. DESIGN.md at the repo root is this surface's world; the tier below
|
|
5
|
+
is its "Reuse: the hall and the status ledger" recipe followed literally, and
|
|
6
|
+
it is the tier the composition round authored and verified as
|
|
7
|
+
docs/design/mocks/hall/_tokens.css (task 1003302). The round's pick is v3
|
|
8
|
+
"the glass hall" — a 64px rail at every width, glass chrome, content on
|
|
9
|
+
--bg-card panels at the full radius with tone doing the separation. Record:
|
|
10
|
+
docs/design/hall-direction-v2.md.
|
|
11
|
+
|
|
12
|
+
THEMING CONTRACT (do not rename): the 13 color vars + 2 font vars at the head
|
|
13
|
+
of :root are the instance-pack API — serve-internal.js themeMarkup()
|
|
14
|
+
re-declares exactly these from config/branding.*.json AFTER this file, so an
|
|
15
|
+
instance's palette/fonts win. Their values here are branding.neutral.json's
|
|
16
|
+
theme.ui, byte for byte, so the served page and this sheet agree. Everything
|
|
17
|
+
else derives from them (var / color-mix), so any pack reskins the whole kit.
|
|
18
|
+
|
|
19
|
+
FOUR THINGS THIS TIER DOES THAT world.css DOES NOT, each a hall problem the
|
|
20
|
+
landing never had:
|
|
21
|
+
|
|
22
|
+
a. THE STATUS VOCABULARY IS FIXED, AND IT IS THE ONE SANCTIONED EXCEPTION TO
|
|
23
|
+
THE FIFTEEN RULE. DESIGN.md §Reuse: a surface that renders VERIFICATION
|
|
24
|
+
state — the hall's chips, CI marks — keeps its own green/amber/red and
|
|
25
|
+
must not adopt the world's warm accent-derived ok/warn/err. A grade that
|
|
26
|
+
failed must not be salmon on a page whose claim button is also salmon.
|
|
27
|
+
Three of the four values MOVED, and that is a measurement, not a taste:
|
|
28
|
+
the shipped values were tuned against the hall's retired ground
|
|
29
|
+
(--bg #f5f6f8), and against the world's darker paper (--bg #edecee) they
|
|
30
|
+
fail AA — ok 4.27:1, warn 4.13:1, info 3.85:1 and 4.36:1, and 4.19:1 on
|
|
31
|
+
the dark card. Re-solved here so all eight pairs clear 4.5:1 on both
|
|
32
|
+
grounds in both modes with ~9% of headroom. tests/hall_tokens.mjs measures
|
|
33
|
+
them; do not hand-tune one without re-running it.
|
|
34
|
+
|
|
35
|
+
b. THE HALL KEEPS BOTH MODES, ON ITS OWN SWITCH. The apex went dark only
|
|
36
|
+
(ADR 0204), so light is the hall's alone. shell.js writes
|
|
37
|
+
html[data-theme] — NOT the world's html[data-mode] — so the dark tier is
|
|
38
|
+
written twice on THAT pair: html[data-theme="dark"] and, for first paint
|
|
39
|
+
before the script runs, @media (prefers-color-scheme: dark)
|
|
40
|
+
html:not([data-theme]). Both bodies are byte-identical; the twins rule is
|
|
41
|
+
what keeps them so. html[data-theme="dark"] is (0,1,1) and outranks the
|
|
42
|
+
pack's injected :root (0,1,0), which is what lets dark win over the pack
|
|
43
|
+
while the instance's accent survives.
|
|
44
|
+
|
|
45
|
+
c. --line IS A WIDTH HERE, NOT A COLOUR (DESIGN.md warns about exactly this
|
|
46
|
+
name). The hairline's COLOUR is --rule / --rule-soft.
|
|
47
|
+
|
|
48
|
+
d. THE COMPAT ALIASES ARE LOAD-BEARING. ~450 rules across 20 page sheets
|
|
49
|
+
derive from --surface / --surface-2 / --border / --border-strong /
|
|
50
|
+
--accent-weak / --accent-text, so they are re-derived in the world's terms
|
|
51
|
+
rather than deleted: a page this task does not re-skin degrades into the
|
|
52
|
+
new palette instead of breaking. They retire page family by page family as
|
|
53
|
+
tasks 1003304-1003308 land.
|
|
54
|
+
|
|
55
|
+
Composition — rail/drawer breakpoints, panel padding, page layout — is NOT in
|
|
56
|
+
here. It lives on the shell rules below and on a page's own body, because a
|
|
57
|
+
body declaration beats an inherited :root value at every width and a token
|
|
58
|
+
tier that carries a breakpoint silently defeats its own media query. */
|
|
11
59
|
|
|
12
60
|
:root {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
--bg
|
|
17
|
-
--bg-
|
|
18
|
-
|
|
19
|
-
--
|
|
20
|
-
--ink
|
|
21
|
-
--ink-
|
|
22
|
-
--
|
|
23
|
-
--rule
|
|
24
|
-
--
|
|
25
|
-
--accent
|
|
26
|
-
--
|
|
27
|
-
--
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
--font-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
--
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
--
|
|
42
|
-
--
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
color-scheme: light;
|
|
62
|
+
|
|
63
|
+
/* ---- the contract tier: the thirteen colours + two faces a pack overrides ---- */
|
|
64
|
+
--bg: #edecee;
|
|
65
|
+
--bg-card: #fbfafc;
|
|
66
|
+
--bg-deep: #e2e1e4;
|
|
67
|
+
--bg-frame: #f6f5f7;
|
|
68
|
+
--ink: #17181a;
|
|
69
|
+
--ink-soft: #55565a;
|
|
70
|
+
--ink-faint: #65656a;
|
|
71
|
+
--rule: #c6c6c8;
|
|
72
|
+
--rule-soft: #dcdbdd;
|
|
73
|
+
--accent: #fb9569;
|
|
74
|
+
--accent-deep: #a3481a;
|
|
75
|
+
--sea: #5b6fd0;
|
|
76
|
+
--terracotta: #c9512c;
|
|
77
|
+
|
|
78
|
+
--font-display: "Manrope", "Segoe UI", system-ui, -apple-system, sans-serif;
|
|
79
|
+
--font-body: "Manrope", "Segoe UI", system-ui, -apple-system, sans-serif;
|
|
80
|
+
|
|
81
|
+
/* ---- derived: the third face. Mono is where the hall quotes the machine —
|
|
82
|
+
task ids, column heads, eyebrows, a credit figure's unit. ---- */
|
|
83
|
+
--font-mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
|
|
84
|
+
|
|
85
|
+
/* ---- derived: glass. The blur is a token because light glass over paper is
|
|
86
|
+
a tint, not a frost — light sets it to 0px and stays paper. ---- */
|
|
87
|
+
--glass: rgba(23, 24, 26, .05);
|
|
88
|
+
--glass-strong: rgba(23, 24, 26, .08);
|
|
89
|
+
--glass-edge: rgba(23, 24, 26, .12);
|
|
90
|
+
--glass-blur: 0px;
|
|
91
|
+
|
|
92
|
+
/* ---- derived: the void. The hall has no hero; the void is what a control
|
|
93
|
+
needs when it sits over a plate, and the seam for one. ---- */
|
|
94
|
+
--void: #050508;
|
|
95
|
+
--void-ink: #ffffff;
|
|
96
|
+
--void-edge: rgba(23, 24, 26, .12);
|
|
97
|
+
|
|
98
|
+
/* ---- derived: the skeleton tone. --bg-deep is the obvious choice and it is
|
|
99
|
+
WRONG: DESIGN.md collapses deep back to black in dark, so --bg-deep
|
|
100
|
+
and --bg are the same value there and a skeleton painted with it is
|
|
101
|
+
invisible. This mix reads in both modes and needs no dark twin,
|
|
102
|
+
because both of its terms already flip. ---- */
|
|
103
|
+
--skeleton: color-mix(in srgb, var(--ink) 10%, var(--bg-card));
|
|
104
|
+
|
|
105
|
+
/* ---- derived: the reading measure. A `ch` is the width of the font's ZERO
|
|
106
|
+
glyph, not a character, and Manrope's zero is much wider than its
|
|
107
|
+
average lowercase — primer.css's `max-width: 72ch` renders about 90
|
|
108
|
+
characters under a comment claiming 60-72. This token is MEASURED:
|
|
109
|
+
48ch renders ~60 characters at the hall's body size. Re-measure rather
|
|
110
|
+
than doing the ch maths. ---- */
|
|
111
|
+
--measure: 48ch;
|
|
112
|
+
|
|
113
|
+
/* ---- derived: accent behaviours. The One Warm Thing Rule holds in the hall
|
|
114
|
+
too — the accent lights only what is pressable or live (the claim
|
|
115
|
+
button, the current nav item, the active tab, a focus ring). A credit
|
|
116
|
+
figure is data, not live, so it is ink. --accent-on is the DARK ink
|
|
117
|
+
that goes on an accent fill: white on this salmon fails AA. ---- */
|
|
118
|
+
--accent-ink: color-mix(in srgb, var(--accent) 45%, #240e00);
|
|
119
|
+
--accent-lift: color-mix(in srgb, var(--accent) 58%, #ffffff);
|
|
120
|
+
--accent-tint: color-mix(in srgb, var(--accent) 30%, #fffdf9);
|
|
121
|
+
--accent-on: #2a1305;
|
|
122
|
+
--accent-glow: 0 0 0 0 transparent;
|
|
123
|
+
|
|
124
|
+
/* ---- the status vocabulary: fixed, not pack-driven, not accent-derived.
|
|
125
|
+
See note (a) — these values are measured, not chosen. ---- */
|
|
126
|
+
--ok: #187444;
|
|
127
|
+
--ok-weak: color-mix(in srgb, #187444 12%, var(--bg-card));
|
|
128
|
+
--warn: #895c00;
|
|
129
|
+
--warn-weak: color-mix(in srgb, #895c00 14%, var(--bg-card));
|
|
45
130
|
--danger: #b42318;
|
|
46
131
|
--danger-weak: color-mix(in srgb, #b42318 10%, var(--bg-card));
|
|
47
|
-
--info
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
--
|
|
57
|
-
--
|
|
58
|
-
|
|
59
|
-
/*
|
|
132
|
+
/* --info is the one state that is NOT a bright colour, because it derives
|
|
133
|
+
from the contract's --sea rather than a chosen hex, and that makes its
|
|
134
|
+
own weak fill the binding pair rather than the grounds. The round
|
|
135
|
+
measured info against --bg and --bg-card only; measured against
|
|
136
|
+
--info-weak too (tests/hall_tokens.mjs), dark's 91% sea fell to 4.12:1,
|
|
137
|
+
so dark lightens to 80% for 5.00:1 with the ~9% headroom the rest of
|
|
138
|
+
the vocabulary holds. Both weak fills mix the STATE colour into the
|
|
139
|
+
card, which is the shape ok/warn/danger already use — mixing the raw
|
|
140
|
+
--sea instead is what made the two drift apart. ---- */
|
|
141
|
+
--info: color-mix(in srgb, var(--sea) 86%, #000000);
|
|
142
|
+
--info-weak: color-mix(in srgb, var(--info) 9%, var(--bg-card));
|
|
143
|
+
|
|
144
|
+
/* ---- derived: focus. The world's two-tone ring — a 2px accent-derived
|
|
145
|
+
outline at 3px offset inside an 8px --bg halo, so the indicator keeps
|
|
146
|
+
its own edge over whatever it lands on. ---- */
|
|
147
|
+
--focus: color-mix(in srgb, var(--accent-deep) 82%, #3a1400);
|
|
148
|
+
|
|
149
|
+
/* ---- derived: the label face flips. Mono caps read as precise on paper and
|
|
150
|
+
thin on black, so light takes the mono and dark takes the body face.
|
|
151
|
+
Take the token, never the family. ---- */
|
|
152
|
+
--label-face: var(--font-mono);
|
|
153
|
+
--label-size: 11px;
|
|
154
|
+
--label-space: .12em;
|
|
155
|
+
--label-case: uppercase;
|
|
156
|
+
|
|
157
|
+
/* ---- derived: the type halo. Only type over a plate needs one, and in light
|
|
158
|
+
there is nothing behind it. Never a coloured glow. ---- */
|
|
159
|
+
--type-halo: none;
|
|
160
|
+
|
|
161
|
+
/* ---- structure. --line is a WIDTH (note c). ---- */
|
|
162
|
+
--line: 1px;
|
|
163
|
+
--radius: 16px;
|
|
164
|
+
--radius-sm: 10px;
|
|
165
|
+
--radius-pill: 999px;
|
|
166
|
+
|
|
167
|
+
/* ---- the shell's metrics. --topbar-h stays under the kit's 80px top-bar
|
|
168
|
+
floor; --sidebar-w IS the rail, because v3 pins the rail at every
|
|
169
|
+
width and the drawer is the phone's disclosure. ---- */
|
|
170
|
+
--top-h: 56px;
|
|
171
|
+
--topbar-h: 56px;
|
|
172
|
+
--sidebar-w-rail: 64px;
|
|
173
|
+
--sidebar-w: var(--sidebar-w-rail);
|
|
174
|
+
--rail-open: 246px;
|
|
175
|
+
--content-max: 1120px;
|
|
176
|
+
|
|
177
|
+
/* ---- spacing: DESIGN.md's rhythm (6/10/14/22/34/52). The four-step
|
|
178
|
+
--space-* scale task 2179 named aliases onto it, so no ported rule
|
|
179
|
+
breaks; hairlines separate, padding does not. ---- */
|
|
180
|
+
--sp-hair: 6px;
|
|
181
|
+
--sp-xs: 10px;
|
|
182
|
+
--sp-sm: 14px;
|
|
183
|
+
--sp-md: 22px;
|
|
184
|
+
--sp-lg: 34px;
|
|
185
|
+
--sp-xl: 52px;
|
|
186
|
+
--space-1: var(--sp-hair);
|
|
187
|
+
--space-2: var(--sp-xs);
|
|
188
|
+
--space-3: var(--sp-sm);
|
|
189
|
+
--space-4: var(--sp-md);
|
|
190
|
+
|
|
191
|
+
/* ---- the compat aliases (note d) ---- */
|
|
192
|
+
--surface: var(--bg-card);
|
|
193
|
+
--surface-2: color-mix(in srgb, var(--ink) 5%, var(--bg-card));
|
|
194
|
+
--border: var(--rule-soft);
|
|
195
|
+
--border-strong: var(--rule);
|
|
196
|
+
--accent-weak: var(--accent-tint);
|
|
197
|
+
--accent-text: var(--accent-ink);
|
|
198
|
+
/* The world has no shadow vocabulary for UI, so this is spent only where an
|
|
199
|
+
element floats over a scrim (the phone drawer, the deep-link card). Pure
|
|
200
|
+
black with alpha is the one literal the Fifteen Rule allows, as a scrim. */
|
|
201
|
+
--shadow-pop: 0 18px 40px rgba(0, 0, 0, .28);
|
|
202
|
+
|
|
203
|
+
/* ---- z ladder — content overlays (rank tips z-50, modals z-50, toast z-100,
|
|
60
204
|
copy-toast z-1000, deeplink z-2000, diagram fullscreen z-9999) must beat
|
|
61
|
-
the chrome; the mobile drawer sits above chrome but below dialogs. */
|
|
205
|
+
the chrome; the mobile drawer sits above chrome but below dialogs. ---- */
|
|
62
206
|
--z-topbar: 30;
|
|
63
207
|
--z-sidebar: 40;
|
|
64
208
|
--z-scrim: 140;
|
|
65
209
|
--z-drawer: 150;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/* ---------- spacing scale (task 2179) ----------
|
|
69
|
-
Four steps, deliberately matching the values the sheet had already converged
|
|
70
|
-
on (a census found 6/10/16/20 dominant), so this NAMES the existing rhythm
|
|
71
|
-
rather than restyling the hall. It governs the three things that decide
|
|
72
|
-
density — card padding, card gap, section gap — and is not a mandate to
|
|
73
|
-
rewrite every inset; chip and control padding stay as authored.
|
|
74
|
-
|
|
75
|
-
Kept in its OWN block rather than added to :root above: :root is the
|
|
76
|
-
pack-driven theming contract an instance overrides, and the program's audit
|
|
77
|
-
requires it unchanged. Spacing is structure, not theme.
|
|
78
210
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
--
|
|
85
|
-
--
|
|
86
|
-
--
|
|
87
|
-
--space-4: 20px;
|
|
211
|
+
/* ---- the hall's own plate: the declared seam, deferred by the owner
|
|
212
|
+
("decide after the shell lands", 2026-08-30). The hall's plate was
|
|
213
|
+
never shot, so it resolves to none and the shell is a complete
|
|
214
|
+
composition without one — which is exactly what light does anyway.
|
|
215
|
+
Adding one later is a change to these three values, not a re-layout. */
|
|
216
|
+
--plate: none;
|
|
217
|
+
--plate-blend: lighten;
|
|
218
|
+
--plate-veil: none;
|
|
88
219
|
}
|
|
89
220
|
|
|
90
221
|
/* ---------- dark theme ----------
|
|
91
|
-
Only the NEUTRALS flip; the
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
shell.js owns the
|
|
96
|
-
|
|
222
|
+
Only the NEUTRALS and the mode-dependent derivations flip; the pack's
|
|
223
|
+
accent/sea/terracotta + fonts survive (the Unpinned Accent Rule — a dark
|
|
224
|
+
block may pin no accent literal, or a re-themed instance cannot reach dark),
|
|
225
|
+
and every color-mix on them re-derives for free. Written twice, byte-
|
|
226
|
+
identical: the [data-theme] switch shell.js owns, and the media block that
|
|
227
|
+
covers first paint for OS-dark users before the script runs. */
|
|
97
228
|
|
|
98
229
|
html[data-theme="dark"] {
|
|
99
230
|
color-scheme: dark;
|
|
100
|
-
--bg:
|
|
101
|
-
--bg-card:
|
|
102
|
-
--bg-deep:
|
|
103
|
-
--bg-frame:
|
|
104
|
-
--ink: #
|
|
105
|
-
--ink-soft: #
|
|
106
|
-
--ink-faint: #
|
|
107
|
-
--rule:
|
|
108
|
-
--rule-soft:
|
|
109
|
-
--
|
|
231
|
+
--bg: #000000;
|
|
232
|
+
--bg-card: #101012;
|
|
233
|
+
--bg-deep: #000000;
|
|
234
|
+
--bg-frame: #08080a;
|
|
235
|
+
--ink: #ffffff;
|
|
236
|
+
--ink-soft: #c0c0c0;
|
|
237
|
+
--ink-faint: #a8a8a8;
|
|
238
|
+
--rule: rgba(255, 255, 255, .16);
|
|
239
|
+
--rule-soft: rgba(255, 255, 255, .08);
|
|
240
|
+
--glass: rgba(255, 255, 255, .11);
|
|
241
|
+
--glass-strong: rgba(255, 255, 255, .17);
|
|
242
|
+
--glass-edge: rgba(255, 255, 255, .13);
|
|
243
|
+
--glass-blur: 18px;
|
|
244
|
+
--void: #000000;
|
|
245
|
+
--void-ink: var(--ink);
|
|
246
|
+
--void-edge: rgba(255, 255, 255, .16);
|
|
247
|
+
--accent-ink: var(--accent);
|
|
248
|
+
--accent-tint: color-mix(in srgb, var(--accent) 22%, #0b0a09);
|
|
249
|
+
--accent-glow: 0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
|
|
250
|
+
--ok: #4ade80;
|
|
251
|
+
--ok-weak: color-mix(in srgb, #4ade80 14%, var(--bg-card));
|
|
252
|
+
--warn: #fbbf24;
|
|
253
|
+
--warn-weak: color-mix(in srgb, #fbbf24 14%, var(--bg-card));
|
|
254
|
+
--danger: #f87171;
|
|
255
|
+
--danger-weak: color-mix(in srgb, #f87171 14%, var(--bg-card));
|
|
256
|
+
--info: color-mix(in srgb, var(--sea) 80%, #ffffff);
|
|
257
|
+
--info-weak: color-mix(in srgb, var(--info) 14%, var(--bg-card));
|
|
258
|
+
--focus: var(--accent);
|
|
259
|
+
--label-face: var(--font-body);
|
|
260
|
+
--label-size: 11.5px;
|
|
261
|
+
--label-space: .1em;
|
|
262
|
+
--type-halo: 0 2px 18px rgba(0, 0, 0, .94), 0 0 54px rgba(0, 0, 0, .72);
|
|
263
|
+
--surface-2: color-mix(in srgb, var(--ink) 6%, var(--bg-card));
|
|
264
|
+
--shadow-pop: 0 18px 40px rgba(0, 0, 0, .62);
|
|
265
|
+
--plate-veil: linear-gradient(to bottom, rgba(0, 0, 0, .82), rgba(0, 0, 0, .93));
|
|
110
266
|
}
|
|
111
267
|
html[data-theme="dark"] body { background: var(--bg); }
|
|
112
268
|
|
|
113
269
|
@media (prefers-color-scheme: dark) {
|
|
114
270
|
html:not([data-theme]) {
|
|
115
271
|
color-scheme: dark;
|
|
116
|
-
--bg:
|
|
117
|
-
--bg-card:
|
|
118
|
-
--bg-deep:
|
|
119
|
-
--bg-frame:
|
|
120
|
-
--ink: #
|
|
121
|
-
--ink-soft: #
|
|
122
|
-
--ink-faint: #
|
|
123
|
-
--rule:
|
|
124
|
-
--rule-soft:
|
|
125
|
-
--
|
|
272
|
+
--bg: #000000;
|
|
273
|
+
--bg-card: #101012;
|
|
274
|
+
--bg-deep: #000000;
|
|
275
|
+
--bg-frame: #08080a;
|
|
276
|
+
--ink: #ffffff;
|
|
277
|
+
--ink-soft: #c0c0c0;
|
|
278
|
+
--ink-faint: #a8a8a8;
|
|
279
|
+
--rule: rgba(255, 255, 255, .16);
|
|
280
|
+
--rule-soft: rgba(255, 255, 255, .08);
|
|
281
|
+
--glass: rgba(255, 255, 255, .11);
|
|
282
|
+
--glass-strong: rgba(255, 255, 255, .17);
|
|
283
|
+
--glass-edge: rgba(255, 255, 255, .13);
|
|
284
|
+
--glass-blur: 18px;
|
|
285
|
+
--void: #000000;
|
|
286
|
+
--void-ink: var(--ink);
|
|
287
|
+
--void-edge: rgba(255, 255, 255, .16);
|
|
288
|
+
--accent-ink: var(--accent);
|
|
289
|
+
--accent-tint: color-mix(in srgb, var(--accent) 22%, #0b0a09);
|
|
290
|
+
--accent-glow: 0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
|
|
291
|
+
--ok: #4ade80;
|
|
292
|
+
--ok-weak: color-mix(in srgb, #4ade80 14%, var(--bg-card));
|
|
293
|
+
--warn: #fbbf24;
|
|
294
|
+
--warn-weak: color-mix(in srgb, #fbbf24 14%, var(--bg-card));
|
|
295
|
+
--danger: #f87171;
|
|
296
|
+
--danger-weak: color-mix(in srgb, #f87171 14%, var(--bg-card));
|
|
297
|
+
--info: color-mix(in srgb, var(--sea) 80%, #ffffff);
|
|
298
|
+
--info-weak: color-mix(in srgb, var(--info) 14%, var(--bg-card));
|
|
299
|
+
--focus: var(--accent);
|
|
300
|
+
--label-face: var(--font-body);
|
|
301
|
+
--label-size: 11.5px;
|
|
302
|
+
--label-space: .1em;
|
|
303
|
+
--type-halo: 0 2px 18px rgba(0, 0, 0, .94), 0 0 54px rgba(0, 0, 0, .72);
|
|
304
|
+
--surface-2: color-mix(in srgb, var(--ink) 6%, var(--bg-card));
|
|
305
|
+
--shadow-pop: 0 18px 40px rgba(0, 0, 0, .62);
|
|
306
|
+
--plate-veil: linear-gradient(to bottom, rgba(0, 0, 0, .82), rgba(0, 0, 0, .93));
|
|
126
307
|
}
|
|
127
308
|
html:not([data-theme]) body { background: var(--bg); }
|
|
128
309
|
}
|
|
129
310
|
|
|
311
|
+
/* The Kill Switch Rule (DESIGN.md). Nothing escapes it, and no motion is
|
|
312
|
+
authored in JavaScript, because JavaScript motion escapes it. */
|
|
313
|
+
@media (prefers-reduced-motion: reduce) {
|
|
314
|
+
*, *::before, *::after {
|
|
315
|
+
animation: none !important;
|
|
316
|
+
transition: none !important;
|
|
317
|
+
scroll-behavior: auto !important;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
130
321
|
/* ---------- table of contents (task 2166) ----------
|
|
131
322
|
Section banners in file order — grep "----------" to jump:
|
|
132
323
|
tokens + dark theme (ABOVE — the theming contract; never move/rename)
|
|
@@ -158,12 +349,12 @@ html {
|
|
|
158
349
|
|
|
159
350
|
* {
|
|
160
351
|
scrollbar-width: thin;
|
|
161
|
-
scrollbar-color: var(--
|
|
352
|
+
scrollbar-color: var(--rule) transparent;
|
|
162
353
|
}
|
|
163
354
|
::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
164
355
|
::-webkit-scrollbar-track { background: transparent; }
|
|
165
356
|
::-webkit-scrollbar-thumb {
|
|
166
|
-
background: var(--
|
|
357
|
+
background: var(--rule);
|
|
167
358
|
border-radius: 5px;
|
|
168
359
|
border: 2px solid transparent;
|
|
169
360
|
background-clip: content-box;
|
|
@@ -182,33 +373,45 @@ body {
|
|
|
182
373
|
}
|
|
183
374
|
|
|
184
375
|
a {
|
|
185
|
-
color: var(--accent-
|
|
376
|
+
color: var(--accent-ink);
|
|
186
377
|
text-decoration: none;
|
|
187
378
|
}
|
|
188
|
-
a:hover { text-decoration: underline; text-underline-offset:
|
|
379
|
+
a:hover { text-decoration: underline; text-underline-offset: 3px; }
|
|
189
380
|
|
|
190
381
|
code, kbd, pre {
|
|
191
|
-
font-family:
|
|
382
|
+
font-family: var(--font-mono);
|
|
192
383
|
font-size: 0.92em;
|
|
193
384
|
}
|
|
194
385
|
|
|
386
|
+
/* The label voice. Mono in light, the body face in dark — take the token, never
|
|
387
|
+
the family (DESIGN.md, The label face flips). */
|
|
388
|
+
.lbl {
|
|
389
|
+
font-family: var(--label-face);
|
|
390
|
+
font-size: var(--label-size);
|
|
391
|
+
letter-spacing: var(--label-space);
|
|
392
|
+
text-transform: var(--label-case);
|
|
393
|
+
color: var(--ink-faint);
|
|
394
|
+
line-height: 1.2;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/* Every number the ledger produced is tabular, so a live refresh cannot reflow
|
|
398
|
+
the composition around it. */
|
|
399
|
+
.num, .tabular { font-variant-numeric: tabular-nums; }
|
|
400
|
+
|
|
195
401
|
select, input[type="text"], input[type="search"], textarea {
|
|
196
402
|
font-family: var(--font-body);
|
|
197
403
|
font-size: 14px;
|
|
198
404
|
color: var(--ink);
|
|
199
|
-
background:
|
|
200
|
-
border: 1px solid var(--
|
|
201
|
-
border-radius: var(--radius-
|
|
202
|
-
|
|
405
|
+
background: none;
|
|
406
|
+
border: 1px solid var(--rule);
|
|
407
|
+
border-radius: var(--radius-pill);
|
|
408
|
+
min-height: 30px;
|
|
409
|
+
padding: 5px 12px;
|
|
203
410
|
}
|
|
411
|
+
select:hover, input[type="text"]:hover, input[type="search"]:hover { border-color: var(--ink-faint); }
|
|
412
|
+
textarea { border-radius: var(--radius-sm); }
|
|
204
413
|
select:disabled { opacity: 0.55; cursor: not-allowed; }
|
|
205
|
-
select option { background: var(--
|
|
206
|
-
|
|
207
|
-
:focus-visible {
|
|
208
|
-
outline: 2px solid var(--accent);
|
|
209
|
-
outline-offset: 2px;
|
|
210
|
-
border-radius: 4px;
|
|
211
|
-
}
|
|
414
|
+
select option { background: var(--bg-card); color: var(--ink); }
|
|
212
415
|
|
|
213
416
|
button { font-family: var(--font-body); }
|
|
214
417
|
|
|
@@ -221,48 +424,118 @@ button { font-family: var(--font-body); }
|
|
|
221
424
|
white-space: nowrap;
|
|
222
425
|
}
|
|
223
426
|
|
|
224
|
-
/* ---------- app shell ----------
|
|
427
|
+
/* ---------- app shell ----------
|
|
428
|
+
v3 "the glass hall" (the owner's pick, 2026-08-30): the sidebar is the 64px
|
|
429
|
+
rail at EVERY width, opening on hover or focus-within over the page; the
|
|
430
|
+
topbar and sidebar are glass; content sits on --bg-card panels at the full
|
|
431
|
+
--radius with tone doing the separation and no hairline edge.
|
|
432
|
+
|
|
433
|
+
Two rules the round found the hard way and this section obeys:
|
|
434
|
+
- a rail label must LEAVE the layout, not fade to opacity 0. A faded label
|
|
435
|
+
still occupies width and pushes its own icon out of the 64px strip.
|
|
436
|
+
- the rail's breakpoints are composition, so they live here on the shell
|
|
437
|
+
rules and never in the token tier: a page that declares --sidebar-w on
|
|
438
|
+
`body` would beat an inherited :root value and silently defeat the query. */
|
|
225
439
|
|
|
226
440
|
.app { min-height: 100vh; }
|
|
227
441
|
|
|
442
|
+
/* The ground and its veil. Both are tokens; the hall's plate is not shot yet,
|
|
443
|
+
so both resolve to none in both modes and the shell is a complete composition
|
|
444
|
+
without one. Adding one later is a token change, not a re-layout. */
|
|
445
|
+
body::before {
|
|
446
|
+
content: "";
|
|
447
|
+
position: fixed;
|
|
448
|
+
inset: 0;
|
|
449
|
+
z-index: 0;
|
|
450
|
+
pointer-events: none;
|
|
451
|
+
background-image: var(--plate);
|
|
452
|
+
background-size: cover;
|
|
453
|
+
background-position: center;
|
|
454
|
+
mix-blend-mode: var(--plate-blend);
|
|
455
|
+
}
|
|
456
|
+
body::after {
|
|
457
|
+
content: "";
|
|
458
|
+
position: fixed;
|
|
459
|
+
inset: 0;
|
|
460
|
+
z-index: 0;
|
|
461
|
+
pointer-events: none;
|
|
462
|
+
background-image: var(--plate-veil);
|
|
463
|
+
}
|
|
464
|
+
|
|
228
465
|
.app-sidebar {
|
|
229
466
|
position: fixed;
|
|
230
467
|
inset: 0 auto 0 0;
|
|
231
|
-
width: var(--sidebar-w);
|
|
468
|
+
width: var(--sidebar-w-rail);
|
|
232
469
|
z-index: var(--z-sidebar);
|
|
233
470
|
display: flex;
|
|
234
471
|
flex-direction: column;
|
|
235
|
-
background: var(--
|
|
236
|
-
border-right: 1px solid var(--
|
|
472
|
+
background: var(--glass);
|
|
473
|
+
border-right: 1px solid var(--glass-edge);
|
|
474
|
+
backdrop-filter: blur(var(--glass-blur));
|
|
475
|
+
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
237
476
|
overflow: hidden;
|
|
238
477
|
}
|
|
478
|
+
/* The rail opens over the content — no transition, because the world animates
|
|
479
|
+
transform and filter only. `:focus-within` is what makes it keyboard-reachable
|
|
480
|
+
at all; without it a tab into the rail lands on unlabelled icons. */
|
|
481
|
+
.app-sidebar:hover,
|
|
482
|
+
.app-sidebar:focus-within { width: var(--rail-open); }
|
|
239
483
|
|
|
240
484
|
.app-sidebar__brand {
|
|
241
485
|
display: flex;
|
|
242
486
|
align-items: center;
|
|
487
|
+
justify-content: center;
|
|
243
488
|
min-height: var(--topbar-h);
|
|
244
|
-
padding: 0
|
|
245
|
-
border-bottom: 1px solid var(--
|
|
489
|
+
padding: 0;
|
|
490
|
+
border-bottom: 1px solid var(--glass-edge);
|
|
246
491
|
flex-shrink: 0;
|
|
247
492
|
}
|
|
493
|
+
/* The skip link — shell.js renders it as the first focusable thing in the
|
|
494
|
+
document and points it at a focusable, never-ringed <main>. Off-screen until
|
|
495
|
+
focused, then a pill in the top-left over everything. */
|
|
496
|
+
.skip {
|
|
497
|
+
position: absolute;
|
|
498
|
+
left: -9999px;
|
|
499
|
+
top: 8px;
|
|
500
|
+
z-index: 200;
|
|
501
|
+
background: var(--bg-card);
|
|
502
|
+
color: var(--ink);
|
|
503
|
+
border: 1px solid var(--rule);
|
|
504
|
+
border-radius: var(--radius-pill);
|
|
505
|
+
padding: 11px 18px;
|
|
506
|
+
font-size: 13.5px;
|
|
507
|
+
text-decoration: none;
|
|
508
|
+
}
|
|
509
|
+
.skip:focus { left: 12px; }
|
|
510
|
+
main:focus { outline: none; }
|
|
511
|
+
|
|
248
512
|
.brand-mark {
|
|
249
513
|
display: flex;
|
|
250
514
|
align-items: center;
|
|
515
|
+
justify-content: center;
|
|
251
516
|
gap: 10px;
|
|
517
|
+
/* The label leaves the layout in the closed rail, so the dot alone would be
|
|
518
|
+
an 11px target — the mark still has to clear the 24px control floor. */
|
|
519
|
+
min-width: 32px;
|
|
520
|
+
min-height: 32px;
|
|
252
521
|
font-family: var(--font-display);
|
|
253
|
-
font-weight:
|
|
522
|
+
font-weight: 500;
|
|
254
523
|
font-size: 15px;
|
|
524
|
+
letter-spacing: -0.015em;
|
|
255
525
|
color: var(--ink);
|
|
256
|
-
min-width: 0;
|
|
257
526
|
}
|
|
258
527
|
.brand-mark:hover { text-decoration: none; }
|
|
528
|
+
/* An outlined dot, not a filled one: the accent lights only what is pressable
|
|
529
|
+
or live, and a wordmark is neither. */
|
|
259
530
|
.brand-mark__dot {
|
|
260
|
-
width:
|
|
261
|
-
border-radius:
|
|
262
|
-
|
|
531
|
+
width: 11px; height: 11px;
|
|
532
|
+
border-radius: 50%;
|
|
533
|
+
border: 1px solid var(--ink);
|
|
534
|
+
background: none;
|
|
263
535
|
flex-shrink: 0;
|
|
264
536
|
}
|
|
265
537
|
.brand-mark__name {
|
|
538
|
+
display: none;
|
|
266
539
|
white-space: nowrap;
|
|
267
540
|
overflow: hidden;
|
|
268
541
|
text-overflow: ellipsis;
|
|
@@ -270,7 +543,7 @@ button { font-family: var(--font-body); }
|
|
|
270
543
|
|
|
271
544
|
.app-sidebar__nav {
|
|
272
545
|
flex: 1;
|
|
273
|
-
padding:
|
|
546
|
+
padding: 14px 0 22px;
|
|
274
547
|
display: flex;
|
|
275
548
|
flex-direction: column;
|
|
276
549
|
gap: 2px;
|
|
@@ -290,28 +563,39 @@ button { font-family: var(--font-body); }
|
|
|
290
563
|
}
|
|
291
564
|
.nav-group { display: flex; flex-direction: column; gap: 2px; }
|
|
292
565
|
.nav-group + .nav-group { margin-top: 14px; }
|
|
566
|
+
/* task 1003303: the items live in their own wrapper so the group head can carry
|
|
567
|
+
aria-controls (the frozen markup had aria-expanded pointing at nothing, which
|
|
568
|
+
fails the disclosure rule). The class deliberately does NOT start with
|
|
569
|
+
"nav-group" — tests/hall_nav.mjs splits the sidebar on that string to find
|
|
570
|
+
groups, and a wrapper that matched it would parse as a phantom sixth group. */
|
|
571
|
+
.nav-items { display: flex; flex-direction: column; gap: 2px; }
|
|
293
572
|
.nav-group__head {
|
|
294
|
-
|
|
295
|
-
font-weight: 600;
|
|
296
|
-
letter-spacing: 0.06em;
|
|
297
|
-
text-transform: uppercase;
|
|
298
|
-
color: var(--ink-faint);
|
|
299
|
-
padding: 4px 10px 2px;
|
|
300
|
-
}
|
|
301
|
-
.nav-group--collapsible .nav-group__head {
|
|
302
|
-
display: flex;
|
|
573
|
+
display: none;
|
|
303
574
|
align-items: center;
|
|
304
575
|
justify-content: space-between;
|
|
576
|
+
gap: 8px;
|
|
305
577
|
width: 100%;
|
|
578
|
+
min-height: 26px;
|
|
579
|
+
padding: 8px 22px 4px;
|
|
580
|
+
text-align: left;
|
|
306
581
|
background: none;
|
|
307
582
|
border: none;
|
|
308
583
|
cursor: pointer;
|
|
309
584
|
}
|
|
310
|
-
.nav-
|
|
585
|
+
.nav-group__head-label {
|
|
586
|
+
font-family: var(--label-face);
|
|
587
|
+
font-size: var(--label-size);
|
|
588
|
+
letter-spacing: var(--label-space);
|
|
589
|
+
text-transform: var(--label-case);
|
|
590
|
+
color: var(--ink-faint);
|
|
591
|
+
}
|
|
592
|
+
.nav-group--collapsible .nav-group__head:hover .nav-group__head-label { color: var(--ink-soft); }
|
|
311
593
|
.nav-group__chevron {
|
|
312
|
-
width:
|
|
313
|
-
height:
|
|
594
|
+
width: 10px;
|
|
595
|
+
height: 6px;
|
|
314
596
|
flex-shrink: 0;
|
|
597
|
+
stroke: currentColor;
|
|
598
|
+
color: var(--ink-faint);
|
|
315
599
|
transition: transform 0.15s ease;
|
|
316
600
|
}
|
|
317
601
|
.nav-group--collapsed .nav-group__chevron { transform: rotate(-90deg); }
|
|
@@ -321,42 +605,47 @@ button { font-family: var(--font-body); }
|
|
|
321
605
|
position: relative;
|
|
322
606
|
display: flex;
|
|
323
607
|
align-items: center;
|
|
608
|
+
justify-content: center;
|
|
324
609
|
gap: 10px;
|
|
325
|
-
height:
|
|
326
|
-
|
|
610
|
+
min-height: 40px;
|
|
611
|
+
margin: 0 8px;
|
|
612
|
+
padding: 0;
|
|
327
613
|
border-radius: var(--radius-sm);
|
|
328
614
|
color: var(--ink-soft);
|
|
329
|
-
font-weight: 500;
|
|
330
615
|
font-size: 14px;
|
|
616
|
+
text-transform: lowercase;
|
|
331
617
|
white-space: nowrap;
|
|
332
618
|
}
|
|
333
|
-
.nav-item:hover { background: var(--
|
|
334
|
-
.nav-item--active {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
619
|
+
.nav-item:hover { background: var(--glass); color: var(--ink); text-decoration: none; }
|
|
620
|
+
.nav-item--active { background: var(--glass-strong); color: var(--ink); }
|
|
621
|
+
/* The current item is the one live thing in the rail, so it takes the accent —
|
|
622
|
+
the lifecycle rail's lit-step grammar, one 2px bar on the leading edge. */
|
|
338
623
|
.nav-item--active::before {
|
|
339
624
|
content: "";
|
|
340
625
|
position: absolute;
|
|
341
|
-
left:
|
|
342
|
-
width:
|
|
343
|
-
border-radius:
|
|
626
|
+
left: 0; top: 8px; bottom: 8px;
|
|
627
|
+
width: 2px;
|
|
628
|
+
border-radius: 1px;
|
|
344
629
|
background: var(--accent);
|
|
345
630
|
}
|
|
346
|
-
.nav-
|
|
631
|
+
.nav-item__label { display: none; font-size: 14px; }
|
|
632
|
+
.nav-icon { width: 16px; height: 16px; flex-shrink: 0; }
|
|
347
633
|
|
|
348
634
|
.app-sidebar__foot {
|
|
349
|
-
padding:
|
|
350
|
-
border-top: 1px solid var(--
|
|
635
|
+
padding: 10px 0;
|
|
636
|
+
border-top: 1px solid var(--glass-edge);
|
|
351
637
|
display: flex;
|
|
352
638
|
flex-direction: column;
|
|
639
|
+
align-items: center;
|
|
353
640
|
gap: 8px;
|
|
354
641
|
flex-shrink: 0;
|
|
355
642
|
}
|
|
356
643
|
.shell-user {
|
|
357
644
|
display: flex;
|
|
358
645
|
align-items: center;
|
|
646
|
+
justify-content: center;
|
|
359
647
|
gap: 10px;
|
|
648
|
+
min-height: 36px;
|
|
360
649
|
padding: 4px 6px;
|
|
361
650
|
min-width: 0;
|
|
362
651
|
/* task 1831: the chip is now an <a> to /settings — strip link chrome, keep the
|
|
@@ -366,15 +655,15 @@ button { font-family: var(--font-body); }
|
|
|
366
655
|
border-radius: var(--radius-sm);
|
|
367
656
|
cursor: pointer;
|
|
368
657
|
}
|
|
369
|
-
.shell-user:hover { background: var(--
|
|
370
|
-
.shell-user:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
658
|
+
.shell-user:hover { background: var(--glass); text-decoration: none; }
|
|
371
659
|
.shell-user__avatar {
|
|
372
|
-
width:
|
|
660
|
+
width: 26px; height: 26px;
|
|
373
661
|
border-radius: 50%;
|
|
374
|
-
background: var(--
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
font-
|
|
662
|
+
background: var(--surface-2);
|
|
663
|
+
border: 1px solid var(--rule);
|
|
664
|
+
color: var(--ink-soft);
|
|
665
|
+
font-size: 11px;
|
|
666
|
+
font-weight: 500;
|
|
378
667
|
display: flex;
|
|
379
668
|
align-items: center;
|
|
380
669
|
justify-content: center;
|
|
@@ -382,43 +671,75 @@ button { font-family: var(--font-body); }
|
|
|
382
671
|
flex-shrink: 0;
|
|
383
672
|
}
|
|
384
673
|
.shell-user__avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
|
|
385
|
-
.shell-user__meta { display:
|
|
674
|
+
.shell-user__meta { display: none; flex-direction: column; min-width: 0; line-height: 1.3; }
|
|
386
675
|
.shell-user__name {
|
|
387
|
-
font-size:
|
|
388
|
-
font-weight: 600;
|
|
676
|
+
font-size: 13.5px;
|
|
389
677
|
white-space: nowrap;
|
|
390
678
|
overflow: hidden;
|
|
391
679
|
text-overflow: ellipsis;
|
|
392
680
|
}
|
|
393
|
-
.shell-user__rank {
|
|
681
|
+
.shell-user__rank {
|
|
682
|
+
font-family: var(--label-face);
|
|
683
|
+
font-size: 10.5px;
|
|
684
|
+
letter-spacing: var(--label-space);
|
|
685
|
+
text-transform: var(--label-case);
|
|
686
|
+
color: var(--ink-faint);
|
|
687
|
+
}
|
|
394
688
|
.shell-signin,
|
|
395
689
|
.shell-home,
|
|
396
690
|
.shell-signout {
|
|
397
691
|
display: flex;
|
|
398
692
|
align-items: center;
|
|
693
|
+
justify-content: center;
|
|
399
694
|
gap: 10px;
|
|
400
|
-
height:
|
|
401
|
-
padding: 0
|
|
695
|
+
min-height: 32px;
|
|
696
|
+
padding: 0 8px;
|
|
402
697
|
border-radius: var(--radius-sm);
|
|
403
698
|
font-size: 13.5px;
|
|
404
|
-
|
|
405
|
-
color: var(--ink-soft);
|
|
699
|
+
color: var(--ink-faint);
|
|
406
700
|
}
|
|
407
701
|
.shell-home { text-decoration: none; }
|
|
408
702
|
.shell-signin {
|
|
409
|
-
justify-content: center;
|
|
410
703
|
background: var(--accent);
|
|
411
|
-
color:
|
|
704
|
+
color: var(--accent-on);
|
|
705
|
+
border-radius: var(--radius-pill);
|
|
706
|
+
font-weight: 500;
|
|
707
|
+
min-height: 34px;
|
|
412
708
|
}
|
|
413
|
-
.shell-signin:hover { background: var(--accent-
|
|
709
|
+
.shell-signin:hover { background: var(--accent-lift); color: var(--accent-on); text-decoration: none; }
|
|
414
710
|
.shell-home:hover,
|
|
415
|
-
.shell-signout:hover { background: var(--
|
|
711
|
+
.shell-signout:hover { background: var(--glass); color: var(--ink); text-decoration: none; }
|
|
712
|
+
|
|
713
|
+
/* ---- the rail, open. Labels LEAVE the layout when closed and come back here;
|
|
714
|
+
the icon strip is what stays either way. ---- */
|
|
715
|
+
.app-sidebar:hover .brand-mark__name,
|
|
716
|
+
.app-sidebar:focus-within .brand-mark__name,
|
|
717
|
+
.app-sidebar:hover .nav-item__label,
|
|
718
|
+
.app-sidebar:focus-within .nav-item__label,
|
|
719
|
+
.app-sidebar:hover .shell-user__meta,
|
|
720
|
+
.app-sidebar:focus-within .shell-user__meta { display: block; }
|
|
721
|
+
.app-sidebar:hover .nav-group--collapsible .nav-group__head,
|
|
722
|
+
.app-sidebar:focus-within .nav-group--collapsible .nav-group__head { display: flex; }
|
|
723
|
+
.app-sidebar:hover .app-sidebar__brand,
|
|
724
|
+
.app-sidebar:focus-within .app-sidebar__brand { justify-content: flex-start; padding: 0 22px; }
|
|
725
|
+
.app-sidebar:hover .nav-item,
|
|
726
|
+
.app-sidebar:focus-within .nav-item { justify-content: flex-start; padding: 0 12px; }
|
|
727
|
+
.app-sidebar:hover .app-sidebar__foot,
|
|
728
|
+
.app-sidebar:focus-within .app-sidebar__foot { align-items: stretch; padding: 12px 16px; }
|
|
729
|
+
.app-sidebar:hover .shell-user,
|
|
730
|
+
.app-sidebar:focus-within .shell-user { justify-content: flex-start; }
|
|
731
|
+
.app-sidebar:hover .shell-home,
|
|
732
|
+
.app-sidebar:focus-within .shell-home,
|
|
733
|
+
.app-sidebar:hover .shell-signout,
|
|
734
|
+
.app-sidebar:focus-within .shell-signout { justify-content: flex-start; padding: 0 10px; }
|
|
416
735
|
|
|
417
736
|
.app-body {
|
|
418
|
-
margin-left: var(--sidebar-w);
|
|
737
|
+
margin-left: var(--sidebar-w-rail);
|
|
419
738
|
min-height: 100vh;
|
|
420
739
|
display: flex;
|
|
421
740
|
flex-direction: column;
|
|
741
|
+
position: relative;
|
|
742
|
+
z-index: 1;
|
|
422
743
|
}
|
|
423
744
|
|
|
424
745
|
.app-topbar {
|
|
@@ -427,29 +748,36 @@ button { font-family: var(--font-body); }
|
|
|
427
748
|
z-index: var(--z-topbar);
|
|
428
749
|
display: flex;
|
|
429
750
|
align-items: center;
|
|
430
|
-
gap:
|
|
751
|
+
gap: 14px;
|
|
431
752
|
height: var(--topbar-h);
|
|
432
|
-
padding: 0
|
|
433
|
-
background:
|
|
434
|
-
backdrop-filter: blur(
|
|
435
|
-
|
|
753
|
+
padding: 0 22px;
|
|
754
|
+
background: var(--glass);
|
|
755
|
+
backdrop-filter: blur(var(--glass-blur));
|
|
756
|
+
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
757
|
+
border-bottom: 1px solid var(--glass-edge);
|
|
436
758
|
}
|
|
759
|
+
/* Sentence case, not a mono label: v3's own divergence, picked with it. */
|
|
437
760
|
.topbar-title {
|
|
438
761
|
margin: 0;
|
|
439
762
|
font-family: var(--font-display);
|
|
440
|
-
font-
|
|
441
|
-
font-
|
|
442
|
-
letter-spacing: -0.
|
|
763
|
+
font-weight: 300;
|
|
764
|
+
font-size: 19px;
|
|
765
|
+
letter-spacing: -0.025em;
|
|
766
|
+
text-transform: lowercase;
|
|
767
|
+
color: var(--ink);
|
|
443
768
|
}
|
|
444
769
|
.topbar-side {
|
|
445
770
|
margin-left: auto;
|
|
446
771
|
display: flex;
|
|
447
772
|
align-items: center;
|
|
448
|
-
gap:
|
|
773
|
+
gap: 8px;
|
|
449
774
|
min-width: 0;
|
|
450
775
|
}
|
|
451
776
|
.topbar-note {
|
|
452
|
-
font-
|
|
777
|
+
font-family: var(--label-face);
|
|
778
|
+
font-size: var(--label-size);
|
|
779
|
+
letter-spacing: var(--label-space);
|
|
780
|
+
text-transform: var(--label-case);
|
|
453
781
|
color: var(--ink-faint);
|
|
454
782
|
white-space: nowrap;
|
|
455
783
|
overflow: hidden;
|
|
@@ -461,17 +789,19 @@ button { font-family: var(--font-body); }
|
|
|
461
789
|
display: flex;
|
|
462
790
|
align-items: baseline;
|
|
463
791
|
gap: 12px;
|
|
464
|
-
padding: 10px
|
|
792
|
+
padding: 10px 22px;
|
|
465
793
|
font-size: 13px;
|
|
466
794
|
color: var(--warn);
|
|
467
795
|
background: var(--warn-weak);
|
|
468
|
-
border-bottom: 1px solid var(--
|
|
796
|
+
border-bottom: 1px solid var(--rule-soft);
|
|
469
797
|
}
|
|
470
798
|
.denied-notice code {
|
|
471
799
|
font-size: 12px;
|
|
472
800
|
}
|
|
473
801
|
.denied-notice__close {
|
|
474
802
|
margin-left: auto;
|
|
803
|
+
min-width: 24px;
|
|
804
|
+
min-height: 24px;
|
|
475
805
|
border: 0;
|
|
476
806
|
background: none;
|
|
477
807
|
color: inherit;
|
|
@@ -483,31 +813,32 @@ button { font-family: var(--font-body); }
|
|
|
483
813
|
display: none;
|
|
484
814
|
align-items: center;
|
|
485
815
|
justify-content: center;
|
|
486
|
-
width:
|
|
487
|
-
border:
|
|
488
|
-
border-radius: var(--radius-
|
|
489
|
-
background:
|
|
816
|
+
width: 32px; height: 32px;
|
|
817
|
+
border: 0;
|
|
818
|
+
border-radius: var(--radius-pill);
|
|
819
|
+
background: none;
|
|
490
820
|
color: var(--ink-soft);
|
|
491
821
|
cursor: pointer;
|
|
492
822
|
padding: 0;
|
|
493
823
|
}
|
|
494
|
-
.topbar-menu
|
|
824
|
+
.topbar-menu:hover { color: var(--ink); }
|
|
825
|
+
.topbar-menu svg { width: 16px; height: 16px; }
|
|
495
826
|
|
|
496
827
|
.theme-toggle {
|
|
497
828
|
display: inline-flex;
|
|
498
829
|
align-items: center;
|
|
499
830
|
justify-content: center;
|
|
500
831
|
width: 32px; height: 32px;
|
|
501
|
-
border:
|
|
502
|
-
border-radius: var(--radius-
|
|
503
|
-
background:
|
|
832
|
+
border: 0;
|
|
833
|
+
border-radius: var(--radius-pill);
|
|
834
|
+
background: none;
|
|
504
835
|
color: var(--ink-soft);
|
|
505
836
|
cursor: pointer;
|
|
506
837
|
padding: 0;
|
|
507
838
|
flex-shrink: 0;
|
|
508
839
|
}
|
|
509
|
-
.theme-toggle:hover {
|
|
510
|
-
.theme-toggle svg { width:
|
|
840
|
+
.theme-toggle:hover { color: var(--ink); }
|
|
841
|
+
.theme-toggle svg { width: 16px; height: 16px; }
|
|
511
842
|
|
|
512
843
|
/* task 1475: the accessibility zoom control — sibling of the theme toggle.
|
|
513
844
|
Widens to fit the "125%"/"150%" label when zoom is active. */
|
|
@@ -518,24 +849,24 @@ button { font-family: var(--font-body); }
|
|
|
518
849
|
gap: 4px;
|
|
519
850
|
min-width: 32px; height: 32px;
|
|
520
851
|
padding: 0 8px;
|
|
521
|
-
border:
|
|
522
|
-
border-radius: var(--radius-
|
|
523
|
-
background:
|
|
852
|
+
border: 0;
|
|
853
|
+
border-radius: var(--radius-pill);
|
|
854
|
+
background: none;
|
|
524
855
|
color: var(--ink-soft);
|
|
525
856
|
cursor: pointer;
|
|
526
857
|
flex-shrink: 0;
|
|
527
858
|
}
|
|
528
|
-
.zoom-toggle:hover {
|
|
529
|
-
.zoom-toggle svg { width:
|
|
530
|
-
/* Active (zoomed-in) state reads as "on"
|
|
859
|
+
.zoom-toggle:hover { color: var(--ink); }
|
|
860
|
+
.zoom-toggle svg { width: 16px; height: 16px; }
|
|
861
|
+
/* Active (zoomed-in) state reads as "on" — the accent, because a live control
|
|
862
|
+
is exactly what the accent is for. */
|
|
531
863
|
.zoom-toggle--on {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
color: var(--accent-text);
|
|
864
|
+
background: var(--accent-tint);
|
|
865
|
+
color: var(--accent-ink);
|
|
535
866
|
}
|
|
536
867
|
.zoom-toggle__pct {
|
|
537
868
|
font-size: 12px;
|
|
538
|
-
font-weight:
|
|
869
|
+
font-weight: 500;
|
|
539
870
|
font-variant-numeric: tabular-nums;
|
|
540
871
|
line-height: 1;
|
|
541
872
|
}
|
|
@@ -544,15 +875,15 @@ button { font-family: var(--font-body); }
|
|
|
544
875
|
width: 100%;
|
|
545
876
|
max-width: calc(var(--content-max) + 64px);
|
|
546
877
|
margin: 0 auto;
|
|
547
|
-
padding:
|
|
878
|
+
padding: 26px 22px 108px;
|
|
548
879
|
flex: 1;
|
|
549
880
|
}
|
|
550
881
|
|
|
551
|
-
.app-views .view > .view-zone + .view-zone { margin-top: var(--
|
|
882
|
+
.app-views .view > .view-zone + .view-zone { margin-top: var(--sp-md); }
|
|
552
883
|
.view-zone--band {
|
|
553
884
|
display: grid;
|
|
554
885
|
grid-template-columns: 1fr 1fr;
|
|
555
|
-
gap: var(--
|
|
886
|
+
gap: var(--sp-md);
|
|
556
887
|
align-items: start;
|
|
557
888
|
}
|
|
558
889
|
.view-zone--band > .scroll { margin: 0; }
|
|
@@ -564,11 +895,13 @@ button { font-family: var(--font-body); }
|
|
|
564
895
|
gap: 12px;
|
|
565
896
|
padding: 18px 4px 0;
|
|
566
897
|
margin-top: 24px;
|
|
567
|
-
border-top: 1px solid var(--
|
|
898
|
+
border-top: 1px solid var(--rule-soft);
|
|
568
899
|
font-size: 12.5px;
|
|
569
900
|
color: var(--ink-faint);
|
|
570
901
|
}
|
|
571
|
-
|
|
902
|
+
/* 3px of vertical padding so a link in a row with no rhythm of its own still
|
|
903
|
+
clears the 24px control floor (DESIGN.md §The footer). */
|
|
904
|
+
.app-foot a { color: var(--ink-faint); display: inline-block; padding: 3px 0; min-height: 24px; }
|
|
572
905
|
.app-foot a:hover { color: var(--ink); }
|
|
573
906
|
.app-foot span { margin-right: auto; }
|
|
574
907
|
|
|
@@ -576,54 +909,67 @@ button { font-family: var(--font-body); }
|
|
|
576
909
|
position: fixed;
|
|
577
910
|
inset: 0;
|
|
578
911
|
z-index: var(--z-scrim);
|
|
579
|
-
background:
|
|
912
|
+
background: rgba(0, 0, 0, .55);
|
|
580
913
|
}
|
|
581
914
|
|
|
582
|
-
/*
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
915
|
+
/* Focus: the world's two-tone ring — a 2px accent-derived outline at 3px offset
|
|
916
|
+
inside an 8px --bg halo, so the indicator keeps its own edge over whatever it
|
|
917
|
+
lands on (a bare outline measured 1.1:1 over the light bar). The rail's items
|
|
918
|
+
ring inside themselves instead, or the halo would spill out of the 64px strip. */
|
|
919
|
+
:focus-visible {
|
|
920
|
+
outline: 2px solid var(--focus);
|
|
921
|
+
outline-offset: 3px;
|
|
922
|
+
box-shadow: 0 0 0 8px var(--bg);
|
|
923
|
+
border-radius: var(--radius-sm);
|
|
924
|
+
}
|
|
925
|
+
.nav-item:focus-visible,
|
|
926
|
+
.shell-user:focus-visible,
|
|
927
|
+
.shell-home:focus-visible,
|
|
928
|
+
.shell-signout:focus-visible {
|
|
929
|
+
outline-offset: -2px;
|
|
930
|
+
box-shadow: none;
|
|
596
931
|
}
|
|
597
932
|
|
|
933
|
+
/* ---------- responsive shell (scope §10) ----------
|
|
934
|
+
The rail holds at every width (v3), so there is no 1024px collapse any more.
|
|
935
|
+
What is left is the phone: under 768 the rail becomes the drawer shell.js
|
|
936
|
+
already owns, and the hamburger appears to open it. */
|
|
937
|
+
|
|
598
938
|
@media (max-width: 768px) {
|
|
599
939
|
.app-sidebar {
|
|
600
|
-
width: var(--
|
|
940
|
+
width: var(--rail-open);
|
|
601
941
|
transform: translateX(-100%);
|
|
602
942
|
transition: transform 160ms ease;
|
|
603
943
|
z-index: var(--z-drawer);
|
|
604
944
|
}
|
|
945
|
+
/* The drawer is the rail already open — the hover expansion is off, because
|
|
946
|
+
there is no hover on a phone and a drawer that needed one could not open. */
|
|
947
|
+
.app-sidebar:hover,
|
|
948
|
+
.app-sidebar:focus-within { width: var(--rail-open); }
|
|
605
949
|
html.drawer-open .app-sidebar { transform: translateX(0); box-shadow: var(--shadow-pop); }
|
|
606
950
|
.app-body { margin-left: 0; }
|
|
607
|
-
.brand-mark__name, .nav-item__label, .
|
|
608
|
-
.nav-
|
|
951
|
+
.brand-mark__name, .nav-item__label, .shell-user__meta { display: block; }
|
|
952
|
+
.nav-group--collapsible .nav-group__head { display: flex; }
|
|
953
|
+
.app-sidebar__brand { justify-content: flex-start; padding: 0 22px; }
|
|
954
|
+
.nav-item, .shell-home, .shell-signout { justify-content: flex-start; padding: 0 12px; }
|
|
955
|
+
.app-sidebar__foot { align-items: stretch; padding: 12px 16px; }
|
|
609
956
|
.shell-user { justify-content: flex-start; }
|
|
610
|
-
.shell-signin { font-size: 13.5px; padding: 0 10px; }
|
|
611
|
-
.shell-signin::after { content: none; }
|
|
612
957
|
.topbar-menu { display: flex; }
|
|
613
958
|
.topbar-note { display: none; }
|
|
614
|
-
.app-content { padding:
|
|
959
|
+
.app-content { padding: 18px 14px 48px; }
|
|
615
960
|
.view-zone--band { grid-template-columns: 1fr; }
|
|
616
961
|
}
|
|
617
962
|
|
|
618
963
|
@media (max-width: 480px) {
|
|
619
|
-
.app-content { padding: 12px
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
@media (prefers-reduced-motion: reduce) {
|
|
623
|
-
* { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
|
|
964
|
+
.app-content { padding: 14px 12px 40px; }
|
|
624
965
|
}
|
|
625
966
|
|
|
626
|
-
/* ---------- cards (the .scroll legacy name is load-bearing) ----------
|
|
967
|
+
/* ---------- cards (the .scroll legacy name is load-bearing) ----------
|
|
968
|
+
v3's panels: --bg-card at the full --radius, with TONE doing the separation
|
|
969
|
+
and no hairline edge. The world's "hairlines, not containers" rule is a
|
|
970
|
+
poster's rule; the owner's pick answers the container question for an
|
|
971
|
+
application surface with yes, and the compromise the pick makes is that a
|
|
972
|
+
panel is a tone, never a drawn box and never a shadow. */
|
|
627
973
|
|
|
628
974
|
/* The three sanctioned card levels (task 2179). Anything that looks like a card
|
|
629
975
|
is one of these — a fourth variant is a design decision, not a local override:
|
|
@@ -631,11 +977,11 @@ button { font-family: var(--font-body); }
|
|
|
631
977
|
.scroll--quiet secondary — a card INSIDE a card, or supporting detail
|
|
632
978
|
.scroll--bare none — layout-only, for stat rows and grids */
|
|
633
979
|
.scroll {
|
|
634
|
-
background: var(--
|
|
635
|
-
border: 1px solid
|
|
980
|
+
background: var(--bg-card);
|
|
981
|
+
border: 1px solid transparent;
|
|
636
982
|
border-radius: var(--radius);
|
|
637
|
-
padding: var(--
|
|
638
|
-
margin: 0 0 var(--
|
|
983
|
+
padding: var(--sp-md);
|
|
984
|
+
margin: 0 0 var(--sp-md);
|
|
639
985
|
/* anchor jumps must clear the 56px sticky top bar */
|
|
640
986
|
scroll-margin-top: calc(var(--topbar-h) + 16px);
|
|
641
987
|
}
|
|
@@ -646,88 +992,144 @@ button { font-family: var(--font-body); }
|
|
|
646
992
|
border-radius: 0;
|
|
647
993
|
padding: 0;
|
|
648
994
|
}
|
|
649
|
-
/* Secondary level:
|
|
650
|
-
|
|
995
|
+
/* Secondary level: a card inside a card recedes by tone, one step further from
|
|
996
|
+
the ground than its parent. Use for supporting detail — not to fit more onto
|
|
997
|
+
Home. */
|
|
651
998
|
.scroll--quiet {
|
|
652
999
|
background: var(--surface-2);
|
|
653
|
-
padding: var(--
|
|
1000
|
+
padding: var(--sp-sm);
|
|
654
1001
|
}
|
|
655
1002
|
.scroll--quiet > .scroll__h {
|
|
656
|
-
font-size:
|
|
1003
|
+
font-size: 14px;
|
|
657
1004
|
color: var(--ink-soft);
|
|
658
1005
|
}
|
|
659
1006
|
|
|
1007
|
+
/* Section headings take the display voice in sentence case — v3's own
|
|
1008
|
+
divergence from the mono label, picked with it. */
|
|
660
1009
|
.scroll__h {
|
|
661
|
-
margin: 0 0
|
|
1010
|
+
margin: 0 0 8px;
|
|
662
1011
|
font-family: var(--font-display);
|
|
663
|
-
font-
|
|
664
|
-
font-
|
|
665
|
-
|
|
1012
|
+
font-weight: 300;
|
|
1013
|
+
font-size: 21px;
|
|
1014
|
+
line-height: 1.15;
|
|
1015
|
+
letter-spacing: -0.03em;
|
|
1016
|
+
color: var(--ink);
|
|
1017
|
+
text-shadow: var(--type-halo);
|
|
666
1018
|
}
|
|
667
1019
|
.scroll__lede {
|
|
668
1020
|
margin: 0 0 14px;
|
|
669
1021
|
font-size: 13.5px;
|
|
670
1022
|
color: var(--ink-soft);
|
|
671
|
-
max-width:
|
|
1023
|
+
max-width: var(--measure);
|
|
672
1024
|
}
|
|
673
1025
|
.card-foot {
|
|
674
|
-
margin:
|
|
1026
|
+
margin: 14px 0 0;
|
|
675
1027
|
font-size: 13px;
|
|
676
1028
|
}
|
|
677
1029
|
|
|
1030
|
+
/* The 24px floor for links that sit in PROSE (task 1003304). A link in a lede,
|
|
1031
|
+
a card foot or a setup hint is a real control in a line with no vertical
|
|
1032
|
+
rhythm of its own, so it renders at its 17-19px line box and fails the floor
|
|
1033
|
+
— measured on Home and the board at every width in both modes ("Roadmap"
|
|
1034
|
+
59x18, "Goals page" 69x18, "View full standing" 118x18, "primer" 37x17).
|
|
1035
|
+
DESIGN.md's footer rule is the remedy: go inline-block and buy the height
|
|
1036
|
+
back with padding, which costs the line's own leading nothing.
|
|
1037
|
+
THE FLOOR IS BOTH AXES, and that is the half worth writing down — "Git" came
|
|
1038
|
+
back 17x24, still failing, because a three-letter link is genuinely narrower
|
|
1039
|
+
than 24px. The horizontal padding buys the width and the equal negative
|
|
1040
|
+
margin gives it straight back to the layout, so the target grows and the
|
|
1041
|
+
sentence does not re-space around it.
|
|
1042
|
+
It lives here rather than in each page's sheet because these classes are the
|
|
1043
|
+
shell's, and the alternative is five identical copies as 1003305-1003308
|
|
1044
|
+
land. */
|
|
1045
|
+
.scroll__lede a,
|
|
1046
|
+
.card-foot a,
|
|
1047
|
+
.next-up__foot a,
|
|
1048
|
+
.setup__steps a,
|
|
1049
|
+
.setup__hint a,
|
|
1050
|
+
.setup__foot a {
|
|
1051
|
+
display: inline-block;
|
|
1052
|
+
min-width: 24px;
|
|
1053
|
+
min-height: 24px;
|
|
1054
|
+
padding: 3px 4px;
|
|
1055
|
+
margin: 0 -4px;
|
|
1056
|
+
line-height: 18px;
|
|
1057
|
+
text-align: center;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
678
1060
|
.pill-link,
|
|
679
1061
|
#welcome-reopen a {
|
|
680
|
-
display: inline-
|
|
681
|
-
|
|
682
|
-
|
|
1062
|
+
display: inline-flex;
|
|
1063
|
+
align-items: center;
|
|
1064
|
+
min-height: 28px;
|
|
1065
|
+
font-size: 13px;
|
|
1066
|
+
text-transform: lowercase;
|
|
683
1067
|
color: var(--ink-soft);
|
|
684
|
-
background:
|
|
685
|
-
border: 1px solid var(--
|
|
686
|
-
border-radius:
|
|
687
|
-
padding:
|
|
1068
|
+
background: none;
|
|
1069
|
+
border: 1px solid var(--rule);
|
|
1070
|
+
border-radius: var(--radius-pill);
|
|
1071
|
+
padding: 0 12px;
|
|
688
1072
|
}
|
|
689
1073
|
#welcome-reopen { margin: 0; }
|
|
690
|
-
.pill-link:hover { color: var(--ink); text-decoration: none;
|
|
1074
|
+
.pill-link:hover { color: var(--ink); text-decoration: none; border-color: var(--ink-faint); }
|
|
691
1075
|
|
|
692
|
-
/* ---------- stat tiles (Home) ----------
|
|
1076
|
+
/* ---------- stat tiles (Home) ----------
|
|
1077
|
+
v3's signature: ONE glass band of figures divided by vertical hairlines, the
|
|
1078
|
+
owner's dark reference exactly, rather than four separate objects. The figure
|
|
1079
|
+
is the display face at 300 with tabular numerals — every number the ledger
|
|
1080
|
+
produced holds its column when it refreshes (DESIGN.md, The Tabular Rule). */
|
|
693
1081
|
|
|
694
1082
|
.stat-row {
|
|
695
1083
|
display: grid;
|
|
696
1084
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
697
|
-
gap:
|
|
1085
|
+
gap: 0;
|
|
1086
|
+
background: var(--glass);
|
|
1087
|
+
border: 1px solid var(--glass-edge);
|
|
1088
|
+
border-radius: var(--radius);
|
|
1089
|
+
backdrop-filter: blur(var(--glass-blur));
|
|
1090
|
+
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
1091
|
+
overflow: hidden;
|
|
698
1092
|
}
|
|
699
1093
|
.stat-tile {
|
|
700
|
-
background:
|
|
701
|
-
border:
|
|
702
|
-
border-
|
|
703
|
-
|
|
1094
|
+
background: none;
|
|
1095
|
+
border: 0;
|
|
1096
|
+
border-left: 1px solid var(--glass-edge);
|
|
1097
|
+
border-radius: 0;
|
|
1098
|
+
padding: 20px 22px;
|
|
704
1099
|
min-height: 88px;
|
|
705
1100
|
display: flex;
|
|
706
1101
|
flex-direction: column;
|
|
707
1102
|
justify-content: center;
|
|
708
|
-
gap:
|
|
1103
|
+
gap: 8px;
|
|
709
1104
|
}
|
|
1105
|
+
.stat-tile:first-child { border-left: 0; }
|
|
710
1106
|
.stat-tile__label {
|
|
711
|
-
font-
|
|
712
|
-
font-
|
|
713
|
-
letter-spacing:
|
|
714
|
-
text-transform:
|
|
1107
|
+
font-family: var(--label-face);
|
|
1108
|
+
font-size: var(--label-size);
|
|
1109
|
+
letter-spacing: var(--label-space);
|
|
1110
|
+
text-transform: var(--label-case);
|
|
715
1111
|
color: var(--ink-faint);
|
|
716
1112
|
}
|
|
717
1113
|
.stat-tile__num {
|
|
718
|
-
font-
|
|
719
|
-
font-
|
|
720
|
-
|
|
1114
|
+
font-family: var(--font-display);
|
|
1115
|
+
font-size: clamp(26px, 2.6vw, 34px);
|
|
1116
|
+
font-weight: 300;
|
|
1117
|
+
letter-spacing: -0.035em;
|
|
721
1118
|
font-variant-numeric: tabular-nums;
|
|
722
|
-
line-height: 1
|
|
1119
|
+
line-height: 1;
|
|
1120
|
+
color: var(--ink);
|
|
1121
|
+
text-shadow: var(--type-halo);
|
|
723
1122
|
}
|
|
724
|
-
.stat-tile__num--badge { font-size: 15px; }
|
|
725
|
-
.stat-tile__sub { font-size:
|
|
1123
|
+
.stat-tile__num--badge { font-size: 15px; letter-spacing: -0.02em; }
|
|
1124
|
+
.stat-tile__sub { font-size: 12.5px; color: var(--ink-faint); }
|
|
726
1125
|
|
|
727
1126
|
@media (max-width: 480px) {
|
|
728
|
-
.stat-row { grid-template-columns: 1fr 1fr;
|
|
729
|
-
.stat-tile { padding:
|
|
730
|
-
.stat-tile__num { font-size: 21px; }
|
|
1127
|
+
.stat-row { grid-template-columns: 1fr 1fr; }
|
|
1128
|
+
.stat-tile { padding: 14px 16px; min-height: 72px; gap: 6px; }
|
|
1129
|
+
.stat-tile__num { font-size: clamp(21px, 6.6vw, 28px); }
|
|
1130
|
+
/* On two columns the band still divides, but now on both axes. */
|
|
1131
|
+
.stat-tile:nth-child(odd) { border-left: 0; }
|
|
1132
|
+
.stat-tile:nth-child(n + 3) { border-top: 1px solid var(--glass-edge); }
|
|
731
1133
|
}
|
|
732
1134
|
|
|
733
1135
|
/* ---------- Standing layout: section rail + panels ---------- */
|
|
@@ -746,15 +1148,28 @@ button { font-family: var(--font-body); }
|
|
|
746
1148
|
gap: 2px;
|
|
747
1149
|
}
|
|
748
1150
|
.rail-link {
|
|
749
|
-
display:
|
|
750
|
-
|
|
1151
|
+
display: flex;
|
|
1152
|
+
align-items: center;
|
|
1153
|
+
min-height: 28px;
|
|
1154
|
+
padding: 0 10px;
|
|
751
1155
|
border-radius: var(--radius-sm);
|
|
752
1156
|
font-size: 13px;
|
|
753
|
-
|
|
1157
|
+
text-transform: lowercase;
|
|
754
1158
|
color: var(--ink-soft);
|
|
1159
|
+
position: relative;
|
|
1160
|
+
}
|
|
1161
|
+
.rail-link:hover { background: var(--glass); color: var(--ink); text-decoration: none; }
|
|
1162
|
+
/* The current section is live, so it takes the accent — the same lit-step
|
|
1163
|
+
grammar the rail’s nav items use. */
|
|
1164
|
+
.rail-link--active { background: var(--glass-strong); color: var(--ink); }
|
|
1165
|
+
.rail-link--active::before {
|
|
1166
|
+
content: "";
|
|
1167
|
+
position: absolute;
|
|
1168
|
+
left: 0; top: 6px; bottom: 6px;
|
|
1169
|
+
width: 2px;
|
|
1170
|
+
border-radius: 1px;
|
|
1171
|
+
background: var(--accent);
|
|
755
1172
|
}
|
|
756
|
-
.rail-link:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
|
|
757
|
-
.rail-link--active { background: var(--accent-weak); color: var(--accent-text); }
|
|
758
1173
|
|
|
759
1174
|
/* task 2174: a Standing rail section — the scroll-spy anchor holding one or
|
|
760
1175
|
more cards. The extra air between groups is what makes the grouping legible
|
|
@@ -772,11 +1187,11 @@ button { font-family: var(--font-body); }
|
|
|
772
1187
|
overflow-x: auto;
|
|
773
1188
|
gap: 6px;
|
|
774
1189
|
padding: 8px 0;
|
|
775
|
-
background:
|
|
776
|
-
backdrop-filter: blur(6px);
|
|
1190
|
+
background: var(--bg);
|
|
777
1191
|
}
|
|
778
|
-
.rail-link { white-space: nowrap; border: 1px solid var(--
|
|
779
|
-
.rail-link--active { border-color:
|
|
1192
|
+
.rail-link { white-space: nowrap; border: 1px solid var(--rule); background: none; border-radius: var(--radius-pill); min-height: 26px; padding: 0 12px; font-size: 12.5px; }
|
|
1193
|
+
.rail-link--active { border-color: var(--accent); background: none; }
|
|
1194
|
+
.rail-link--active::before { content: none; }
|
|
780
1195
|
}
|
|
781
1196
|
|
|
782
1197
|
/* ---------- legacy page chrome compat (pre-shell pages) ---------- */
|
|
@@ -871,28 +1286,30 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
871
1286
|
.ledger th {
|
|
872
1287
|
position: sticky;
|
|
873
1288
|
top: var(--topbar-h);
|
|
874
|
-
background: var(--
|
|
1289
|
+
background: var(--bg-card);
|
|
875
1290
|
text-align: left;
|
|
876
|
-
font-
|
|
877
|
-
font-
|
|
878
|
-
|
|
879
|
-
|
|
1291
|
+
font-family: var(--label-face);
|
|
1292
|
+
font-size: var(--label-size);
|
|
1293
|
+
font-weight: 400;
|
|
1294
|
+
letter-spacing: var(--label-space);
|
|
1295
|
+
text-transform: var(--label-case);
|
|
880
1296
|
color: var(--ink-faint);
|
|
881
|
-
padding: 8px
|
|
882
|
-
border-bottom: 1px solid var(--
|
|
1297
|
+
padding: 0 12px 8px 0;
|
|
1298
|
+
border-bottom: 1px solid var(--rule);
|
|
883
1299
|
z-index: 1;
|
|
884
1300
|
}
|
|
885
1301
|
.ledger td {
|
|
886
|
-
padding: 12px;
|
|
1302
|
+
padding: 14px 12px 14px 0;
|
|
887
1303
|
border-bottom: 1px solid var(--rule-soft);
|
|
888
1304
|
vertical-align: top;
|
|
889
1305
|
}
|
|
1306
|
+
.ledger th:last-child, .ledger td:last-child { padding-right: 0; }
|
|
890
1307
|
.ledger tr:last-child td { border-bottom: none; }
|
|
891
|
-
.ledger tbody tr:hover td { background: var(--
|
|
1308
|
+
.ledger tbody tr:hover td { background: var(--glass); }
|
|
892
1309
|
/* task 1467: a builder name that links to their profile page reads as plain
|
|
893
1310
|
text in the dense leaderboard/roster, revealing itself as a link on hover. */
|
|
894
1311
|
.lb-name { color: inherit; }
|
|
895
|
-
.lb-name:hover { color: var(--accent-
|
|
1312
|
+
.lb-name:hover { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px; }
|
|
896
1313
|
.ledger__empty {
|
|
897
1314
|
color: var(--ink-faint);
|
|
898
1315
|
font-size: 13px;
|
|
@@ -956,16 +1373,17 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
956
1373
|
.filter {
|
|
957
1374
|
display: flex;
|
|
958
1375
|
flex-direction: column;
|
|
959
|
-
gap:
|
|
960
|
-
font-
|
|
961
|
-
font-
|
|
962
|
-
letter-spacing:
|
|
963
|
-
text-transform:
|
|
1376
|
+
gap: 4px;
|
|
1377
|
+
font-family: var(--label-face);
|
|
1378
|
+
font-size: var(--label-size);
|
|
1379
|
+
letter-spacing: var(--label-space);
|
|
1380
|
+
text-transform: var(--label-case);
|
|
964
1381
|
color: var(--ink-faint);
|
|
965
1382
|
}
|
|
966
1383
|
.filter select {
|
|
967
1384
|
min-width: 150px;
|
|
968
|
-
height: 32px;
|
|
1385
|
+
min-height: 32px;
|
|
1386
|
+
font-family: var(--font-body);
|
|
969
1387
|
padding: 4px 8px;
|
|
970
1388
|
font-size: 13.5px;
|
|
971
1389
|
text-transform: none;
|
|
@@ -976,7 +1394,8 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
976
1394
|
selects it sits alongside. */
|
|
977
1395
|
.filter input[type="search"] {
|
|
978
1396
|
min-width: 200px;
|
|
979
|
-
height: 32px;
|
|
1397
|
+
min-height: 32px;
|
|
1398
|
+
font-family: var(--font-body);
|
|
980
1399
|
padding: 4px 8px;
|
|
981
1400
|
font-size: 13.5px;
|
|
982
1401
|
text-transform: none;
|
|
@@ -999,24 +1418,51 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
999
1418
|
gap: 12px;
|
|
1000
1419
|
margin-top: 12px;
|
|
1001
1420
|
}
|
|
1002
|
-
.pager__range { font-size:
|
|
1421
|
+
.pager__range { font-family: var(--font-mono); font-size: 12px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
|
|
1003
1422
|
|
|
1423
|
+
/* Pill or nothing (DESIGN.md, Shapes). A ghost button is a hairline pill; the
|
|
1424
|
+
one filled shape on a page is the accent door, and only where the action is
|
|
1425
|
+
the live thing. 28px of box plus the row’s own air clears the 24px floor. */
|
|
1004
1426
|
.btn-ghost {
|
|
1005
1427
|
display: inline-flex;
|
|
1006
1428
|
align-items: center;
|
|
1429
|
+
justify-content: center;
|
|
1007
1430
|
gap: 6px;
|
|
1008
|
-
height: 30px;
|
|
1009
|
-
|
|
1431
|
+
min-height: 30px;
|
|
1432
|
+
min-width: 56px;
|
|
1433
|
+
padding: 0 14px;
|
|
1010
1434
|
font-size: 13px;
|
|
1011
|
-
|
|
1435
|
+
text-transform: lowercase;
|
|
1012
1436
|
color: var(--ink-soft);
|
|
1013
|
-
background:
|
|
1014
|
-
border: 1px solid var(--
|
|
1015
|
-
border-radius: var(--radius-
|
|
1437
|
+
background: none;
|
|
1438
|
+
border: 1px solid var(--rule);
|
|
1439
|
+
border-radius: var(--radius-pill);
|
|
1440
|
+
cursor: pointer;
|
|
1441
|
+
}
|
|
1442
|
+
.btn-ghost:hover:not(:disabled) { border-color: var(--ink-faint); color: var(--ink); text-decoration: none; }
|
|
1443
|
+
.btn-ghost:disabled { color: var(--ink-faint); border-color: var(--rule-soft); cursor: default; }
|
|
1444
|
+
|
|
1445
|
+
/* The accent door: the page’s one primary action. --accent-on is the dark ink
|
|
1446
|
+
that goes on the salmon; white on it fails AA and is banned. */
|
|
1447
|
+
.btn-accent {
|
|
1448
|
+
display: inline-flex;
|
|
1449
|
+
align-items: center;
|
|
1450
|
+
justify-content: center;
|
|
1451
|
+
gap: 6px;
|
|
1452
|
+
min-height: 34px;
|
|
1453
|
+
min-width: 74px;
|
|
1454
|
+
padding: 0 16px;
|
|
1455
|
+
font-size: 13.5px;
|
|
1456
|
+
font-weight: 500;
|
|
1457
|
+
text-transform: lowercase;
|
|
1458
|
+
color: var(--accent-on);
|
|
1459
|
+
background: var(--accent);
|
|
1460
|
+
border: 0;
|
|
1461
|
+
border-radius: var(--radius-pill);
|
|
1016
1462
|
cursor: pointer;
|
|
1017
1463
|
}
|
|
1018
|
-
.btn-
|
|
1019
|
-
.btn-
|
|
1464
|
+
.btn-accent:hover:not(:disabled) { background: var(--accent-lift); color: var(--accent-on); text-decoration: none; }
|
|
1465
|
+
.btn-accent:disabled { background: var(--surface-2); color: var(--ink-faint); cursor: default; }
|
|
1020
1466
|
|
|
1021
1467
|
/* ---------- profile / standing ---------- */
|
|
1022
1468
|
|
|
@@ -1139,7 +1585,7 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1139
1585
|
.conn-reqs { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
|
|
1140
1586
|
.conn-req {
|
|
1141
1587
|
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
|
1142
|
-
padding: 8px 10px; border: 1px solid var(--border); border-radius:
|
|
1588
|
+
padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2);
|
|
1143
1589
|
}
|
|
1144
1590
|
.conn-req__note { flex: 1 1 100%; margin: 0; font-size: 13px; color: var(--ink-soft); }
|
|
1145
1591
|
.conn-req__state { font-size: 13px; color: var(--ink-faint); }
|
|
@@ -1153,10 +1599,14 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1153
1599
|
|
|
1154
1600
|
/* ---------- rank badges + tooltip ---------- */
|
|
1155
1601
|
|
|
1602
|
+
/* 24px, not the old 20 (task 1003304). The badge is not itself a control, but
|
|
1603
|
+
.rank-badge-stretch below covers it edge to edge and IS one — so the badge's
|
|
1604
|
+
height is the link's height, and at 20 it failed the floor on every page that
|
|
1605
|
+
renders a rank. Only the box grew; the type and the colours are untouched. */
|
|
1156
1606
|
.rank-badge {
|
|
1157
1607
|
display: inline-flex;
|
|
1158
1608
|
align-items: center;
|
|
1159
|
-
height:
|
|
1609
|
+
height: 24px;
|
|
1160
1610
|
padding: 0 9px;
|
|
1161
1611
|
border-radius: 999px;
|
|
1162
1612
|
font-size: 11.5px;
|
|
@@ -1429,25 +1879,36 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1429
1879
|
|
|
1430
1880
|
.setup { margin-top: 12px; }
|
|
1431
1881
|
.setup__intro { font-size: 13px; color: var(--ink-soft); }
|
|
1432
|
-
.setup__toggle { display:
|
|
1882
|
+
.setup__toggle { display: flex; border: 0; border-bottom: 1px solid var(--rule); margin: 8px 0 12px; flex-wrap: wrap; }
|
|
1883
|
+
/* An open tab is the live thing in the strip, so it is what the accent lights:
|
|
1884
|
+
a 2px underline sitting on the strip’s own hairline. */
|
|
1433
1885
|
.setup__tab {
|
|
1434
|
-
|
|
1435
|
-
|
|
1886
|
+
display: inline-flex;
|
|
1887
|
+
align-items: baseline;
|
|
1888
|
+
gap: 8px;
|
|
1889
|
+
min-height: 38px;
|
|
1890
|
+
border: 0;
|
|
1891
|
+
border-bottom: 2px solid transparent;
|
|
1892
|
+
margin-bottom: -1px;
|
|
1893
|
+
background: none;
|
|
1436
1894
|
color: var(--ink-soft);
|
|
1437
|
-
font-size:
|
|
1438
|
-
|
|
1439
|
-
padding:
|
|
1895
|
+
font-size: 14px;
|
|
1896
|
+
text-transform: lowercase;
|
|
1897
|
+
padding: 0 16px;
|
|
1440
1898
|
cursor: pointer;
|
|
1441
1899
|
}
|
|
1442
|
-
.setup__tab
|
|
1443
|
-
.setup__tab
|
|
1444
|
-
.setup__tab-
|
|
1445
|
-
.setup__tab-tag
|
|
1900
|
+
.setup__tab:first-child { padding-left: 0; }
|
|
1901
|
+
.setup__tab:hover { color: var(--ink); }
|
|
1902
|
+
.setup__tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }
|
|
1903
|
+
.setup__tab-tag { font-family: var(--label-face); font-size: 10.5px; letter-spacing: var(--label-space); text-transform: var(--label-case); margin-left: 6px; color: var(--ink-faint); }
|
|
1904
|
+
.setup__tab-tag--rec { color: var(--ok); }
|
|
1446
1905
|
.setup__pane { display: none; }
|
|
1447
1906
|
.setup[data-config="desktop"] .setup__pane--desktop { display: block; }
|
|
1448
1907
|
.setup[data-config="online"] .setup__pane--online { display: block; }
|
|
1449
1908
|
.setup__steps { margin: 8px 0; padding-left: 20px; font-size: 13.5px; }
|
|
1450
1909
|
.setup__steps li { margin: 6px 0; }
|
|
1910
|
+
/* The setup panel's prose links ("Git", "Claude Code", "primer") take the
|
|
1911
|
+
shared prose-link floor rule in the cards section above (task 1003304). */
|
|
1451
1912
|
.setup__steps code {
|
|
1452
1913
|
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
|
1453
1914
|
font-size: 12px;
|
|
@@ -1531,46 +1992,67 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1531
1992
|
.setup__copy:hover { background: var(--surface-2); }
|
|
1532
1993
|
.setup__copy--copied { background: var(--ok-weak); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, transparent); }
|
|
1533
1994
|
.setup__getcode { margin: 10px 0; }
|
|
1534
|
-
|
|
1995
|
+
/* A <summary> is a control, so it owes the 24px floor like any other; it
|
|
1996
|
+
measured 20px tall (task 1003304). The height is bought with padding rather
|
|
1997
|
+
than a display change, because a <summary> is display:list-item by default
|
|
1998
|
+
and flex or block would silently eat its disclosure marker. */
|
|
1999
|
+
.setup__getcode-summary {
|
|
2000
|
+
cursor: pointer;
|
|
2001
|
+
font-weight: 600;
|
|
2002
|
+
font-size: 13px;
|
|
2003
|
+
min-height: 24px;
|
|
2004
|
+
padding: 3px 0;
|
|
2005
|
+
line-height: 18px;
|
|
2006
|
+
}
|
|
1535
2007
|
.setup__getcode-lede { font-size: 12.5px; color: var(--ink-soft); }
|
|
1536
2008
|
.setup__getcode-body { margin-top: 8px; }
|
|
1537
2009
|
|
|
1538
2010
|
/* ---------- landing (signed-out) ---------- */
|
|
1539
2011
|
|
|
1540
|
-
.landing { max-width:
|
|
2012
|
+
.landing { max-width: var(--measure); }
|
|
1541
2013
|
.landing__lede { font-size: 14px; color: var(--ink-soft); }
|
|
2014
|
+
/* A link inside landing prose is still a control: 3px of vertical padding is
|
|
2015
|
+
what clears the 24px floor in a line that has no rhythm of its own
|
|
2016
|
+
(DESIGN.md §The footer applies the same rule to its links). */
|
|
2017
|
+
.landing p a:not(.landing__btn) {
|
|
2018
|
+
display: inline-block;
|
|
2019
|
+
padding: 3px 0;
|
|
2020
|
+
min-height: 24px;
|
|
2021
|
+
line-height: 18px;
|
|
2022
|
+
}
|
|
1542
2023
|
.landing__cta { margin: 14px 0; }
|
|
1543
2024
|
.landing__btn {
|
|
1544
2025
|
display: inline-flex;
|
|
1545
2026
|
align-items: center;
|
|
1546
2027
|
justify-content: center;
|
|
1547
|
-
height:
|
|
1548
|
-
padding: 0
|
|
1549
|
-
border-radius: var(--radius-
|
|
1550
|
-
border:
|
|
2028
|
+
min-height: 46px;
|
|
2029
|
+
padding: 0 22px;
|
|
2030
|
+
border-radius: var(--radius-pill);
|
|
2031
|
+
border: 0;
|
|
1551
2032
|
background: var(--accent);
|
|
1552
|
-
color:
|
|
1553
|
-
font-size:
|
|
1554
|
-
font-weight:
|
|
2033
|
+
color: var(--accent-on);
|
|
2034
|
+
font-size: 14px;
|
|
2035
|
+
font-weight: 500;
|
|
2036
|
+
text-transform: lowercase;
|
|
1555
2037
|
cursor: pointer;
|
|
1556
2038
|
}
|
|
1557
|
-
.landing__btn:hover { background: var(--accent-
|
|
2039
|
+
.landing__btn:hover { background: var(--accent-lift); text-decoration: none; color: var(--accent-on); }
|
|
1558
2040
|
.landing__note { font-size: 12.5px; color: var(--ink-faint); }
|
|
1559
2041
|
.landing__error { color: var(--danger); }
|
|
1560
2042
|
.landing__error-h { color: var(--danger); margin: 0 0 4px; font-size: 14px; }
|
|
1561
2043
|
.landing__request {
|
|
1562
|
-
border:
|
|
2044
|
+
border: 0;
|
|
1563
2045
|
border-radius: var(--radius);
|
|
1564
2046
|
background: var(--surface-2);
|
|
1565
|
-
padding:
|
|
2047
|
+
padding: 18px 20px;
|
|
1566
2048
|
margin: 16px 0;
|
|
1567
2049
|
}
|
|
1568
|
-
.landing__request-h { margin: 0 0
|
|
2050
|
+
.landing__request-h { margin: 0 0 6px; font-family: var(--font-display); font-size: 18px; font-weight: 300; letter-spacing: -0.025em; }
|
|
1569
2051
|
.landing__request-lede { margin: 0 0 12px; font-size: 13px; color: var(--ink-soft); }
|
|
1570
2052
|
.landing__request-lede--soft { color: var(--ink-faint); }
|
|
1571
2053
|
.landing__form { display: flex; flex-direction: column; gap: 10px; }
|
|
1572
|
-
.landing__field { display: flex; flex-direction: column; gap:
|
|
1573
|
-
.landing__field input {
|
|
2054
|
+
.landing__field { display: flex; flex-direction: column; gap: 4px; font-family: var(--label-face); font-size: var(--label-size); letter-spacing: var(--label-space); text-transform: var(--label-case); color: var(--ink-faint); }
|
|
2055
|
+
.landing__field input { font-family: var(--font-body); font-size: 14px; text-transform: none; letter-spacing: normal; }
|
|
1574
2056
|
.landing__req-mark { color: var(--danger); }
|
|
1575
2057
|
.landing__opt { color: var(--ink-faint); font-weight: 400; }
|
|
1576
2058
|
.landing__form-hint { font-size: 12.5px; color: var(--ink-faint); margin: 0; }
|
|
@@ -1613,32 +2095,87 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1613
2095
|
.goal-mine__ver { font-size: 12px; color: var(--ink-faint); }
|
|
1614
2096
|
.goal-mine__foot { font-size: 13px; margin: 10px 0 0; }
|
|
1615
2097
|
|
|
1616
|
-
/* ---------- work-board task cards (work page) ----------
|
|
2098
|
+
/* ---------- work-board task cards (work page) ----------
|
|
2099
|
+
Re-skinned into the chrome world by task 1003304 (goal 1000081). In v3 "the
|
|
2100
|
+
glass hall" a claimable task IS the panel — --bg-card at the full --radius,
|
|
2101
|
+
tone separating it from the ground, no drawn edge at rest — which is why
|
|
2102
|
+
#claim-scroll in work.html is .scroll--bare: a .scroll around these would be
|
|
2103
|
+
a card inside a card. The dense LISTS on the other three tabs keep their
|
|
2104
|
+
panel and take v1's bare-ledger row inside it (direction §6). */
|
|
1617
2105
|
|
|
1618
|
-
.task-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap:
|
|
2106
|
+
.task-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
|
|
1619
2107
|
.task {
|
|
1620
2108
|
display: grid;
|
|
1621
2109
|
grid-template-columns: auto minmax(0, 1fr) auto auto;
|
|
1622
|
-
gap:
|
|
1623
|
-
align-items:
|
|
1624
|
-
background: var(--
|
|
1625
|
-
|
|
2110
|
+
gap: 0 18px;
|
|
2111
|
+
align-items: start;
|
|
2112
|
+
background: var(--bg-card);
|
|
2113
|
+
/* The edge is transparent at rest and spends --glass-edge on hover: v3
|
|
2114
|
+
separates by tone, and a drawn border on every row rebuilds the boxed
|
|
2115
|
+
stack the pick removed. The 1px is always there so nothing reflows. */
|
|
2116
|
+
border: var(--line) solid transparent;
|
|
1626
2117
|
border-radius: var(--radius);
|
|
1627
|
-
padding:
|
|
1628
|
-
}
|
|
1629
|
-
.
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
2118
|
+
padding: 17px 22px;
|
|
2119
|
+
}
|
|
2120
|
+
.task:hover { border-color: var(--glass-edge); }
|
|
2121
|
+
.task__id { display: flex; align-items: center; gap: 2px; padding-top: 2px; }
|
|
2122
|
+
.task__num {
|
|
2123
|
+
font-family: var(--font-mono);
|
|
2124
|
+
font-size: 12.5px;
|
|
2125
|
+
font-variant-numeric: tabular-nums;
|
|
2126
|
+
color: var(--ink-faint);
|
|
2127
|
+
}
|
|
2128
|
+
/* task 1759, re-cut for the 24px floor (task 1003304): the hit area is 24px and
|
|
2129
|
+
the DRAWN box is 14px inside it. The old 15px input was the control itself,
|
|
2130
|
+
so it failed the floor at every width — painting the box with ::before is
|
|
2131
|
+
what lets the target grow without the checkbox growing with it. */
|
|
2132
|
+
.task__select {
|
|
2133
|
+
appearance: none;
|
|
2134
|
+
-webkit-appearance: none;
|
|
2135
|
+
position: relative;
|
|
2136
|
+
width: 24px;
|
|
2137
|
+
height: 24px;
|
|
2138
|
+
margin: 0;
|
|
2139
|
+
flex: none;
|
|
2140
|
+
cursor: pointer;
|
|
2141
|
+
}
|
|
2142
|
+
.task__select::before {
|
|
2143
|
+
content: "";
|
|
2144
|
+
position: absolute;
|
|
2145
|
+
left: 5px;
|
|
2146
|
+
top: 5px;
|
|
2147
|
+
width: 14px;
|
|
2148
|
+
height: 14px;
|
|
2149
|
+
border: var(--line) solid var(--rule);
|
|
2150
|
+
border-radius: 3px;
|
|
2151
|
+
}
|
|
2152
|
+
.task__select:checked::before { background: var(--accent); border-color: var(--accent); }
|
|
2153
|
+
.task__select:checked::after {
|
|
2154
|
+
content: "";
|
|
2155
|
+
position: absolute;
|
|
2156
|
+
left: 9px;
|
|
2157
|
+
top: 8px;
|
|
2158
|
+
width: 4px;
|
|
2159
|
+
height: 8px;
|
|
2160
|
+
border: solid var(--accent-on);
|
|
2161
|
+
border-width: 0 1.5px 1.5px 0;
|
|
2162
|
+
transform: rotate(42deg);
|
|
2163
|
+
}
|
|
2164
|
+
/* Selection is NOT hover. The mock draws both with --glass-edge, which reads
|
|
2165
|
+
fine on a mock with one selected row and not at all on a board whose whole
|
|
2166
|
+
point is selecting several for the bulk bar — so selection keeps an accent
|
|
2167
|
+
signal (a selected row is live, which is what the accent is for).
|
|
2168
|
+
The EDGE carries it, not a fill: --accent-tint is a 30% mix in light, and
|
|
2169
|
+
three selected rows painted with it took over the page (looked at, 1280w
|
|
2170
|
+
light). The checked box is already an accent fill on every selected row;
|
|
2171
|
+
a second one per row is what made it shout. */
|
|
2172
|
+
.task--selected { border-color: var(--accent); }
|
|
2173
|
+
/* task 1869: the explicit open-detail hitbox — clicking the card body toggles
|
|
2174
|
+
selection, so this is the only way from a claimable card into the overlay. */
|
|
1638
2175
|
.task__open {
|
|
1639
2176
|
flex: none;
|
|
1640
|
-
width:
|
|
1641
|
-
height:
|
|
2177
|
+
width: 26px;
|
|
2178
|
+
height: 26px;
|
|
1642
2179
|
display: inline-flex;
|
|
1643
2180
|
align-items: center;
|
|
1644
2181
|
justify-content: center;
|
|
@@ -1650,41 +2187,68 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1650
2187
|
cursor: pointer;
|
|
1651
2188
|
border-radius: var(--radius-sm);
|
|
1652
2189
|
}
|
|
1653
|
-
.task__open:hover { color: var(--ink); background: var(--
|
|
1654
|
-
.task__body { min-width: 0; }
|
|
1655
|
-
.task__title { font-weight:
|
|
1656
|
-
.task__meta { display: flex; flex-wrap: wrap; gap:
|
|
2190
|
+
.task__open:hover { color: var(--ink); background: var(--glass); }
|
|
2191
|
+
.task__body { min-width: 0; padding-top: 2px; }
|
|
2192
|
+
.task__title { font-weight: 400; font-size: 14.5px; line-height: 1.4; margin: 0 0 7px; color: var(--ink); }
|
|
2193
|
+
.task__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; font-size: 12px; color: var(--ink-faint); margin-top: 0; }
|
|
2194
|
+
/* The label voice, outlined — a tag is a fact about the task, never a fill. */
|
|
1657
2195
|
.task__tag {
|
|
1658
2196
|
display: inline-flex;
|
|
1659
2197
|
align-items: center;
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
font-size:
|
|
1666
|
-
|
|
2198
|
+
padding: 2px 8px;
|
|
2199
|
+
border-radius: var(--radius-pill);
|
|
2200
|
+
background: none;
|
|
2201
|
+
border: var(--line) solid var(--rule);
|
|
2202
|
+
font-family: var(--label-face);
|
|
2203
|
+
font-size: 10.5px;
|
|
2204
|
+
letter-spacing: var(--label-space);
|
|
2205
|
+
text-transform: var(--label-case);
|
|
1667
2206
|
color: var(--ink-soft);
|
|
1668
2207
|
}
|
|
1669
|
-
.task__credits {
|
|
1670
|
-
|
|
1671
|
-
.
|
|
2208
|
+
.task__credits { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; padding-top: 2px; }
|
|
2209
|
+
/* A credit figure is DATA, not live — the display face in ink, never accent
|
|
2210
|
+
(DESIGN.md, The One Warm Thing Rule + The Tabular Rule). */
|
|
2211
|
+
.task__credits-num {
|
|
2212
|
+
font-family: var(--font-display);
|
|
2213
|
+
font-weight: 300;
|
|
2214
|
+
font-size: 26px;
|
|
2215
|
+
line-height: 1;
|
|
2216
|
+
letter-spacing: -0.03em;
|
|
2217
|
+
font-variant-numeric: tabular-nums;
|
|
2218
|
+
color: var(--ink);
|
|
2219
|
+
}
|
|
2220
|
+
.task__credits-label {
|
|
2221
|
+
font-family: var(--label-face);
|
|
2222
|
+
font-size: 10px;
|
|
2223
|
+
letter-spacing: var(--label-space);
|
|
2224
|
+
text-transform: var(--label-case);
|
|
2225
|
+
color: var(--ink-faint);
|
|
2226
|
+
}
|
|
1672
2227
|
.task__copy {
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
2228
|
+
display: inline-flex;
|
|
2229
|
+
align-items: center;
|
|
2230
|
+
justify-content: center;
|
|
2231
|
+
width: 32px;
|
|
2232
|
+
height: 32px;
|
|
2233
|
+
border: var(--line) solid var(--rule);
|
|
2234
|
+
background: none;
|
|
2235
|
+
color: var(--ink-faint);
|
|
2236
|
+
border-radius: var(--radius-pill);
|
|
1677
2237
|
font-size: 12.5px;
|
|
1678
|
-
padding:
|
|
2238
|
+
padding: 0;
|
|
1679
2239
|
cursor: pointer;
|
|
1680
2240
|
}
|
|
1681
|
-
.task__copy:hover {
|
|
2241
|
+
.task__copy:hover { color: var(--ink); border-color: var(--ink-faint); }
|
|
2242
|
+
/* The status vocabulary, not the accent: "copied" is a verification state. */
|
|
1682
2243
|
.task__copy[data-copied="1"] { background: var(--ok-weak); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, transparent); }
|
|
1683
|
-
.task__copy-icon { margin-right:
|
|
2244
|
+
.task__copy-icon { margin-right: 0; }
|
|
1684
2245
|
|
|
1685
2246
|
@media (max-width: 640px) {
|
|
1686
|
-
.task { grid-template-columns:
|
|
1687
|
-
.
|
|
2247
|
+
.task { grid-template-columns: minmax(0, 1fr) auto; gap: 6px 14px; padding: 14px 16px; }
|
|
2248
|
+
.task__id { grid-column: 1; }
|
|
2249
|
+
.task__credits { grid-column: 2; grid-row: 1; flex-direction: row; align-items: baseline; gap: 6px; }
|
|
2250
|
+
.task__credits-num { font-size: 20px; }
|
|
2251
|
+
.task__body { grid-column: 1 / -1; }
|
|
1688
2252
|
}
|
|
1689
2253
|
|
|
1690
2254
|
/* ---------- ranks page ---------- */
|
|
@@ -1748,10 +2312,10 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1748
2312
|
transform: translate(-50%, 12px);
|
|
1749
2313
|
z-index: 100;
|
|
1750
2314
|
background: var(--ink);
|
|
1751
|
-
color: var(--bg
|
|
2315
|
+
color: var(--bg);
|
|
1752
2316
|
font-size: 13.5px;
|
|
1753
|
-
padding:
|
|
1754
|
-
border-radius: var(--radius);
|
|
2317
|
+
padding: 11px 20px;
|
|
2318
|
+
border-radius: var(--radius-pill);
|
|
1755
2319
|
box-shadow: var(--shadow-pop);
|
|
1756
2320
|
opacity: 0;
|
|
1757
2321
|
visibility: hidden;
|
|
@@ -1782,7 +2346,7 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1782
2346
|
position: fixed;
|
|
1783
2347
|
inset: 0;
|
|
1784
2348
|
z-index: 2000;
|
|
1785
|
-
background:
|
|
2349
|
+
background: rgba(0, 0, 0, .55);
|
|
1786
2350
|
display: flex;
|
|
1787
2351
|
align-items: center;
|
|
1788
2352
|
justify-content: center;
|
|
@@ -1790,8 +2354,8 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1790
2354
|
}
|
|
1791
2355
|
.deeplink-card__panel {
|
|
1792
2356
|
position: relative;
|
|
1793
|
-
background: var(--
|
|
1794
|
-
border: 1px solid var(--
|
|
2357
|
+
background: var(--bg-card);
|
|
2358
|
+
border: 1px solid var(--rule);
|
|
1795
2359
|
border-radius: var(--radius);
|
|
1796
2360
|
box-shadow: var(--shadow-pop);
|
|
1797
2361
|
max-width: 560px;
|
|
@@ -1804,15 +2368,15 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1804
2368
|
position: absolute;
|
|
1805
2369
|
top: 10px; right: 10px;
|
|
1806
2370
|
width: 28px; height: 28px;
|
|
1807
|
-
border: 1px solid var(--
|
|
1808
|
-
border-radius: var(--radius-
|
|
1809
|
-
background:
|
|
2371
|
+
border: 1px solid var(--rule);
|
|
2372
|
+
border-radius: var(--radius-pill);
|
|
2373
|
+
background: none;
|
|
1810
2374
|
color: var(--ink-soft);
|
|
1811
2375
|
font-size: 16px;
|
|
1812
2376
|
line-height: 1;
|
|
1813
2377
|
cursor: pointer;
|
|
1814
2378
|
}
|
|
1815
|
-
.deeplink-card__close:hover {
|
|
2379
|
+
.deeplink-card__close:hover { border-color: var(--ink-faint); color: var(--ink); }
|
|
1816
2380
|
.deeplink-card__kind {
|
|
1817
2381
|
font-size: 11px;
|
|
1818
2382
|
font-weight: 600;
|
|
@@ -1821,7 +2385,7 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1821
2385
|
color: var(--ink-faint);
|
|
1822
2386
|
margin: 0 0 4px;
|
|
1823
2387
|
}
|
|
1824
|
-
.deeplink-card__title { font-size:
|
|
2388
|
+
.deeplink-card__title { font-family: var(--font-display); font-size: 21px; font-weight: 300; letter-spacing: -0.03em; margin: 0 0 8px; }
|
|
1825
2389
|
.deeplink-card__meta { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12.5px; color: var(--ink-soft); margin: 0 0 10px; }
|
|
1826
2390
|
.deeplink-card__summary { font-size: 13.5px; margin: 0 0 10px; }
|
|
1827
2391
|
.deeplink-card__note { font-size: 12.5px; color: var(--ink-faint); margin: 0; }
|
|
@@ -1954,10 +2518,21 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1954
2518
|
invitations to accept + join-requests to approve. Matches the home widgets'
|
|
1955
2519
|
card language (.scroll host); each row is body-left / actions-right. */
|
|
1956
2520
|
.ginbox { list-style: none; margin: 0 0 4px; padding: 0; }
|
|
2521
|
+
/* Home's sub-heading voice — the label token, not a hardcoded uppercase (task
|
|
2522
|
+
1003304). Taking the token is what makes it flip: --label-face resolves to
|
|
2523
|
+
the mono in light and back to the body face in dark, because mono caps read
|
|
2524
|
+
as precise on paper and thin on black. All four users of this class
|
|
2525
|
+
(hall-widgets, goal-inbox, profile-nudge, builders) are Home surfaces. */
|
|
1957
2526
|
.ginbox__sec-h {
|
|
1958
|
-
margin:
|
|
1959
|
-
|
|
2527
|
+
margin: 22px 0 10px;
|
|
2528
|
+
font-family: var(--label-face);
|
|
2529
|
+
font-size: var(--label-size);
|
|
2530
|
+
font-weight: 400;
|
|
2531
|
+
letter-spacing: var(--label-space);
|
|
2532
|
+
text-transform: var(--label-case);
|
|
2533
|
+
color: var(--ink-faint);
|
|
1960
2534
|
}
|
|
2535
|
+
.ginbox__sec-h:first-child { margin-top: 0; }
|
|
1961
2536
|
.ginbox__item {
|
|
1962
2537
|
display: flex; align-items: flex-start; gap: 12px;
|
|
1963
2538
|
padding: 9px 0; border-top: 1px solid var(--rule-soft);
|
|
@@ -1995,40 +2570,47 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
1995
2570
|
/* filter-bar disclosure ("Filters" button) + removable active-filter chips */
|
|
1996
2571
|
.filters__more-count { margin-left: 6px; }
|
|
1997
2572
|
.filters--overflow {
|
|
1998
|
-
padding:
|
|
1999
|
-
border:
|
|
2573
|
+
padding: 12px 14px;
|
|
2574
|
+
border: 0;
|
|
2000
2575
|
border-radius: var(--radius-sm);
|
|
2001
2576
|
background: var(--surface-2);
|
|
2002
2577
|
margin-bottom: 14px;
|
|
2003
2578
|
}
|
|
2004
2579
|
.filter-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
|
|
2580
|
+
/* An active filter IS live, so the chip is the one place in a filter bar the
|
|
2581
|
+
accent belongs. */
|
|
2005
2582
|
.chip {
|
|
2006
|
-
display: inline-flex; align-items: center; gap: 6px;
|
|
2007
|
-
|
|
2583
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
2584
|
+
min-height: 26px;
|
|
2585
|
+
padding: 0 12px;
|
|
2008
2586
|
font-size: 12.5px;
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
border
|
|
2587
|
+
text-transform: lowercase;
|
|
2588
|
+
color: var(--accent-ink);
|
|
2589
|
+
background: var(--accent-tint);
|
|
2590
|
+
border: 0;
|
|
2591
|
+
border-radius: var(--radius-pill);
|
|
2013
2592
|
cursor: pointer;
|
|
2014
2593
|
}
|
|
2015
|
-
.chip:hover {
|
|
2594
|
+
.chip:hover { color: var(--ink); }
|
|
2016
2595
|
|
|
2017
2596
|
/* tab strip — the .setup__tab idiom in the .setup__toggle frame, promoted */
|
|
2597
|
+
/* A tab strip is hairlines, not a segmented box: one rule under the row and a
|
|
2598
|
+
2px accent underline on the open tab, the lit-step grammar again. */
|
|
2018
2599
|
.kit-tabs {
|
|
2019
|
-
display:
|
|
2600
|
+
display: flex;
|
|
2020
2601
|
max-width: 100%;
|
|
2021
2602
|
overflow-x: auto;
|
|
2022
|
-
border:
|
|
2023
|
-
border-
|
|
2603
|
+
border: 0;
|
|
2604
|
+
border-bottom: 1px solid var(--rule);
|
|
2605
|
+
border-radius: 0;
|
|
2024
2606
|
margin: 0 0 14px;
|
|
2025
2607
|
}
|
|
2026
2608
|
.kit-tabs .setup__tab { white-space: nowrap; }
|
|
2027
2609
|
.kit-tabs .setup__tab .count-pill { margin-left: 6px; }
|
|
2028
2610
|
|
|
2029
2611
|
/* empty state — one short line + at most one action link */
|
|
2030
|
-
.empty-state { padding:
|
|
2031
|
-
.empty-state p { margin: 0; font-size:
|
|
2612
|
+
.empty-state { padding: 8px 0; }
|
|
2613
|
+
.empty-state p { margin: 0; font-size: 13.5px; color: var(--ink-soft); }
|
|
2032
2614
|
.empty-state__action { display: inline-block; margin-top: 6px; font-size: 13px; }
|
|
2033
2615
|
|
|
2034
2616
|
/* skeleton shimmer — standard-height placeholder rows while data loads, so
|
|
@@ -2038,22 +2620,10 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
2038
2620
|
width: 60%;
|
|
2039
2621
|
min-width: 80px;
|
|
2040
2622
|
height: 12px;
|
|
2041
|
-
border-radius:
|
|
2042
|
-
background:
|
|
2043
|
-
color-mix(in srgb, var(--ink) 7%, var(--bg-card)) 25%,
|
|
2044
|
-
color-mix(in srgb, var(--ink) 13%, var(--bg-card)) 45%,
|
|
2045
|
-
color-mix(in srgb, var(--ink) 7%, var(--bg-card)) 65%);
|
|
2046
|
-
background-size: 200% 100%;
|
|
2047
|
-
animation: kit-skel-shimmer 1.2s ease-in-out infinite;
|
|
2623
|
+
border-radius: 2px;
|
|
2624
|
+
background: var(--skeleton);
|
|
2048
2625
|
}
|
|
2049
2626
|
.kit-skel-row td { border-bottom: 1px solid var(--rule-soft); }
|
|
2050
|
-
@keyframes kit-skel-shimmer {
|
|
2051
|
-
from { background-position: 120% 0; }
|
|
2052
|
-
to { background-position: -80% 0; }
|
|
2053
|
-
}
|
|
2054
|
-
@media (prefers-reduced-motion: reduce) {
|
|
2055
|
-
.kit-skel { animation: none; }
|
|
2056
|
-
}
|
|
2057
2627
|
|
|
2058
2628
|
/* collapsible card body — the Work-backlog <details> idiom, generalized */
|
|
2059
2629
|
.kit-collapse__summary {
|
|
@@ -2065,47 +2635,45 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
2065
2635
|
.kit-collapse__summary .scroll__h { display: inline; margin: 0; }
|
|
2066
2636
|
.kit-collapse__body { margin-top: 12px; }
|
|
2067
2637
|
|
|
2068
|
-
/* ---- Home dashboard (task 2169) ---- */
|
|
2638
|
+
/* ---- Home dashboard (task 2169; re-skinned into the world by task 1003304) ---- */
|
|
2069
2639
|
/* Stat tiles are links now — inherit ink, reveal affordance on hover. */
|
|
2070
2640
|
a.stat-tile { color: inherit; }
|
|
2071
|
-
a.stat-tile:hover {
|
|
2072
|
-
|
|
2073
|
-
border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
|
|
2074
|
-
background: color-mix(in srgb, var(--accent) 3%, var(--surface));
|
|
2075
|
-
}
|
|
2641
|
+
a.stat-tile:hover { text-decoration: none; background: var(--glass); }
|
|
2642
|
+
a.stat-tile:hover .stat-tile__sub { color: var(--ink-soft); }
|
|
2076
2643
|
/* The over-budget "More" row — one quiet line, not a card. */
|
|
2077
2644
|
.home-more { margin: 0; font-size: 13px; color: var(--ink-soft); }
|
|
2078
2645
|
|
|
2079
|
-
/* task 2184
|
|
2080
|
-
|
|
2081
|
-
columns
|
|
2082
|
-
|
|
2646
|
+
/* task 2184's two-column main zone, RETIRED by task 1003304. The zone holds
|
|
2647
|
+
the attention inbox, the More row and the overflow — all three of which
|
|
2648
|
+
already spanned both columns — plus ONE card, Your work. So the second
|
|
2649
|
+
column was always empty and the "dashboard, not a stack" it was reaching for
|
|
2650
|
+
is what #zone-home-band above actually delivers (Standing beside Goals).
|
|
2651
|
+
v3 agrees: its board mock puts the two-up in a .band and runs
|
|
2652
|
+
"Needs your attention" and "Your work" full width as sheets. One column
|
|
2653
|
+
here, and the dead half of the page goes away. */
|
|
2083
2654
|
#zone-home-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
|
|
2084
2655
|
#zone-home-main > .scroll { margin: 0; }
|
|
2085
|
-
@media (min-width: 1024px) {
|
|
2086
|
-
#zone-home-main { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
2087
|
-
#zone-home-main > #attention-scroll,
|
|
2088
|
-
#zone-home-main > #home-more-row,
|
|
2089
|
-
#zone-home-main > #zone-home-overflow { grid-column: 1 / -1; }
|
|
2090
|
-
}
|
|
2091
2656
|
|
|
2092
2657
|
/* task 2184: the "Next up" slice in the Your-work card — the page's answer to
|
|
2093
|
-
"what's my next action".
|
|
2094
|
-
|
|
2658
|
+
"what's my next action". v1's bare ledger row inside v3's panel (direction
|
|
2659
|
+
§6): a hairline and the row's own air, never a filled tile — a fill here was
|
|
2660
|
+
a card inside a card, and it was the last site in the hall spending
|
|
2661
|
+
--surface-2 as a raised surface. The first row drops its rule and its top
|
|
2662
|
+
padding so the list starts flush against the panel's air. */
|
|
2663
|
+
.next-up { list-style: none; margin: 0 0 4px; padding: 0; display: flex; flex-direction: column; gap: 0; }
|
|
2095
2664
|
.next-up__item {
|
|
2096
2665
|
display: flex;
|
|
2097
2666
|
flex-direction: column;
|
|
2098
2667
|
gap: 2px;
|
|
2099
|
-
padding:
|
|
2100
|
-
border:
|
|
2101
|
-
|
|
2102
|
-
border-radius: var(--radius-sm);
|
|
2103
|
-
background: var(--surface-2);
|
|
2668
|
+
padding: 14px 0;
|
|
2669
|
+
border-top: var(--line) solid var(--rule-soft);
|
|
2670
|
+
background: none;
|
|
2104
2671
|
}
|
|
2105
|
-
.next-
|
|
2106
|
-
.next-up__title
|
|
2107
|
-
.next-
|
|
2108
|
-
.next-
|
|
2672
|
+
.next-up__item:first-child { border-top: 0; padding-top: 0; }
|
|
2673
|
+
.next-up__title { font-weight: 400; font-size: 14px; color: var(--ink); }
|
|
2674
|
+
.next-up__title:hover { color: var(--accent-ink); }
|
|
2675
|
+
.next-up__meta { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
|
|
2676
|
+
.next-up__foot { margin: 14px 0 18px; font-size: 13px; }
|
|
2109
2677
|
|
|
2110
2678
|
/* ---------- jump palette (task 2178) ----------
|
|
2111
2679
|
The top-bar slot + the Ctrl/Cmd-K overlay. Styled from existing tokens only —
|