@1agh/maude 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/apps/studio/ai-banner.tsx +0 -1
- package/apps/studio/annotations-align.ts +149 -0
- package/apps/studio/annotations-bindings.ts +197 -0
- package/apps/studio/annotations-context-toolbar.tsx +436 -186
- package/apps/studio/annotations-groups.ts +270 -0
- package/apps/studio/annotations-layer.tsx +1708 -1660
- package/apps/studio/annotations-model.ts +2077 -0
- package/apps/studio/annotations-snap.ts +125 -0
- package/apps/studio/api.ts +208 -116
- package/apps/studio/bin/_png-playwright.mjs +1 -1
- package/apps/studio/bin/annotate.mjs +732 -0
- package/apps/studio/bin/annotate.sh +17 -0
- package/apps/studio/bin/read-annotations.mjs +152 -17
- package/apps/studio/build.ts +1 -1
- package/apps/studio/canvas-arrowheads.ts +78 -9
- package/apps/studio/canvas-cursors.ts +2 -0
- package/apps/studio/canvas-edit.ts +257 -7
- package/apps/studio/canvas-icons.tsx +105 -0
- package/apps/studio/canvas-shell.tsx +305 -8
- package/apps/studio/client/app.jsx +2812 -238
- package/apps/studio/client/index.html +1 -1
- package/apps/studio/client/styles/3-shell-maude.css +713 -11
- package/apps/studio/client/styles/4-components.css +39 -0
- package/apps/studio/client/styles/5-maude-overrides.css +16 -2
- package/apps/studio/client/tour/overlay.jsx +105 -17
- package/apps/studio/client/tour/usage-tour.js +23 -10
- package/apps/studio/commands/annotation-strokes-command.ts +1 -1
- package/apps/studio/commands/move-artboards-command.ts +1 -1
- package/apps/studio/comments-overlay.tsx +7 -5
- package/apps/studio/context-menu.tsx +4 -3
- package/apps/studio/contextual-toolbar.tsx +14 -0
- package/apps/studio/cursors-overlay.tsx +20 -20
- package/apps/studio/dist/client.bundle.js +3322 -602
- package/apps/studio/dist/comment-mount.js +95 -9
- package/apps/studio/dist/styles.css +2490 -167
- package/apps/studio/dom-selection.ts +115 -0
- package/apps/studio/export-dialog.tsx +3 -3
- package/apps/studio/history.ts +20 -3
- package/apps/studio/http.ts +124 -5
- package/apps/studio/input-router.tsx +7 -0
- package/apps/studio/inspect.ts +37 -8
- package/apps/studio/participants-chrome.tsx +1 -7
- package/apps/studio/server.ts +5 -2
- package/apps/studio/sync/agent.ts +231 -57
- package/apps/studio/sync/codec.ts +45 -0
- package/apps/studio/sync/cold-start.ts +158 -0
- package/apps/studio/sync/connection-state.ts +58 -2
- package/apps/studio/sync/index.ts +563 -221
- package/apps/studio/sync/journal.ts +190 -0
- package/apps/studio/sync/migrate-seed.ts +202 -44
- package/apps/studio/sync/projection.ts +22 -3
- package/apps/studio/sync/status.ts +15 -4
- package/apps/studio/test/activity.test.ts +1 -7
- package/apps/studio/test/annotate-write.test.ts +184 -0
- package/apps/studio/test/annotations-align.test.ts +88 -0
- package/apps/studio/test/annotations-bindings.test.ts +124 -0
- package/apps/studio/test/annotations-groups.test.ts +231 -0
- package/apps/studio/test/annotations-snap.test.ts +79 -0
- package/apps/studio/test/canvas-edit.test.ts +181 -1
- package/apps/studio/test/canvas-origin-gate.test.ts +8 -0
- package/apps/studio/test/collab-bridge.test.ts +0 -2
- package/apps/studio/test/collab-room.test.ts +2 -7
- package/apps/studio/test/csp-canvas-shell.test.ts +5 -0
- package/apps/studio/test/csrf-write-guard.test.ts +52 -0
- package/apps/studio/test/figjam-v3-model.test.ts +342 -0
- package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +1 -0
- package/apps/studio/test/shared-doc-migrate.test.ts +224 -14
- package/apps/studio/test/sync-agent.test.ts +272 -2
- package/apps/studio/test/sync-codec.test.ts +65 -0
- package/apps/studio/test/sync-cold-start.test.ts +244 -0
- package/apps/studio/test/sync-connection-state.test.ts +68 -0
- package/apps/studio/test/sync-hardening.test.ts +0 -8
- package/apps/studio/test/sync-hubs-config.test.ts +0 -1
- package/apps/studio/test/sync-incident-replay.test.ts +211 -0
- package/apps/studio/test/sync-journal.test.ts +176 -0
- package/apps/studio/test/sync-runtime.test.ts +360 -5
- package/apps/studio/test/sync-status.test.ts +66 -0
- package/apps/studio/test/use-annotation-resize.test.ts +159 -0
- package/apps/studio/test/use-artboard-drag.test.ts +0 -1
- package/apps/studio/test/use-collab.test.ts +0 -0
- package/apps/studio/test/use-tool-mode.test.tsx +5 -2
- package/apps/studio/tool-palette.tsx +12 -2
- package/apps/studio/undo-hud.tsx +0 -1
- package/apps/studio/use-agent-presence.tsx +4 -2
- package/apps/studio/use-annotation-resize.tsx +484 -54
- package/apps/studio/use-annotation-selection.tsx +16 -4
- package/apps/studio/use-canvas-activity.tsx +2 -2
- package/apps/studio/use-collab.tsx +20 -15
- package/apps/studio/use-selection-set.tsx +9 -0
- package/apps/studio/use-tool-mode.tsx +5 -1
- package/apps/studio/whats-new.json +135 -10
- package/apps/studio/whats-new.schema.json +18 -2
- package/cli/commands/design-link.test.mjs +84 -0
- package/cli/commands/design.mjs +2 -1
- package/cli/commands/design.test.mjs +5 -1
- package/cli/lib/design-link.mjs +51 -1
- package/package.json +8 -8
- package/plugins/design/templates/_shell.html +28 -4
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
.st-menu:hover { background: var(--bg-3); color: var(--fg-0); }
|
|
61
61
|
.st-menu[aria-expanded="true"] { background: var(--bg-3); color: var(--fg-0); }
|
|
62
62
|
.st-menu[aria-disabled="true"] { color: var(--fg-3); cursor: default; }
|
|
63
|
-
|
|
63
|
+
/* keyboard ring: the shared `.maude :is(button…):focus-visible` recipe */
|
|
64
64
|
|
|
65
65
|
.st-mb-right { margin-left: auto; display: flex; align-items: center; gap: var(--space-3); }
|
|
66
66
|
.st-stamp {
|
|
@@ -91,7 +91,9 @@
|
|
|
91
91
|
position: absolute; top: 38px; min-width: 230px;
|
|
92
92
|
background: var(--bg-2); border: 1px solid var(--border-default);
|
|
93
93
|
border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
|
|
94
|
-
|
|
94
|
+
/* above the floating st-banner (9100) — an open menu must never sit under
|
|
95
|
+
a transient notice */
|
|
96
|
+
padding: var(--space-2); z-index: 9150;
|
|
95
97
|
animation: st-pop var(--dur-panel) var(--ease-out);
|
|
96
98
|
transform-origin: top left;
|
|
97
99
|
}
|
|
@@ -123,12 +125,23 @@
|
|
|
123
125
|
transition: background var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out);
|
|
124
126
|
}
|
|
125
127
|
.st-iconbtn:hover { background: var(--bg-3); color: var(--fg-0); }
|
|
126
|
-
.st-iconbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
127
128
|
|
|
128
129
|
/* ─── Presence avatars (menubar) ──────────────────────────────────────────── */
|
|
129
130
|
.st-presence { display: flex; align-items: center; }
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
/* DS avatar recipe (ui_kits showcase `.sc-avatar`): hue-TINTED surface + hue
|
|
132
|
+
* border + fg-0 text. A solid hue fill with white text broke the accent-fg
|
|
133
|
+
* contrast rule on dark and washed out entirely in light theme. */
|
|
134
|
+
.st-avatar {
|
|
135
|
+
--av-hue: var(--accent);
|
|
136
|
+
width: 22px; height: 22px; border-radius: var(--radius-pill);
|
|
137
|
+
display: grid; place-items: center;
|
|
138
|
+
font-family: var(--font-mono); font-size: 10px; line-height: 1;
|
|
139
|
+
letter-spacing: 0.02em; text-transform: uppercase; font-weight: 600;
|
|
140
|
+
background: color-mix(in oklab, var(--av-hue) 22%, var(--bg-3));
|
|
141
|
+
border: 1px solid var(--av-hue);
|
|
142
|
+
color: var(--fg-0);
|
|
143
|
+
}
|
|
144
|
+
.st-presence .st-avatar { margin-left: -6px; box-shadow: 0 0 0 1.5px var(--bg-1); }
|
|
132
145
|
.st-presence .st-avatar:first-child { margin-left: 0; }
|
|
133
146
|
|
|
134
147
|
/* ─── Status bar (bottom — context) ───────────────────────────────────────── */
|
|
@@ -151,7 +164,6 @@
|
|
|
151
164
|
.st-sb-spacer { flex: 1; }
|
|
152
165
|
.st-sb-theme { display: inline-flex; align-items: center; gap: var(--space-2); cursor: pointer; appearance: none; color: var(--fg-0); font-family: var(--font-mono); font-size: var(--type-xs); padding: 3px var(--space-3); border-radius: var(--radius-sm); border: 1px solid var(--border-default); background: var(--bg-3); }
|
|
153
166
|
.st-sb-theme:hover { background: var(--bg-4); border-color: var(--border-strong); }
|
|
154
|
-
.st-sb-theme:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
155
167
|
.st-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); display: inline-block; flex: none; }
|
|
156
168
|
.st-live-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--presence-offline); flex: none; }
|
|
157
169
|
.st-live-dot.is-connected { background: var(--presence-online); }
|
|
@@ -205,7 +217,6 @@
|
|
|
205
217
|
border-radius: var(--radius-sm); color: var(--fg-0); font-family: var(--font-body); font-size: var(--type-sm);
|
|
206
218
|
padding: var(--space-2) var(--space-3);
|
|
207
219
|
}
|
|
208
|
-
.st-newboard input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
209
220
|
.st-newboard-go {
|
|
210
221
|
appearance: none; border: 1px solid var(--accent); background: var(--accent); color: var(--accent-fg);
|
|
211
222
|
border-radius: var(--radius-sm); cursor: pointer; padding: 0 var(--space-3); font-family: var(--font-mono); font-size: var(--type-sm);
|
|
@@ -359,7 +370,8 @@
|
|
|
359
370
|
|
|
360
371
|
/* ─── Floating status banners (sync / git-lifecycle) ──────────────────────── */
|
|
361
372
|
.st-banner {
|
|
362
|
-
|
|
373
|
+
/* below the 40px menubar — at top:12px the banner covered the menus + file slot */
|
|
374
|
+
position: fixed; top: 48px; left: 50%; transform: translateX(-50%); z-index: 9100;
|
|
363
375
|
display: flex; align-items: center; gap: var(--space-3);
|
|
364
376
|
padding: var(--space-2) var(--space-4); border-radius: var(--radius-pill);
|
|
365
377
|
border: 1px solid var(--border-default); background: var(--bg-2); color: var(--fg-0);
|
|
@@ -384,7 +396,7 @@
|
|
|
384
396
|
/* ─── Command palette (⌘K) ───────────────────────────────────────────────── */
|
|
385
397
|
.st-scrim { position: fixed; inset: 0; background: color-mix(in oklab, var(--bg-0) 62%, transparent); z-index: 9000; display: grid; place-items: start center; padding-top: 12vh; }
|
|
386
398
|
.st-palette {
|
|
387
|
-
width: 560px; max-width: 92vw; background: var(--bg-2); border: 1px solid var(--border-
|
|
399
|
+
width: 560px; max-width: 92vw; background: var(--bg-2); border: 1px solid var(--border-default);
|
|
388
400
|
border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden;
|
|
389
401
|
animation: st-pop var(--dur-route) var(--ease-out);
|
|
390
402
|
}
|
|
@@ -424,7 +436,7 @@
|
|
|
424
436
|
|
|
425
437
|
/* ─── Export & handoff dialog (Plan C P9/P10) ──────────────────────────────
|
|
426
438
|
* Lifted from Studio.css `.st-dialog*` / `.st-fmt*`. Rendered inside `.st-scrim`. */
|
|
427
|
-
.st-dialog { width: 540px; max-width: 92vw; background: var(--bg-1); border: 1px solid var(--border-
|
|
439
|
+
.st-dialog { width: 540px; max-width: 92vw; background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden; animation: st-pop var(--dur-route) var(--ease-out); }
|
|
428
440
|
.st-dialog-hd { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-subtle); }
|
|
429
441
|
.st-dialog-title { font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); }
|
|
430
442
|
.st-dialog-bd { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); }
|
|
@@ -450,10 +462,700 @@
|
|
|
450
462
|
.st-field { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: var(--space-1) var(--space-2); width: 58px; text-align: right; }
|
|
451
463
|
.st-field-lead { display: inline-flex; align-items: center; gap: var(--space-1); }
|
|
452
464
|
.st-field-lead .k { font-family: var(--font-mono); font-size: 9px; color: var(--fg-3); }
|
|
465
|
+
/* Phase 12.3 — maude DS coordinate cell (components-inputs `.fld-mini`): a mono
|
|
466
|
+
* axis tag glued to the tabular field, the tag a left segment of one bordered
|
|
467
|
+
* group. focus-within rings the whole cell (border-accent + 3px tint halo). */
|
|
468
|
+
.st-fmini { display: inline-flex; align-items: stretch; min-width: 0; flex: 1 1 0; border: 1px solid var(--border-default); border-radius: var(--radius-xs); overflow: hidden; background: var(--bg-3); transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
|
|
469
|
+
.st-fmini .st-mtag { flex: none; display: flex; align-items: center; justify-content: center; width: 20px; font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); background: var(--bg-2); border-right: 1px solid var(--border-default); }
|
|
470
|
+
.st-fmini input, .st-fmini .st-fminival { flex: 1 1 auto; min-width: 0; width: 100%; box-sizing: border-box; appearance: none; border: 0; border-radius: 0; background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); text-align: right; padding: 3px var(--space-2); }
|
|
471
|
+
.st-fmini input:focus { outline: none; }
|
|
472
|
+
.st-fmini:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
|
|
473
|
+
.st-insp-unit { align-self: center; font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); letter-spacing: var(--tracking-wide); }
|
|
474
|
+
/* design-critic 1.2 — the Inspect FILL/TEXT chip was collapsing to a thin sliver
|
|
475
|
+
* (read as a text caret) because its container `.st-swatch-row` had no flex rule,
|
|
476
|
+
* so the inline swatch span ignored its width/height. Define the row + make the
|
|
477
|
+
* chip a block so the resolved colour reads as a real swatch. */
|
|
478
|
+
.st-swatch-row { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
479
|
+
.st-insp-swatch { display: block; width: 18px; height: 18px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); flex: none; }
|
|
453
480
|
.st-layer { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2); border-radius: var(--radius-xs); font-size: var(--type-sm); color: var(--fg-1); font-family: var(--font-mono); }
|
|
454
481
|
.st-layer:hover { background: var(--bg-2); }
|
|
455
|
-
|
|
482
|
+
/* maude signature — selection is an accent-tint wash + an inset 2px accent bar,
|
|
483
|
+
* never a solid fill (DS hard rule). */
|
|
484
|
+
.st-layer.is-sel { background: var(--accent-tint); color: var(--fg-0); box-shadow: inset 2px 0 0 var(--accent); }
|
|
485
|
+
/* Phase 12 Task 4 — browsable layers tree rows */
|
|
486
|
+
.st-layer--row { cursor: pointer; padding: 3px var(--space-2); gap: 4px; white-space: nowrap; }
|
|
487
|
+
.st-layer--row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
|
488
|
+
.st-layer-caret { flex: none; width: 14px; height: 14px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 0; color: var(--fg-3); font-size: 9px; line-height: 1; cursor: pointer; padding: 0; }
|
|
489
|
+
.st-layer-label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; }
|
|
490
|
+
.st-layer-type { flex: none; font-size: 9px; color: var(--fg-3); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
|
|
491
|
+
/* Phase 12.3 (W3.1) — type icon tint + per-row visibility (eye) toggle. */
|
|
492
|
+
.st-layer-ticon { flex: none; color: var(--fg-3); }
|
|
493
|
+
.st-layer.is-sel .st-layer-ticon { color: var(--accent); }
|
|
494
|
+
.st-layer-eye { flex: none; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 0; color: var(--fg-3); cursor: pointer; padding: 0; border-radius: var(--radius-xs); opacity: 0; }
|
|
495
|
+
.st-layer--row:hover .st-layer-eye, .st-layer--row:focus-within .st-layer-eye { opacity: 1; }
|
|
496
|
+
.st-layer-eye:hover { color: var(--fg-0); background: var(--bg-3); }
|
|
497
|
+
.st-layer-eye:focus-visible { outline: none; color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
498
|
+
/* a hidden layer stays dim + keeps its eye visible (so it can be re-shown) */
|
|
499
|
+
.st-layer.is-hidden { opacity: 0.45; }
|
|
500
|
+
.st-layer.is-hidden .st-layer-eye { opacity: 1; color: var(--fg-2); }
|
|
456
501
|
.st-css { font-family: var(--font-mono); font-size: var(--type-xs); background: var(--bg-0); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: var(--space-3); line-height: 1.7; color: var(--fg-1); }
|
|
457
502
|
.st-css .comment { color: var(--fg-3); }
|
|
458
503
|
|
|
504
|
+
/* Phase 12.2 — in-canvas CSS editor knobs. Full-width value fields (NOT the 58px
|
|
505
|
+
read-only inspect fields), grouped sections, color swatch, per-field feedback. */
|
|
506
|
+
.st-css-panel { display: flex; flex-direction: column; gap: var(--space-2); }
|
|
507
|
+
.st-css-title { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); word-break: break-word; }
|
|
508
|
+
.st-css-group { font-family: var(--font-mono); font-size: 10px; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-3); margin-top: var(--space-3); }
|
|
509
|
+
.st-css-row { display: grid; grid-template-columns: 72px 1fr; align-items: center; gap: var(--space-2); }
|
|
510
|
+
.st-css-label { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
|
|
511
|
+
.st-css-control { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
512
|
+
.st-css-input { flex: 1 1 auto; min-width: 0; width: 100%; box-sizing: border-box; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: var(--space-1) var(--space-2); text-align: left; }
|
|
513
|
+
.st-css-input::placeholder { color: var(--fg-3); }
|
|
514
|
+
.st-css-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
515
|
+
.st-css-swatch { position: relative; flex: none; width: 22px; height: 22px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); padding: 0; cursor: pointer; overflow: hidden; background-image: linear-gradient(45deg, var(--bg-2) 25%, transparent 25%), linear-gradient(-45deg, var(--bg-2) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--bg-2) 75%), linear-gradient(-45deg, transparent 75%, var(--bg-2) 75%); background-size: 8px 8px; background-position: 0 0, 0 4px, 4px -4px, -4px 0; }
|
|
516
|
+
.st-css-swatch > span { position: absolute; inset: 0; }
|
|
517
|
+
.st-css-swatch input[type="color"] { position: absolute; inset: -4px; width: calc(100% + 8px); height: calc(100% + 8px); opacity: 0; cursor: pointer; border: 0; padding: 0; }
|
|
518
|
+
.st-css-status { font-family: var(--font-mono); font-size: 10px; min-height: 12px; }
|
|
519
|
+
.st-css-status.is-error { color: oklch(0.62 0.2 25); }
|
|
520
|
+
.st-css-status.is-saved { color: var(--fg-3); }
|
|
521
|
+
.st-css-help { font-size: var(--type-xs); color: var(--fg-3); line-height: 1.5; margin-top: var(--space-2); }
|
|
522
|
+
.st-css-help code { font-family: var(--font-mono); color: var(--fg-2); background: var(--bg-3); padding: 0 3px; border-radius: 3px; }
|
|
523
|
+
.st-css-disabled { color: var(--fg-2); font-size: var(--type-sm); line-height: 1.6; }
|
|
524
|
+
.st-css-disabled code { font-family: var(--font-mono); color: var(--accent); background: var(--bg-2); padding: 1px 5px; border-radius: var(--radius-xs); }
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
/* Phase 12.2 port — interactive CSS panel knobs (DDR-104). Ported from the
|
|
528
|
+
critic-approved + user-iterated Studio.css spec. Tokens resolve from the
|
|
529
|
+
shell .maude[data-theme] root (1-tokens-maude.css). */
|
|
530
|
+
/* ─── CSS panel · Phase 12.2 spec (DDR-104) ──────────────────────────────────
|
|
531
|
+
* Hybrid vocabulary (friendly section headers + CSS-named rows), per-field
|
|
532
|
+
* token dropdowns, nested box-model widget, per-row provenance, two-hatch
|
|
533
|
+
* Advanced section. Scoped `.st-cp-*` (never reuses the cramped `.st-field`).
|
|
534
|
+
* Critic iter-1 fixes: live text off the disabled --fg-3 token → --fg-2 (WCAG
|
|
535
|
+
* AA ≥4.5:1); SHAPE-coded provenance (circle/square/ring, not colour alone);
|
|
536
|
+
* colour swatch lives INSIDE the token field so every control shares one left
|
|
537
|
+
* rail; 24px+ targets (bind / seg / box-model inputs); legible box-model. */
|
|
538
|
+
.st-cp { display: flex; flex-direction: column; gap: var(--space-4); }
|
|
539
|
+
|
|
540
|
+
/* element identity — Phase 12.3 (W2.3) hairline under the header for structure (Figma-ish) */
|
|
541
|
+
.st-cp-id { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); padding-bottom: var(--space-3); border-bottom: 1px solid var(--border-subtle); }
|
|
542
|
+
.st-cp-idtag { font-family: var(--font-mono); font-size: var(--type-sm); color: var(--fg-0); }
|
|
543
|
+
.st-cp-idcls { color: var(--accent); }
|
|
544
|
+
.st-cp-idmeta { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
|
|
545
|
+
|
|
546
|
+
/* sections */
|
|
547
|
+
.st-cp-sec { display: flex; flex-direction: column; gap: var(--space-2); }
|
|
548
|
+
/* section header — collapsible disclosure button */
|
|
549
|
+
.st-cp-sechd { width: 100%; appearance: none; cursor: pointer; display: flex; align-items: center; gap: var(--space-2); background: transparent; border: 0; border-bottom: 1px solid var(--border-subtle); text-align: left; font-family: var(--font-mono); font-size: var(--type-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2); padding: 0 0 var(--space-1); }
|
|
550
|
+
.st-cp-sechd svg { color: var(--fg-2); }
|
|
551
|
+
.st-cp-sechd:hover, .st-cp-sechd:hover svg { color: var(--fg-0); }
|
|
552
|
+
/* Phase 12.3 — section header row carries the shared underline so the toggle
|
|
553
|
+
* button + the per-section reset sit on one baseline. */
|
|
554
|
+
.st-cp-sechd-row { display: flex; align-items: stretch; gap: var(--space-1); border-bottom: 1px solid var(--border-subtle); }
|
|
555
|
+
.st-cp-sechd-row .st-cp-sechd { border-bottom: 0; flex: 1 1 auto; }
|
|
556
|
+
/* reset affordances — a subtle revert glyph (⟲). Muted by default, brightens on
|
|
557
|
+
* hover/focus. The per-row variant lives in .st-cp-ctl / .st-cp-kv; the
|
|
558
|
+
* per-section variant sits at the end of the header row. */
|
|
559
|
+
.st-cp-reset, .st-cp-secreset { flex: none; appearance: none; cursor: pointer; background: transparent; border: 0; color: var(--fg-3); font-size: 12px; line-height: 1; padding: 2px; border-radius: var(--radius-xs); }
|
|
560
|
+
.st-cp-reset { width: 16px; height: 16px; }
|
|
561
|
+
.st-cp-reset:hover, .st-cp-secreset:hover { color: var(--accent); background: var(--accent-tint); }
|
|
562
|
+
.st-cp-reset:focus-visible, .st-cp-secreset:focus-visible { outline: none; color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
563
|
+
.st-cp-secreset { align-self: center; }
|
|
564
|
+
/* read-only name field for an existing custom CSS prop / HTML attr row */
|
|
565
|
+
.st-cp-fin--ro { flex: 0 0 38%; background: var(--bg-2); color: var(--fg-2); cursor: default; }
|
|
566
|
+
.st-cp-fin--ro:focus { outline: none; border-color: var(--border-strong); box-shadow: none; }
|
|
567
|
+
|
|
568
|
+
/* a labelled row: [provenance] [css property] [control] */
|
|
569
|
+
.st-cp-row { display: grid; grid-template-columns: 10px 92px 1fr; align-items: center; gap: var(--space-2); min-height: 28px; }
|
|
570
|
+
/* #1 bigger-bet — unset rows recede so the overridden ones pop; full opacity on
|
|
571
|
+
* hover/focus so they're still editable. The panel reads as a diff of overrides. */
|
|
572
|
+
.st-cp-row.is-unset { opacity: 0.5; transition: opacity var(--dur-soft) var(--ease-out); }
|
|
573
|
+
.st-cp-row.is-unset:hover, .st-cp-row.is-unset:focus-within { opacity: 1; }
|
|
574
|
+
/* one-line labels keep the row rhythm uniform; the full property name is in the
|
|
575
|
+
* row's title tooltip (design-critic 4.1 — uneven wrap was the top craft nit). */
|
|
576
|
+
.st-cp-label { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
577
|
+
.st-cp-ctl { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
578
|
+
|
|
579
|
+
/* provenance — SHAPE-coded so token/override/inherited survive small size +
|
|
580
|
+
* colour-blindness: token = filled accent circle · override = filled neutral
|
|
581
|
+
* square · inherited = hollow ring. Each carries role=img + aria-label. */
|
|
582
|
+
.st-cp-prov { width: 8px; height: 8px; display: inline-block; flex: none; padding: 0; }
|
|
583
|
+
/* Phase 12.3 (#4) — the row's leading dot is a button: provenance + save status
|
|
584
|
+
* (glow) + double-click reset. No appearance chrome; the variant fills it. */
|
|
585
|
+
/* reset native button chrome; the variants own the FILL (a transparent bg here
|
|
586
|
+
* would out-specify them and hollow the dot — that was the bug). */
|
|
587
|
+
button.st-cp-prov { appearance: none; border: 0; cursor: default; }
|
|
588
|
+
.st-cp-prov.is-resettable { cursor: pointer; }
|
|
589
|
+
.st-cp-prov.is-resettable:hover { box-shadow: 0 0 0 3px var(--bg-4); }
|
|
590
|
+
.st-cp-prov:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
591
|
+
/* save-status glows (replaces the trailing ✓/! markers) */
|
|
592
|
+
.st-cp-prov.is-saved { box-shadow: 0 0 0 3px color-mix(in oklab, var(--status-success) 45%, transparent); }
|
|
593
|
+
.st-cp-prov.is-saving { box-shadow: 0 0 0 3px color-mix(in oklab, var(--fg-2) 35%, transparent); }
|
|
594
|
+
.st-cp-prov.is-err { background: var(--status-error); border-color: var(--status-error); box-shadow: 0 0 0 3px color-mix(in oklab, var(--status-error) 40%, transparent); }
|
|
595
|
+
/* Phase 12.3 — provenance is SHAPE-coded (token=circle · override=square ·
|
|
596
|
+
* inherited=ring) on NEUTRAL fills. Indigo is reserved for its one job on this
|
|
597
|
+
* surface (the bound-token ◇ button + the focus ring), so the token dot must NOT
|
|
598
|
+
* reuse the accent (design-critic 1.4/1.5). */
|
|
599
|
+
.st-cp-prov--bound { background: var(--fg-0); border-radius: 50%; }
|
|
600
|
+
.st-cp-prov--raw { background: var(--fg-2); border-radius: 1px; }
|
|
601
|
+
.st-cp-prov--inherit { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fg-3); border-radius: 50%; }
|
|
602
|
+
|
|
603
|
+
/* colour swatch — standalone (border cluster) + inline (inside the token field) */
|
|
604
|
+
.st-cp-swatch { flex: none; width: 22px; height: 22px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); }
|
|
605
|
+
.st-cp-swatch--mini { width: 18px; height: 18px; }
|
|
606
|
+
.st-cp-tokswatch { flex: none; width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--border-default); }
|
|
607
|
+
|
|
608
|
+
/* token field (per-field DS-token dropdown) */
|
|
609
|
+
.st-cp-token { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: var(--space-2); appearance: none; cursor: pointer; font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 4px var(--space-2); }
|
|
610
|
+
.st-cp-token:hover { border-color: var(--accent); }
|
|
611
|
+
.st-cp-tokdot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
|
|
612
|
+
.st-cp-tokname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
613
|
+
.st-cp-token svg { flex: none; color: var(--fg-2); }
|
|
614
|
+
|
|
615
|
+
/* number field: input + steppers + unit-select + bind-to-token */
|
|
616
|
+
.st-cp-num { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: stretch; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); overflow: hidden; min-height: 26px; }
|
|
617
|
+
/* #2 — Figma-style property prefix segment inside the numeric field. */
|
|
618
|
+
.st-cp-numlead { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 20px; color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); border-right: 1px solid var(--border-subtle); background: var(--bg-2); }
|
|
619
|
+
.st-cp-num:focus-within .st-cp-numlead { color: var(--fg-1); }
|
|
620
|
+
.st-cp-num:hover { border-color: var(--border-strong); }
|
|
621
|
+
.st-cp-num:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
|
|
622
|
+
.st-cp-numin { flex: 1 1 auto; min-width: 0; width: 100%; appearance: none; border: 0; background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); padding: 3px var(--space-2); }
|
|
623
|
+
.st-cp-numin::placeholder { color: var(--fg-2); }
|
|
624
|
+
.st-cp-numin:focus { outline: none; }
|
|
625
|
+
/* Phase 12.3 (W2.2) — scrub affordance: a number field signals it's draggable
|
|
626
|
+
* (ew-resize), reverts to a text caret when focused for typing. While a scrub is
|
|
627
|
+
* active the whole document holds the resize cursor + suppresses selection. */
|
|
628
|
+
.st-cp-scrub { cursor: ew-resize; }
|
|
629
|
+
.st-cp-scrub:focus { cursor: text; }
|
|
630
|
+
body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-select: none !important; }
|
|
631
|
+
.st-cp-step { flex: none; display: flex; flex-direction: column; border-left: 1px solid var(--border-subtle); }
|
|
632
|
+
.st-cp-stepb { flex: 1; appearance: none; cursor: pointer; border: 0; background: var(--bg-2); color: var(--fg-2); font-size: 7px; line-height: 1; padding: 0 5px; }
|
|
633
|
+
.st-cp-stepb:first-child { border-bottom: 1px solid var(--border-subtle); }
|
|
634
|
+
.st-cp-stepb:hover { color: var(--accent); }
|
|
635
|
+
.st-cp-unit { flex: none; appearance: none; cursor: pointer; display: inline-flex; align-items: center; gap: 2px; border: 0; border-left: 1px solid var(--border-subtle); background: var(--bg-2); color: var(--fg-2); font-family: var(--font-mono); font-size: 10px; padding: 0 var(--space-2); }
|
|
636
|
+
.st-cp-unit svg { color: var(--fg-2); }
|
|
637
|
+
.st-cp-bind { flex: none; width: 24px; appearance: none; cursor: pointer; border: 0; border-left: 1px solid var(--border-subtle); background: var(--bg-2); position: relative; }
|
|
638
|
+
.st-cp-bind::before { content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid var(--fg-2); }
|
|
639
|
+
.st-cp-bind:hover::before { border-color: var(--accent); }
|
|
640
|
+
.st-cp-numin--mini { flex: none; width: 38px; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); }
|
|
641
|
+
|
|
642
|
+
/* select (font-weight, border-style) */
|
|
643
|
+
.st-cp-select { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; justify-content: space-between; gap: var(--space-2); appearance: none; cursor: pointer; font-family: var(--font-body); font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 4px var(--space-2); min-height: 26px; }
|
|
644
|
+
.st-cp-select span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
645
|
+
.st-cp-select svg { flex: none; color: var(--fg-2); }
|
|
646
|
+
.st-cp-select--mini { flex: 0 1 auto; }
|
|
647
|
+
|
|
648
|
+
/* segmented control (text-align) with drawn align glyphs — 26px tall targets */
|
|
649
|
+
.st-cp-seg { display: inline-flex; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); overflow: hidden; }
|
|
650
|
+
.st-cp-segbtn { appearance: none; cursor: pointer; border: 0; background: transparent; min-width: 26px; min-height: 26px; padding: 0 7px; display: inline-flex; align-items: center; justify-content: center; border-right: 1px solid var(--border-subtle); }
|
|
651
|
+
.st-cp-segbtn:last-child { border-right: 0; }
|
|
652
|
+
.st-cp-segbtn.is-active { background: var(--accent-tint); }
|
|
653
|
+
.st-cp-segbtn:hover:not(.is-active) { background: var(--bg-4); }
|
|
654
|
+
.st-cp-bars { display: flex; flex-direction: column; gap: 2px; width: 13px; color: var(--fg-1); }
|
|
655
|
+
.st-cp-segbtn.is-active .st-cp-bars { color: var(--accent); }
|
|
656
|
+
.st-cp-bars i { height: 2px; border-radius: 1px; background: currentColor; }
|
|
657
|
+
.st-cp-bars--left i:nth-child(1) { width: 100%; }
|
|
658
|
+
.st-cp-bars--left i:nth-child(2) { width: 60%; }
|
|
659
|
+
.st-cp-bars--left i:nth-child(3) { width: 80%; }
|
|
660
|
+
.st-cp-bars--center i { margin: 0 auto; }
|
|
661
|
+
.st-cp-bars--center i:nth-child(1) { width: 100%; }
|
|
662
|
+
.st-cp-bars--center i:nth-child(2) { width: 55%; }
|
|
663
|
+
.st-cp-bars--center i:nth-child(3) { width: 75%; }
|
|
664
|
+
.st-cp-bars--right i { margin-left: auto; }
|
|
665
|
+
.st-cp-bars--right i:nth-child(1) { width: 100%; }
|
|
666
|
+
.st-cp-bars--right i:nth-child(2) { width: 60%; }
|
|
667
|
+
.st-cp-bars--right i:nth-child(3) { width: 80%; }
|
|
668
|
+
.st-cp-bars--just i { width: 100%; }
|
|
669
|
+
|
|
670
|
+
/* nested box-model widget (Webflow-style): margin outer · padding inner */
|
|
671
|
+
.st-cp-box { position: relative; margin-top: var(--space-1); padding: 26px; border: 1px dashed var(--border-default); border-radius: var(--radius-sm); background: var(--bg-2); display: grid; place-items: center; }
|
|
672
|
+
.st-cp-boxpad { position: relative; width: 100%; padding: 26px; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); display: grid; place-items: center; }
|
|
673
|
+
.st-cp-boxcore { min-width: 72px; padding: 7px 12px; border-radius: var(--radius-xs); background: var(--bg-4); border: 1px solid var(--accent); color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11px; text-align: center; }
|
|
674
|
+
.st-cp-boxtag { position: absolute; top: 4px; left: 6px; display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-mono); font-size: 10px; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); pointer-events: none; }
|
|
675
|
+
.st-cp-boxtag .st-cp-prov { width: 6px; height: 6px; }
|
|
676
|
+
.st-cp-boxv { position: absolute; width: 36px; height: 24px; border: 1px solid transparent; border-radius: var(--radius-xs); background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11px; text-align: center; padding: 0; }
|
|
677
|
+
.st-cp-boxv.is-zero { color: var(--fg-2); }
|
|
678
|
+
.st-cp-boxv:hover, .st-cp-boxv:focus { border-color: var(--border-strong); background: var(--bg-1); outline: none; color: var(--fg-0); }
|
|
679
|
+
.st-cp-boxv--mt, .st-cp-boxv--pt { top: 1px; left: 50%; transform: translateX(-50%); }
|
|
680
|
+
.st-cp-boxv--mb, .st-cp-boxv--pb { bottom: 1px; left: 50%; transform: translateX(-50%); }
|
|
681
|
+
.st-cp-boxv--ml, .st-cp-boxv--pl { left: 0; top: 50%; transform: translateY(-50%); }
|
|
682
|
+
.st-cp-boxv--mr, .st-cp-boxv--pr { right: 0; top: 50%; transform: translateY(-50%); }
|
|
683
|
+
.st-cp-boxhint { display: flex; flex-wrap: wrap; gap: var(--space-1); }
|
|
684
|
+
.st-cp-boxhint + .st-cp-row { margin-top: var(--space-1); }
|
|
685
|
+
.st-cp-chip { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 1px 6px; }
|
|
686
|
+
|
|
687
|
+
/* opacity slider — role=slider, focusable */
|
|
688
|
+
.st-cp-slider { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
689
|
+
.st-cp-track { position: relative; flex: 1 1 auto; height: 6px; border-radius: 3px; background: var(--bg-4); border: 1px solid var(--border-default); cursor: pointer; }
|
|
690
|
+
.st-cp-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
691
|
+
.st-cp-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: var(--accent); }
|
|
692
|
+
.st-cp-thumb { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%; background: var(--fg-0); border: 2px solid var(--accent); transform: translate(-50%, -50%); }
|
|
693
|
+
.st-cp-slval { flex: none; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); color: var(--fg-1); width: 34px; text-align: right; }
|
|
694
|
+
|
|
695
|
+
/* border cluster — fills to the right control rail */
|
|
696
|
+
.st-cp-border { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
697
|
+
.st-cp-border .st-cp-swatch--mini { margin-left: 0; }
|
|
698
|
+
/* design-critic 1.1 — the border row was cramming width+style+swatch; the
|
|
699
|
+
* width field was eating the flex and clipping the style select to "styl▾".
|
|
700
|
+
* Fix the width field, let the style select take the rest. */
|
|
701
|
+
.st-cp-border .st-cp-num { flex: 0 0 58px; }
|
|
702
|
+
.st-cp-border .st-cp-nsel { flex: 1 1 auto; max-width: none; }
|
|
703
|
+
|
|
704
|
+
/* per-field save state */
|
|
705
|
+
/* #5 — error-only now (idle/saved status moved into each row's leading dot). */
|
|
706
|
+
.st-cp-save { display: inline-flex; align-items: center; gap: var(--space-2); align-self: flex-start; font-size: var(--type-xs); font-family: var(--font-mono); padding: 4px var(--space-2); border-radius: var(--radius-xs); background: color-mix(in oklab, var(--status-error) 14%, var(--bg-2)); border: 1px solid var(--status-error); color: var(--status-error); }
|
|
707
|
+
.st-cp-save.is-saved { color: var(--status-success); }
|
|
708
|
+
.st-cp-save.is-saved svg { color: var(--status-success); }
|
|
709
|
+
|
|
710
|
+
/* Advanced — the two-hatch escape (custom CSS property + custom HTML attribute) */
|
|
711
|
+
.st-cp-adv { border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-0); overflow: hidden; }
|
|
712
|
+
.st-cp-advhd { width: 100%; appearance: none; cursor: pointer; display: flex; align-items: center; gap: var(--space-2); border: 0; background: transparent; color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); padding: var(--space-2) var(--space-3); }
|
|
713
|
+
.st-cp-advhd svg { color: var(--fg-2); }
|
|
714
|
+
.st-cp-advbody { display: flex; flex-direction: column; gap: var(--space-2); padding: 0 var(--space-3) var(--space-3); }
|
|
715
|
+
.st-cp-advgrp { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2); margin-top: var(--space-1); }
|
|
716
|
+
/* #3 — custom prop/attr rows are ONE line: [name] [value] [×]. The reset glyph
|
|
717
|
+
* used to wrap to a second line; a trailing × close button keeps it on one row. */
|
|
718
|
+
.st-cp-kv { display: grid; grid-template-columns: 1fr 1fr auto; gap: var(--space-2); align-items: center; }
|
|
719
|
+
.st-cp-kvx { flex: none; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; appearance: none; cursor: pointer; background: transparent; border: 0; color: var(--fg-3); padding: 0; border-radius: var(--radius-xs); }
|
|
720
|
+
.st-cp-kvx:hover { color: var(--status-error); background: var(--bg-3); }
|
|
721
|
+
.st-cp-kvx:focus-visible { outline: none; color: var(--status-error); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
722
|
+
.st-cp-kv .st-cp-numin { background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); }
|
|
723
|
+
.st-cp-kv.has-warn .st-cp-numin { border-color: var(--status-warn); }
|
|
724
|
+
.st-cp-warn { font-size: 10px; color: var(--status-warn); font-family: var(--font-mono); }
|
|
725
|
+
.st-cp-add { align-self: flex-start; appearance: none; cursor: pointer; border: 1px dashed var(--border-default); background: transparent; color: var(--fg-1); font-family: var(--font-mono); font-size: var(--type-xs); border-radius: var(--radius-xs); padding: 4px var(--space-2); }
|
|
726
|
+
.st-cp-add:hover { border-color: var(--accent); color: var(--fg-0); }
|
|
727
|
+
.st-cp-note { font-size: 10px; color: var(--fg-2); font-style: italic; }
|
|
728
|
+
|
|
729
|
+
/* provenance legend */
|
|
730
|
+
.st-cp-legend { display: flex; flex-wrap: wrap; gap: var(--space-3); padding-top: var(--space-1); border-top: 1px solid var(--border-subtle); }
|
|
731
|
+
.st-cp-legend span { display: inline-flex; align-items: center; gap: var(--space-1); font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
|
|
732
|
+
|
|
733
|
+
/* box-model link-all-sides toggle (replaces the cryptic modifier-key chips) */
|
|
734
|
+
.st-cp-boxlink { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
|
|
735
|
+
.st-cp-linkbtn { appearance: none; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; min-height: 24px; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); color: var(--fg-1); font-family: var(--font-mono); font-size: 10px; padding: 0 8px; }
|
|
736
|
+
.st-cp-linkbtn.is-on { border-color: var(--accent); color: var(--fg-0); background: var(--accent-tint); }
|
|
737
|
+
.st-cp-linkglyph { width: 13px; height: 9px; border: 1.5px solid currentColor; border-radius: 4px; }
|
|
738
|
+
.st-cp-linkhint { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
|
|
739
|
+
|
|
740
|
+
/* per-corner border-radius: split toggle + 4-corner inputs (TL/TR/BL/BR) */
|
|
741
|
+
.st-cp-split { flex: none; width: 24px; height: 24px; appearance: none; cursor: pointer; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); position: relative; }
|
|
742
|
+
.st-cp-split.is-on { border-color: var(--accent); background: var(--accent-tint); }
|
|
743
|
+
.st-cp-split::before { content: ""; position: absolute; inset: 6px; border: 1.5px solid var(--fg-1); border-radius: 3px; }
|
|
744
|
+
.st-cp-split.is-on::before { border-color: var(--accent); border-style: dashed; }
|
|
745
|
+
.st-cp-corners { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-1); margin: 0 0 var(--space-1) 18px; }
|
|
746
|
+
.st-cp-cornerf { display: flex; align-items: center; gap: 6px; min-height: 24px; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 0 8px; }
|
|
747
|
+
.st-cp-cornerf span { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
|
|
748
|
+
.st-cp-cornerf input { flex: 1; min-width: 0; width: 100%; appearance: none; border: 0; background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11px; padding: 0; }
|
|
749
|
+
.st-cp-cornerf input:focus { outline: none; }
|
|
750
|
+
|
|
751
|
+
/* Phase 12.2 PORT-only controls — the live panel uses native <select>/<input>
|
|
752
|
+
for real interactivity + a11y where the Studio.tsx spec used styled buttons. */
|
|
753
|
+
/* The port mounts an absolute `inset:0` fill span + a hidden color <input>
|
|
754
|
+
INSIDE the swatch (the spec's swatch was decorative-only, so the ported rule
|
|
755
|
+
has no `position`). Without `relative` the fill anchored to `.maude` and
|
|
756
|
+
painted the element's computed colour across the ENTIRE window (dark element
|
|
757
|
+
→ black screen, light → white), and the invisible input swallowed every
|
|
758
|
+
click. The old `.st-css-swatch` had `position:relative` for exactly this. */
|
|
759
|
+
.st-cp-swatch { position: relative; overflow: hidden; }
|
|
760
|
+
.st-cp-caret { flex: none; color: var(--fg-2); font-size: 9px; width: 9px; text-align: center; }
|
|
761
|
+
.st-cp-fin { flex: 1 1 auto; min-width: 0; width: 100%; box-sizing: border-box; appearance: none; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); padding: 4px var(--space-2); min-height: 26px; transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
|
|
762
|
+
.st-cp-fin::placeholder { color: var(--fg-2); }
|
|
763
|
+
.st-cp-fin:hover { border-color: var(--border-strong); }
|
|
764
|
+
/* maude signature focus — border goes accent + a 3px tint halo (DS focus spec). */
|
|
765
|
+
.st-cp-fin:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
|
|
766
|
+
.st-cp-nsel { flex: 1 1 auto; min-width: 0; box-sizing: border-box; cursor: pointer; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-0); font-family: var(--font-body); font-size: var(--type-xs); padding: 3px var(--space-2); min-height: 26px; transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
|
|
767
|
+
.st-cp-nsel:hover { border-color: var(--border-strong); }
|
|
768
|
+
.st-cp-nsel:focus, .st-cp-nsel:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
|
|
769
|
+
.st-cp-nsel--tok { flex: 0 1 auto; max-width: 108px; font-family: var(--font-mono); color: var(--fg-2); background: var(--bg-2); }
|
|
770
|
+
.st-cp-nsel--mini { flex: 0 1 auto; max-width: 92px; }
|
|
771
|
+
.st-cp-unitsel { flex: none; cursor: pointer; appearance: none; border: 0; border-left: 1px solid var(--border-subtle); background: var(--bg-2); color: var(--fg-2); font-family: var(--font-mono); font-size: 10px; padding: 0 4px; }
|
|
772
|
+
/* Phase 12.3 (W2.1) — token picker as a popover. The trigger is a compact
|
|
773
|
+
* variables button (◇ glyph); bound state tints it accent. */
|
|
774
|
+
.st-cp-tokbtn { flex: none; width: 24px; height: 26px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; appearance: none; background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-2); padding: 0; }
|
|
775
|
+
.st-cp-tokbtn:hover { color: var(--fg-0); border-color: var(--border-strong); }
|
|
776
|
+
.st-cp-tokbtn:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
777
|
+
.st-cp-tokbtn.is-bound { color: var(--accent); border-color: var(--accent-muted); background: var(--accent-tint); }
|
|
778
|
+
/* the glyph — a small rotated square (variable diamond, Figma-ish) */
|
|
779
|
+
.st-cp-tokbtn-glyph { width: 8px; height: 8px; border: 1.5px solid currentColor; border-radius: 1px; transform: rotate(45deg); }
|
|
780
|
+
.st-cp-tokbtn.is-bound .st-cp-tokbtn-glyph { background: currentColor; }
|
|
781
|
+
/* the floating popover (portalled to body, fixed-positioned) */
|
|
782
|
+
.st-cp-pop { position: fixed; z-index: 1000; overflow-y: auto; background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: var(--space-2); }
|
|
783
|
+
.st-cp-pop-empty { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); padding: var(--space-2); }
|
|
784
|
+
/* sticky search over the token list */
|
|
785
|
+
.st-cp-pop-search { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: var(--space-2); padding: 0 0 var(--space-2); margin: calc(-1 * var(--space-2)) 0 0; background: var(--bg-2); color: var(--fg-2); }
|
|
786
|
+
.st-cp-pop-search svg { flex: none; margin-left: var(--space-1); }
|
|
787
|
+
.st-cp-pop-search input { flex: 1 1 auto; min-width: 0; appearance: none; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-0); font-family: var(--font-body); font-size: var(--type-xs); padding: 4px var(--space-2); }
|
|
788
|
+
.st-cp-pop-search input::placeholder { color: var(--fg-3); }
|
|
789
|
+
.st-cp-pop-search input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
790
|
+
/* #4 — colour popover tabs (Custom picker · Variables list) */
|
|
791
|
+
.st-cp-poptabs { display: flex; border-bottom: 1px solid var(--border-subtle); margin: calc(-1 * var(--space-2)) calc(-1 * var(--space-2)) var(--space-2); }
|
|
792
|
+
.st-cp-poptab { flex: 1; appearance: none; border: 0; background: transparent; cursor: pointer; font-family: var(--font-body); font-size: var(--type-xs); color: var(--fg-2); padding: var(--space-3); border-bottom: 2px solid transparent; }
|
|
793
|
+
.st-cp-poptab.is-active { color: var(--fg-0); border-bottom-color: var(--accent); }
|
|
794
|
+
.st-cp-poptab:hover:not(.is-active) { color: var(--fg-1); }
|
|
795
|
+
/* #6 — the unified HSV colour picker (Custom tab): saturation/value square +
|
|
796
|
+
* hue slider + eyedropper + hex field. The swatch on the colour row is the only
|
|
797
|
+
* trigger (no separate native picker). */
|
|
798
|
+
.st-cp-cpick { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-1); }
|
|
799
|
+
.st-cp-swatch--trigger { position: relative; overflow: hidden; cursor: pointer; appearance: none; padding: 0; }
|
|
800
|
+
.st-cp-swatch--trigger.is-bound { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
801
|
+
.st-cp-cpick-sv { position: relative; display: block; width: 100%; height: 120px; border-radius: var(--radius-sm); border: 1px solid var(--border-default); overflow: hidden; cursor: crosshair; padding: 0; touch-action: none; }
|
|
802
|
+
.st-cp-cpick-svwhite { position: absolute; inset: 0; background: linear-gradient(to right, #fff, transparent); }
|
|
803
|
+
.st-cp-cpick-svblack { position: absolute; inset: 0; background: linear-gradient(to top, #000, transparent); }
|
|
804
|
+
.st-cp-cpick-knob { position: absolute; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.5); transform: translate(-50%, -50%); pointer-events: none; }
|
|
805
|
+
.st-cp-cpick-controls { display: flex; align-items: center; gap: var(--space-2); }
|
|
806
|
+
.st-cp-cpick-eye { flex: none; width: 26px; height: 16px; display: inline-flex; align-items: center; justify-content: center; appearance: none; cursor: pointer; background: transparent; border: 0; color: var(--fg-2); padding: 0; border-radius: var(--radius-xs); }
|
|
807
|
+
.st-cp-cpick-eye:hover { color: var(--fg-0); }
|
|
808
|
+
.st-cp-cpick-hue { position: relative; flex: 1 1 auto; height: 12px; border-radius: var(--radius-pill); border: 1px solid var(--border-default); cursor: pointer; padding: 0; touch-action: none; background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%); }
|
|
809
|
+
.st-cp-cpick-huethumb { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 1px solid rgba(0,0,0,0.4); box-shadow: 0 1px 3px rgba(0,0,0,0.4); transform: translate(-50%, -50%); pointer-events: none; }
|
|
810
|
+
/* W3 — per-design-system grouping. The DS name labels each group when >1 DS. */
|
|
811
|
+
.st-cp-pop-group + .st-cp-pop-group { margin-top: var(--space-2); }
|
|
812
|
+
.st-cp-pop-ds { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2); padding: 2px var(--space-1) 4px; position: sticky; top: 30px; background: var(--bg-2); z-index: 1; }
|
|
813
|
+
/* color: swatch grid */
|
|
814
|
+
.st-cp-pop-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
|
|
815
|
+
.st-cp-pop-sw { aspect-ratio: 1; min-height: 26px; cursor: pointer; appearance: none; border: 1px solid var(--border-subtle); border-radius: var(--radius-xs); padding: 0; }
|
|
816
|
+
.st-cp-pop-sw:hover { border-color: var(--fg-2); transform: scale(1.06); }
|
|
817
|
+
.st-cp-pop-sw.is-on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
818
|
+
.st-cp-pop-sw:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
819
|
+
/* value: variable list (name + resolved value) */
|
|
820
|
+
.st-cp-pop-list { display: flex; flex-direction: column; gap: 1px; }
|
|
821
|
+
.st-cp-pop-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); cursor: pointer; appearance: none; background: transparent; border: 0; border-radius: var(--radius-xs); padding: 5px var(--space-2); text-align: left; }
|
|
822
|
+
.st-cp-pop-row:hover { background: var(--bg-3); }
|
|
823
|
+
.st-cp-pop-row.is-on { background: var(--accent-tint); }
|
|
824
|
+
.st-cp-pop-row:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-tint); }
|
|
825
|
+
.st-cp-pop-name { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
826
|
+
/* #2 — colour Variables as a list row: [swatch] [name] [value] */
|
|
827
|
+
.st-cp-pop-crow { justify-content: flex-start; }
|
|
828
|
+
.st-cp-pop-crow .st-cp-pop-name { flex: 1 1 auto; min-width: 0; }
|
|
829
|
+
.st-cp-pop-cswatch { flex: none; width: 16px; height: 16px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); }
|
|
830
|
+
.st-cp-pop-val { flex: none; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 10px; color: var(--fg-2); }
|
|
831
|
+
.st-cp-pop-row.is-on .st-cp-pop-name { color: var(--accent); }
|
|
832
|
+
.st-cp-fs { flex: none; width: 14px; text-align: center; font-family: var(--font-mono); font-size: 11px; }
|
|
833
|
+
.st-cp-fs.is-saving { color: var(--fg-3); }
|
|
834
|
+
.st-cp-fs.is-saved { color: var(--status-success); }
|
|
835
|
+
.st-cp-fs.is-err { color: var(--status-warn); cursor: help; }
|
|
836
|
+
|
|
837
|
+
/* shared focus ring for the panel's interactive controls (incl. native selects) */
|
|
838
|
+
.st-cp button:focus-visible, .st-cp input:focus-visible, .st-cp select:focus-visible, .st-cp-token:focus-visible, .st-cp-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
839
|
+
/* ═══ DS-parity polish (specimen sweep) ═══════════════════════════════════════
|
|
840
|
+
* Gaps found auditing the shell against `.design/system/maude/preview/*`:
|
|
841
|
+
* focus-visible coverage, the DS input focus ring, select chevron, unified
|
|
842
|
+
* thin scrollbars, tooltip bubbles. */
|
|
843
|
+
|
|
844
|
+
/* Catch-all keyboard focus — the DS focus specimen's ONE ring: 2px accent
|
|
845
|
+
* outline at 2px offset wrapped in a 5px --accent-tint halo (`focus.css`
|
|
846
|
+
* .fo-chip). :focus-visible only — mouse clicks never paint it. Inputs are
|
|
847
|
+
* NOT here — they take the DS input recipe (accent border + 3px tint ring). */
|
|
848
|
+
.maude :is(button, [role="tab"], select, summary, a):focus-visible {
|
|
849
|
+
outline: 2px solid var(--accent);
|
|
850
|
+
outline-offset: 2px;
|
|
851
|
+
box-shadow: 0 0 0 5px var(--accent-tint);
|
|
852
|
+
}
|
|
853
|
+
/* tight rows inside scrollers — the inset variant so the ring never clips
|
|
854
|
+
* (focus.css .fo-tree .tree-row recipe). */
|
|
855
|
+
.maude :is(.st-row, .st-dd-item, .st-pal-item, .st-layer, .st-tree-sec-hd, .st-cm-group-hd):focus-visible {
|
|
856
|
+
outline-offset: -2px;
|
|
857
|
+
box-shadow: inset 0 0 0 5px var(--accent-tint);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/* DS input recipe (`_components.css` .input:focus) — accent hairline + 3px tint
|
|
861
|
+
* ring, never the default UA outline. */
|
|
862
|
+
.st-search-box:focus-within {
|
|
863
|
+
border-color: var(--accent);
|
|
864
|
+
box-shadow: 0 0 0 3px var(--accent-tint);
|
|
865
|
+
color: var(--fg-2);
|
|
866
|
+
}
|
|
867
|
+
.st-search-box input:focus { outline: none; }
|
|
868
|
+
.st-newboard input:focus,
|
|
869
|
+
.st-newboard input:focus-visible {
|
|
870
|
+
outline: none;
|
|
871
|
+
border-color: var(--accent);
|
|
872
|
+
box-shadow: 0 0 0 3px var(--accent-tint);
|
|
873
|
+
}
|
|
874
|
+
.st-field:focus {
|
|
875
|
+
outline: none;
|
|
876
|
+
border-color: var(--accent);
|
|
877
|
+
box-shadow: 0 0 0 3px var(--accent-tint);
|
|
878
|
+
}
|
|
879
|
+
.st-select:hover { border-color: var(--border-strong); background-color: var(--bg-3); }
|
|
880
|
+
.st-select:focus-visible {
|
|
881
|
+
outline: none;
|
|
882
|
+
border-color: var(--accent);
|
|
883
|
+
box-shadow: 0 0 0 3px var(--accent-tint);
|
|
884
|
+
}
|
|
885
|
+
/* palette search — the container is the field; the inner input stays naked */
|
|
886
|
+
.st-pal-search input:focus { outline: none; }
|
|
887
|
+
.st-pal-search:focus-within { border-bottom-color: var(--accent-muted); }
|
|
888
|
+
|
|
889
|
+
/* select chevron — `appearance:none` dropped the UA arrow and left the control
|
|
890
|
+
* affordance-less. Data-URIs can't read tokens, so the stroke is the resolved
|
|
891
|
+
* --fg-1 per theme (dark ≈ #c0c4cf, light ≈ #4f5563). */
|
|
892
|
+
.st-select {
|
|
893
|
+
padding-right: 30px;
|
|
894
|
+
background-repeat: no-repeat;
|
|
895
|
+
background-position: right 10px center;
|
|
896
|
+
background-size: 12px;
|
|
897
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23c0c4cf' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3.5 6 8 10.5 12.5 6'/%3E%3C/svg%3E");
|
|
898
|
+
}
|
|
899
|
+
.maude[data-theme="light"] .st-select {
|
|
900
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%234f5563' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3.5 6 8 10.5 12.5 6'/%3E%3C/svg%3E");
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/* unified thin scrollbars — one material everywhere (tree, panels, palette,
|
|
904
|
+
* system view, modals). Hairline thumb, transparent track. */
|
|
905
|
+
.maude * {
|
|
906
|
+
scrollbar-width: thin;
|
|
907
|
+
scrollbar-color: var(--border-default) transparent;
|
|
908
|
+
}
|
|
909
|
+
.maude ::-webkit-scrollbar { width: 8px; height: 8px; }
|
|
910
|
+
.maude ::-webkit-scrollbar-track { background: transparent; }
|
|
911
|
+
.maude ::-webkit-scrollbar-thumb {
|
|
912
|
+
background: var(--border-default);
|
|
913
|
+
border-radius: var(--radius-pill);
|
|
914
|
+
border: 2px solid transparent;
|
|
915
|
+
background-clip: padding-box;
|
|
916
|
+
}
|
|
917
|
+
.maude ::-webkit-scrollbar-thumb:hover { background-color: var(--border-strong); }
|
|
918
|
+
|
|
919
|
+
/* tooltip bubble — DS `components-tooltips` recipe (bg-2 hairline bubble), CSS
|
|
920
|
+
* attr-driven so chrome controls opt in via `data-tip` without a JS layer.
|
|
921
|
+
* 500ms reveal delay ≈ native tooltip timing; reduced-motion shows instantly. */
|
|
922
|
+
.maude [data-tip] { position: relative; }
|
|
923
|
+
.maude [data-tip]::after {
|
|
924
|
+
content: attr(data-tip);
|
|
925
|
+
position: absolute;
|
|
926
|
+
top: calc(100% + 7px);
|
|
927
|
+
left: 50%;
|
|
928
|
+
transform: translateX(-50%);
|
|
929
|
+
z-index: 9200;
|
|
930
|
+
white-space: nowrap;
|
|
931
|
+
padding: var(--space-2) var(--space-3);
|
|
932
|
+
background: var(--bg-2);
|
|
933
|
+
color: var(--fg-0);
|
|
934
|
+
font-family: var(--font-body);
|
|
935
|
+
font-size: var(--type-xs);
|
|
936
|
+
font-weight: 400;
|
|
937
|
+
letter-spacing: normal;
|
|
938
|
+
text-transform: none;
|
|
939
|
+
line-height: 1;
|
|
940
|
+
border: 1px solid var(--border-default);
|
|
941
|
+
border-radius: var(--radius-sm);
|
|
942
|
+
box-shadow: var(--shadow-md);
|
|
943
|
+
pointer-events: none;
|
|
944
|
+
opacity: 0;
|
|
945
|
+
transition: opacity var(--dur-soft) var(--ease-out);
|
|
946
|
+
}
|
|
947
|
+
.maude [data-tip]:hover::after,
|
|
948
|
+
.maude [data-tip]:focus-visible::after {
|
|
949
|
+
opacity: 1;
|
|
950
|
+
transition-delay: 500ms;
|
|
951
|
+
}
|
|
952
|
+
/* bottom-bar + right-edge hosts flip/clamp so the bubble stays on screen */
|
|
953
|
+
.maude [data-tip][data-tip-pos="top"]::after { top: auto; bottom: calc(100% + 7px); }
|
|
954
|
+
.maude [data-tip][data-tip-pos="left"]::after { top: 50%; left: auto; right: calc(100% + 7px); transform: translateY(-50%); }
|
|
955
|
+
|
|
956
|
+
/* ═══ Behavioral polish (specimen sweep, round 2) ═════════════════════════════ */
|
|
957
|
+
|
|
958
|
+
/* ─── Panel grip — DS components-resize-panels recipe ──────────────────────
|
|
959
|
+
* 8px hit area; the panel's own border is the at-rest hairline, the grip seam
|
|
960
|
+
* surfaces accent + grip dots on hover/focus/drag. col-resize everywhere
|
|
961
|
+
* while dragging; iframes drop pointer events so they can't eat the stream. */
|
|
962
|
+
.st-grip {
|
|
963
|
+
flex: 0 0 8px;
|
|
964
|
+
width: 8px;
|
|
965
|
+
position: relative;
|
|
966
|
+
cursor: col-resize;
|
|
967
|
+
display: grid;
|
|
968
|
+
place-items: center;
|
|
969
|
+
background: transparent;
|
|
970
|
+
/* sit over the adjacent panel borders so the accent seam reads centered */
|
|
971
|
+
margin: 0 -4px;
|
|
972
|
+
z-index: 25;
|
|
973
|
+
}
|
|
974
|
+
.st-grip::before {
|
|
975
|
+
content: "";
|
|
976
|
+
position: absolute;
|
|
977
|
+
top: 0; bottom: 0; left: 50%;
|
|
978
|
+
width: 1px;
|
|
979
|
+
transform: translateX(-50%);
|
|
980
|
+
background: transparent;
|
|
981
|
+
transition: background var(--dur-flip) var(--ease-out), width var(--dur-flip) var(--ease-out);
|
|
982
|
+
}
|
|
983
|
+
.st-grip:hover::before,
|
|
984
|
+
.st-grip:focus-visible::before,
|
|
985
|
+
.st-grip.is-active::before { background: var(--accent); width: 2px; }
|
|
986
|
+
.st-grip-dots {
|
|
987
|
+
width: 6px; height: 18px;
|
|
988
|
+
color: var(--accent);
|
|
989
|
+
opacity: 0;
|
|
990
|
+
position: relative;
|
|
991
|
+
transition: opacity var(--dur-flip) var(--ease-out);
|
|
992
|
+
}
|
|
993
|
+
.st-grip:hover .st-grip-dots,
|
|
994
|
+
.st-grip:focus-visible .st-grip-dots,
|
|
995
|
+
.st-grip.is-active .st-grip-dots { opacity: 1; }
|
|
996
|
+
/* specimen recipe — inset ring on the narrow hit area (the seam + dots already
|
|
997
|
+
* surface accent, this keeps a proper outline for WCAG focus visibility) */
|
|
998
|
+
.st-grip:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
|
|
999
|
+
.st-body.is-resizing { cursor: col-resize; user-select: none; }
|
|
1000
|
+
.st-body.is-resizing iframe { pointer-events: none; }
|
|
1001
|
+
.st-sidebar.is-resizing, .st-rpanel.is-resizing { transition: none; }
|
|
1002
|
+
|
|
1003
|
+
/* ─── Canvas-compile skeleton — DS skeletons recipe (.skel pulse) ──────────── */
|
|
1004
|
+
.st-canvas-loading {
|
|
1005
|
+
position: absolute; inset: 0;
|
|
1006
|
+
display: grid; place-items: center;
|
|
1007
|
+
pointer-events: none;
|
|
1008
|
+
z-index: 5;
|
|
1009
|
+
/* 180ms appearance delay — warm canvases mount in <150ms and never flash it */
|
|
1010
|
+
opacity: 0;
|
|
1011
|
+
animation: st-loading-in var(--dur-soft) var(--ease-out) 180ms forwards;
|
|
1012
|
+
}
|
|
1013
|
+
@keyframes st-loading-in { to { opacity: 1; } }
|
|
1014
|
+
.st-skel-card {
|
|
1015
|
+
width: 300px;
|
|
1016
|
+
display: flex; flex-direction: column; gap: var(--space-3);
|
|
1017
|
+
padding: var(--space-5);
|
|
1018
|
+
background: var(--bg-1);
|
|
1019
|
+
border: 1px solid var(--border-default);
|
|
1020
|
+
border-radius: var(--radius-md);
|
|
1021
|
+
box-shadow: var(--shadow-md);
|
|
1022
|
+
animation: st-pop var(--dur-panel) var(--ease-out);
|
|
1023
|
+
}
|
|
1024
|
+
.st-skel-cap {
|
|
1025
|
+
font-size: var(--type-xs); letter-spacing: var(--tracking-wide);
|
|
1026
|
+
text-transform: uppercase; color: var(--fg-3);
|
|
1027
|
+
}
|
|
1028
|
+
.skel {
|
|
1029
|
+
display: block;
|
|
1030
|
+
background: var(--bg-3);
|
|
1031
|
+
border-radius: var(--radius-xs);
|
|
1032
|
+
animation: sk-pulse calc(var(--dur-route) * 3) var(--ease-in-out) infinite alternate;
|
|
1033
|
+
}
|
|
1034
|
+
@keyframes sk-pulse { from { opacity: 0.45; } to { opacity: 0.95; } }
|
|
1035
|
+
@media (prefers-reduced-motion: reduce) { .skel { animation: none; opacity: 0.7; } }
|
|
1036
|
+
.st-skel-thumb { height: 96px; border-radius: var(--radius-sm); }
|
|
1037
|
+
.st-skel-line { height: 10px; }
|
|
1038
|
+
|
|
1039
|
+
/* ─── Micro-motion — hover/disclosure transitions on the dense surfaces ───── */
|
|
1040
|
+
.st-row,
|
|
1041
|
+
.st-comment,
|
|
1042
|
+
.st-fmt,
|
|
1043
|
+
.st-cm-filter,
|
|
1044
|
+
.st-rp-tab,
|
|
1045
|
+
.st-dd-item,
|
|
1046
|
+
.st-pal-item,
|
|
1047
|
+
.st-layer,
|
|
1048
|
+
.st-export-recent-row {
|
|
1049
|
+
transition: background var(--dur-soft) var(--ease-out),
|
|
1050
|
+
border-color var(--dur-soft) var(--ease-out),
|
|
1051
|
+
color var(--dur-soft) var(--ease-out);
|
|
1052
|
+
}
|
|
1053
|
+
/* tree disclosure chevron — one glyph, rotated (animatable) */
|
|
1054
|
+
.st-chev { transition: transform var(--dur-flip) var(--ease-out); }
|
|
1055
|
+
.st-chev.is-open { transform: rotate(90deg); }
|
|
1056
|
+
/* right dock slides in as a panel (DS motion role: panel) */
|
|
1057
|
+
.st-rpanel { animation: st-panel-in var(--dur-panel) var(--ease-out); }
|
|
1058
|
+
@keyframes st-panel-in { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }
|
|
1059
|
+
|
|
1060
|
+
/* ─── Keyboard-shortcuts overlay — DS components-shortcuts-overlay recipe ──── */
|
|
1061
|
+
.so-overlay {
|
|
1062
|
+
position: relative;
|
|
1063
|
+
width: 100%;
|
|
1064
|
+
max-width: 720px;
|
|
1065
|
+
background: var(--bg-1);
|
|
1066
|
+
border: 1px solid var(--border-default);
|
|
1067
|
+
border-radius: var(--radius-lg);
|
|
1068
|
+
box-shadow: var(--shadow-lg);
|
|
1069
|
+
padding: var(--space-6);
|
|
1070
|
+
margin-top: -4vh;
|
|
1071
|
+
animation: so-enter var(--dur-panel) var(--ease-out) both;
|
|
1072
|
+
}
|
|
1073
|
+
@keyframes so-enter {
|
|
1074
|
+
0% { opacity: 0; transform: translateY(-6px) scale(0.99); }
|
|
1075
|
+
100% { opacity: 1; transform: none; }
|
|
1076
|
+
}
|
|
1077
|
+
.so-overlay-hd {
|
|
1078
|
+
display: flex;
|
|
1079
|
+
align-items: baseline;
|
|
1080
|
+
justify-content: space-between;
|
|
1081
|
+
gap: var(--space-4);
|
|
1082
|
+
margin: 0 0 var(--space-5);
|
|
1083
|
+
padding-bottom: var(--space-4);
|
|
1084
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
1085
|
+
}
|
|
1086
|
+
.so-title {
|
|
1087
|
+
font-family: var(--font-display);
|
|
1088
|
+
font-size: var(--type-lg);
|
|
1089
|
+
line-height: var(--lh-lg);
|
|
1090
|
+
font-weight: 600;
|
|
1091
|
+
letter-spacing: var(--tracking-tight);
|
|
1092
|
+
color: var(--fg-0);
|
|
1093
|
+
}
|
|
1094
|
+
.so-trigger { font-size: var(--type-xs); color: var(--fg-2); }
|
|
1095
|
+
.so-columns {
|
|
1096
|
+
display: grid;
|
|
1097
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1098
|
+
gap: var(--space-6) var(--space-7);
|
|
1099
|
+
}
|
|
1100
|
+
.so-section-hd {
|
|
1101
|
+
margin: 0 0 var(--space-3);
|
|
1102
|
+
font-family: var(--font-mono);
|
|
1103
|
+
font-size: var(--type-xs);
|
|
1104
|
+
font-weight: 500;
|
|
1105
|
+
letter-spacing: var(--tracking-wide);
|
|
1106
|
+
text-transform: uppercase;
|
|
1107
|
+
color: var(--fg-2);
|
|
1108
|
+
padding-bottom: var(--space-2);
|
|
1109
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
1110
|
+
}
|
|
1111
|
+
/* the canvas-tools column reads as the in-canvas scope — accent-muted header */
|
|
1112
|
+
.so-section--tools .so-section-hd {
|
|
1113
|
+
color: var(--accent);
|
|
1114
|
+
border-bottom-color: color-mix(in oklab, var(--accent) 40%, var(--border-subtle));
|
|
1115
|
+
}
|
|
1116
|
+
.so-list { display: flex; flex-direction: column; gap: var(--space-1); margin: 0; }
|
|
1117
|
+
.so-pair {
|
|
1118
|
+
display: grid;
|
|
1119
|
+
grid-template-columns: 1fr auto;
|
|
1120
|
+
align-items: center;
|
|
1121
|
+
gap: var(--space-4);
|
|
1122
|
+
padding: var(--space-1) var(--space-1);
|
|
1123
|
+
border-radius: var(--radius-xs);
|
|
1124
|
+
}
|
|
1125
|
+
.so-pair:hover { background: var(--bg-2); }
|
|
1126
|
+
.so-pair dt { font-size: var(--type-sm); color: var(--fg-1); }
|
|
1127
|
+
.so-pair dd { margin: 0; justify-self: end; }
|
|
1128
|
+
.so-combos { display: inline-flex; align-items: center; gap: var(--space-2); }
|
|
1129
|
+
.so-combo { display: inline-flex; align-items: center; gap: var(--space-1); }
|
|
1130
|
+
.so-or { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-3); padding: 0 1px; }
|
|
1131
|
+
.so-overlay-ft {
|
|
1132
|
+
display: flex;
|
|
1133
|
+
align-items: center;
|
|
1134
|
+
justify-content: space-between;
|
|
1135
|
+
gap: var(--space-4);
|
|
1136
|
+
margin-top: var(--space-5);
|
|
1137
|
+
padding-top: var(--space-4);
|
|
1138
|
+
border-top: 1px solid var(--border-subtle);
|
|
1139
|
+
font-size: var(--type-xs);
|
|
1140
|
+
color: var(--fg-2);
|
|
1141
|
+
}
|
|
1142
|
+
@media (max-width: 640px) { .so-columns { grid-template-columns: 1fr; } }
|
|
1143
|
+
|
|
1144
|
+
/* ─── Agent presence pulse — DS motion-presence role (scale+opacity ring) ──── */
|
|
1145
|
+
.st-avatar.is-pulsing::after {
|
|
1146
|
+
content: "";
|
|
1147
|
+
position: absolute;
|
|
1148
|
+
inset: -1px;
|
|
1149
|
+
border-radius: var(--radius-pill);
|
|
1150
|
+
border: 1px solid var(--av-hue);
|
|
1151
|
+
animation: st-presence-ring 1600ms var(--ease-out) infinite;
|
|
1152
|
+
pointer-events: none;
|
|
1153
|
+
}
|
|
1154
|
+
.st-avatar { position: relative; }
|
|
1155
|
+
@keyframes st-presence-ring {
|
|
1156
|
+
0% { opacity: 0.9; transform: scale(1); }
|
|
1157
|
+
70%, 100% { opacity: 0; transform: scale(1.45); }
|
|
1158
|
+
}
|
|
1159
|
+
@media (prefers-reduced-motion: reduce) { .st-avatar.is-pulsing::after { animation: none; opacity: 0; } }
|
|
1160
|
+
|
|
459
1161
|
}
|