@graview/primitives 0.1.4 → 0.1.6
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/dist/arrange-bar.d.ts +1 -3
- package/dist/arrange-bar.d.ts.map +1 -1
- package/dist/arrange-bar.js +2 -24
- package/dist/arrange-bar.js.map +1 -1
- package/dist/arrangement.d.ts +5 -0
- package/dist/arrangement.d.ts.map +1 -0
- package/dist/arrangement.js +25 -0
- package/dist/arrangement.js.map +1 -0
- package/dist/chat.js +2 -2
- package/dist/chat.js.map +1 -1
- package/dist/companion.js +1 -1
- package/dist/companion.js.map +1 -1
- package/dist/connections.js +1 -1
- package/dist/connections.js.map +1 -1
- package/dist/default-view.d.ts +1 -1
- package/dist/default-view.d.ts.map +1 -1
- package/dist/default-view.js +1 -1
- package/dist/default-view.js.map +1 -1
- package/dist/default-views.d.ts +1 -1
- package/dist/default-views.d.ts.map +1 -1
- package/dist/default-views.js +11 -5
- package/dist/default-views.js.map +1 -1
- package/dist/editable.js +1 -1
- package/dist/editable.js.map +1 -1
- package/dist/find.js +2 -2
- package/dist/find.js.map +1 -1
- package/dist/frame.d.ts +22 -0
- package/dist/frame.d.ts.map +1 -0
- package/dist/frame.js +21 -0
- package/dist/frame.js.map +1 -0
- package/dist/framework-views.d.ts +5 -0
- package/dist/framework-views.d.ts.map +1 -0
- package/dist/framework-views.js +20 -0
- package/dist/framework-views.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/installation.js +2 -2
- package/dist/installation.js.map +1 -1
- package/dist/ladder.js +1 -1
- package/dist/ladder.js.map +1 -1
- package/dist/pages.d.ts +20 -0
- package/dist/pages.d.ts.map +1 -0
- package/dist/pages.js +19 -0
- package/dist/pages.js.map +1 -0
- package/dist/places.js +2 -2
- package/dist/places.js.map +1 -1
- package/dist/primitives/index.js +1 -1
- package/dist/primitives/index.js.map +1 -1
- package/dist/profile.js +1 -1
- package/dist/profile.js.map +1 -1
- package/dist/quick-relations.js +2 -2
- package/dist/quick-relations.js.map +1 -1
- package/dist/relation-key.js +1 -1
- package/dist/relation-key.js.map +1 -1
- package/dist/seats.js +1 -1
- package/dist/seats.js.map +1 -1
- package/dist/seeding.js +1 -1
- package/dist/seeding.js.map +1 -1
- package/dist/spec-views.d.ts +1 -1
- package/dist/spec-views.d.ts.map +1 -1
- package/dist/spec-views.js +1 -1
- package/dist/spec-views.js.map +1 -1
- package/dist/theme.d.ts +6 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +507 -393
- package/dist/theme.js.map +1 -1
- package/dist/view-doors.d.ts +10 -0
- package/dist/view-doors.d.ts.map +1 -0
- package/dist/view-doors.js +47 -0
- package/dist/view-doors.js.map +1 -0
- package/dist/wordmark.js +1 -1
- package/dist/wordmark.js.map +1 -1
- package/dist/workbench/activity.js +1 -1
- package/dist/workbench/activity.js.map +1 -1
- package/dist/workbench/agent-seat.js +2 -2
- package/dist/workbench/agent-seat.js.map +1 -1
- package/dist/workbench/answer-args.js +2 -2
- package/dist/workbench/answer-args.js.map +1 -1
- package/dist/workbench/back-out.d.ts +1 -1
- package/dist/workbench/back-out.d.ts.map +1 -1
- package/dist/workbench/back-out.js +2 -2
- package/dist/workbench/back-out.js.map +1 -1
- package/dist/workbench/following.js +1 -1
- package/dist/workbench/following.js.map +1 -1
- package/dist/workbench/inspector.js +1 -1
- package/dist/workbench/inspector.js.map +1 -1
- package/dist/workbench/standing.js +1 -1
- package/dist/workbench/standing.js.map +1 -1
- package/dist/workbench/trail.js +2 -2
- package/dist/workbench/trail.js.map +1 -1
- package/package.json +14 -6
package/dist/theme.js
CHANGED
|
@@ -99,7 +99,121 @@ function stillness(asking, within) {
|
|
|
99
99
|
${at} [data-graview-view][data-graview-read] > * { box-shadow: 0 0 0 1px var(--graview-activity); }
|
|
100
100
|
${at} [data-graview-connector][data-graview-activity] { animation: none; stroke-opacity: 1; }`;
|
|
101
101
|
}
|
|
102
|
+
/*
|
|
103
|
+
* WHY THE STYLESHEET'S NOTES ARE WRITTEN `${/* … *\/ ""}`. They were CSS
|
|
104
|
+
* comments inside the template, and every page carried them — 25 KB of the
|
|
105
|
+
* 60 this function was, shipped to each reader and parsed into each embed's
|
|
106
|
+
* <style> (FR-57). As a JS comment in an empty interpolation the words stay
|
|
107
|
+
* where they explain the rule, and a minifier folds them away.
|
|
108
|
+
*/
|
|
102
109
|
export function themeCss(scheme = "dark", brand = GRAVIEW_BRAND, options = {}) {
|
|
110
|
+
const css = sheet(scheme, brand, options);
|
|
111
|
+
return options.scope === undefined ? css : withinTheBox(css, options.scope);
|
|
112
|
+
}
|
|
113
|
+
/*
|
|
114
|
+
* A SCOPED STYLESHEET KEEPS TO ITS BOX (FR-64).
|
|
115
|
+
*
|
|
116
|
+
* The tokens, the ground and the type were written on the scope, but every
|
|
117
|
+
* other rule was written for a whole page — `button`, `h1, h2, h3, h4`,
|
|
118
|
+
* `code` — and an embed's <style> is a whole page's stylesheet: on Cloud's
|
|
119
|
+
* builder the host's own buttons, below the studio, took the framework's
|
|
120
|
+
* ink on a transparent ground and failed contrast in dark. Rather than
|
|
121
|
+
* remember to scope each rule as it is written, the finished sheet is
|
|
122
|
+
* rewritten: every selector that does not already start at the box is put
|
|
123
|
+
* under `:where(<scope>)`. `:where` weighs nothing, so each rule wins and
|
|
124
|
+
* loses exactly the contests it did on a whole page, and only where it
|
|
125
|
+
* applies changes. What is not a style rule (a registered property, the
|
|
126
|
+
* keyframes) names no element and is left as it is; @media and @supports
|
|
127
|
+
* are walked into.
|
|
128
|
+
*/
|
|
129
|
+
function withinTheBox(css, scope) {
|
|
130
|
+
const under = `:where(${scope}) `;
|
|
131
|
+
const at = (selector) => selector === scope ||
|
|
132
|
+
selector.startsWith(`${scope} `) ||
|
|
133
|
+
selector.startsWith(`${scope}:`) ||
|
|
134
|
+
selector.startsWith(`${scope}[`) ||
|
|
135
|
+
// The reader's motion answer: asked of the document, applied inside the box.
|
|
136
|
+
(selector.startsWith(":root") && selector.includes(` ${scope} `));
|
|
137
|
+
const rewrite = (prelude) => {
|
|
138
|
+
const lead = prelude.match(/^\s*/)[0];
|
|
139
|
+
const list = splitSelectors(prelude.trim()).map((selector) => (at(selector) ? selector : `${under}${selector}`));
|
|
140
|
+
return `${lead}${list.join(", ")} `;
|
|
141
|
+
};
|
|
142
|
+
const walk = (text) => {
|
|
143
|
+
let out = "";
|
|
144
|
+
let i = 0;
|
|
145
|
+
while (i < text.length) {
|
|
146
|
+
const open = text.indexOf("{", i);
|
|
147
|
+
if (open === -1)
|
|
148
|
+
return out + text.slice(i);
|
|
149
|
+
const close = blockEnd(text, open);
|
|
150
|
+
const prelude = text.slice(i, open);
|
|
151
|
+
const body = text.slice(open + 1, close);
|
|
152
|
+
const name = prelude.trim().startsWith("@") ? prelude.trim().split(/[\s(]/)[0] : null;
|
|
153
|
+
if (name === null)
|
|
154
|
+
out += `${rewrite(prelude)}{${body}}`;
|
|
155
|
+
else if (name === "@media" || name === "@supports" || name === "@container" || name === "@layer")
|
|
156
|
+
out += `${prelude}{${walk(body)}}`;
|
|
157
|
+
else
|
|
158
|
+
out += `${prelude}{${body}}`;
|
|
159
|
+
i = close + 1;
|
|
160
|
+
}
|
|
161
|
+
return out;
|
|
162
|
+
};
|
|
163
|
+
return walk(css);
|
|
164
|
+
}
|
|
165
|
+
/** The index of the brace that closes the block opened at `open`, past strings and comments. */
|
|
166
|
+
function blockEnd(text, open) {
|
|
167
|
+
let depth = 0;
|
|
168
|
+
let quote = null;
|
|
169
|
+
for (let j = open; j < text.length; j++) {
|
|
170
|
+
const ch = text[j];
|
|
171
|
+
if (quote) {
|
|
172
|
+
if (ch === "\\")
|
|
173
|
+
j++;
|
|
174
|
+
else if (ch === quote)
|
|
175
|
+
quote = null;
|
|
176
|
+
}
|
|
177
|
+
else if (ch === '"' || ch === "'")
|
|
178
|
+
quote = ch;
|
|
179
|
+
else if (ch === "/" && text[j + 1] === "*")
|
|
180
|
+
j = text.indexOf("*/", j + 2) + 1 || text.length;
|
|
181
|
+
else if (ch === "{")
|
|
182
|
+
depth++;
|
|
183
|
+
else if (ch === "}" && --depth === 0)
|
|
184
|
+
return j;
|
|
185
|
+
}
|
|
186
|
+
return text.length;
|
|
187
|
+
}
|
|
188
|
+
/** A selector list split on its own commas — not those inside `:is(…)`, `[…]` or a string. */
|
|
189
|
+
function splitSelectors(list) {
|
|
190
|
+
const out = [];
|
|
191
|
+
let depth = 0;
|
|
192
|
+
let quote = null;
|
|
193
|
+
let current = "";
|
|
194
|
+
for (const ch of list) {
|
|
195
|
+
if (quote) {
|
|
196
|
+
if (ch === quote)
|
|
197
|
+
quote = null;
|
|
198
|
+
}
|
|
199
|
+
else if (ch === '"' || ch === "'")
|
|
200
|
+
quote = ch;
|
|
201
|
+
else if (ch === "(" || ch === "[")
|
|
202
|
+
depth++;
|
|
203
|
+
else if (ch === ")" || ch === "]")
|
|
204
|
+
depth--;
|
|
205
|
+
else if (ch === "," && depth === 0) {
|
|
206
|
+
out.push(current.trim());
|
|
207
|
+
current = "";
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
current += ch;
|
|
211
|
+
}
|
|
212
|
+
if (current.trim())
|
|
213
|
+
out.push(current.trim());
|
|
214
|
+
return out;
|
|
215
|
+
}
|
|
216
|
+
function sheet(scheme, brand, options) {
|
|
103
217
|
const tokens = brand.schemes[scheme];
|
|
104
218
|
const root = options.scope ?? ":root";
|
|
105
219
|
const surface = options.scope ?? "html, body";
|
|
@@ -138,7 +252,7 @@ ${kitVariables(kit)}
|
|
|
138
252
|
--graview-font-body: ${body};
|
|
139
253
|
--graview-font-display: ${brand.typography?.display ?? body};
|
|
140
254
|
--graview-font-mono: ${brand.typography?.mono ?? 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace'};
|
|
141
|
-
/* Shape, as tokens, so a component never has to know whose product it is. */
|
|
255
|
+
${ /* Shape, as tokens, so a component never has to know whose product it is. */""}
|
|
142
256
|
--graview-radius: ${radius}px;
|
|
143
257
|
--graview-radius-sm: ${Math.max(2, Math.round(radius * 0.72))}px;
|
|
144
258
|
--graview-pad: ${Math.round(15 * density)}px;
|
|
@@ -153,36 +267,36 @@ ${surface} {
|
|
|
153
267
|
color: var(--graview-ink);
|
|
154
268
|
}
|
|
155
269
|
|
|
156
|
-
/*
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
270
|
+
${ /*
|
|
271
|
+
* THE READER'S OWN TEXT SIZE.
|
|
272
|
+
*
|
|
273
|
+
* Every size in the framework was once an absolute pixel count, so somebody
|
|
274
|
+
* who sets a larger default font in their browser — the setting WCAG 1.4.4
|
|
275
|
+
* is about — got a Graview that ignored them completely. 0.875rem is 14px
|
|
276
|
+
* at the default 16px root, so nothing moves for anyone who has not asked
|
|
277
|
+
* for anything, and everything moves together for anyone who has.
|
|
278
|
+
*/""}
|
|
165
279
|
${text} {
|
|
166
280
|
font: 0.875rem/1.55 var(--graview-font-body);
|
|
167
281
|
font-variant-numeric: tabular-nums;
|
|
168
282
|
-webkit-font-smoothing: antialiased;
|
|
169
283
|
}
|
|
170
284
|
|
|
171
|
-
/* Headings and the wordmark take the display face when a brand supplies one,
|
|
172
|
-
|
|
173
|
-
|
|
285
|
+
${ /* Headings and the wordmark take the display face when a brand supplies one,
|
|
286
|
+
and the body face when it does not — so a brand with one font is not asked
|
|
287
|
+
to name it twice. */""}
|
|
174
288
|
h1, h2, h3, h4, .graview-wordmark { font-family: var(--graview-font-display); }
|
|
175
289
|
code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
176
290
|
|
|
177
|
-
/*
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
291
|
+
${ /*
|
|
292
|
+
* A KIND'S FIGURE fills the box it is given.
|
|
293
|
+
*
|
|
294
|
+
* The art declares its own viewBox and knows nothing about where it is
|
|
295
|
+
* drawn — a chip at twelve pixels, a district's heading at eighteen, a kind
|
|
296
|
+
* card's landmark at forty — so the SIZE is the container's and the drawing
|
|
297
|
+
* scales into it. currentColor on the strokes means the kind's own hue
|
|
298
|
+
* arrives through the cascade without the art being redrawn.
|
|
299
|
+
*/""}
|
|
186
300
|
[data-graview-figure] > svg {
|
|
187
301
|
width: 100%;
|
|
188
302
|
height: 100%;
|
|
@@ -190,17 +304,17 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
190
304
|
overflow: visible;
|
|
191
305
|
}
|
|
192
306
|
|
|
193
|
-
/* How far above the stack the camera is, 0..1 — REGISTERED so it can
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
307
|
+
${ /* How far above the stack the camera is, 0..1 — REGISTERED so it can
|
|
308
|
+
transition. Rising to the Graview morphs the scene instead of cutting:
|
|
309
|
+
the square grid dissolves into the iso lattice and the districts grow up
|
|
310
|
+
out of their cards, all riding this one number. */""}
|
|
197
311
|
@property --graview-altitude {
|
|
198
312
|
syntax: "<number>";
|
|
199
313
|
inherits: true;
|
|
200
314
|
initial-value: 0;
|
|
201
315
|
}
|
|
202
316
|
|
|
203
|
-
/* The ground: a slow wash, so depth has something to recede into. */
|
|
317
|
+
${ /* The ground: a slow wash, so depth has something to recede into. */""}
|
|
204
318
|
.graview-ground {
|
|
205
319
|
position: relative;
|
|
206
320
|
background: var(--graview-wash), var(--graview-ground);
|
|
@@ -208,13 +322,13 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
208
322
|
transition: --graview-altitude 640ms cubic-bezier(0.33, 0, 0.2, 1);
|
|
209
323
|
}
|
|
210
324
|
|
|
211
|
-
/*
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
325
|
+
${ /*
|
|
326
|
+
* The altitude control rides the SAME number the scene rides — its own copy,
|
|
327
|
+
* because it sits beside the ground rather than inside it — on the same
|
|
328
|
+
* curve. So the mark morphs exactly as long as the scene does, and where an
|
|
329
|
+
* engine cannot register the property, both cut together: one mechanism,
|
|
330
|
+
* and no way for the control and the picture to disagree about the change.
|
|
331
|
+
*/""}
|
|
218
332
|
.graview-altitude-control {
|
|
219
333
|
--graview-altitude: 0;
|
|
220
334
|
transition:
|
|
@@ -226,7 +340,7 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
226
340
|
transform-box: fill-box;
|
|
227
341
|
transform-origin: center;
|
|
228
342
|
}
|
|
229
|
-
/* The ring of three kinds tightens to one ring around one node. */
|
|
343
|
+
${ /* The ring of three kinds tightens to one ring around one node. */""}
|
|
230
344
|
.graview-altitude-mark-ring {
|
|
231
345
|
transform: scaleX(calc(1 - 0.48 * var(--graview-altitude)));
|
|
232
346
|
opacity: calc(0.55 + 0.4 * var(--graview-altitude));
|
|
@@ -234,7 +348,7 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
234
348
|
.graview-altitude-mark-apex {
|
|
235
349
|
transform: translateY(calc(2.6px * var(--graview-altitude)));
|
|
236
350
|
}
|
|
237
|
-
/* The two wings gather into the centre and give their ink to the apex. */
|
|
351
|
+
${ /* The two wings gather into the centre and give their ink to the apex. */""}
|
|
238
352
|
.graview-altitude-mark-wing {
|
|
239
353
|
opacity: calc(0.75 * (1 - var(--graview-altitude)));
|
|
240
354
|
}
|
|
@@ -245,9 +359,9 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
245
359
|
transform: translate(calc(-4.4px * var(--graview-altitude)), calc(-0.8px * var(--graview-altitude)));
|
|
246
360
|
}
|
|
247
361
|
|
|
248
|
-
/* A fine measure under the scene. Faint enough to feel like calibration
|
|
249
|
-
|
|
250
|
-
|
|
362
|
+
${ /* A fine measure under the scene. Faint enough to feel like calibration
|
|
363
|
+
rather than graph paper, and it fades out at the edges so the scene has no
|
|
364
|
+
hard boundary. */""}
|
|
251
365
|
.graview-ground::before {
|
|
252
366
|
content: "";
|
|
253
367
|
position: absolute;
|
|
@@ -261,15 +375,15 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
261
375
|
mask-image: radial-gradient(120% 90% at 50% 40%, #000 30%, transparent 78%);
|
|
262
376
|
}
|
|
263
377
|
|
|
264
|
-
/* Content that scrolls inside a panel, and SAYS SO.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
378
|
+
${ /* Content that scrolls inside a panel, and SAYS SO.
|
|
379
|
+
*
|
|
380
|
+
* A pure-CSS scroll shadow: two cover gradients painted in the panel's own
|
|
381
|
+
* ground scroll with the content, two shadows stay put, and so a shadow
|
|
382
|
+
* only shows at an edge there is more content past. No
|
|
383
|
+
* JavaScript, no measurement, and nothing to go stale — which matters
|
|
384
|
+
* because the failure it prevents is silent. macOS hides overlay scrollbars
|
|
385
|
+
* until you scroll, so without this a clipped list looks like a finished
|
|
386
|
+
* one. */""}
|
|
273
387
|
.graview-scroll {
|
|
274
388
|
overflow: auto;
|
|
275
389
|
min-height: 0;
|
|
@@ -282,8 +396,8 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
282
396
|
background-size: 100% 24px, 100% 24px, 100% 10px, 100% 10px;
|
|
283
397
|
background-attachment: local, local, scroll, scroll;
|
|
284
398
|
}
|
|
285
|
-
/* "There is more of this", said by the ground: a few pixels of the panel's
|
|
286
|
-
|
|
399
|
+
${ /* "There is more of this", said by the ground: a few pixels of the panel's
|
|
400
|
+
* own colour over the last row, stuck to the bottom of what scrolls. */""}
|
|
287
401
|
.graview-scroll[data-graview-overflowing]::after {
|
|
288
402
|
content: "";
|
|
289
403
|
position: sticky;
|
|
@@ -294,23 +408,23 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
294
408
|
pointer-events: none;
|
|
295
409
|
}
|
|
296
410
|
|
|
297
|
-
/* A card on the kinds plane.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
411
|
+
${ /* A card on the kinds plane.
|
|
412
|
+
*
|
|
413
|
+
* Title and count only at rest — a strip of ten cards each showing three
|
|
414
|
+
* truncated member names is ten unreadable things, and the members are not
|
|
415
|
+
* what you are asking the strip. Hovering lifts one and reveals the kind's
|
|
416
|
+
* own description, which the declaration has always carried and nothing has
|
|
417
|
+
* ever shown. */""}
|
|
304
418
|
.graview-kind-card {
|
|
305
419
|
height: 100%;
|
|
306
420
|
transition: transform 170ms cubic-bezier(0.22, 1, 0.36, 1), height 170ms ease,
|
|
307
421
|
box-shadow 170ms ease;
|
|
308
|
-
/* IN THE STACK NOTHING HANGS BELOW A CARD. The iso block rests eighteen
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
422
|
+
${ /* IN THE STACK NOTHING HANGS BELOW A CARD. The iso block rests eighteen
|
|
423
|
+
pixels low there, invisible, ready to rise — and an invisible box that
|
|
424
|
+
pokes under the bottom row still made the stage scroll by nine pixels
|
|
425
|
+
with nowhere to scroll. Clipped (not hidden: no scroll container, no
|
|
426
|
+
scrollable overflow), and let out again from altitude, where the plate
|
|
427
|
+
floats above the card and the block stands up out of it. */""}
|
|
314
428
|
overflow: clip;
|
|
315
429
|
}
|
|
316
430
|
[data-graview-altitude] .graview-kind-card {
|
|
@@ -324,9 +438,9 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
324
438
|
position: relative;
|
|
325
439
|
z-index: 3;
|
|
326
440
|
}
|
|
327
|
-
/* From altitude a district is a village on its plot, not a card: hovering
|
|
328
|
-
|
|
329
|
-
|
|
441
|
+
${ /* From altitude a district is a village on its plot, not a card: hovering
|
|
442
|
+
it must not raise a white panel over the buildings. The lift stays in
|
|
443
|
+
the stack, where the card is a card. */""}
|
|
330
444
|
[data-graview-altitude] .graview-kind-card:hover,
|
|
331
445
|
[data-graview-altitude] .graview-kind-card:focus-within {
|
|
332
446
|
transform: none;
|
|
@@ -334,19 +448,19 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
334
448
|
background: transparent;
|
|
335
449
|
}
|
|
336
450
|
|
|
337
|
-
/* FROM ALTITUDE the ground is an ISOMETRIC LATTICE — diamond cells at the
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
/* DRAWN AS TILES, one cell each. A repeating gradient at the lattice's
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
451
|
+
${ /* FROM ALTITUDE the ground is an ISOMETRIC LATTICE — diamond cells at the
|
|
452
|
+
classic 2:1 pitch, a finer far weave above, dissolving toward the
|
|
453
|
+
horizon. Always present, faded by the altitude number, so rising
|
|
454
|
+
CROSSFADES the square grid into the lattice instead of cutting. */""}
|
|
455
|
+
${ /* DRAWN AS TILES, one cell each. A repeating gradient at the lattice's
|
|
456
|
+
angle was phased from the middle of the box and seamed at the box's own
|
|
457
|
+
edge when repeated with an offset, so the lines never sat where the
|
|
458
|
+
city's cells were: a plot stood beside the grid, not on it. Each tile is
|
|
459
|
+
one cell wide and half a cell tall — the diamond's bounding box — with
|
|
460
|
+
the tile's two diagonals drawn across it, which is the whole lattice:
|
|
461
|
+
corners and centres of the tiles are its vertices, and a tile corner is
|
|
462
|
+
pinned where the city's cell (0,0) meets the canvas. The far weave is the
|
|
463
|
+
same tile at half size. */""}
|
|
350
464
|
.graview-ground::after {
|
|
351
465
|
content: "";
|
|
352
466
|
position: absolute;
|
|
@@ -364,21 +478,21 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
364
478
|
var(--graview-lattice-tile) calc(var(--graview-lattice-tile) / 2),
|
|
365
479
|
calc(var(--graview-lattice-tile) / 2) calc(var(--graview-lattice-tile) / 4),
|
|
366
480
|
calc(var(--graview-lattice-tile) / 2) calc(var(--graview-lattice-tile) / 4);
|
|
367
|
-
/* Anchored where the city's cell (0,0) meets the canvas, so a plot placed
|
|
368
|
-
|
|
481
|
+
${ /* Anchored where the city's cell (0,0) meets the canvas, so a plot placed
|
|
482
|
+
by the map sits ON the grid a person can see, and pans with it. */""}
|
|
369
483
|
background-position: var(--graview-lattice-x, 0px) var(--graview-lattice-y, 0px);
|
|
370
|
-
/* Twice the square grid's weight: fields are meant to be seen, the grid is meant to be felt. */
|
|
484
|
+
${ /* Twice the square grid's weight: fields are meant to be seen, the grid is meant to be felt. */""}
|
|
371
485
|
opacity: calc(var(--graview-kit-lattice, 1) * var(--graview-grid-alpha) * 2 * var(--graview-altitude));
|
|
372
486
|
mask-image: linear-gradient(to top, #000 42%, rgba(0,0,0,0.35) 70%, transparent 92%);
|
|
373
487
|
-webkit-mask-image: linear-gradient(to top, #000 42%, rgba(0,0,0,0.35) 70%, transparent 92%);
|
|
374
488
|
}
|
|
375
489
|
|
|
376
|
-
/* THE GROUND UNDER A DISTRICT: its plot, drawn. Four lattice corners in
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
490
|
+
${ /* THE GROUND UNDER A DISTRICT: its plot, drawn. Four lattice corners in
|
|
491
|
+
the kind's hue, a kerb, a cast shadow toward the light — the arithmetic
|
|
492
|
+
the layout already did, made visible, so a district stands on land
|
|
493
|
+
rather than floating on a hatch. Fades in with the altitude number the
|
|
494
|
+
lattice fades in with; a hand-placed district's kerb is dashed, which is
|
|
495
|
+
the pinned mark on the ground rather than a box over the drawing. */""}
|
|
382
496
|
.graview-plots {
|
|
383
497
|
z-index: 0;
|
|
384
498
|
opacity: var(--graview-altitude);
|
|
@@ -400,10 +514,10 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
400
514
|
.graview-plot[data-graview-pinned] .graview-plot-tile {
|
|
401
515
|
stroke-dasharray: 4 3;
|
|
402
516
|
}
|
|
403
|
-
/* THE VILLAGE on the tile: one small iso building per member in the kind's
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
517
|
+
${ /* THE VILLAGE on the tile: one small iso building per member in the kind's
|
|
518
|
+
own faces (the same roof and walls the block had), a flagged member's roof
|
|
519
|
+
in the warning colour, a selected member's building lit in the accent.
|
|
520
|
+
Architecture, not controls: the tile under them takes the click. */""}
|
|
407
521
|
.graview-village { pointer-events: none; }
|
|
408
522
|
.graview-building polygon { stroke-width: 0.8; }
|
|
409
523
|
.graview-building[data-graview-flagged] .graview-iso-roof { fill: var(--graview-warn); stroke: var(--graview-warn); }
|
|
@@ -414,10 +528,10 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
414
528
|
letter-spacing: 0.06em;
|
|
415
529
|
fill: var(--graview-ink-muted);
|
|
416
530
|
}
|
|
417
|
-
/* THE ROADS between plots: the lattice's own two legs from kerb to kerb, a
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
531
|
+
${ /* THE ROADS between plots: the lattice's own two legs from kerb to kerb, a
|
|
532
|
+
bed between two edges in the ground's ink. Under the tiles and the
|
|
533
|
+
buildings, over the fields. A road the legend is asking about comes up
|
|
534
|
+
in the accent. */""}
|
|
421
535
|
.graview-road-edge {
|
|
422
536
|
fill: none;
|
|
423
537
|
stroke: var(--graview-ink);
|
|
@@ -437,34 +551,34 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
437
551
|
stroke: var(--graview-accent);
|
|
438
552
|
stroke-opacity: 0.9;
|
|
439
553
|
}
|
|
440
|
-
/* FIELDS. From altitude the ground darkens a shade toward the near edge and
|
|
441
|
-
|
|
442
|
-
|
|
554
|
+
${ /* FIELDS. From altitude the ground darkens a shade toward the near edge and
|
|
555
|
+
fades to the page at the horizon, so the lattice is land with a distance
|
|
556
|
+
rather than paper with a pattern. */""}
|
|
443
557
|
.graview-ground[data-graview-altitude] {
|
|
444
558
|
background:
|
|
445
559
|
linear-gradient(to top, color-mix(in oklab, var(--graview-ground) ${scheme === "light" ? "93%" : "88%"}, var(--graview-ink)) 0%, var(--graview-ground) 78%),
|
|
446
560
|
var(--graview-ground);
|
|
447
561
|
}
|
|
448
562
|
|
|
449
|
-
/* THE KEEPER'S BLOCK IN THE PROFILE, which hides itself when it is empty.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
563
|
+
${ /* THE KEEPER'S BLOCK IN THE PROFILE, which hides itself when it is empty.
|
|
564
|
+
Both controls inside it draw nothing for a seat that may not administer,
|
|
565
|
+
and a heading with nothing under it is worse than no heading — so the
|
|
566
|
+
block is drawn only when it actually holds a control. */""}
|
|
453
567
|
.graview-profile-keeping { display: grid; gap: 6px; }
|
|
454
568
|
.graview-profile-keeping:not(:has(button, a)) { display: none; }
|
|
455
569
|
.graview-profile-keeping > * { justify-self: start; }
|
|
456
570
|
|
|
457
|
-
/* THE OPEN CHEVRON APPEARS WHEN REACHED FOR. Drawn on every plate at
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
571
|
+
${ /* THE OPEN CHEVRON APPEARS WHEN REACHED FOR. Drawn on every plate at
|
|
572
|
+
altitude it was noise times the number of districts; it shows on hover,
|
|
573
|
+
on keyboard focus, and while the district is open — and stays a real
|
|
574
|
+
button in between, so Tab still finds it and Enter still opens. */""}
|
|
461
575
|
[data-graview-altitude] .graview-kind-open {
|
|
462
576
|
opacity: 0.5;
|
|
463
577
|
transition: opacity 150ms ease;
|
|
464
578
|
}
|
|
465
|
-
/* Quiet: the chevron alone until reached for. Never opacity zero — a
|
|
466
|
-
|
|
467
|
-
|
|
579
|
+
${ /* Quiet: the chevron alone until reached for. Never opacity zero — a
|
|
580
|
+
button nobody can see is a button a driven browser cannot press either,
|
|
581
|
+
and Tab must land on something that looks like something. */""}
|
|
468
582
|
[data-graview-altitude] .graview-kind-open-word {
|
|
469
583
|
display: none;
|
|
470
584
|
}
|
|
@@ -478,22 +592,22 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
478
592
|
[data-graview-altitude] .graview-kind-open[aria-expanded="true"] .graview-kind-open-word {
|
|
479
593
|
display: inline;
|
|
480
594
|
}
|
|
481
|
-
/* The district-open control and its roster: altitude-only chrome. Inside
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
595
|
+
${ /* The district-open control and its roster: altitude-only chrome. Inside
|
|
596
|
+
the stack expanding dissolves a card, so the control does not exist
|
|
597
|
+
there. A full fingertip even though the glyph is small — the audit holds
|
|
598
|
+
every control to 24px. */""}
|
|
485
599
|
.graview-kind-open { display: none; }
|
|
486
600
|
[data-graview-altitude] .graview-kind-open {
|
|
487
601
|
display: inline-flex;
|
|
488
602
|
align-items: center;
|
|
489
603
|
justify-content: center;
|
|
490
604
|
flex: 0 0 auto;
|
|
491
|
-
/* A FINGERTIP, AND THE READER'S FINGERTIP IF IT IS BIGGER. 24px is the
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
605
|
+
${ /* A FINGERTIP, AND THE READER'S FINGERTIP IF IT IS BIGGER. 24px is the
|
|
606
|
+
floor audit-ui holds every control to; 1.5rem is the same 24 at the
|
|
607
|
+
default text size and grows with a reader who asked for more, so the
|
|
608
|
+
control never drifts under the words it sits beside. A max() rather than
|
|
609
|
+
either one alone: rem alone drops below the fingertip at a smaller
|
|
610
|
+
setting, px alone ignores the setting altogether. */""}
|
|
497
611
|
min-height: max(1.5rem, 24px);
|
|
498
612
|
padding: 1px 9px;
|
|
499
613
|
margin: -3px 0;
|
|
@@ -503,12 +617,12 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
503
617
|
box-shadow: none;
|
|
504
618
|
color: var(--graview-ink-muted);
|
|
505
619
|
cursor: pointer;
|
|
506
|
-
/* IN REM, LIKE EVERY OTHER SIZE HERE. At 10px this control's words were
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
620
|
+
${ /* IN REM, LIKE EVERY OTHER SIZE HERE. At 10px this control's words were
|
|
621
|
+
the one piece of text in the framework that ignored the reader's text
|
|
622
|
+
size completely: set to Largest, every name on the screen doubled and
|
|
623
|
+
"open" stayed ten pixels tall. A size a person chose and a control that
|
|
624
|
+
will not take it is the accessibility setting failing on its own
|
|
625
|
+
surface. */""}
|
|
512
626
|
font-size: 0.75rem;
|
|
513
627
|
letter-spacing: 0.08em;
|
|
514
628
|
text-transform: uppercase;
|
|
@@ -519,19 +633,19 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
519
633
|
color: var(--graview-accent);
|
|
520
634
|
border-color: var(--graview-accent-dim);
|
|
521
635
|
}
|
|
522
|
-
/* The roster reads as a LIST, one member a row — chips wrapping at their
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
/* A DRIVE-IN: a dark screen standing on the plot, and the showings under
|
|
526
|
-
|
|
527
|
-
|
|
636
|
+
${ /* The roster reads as a LIST, one member a row — chips wrapping at their
|
|
637
|
+
own widths read as spilled tiles, and a district's population is a roll
|
|
638
|
+
call, not a mosaic. */""}
|
|
639
|
+
${ /* A DRIVE-IN: a dark screen standing on the plot, and the showings under
|
|
640
|
+
it as a marquee of real buttons. Only from altitude; the same list the
|
|
641
|
+
Places pills carry, drawn where the pictures live. */""}
|
|
528
642
|
.graview-drive-in {
|
|
529
|
-
/* Its own block under the nameplate, never a row inside the pill: the
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
643
|
+
${ /* Its own block under the nameplate, never a row inside the pill: the
|
|
644
|
+
pill is one line of name and count, and a marquee flattened into it
|
|
645
|
+
read as "12 • shown above The month The week". On a box the pill sits
|
|
646
|
+
on the roof at the top of the card, so the marquee hangs under it; on
|
|
647
|
+
a landmark the pill floats above the card, so the marquee takes the
|
|
648
|
+
card's own top edge. */""}
|
|
535
649
|
position: absolute;
|
|
536
650
|
left: 50%;
|
|
537
651
|
top: 42px;
|
|
@@ -554,9 +668,9 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
554
668
|
.graview-drive-in-marquee[data-graview-thumbs="one"] {
|
|
555
669
|
grid-template-columns: 120px;
|
|
556
670
|
}
|
|
557
|
-
/* THE LENSES AS PICTURES: each showing is its lens drawn small — the real
|
|
558
|
-
|
|
559
|
-
|
|
671
|
+
${ /* THE LENSES AS PICTURES: each showing is its lens drawn small — the real
|
|
672
|
+
component at a fraction of its size, cut to a thumbnail — with its name
|
|
673
|
+
under it. The picture takes no pointer; the button around it does. */""}
|
|
560
674
|
.graview-drive-in-thumb {
|
|
561
675
|
position: relative;
|
|
562
676
|
display: grid;
|
|
@@ -574,12 +688,12 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
574
688
|
border-color: var(--graview-accent);
|
|
575
689
|
color: var(--graview-accent);
|
|
576
690
|
}
|
|
577
|
-
/* The press: the whole frame, laid over the picture and the title rather than
|
|
578
|
-
|
|
691
|
+
${ /* The press: the whole frame, laid over the picture and the title rather than
|
|
692
|
+
around them, so the lens drawn small never sits inside a button. */""}
|
|
579
693
|
.graview-drive-in-thumb-press {
|
|
580
694
|
position: absolute;
|
|
581
695
|
inset: -1px;
|
|
582
|
-
/* It fills its frame, and says the frame's floor itself: a target is sized where it is declared. */
|
|
696
|
+
${ /* It fills its frame, and says the frame's floor itself: a target is sized where it is declared. */""}
|
|
583
697
|
min-height: max(1.75rem, 28px);
|
|
584
698
|
margin: 0;
|
|
585
699
|
padding: 0;
|
|
@@ -588,7 +702,7 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
588
702
|
background: transparent;
|
|
589
703
|
box-shadow: none;
|
|
590
704
|
cursor: pointer;
|
|
591
|
-
/* The card's own floor, stated: it covers the card, and the card is at least this tall. */
|
|
705
|
+
${ /* The card's own floor, stated: it covers the card, and the card is at least this tall. */""}
|
|
592
706
|
min-height: max(1.75rem, 28px);
|
|
593
707
|
}
|
|
594
708
|
.graview-drive-in-thumb-press:focus-visible {
|
|
@@ -624,20 +738,20 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
624
738
|
font-size: 0.75rem;
|
|
625
739
|
line-height: 1.2;
|
|
626
740
|
white-space: nowrap;
|
|
627
|
-
/* Its own frame's width: two pictures share the marquee, and two names
|
|
628
|
-
|
|
741
|
+
${ /* Its own frame's width: two pictures share the marquee, and two names
|
|
742
|
+
each allowed the width of one picture ran into each other. */""}
|
|
629
743
|
max-width: 100%;
|
|
630
744
|
overflow: hidden;
|
|
631
745
|
text-overflow: ellipsis;
|
|
632
746
|
}
|
|
633
|
-
/* THE BILLBOARD'S FULL-SCREEN CONTROL: the one way down from a picture. */
|
|
634
|
-
/* THE RAIL A BILLBOARD IS MOVED BY: a title bar, in the board's own frame
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
747
|
+
${ /* THE BILLBOARD'S FULL-SCREEN CONTROL: the one way down from a picture. */""}
|
|
748
|
+
${ /* THE RAIL A BILLBOARD IS MOVED BY: a title bar, in the board's own frame
|
|
749
|
+
ink, along its top edge. Positioned like the full-screen control beside
|
|
750
|
+
it — the host wraps its children, so the rail is a grandchild of the
|
|
751
|
+
screen box and a child selector never reaches it. Wide enough to be an
|
|
752
|
+
easy target, short enough that the picture underneath is still what you
|
|
753
|
+
see, and present only at altitude, because only up there is the board
|
|
754
|
+
standing on a plot it could be moved around. */""}
|
|
641
755
|
.graview-screen-grip {
|
|
642
756
|
display: none;
|
|
643
757
|
}
|
|
@@ -649,15 +763,15 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
649
763
|
left: 0;
|
|
650
764
|
right: 0;
|
|
651
765
|
top: 0;
|
|
652
|
-
/* Drawn height, not CSS height: a district's plane is scaled down at
|
|
653
|
-
|
|
654
|
-
|
|
766
|
+
${ /* Drawn height, not CSS height: a district's plane is scaled down at
|
|
767
|
+
altitude, and 14 here reached the screen as an eight-pixel strip that
|
|
768
|
+
took three attempts to catch. */""}
|
|
655
769
|
height: 32px;
|
|
656
770
|
padding: 0 6px 0 12px;
|
|
657
771
|
box-sizing: border-box;
|
|
658
772
|
cursor: grab;
|
|
659
|
-
/* A title bar in the panel's own colours, not a grey strip: the board is
|
|
660
|
-
|
|
773
|
+
${ /* A title bar in the panel's own colours, not a grey strip: the board is
|
|
774
|
+
a window onto the picture, and its bar reads as the window's. */""}
|
|
661
775
|
background: var(--graview-panel-muted);
|
|
662
776
|
border-bottom: 1px solid var(--graview-edge);
|
|
663
777
|
z-index: 3;
|
|
@@ -703,11 +817,11 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
703
817
|
color: var(--graview-accent);
|
|
704
818
|
}
|
|
705
819
|
|
|
706
|
-
/* THE OTHERS: people and their agents in the city, each a small figure in
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
820
|
+
${ /* THE OTHERS: people and their agents in the city, each a small figure in
|
|
821
|
+
the scene's own line vocabulary with a name under it. They move by a
|
|
822
|
+
transition on transform — one number, the layout tween's curve — so a
|
|
823
|
+
quiet city runs nothing. This tab's own seat is not drawn here: the
|
|
824
|
+
companion on the frame is where it speaks. */""}
|
|
711
825
|
.graview-occupants {
|
|
712
826
|
position: absolute;
|
|
713
827
|
inset: 0;
|
|
@@ -767,9 +881,9 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
767
881
|
color: var(--graview-ink-muted);
|
|
768
882
|
pointer-events: none;
|
|
769
883
|
}
|
|
770
|
-
/* ANOTHER PERSON, on your map: a head and shoulders in their own hue, at
|
|
771
|
-
|
|
772
|
-
|
|
884
|
+
${ /* ANOTHER PERSON, on your map: a head and shoulders in their own hue, at
|
|
885
|
+
the plot their stop names or in the audience row of the showing they are
|
|
886
|
+
watching. Press to follow them; their name is under them like a robot's. */""}
|
|
773
887
|
.graview-figure[data-graview-person] .graview-figure-body {
|
|
774
888
|
left: -11px;
|
|
775
889
|
top: -24px;
|
|
@@ -784,11 +898,11 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
784
898
|
.graview-figure[data-graview-person][data-graview-followed] .graview-figure-body {
|
|
785
899
|
color: var(--graview-accent);
|
|
786
900
|
}
|
|
787
|
-
/* Their robot, beside them, captioned as theirs. */
|
|
901
|
+
${ /* Their robot, beside them, captioned as theirs. */""}
|
|
788
902
|
.graview-figure[data-graview-theirs] .graview-figure-body {
|
|
789
903
|
opacity: 0.85;
|
|
790
904
|
}
|
|
791
|
-
/* More than a row can hold, and the anonymous: a number where they stand. */
|
|
905
|
+
${ /* More than a row can hold, and the anonymous: a number where they stand. */""}
|
|
792
906
|
.graview-figure-count {
|
|
793
907
|
position: absolute;
|
|
794
908
|
transform: translate(-50%, -100%);
|
|
@@ -801,7 +915,7 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
801
915
|
white-space: nowrap;
|
|
802
916
|
pointer-events: auto;
|
|
803
917
|
}
|
|
804
|
-
/* What somebody else is pointing at, outlined in their colour. */
|
|
918
|
+
${ /* What somebody else is pointing at, outlined in their colour. */""}
|
|
805
919
|
.graview-presence-over {
|
|
806
920
|
position: absolute;
|
|
807
921
|
border: 2px solid hsl(var(--graview-hue, 200) 55% 52%);
|
|
@@ -810,7 +924,7 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
810
924
|
opacity: 0.75;
|
|
811
925
|
transition: left 200ms ease, top 200ms ease, width 200ms ease, height 200ms ease;
|
|
812
926
|
}
|
|
813
|
-
/* Off the visible ground: an indicator at the border, pointing at it. */
|
|
927
|
+
${ /* Off the visible ground: an indicator at the border, pointing at it. */""}
|
|
814
928
|
.graview-figure-edge {
|
|
815
929
|
position: absolute;
|
|
816
930
|
min-height: max(1.5rem, 24px);
|
|
@@ -839,14 +953,14 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
839
953
|
justify-content: flex-start;
|
|
840
954
|
max-width: none;
|
|
841
955
|
}
|
|
842
|
-
/* An OPENED district is a PANEL, not a pill with a list stuffed in it:
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
956
|
+
${ /* An OPENED district is a PANEL, not a pill with a list stuffed in it:
|
|
957
|
+
name and count share the header line, the roster sits under a hairline,
|
|
958
|
+
and the block behind fades — the plate IS the district while it is
|
|
959
|
+
open, so no roof pokes out above the roster. */""}
|
|
846
960
|
[data-graview-altitude] .graview-kind-face[data-graview-opened] {
|
|
847
|
-
/* A header that WRAPS rather than a grid that squeezes: the name's column
|
|
848
|
-
|
|
849
|
-
|
|
961
|
+
${ /* A header that WRAPS rather than a grid that squeezes: the name's column
|
|
962
|
+
was minmax(0, 1fr) beside the count's auto, so "VEHICLES" beside
|
|
963
|
+
"291 · +29 past · close" got 25 pixels and the count was drawn over it. */""}
|
|
850
964
|
display: flex !important;
|
|
851
965
|
flex-wrap: wrap;
|
|
852
966
|
justify-content: flex-start !important;
|
|
@@ -869,9 +983,9 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
869
983
|
opacity: calc(var(--graview-altitude) * 0.22);
|
|
870
984
|
}
|
|
871
985
|
|
|
872
|
-
/* WHAT KIND OF THING THIS IS, astride the focus panel's top-right edge —
|
|
873
|
-
|
|
874
|
-
|
|
986
|
+
${ /* WHAT KIND OF THING THIS IS, astride the focus panel's top-right edge —
|
|
987
|
+
the kind's dot and its name, the same thread the chips and the legend
|
|
988
|
+
carry. Scene chrome, so no view has to remember to say it. */""}
|
|
875
989
|
.graview-kind-tag {
|
|
876
990
|
position: absolute;
|
|
877
991
|
top: -9px;
|
|
@@ -882,8 +996,8 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
882
996
|
gap: 5px;
|
|
883
997
|
padding: 2px 8px;
|
|
884
998
|
border-radius: 999px;
|
|
885
|
-
/* The kind's own hue on the border and the words, so the tag and the
|
|
886
|
-
|
|
999
|
+
${ /* The kind's own hue on the border and the words, so the tag and the
|
|
1000
|
+
district it belongs to read as one thread. */""}
|
|
887
1001
|
border: 1px solid hsl(var(--graview-hue, 200) 45% var(--graview-tint-lightness) / 0.55);
|
|
888
1002
|
color: hsl(var(--graview-hue, 200) 45% calc(var(--graview-tint-lightness) + ${scheme === "light" ? "-32%" : "28%"}));
|
|
889
1003
|
background: var(--graview-float);
|
|
@@ -895,28 +1009,28 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
895
1009
|
pointer-events: none;
|
|
896
1010
|
}
|
|
897
1011
|
|
|
898
|
-
/* A LINE UNDER THE POINTER says it will take the press: the invisible hit
|
|
899
|
-
|
|
900
|
-
|
|
1012
|
+
${ /* A LINE UNDER THE POINTER says it will take the press: the invisible hit
|
|
1013
|
+
run ghosts in, so editability is discoverable by hovering the relation
|
|
1014
|
+
itself rather than by rumor. */""}
|
|
901
1015
|
.graview-edge-hit:hover {
|
|
902
1016
|
stroke: var(--graview-accent);
|
|
903
1017
|
opacity: 0.3;
|
|
904
1018
|
}
|
|
905
1019
|
|
|
906
|
-
/* THE DISTRICTS THE ROW COULD NOT HOLD.
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
/* A RELATION THE BAND COULD NOT HOLD: a group with its count and first names,
|
|
913
|
-
|
|
1020
|
+
${ /* THE DISTRICTS THE ROW COULD NOT HOLD.
|
|
1021
|
+
Not a district: no figure, no count, no tint of its own. A card that is
|
|
1022
|
+
one control — how many more, and a press — and, open, a panel above the
|
|
1023
|
+
row naming every district with what it holds. Solid rather than dashed
|
|
1024
|
+
and faded: a dashed, translucent card read as a placeholder, and the only
|
|
1025
|
+
way to five districts should not look like something that failed to load. */""}
|
|
1026
|
+
${ /* A RELATION THE BAND COULD NOT HOLD: a group with its count and first names,
|
|
1027
|
+
or the door to the rest. A card like the others, never the kind's lens small. */""}
|
|
914
1028
|
.graview-band-group {
|
|
915
1029
|
display: grid;
|
|
916
1030
|
align-content: center;
|
|
917
1031
|
gap: 2px;
|
|
918
1032
|
height: 100%;
|
|
919
|
-
/* A card you press, held to the floor every pressable piece of chrome keeps. */
|
|
1033
|
+
${ /* A card you press, held to the floor every pressable piece of chrome keeps. */""}
|
|
920
1034
|
min-height: max(1.75rem, 28px);
|
|
921
1035
|
box-sizing: border-box;
|
|
922
1036
|
padding: 6px 10px;
|
|
@@ -1014,16 +1128,16 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1014
1128
|
margin-left: auto;
|
|
1015
1129
|
font-size: 0.8125rem;
|
|
1016
1130
|
}
|
|
1017
|
-
/* The panel stands above the card, inside the scene, and never clips: the
|
|
1018
|
-
|
|
1131
|
+
${ /* The panel stands above the card, inside the scene, and never clips: the
|
|
1132
|
+
card's box is a district's height, which holds a count and not a list. */""}
|
|
1019
1133
|
.graview-beyond-list {
|
|
1020
1134
|
position: absolute;
|
|
1021
1135
|
left: 0;
|
|
1022
1136
|
bottom: calc(100% + 6px);
|
|
1023
|
-
/* On the ground, over every plane — the focused card on plane zero
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1137
|
+
${ /* On the ground, over every plane — the focused card on plane zero
|
|
1138
|
+
painted over a panel drawn on plane two, and a menu under a card is
|
|
1139
|
+
no menu. Above the zoom control too, which is the only other thing
|
|
1140
|
+
that stands on the ground. */""}
|
|
1027
1141
|
z-index: 60;
|
|
1028
1142
|
margin: 0;
|
|
1029
1143
|
padding: 6px;
|
|
@@ -1031,8 +1145,8 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1031
1145
|
display: flex;
|
|
1032
1146
|
flex-direction: column;
|
|
1033
1147
|
gap: 1px;
|
|
1034
|
-
/* Its own width, not the ground's: portalled, a percentage here is the
|
|
1035
|
-
|
|
1148
|
+
${ /* Its own width, not the ground's: portalled, a percentage here is the
|
|
1149
|
+
whole scene. */""}
|
|
1036
1150
|
min-width: 200px;
|
|
1037
1151
|
max-width: min(280px, 92%);
|
|
1038
1152
|
max-height: 60vh;
|
|
@@ -1047,14 +1161,14 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1047
1161
|
align-items: center;
|
|
1048
1162
|
gap: 10px;
|
|
1049
1163
|
width: 100%;
|
|
1050
|
-
/* A FINGERTIP WHERE IT IS ACTUALLY DRAWN, not where it was designed.
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1164
|
+
${ /* A FINGERTIP WHERE IT IS ACTUALLY DRAWN, not where it was designed.
|
|
1165
|
+
Every other control in this sheet is floored at 24 and the audit divides
|
|
1166
|
+
by the plane's scale before judging it, which is right for a control
|
|
1167
|
+
that sits ON a large target: the chip's disclosure is small, and the
|
|
1168
|
+
card behind it is the size of a card. These names are not that. They are
|
|
1169
|
+
the ONLY way to the districts the row could not hold, and plane two is
|
|
1170
|
+
drawn at 0.90 — so a designed 24 meets a finger as 21.7. Designed at 28
|
|
1171
|
+
it is drawn at 25, which is the number the floor was always about. */""}
|
|
1058
1172
|
min-height: max(1.75rem, 28px);
|
|
1059
1173
|
padding: 0 8px;
|
|
1060
1174
|
border: none;
|
|
@@ -1083,13 +1197,13 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1083
1197
|
color: var(--graview-ink-faint);
|
|
1084
1198
|
}
|
|
1085
1199
|
|
|
1086
|
-
/* The way into the archive, on the card that fed it: quiet, but a real
|
|
1087
|
-
|
|
1200
|
+
${ /* The way into the archive, on the card that fed it: quiet, but a real
|
|
1201
|
+
control at a real size. */""}
|
|
1088
1202
|
.graview-kind-past {
|
|
1089
1203
|
display: inline-flex;
|
|
1090
1204
|
align-items: center;
|
|
1091
1205
|
flex: 0 0 auto;
|
|
1092
|
-
/* The same floor as the disclosure beside it — see .graview-kind-open. */
|
|
1206
|
+
${ /* The same floor as the disclosure beside it — see .graview-kind-open. */""}
|
|
1093
1207
|
min-height: max(1.5rem, 24px);
|
|
1094
1208
|
padding: 1px 8px;
|
|
1095
1209
|
margin: -3px 0;
|
|
@@ -1107,10 +1221,10 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1107
1221
|
border-color: var(--graview-accent-dim);
|
|
1108
1222
|
}
|
|
1109
1223
|
|
|
1110
|
-
/* A SEARCH OVER THE CITY. The districts the words found are lit and say how
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1224
|
+
${ /* A SEARCH OVER THE CITY. The districts the words found are lit and say how
|
|
1225
|
+
many; the rest recede — the same dimming a selection's reach has always
|
|
1226
|
+
used, so a search reads as "where the thing is", not as a new mode. The
|
|
1227
|
+
count is the way in: a real control, the words carried down. */""}
|
|
1114
1228
|
.graview-kind-card[data-graview-emphasis="dimmed"] {
|
|
1115
1229
|
opacity: 0.42;
|
|
1116
1230
|
transition: opacity 160ms ease;
|
|
@@ -1143,27 +1257,27 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1143
1257
|
.graview-kind-card[data-graview-emphasis="dimmed"] { transition: none; }
|
|
1144
1258
|
}
|
|
1145
1259
|
|
|
1146
|
-
/* Chrome that arrives with a state settles in rather than popping. */
|
|
1260
|
+
${ /* Chrome that arrives with a state settles in rather than popping. */""}
|
|
1147
1261
|
@keyframes graview-settle {
|
|
1148
1262
|
from { opacity: 0; transform: translateY(7px); }
|
|
1149
1263
|
}
|
|
1150
1264
|
|
|
1151
|
-
/* A district STANDS: an isometric block — roof, two shaded walls — whose
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1265
|
+
${ /* A district STANDS: an isometric block — roof, two shaded walls — whose
|
|
1266
|
+
height is its population. Always in the tree, faded and settled by the
|
|
1267
|
+
altitude number: rising, each block grows up out of its card while the
|
|
1268
|
+
card flies to its ring stop — a morph, not a cut. At altitude zero it is
|
|
1269
|
+
fully transparent and costs nothing. */""}
|
|
1156
1270
|
.graview-kind-block {
|
|
1157
1271
|
display: block;
|
|
1158
|
-
/* Architecture, not a control: clicks fall through to the card, and an
|
|
1159
|
-
|
|
1272
|
+
${ /* Architecture, not a control: clicks fall through to the card, and an
|
|
1273
|
+
invisible in-stack block must never sit over a neighbour's tuck. */""}
|
|
1160
1274
|
pointer-events: none;
|
|
1161
1275
|
position: absolute;
|
|
1162
1276
|
left: 8%;
|
|
1163
1277
|
bottom: 2px;
|
|
1164
1278
|
width: 84%;
|
|
1165
1279
|
height: auto;
|
|
1166
|
-
/* Under a marquee the block keeps out of its band: the drawing scales down inside the box. */
|
|
1280
|
+
${ /* Under a marquee the block keeps out of its band: the drawing scales down inside the box. */""}
|
|
1167
1281
|
max-height: calc(100% - var(--graview-marquee-room, 0px));
|
|
1168
1282
|
opacity: var(--graview-altitude);
|
|
1169
1283
|
transform: translateY(calc((1 - var(--graview-altitude)) * 18px));
|
|
@@ -1181,64 +1295,64 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1181
1295
|
fill: hsl(var(--graview-hue, 200) ${scheme === "light" ? "34% 55%" : "38% 13%"});
|
|
1182
1296
|
}
|
|
1183
1297
|
|
|
1184
|
-
/* WHERE THE KIND HAS ITS OWN DRAWING, the drawing is the building.
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1298
|
+
${ /* WHERE THE KIND HAS ITS OWN DRAWING, the drawing is the building.
|
|
1299
|
+
Same footprint as the block, same ground line, same cast shadow — the
|
|
1300
|
+
difference is that the district is now a person, a plot or a vehicle
|
|
1301
|
+
rather than one more box. Size carries the population the box's height
|
|
1302
|
+
used to: the rise the card computed, in a channel a drawing can use.
|
|
1303
|
+
|
|
1304
|
+
Stroke weight is set HERE rather than in the art, because the art is
|
|
1305
|
+
drawn to read at twenty pixels and a 1.4-unit stroke on a 24-unit box
|
|
1306
|
+
becomes a six-pixel marker line at a hundred. Thinned to a drafting
|
|
1307
|
+
line, which is what a blueprint of a thing looks like. */""}
|
|
1194
1308
|
.graview-kind-landmark {
|
|
1195
1309
|
display: block;
|
|
1196
1310
|
left: 50%;
|
|
1197
|
-
/* The block's own two pixels of ground clearance, kept: at altitude zero
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1311
|
+
${ /* The block's own two pixels of ground clearance, kept: at altitude zero
|
|
1312
|
+
every block is pushed eighteen pixels down as part of the morph, and
|
|
1313
|
+
without them the drawing hangs two pixels past the bottom of the scene
|
|
1314
|
+
and gives the whole page a scrollbar's worth of overflow. */""}
|
|
1201
1315
|
bottom: 2px;
|
|
1202
1316
|
aspect-ratio: 1;
|
|
1203
|
-
/* Sized by the card's HEIGHT, not its width: a district card is wider
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1317
|
+
${ /* Sized by the card's HEIGHT, not its width: a district card is wider
|
|
1318
|
+
than it is tall, and a square drawing at 96% of the width stood a third
|
|
1319
|
+
of itself above the card and back through the nameplate. Population is
|
|
1320
|
+
in the drawing's size either way — the same rise the box's height
|
|
1321
|
+
carried, 10 for a district of one and 46 for the largest. */""}
|
|
1208
1322
|
height: calc((100% - var(--graview-marquee-room, 0px)) * (0.72 + var(--graview-rise, 24) * 0.008));
|
|
1209
1323
|
width: auto;
|
|
1210
|
-
/* AND IT KEEPS UP WITH THE WORDS. The card is laid out in pixels off the
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1324
|
+
${ /* AND IT KEEPS UP WITH THE WORDS. The card is laid out in pixels off the
|
|
1325
|
+
stage and the nameplate is sized in rem, so a reader on Largest doubled
|
|
1326
|
+
every name in the city while every drawing under one stayed exactly the
|
|
1327
|
+
size it was — a postage stamp under a headline. A floor in em ties the
|
|
1328
|
+
drawing to the same number the names follow; at the browser's own size
|
|
1329
|
+
it is below what the card already gives and nothing moves.
|
|
1330
|
+
|
|
1331
|
+
Capped at the card, because a floor alone overflowed it: the drawings
|
|
1332
|
+
grew past the box they stand in and were sliced off at the bottom
|
|
1333
|
+
edge — a plot that reads as a V rather than a bed. The card's own
|
|
1334
|
+
height is what the picture can actually show, and the CARD is the thing
|
|
1335
|
+
that still does not follow the reader's size (see below).
|
|
1336
|
+
|
|
1337
|
+
(No back ticks in here: this whole stylesheet is a template literal,
|
|
1338
|
+
and one of them ends it.) */""}
|
|
1225
1339
|
min-height: min(5em, calc(96% - var(--graview-marquee-room, 0px)));
|
|
1226
|
-
/* The morph is a GROWTH from the ground line, not a drop: a block slides
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1340
|
+
${ /* The morph is a GROWTH from the ground line, not a drop: a block slides
|
|
1341
|
+
eighteen pixels down at altitude zero and grows up out of the card, and
|
|
1342
|
+
a drawing given the same treatment hangs below the card it belongs to —
|
|
1343
|
+
two pixels past the bottom of the scene on the lowest row, which is a
|
|
1344
|
+
scrollbar on every ground-level screen in the app. Scaling from the
|
|
1345
|
+
drawing's own feet is the same reading and costs nothing below. */""}
|
|
1232
1346
|
transform-origin: bottom center;
|
|
1233
1347
|
transform: translateX(-50%) scale(calc(0.55 + var(--graview-altitude) * 0.45));
|
|
1234
|
-
/* A cast shadow belongs to a solid; on a line drawing it is a blurred
|
|
1235
|
-
|
|
1236
|
-
|
|
1348
|
+
${ /* A cast shadow belongs to a solid; on a line drawing it is a blurred
|
|
1349
|
+
second copy of every stroke. The drawing keeps a hint of one so it
|
|
1350
|
+
still stands on the lattice rather than floating over it. */""}
|
|
1237
1351
|
filter: drop-shadow(${scheme === "light" ? "6px 5px 7px rgba(20,30,32,0.16)" : "7px 6px 9px rgba(0,0,0,0.45)"});
|
|
1238
1352
|
}
|
|
1239
|
-
/* The nameplate floats ABOVE a drawing rather than standing on it. On a box
|
|
1240
|
-
|
|
1241
|
-
|
|
1353
|
+
${ /* The nameplate floats ABOVE a drawing rather than standing on it. On a box
|
|
1354
|
+
the pill sits on the roof, which is what a label does over a building; on
|
|
1355
|
+
a figure the same 2% put it across the head. */""}
|
|
1242
1356
|
|
|
1243
1357
|
.graview-kind-landmark [data-graview-figure] {
|
|
1244
1358
|
width: 100% !important;
|
|
@@ -1251,29 +1365,29 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1251
1365
|
stroke-width: 0.85;
|
|
1252
1366
|
}
|
|
1253
1367
|
|
|
1254
|
-
/* From altitude the card's face becomes the district's NAMEPLATE: an
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1368
|
+
${ /* From altitude the card's face becomes the district's NAMEPLATE: an
|
|
1369
|
+
upright pill standing on the roof, the way a label floats over a building
|
|
1370
|
+
in any city view — the block carries the architecture, the pill carries
|
|
1371
|
+
the words. Inline styles drew the in-stack card, so the pill overrides
|
|
1372
|
+
must outrank them. */""}
|
|
1259
1373
|
.graview-kind-face {
|
|
1260
1374
|
transition: border-radius 640ms cubic-bezier(0.33, 0, 0.2, 1),
|
|
1261
1375
|
padding 640ms cubic-bezier(0.33, 0, 0.2, 1),
|
|
1262
1376
|
box-shadow 640ms ease;
|
|
1263
1377
|
}
|
|
1264
|
-
/* A SIGNPOST at the plot's front corner. From altitude the nameplate stood
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1378
|
+
${ /* A SIGNPOST at the plot's front corner. From altitude the nameplate stood
|
|
1379
|
+
at the top of the card — over the back row of the village — and the
|
|
1380
|
+
screen had to clear it. It is planted at the front vertex of the tile
|
|
1381
|
+
now, on a short post, where a sign stands at the entrance to a place;
|
|
1382
|
+
the scene says where that vertex is in --graview-front-y. */""}
|
|
1269
1383
|
[data-graview-altitude] .graview-kind-face {
|
|
1270
1384
|
position: absolute !important;
|
|
1271
1385
|
left: 50% !important;
|
|
1272
1386
|
top: 2% !important;
|
|
1273
1387
|
transform: translateX(-50%);
|
|
1274
1388
|
width: max-content;
|
|
1275
|
-
/* Wider than the block when the name is: a label overflows its building
|
|
1276
|
-
|
|
1389
|
+
${ /* Wider than the block when the name is: a label overflows its building
|
|
1390
|
+
the way a map label does. "REQUIRE / MENTS" on two lines does not. */""}
|
|
1277
1391
|
max-width: none;
|
|
1278
1392
|
white-space: nowrap;
|
|
1279
1393
|
height: auto !important;
|
|
@@ -1297,38 +1411,38 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1297
1411
|
height: 10px;
|
|
1298
1412
|
background: var(--graview-ink-faint);
|
|
1299
1413
|
}
|
|
1300
|
-
/* A landmark WITHOUT a plot — a nested card — keeps its plate floating
|
|
1301
|
-
|
|
1302
|
-
|
|
1414
|
+
${ /* A landmark WITHOUT a plot — a nested card — keeps its plate floating
|
|
1415
|
+
above the drawing rather than across its head; one on a plot stands at
|
|
1416
|
+
the signpost like every other district (the rule above). */""}
|
|
1303
1417
|
[data-graview-altitude] [data-graview-landmark]:not([data-graview-plot] *) .graview-kind-face {
|
|
1304
1418
|
top: 0 !important;
|
|
1305
1419
|
transform: translate(-50%, calc(-100% - 7px));
|
|
1306
1420
|
}
|
|
1307
|
-
/* The drive-in's board hangs UNDER the signpost, in the ground the layout
|
|
1308
|
-
|
|
1421
|
+
${ /* The drive-in's board hangs UNDER the signpost, in the ground the layout
|
|
1422
|
+
reserved for it below the tile's front corner, not over the village. */""}
|
|
1309
1423
|
[data-graview-altitude] .graview-drive-in {
|
|
1310
1424
|
top: calc(var(--graview-front-y, 42px) + 12px);
|
|
1311
1425
|
}
|
|
1312
|
-
/* An OPENED district's listing takes the ground under the signpost; the
|
|
1313
|
-
|
|
1426
|
+
${ /* An OPENED district's listing takes the ground under the signpost; the
|
|
1427
|
+
board steps up over the village, which the listing covers anyway. */""}
|
|
1314
1428
|
[data-graview-altitude] .graview-kind-face[data-graview-opened] ~ .graview-drive-in {
|
|
1315
1429
|
top: calc(var(--graview-front-y, 42px) - 22px - var(--graview-marquee-room, 0px) + 8px);
|
|
1316
1430
|
}
|
|
1317
|
-
/* THE LANDMARK STANDS IN THE SQUARE: its feet at the plot's centre, among
|
|
1318
|
-
|
|
1319
|
-
|
|
1431
|
+
${ /* THE LANDMARK STANDS IN THE SQUARE: its feet at the plot's centre, among
|
|
1432
|
+
the buildings, rather than at the card's bottom edge — which, once the
|
|
1433
|
+
card grew for a board, was out in the road in front of the village. */""}
|
|
1320
1434
|
[data-graview-altitude] [data-graview-plot] .graview-kind-landmark {
|
|
1321
1435
|
bottom: auto;
|
|
1322
1436
|
top: calc(var(--graview-centre-y, 50%) + 10px);
|
|
1323
1437
|
transform: translate(-50%, -100%) scale(calc(0.55 + var(--graview-altitude) * 0.45));
|
|
1324
1438
|
}
|
|
1325
|
-
/* ZOOM, in the ground's corner: the way a map carries its own. Two
|
|
1326
|
-
|
|
1439
|
+
${ /* ZOOM, in the ground's corner: the way a map carries its own. Two
|
|
1440
|
+
fingertip-sized buttons and the level between them, shown from altitude. */""}
|
|
1327
1441
|
.graview-zoom {
|
|
1328
1442
|
position: absolute;
|
|
1329
1443
|
right: 16px;
|
|
1330
1444
|
bottom: 16px;
|
|
1331
|
-
/* Above the occupants: a robot walking past a control must not cover it. */
|
|
1445
|
+
${ /* Above the occupants: a robot walking past a control must not cover it. */""}
|
|
1332
1446
|
z-index: 8;
|
|
1333
1447
|
display: inline-flex;
|
|
1334
1448
|
align-items: center;
|
|
@@ -1366,16 +1480,16 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1366
1480
|
font-variant-numeric: tabular-nums;
|
|
1367
1481
|
}
|
|
1368
1482
|
|
|
1369
|
-
/* THE SCREEN IS A BILLBOARD at the back of the village: a frame, and two
|
|
1370
|
-
|
|
1371
|
-
/* On the NATURAL BOX, which is the picture now: the layout cuts the
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1483
|
+
${ /* THE SCREEN IS A BILLBOARD at the back of the village: a frame, and two
|
|
1484
|
+
posts into the ground at its foot. */""}
|
|
1485
|
+
${ /* On the NATURAL BOX, which is the picture now: the layout cuts the
|
|
1486
|
+
billboard to what the lens drew (measured by the scene), never shorter
|
|
1487
|
+
than a screen's worth — so the box is the picture, and an empty lens is a
|
|
1488
|
+
header over an empty screen rather than a strip floating over the
|
|
1489
|
+
village. The frame used to sit on the drawing itself, from the days the
|
|
1490
|
+
box was as tall as the window with the picture in its top third. It
|
|
1491
|
+
carries the panel's own ground so the empty part of a screen is a screen
|
|
1492
|
+
and not the field showing through a frame. */""}
|
|
1379
1493
|
[data-graview-altitude] [data-graview-screen] > [data-graview-natural],
|
|
1380
1494
|
[data-graview-altitude] [data-graview-screen] > :not([data-graview-natural]):not(.graview-kind-tag) {
|
|
1381
1495
|
outline: 2px solid color-mix(in oklab, var(--graview-ink) 60%, var(--graview-panel));
|
|
@@ -1401,31 +1515,31 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1401
1515
|
[data-graview-altitude] [data-graview-screen] > [data-graview-natural]::after,
|
|
1402
1516
|
[data-graview-altitude] [data-graview-screen] > :not([data-graview-natural]):not(.graview-kind-tag)::after { right: 22%; }
|
|
1403
1517
|
|
|
1404
|
-
/* A thing inside a view that is itself a thing: an event in a calendar, a
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
/* A card someone dragged into place. Marked, not decorated: a dotted tie to
|
|
1409
|
-
|
|
1410
|
-
/* On the CHILD, not the host: the host is the layout's box, and a view
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
/* And never on the natural box either — a view drawn scaled sits inside a
|
|
1415
|
-
|
|
1416
|
-
|
|
1518
|
+
${ /* A thing inside a view that is itself a thing: an event in a calendar, a
|
|
1519
|
+
person in a list. It has to look reachable, and it has to SHOW focus —
|
|
1520
|
+
these are the primary way anyone moves through the graph, so a keyboard
|
|
1521
|
+
user who cannot see where they are is stuck. */""}
|
|
1522
|
+
${ /* A card someone dragged into place. Marked, not decorated: a dotted tie to
|
|
1523
|
+
say this position is held rather than computed. */""}
|
|
1524
|
+
${ /* On the CHILD, not the host: the host is the layout's box, and a view
|
|
1525
|
+
that sizes to its content (a zoomed record, a fit panel) fills only part
|
|
1526
|
+
of it — a dashed box around the empty remainder read as a drawing
|
|
1527
|
+
mistake, not a mark. */""}
|
|
1528
|
+
${ /* And never on the natural box either — a view drawn scaled sits inside a
|
|
1529
|
+
box the size of the whole scene, and the mark belongs on the drawing, not
|
|
1530
|
+
on the box; nor on the kind tag, which is a label and not the thing. */""}
|
|
1417
1531
|
[data-graview-pinned] > :not([data-graview-natural]):not(.graview-kind-tag),
|
|
1418
1532
|
[data-graview-pinned] > [data-graview-natural] > * {
|
|
1419
1533
|
outline: 1px dashed var(--graview-edge-bright);
|
|
1420
1534
|
outline-offset: 3px;
|
|
1421
1535
|
border-radius: 12px;
|
|
1422
1536
|
}
|
|
1423
|
-
/* AND NOT FROM ALTITUDE, where a district is a village on a plot and its
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1537
|
+
${ /* AND NOT FROM ALTITUDE, where a district is a village on a plot and its
|
|
1538
|
+
card is a box with nothing drawn in it: the dashed outline was the only
|
|
1539
|
+
visible part, so a hand-placed district read as an empty rounded
|
|
1540
|
+
rectangle sitting on the ground — several of them, in a picture that had
|
|
1541
|
+
no rectangles in it. The plot's own kerb goes dashed up here, which is
|
|
1542
|
+
the same fact said where the district actually is. */""}
|
|
1429
1543
|
[data-graview-altitude] [data-graview-pinned] > :not([data-graview-natural]):not(.graview-kind-tag),
|
|
1430
1544
|
[data-graview-altitude] [data-graview-pinned] > [data-graview-natural] > * {
|
|
1431
1545
|
outline: none;
|
|
@@ -1443,10 +1557,10 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1443
1557
|
outline-offset: 2px;
|
|
1444
1558
|
border-radius: 7px;
|
|
1445
1559
|
}
|
|
1446
|
-
/* On a board the keyboard ring hugs the DISC, not the disc-plus-label
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1560
|
+
${ /* On a board the keyboard ring hugs the DISC, not the disc-plus-label
|
|
1561
|
+
group: a rectangle drawn around a circle read as a mystery box on the
|
|
1562
|
+
pitch ("why does Left Midfield have this box?"), when all it ever said
|
|
1563
|
+
was "the keyboard is here". */""}
|
|
1450
1564
|
[data-graview-slot]:focus-visible {
|
|
1451
1565
|
outline: none;
|
|
1452
1566
|
}
|
|
@@ -1454,7 +1568,7 @@ code, kbd, samp { font-family: var(--graview-font-mono); }
|
|
|
1454
1568
|
box-shadow: 0 0 0 2px var(--graview-ground), 0 0 0 4px var(--graview-accent);
|
|
1455
1569
|
}
|
|
1456
1570
|
|
|
1457
|
-
/* A view is a thing you can act on. It should look like one. */
|
|
1571
|
+
${ /* A view is a thing you can act on. It should look like one. */""}
|
|
1458
1572
|
[data-graview-view] { cursor: pointer; }
|
|
1459
1573
|
[data-graview-view]:hover { filter: brightness(${scheme === "light" ? 0.985 : 1.12}); }
|
|
1460
1574
|
[data-graview-view]:focus-visible {
|
|
@@ -1488,25 +1602,25 @@ button:disabled { opacity: 0.45; cursor: default; }
|
|
|
1488
1602
|
|
|
1489
1603
|
code { color: var(--graview-ink-muted); font-size: 0.8125rem; letter-spacing: 0.02em; }
|
|
1490
1604
|
|
|
1491
|
-
/* A view host, once the scene has placed it. The transition is on filter
|
|
1492
|
-
|
|
1493
|
-
|
|
1605
|
+
${ /* A view host, once the scene has placed it. The transition is on filter
|
|
1606
|
+
only — never on layout properties, which would make every navigation
|
|
1607
|
+
reflow the page. */""}
|
|
1494
1608
|
[data-graview-view] {
|
|
1495
1609
|
transition: filter 260ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
1496
1610
|
}
|
|
1497
1611
|
|
|
1498
|
-
/* WHAT YOU CAN PRESS IS WHAT YOU CAN SEE.
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1612
|
+
${ /* WHAT YOU CAN PRESS IS WHAT YOU CAN SEE.
|
|
1613
|
+
|
|
1614
|
+
A host is the box the LAYOUT gave a view — a band on the ground, the whole
|
|
1615
|
+
scene scaled small from altitude — and a view that sizes to its content
|
|
1616
|
+
fills only part of it. The rest is invisible, and an invisible box must
|
|
1617
|
+
not be a target: a record read from altitude and pinned beside a district
|
|
1618
|
+
covered that district's open button with nothing at all, and the button
|
|
1619
|
+
stopped answering. So the host itself is out of hit-testing on the DOM
|
|
1620
|
+
path and only the drawn content is in; every handler still hears the
|
|
1621
|
+
content's events on the way up. The GPU path keeps its own rule: there
|
|
1622
|
+
the whole subtree stays out, because the platform's hit-test descending
|
|
1623
|
+
into a captured view brings the renderer down. */""}
|
|
1510
1624
|
[data-graview-stage="dom"] [data-graview-view],
|
|
1511
1625
|
[data-graview-stage="dom"] [data-graview-view] > [data-graview-natural] {
|
|
1512
1626
|
pointer-events: none;
|
|
@@ -1519,11 +1633,11 @@ code { color: var(--graview-ink-muted); font-size: 0.8125rem; letter-spacing: 0.
|
|
|
1519
1633
|
filter: drop-shadow(0 0 14px var(--graview-accent-dim));
|
|
1520
1634
|
}
|
|
1521
1635
|
|
|
1522
|
-
/* A node implicated by the last change, whoever made it. The pulse is the
|
|
1523
|
-
|
|
1524
|
-
/* THE SEAT'S MARK on what it just wrote: its own glyph, in its own hue, at
|
|
1525
|
-
|
|
1526
|
-
|
|
1636
|
+
${ /* A node implicated by the last change, whoever made it. The pulse is the
|
|
1637
|
+
same for a human edit and an agent edit, because the diff is. */""}
|
|
1638
|
+
${ /* THE SEAT'S MARK on what it just wrote: its own glyph, in its own hue, at
|
|
1639
|
+
the thing's top-right corner. It arrives with the change and fades with
|
|
1640
|
+
it; the companion's log is what remembers. */""}
|
|
1527
1641
|
.graview-seat-marks {
|
|
1528
1642
|
position: absolute;
|
|
1529
1643
|
inset: 0;
|
|
@@ -1546,9 +1660,9 @@ code { color: var(--graview-ink-muted); font-size: 0.8125rem; letter-spacing: 0.
|
|
|
1546
1660
|
box-shadow: var(--graview-lift-low);
|
|
1547
1661
|
animation: graview-seat-mark 4000ms ease-out forwards;
|
|
1548
1662
|
}
|
|
1549
|
-
/* A QUESTION THE SEAT ASKED, standing at the node it is about: it says
|
|
1550
|
-
|
|
1551
|
-
|
|
1663
|
+
${ /* A QUESTION THE SEAT ASKED, standing at the node it is about: it says
|
|
1664
|
+
itself and waits, because a dot nobody can read is a question nobody
|
|
1665
|
+
answers. It does not fade — an unanswered question is still open. */""}
|
|
1552
1666
|
.graview-seat-asking {
|
|
1553
1667
|
position: absolute;
|
|
1554
1668
|
transform: translate(-50%, -100%);
|
|
@@ -1599,20 +1713,20 @@ code { color: var(--graview-ink-muted); font-size: 0.8125rem; letter-spacing: 0.
|
|
|
1599
1713
|
border-radius: 10px;
|
|
1600
1714
|
}
|
|
1601
1715
|
|
|
1602
|
-
/* ------------------------------------------------------------ watching
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1716
|
+
${ /* ------------------------------------------------------------ watching
|
|
1717
|
+
*
|
|
1718
|
+
* From outside the plane stack, activity has somewhere to HAPPEN: a kind
|
|
1719
|
+
* lights where an edit landed, an edge pulses where a relation was made or
|
|
1720
|
+
* broken, and a flag appears where a rule started failing. All of it is
|
|
1721
|
+
* derived from the op log — author, intent, reads and writes — and all of it
|
|
1722
|
+
* is drawn by these rules rather than by a frame loop, which is why watching
|
|
1723
|
+
* costs nothing while nothing is happening.
|
|
1724
|
+
*
|
|
1725
|
+
* Who moved is carried in HUE, not in a badge. A person is the accent the
|
|
1726
|
+
* whole interface already uses for "you did this"; an agent is a colder cast,
|
|
1727
|
+
* so a turn it took on its own is distinguishable at a glance from one you
|
|
1728
|
+
* directed; both at once takes both.
|
|
1729
|
+
*/""}
|
|
1616
1730
|
[data-graview-activity] {
|
|
1617
1731
|
--graview-activity: var(--graview-accent);
|
|
1618
1732
|
}
|
|
@@ -1636,9 +1750,9 @@ code { color: var(--graview-ink-muted); font-size: 0.8125rem; letter-spacing: 0.
|
|
|
1636
1750
|
border-radius: 10px;
|
|
1637
1751
|
}
|
|
1638
1752
|
|
|
1639
|
-
/* What an agent READ is the half a diff cannot show, and the half that says
|
|
1640
|
-
|
|
1641
|
-
|
|
1753
|
+
${ /* What an agent READ is the half a diff cannot show, and the half that says
|
|
1754
|
+
whether to trust what it then did. Quieter than a write on purpose: it is
|
|
1755
|
+
evidence of attention, not of a change. */""}
|
|
1642
1756
|
@keyframes graview-considered {
|
|
1643
1757
|
0% { outline-color: transparent; }
|
|
1644
1758
|
25% { outline-color: var(--graview-activity); }
|
|
@@ -1652,15 +1766,15 @@ code { color: var(--graview-ink-muted); font-size: 0.8125rem; letter-spacing: 0.
|
|
|
1652
1766
|
animation: graview-considered 1800ms ease-out;
|
|
1653
1767
|
}
|
|
1654
1768
|
|
|
1655
|
-
/* A rule that has just begun to fail. It outlives the edit that caused it,
|
|
1656
|
-
|
|
1769
|
+
${ /* A rule that has just begun to fail. It outlives the edit that caused it,
|
|
1770
|
+
because the problem does. */""}
|
|
1657
1771
|
[data-graview-view][data-graview-broke] > * {
|
|
1658
1772
|
box-shadow: 0 0 0 1px var(--graview-warn), 0 0 22px -6px var(--graview-warn);
|
|
1659
1773
|
border-radius: 10px;
|
|
1660
1774
|
}
|
|
1661
1775
|
|
|
1662
|
-
/* A relation made or broken: both ends were written, so the line between
|
|
1663
|
-
|
|
1776
|
+
${ /* A relation made or broken: both ends were written, so the line between
|
|
1777
|
+
them is the thing that changed. */""}
|
|
1664
1778
|
@keyframes graview-relation {
|
|
1665
1779
|
0% { stroke-opacity: 0.28; stroke-width: 1.4; }
|
|
1666
1780
|
30% { stroke-opacity: 1; stroke-width: 3; }
|
|
@@ -1670,28 +1784,28 @@ code { color: var(--graview-ink-muted); font-size: 0.8125rem; letter-spacing: 0.
|
|
|
1670
1784
|
animation: graview-relation 1200ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
1671
1785
|
}
|
|
1672
1786
|
|
|
1673
|
-
/*
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1787
|
+
${ /*
|
|
1788
|
+
* MOTION, ASKED OF THE SYSTEM AND OVERRIDABLE BY THE PERSON.
|
|
1789
|
+
*
|
|
1790
|
+
* The system's own preference is the default and always was. The "motion"
|
|
1791
|
+
* setting (see readerSettings) stamps data-graview-motion on the root
|
|
1792
|
+
* element when — and only when — a reader overrides it: "reduce" turns the same
|
|
1793
|
+
* rules on for somebody whose system says otherwise, and "full" turns them
|
|
1794
|
+
* off for somebody whose system says reduce and who wants the movement
|
|
1795
|
+
* here anyway. Choosing "as your system has it" removes the attribute, so
|
|
1796
|
+
* the media query is what answers again.
|
|
1797
|
+
*
|
|
1798
|
+
* Written as one rule list under two selectors rather than duplicated,
|
|
1799
|
+
* because a stylesheet where the two copies can drift is a stylesheet where
|
|
1800
|
+
* they will.
|
|
1801
|
+
*/""}
|
|
1688
1802
|
@media (prefers-reduced-motion: reduce) {
|
|
1689
1803
|
.graview-figure { transition: none; }
|
|
1690
1804
|
${stillness(`${motionRoot}:not([data-graview-motion='full'])`, text)}
|
|
1691
1805
|
}
|
|
1692
1806
|
${stillness(`${motionRoot}[data-graview-motion='reduce']`, text)}
|
|
1693
1807
|
|
|
1694
|
-
/* VIEWS AS DATA (FR-03): the blocks a view spec is drawn with, over the tokens above. */
|
|
1808
|
+
${ /* VIEWS AS DATA (FR-03): the blocks a view spec is drawn with, over the tokens above. */""}
|
|
1695
1809
|
${SPEC_VIEW_CSS}`;
|
|
1696
1810
|
}
|
|
1697
1811
|
//# sourceMappingURL=theme.js.map
|