@divlet/web 0.0.0-stage → 0.0.1
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 +12 -2
- package/dist/LICENSE +21 -0
- package/dist/board.css +948 -0
- package/dist/board.js +427 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.html +73 -0
- package/dist/index.js +3 -0
- package/dist/lib/actions.js +472 -0
- package/dist/lib/activity.js +311 -0
- package/dist/lib/artboards.js +56 -0
- package/dist/lib/ask.js +350 -0
- package/dist/lib/attrs.js +144 -0
- package/dist/lib/board-host.d.ts +14 -0
- package/dist/lib/board-host.js +2 -0
- package/dist/lib/board-session.d.ts +53 -0
- package/dist/lib/board-session.js +24 -0
- package/dist/lib/canvas.js +1594 -0
- package/dist/lib/chat.js +156 -0
- package/dist/lib/clip.js +231 -0
- package/dist/lib/crumbbar.js +56 -0
- package/dist/lib/crumbs.js +63 -0
- package/dist/lib/css.js +238 -0
- package/dist/lib/expandbar.js +64 -0
- package/dist/lib/file-picker.js +103 -0
- package/dist/lib/help.js +273 -0
- package/dist/lib/host.js +16 -0
- package/dist/lib/http-services.js +24 -0
- package/dist/lib/http-session.js +45 -0
- package/dist/lib/http.js +17 -0
- package/dist/lib/inspector.js +857 -0
- package/dist/lib/layers.js +298 -0
- package/dist/lib/menu.js +119 -0
- package/dist/lib/palette.js +292 -0
- package/dist/lib/panels.js +27 -0
- package/dist/lib/project.js +178 -0
- package/dist/lib/resize.js +114 -0
- package/dist/lib/shortcuts.js +91 -0
- package/dist/lib/sidebar.js +85 -0
- package/dist/lib/store.js +249 -0
- package/dist/lib/suggest.js +130 -0
- package/dist/lib/toolbar.js +54 -0
- package/dist/lib/typography.js +120 -0
- package/dist/lib/util.js +177 -0
- package/package.json +37 -4
package/dist/board.css
ADDED
|
@@ -0,0 +1,948 @@
|
|
|
1
|
+
/* divlet — a quiet, fluid workspace. One accent, hairlines, no chrome you do not need. */
|
|
2
|
+
:root {
|
|
3
|
+
color-scheme: light;
|
|
4
|
+
/* Interface size (Settings): the chrome is drawn at --ui times its size, the canvas never is. */
|
|
5
|
+
--ui: 1;
|
|
6
|
+
--vw: calc(100vw / var(--ui));
|
|
7
|
+
--vh: calc(100dvh / var(--ui));
|
|
8
|
+
--bg: #f3f2ee;
|
|
9
|
+
--dot: #d6d3c9;
|
|
10
|
+
--ink: #1b1b19;
|
|
11
|
+
--muted: #6a675d;
|
|
12
|
+
--faint: #b2afa3;
|
|
13
|
+
--panel: rgba(255, 255, 253, .94);
|
|
14
|
+
--solid: #fffffd;
|
|
15
|
+
--field: rgba(27, 27, 25, .05);
|
|
16
|
+
--field-hover: rgba(27, 27, 25, .085);
|
|
17
|
+
--hair: rgba(27, 27, 25, .1);
|
|
18
|
+
--accent: #5b5bf0; --on-accent: #fff; --bad-ink: #c4262c;
|
|
19
|
+
--accent-ink: #4545d6;
|
|
20
|
+
--accent-soft: rgba(91, 91, 240, .13);
|
|
21
|
+
--ok: #2fa56f;
|
|
22
|
+
--warn: #c98a1c;
|
|
23
|
+
--bad: #e5484d;
|
|
24
|
+
--bad-soft: rgba(229, 72, 77, .12);
|
|
25
|
+
--guide: #ff4d8d;
|
|
26
|
+
--component: #b2459b;
|
|
27
|
+
--component-soft: rgba(178, 69, 155, .13);
|
|
28
|
+
--syn-comment: #9a978a; --syn-atrule: #9333ea; --syn-selector: #b45309; --syn-class: #c2410c; --syn-pseudo: #0e7490; --syn-prop: #2563eb; --syn-number: #0f766e; --syn-color: #be185d; --syn-string: #15803d; --syn-func: #0369a1; --syn-var: #7c3aed; --syn-important: #dc2626; --syn-punct: #8d8a7f;
|
|
29
|
+
--shadow: 0 1px 2px rgba(20, 20, 15, .06), 0 10px 32px rgba(20, 20, 15, .1);
|
|
30
|
+
--page-shadow: 0 1px 3px rgba(20, 20, 15, .1), 0 14px 44px rgba(20, 20, 15, .14);
|
|
31
|
+
--radius: 14px;
|
|
32
|
+
/* Inside a chrome surface: one step smaller than the surface, so a row reads as part of the pill. */
|
|
33
|
+
--radius-inner: 9px;
|
|
34
|
+
/* Small controls (chips, cells, swatches, mini links) and the one focus ring every control shares. */
|
|
35
|
+
--radius-small: 6px;
|
|
36
|
+
--focus-ring: 2px;
|
|
37
|
+
/* A disabled control is one step back; a disabled field keeps its text readable. */
|
|
38
|
+
--disabled: .4;
|
|
39
|
+
--disabled-field: .55;
|
|
40
|
+
--font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
41
|
+
--mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
|
|
42
|
+
--ease: cubic-bezier(.2, .7, .2, 1);
|
|
43
|
+
}
|
|
44
|
+
@media (prefers-color-scheme: dark) {
|
|
45
|
+
:root:not([data-theme="light"]) {
|
|
46
|
+
color-scheme: dark;
|
|
47
|
+
--bg: #131312; --dot: #2b2b28; --ink: #ecebe6; --muted: #a3a199; --faint: #57564f;
|
|
48
|
+
--panel: rgba(28, 28, 26, .93); --solid: #1c1c1a; --field: rgba(236, 235, 230, .06); --field-hover: rgba(236, 235, 230, .1); --hair: rgba(236, 235, 230, .1);
|
|
49
|
+
--accent: #8d8dff; --on-accent: #15141f; --bad-ink: #ff8f93; --accent-ink: #a5a5ff; --accent-soft: rgba(141, 141, 255, .17); --ok: #46c88e; --warn: #e3a83b; --bad-soft: rgba(229, 72, 77, .18); --component: #e58ad0; --component-soft: rgba(229, 138, 208, .16);
|
|
50
|
+
--syn-comment: #6f6e65; --syn-atrule: #c792ea; --syn-selector: #f0b36b; --syn-class: #ffa07a; --syn-pseudo: #7fd6e6; --syn-prop: #82aaff; --syn-number: #7fdbca; --syn-color: #f78fb3; --syn-string: #a5d6a7; --syn-func: #7dcfff; --syn-var: #bb9af7; --syn-important: #ff757f; --syn-punct: #7d7b72;
|
|
51
|
+
--shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 12px 36px rgba(0, 0, 0, .45);
|
|
52
|
+
--page-shadow: 0 1px 3px rgba(0, 0, 0, .4), 0 16px 50px rgba(0, 0, 0, .5);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
:root[data-theme="dark"] {
|
|
56
|
+
color-scheme: dark;
|
|
57
|
+
--bg: #131312; --dot: #2b2b28; --ink: #ecebe6; --muted: #a3a199; --faint: #57564f;
|
|
58
|
+
--panel: rgba(28, 28, 26, .93); --solid: #1c1c1a; --field: rgba(236, 235, 230, .06); --field-hover: rgba(236, 235, 230, .1); --hair: rgba(236, 235, 230, .1);
|
|
59
|
+
--accent: #8d8dff; --on-accent: #15141f; --bad-ink: #ff8f93; --accent-ink: #a5a5ff; --accent-soft: rgba(141, 141, 255, .17); --ok: #46c88e; --warn: #e3a83b; --bad-soft: rgba(229, 72, 77, .18); --component: #e58ad0; --component-soft: rgba(229, 138, 208, .16);
|
|
60
|
+
--syn-comment: #6f6e65; --syn-atrule: #c792ea; --syn-selector: #f0b36b; --syn-class: #ffa07a; --syn-pseudo: #7fd6e6; --syn-prop: #82aaff; --syn-number: #7fdbca; --syn-color: #f78fb3; --syn-string: #a5d6a7; --syn-func: #7dcfff; --syn-var: #bb9af7; --syn-important: #ff757f; --syn-punct: #7d7b72;
|
|
61
|
+
--shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 12px 36px rgba(0, 0, 0, .45);
|
|
62
|
+
--page-shadow: 0 1px 3px rgba(0, 0, 0, .4), 0 16px 50px rgba(0, 0, 0, .5);
|
|
63
|
+
}
|
|
64
|
+
* { box-sizing: border-box; }
|
|
65
|
+
/* Everything that is not the canvas lives here and is scaled as one. */
|
|
66
|
+
#ui { position: fixed; left: 0; top: 0; z-index: 50; width: var(--vw); height: var(--vh); transform: scale(var(--ui)); transform-origin: 0 0; pointer-events: none; }
|
|
67
|
+
#ui > * { pointer-events: auto; }
|
|
68
|
+
/* Popups sit outside #ui (they are placed from on-screen rectangles) and scale from their own corner. */
|
|
69
|
+
@keyframes rise-ui { from { opacity: 0; transform: translateY(6px) scale(calc(var(--ui) * .985)); } }
|
|
70
|
+
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--bg); color: var(--ink); font: 12.5px/1.4 var(--font); -webkit-font-smoothing: antialiased; overscroll-behavior: none; }
|
|
71
|
+
button, input, textarea { font: inherit; color: inherit; }
|
|
72
|
+
button { cursor: pointer; }
|
|
73
|
+
[hidden] { display: none !important; }
|
|
74
|
+
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
75
|
+
kbd { flex: none; white-space: nowrap; font: 600 11px var(--mono); color: var(--muted); border: 1px solid var(--hair); border-radius: 6px; padding: 1px 6px; }
|
|
76
|
+
:focus-visible { outline: var(--focus-ring) solid var(--accent); outline-offset: 1px; }
|
|
77
|
+
/* A control that lives inside a field wrapper is ringed by the wrapper, never twice. */
|
|
78
|
+
:is(.vf, .num, .code, .classes, .ident-field, .search, .color-field, .bm-field, .settings-output) :is(input, textarea):focus-visible { outline: none; }
|
|
79
|
+
* { scrollbar-width: thin; scrollbar-color: var(--hair) transparent; }
|
|
80
|
+
.grow { flex: 1; }
|
|
81
|
+
|
|
82
|
+
/* ---- canvas --------------------------------------------------------------- */
|
|
83
|
+
.viewport { position: fixed; inset: 0; overflow: hidden; touch-action: none; outline: none; cursor: default; user-select: none; -webkit-user-select: none;
|
|
84
|
+
--grid: 24px; --gx: 0px; --gy: 0px;
|
|
85
|
+
background-image: radial-gradient(circle at 1px 1px, var(--dot) 1.1px, transparent 1.5px); background-size: var(--grid) var(--grid); background-position: var(--gx) var(--gy); }
|
|
86
|
+
.viewport.space-ready, .viewport.mode-interact.space-ready { cursor: grab; }
|
|
87
|
+
.viewport.panning, .viewport.moving { cursor: grabbing; }
|
|
88
|
+
.stage { position: absolute; inset: 0; }
|
|
89
|
+
.guides { position: absolute; inset: 0; pointer-events: none; z-index: 5; }
|
|
90
|
+
.guide { position: absolute; background: var(--guide); }
|
|
91
|
+
.guide-x { width: 1px; }
|
|
92
|
+
.guide-y { height: 1px; }
|
|
93
|
+
.marquee { position: absolute; z-index: 6; border: 1px solid var(--accent); background: var(--accent-soft); border-radius: 3px; pointer-events: none; }
|
|
94
|
+
.hover-badge { position: absolute; z-index: 7; display: flex; align-items: center; gap: 6px; min-height: 21px; padding: 0 7px; border-radius: 6px; background: var(--accent); color: var(--on-accent); font: 11px var(--mono); pointer-events: none; box-shadow: 0 2px 8px rgba(0, 0, 0, .18); }
|
|
95
|
+
.hover-badge b { font-weight: 700; }
|
|
96
|
+
.hover-badge span { opacity: .82; max-width: 16em; white-space: normal; overflow-wrap: anywhere; }
|
|
97
|
+
.hover-badge i { font-style: normal; opacity: .7; }
|
|
98
|
+
|
|
99
|
+
.artboard { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; background: #fff; box-shadow: var(--page-shadow); border-radius: 2px; }
|
|
100
|
+
.artboard::after { content: ""; position: absolute; inset: -1px; border: 1px solid var(--hair); border-radius: 3px; pointer-events: none; transition: border-color .15s, box-shadow .15s; }
|
|
101
|
+
.mode-select .artboard:hover:not(.selected)::after { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
102
|
+
.artboard.selected::after { inset: -2px; border: 2px solid var(--accent); }
|
|
103
|
+
.artboard.working::after { inset: -2px; border: 2px solid var(--accent); animation: work-glow 1.5s ease-in-out infinite; }
|
|
104
|
+
@keyframes work-glow { 0%, 100% { box-shadow: 0 0 0 0 transparent; border-color: color-mix(in srgb, var(--accent) 45%, transparent); } 50% { box-shadow: 0 0 0 8px var(--accent-soft), 0 0 28px var(--accent-soft); border-color: var(--accent); } }
|
|
105
|
+
.artboard.working .ab-body::after { content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 2; background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--accent) 14%, transparent) 50%, transparent 70%) 150% 0 / 250% 100% no-repeat; animation: work-sweep 1.8s linear infinite; }
|
|
106
|
+
@keyframes work-sweep { to { background-position: -150% 0; } }
|
|
107
|
+
.artboard.touched::after { box-shadow: 0 0 0 6px var(--accent-soft); }
|
|
108
|
+
.ab-body { position: absolute; left: 0; top: 0; transform-origin: 0 0; overflow: hidden; border-radius: 2px; background: #fff; }
|
|
109
|
+
.ab-body iframe { display: block; width: 100%; height: 100%; border: 0; background: #fff; color-scheme: light; }
|
|
110
|
+
.frame-cover { position: absolute; inset: 0; pointer-events: none; }
|
|
111
|
+
/* Far zoom: the cached picture replaces the live page, which stays loaded but is not painted. */
|
|
112
|
+
.ab-body img.frame-snapshot { position: absolute; left: 0; top: 0; z-index: 1; width: 100%; height: 100%; display: block; pointer-events: none; user-select: none; }
|
|
113
|
+
.artboard.lod iframe { visibility: hidden; }
|
|
114
|
+
/* The previous page of a frame, held above its replacement until that one has painted (no blank flash). */
|
|
115
|
+
.ab-body iframe.frame-ghost { position: absolute; left: 0; top: 0; z-index: 1; pointer-events: none; }
|
|
116
|
+
.mode-select .frame-cover { pointer-events: auto; cursor: default; }
|
|
117
|
+
.mode-select .artboard.editing .frame-cover { pointer-events: none; }
|
|
118
|
+
.frame-placeholder { position: absolute; inset: 0; background: linear-gradient(100deg, transparent 30%, rgba(127, 127, 127, .09) 50%, transparent 70%) 0 0 / 220% 100%, #fff; animation: shimmer 1.6s linear infinite; }
|
|
119
|
+
.artboard[data-status="live"] .frame-placeholder, .artboard[data-status="updating"] .frame-placeholder { display: none; }
|
|
120
|
+
@keyframes shimmer { to { background-position: -220% 0; } }
|
|
121
|
+
|
|
122
|
+
.ab-label { --label-scale: min(1, var(--canvas-scale, 1)); position: absolute; left: 0; bottom: calc(100% + 6px * min(1, var(--canvas-scale, 1))); display: flex; align-items: center; gap: 6px; width: calc(100% / var(--label-scale)); min-width: 0; height: calc(22px * var(--ui)); color: var(--muted); font-size: calc(12px * var(--ui)); white-space: nowrap; cursor: grab; transform: scale(var(--label-scale)); transform-origin: bottom left; transition: color .15s; }
|
|
123
|
+
.artboard:is(:hover, .selected, :focus-within) .ab-label { --label-scale: 1; min-width: min(220px, calc(100vw - 32px)); }
|
|
124
|
+
.artboard:is(:hover, .selected, :focus-within) .ab-name { flex: none; overflow: visible; max-width: calc(100vw - 32px); }
|
|
125
|
+
.artboard:hover .ab-label, .artboard.selected .ab-label { color: var(--ink); }
|
|
126
|
+
.ab-name { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
|
|
127
|
+
.ab-size { font: calc(11px * var(--ui)) var(--mono); color: var(--muted); opacity: 0; transition: opacity .15s; flex: none; }
|
|
128
|
+
.artboard:hover .ab-size, .artboard.selected .ab-size, .artboard.resizing .ab-size { opacity: 1; }
|
|
129
|
+
.artboard.resizing .ab-size { color: var(--accent); }
|
|
130
|
+
.ab-size-input { width: 9.5em; font: 11px var(--mono); }
|
|
131
|
+
.ab-size { cursor: text; }
|
|
132
|
+
.chip.lock { display: inline-grid; place-items: center; width: 26px; padding: 0; }
|
|
133
|
+
.chip.lock .icon { width: 13px; height: 13px; }
|
|
134
|
+
.ab-rename { font: inherit; width: 14em; padding: 1px 5px; border: 0; border-radius: var(--radius-small); background: var(--solid); color: var(--ink); outline: var(--focus-ring) solid var(--accent); }
|
|
135
|
+
.ab-expand { margin-left: auto; }
|
|
136
|
+
.ab-expand, .ab-more { display: grid; place-items: center; width: 20px; height: 20px; flex: none; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--muted); opacity: 0; transition: opacity .15s, background .15s; }
|
|
137
|
+
.artboard:hover :is(.ab-expand, .ab-more), .artboard.selected :is(.ab-expand, .ab-more), :is(.ab-expand, .ab-more):focus-visible { opacity: 1; }
|
|
138
|
+
:is(.ab-expand, .ab-more):hover { background: var(--field-hover); color: var(--ink); }
|
|
139
|
+
:is(.ab-expand, .ab-more) .icon { width: 13px; height: 13px; }
|
|
140
|
+
.ab-error { display: none; flex: none; color: var(--bad); font-weight: 700; }
|
|
141
|
+
.artboard[data-status="error"] .ab-error { display: block; }
|
|
142
|
+
@keyframes pulse { 50% { opacity: .35; } }
|
|
143
|
+
|
|
144
|
+
.ab-handles { position: absolute; inset: 0; pointer-events: none; z-index: 3; display: none; }
|
|
145
|
+
.artboard.sole .ab-handles { display: block; }
|
|
146
|
+
.ab-handle { position: absolute; pointer-events: auto; touch-action: none; }
|
|
147
|
+
.h-n, .h-s { left: 8px; right: 8px; height: 12px; cursor: ns-resize; }
|
|
148
|
+
.h-e, .h-w { top: 8px; bottom: 8px; width: 12px; cursor: ew-resize; }
|
|
149
|
+
.h-n { top: -7px; } .h-s { bottom: -7px; } .h-e { right: -7px; } .h-w { left: -7px; }
|
|
150
|
+
.h-ne, .h-nw, .h-se, .h-sw { width: 10px; height: 10px; background: #fff; border: 1.5px solid var(--accent); border-radius: 3px; }
|
|
151
|
+
.h-ne { top: -6px; right: -6px; cursor: nesw-resize; } .h-nw { top: -6px; left: -6px; cursor: nwse-resize; }
|
|
152
|
+
.h-se { bottom: -6px; right: -6px; cursor: nwse-resize; } .h-sw { bottom: -6px; left: -6px; cursor: nesw-resize; }
|
|
153
|
+
@media (pointer: coarse) { .h-ne, .h-nw, .h-se, .h-sw { width: 16px; height: 16px; } .h-ne { top: -9px; right: -9px; } .h-nw { top: -9px; left: -9px; } .h-se { bottom: -9px; right: -9px; } .h-sw { bottom: -9px; left: -9px; } .ab-expand, .ab-more { opacity: 1; } }
|
|
154
|
+
|
|
155
|
+
.artboard.expanded { position: fixed; inset: 0; z-index: 40; width: 100% !important; height: 100% !important; transform: none !important; border-radius: 0; box-shadow: none; will-change: auto; }
|
|
156
|
+
.artboard.expanded::after, .artboard.expanded .ab-label, .artboard.expanded .ab-handles, .artboard.expanded .frame-cover { display: none; }
|
|
157
|
+
.artboard.expanded .ab-body { width: 100% !important; height: 100% !important; transform: none !important; border-radius: 0; }
|
|
158
|
+
|
|
159
|
+
.empty { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 10px; color: var(--muted); }
|
|
160
|
+
.empty svg { width: 44px; height: 44px; fill: none; color: var(--faint); stroke: currentColor; stroke-width: .9; stroke-linejoin: round; stroke-linecap: round; margin-bottom: 4px; }
|
|
161
|
+
.empty p { margin: 0; font-size: 14px; color: var(--ink); }
|
|
162
|
+
.empty .hint { color: var(--muted); font-size: 12px; }
|
|
163
|
+
.cta { display: inline-flex; align-items: center; gap: 10px; height: 34px; padding: 0 8px 0 14px; border: 0; border-radius: 10px; background: var(--accent); color: var(--on-accent); font-weight: 600; box-shadow: var(--shadow); transition: transform .12s, background .12s; }
|
|
164
|
+
.cta:hover { background: var(--accent-ink); }
|
|
165
|
+
.cta:active { transform: scale(.97); }
|
|
166
|
+
.cta kbd { color: inherit; border-color: rgba(255, 255, 255, .35); }
|
|
167
|
+
.loading { position: absolute; inset: 0; display: grid; place-items: center; }
|
|
168
|
+
.loading i { width: 56px; height: 2px; border-radius: 2px; background: linear-gradient(90deg, transparent, var(--accent), transparent) 0 0 / 200% 100%; animation: shimmer 1s linear infinite; }
|
|
169
|
+
|
|
170
|
+
/* ---- chrome --------------------------------------------------------------- */
|
|
171
|
+
/* Left column: logo + search on top, the sidebar, its tabs below. Folded, the top and bottom pieces stay as two separate pills. */
|
|
172
|
+
:root { --chrome-h: 44px; --edge: 10px; }
|
|
173
|
+
:root { --brand-h: 36px; }
|
|
174
|
+
.dock { position: fixed; z-index: 65; height: var(--chrome-h); display: flex; align-items: center; gap: 2px; padding: 4px; border: 1px solid var(--hair); border-radius: var(--radius); background: var(--panel); backdrop-filter: blur(18px) saturate(1.4); box-shadow: var(--shadow); }
|
|
175
|
+
/* Islands: the logo, search and tabs are separate pieces that stay in place; the tabs join the sidebar when it opens. */
|
|
176
|
+
.brand { position: fixed; z-index: 65; left: var(--edge); top: var(--edge); display: flex; gap: 6px; max-width: calc(var(--vw) - 2 * var(--edge)); }
|
|
177
|
+
.status, .search-pill { border: 1px solid var(--hair); border-radius: var(--radius); background: var(--panel); backdrop-filter: blur(18px) saturate(1.4); box-shadow: var(--shadow); }
|
|
178
|
+
/* One chrome language, chosen by the panels: folded panels leave the pinned chrome floating and frosted over the canvas; an
|
|
179
|
+
open panel makes the chrome part of one solid body (sidebar.js publishes which side is open). */
|
|
180
|
+
:is([data-panels="left"], [data-panels="right"], [data-panels="both"]) :is(.status, .search-pill, .dock, .tab) { background: var(--solid); backdrop-filter: none; }
|
|
181
|
+
:is([data-panels="left"], [data-panels="right"], [data-panels="both"]) .pill { background: var(--solid); backdrop-filter: none; }
|
|
182
|
+
/* The tab row is as wide as the sidebar whether the sidebar is open or folded, and its tabs share that width equally: opening
|
|
183
|
+
the sidebar then changes only the surface behind the labels, never where a label sits. */
|
|
184
|
+
.sidebar-foot { position: fixed; z-index: 65; left: var(--edge); bottom: max(var(--edge), env(safe-area-inset-bottom)); display: flex; flex-direction: column; gap: 8px; width: min(var(--sidebar-w, 300px), calc(var(--vw) - 2 * var(--edge))); max-width: calc(var(--vw) - 2 * var(--edge)); }
|
|
185
|
+
.side-tabs { display: flex; align-items: center; gap: 6px; min-width: 0; border: 1px solid transparent; border-top: 0; border-bottom: 0; container: sidebar-tabs / inline-size; }
|
|
186
|
+
.side-tabs .tab { flex: 1 1 0; }
|
|
187
|
+
/* Opening the sidebar changes the surroundings of the tabs, never their boxes: the row keeps its height, padding and gap, so
|
|
188
|
+
the labels stay exactly where they were and only the surface behind them (and the pill borders) changes. */
|
|
189
|
+
body.has-sidebar .side-tabs { height: var(--brand-h); padding: 0; gap: 6px; border: 1px solid var(--hair); border-top: 0; border-bottom: 0; border-radius: 0 0 var(--radius) var(--radius); background: var(--solid); box-shadow: var(--shadow); }
|
|
190
|
+
body.has-sidebar .tab { border-color: transparent; border-radius: var(--radius-inner); background: transparent; box-shadow: none; backdrop-filter: none; }
|
|
191
|
+
.tool { display: inline-grid; place-items: center; min-width: 32px; height: 32px; padding: 0 7px; border: 0; border-radius: var(--radius-inner); background: transparent; color: var(--muted); text-decoration: none; transition: background .12s, color .12s, transform .12s; }
|
|
192
|
+
.tool:hover:not(:disabled) { background: var(--field-hover); color: var(--ink); }
|
|
193
|
+
.tool:active:not(:disabled) { transform: scale(.94); }
|
|
194
|
+
.tool.on { background: var(--accent-soft); color: var(--accent); }
|
|
195
|
+
.tool:disabled { opacity: var(--disabled); cursor: default; }
|
|
196
|
+
.tool.danger:hover:not(:disabled) { color: var(--bad); background: var(--bad-soft); }
|
|
197
|
+
.tool.mini { min-width: 26px; height: 26px; padding: 0 3px; border-radius: var(--radius-small); }
|
|
198
|
+
.tool.mini .icon { width: 14px; height: 14px; }
|
|
199
|
+
.tool.up .icon { transform: rotate(-90deg); } .tool.down .icon { transform: rotate(90deg); }
|
|
200
|
+
.icon { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; flex: none; }
|
|
201
|
+
.pill { height: 32px; background: var(--panel); backdrop-filter: blur(16px); border: 1px solid var(--hair); box-shadow: var(--shadow); border-radius: var(--radius-inner); }
|
|
202
|
+
.status { display: inline-flex; align-items: center; gap: 8px; min-height: var(--brand-h); min-width: 32px; max-width: min(260px, calc(var(--vw) - 80px)); padding: 0 12px 0 10px; color: var(--ink); transition: background .12s; }
|
|
203
|
+
.logo { display: inline-grid; place-items: center; flex: none; color: var(--faint); transition: color .25s; }
|
|
204
|
+
.logo .icon { width: 18px; height: 18px; stroke-width: 1.7; }
|
|
205
|
+
/* The logo itself is the connection light: brand colour when live, amber while saving, red when attention is needed or offline. */
|
|
206
|
+
.logo[data-kind="live"] { color: var(--accent); }
|
|
207
|
+
.logo[data-kind="saving"] { color: var(--warn); animation: pulse 1s ease-in-out infinite; }
|
|
208
|
+
.logo[data-kind="attention"], .logo[data-kind="offline"] { color: var(--bad); }
|
|
209
|
+
.logo[data-kind="offline"], .logo[data-kind="connecting"] { animation: pulse 1.2s ease-in-out infinite; }
|
|
210
|
+
.status:hover { background: var(--solid); }
|
|
211
|
+
.status .project { font-weight: 700; letter-spacing: .12em; }
|
|
212
|
+
.status:hover { cursor: pointer; }
|
|
213
|
+
.tab { position: relative; display: inline-flex; flex: 1 1 auto; align-items: center; justify-content: center; gap: 6px; min-width: 0; height: var(--brand-h); padding: 0 4px; border: 1px solid var(--hair); border-radius: var(--radius); background: var(--panel); backdrop-filter: blur(18px) saturate(1.4); box-shadow: var(--shadow); color: var(--muted); font-size: 12.5px; white-space: nowrap; transition: background .12s, color .12s; }
|
|
214
|
+
.tab:hover { background: var(--field-hover); color: var(--ink); }
|
|
215
|
+
.tab.on { background: var(--accent-soft); color: var(--accent); }
|
|
216
|
+
.tab .icon { width: 15px; height: 15px; }
|
|
217
|
+
.tab-mark { display: inline-flex; flex: none; align-items: center; }
|
|
218
|
+
.tab-copy { display: flex; flex-wrap: wrap; align-items: center; min-width: 0; column-gap: 3px; }
|
|
219
|
+
.tab .badge { position: static; flex: none; min-width: 14px; padding: 0 4px; font-size: 9.5px; line-height: 14px; pointer-events: none; }
|
|
220
|
+
.tab .tool-label { flex: none; line-height: 16px; }
|
|
221
|
+
/* Icons always precede the full label; only a count may wrap within the text column. Folding does not change density. */
|
|
222
|
+
@container sidebar-tabs (max-width: 340px) {
|
|
223
|
+
.tab { gap: 3px; padding: 0 2px; }
|
|
224
|
+
.tab .icon { width: 13px; height: 13px; }
|
|
225
|
+
}
|
|
226
|
+
@container sidebar-tabs (max-width: 220px) {
|
|
227
|
+
.tab { gap: 2px; padding: 0 1px; font-size: 11px; }
|
|
228
|
+
.tab .icon { width: 12px; height: 12px; }
|
|
229
|
+
}
|
|
230
|
+
.tab .spinner { width: 10px; height: 10px; }
|
|
231
|
+
/* Working: a band sweeps across the tab, over the surface it already has. No spinner, so the label never shifts or runs out of
|
|
232
|
+
room, and the same shape works on the folded pills and inside the open panel's bar. */
|
|
233
|
+
body.agent-busy #open-agent { background-image: linear-gradient(100deg, transparent 32%, color-mix(in srgb, var(--accent) 34%, transparent) 50%, transparent 68%); background-size: 55% 100%; background-repeat: no-repeat; animation: tab-sweep 1.9s linear infinite; }
|
|
234
|
+
@keyframes tab-sweep { from { background-position: -110% 0, 0 0; } to { background-position: 210% 0, 0 0; } }
|
|
235
|
+
.project { white-space: nowrap; font-weight: 500; } /* the brand word, never broken */
|
|
236
|
+
.dot { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--faint); transition: background .25s; }
|
|
237
|
+
.dot[data-kind="live"] { background: var(--ok); }
|
|
238
|
+
.dot[data-kind="saving"] { background: var(--warn); animation: pulse 1s ease-in-out infinite; }
|
|
239
|
+
.dot[data-kind="attention"], .dot[data-kind="offline"] { background: var(--bad); }
|
|
240
|
+
.dot[data-kind="offline"], .dot[data-kind="connecting"] { animation: pulse 1.2s ease-in-out infinite; }
|
|
241
|
+
|
|
242
|
+
.dock { right: var(--edge); bottom: max(var(--edge), env(safe-area-inset-bottom)); z-index: 20; gap: 1px; max-width: calc(var(--vw) - 2 * var(--edge)); flex-wrap: wrap; justify-content: flex-end; height: auto; min-height: var(--chrome-h); }
|
|
243
|
+
.dock::-webkit-scrollbar { display: none; }
|
|
244
|
+
.sep { width: 1px; height: 18px; margin: 0 4px; background: var(--hair); flex: none; }
|
|
245
|
+
.zoom { min-width: 50px; height: 32px; padding: 0 4px; border: 0; border-radius: 9px; background: transparent; color: var(--ink); font: 11.5px var(--mono); font-variant-numeric: tabular-nums; }
|
|
246
|
+
.zoom:hover { background: var(--field-hover); }
|
|
247
|
+
@media (pointer: coarse) { .tool { min-width: 40px; height: 40px; } .zoom { height: 40px; } }
|
|
248
|
+
|
|
249
|
+
/* An open panel is one opaque body; the chrome around it follows (see the [data-panels] rules below). Only a floating,
|
|
250
|
+
folded-away surface would be frosted, and no surface is shown in that state. */
|
|
251
|
+
.panel { position: fixed; z-index: 15; display: flex; flex-direction: column; border: 1px solid var(--hair); border-radius: var(--radius); background: var(--solid); box-shadow: var(--shadow); animation: rise .22s var(--ease); }
|
|
252
|
+
@keyframes rise { from { opacity: 0; transform: translateY(6px) scale(.985); } }
|
|
253
|
+
.panel.left { --sidebar-max-height: calc(var(--vh) - 2 * var(--edge) - var(--brand-h) - var(--brand-h) - 8px); left: var(--edge); top: calc(var(--edge) + var(--brand-h) + 8px); bottom: calc(max(var(--edge), env(safe-area-inset-bottom)) + var(--brand-h) - 1px); z-index: 64; width: min(var(--sidebar-w, 300px), calc(var(--vw) - 2 * var(--edge))); border-bottom: 0; border-radius: var(--radius) var(--radius) 0 0; background: var(--solid); backdrop-filter: none; box-shadow: var(--shadow); animation: none; }
|
|
254
|
+
.panel.right { right: var(--edge); top: auto; bottom: calc(max(var(--edge), env(safe-area-inset-bottom)) + var(--dock-h, var(--chrome-h)) + 8px); width: min(var(--inspector-w, 336px), calc(var(--vw) - 2 * var(--edge))); max-height: calc(var(--vh) - var(--dock-h, var(--chrome-h)) - 2 * var(--edge) - 8px); overflow-x: hidden; overflow-y: auto; padding: 10px; gap: 12px; }
|
|
255
|
+
.panel.right > * { min-width: 0; max-width: 100%; }
|
|
256
|
+
/* the grab edge of a resizable panel */
|
|
257
|
+
.resize-handle { position: fixed; z-index: 60; width: 8px; cursor: ew-resize; touch-action: none; border-radius: 4px; }
|
|
258
|
+
.resize-handle::after { content: ""; position: absolute; inset: 24px 3px; border-radius: 2px; background: transparent; transition: background .12s; }
|
|
259
|
+
.resize-handle:hover::after, .resize-handle:focus-visible::after, .resize-handle.dragging::after { background: var(--accent); }
|
|
260
|
+
body.resizing-panel { cursor: ew-resize; user-select: none; }
|
|
261
|
+
body.resizing-panel iframe { pointer-events: none; }
|
|
262
|
+
body.is-expanded .resize-handle, body:has(.scrim:not([hidden])) .resize-handle { display: none; }
|
|
263
|
+
.pane { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
|
|
264
|
+
.pane[hidden] { display: none; }
|
|
265
|
+
.panel-head { position: relative; display: flex; align-items: center; gap: 2px; padding: 6px 8px 4px; }
|
|
266
|
+
.panel-body { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; padding: 4px 6px 8px; }
|
|
267
|
+
.panel-foot { display: flex; gap: 12px; margin: 0 8px 8px; padding: 7px 12px; border-radius: var(--radius-inner); background: var(--field); }
|
|
268
|
+
.quiet { padding: 14px 10px; color: var(--muted); font-size: 12px; line-height: 1.5; }
|
|
269
|
+
.search { flex: 1; display: flex; align-items: center; gap: 6px; height: 28px; min-width: 0; padding: 0 8px; border-radius: var(--radius-inner); background: var(--field); color: var(--muted); }
|
|
270
|
+
.search:focus-within { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
271
|
+
.search input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); }
|
|
272
|
+
.search input::placeholder { color: var(--faint); }
|
|
273
|
+
.search .icon { width: 13px; height: 13px; }
|
|
274
|
+
|
|
275
|
+
/* sidebar tabs */
|
|
276
|
+
.badge { min-width: 17px; padding: 0 5px; border-radius: 9px; background: var(--accent); color: var(--on-accent); font: 600 10.5px/17px var(--mono); text-align: center; }
|
|
277
|
+
.badge.bad { background: color-mix(in srgb, var(--bad) 80%, #000); color: #fff; }
|
|
278
|
+
|
|
279
|
+
/* layers */
|
|
280
|
+
.board, .node { position: relative; display: flex; align-items: center; gap: 6px; min-height: 27px; padding: 0 8px; border-radius: var(--radius-small); cursor: default; color: var(--ink); outline-offset: -2px; }
|
|
281
|
+
.board { font-size: 12px; }
|
|
282
|
+
.board .icon { width: 14px; height: 14px; color: var(--muted); flex: none; }
|
|
283
|
+
.board .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
284
|
+
.board.on .icon { color: var(--accent); }
|
|
285
|
+
/* Reserve at least one row; cap against the sidebar budget so a long tree cannot crush it. */
|
|
286
|
+
.board-list { position: relative; flex: 0 0 auto; min-height: 33px; max-height: min(calc(7 * 27px + 8px), max(33px, calc((var(--sidebar-max-height) - 88px) / 2))); overflow-x: hidden; overflow-y: auto; margin: 0 6px 4px; padding: 3px; border-radius: var(--radius-inner); background: var(--field); }
|
|
287
|
+
.panel .panel-head .caption { font-size: 11px; letter-spacing: .02em; color: var(--muted); padding-left: 4px; white-space: normal; overflow-wrap: anywhere; min-width: 0; }
|
|
288
|
+
.board:hover, .node:hover, .node.hover { background: var(--field); }
|
|
289
|
+
.board-list .board:hover { background: var(--field-hover); }
|
|
290
|
+
.board.on, .board-list .board.on { background: var(--accent-soft); }
|
|
291
|
+
.tree { margin: 1px 0 6px; }
|
|
292
|
+
.node { padding-left: calc(var(--depth) * 12px + 4px); font-size: 12px; }
|
|
293
|
+
.node.on { background: var(--accent-soft); }
|
|
294
|
+
.node.dragging { opacity: .45; }
|
|
295
|
+
.twist { display: grid; place-items: center; width: 16px; height: 16px; color: var(--muted); flex: none; border-radius: 4px; }
|
|
296
|
+
.twist:hover { background: var(--field-hover); color: var(--ink); }
|
|
297
|
+
.twist .icon { width: 10px; height: 10px; transition: transform .12s; }
|
|
298
|
+
.twist.open .icon { transform: rotate(90deg); }
|
|
299
|
+
.twist.none { visibility: hidden; }
|
|
300
|
+
.tagname { font: 11px var(--mono); color: var(--accent); flex: none; }
|
|
301
|
+
.tagname.is-text { color: var(--muted); }
|
|
302
|
+
.snip { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
|
|
303
|
+
.snip.named { color: var(--ink); }
|
|
304
|
+
.row-rename { flex: 1; min-width: 0; height: 21px; padding: 0 5px; border: 0; border-radius: var(--radius-small); background: var(--solid); color: var(--ink); outline: var(--focus-ring) solid var(--accent); font: inherit; }
|
|
305
|
+
.drop-before::before, .drop-after::after { content: ""; position: absolute; left: 6px; right: 6px; height: 2px; border-radius: 2px; background: var(--accent); }
|
|
306
|
+
.drop-before::before { top: -1px; } .drop-after::after { bottom: -1px; }
|
|
307
|
+
.drop-inside { box-shadow: inset 0 0 0 1.5px var(--accent); }
|
|
308
|
+
|
|
309
|
+
/* menus */
|
|
310
|
+
.menu { position: fixed; z-index: 95; display: flex; flex-direction: column; min-width: min(200px, calc(var(--vw) - 16px)); max-width: min(320px, calc(var(--vw) - 16px)); max-height: calc(var(--vh) - 16px); overflow-y: auto; padding: 5px; border: 1px solid var(--hair); border-radius: var(--radius); background: var(--solid); box-shadow: var(--shadow), 0 0 0 .5px rgba(0, 0, 0, .04); animation: rise-ui .14s var(--ease); transform: scale(var(--ui)); transform-origin: 0 0; outline: none; }
|
|
311
|
+
.menu-item { display: flex; align-items: center; gap: 10px; min-height: 30px; padding: 4px 10px 4px 8px; border: 0; border-radius: var(--radius-small); background: transparent; color: var(--ink); text-align: left; }
|
|
312
|
+
.menu-item:hover:not(:disabled), .menu-item:focus-visible { background: var(--accent-soft); outline: none; }
|
|
313
|
+
.menu-item .icon { width: 15px; height: 15px; color: var(--muted); }
|
|
314
|
+
.menu-item:hover:not(:disabled) .icon, .menu-item:focus-visible .icon { color: var(--accent); }
|
|
315
|
+
.menu-item.danger { color: var(--bad-ink); }
|
|
316
|
+
.menu-item.danger .icon, .menu-item.danger:hover .icon { color: var(--bad); }
|
|
317
|
+
.menu-item.danger:hover:not(:disabled), .menu-item.danger:focus-visible { background: var(--bad-soft); }
|
|
318
|
+
.menu-item:disabled { opacity: var(--disabled); cursor: default; }
|
|
319
|
+
.menu-item.checked { color: var(--accent); font-weight: 600; }
|
|
320
|
+
.menu-item.checked .icon-space::before { content: ""; display: block; width: 6px; height: 6px; margin: 4px; border-radius: 50%; background: var(--accent); }
|
|
321
|
+
.icon-space { width: 15px; flex: none; }
|
|
322
|
+
.menu-label { flex: 1; min-width: 0; white-space: normal; overflow-wrap: anywhere; }
|
|
323
|
+
.menu-keys { flex: none; white-space: nowrap; margin-left: 18px; font: 11px var(--mono); color: var(--muted); }
|
|
324
|
+
.menu-sep { height: 1px; margin: 4px 6px; background: var(--hair); flex: none; }
|
|
325
|
+
.menu-heading { padding: 6px 10px 3px 8px; font-size: 11px; color: var(--muted); }
|
|
326
|
+
.menu-tags { columns: 1; }
|
|
327
|
+
.menu-tags .menu-item { height: 26px; font: 12px var(--mono); }
|
|
328
|
+
|
|
329
|
+
/* activity */
|
|
330
|
+
.filters { gap: 4px; padding: 6px 10px 6px; }
|
|
331
|
+
.change, .diag { display: flex; align-items: flex-start; gap: 9px; width: 100%; padding: 7px 8px; border: 0; border-radius: var(--radius-inner); background: transparent; text-align: left; color: var(--ink); }
|
|
332
|
+
button.change:hover:not(:disabled) { background: var(--field); }
|
|
333
|
+
.change:disabled { opacity: var(--disabled-field); cursor: default; }
|
|
334
|
+
.change .icon, .diag .icon { margin-top: 1px; color: var(--muted); }
|
|
335
|
+
.change.actor-agent .icon { color: var(--accent); }
|
|
336
|
+
.change.actor-file .icon { color: var(--warn); }
|
|
337
|
+
.diag { background: var(--bad-soft); margin-bottom: 4px; }
|
|
338
|
+
.diag .icon { color: var(--bad); }
|
|
339
|
+
.text { flex: 1; min-width: 0; }
|
|
340
|
+
.msg { white-space: normal; overflow-wrap: anywhere; }
|
|
341
|
+
.diag .msg { white-space: normal; }
|
|
342
|
+
.kind { display: inline-block; margin-right: 6px; padding: 0 5px; border-radius: 5px; background: var(--field-hover); color: var(--muted); font-size: 10.5px; font-weight: 600; line-height: 16px; vertical-align: 1px; }
|
|
343
|
+
.kind-undo .kind, .kind-redo .kind { background: var(--accent-soft); color: var(--accent); }
|
|
344
|
+
.kind-delete .kind { background: var(--bad-soft); color: var(--bad); }
|
|
345
|
+
.sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-size: 11px; }
|
|
346
|
+
.when { font: 11px var(--mono); color: var(--muted); flex: none; }
|
|
347
|
+
.value { display: inline-flex; gap: 5px; align-items: baseline; font: 11px var(--mono); color: var(--ink); }
|
|
348
|
+
.value i { font-style: normal; color: var(--muted); }
|
|
349
|
+
.value.warn { color: var(--warn); }
|
|
350
|
+
.link-button { flex: none; height: 24px; padding: 0 8px; border: 0; border-radius: var(--radius-small); background: var(--field-hover); color: var(--ink); font-weight: 500; }
|
|
351
|
+
.link-button:hover { background: var(--accent-soft); color: var(--accent); }
|
|
352
|
+
|
|
353
|
+
/* Addressable states and audit activity have different semantics, not two competing replay controls. */
|
|
354
|
+
.history-state { position: relative; cursor: pointer; }
|
|
355
|
+
.history-state.is-current { background: var(--accent-soft); }
|
|
356
|
+
.history-state[aria-disabled="true"] { cursor: default; }
|
|
357
|
+
.history-state[aria-busy="true"] { box-shadow: inset 0 -2px var(--accent); }
|
|
358
|
+
.history-state .icon { flex: none; }
|
|
359
|
+
.history-tag { flex: none; min-width: calc(7ch + 8px); padding: 2px 4px; border-radius: var(--radius-small); background: var(--field); color: var(--muted); font: 10px/16px var(--mono); text-align: center; white-space: nowrap; }
|
|
360
|
+
.history-state.is-current .history-tag { color: var(--accent-ink); }
|
|
361
|
+
.history-caption { padding: 7px 8px; }
|
|
362
|
+
.history-boundary { margin: 6px 8px 10px; color: var(--muted); font-size: 11px; line-height: 1.45; overflow-wrap: anywhere; }
|
|
363
|
+
.history-log { margin-top: 8px; border-radius: var(--radius-inner); background: var(--field); }
|
|
364
|
+
.history-log > summary { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px; cursor: pointer; color: var(--muted); }
|
|
365
|
+
.history-log[open] > summary .icon { transform: rotate(90deg); }
|
|
366
|
+
#activity .sub { overflow: visible; white-space: normal; overflow-wrap: anywhere; text-overflow: clip; }
|
|
367
|
+
.history-foot { display: grid; gap: 4px; }
|
|
368
|
+
.history-counters { display: flex; gap: 12px; flex-wrap: wrap; }
|
|
369
|
+
.history-feedback { min-height: 2.8em; font-size: 11px; line-height: 1.4; overflow-wrap: anywhere; }
|
|
370
|
+
.history-feedback.is-error { color: var(--bad-ink); }
|
|
371
|
+
|
|
372
|
+
/* inspector */
|
|
373
|
+
.group { display: grid; grid-template-columns: minmax(0, 1fr); gap: 7px; }
|
|
374
|
+
.html-presentation { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; min-width: 0; margin: 0; padding: 0; border: 0; }
|
|
375
|
+
.html-presentation:disabled { opacity: var(--disabled); }
|
|
376
|
+
.html-scope-toggle { justify-self: start; height: auto; min-height: 30px; padding: 5px 8px; white-space: normal; text-align: left; }
|
|
377
|
+
.grid2, .box3, .box4 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--control-min, 140px)), 1fr)); gap: 6px; }
|
|
378
|
+
.geometry-grid, .box3, .box4, .layout-box > .grid2, .appearance-box > .grid2, .typography-controls > .grid2 { --control-min: 120px; }
|
|
379
|
+
/* Selectors wrap as whole fields according to their label/value widths, not a shared numeric-field minimum. */
|
|
380
|
+
.grid2:has(> .pick) { display: flex; flex-wrap: wrap; }
|
|
381
|
+
.grid2:has(> .pick) > * { flex: 1 1 var(--control-min, 140px); }
|
|
382
|
+
.grid2:has(> .pick) > .pick { flex-basis: auto; max-width: 100%; }
|
|
383
|
+
/* layout, spacing, effects: small controls that write Tailwind classes */
|
|
384
|
+
.layout-box, .spacing-box { display: grid; gap: 8px; }
|
|
385
|
+
.pick { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; gap: 2px 6px; min-width: 0; min-height: 30px; padding: 6px 22px 6px 9px; line-height: 18px; border: 0; border-radius: var(--radius-inner); background: var(--field); color: var(--ink); text-align: left; }
|
|
386
|
+
.pick:hover { background: var(--field-hover); }
|
|
387
|
+
.pick-k { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 600; color: var(--ink); }
|
|
388
|
+
.pick-v { text-align: right; white-space: nowrap; overflow-wrap: normal; color: var(--muted); font: 11.5px/18px var(--mono); }
|
|
389
|
+
.pick-caret { position: absolute; right: 7px; top: calc(50% - 5px); width: 10px; height: 10px; color: var(--muted); transform: rotate(90deg); }
|
|
390
|
+
.variant-dot { position: absolute; top: 4px; right: 4px; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); pointer-events: none; }
|
|
391
|
+
.flow-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px; }
|
|
392
|
+
.flow-side { flex: 1 1 105px; min-width: 0; display: grid; gap: 6px; align-content: start; }
|
|
393
|
+
.align-grid { display: grid; grid-template-columns: repeat(3, 20px); grid-auto-rows: 20px; gap: 1px; padding: 3px; border-radius: var(--radius-small); background: var(--field); flex: none; }
|
|
394
|
+
.align-cell { display: grid; place-items: center; padding: 0; border: 0; border-radius: var(--radius-small); background: transparent; color: var(--faint); }
|
|
395
|
+
.align-cell i { width: 4px; height: 4px; border-radius: 50%; background: currentColor; transition: width .12s, height .12s; }
|
|
396
|
+
.align-cell.half { color: var(--muted); }
|
|
397
|
+
.align-cell:hover { background: var(--field-hover); color: var(--ink); }
|
|
398
|
+
.align-cell.on { background: var(--accent-soft); color: var(--accent); }
|
|
399
|
+
.align-cell.on i { width: 10px; height: 4px; border-radius: 2px; }
|
|
400
|
+
.segs-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; }
|
|
401
|
+
.align-controls { justify-content: space-between; }
|
|
402
|
+
.labeled-segs { display: inline-flex; flex: none; align-items: center; gap: 6px; white-space: nowrap; }
|
|
403
|
+
.segs { display: inline-flex; gap: 2px; padding: 2px; border-radius: var(--radius-inner); background: var(--field); }
|
|
404
|
+
.seg-icon { display: grid; place-items: center; width: 26px; height: 24px; padding: 0; border: 0; border-radius: var(--radius-small); background: transparent; color: var(--muted); }
|
|
405
|
+
.seg-icon .icon { width: 14px; height: 14px; }
|
|
406
|
+
.seg-icon:hover { color: var(--ink); }
|
|
407
|
+
.seg-icon.on { background: var(--solid); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .14); }
|
|
408
|
+
.seg-icon.solo { width: 28px; height: 28px; border-radius: var(--radius-small); background: var(--field); }
|
|
409
|
+
.seg-icon.solo.on { background: var(--accent-soft); color: var(--accent); box-shadow: none; }
|
|
410
|
+
.vf { position: relative; display: flex; align-items: center; gap: 3px; min-width: 0; height: 28px; padding: 0 6px 0 0; border-radius: var(--radius-small); background: var(--field); }
|
|
411
|
+
.vf:focus-within, .vf.scrubbing { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
412
|
+
.vf-k { flex: none; align-self: stretch; display: grid; place-items: center; min-width: 18px; padding-left: 6px; font: 600 10.5px var(--mono); color: var(--muted); cursor: ew-resize; user-select: none; touch-action: none; }
|
|
413
|
+
.vf-k:hover, .scrubbing .vf-k { color: var(--accent); }
|
|
414
|
+
.vf-input { flex: 1; width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); font: 11.5px var(--mono); font-variant-numeric: tabular-nums; }
|
|
415
|
+
.vf-input::placeholder { color: var(--faint); }
|
|
416
|
+
.vf-unit, .num-unit { flex: none; font: 10px var(--mono); color: var(--muted); pointer-events: none; user-select: none; }
|
|
417
|
+
.vf-unit[hidden] { display: none; }
|
|
418
|
+
.num-unit { padding-right: 8px; }
|
|
419
|
+
/* Developer-tools box model: nested, non-proportional CSS bands with the actual values on each edge. */
|
|
420
|
+
.boxmodel { --bm-edge: 24px; --bm-field: 24px; position: relative; min-width: 0; container: boxmodel / inline-size; }
|
|
421
|
+
.bm-sq { position: relative; padding: 20px var(--bm-edge); min-width: 0; border: 1px solid #4c4b40; color: #202621; }
|
|
422
|
+
.bm-position { border: 0; color: var(--ink); }
|
|
423
|
+
.bm-margin { background: #bc8c61; border-style: dashed; }
|
|
424
|
+
.bm-border { background: #e3c78f; }
|
|
425
|
+
.bm-padding { background: #c6d7a7; border-style: dashed; }
|
|
426
|
+
.bm-caption { position: absolute; top: 2px; left: 4px; font: 10px/14px var(--font); pointer-events: none; }
|
|
427
|
+
.bm-cell { position: absolute; display: flex; justify-content: center; align-items: center; width: var(--bm-field); height: 18px; min-width: 0; font: 10px/16px var(--mono); }
|
|
428
|
+
.bm-cell.bm-t { top: 1px; left: 50%; transform: translateX(-50%); }
|
|
429
|
+
.bm-cell.bm-b { bottom: 1px; left: 50%; transform: translateX(-50%); }
|
|
430
|
+
.bm-cell.bm-l { left: 0; top: 50%; transform: translateY(-50%); width: var(--bm-field); }
|
|
431
|
+
.bm-cell.bm-r { right: 0; top: 50%; transform: translateY(-50%); width: var(--bm-field); }
|
|
432
|
+
.bm-centre { min-width: 0; }
|
|
433
|
+
.vf.bm-field, .vf.bm-offset, .vf.bm-value { flex: none; width: var(--bm-field); min-height: 18px; height: 18px; padding: 0; border-radius: var(--radius-small); background: transparent; box-shadow: none; color: inherit; }
|
|
434
|
+
.bm-field:hover, .bm-offset:hover, .bm-value:hover { background: #ffffff30; }
|
|
435
|
+
.bm-field:focus-within, .bm-offset:focus-within, .bm-value:focus-within { background: var(--solid); color: var(--ink); }
|
|
436
|
+
.bm-field .vf-input, .bm-offset .vf-input, .bm-value .vf-input { width: 100%; min-width: 0; padding: 0; color: inherit; font: 10px/16px var(--mono); text-align: center; }
|
|
437
|
+
.bm-field .vf-input::placeholder, .bm-offset .vf-input::placeholder, .bm-value .vf-input::placeholder { color: inherit; opacity: 1; }
|
|
438
|
+
.bm-core { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0 3px; min-width: 0; min-height: 23px; padding: 2px; border: 1px solid #314554; background: #8eaec2; color: #17232b; font: 10px/15px var(--mono); }
|
|
439
|
+
.vf.bm-dimension { width: min(100%, var(--bm-value-width)); min-width: 3ch; }
|
|
440
|
+
.bm-value .vf-input { font-size: inherit; }
|
|
441
|
+
.spacing-box { display: grid; gap: 6px; }
|
|
442
|
+
.bm-unit { position: absolute; top: 4px; right: 5px; color: var(--muted); font: 9px/12px var(--mono); pointer-events: none; }
|
|
443
|
+
@container boxmodel (max-width: 270px) {
|
|
444
|
+
.bm-sq { --bm-edge: 20px; --bm-field: 20px; }
|
|
445
|
+
.bm-cell, .bm-field .vf-input, .bm-offset .vf-input { font-size: 8.5px; }
|
|
446
|
+
}
|
|
447
|
+
/* At phone/200% widths, stagger the side values down the bands instead of hiding or overlapping them. */
|
|
448
|
+
@container boxmodel (max-width: 230px) {
|
|
449
|
+
.bm-sq { --bm-edge: 8px; --bm-field: 24px; }
|
|
450
|
+
.bm-padding { --bm-edge: 24px; }
|
|
451
|
+
.bm-caption { font-size: 8px; }
|
|
452
|
+
.bm-cell.bm-l, .bm-cell.bm-r { top: auto; bottom: 4px; transform: none; }
|
|
453
|
+
.bm-cell, .bm-field .vf-input, .bm-offset .vf-input, .bm-core { font-size: 9px; }
|
|
454
|
+
}
|
|
455
|
+
/* Long signed/fractional values earn rows, not clipping or tiny type; short values keep the reference's compact shape. */
|
|
456
|
+
.bm-expanded-values { padding-top: 76px; }
|
|
457
|
+
.bm-expanded-values > .bm-cell { width: max(var(--bm-field), var(--bm-value-width)); max-width: calc(100% - 4px); }
|
|
458
|
+
.bm-expanded-values > .bm-cell > .vf { width: 100%; }
|
|
459
|
+
.bm-expanded-values > .bm-t { top: 18px; }
|
|
460
|
+
.bm-expanded-values > .bm-l { top: 36px; left: 2px; bottom: auto; transform: none; }
|
|
461
|
+
.bm-expanded-values > .bm-r { top: 54px; right: 2px; bottom: auto; transform: none; }
|
|
462
|
+
.box4 { min-width: 0; flex: 1 1 var(--control-min); }
|
|
463
|
+
.caption.has-variants::after { content: ""; display: inline-block; width: 5px; height: 5px; margin-left: 4px; border-radius: 50%; background: var(--accent); vertical-align: 1px; }
|
|
464
|
+
.quick-attrs { margin-top: 1px; }
|
|
465
|
+
/* code with colors: a highlighted copy under a transparent textarea, identical metrics */
|
|
466
|
+
.code { position: relative; border-radius: var(--radius-inner); background: var(--field); }
|
|
467
|
+
.code-hl, .code-ta { margin: 0; padding: 7px 9px; border: 0; font: 11.5px/1.5 var(--mono); letter-spacing: 0; tab-size: 2; white-space: pre-wrap; overflow-wrap: anywhere; word-break: normal; }
|
|
468
|
+
.code-hl { position: absolute; inset: 0; overflow: hidden; color: var(--ink); pointer-events: none; }
|
|
469
|
+
.code-ta { position: relative; display: block; width: 100%; min-height: 54px; resize: none; outline: 0; background: transparent; color: transparent; caret-color: var(--ink); scrollbar-width: none; border-radius: var(--radius-inner); }
|
|
470
|
+
.code-ta::selection { background: var(--accent-soft); color: transparent; }
|
|
471
|
+
.code-ta::placeholder { color: var(--faint); }
|
|
472
|
+
.code:focus-within { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
473
|
+
.syn-comment { color: var(--syn-comment); font-style: italic; }
|
|
474
|
+
.syn-atrule { color: var(--syn-atrule); }
|
|
475
|
+
.syn-tag, .syn-id { color: var(--syn-selector); }
|
|
476
|
+
.syn-class { color: var(--syn-class); }
|
|
477
|
+
.syn-pseudo { color: var(--syn-pseudo); }
|
|
478
|
+
.syn-attr { color: var(--syn-string); }
|
|
479
|
+
.syn-prop { color: var(--syn-prop); }
|
|
480
|
+
.syn-number { color: var(--syn-number); }
|
|
481
|
+
.syn-color { color: var(--syn-color); }
|
|
482
|
+
.syn-string { color: var(--syn-string); }
|
|
483
|
+
.syn-func { color: var(--syn-func); }
|
|
484
|
+
.syn-var { color: var(--syn-var); }
|
|
485
|
+
.syn-important { color: var(--syn-important); font-weight: 600; }
|
|
486
|
+
.syn-punct { color: var(--syn-punct); }
|
|
487
|
+
.num { display: flex; align-items: center; height: 30px; border-radius: var(--radius-inner); background: var(--field); overflow: hidden; }
|
|
488
|
+
.num:focus-within, .num.scrubbing { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
489
|
+
.num-label { width: 26px; text-align: center; font: 600 10.5px var(--mono); color: var(--muted); cursor: ew-resize; user-select: none; touch-action: none; align-self: stretch; display: grid; place-items: center; }
|
|
490
|
+
.num-label:hover, .scrubbing .num-label { color: var(--accent); }
|
|
491
|
+
.num-input, .field { min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); }
|
|
492
|
+
.num-input { flex: 1; width: 100%; padding: 0 3px 0 0; font: 12px var(--mono); font-variant-numeric: tabular-nums; }
|
|
493
|
+
.field { width: 100%; padding: 6px 9px; border-radius: var(--radius-inner); background: var(--field); resize: none; display: block; }
|
|
494
|
+
.field:focus { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
495
|
+
.field.mono, textarea.field { font: 11.5px/1.5 var(--mono); }
|
|
496
|
+
textarea.field { overflow: auto; }
|
|
497
|
+
.field::placeholder { color: var(--faint); }
|
|
498
|
+
.chips { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
|
|
499
|
+
.chip { height: 22px; padding: 0 8px; border: 0; border-radius: 11px; background: var(--field); color: var(--muted); font: 11px var(--mono); }
|
|
500
|
+
.chip:hover { color: var(--ink); background: var(--field-hover); }
|
|
501
|
+
.chip.on { background: var(--accent-soft); color: var(--accent); }
|
|
502
|
+
.note { display: flex; align-items: center; gap: 7px; padding: 5px 5px 5px 9px; border-radius: var(--radius-inner); background: var(--accent-soft); color: var(--ink); font-size: 11.5px; }
|
|
503
|
+
.note .icon { width: 14px; height: 14px; color: var(--accent); }
|
|
504
|
+
.note span { flex: 1; }
|
|
505
|
+
.fold > summary { list-style: none; cursor: pointer; color: var(--muted); font-size: 11.5px; display: inline-flex; align-items: center; gap: 6px; padding: 2px 0; user-select: none; border-radius: 5px; }
|
|
506
|
+
.fold > summary:hover { color: var(--ink); }
|
|
507
|
+
.fold > summary::-webkit-details-marker { display: none; }
|
|
508
|
+
.fold > summary::before { content: ""; width: 5px; height: 5px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg); transition: transform .12s; }
|
|
509
|
+
.fold[open] > summary::before { transform: rotate(45deg); }
|
|
510
|
+
.fold[open] > summary { margin-bottom: 6px; }
|
|
511
|
+
.fold-count { font: 10.5px var(--mono); color: var(--muted); }
|
|
512
|
+
.caption { font-size: 11px; color: var(--muted); }
|
|
513
|
+
/* Key–value rows share one label column, as wide as the longest label (up to 45%). */
|
|
514
|
+
.rows { display: grid; grid-template-columns: 16px fit-content(45%) minmax(0, 1fr) auto; gap: 5px; }
|
|
515
|
+
.rows > * { grid-column: 1 / -1; min-width: 0; }
|
|
516
|
+
.kv { display: grid; grid-template-columns: subgrid; align-items: center; }
|
|
517
|
+
.kv .k { font: 11px var(--mono); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
518
|
+
.kv.add > :first-child { grid-column: 1 / 3; }
|
|
519
|
+
.kv.add > :last-child { grid-column: 3 / 5; }
|
|
520
|
+
.kv .field { padding: 4px 7px; }
|
|
521
|
+
.swatch { width: 16px; height: 16px; padding: 0; border: 1px solid var(--hair); border-radius: var(--radius-small); background: none; cursor: pointer; overflow: hidden; }
|
|
522
|
+
.swatch::-webkit-color-swatch-wrapper { padding: 0; } .swatch::-webkit-color-swatch { border: 0; }
|
|
523
|
+
.swatch.plain { background: var(--field); cursor: default; display: inline-block; }
|
|
524
|
+
.swatch.none { visibility: hidden; }
|
|
525
|
+
.classes { display: flex; flex-wrap: wrap; gap: 4px; padding: 5px; border-radius: var(--radius-inner); background: var(--field); min-height: 32px; cursor: text; }
|
|
526
|
+
.classes:focus-within { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
527
|
+
.cls { position: relative; display: inline-flex; align-items: center; min-height: 20px; max-width: 100%; border-radius: 6px; background: var(--accent-soft); color: var(--accent); font: 11px var(--mono); }
|
|
528
|
+
.cls-name { align-self: stretch; min-width: 0; min-height: 20px; padding: 0 7px; border: 0; border-radius: inherit; background: transparent; color: inherit; font: inherit; text-align: left; white-space: normal; overflow-wrap: anywhere; } /* a long arbitrary class wraps inside its chip instead of being cut */
|
|
529
|
+
.cls-x { position: absolute; right: 2px; top: 2px; display: none; place-items: center; width: 16px; height: 16px; margin: 0; padding: 0; border: 0; border-radius: 4px; background: color-mix(in srgb, var(--solid) 88%, var(--accent)); color: inherit; opacity: .9; } /* an overlay: showing it must never reflow the chips (a reflow can move the chip out from under the pointer) */
|
|
530
|
+
.cls-x .icon { width: 10px; height: 10px; }
|
|
531
|
+
.cls:hover .cls-x, .cls:focus-within .cls-x { display: grid; }
|
|
532
|
+
.cls-x:hover { opacity: 1; background: var(--bad-soft); color: var(--bad); }
|
|
533
|
+
.cls:has(.cls-name:hover) { background: color-mix(in srgb, var(--accent) 22%, transparent); }
|
|
534
|
+
.cls-color { width: 8px; height: 8px; margin-left: 6px; margin-right: -3px; flex: none; border-radius: 2px; box-shadow: inset 0 0 0 1px var(--hair); }
|
|
535
|
+
.cls[data-kind="custom"] { background: var(--field-hover); color: var(--ink); }
|
|
536
|
+
.cls[data-kind="custom"] .cls-name { text-decoration: underline dotted var(--muted); text-underline-offset: 3px; }
|
|
537
|
+
.cls[data-kind="marker"] { background: var(--field-hover); color: var(--muted); }
|
|
538
|
+
.cls[data-kind="unknown"] { background: var(--bad-soft); color: var(--bad); }
|
|
539
|
+
.cls[data-kind="unknown"] .cls-name { text-decoration: underline wavy color-mix(in srgb, var(--bad) 70%, transparent); text-underline-offset: 3px; }
|
|
540
|
+
.cls-edit { height: 20px; min-width: 4ch; max-width: 100%; padding: 0 6px; border: 0; border-radius: var(--radius-small); outline: var(--focus-ring) solid var(--accent); background: var(--solid); color: var(--ink); font: 11px var(--mono); }
|
|
541
|
+
.cls-input { flex: 1; min-width: 6em; height: 20px; border: 0; outline: 0; background: transparent; color: var(--ink); font: 11.5px var(--mono); }
|
|
542
|
+
.cls-input::placeholder { color: var(--faint); }
|
|
543
|
+
.suggest { transform: scale(var(--ui)); transform-origin: 0 0; position: fixed; z-index: 96; width: min(300px, calc(var(--vw) - 12px)); padding: 4px; border: 1px solid var(--hair); border-radius: 10px; background: var(--solid); box-shadow: var(--shadow); font: 11.5px var(--mono); }
|
|
544
|
+
.suggest-item { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 8px; border-radius: 6px; color: var(--ink); cursor: pointer; }
|
|
545
|
+
.suggest-item.on { background: var(--accent-soft); }
|
|
546
|
+
.suggest-mark { width: 8px; height: 8px; flex: none; border-radius: 2px; background: var(--field-hover); box-shadow: inset 0 0 0 1px var(--hair); }
|
|
547
|
+
.suggest-mark.variant { border-radius: 50%; background: transparent; box-shadow: inset 0 0 0 1.5px var(--accent); }
|
|
548
|
+
.suggest-mark.used { background: var(--accent); box-shadow: none; }
|
|
549
|
+
.suggest-name { flex: none; max-width: 60%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
550
|
+
.suggest-hint { flex: 1; min-width: 0; color: var(--muted); font-size: 10.5px; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
551
|
+
.crumbs { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; margin: -2px 0 -4px; }
|
|
552
|
+
.crumb { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; min-height: 22px; padding: 0 6px; border: 0; border-radius: 6px; background: transparent; color: var(--muted); font: 11px var(--mono); }
|
|
553
|
+
.crumb.home { font: 11.5px var(--font); padding-left: 4px; }
|
|
554
|
+
.crumb.home { min-width: 0; }
|
|
555
|
+
.crumb.home span { white-space: normal; overflow-wrap: anywhere; max-width: 100%; }
|
|
556
|
+
.crumb .icon { width: 13px; height: 13px; }
|
|
557
|
+
.crumb:hover { background: var(--field); color: var(--ink); }
|
|
558
|
+
.crumb-sep { width: 4px; height: 4px; border-right: 1.2px solid var(--faint); border-top: 1.2px solid var(--faint); transform: rotate(45deg); margin: 0 2px; }
|
|
559
|
+
.node-head { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
560
|
+
.tag { display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 6px 0 8px; border: 0; border-radius: var(--radius-small); background: var(--accent-soft); color: var(--accent); font: 600 12px var(--mono); }
|
|
561
|
+
.tag:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
|
|
562
|
+
.tag.static { padding-right: 8px; }
|
|
563
|
+
.tag .caret { width: 10px; height: 10px; transform: rotate(90deg); }
|
|
564
|
+
.ident { min-width: 0; height: 24px; padding: 0 6px; border: 0; border-radius: var(--radius-small); background: transparent; font: 11px var(--mono); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
565
|
+
.ident:hover { background: var(--field); color: var(--ink); }
|
|
566
|
+
.ident-field { display: inline-flex; align-items: center; min-width: 0; height: 24px; padding: 0 6px 0 7px; border-radius: var(--radius-small); color: var(--muted); font: 11px var(--mono); cursor: text; }
|
|
567
|
+
.ident-field:hover { background: var(--field); }
|
|
568
|
+
.ident-field:focus-within { background: var(--field); outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); color: var(--ink); }
|
|
569
|
+
.ident-hash { flex: none; }
|
|
570
|
+
.ident-input { min-width: 0; max-width: 100%; padding: 0; border: 0; outline: 0; background: transparent; color: var(--ink); font: inherit; }
|
|
571
|
+
.values { display: flex; flex-wrap: wrap; gap: 4px 12px; padding: 7px 9px; border-radius: var(--radius-inner); background: var(--field); }
|
|
572
|
+
.count { display: flex; align-items: baseline; gap: 8px; color: var(--muted); }
|
|
573
|
+
.count b { font: 600 20px var(--mono); color: var(--ink); }
|
|
574
|
+
.actions { display: flex; flex-wrap: wrap; gap: 2px; margin: 0 -4px; }
|
|
575
|
+
.actions.smart-bar { flex-shrink: 0; flex-wrap: nowrap; overflow: hidden; margin: 0; }
|
|
576
|
+
.tool[hidden] { display: none; }
|
|
577
|
+
|
|
578
|
+
/* ---- floating hints ------------------------------------------------------- */
|
|
579
|
+
/* Floating surfaces follow the theme like panels and menus: never an inverted white box in dark mode. */
|
|
580
|
+
.tip { transform-origin: 0 0; position: fixed; z-index: 100; width: max-content; max-width: min(280px, calc(var(--vw) - 12px)); padding: 4px 9px; border: 1px solid var(--hair); border-radius: var(--radius-small); background: var(--solid); color: var(--ink); box-shadow: var(--shadow); font-size: 11.5px; line-height: 1.35; pointer-events: none; white-space: pre-wrap; overflow-wrap: anywhere; opacity: 0; transform: scale(var(--ui)) translateY(2px); transition: opacity .12s, transform .12s; }
|
|
581
|
+
.tip.show { opacity: 1; transform: scale(var(--ui)); }
|
|
582
|
+
.tip.code { max-width: min(380px, calc(var(--vw) - 12px)); padding: 7px 10px 8px; white-space: normal; }
|
|
583
|
+
.tip-title { display: block; margin-bottom: 4px; font: 600 11px var(--mono); color: var(--ink); white-space: normal; overflow-wrap: anywhere; }
|
|
584
|
+
.tip-code { margin: 0; font: 11px/1.5 var(--mono); color: var(--muted); white-space: pre-wrap; overflow-wrap: anywhere; max-height: calc(var(--vh) * 0.5); overflow: hidden; }
|
|
585
|
+
.toast { position: fixed; z-index: 90; left: 50%; top: calc(var(--edge) + 2px); display: flex; align-items: center; gap: 10px; max-width: min(540px, calc(var(--vw) - 24px)); padding: 6px 6px 6px 14px; transform: translateX(-50%); border: 1px solid var(--hair); border-radius: 12px; background: var(--solid); color: var(--ink); box-shadow: var(--shadow); }
|
|
586
|
+
.toast.pop { animation: rise .2s var(--ease); }
|
|
587
|
+
.toast-msg { flex: 1; min-width: 0; }
|
|
588
|
+
.toast-action { flex: none; height: 26px; padding: 0 10px; border: 0; border-radius: var(--radius-small); background: var(--accent-soft); color: var(--accent-ink); font-weight: 600; }
|
|
589
|
+
.toast-action:hover { background: color-mix(in srgb, var(--accent) 24%, transparent); }
|
|
590
|
+
.toast-close { flex: none; display: grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: var(--radius-small); background: transparent; color: inherit; opacity: .6; }
|
|
591
|
+
.toast-close:hover { opacity: 1; background: var(--field-hover); }
|
|
592
|
+
.toast-close .icon { width: 13px; height: 13px; }
|
|
593
|
+
|
|
594
|
+
.expanded-bar { position: fixed; z-index: 60; top: 10px; left: 50%; display: flex; align-items: center; gap: 4px; padding: 3px; transform: translateX(-50%); border: 1px solid var(--hair); border-radius: var(--radius); background: var(--panel); backdrop-filter: blur(18px); box-shadow: var(--shadow); animation: rise .2s var(--ease); }
|
|
595
|
+
.expanded-bar.moved { transform: none; }
|
|
596
|
+
.expanded-bar.dragging { cursor: grabbing; box-shadow: 0 6px 24px rgba(0, 0, 0, .3); }
|
|
597
|
+
.expanded-back { display: inline-flex; align-items: center; gap: 8px; min-height: 30px; max-width: calc(var(--vw) * 0.6); padding: 0 12px 0 9px; border: 0; border-radius: 10px; background: transparent; color: var(--ink); font-weight: 500; cursor: grab; touch-action: none; user-select: none; }
|
|
598
|
+
.expanded-back:hover { background: var(--field-hover); }
|
|
599
|
+
.expanded-back:active, .expanded-bar.dragging .expanded-back { cursor: grabbing; }
|
|
600
|
+
.expanded-back .icon { width: 15px; height: 15px; flex: none; color: var(--muted); }
|
|
601
|
+
.expanded-back #expanded-title { white-space: normal; overflow-wrap: anywhere; }
|
|
602
|
+
body.bar-dragging iframe { pointer-events: none; }
|
|
603
|
+
body.bar-dragging { user-select: none; }
|
|
604
|
+
/* In full screen only the name/back control stays. */
|
|
605
|
+
|
|
606
|
+
/* open / save project */
|
|
607
|
+
.project-dialog { width: min(560px, 100%); display: grid; gap: 10px; }
|
|
608
|
+
.image-history { display: grid; gap: 4px; min-width: 0; }
|
|
609
|
+
.image-history .field { width: 100%; min-width: 0; text-overflow: ellipsis; }
|
|
610
|
+
.image-review { margin: 0; }
|
|
611
|
+
.image-review legend { padding: 0 4px; font-weight: 600; }
|
|
612
|
+
.image-review label { display: flex; align-items: flex-start; gap: 8px; margin: 10px 0; }
|
|
613
|
+
.image-review input[type="checkbox"] { flex: none; margin-top: 3px; accent-color: var(--accent); }
|
|
614
|
+
.project-hint { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.5; }
|
|
615
|
+
.file-picker { display: grid; gap: 8px; min-width: 0; }
|
|
616
|
+
.file-picker-path { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
617
|
+
.file-picker-path .field { flex: 1; min-width: 0; }
|
|
618
|
+
.file-picker-path .tool { flex: none; }
|
|
619
|
+
.file-picker[aria-busy="true"] .dir-list { opacity: .6; }
|
|
620
|
+
.file-picker-status { min-height: 3em; margin: 0; overflow-wrap: anywhere; }
|
|
621
|
+
.dir-list { display: grid; align-content: start; gap: 1px; height: 260px; overflow-y: auto; padding: 4px; border-radius: 10px; background: var(--field); }
|
|
622
|
+
.dir { display: flex; align-items: center; gap: 9px; height: 30px; padding: 0 9px; border: 0; border-radius: var(--radius-small); background: transparent; color: var(--ink); text-align: left; }
|
|
623
|
+
.dir:hover, .dir:focus-visible { background: var(--field-hover); }
|
|
624
|
+
.dir .icon { width: 15px; height: 15px; color: var(--muted); flex: none; }
|
|
625
|
+
.dir.is-project .icon { color: var(--accent); }
|
|
626
|
+
.dir-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
627
|
+
.dir-tag { padding: 0 7px; border-radius: 6px; background: var(--accent-soft); color: var(--accent-ink); font-size: 10.5px; line-height: 18px; }
|
|
628
|
+
.dir-empty { padding: 18px 10px; color: var(--muted); }
|
|
629
|
+
.project-status { min-width: 0; min-height: 3em; overflow-wrap: anywhere; }
|
|
630
|
+
/* Anchored to the top so a longer message or recovery box grows downward and never moves the controls above it. */
|
|
631
|
+
#project { place-items: start center; padding-top: min(calc(var(--vh) * 0.14), 120px); }
|
|
632
|
+
#project .dialog-foot { align-items: flex-start; padding-bottom: 0; }
|
|
633
|
+
.project-go { height: 32px; min-width: 156px; padding: 0 14px; }
|
|
634
|
+
.project-go:disabled { opacity: var(--disabled); cursor: default; }
|
|
635
|
+
/* Read-only external-file recovery (picker, launcher and diagnostics). */
|
|
636
|
+
.project-recovery:empty, .project-revision:empty { display: none; }
|
|
637
|
+
.project-revision { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
|
|
638
|
+
.resource-access { min-width: 0; max-width: 100%; padding: 12px; border: 1px solid var(--hair); border-radius: 10px; background: var(--field); color: var(--ink); font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; }
|
|
639
|
+
.resource-access h3 { margin: 0 0 8px; font-size: 13px; }
|
|
640
|
+
.resource-access p { margin: 6px 0; }
|
|
641
|
+
.resource-access code { font: 11px var(--mono); }
|
|
642
|
+
.resource-access :focus-visible { outline: var(--focus-ring) solid var(--accent); outline-offset: 2px; }
|
|
643
|
+
/* help */
|
|
644
|
+
.scrim { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 16px; background: rgba(10, 10, 8, .28); backdrop-filter: blur(2px); animation: fade .15s ease-out; }
|
|
645
|
+
@keyframes fade { from { opacity: 0; } }
|
|
646
|
+
.dialog { width: min(720px, 100%); max-height: calc(var(--vh) - 32px); overflow-y: auto; padding: 16px 18px 14px; border: 1px solid var(--hair); border-radius: 16px; background: var(--solid); box-shadow: var(--shadow); animation: rise .2s var(--ease); }
|
|
647
|
+
.dialog-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
|
|
648
|
+
.dialog h2 { margin: 0; font-size: 15px; font-weight: 600; }
|
|
649
|
+
/* Settings: one block per section, the divider between blocks, so nothing is glued to a line and the space above and below it
|
|
650
|
+
is the same everywhere. */
|
|
651
|
+
.settings-block { padding: 12px 0; }
|
|
652
|
+
.settings-block + .settings-block { border-top: 1px solid var(--hair); }
|
|
653
|
+
.settings-row { display: flex; align-items: center; gap: 12px; }
|
|
654
|
+
.settings-label { min-width: 96px; color: var(--muted); }
|
|
655
|
+
.settings-row { flex-wrap: wrap; }
|
|
656
|
+
#help .dialog { width: min(560px, 100%); min-width: 0; }
|
|
657
|
+
#help .segmented { flex-wrap: wrap; max-width: 100%; }
|
|
658
|
+
.settings-output { display: grid; gap: 8px; min-width: 0; }
|
|
659
|
+
.settings-field { display: flex; align-items: stretch; gap: 6px; min-width: 0; }
|
|
660
|
+
.settings-field input { flex: 1 1 auto; min-width: 0; }
|
|
661
|
+
.settings-field .tool { flex: none; min-width: 34px; }
|
|
662
|
+
.settings-picker { display: grid; gap: 6px; min-width: 0; padding: 8px; border: 1px solid var(--hair); border-radius: var(--radius-inner); background: var(--field); }
|
|
663
|
+
.settings-picker[hidden] { display: none; }
|
|
664
|
+
.settings-picker .dir-list { height: 180px; }
|
|
665
|
+
.settings-picker > .tool { justify-self: end; }
|
|
666
|
+
.settings-output h3 { margin: 0 0 4px; font-size: 13px; font-weight: 600; }
|
|
667
|
+
.settings-path { display: grid; gap: 3px; min-width: 0; }
|
|
668
|
+
.settings-path code { font: 11px var(--mono); overflow-wrap: anywhere; }
|
|
669
|
+
.settings-field input { width: 100%; min-width: 0; padding: 7px 9px; border: 1px solid var(--hair); border-radius: var(--radius-inner); color: var(--ink); background: var(--field); font: inherit; }
|
|
670
|
+
.settings-output .caption { margin: 0; overflow-wrap: anywhere; }
|
|
671
|
+
.settings-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin-top: 4px; }
|
|
672
|
+
.settings-actions .tool { width: auto; height: auto; min-height: 30px; padding: 5px 9px; white-space: normal; }
|
|
673
|
+
/* Buttons that look like buttons: the one that saves is filled, the others are quiet fields. */
|
|
674
|
+
.settings-actions .tool { background: var(--field-hover); color: var(--ink); font-weight: 500; }
|
|
675
|
+
.settings-actions .tool:hover:not(:disabled) { background: var(--accent-soft); color: var(--accent); }
|
|
676
|
+
.settings-actions .tool.primary { background: var(--accent); color: var(--on-accent); }
|
|
677
|
+
.settings-actions .tool.primary:hover:not(:disabled) { background: var(--accent-ink); color: var(--on-accent); }
|
|
678
|
+
.settings-output :disabled { opacity: var(--disabled); cursor: default; }
|
|
679
|
+
.settings-status { min-height: 1.5em; }
|
|
680
|
+
.settings-row:last-child { border-bottom: 0; }
|
|
681
|
+
.shortcut-grid { columns: 2 260px; column-gap: 28px; }
|
|
682
|
+
.shortcut-group { break-inside: avoid; margin-bottom: 14px; }
|
|
683
|
+
.shortcut-group h3 { margin: 0 0 6px; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
|
|
684
|
+
.shortcut-group dl { display: grid; grid-template-columns: minmax(0, 1fr) max-content; gap: 4px 12px; margin: 0; }
|
|
685
|
+
.shortcut-group dt { min-width: 0; color: var(--ink); overflow-wrap: anywhere; }
|
|
686
|
+
.shortcut-group dd { margin: 0; font: 11px var(--mono); color: var(--muted); text-align: right; white-space: nowrap; }
|
|
687
|
+
/* Narrow screens: a name and its keys are one unit stacked on two lines, so a long key list never squeezes every name. */
|
|
688
|
+
html.w440 .shortcut-group dl { grid-template-columns: minmax(0, 1fr); gap: 0; }
|
|
689
|
+
html.w440 .shortcut-group dt { padding-top: 5px; }
|
|
690
|
+
html.w440 .shortcut-group dd { text-align: left; padding-bottom: 5px; white-space: normal; }
|
|
691
|
+
.dialog-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding-top: 12px; border-top: 1px solid var(--hair); }
|
|
692
|
+
.segmented { display: inline-flex; gap: 2px; padding: 2px; border-radius: 9px; background: var(--field); }
|
|
693
|
+
.seg { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border: 0; border-radius: var(--radius-small); background: transparent; color: var(--muted); }
|
|
694
|
+
.seg .icon { width: 14px; height: 14px; }
|
|
695
|
+
.seg:hover { color: var(--ink); }
|
|
696
|
+
.seg.on { background: var(--solid); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .12); }
|
|
697
|
+
|
|
698
|
+
/* ---- search pill, agent chip ---------------------------------------------- */
|
|
699
|
+
/* The search pill is a chrome pill like the DIVLET button and the tabs, so it carries the same frame and radius even though it
|
|
700
|
+
is also a `.tool` (whose reset would otherwise leave it borderless and squarer). */
|
|
701
|
+
/* Also a `.tool`, whose reset is transparent: the search pill is a chrome pill like the DIVLET button, the tabs and the dock. */
|
|
702
|
+
.search-pill { display: inline-flex; align-items: center; gap: 7px; height: var(--brand-h); padding: 0 8px 0 11px; border: 1px solid var(--hair); border-radius: var(--radius); background: var(--panel); backdrop-filter: blur(18px) saturate(1.4); box-shadow: var(--shadow); color: var(--muted); }
|
|
703
|
+
.search-pill .icon { width: 14px; height: 14px; }
|
|
704
|
+
.search-pill kbd { font-size: 10.5px; padding: 0 5px; line-height: 17px; }
|
|
705
|
+
.search-pill:hover { color: var(--ink); background: var(--solid); }
|
|
706
|
+
.spinner { width: 12px; height: 12px; flex: none; border-radius: 50%; border: 1.6px solid var(--accent-soft); border-top-color: var(--accent); animation: spin .8s linear infinite; }
|
|
707
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
708
|
+
|
|
709
|
+
/* ---- Ask Pi --------------------------------------------------------------- */
|
|
710
|
+
/* the context of a request is a path, like the layers tree: artboard › container › element */
|
|
711
|
+
.ask-about { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; min-width: 0; margin: 0; }
|
|
712
|
+
.ask-about .crumb { height: 24px; }
|
|
713
|
+
.crumbs-bar { position: fixed; z-index: 14; bottom: max(var(--edge), env(safe-area-inset-bottom)); min-height: var(--chrome-h); display: flex; align-items: flex-end; justify-content: center; margin: 0; pointer-events: none; }
|
|
714
|
+
.crumbs-bar.cramped { visibility: hidden; }
|
|
715
|
+
.crumbs-track { display: flex; align-items: center; flex-wrap: wrap; justify-content: center; gap: 2px; max-width: 100%; padding: 3px 5px; border: 1px solid var(--hair); border-radius: 10px; background: var(--panel); backdrop-filter: blur(16px); box-shadow: var(--shadow); pointer-events: auto; }
|
|
716
|
+
.crumbs-bar .crumb { height: 24px; flex: none; max-width: 100%; }
|
|
717
|
+
.crumbs-bar .crumb.home { flex: 0 1 auto; min-width: 0; }
|
|
718
|
+
.crumb.current { background: var(--field); color: var(--ink); }
|
|
719
|
+
.ask-more { padding: 0 6px; font: 11px var(--mono); color: var(--muted); }
|
|
720
|
+
.ask-input { width: 100%; min-height: 40px; max-height: 220px; padding: 9px 11px; border: 0; border-radius: var(--radius-inner); background: var(--field); color: var(--ink); font: 13.5px/1.45 var(--font); resize: none; outline: none; }
|
|
721
|
+
.ask-input:focus { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
722
|
+
.ask-input::placeholder { color: var(--faint); }
|
|
723
|
+
.ask-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px; }
|
|
724
|
+
|
|
725
|
+
/* The session that answers this board, when the host can change it: two chips, no labels — a model and a thinking level read as
|
|
726
|
+
their own values. An MCP client cannot offer this, so there the row is absent rather than disabled. */
|
|
727
|
+
.agent-session { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; min-width: 0; flex: 0 1 auto; }
|
|
728
|
+
.agent-session[hidden] { display: none; }
|
|
729
|
+
.agent-chip { max-width: 100%; height: 24px; min-width: 0; padding: 0 9px; border: 0; border-radius: 999px; background: var(--field); color: var(--muted); font: 10.5px var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
730
|
+
.agent-chip:hover, .agent-chip:focus-visible { background: var(--field-hover); color: var(--ink); }
|
|
731
|
+
.agent-settings-error { margin-top: 4px; padding: 5px 8px; border-radius: var(--radius-small); background: var(--field); color: var(--bad); font-size: 11.5px; line-height: 1.4; }
|
|
732
|
+
.ask-hint { flex: 1 1 140px; min-width: 0; white-space: normal; color: var(--muted); font-size: 11.5px; line-height: 1.4; }
|
|
733
|
+
.ask-hint.busy { color: var(--accent); }
|
|
734
|
+
.ask-scope { display: flex; flex-wrap: wrap; gap: 2px 6px; align-items: baseline; padding: 0 2px; font-size: 11.5px; line-height: 1.4; color: var(--muted); }
|
|
735
|
+
.ask-scope-k { flex: none; font-weight: 600; }
|
|
736
|
+
.ask-scope-v { display: inline-flex; align-items: baseline; gap: 4px; min-width: 0; max-width: 100%; color: var(--ink); }
|
|
737
|
+
/* The frame name may be long; it is the one part of the scope line that is cut. What follows it never is. */
|
|
738
|
+
.ask-scope-frame { min-width: 3ch; max-width: 18ch; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
739
|
+
.ask-scope-sep, .ask-scope-tail { flex: none; white-space: nowrap; }
|
|
740
|
+
.ask-suggest { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 12px 8px; }
|
|
741
|
+
.ask-suggest[hidden] { display: none; }
|
|
742
|
+
.ask-idea { flex: 0 1 auto; max-width: 100%; min-height: 28px; padding: 4px 10px; border: 0; border-radius: 14px; background: var(--field); color: var(--muted); font: 11.5px/1.35 var(--font); white-space: normal; overflow-wrap: anywhere; text-align: left; }
|
|
743
|
+
.ask-idea:hover { background: var(--field-hover); color: var(--ink); }
|
|
744
|
+
.node-name { font-size: 12px; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; padding: 0 2px; }
|
|
745
|
+
.ask-hint .ask-copy { vertical-align: middle; margin-left: 4px; }
|
|
746
|
+
.ask-stop { color: var(--bad); }
|
|
747
|
+
.ask-stop .icon { width: 12px; height: 12px; }
|
|
748
|
+
.ask-send { flex: none; align-self: flex-end; margin-left: auto; height: 30px; padding: 0 10px 0 12px; gap: 6px; }
|
|
749
|
+
.ask-send .icon { width: 14px; height: 14px; }
|
|
750
|
+
.ask-send:disabled { opacity: var(--disabled); cursor: default; transform: none; }
|
|
751
|
+
|
|
752
|
+
/* ---- the Agent tab: conversation above, composer below ---------------------- */
|
|
753
|
+
/* The same plaque lives above the composer or, when folded, in the tab footer. */
|
|
754
|
+
.agent-status-dock { display: flex; flex-direction: column; min-height: 0; max-height: calc(var(--vh) * 0.4); }
|
|
755
|
+
.agent-status-dock:empty { display: none; }
|
|
756
|
+
.agent-status-dock > .agent-status { margin: 0; min-height: 0; grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) max-content; border: 1px solid var(--hair); border-radius: var(--radius); background: linear-gradient(var(--accent-soft), var(--accent-soft)), var(--solid); box-shadow: var(--shadow); }
|
|
757
|
+
.agent-status-dock .agent-status-text { grid-column: 1 / -1; align-self: stretch; min-height: 0; overflow-y: auto; }
|
|
758
|
+
.agent-status-dock .agent-status > .spinner { grid-row: 3; align-self: center; margin-top: 0; }
|
|
759
|
+
.agent-status { display: grid; grid-template-columns: 12px repeat(3, minmax(0, 1fr)) max-content; grid-template-rows: auto auto max-content; gap: 4px 6px; align-items: start; margin: 0 8px 6px; padding: 7px 12px; border-radius: var(--radius-inner); background: var(--accent-soft); color: var(--accent); font-size: 12px; font-weight: 500; }
|
|
760
|
+
.agent-status[hidden] { display: none; }
|
|
761
|
+
.agent-status > .spinner { grid-column: 1; grid-row: 1; margin-top: 3px; }
|
|
762
|
+
.agent-status-text { grid-column: 2 / 6; grid-row: 1 / 3; min-width: 0; white-space: normal; overflow-wrap: anywhere; }
|
|
763
|
+
.agent-status-time { grid-column: 2 / 5; grid-row: 3; align-self: center; justify-self: end; font: 11px var(--mono); color: var(--muted); white-space: nowrap; }
|
|
764
|
+
.agent-status > .ask-stop { grid-column: 5; grid-row: 3; align-self: end; justify-self: end; }
|
|
765
|
+
.chat-list { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; overflow-anchor: none; display: flex; flex-direction: column; gap: 2px; padding: 8px; }
|
|
766
|
+
.chat-list > * { flex-shrink: 0; }
|
|
767
|
+
/* Auto margin absorbs spare space, but disappears on overflow so the oldest message stays reachable. */
|
|
768
|
+
.chat-list > :first-child { margin-top: auto; }
|
|
769
|
+
.agent-composer { display: grid; gap: 8px; margin: 0 8px 8px; padding: 8px; border-radius: var(--radius-inner); background: var(--field); }
|
|
770
|
+
/* A dragged-narrow sidebar (sidebar.js sets data-sidebar): the same content, less air, so nothing is pushed off the edge. */
|
|
771
|
+
html[data-sidebar="narrow"] .agent-composer, html[data-sidebar="tiny"] .agent-composer { margin: 0 6px 6px; padding: 6px; gap: 6px; }
|
|
772
|
+
html[data-sidebar="tiny"] .agent-composer { margin: 0 4px 4px; padding: 5px; }
|
|
773
|
+
html[data-sidebar="narrow"] .bubble.from-user, html[data-sidebar="tiny"] .bubble.from-user { margin-left: 8px; }
|
|
774
|
+
html[data-sidebar="tiny"] .bubble { padding: 6px 8px 7px; }
|
|
775
|
+
html[data-sidebar="tiny"] .ask-hint { font-size: 11px; }
|
|
776
|
+
html[data-sidebar="tiny"] .chat-list { padding: 0 1px; }
|
|
777
|
+
.agent-composer .ask-input { background: var(--solid); }
|
|
778
|
+
.agent-composer .ask-input:disabled { opacity: var(--disabled-field); cursor: not-allowed; }
|
|
779
|
+
|
|
780
|
+
/* ---- palette -------------------------------------------------------------- */
|
|
781
|
+
.palette-scrim { place-items: start center; padding-top: min(calc(var(--vh) * 0.14), 120px); }
|
|
782
|
+
.palette { display: flex; flex-direction: column; width: min(620px, 100%); max-height: min(560px, calc(var(--vh) - 32px)); padding: 0; overflow: hidden; }
|
|
783
|
+
.palette-field { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--hair); color: var(--muted); }
|
|
784
|
+
.palette-field .icon { width: 17px; height: 17px; }
|
|
785
|
+
.palette-input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); font-size: 15px; }
|
|
786
|
+
.palette-input::placeholder { color: var(--faint); }
|
|
787
|
+
.palette-list { flex: 1; min-height: 0; overflow-y: auto; padding: 6px; }
|
|
788
|
+
.palette-group { padding: 8px 10px 4px; font-size: 11px; font-weight: 600; letter-spacing: .03em; color: var(--muted); }
|
|
789
|
+
.palette-item { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 34px; padding: 4px 10px; border: 0; border-radius: var(--radius-small); background: transparent; color: var(--ink); text-align: left; }
|
|
790
|
+
.palette-item .icon { width: 15px; height: 15px; color: var(--muted); }
|
|
791
|
+
.palette-item.on { background: var(--accent-soft); }
|
|
792
|
+
.palette-item.on .icon, .palette-item.pal-ask .icon { color: var(--accent); }
|
|
793
|
+
.palette-item.pal-ask .palette-label { color: var(--accent-ink); font-weight: 500; }
|
|
794
|
+
.palette-label { flex: 1; min-width: 0; white-space: normal; overflow-wrap: anywhere; }
|
|
795
|
+
.palette-hint { flex: none; font: 11px var(--mono); color: var(--muted); max-width: 40%; white-space: normal; overflow-wrap: anywhere; text-align: right; }
|
|
796
|
+
.palette-tag { font-size: 10.5px; color: var(--muted); flex: none; }
|
|
797
|
+
.palette-foot { display: flex; gap: 14px; padding: 7px 14px; border-top: 1px solid var(--hair); color: var(--muted); font-size: 11px; }
|
|
798
|
+
|
|
799
|
+
/* ---- history: conversation and collapsed steps ---------------------------- */
|
|
800
|
+
.times { margin-left: 6px; padding: 0 5px; border-radius: 5px; background: var(--field-hover); color: var(--muted); font: 600 10.5px/16px var(--mono); }
|
|
801
|
+
.bubble { display: grid; gap: 4px; margin: 4px 0 6px; padding: 8px 10px 9px; border-radius: var(--radius-inner); background: var(--field); }
|
|
802
|
+
.bubble.from-user { margin-left: 18px; background: light-dark(#e4edf8, #182b45); }
|
|
803
|
+
.bubble.from-agent { margin-right: 10px; border: 1px solid var(--hair); background: var(--solid); }
|
|
804
|
+
.bubble.flash { animation: glow 1.2s var(--ease); }
|
|
805
|
+
@keyframes glow { 0% { box-shadow: 0 0 0 3px var(--accent); } 100% { box-shadow: 0 0 0 3px transparent; } }
|
|
806
|
+
.bubble-head { display: flex; flex-wrap: nowrap; align-items: center; gap: 6px; min-width: 0; font-size: 11.5px; }
|
|
807
|
+
.bubble-head .icon { width: 14px; height: 14px; color: var(--muted); }
|
|
808
|
+
.from-agent .bubble-head .icon { color: var(--accent); }
|
|
809
|
+
/* One line: a narrow panel must not turn the context label into a block of wrapped text. The whole label is on hover. */
|
|
810
|
+
.bubble-about { flex: 0 1 auto; min-width: 0; max-width: none; min-height: 20px; padding: 0 6px; border: 0; border-radius: 6px; background: var(--solid); color: var(--muted); font: 10.5px var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; }
|
|
811
|
+
.bubble-about:hover:not(:disabled) { color: var(--accent); }
|
|
812
|
+
.bubble-about:disabled { cursor: default; opacity: var(--disabled-field); }
|
|
813
|
+
.rich { font-size: 12.5px; line-height: 1.5; overflow-wrap: anywhere; }
|
|
814
|
+
.rich.clamped { display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
|
|
815
|
+
.rich code { padding: 0 4px; border-radius: 4px; background: var(--field-hover); font: 11.5px var(--mono); }
|
|
816
|
+
.bubble .more { justify-self: start; height: 22px; font-size: 11.5px; }
|
|
817
|
+
.change.flash { animation: glow 1.2s var(--ease); }
|
|
818
|
+
|
|
819
|
+
/* ---- components ----------------------------------------------------------- */
|
|
820
|
+
.tagname.is-instance { display: inline-flex; align-items: center; gap: 3px; color: var(--component); }
|
|
821
|
+
.tagname.is-instance .icon { width: 10px; height: 10px; }
|
|
822
|
+
.node .component-dot { width: 11px; height: 11px; color: var(--component); }
|
|
823
|
+
.tag.instance { display: inline-flex; align-items: center; gap: 5px; background: var(--component-soft); color: var(--component); }
|
|
824
|
+
.tag.instance .icon { width: 11px; height: 11px; }
|
|
825
|
+
.component-mark { display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 7px; border: 0; border-radius: var(--radius-small); background: var(--component-soft); color: var(--component); font-size: 11px; font-weight: 600; }
|
|
826
|
+
.component-mark .icon { width: 12px; height: 12px; }
|
|
827
|
+
.component-mark:hover { background: color-mix(in srgb, var(--component) 26%, transparent); }
|
|
828
|
+
.instance-head { display: flex; align-items: center; gap: 7px; min-width: 0; padding: 6px 6px 6px 9px; border-radius: var(--radius-inner); background: var(--component-soft); }
|
|
829
|
+
.instance-head .instance-icon { width: 13px; height: 13px; color: var(--component); }
|
|
830
|
+
.instance-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
831
|
+
.instance-from { flex: 1; min-width: 0; color: var(--muted); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
832
|
+
.kv.override .swatch.set { visibility: visible; width: 6px; height: 6px; margin: 5px; border: 0; border-radius: 50%; background: var(--component); }
|
|
833
|
+
.instance-foot { display: flex; align-items: center; gap: 6px; }
|
|
834
|
+
.instance-foot .caption { flex: 1; }
|
|
835
|
+
|
|
836
|
+
/* ---- images --------------------------------------------------------------- */
|
|
837
|
+
.image-box { display: flex; align-items: center; gap: 10px; }
|
|
838
|
+
.thumb { position: relative; display: grid; place-items: center; width: 64px; height: 52px; flex: none; overflow: hidden; border-radius: var(--radius-inner); background: repeating-conic-gradient(var(--field-hover) 0 25%, transparent 0 50%) 0 0 / 12px 12px; border: 1px solid var(--hair); }
|
|
839
|
+
.thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
|
|
840
|
+
.thumb .thumb-icon { color: var(--faint); width: 18px; height: 18px; }
|
|
841
|
+
.thumb img + .thumb-icon { display: none; }
|
|
842
|
+
.thumb.broken img { display: none; }
|
|
843
|
+
.thumb.broken .thumb-icon { display: block; color: var(--bad); }
|
|
844
|
+
.image-side { display: grid; gap: 6px; min-width: 0; }
|
|
845
|
+
.image-src { font: 11px var(--mono); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
846
|
+
.image-buttons { display: flex; gap: 4px; }
|
|
847
|
+
.menu-assets .menu-item { font: 12px var(--mono); }
|
|
848
|
+
.artboard.drop-target::after { inset: -3px; border: 2px dashed var(--accent); box-shadow: 0 0 0 6px var(--accent-soft); }
|
|
849
|
+
|
|
850
|
+
/* ---- fluid layouts -------------------------------------------------------- */
|
|
851
|
+
/* Phones and narrow windows: the sidebar opens almost full screen between the logo row and the tabs. The dock is the base row
|
|
852
|
+
(it is used most, so it keeps the thumb-reachable bottom edge) and the tabs sit above it; the inspector is a sheet above both.
|
|
853
|
+
Only one big surface is shown at a time. */
|
|
854
|
+
html.w720 { --edge: 8px; }
|
|
855
|
+
html.w720 .brand { right: var(--edge); max-width: none; justify-content: space-between; }
|
|
856
|
+
html.w720 .sidebar-foot { right: var(--edge); width: auto; max-width: none; }
|
|
857
|
+
html.w720 .side-tabs .tab { flex: 1 1 0; }
|
|
858
|
+
html.w720 body.has-sidebar .sidebar-foot { bottom: max(var(--edge), env(safe-area-inset-bottom)); }
|
|
859
|
+
html.w720 .panel.left { right: var(--edge); width: auto; }
|
|
860
|
+
html.w720 .dock { bottom: max(var(--edge), env(safe-area-inset-bottom)); right: var(--edge); }
|
|
861
|
+
html.w720 .sidebar-foot { bottom: calc(max(var(--edge), env(safe-area-inset-bottom)) + var(--dock-h, var(--chrome-h)) + 8px); }
|
|
862
|
+
html.w720 .crumbs-bar { bottom: calc(max(var(--edge), env(safe-area-inset-bottom)) + var(--dock-h, var(--chrome-h)) + var(--chrome-h) + 12px + var(--agent-float-h, 0px)); }
|
|
863
|
+
html.w720 .panel.right { left: var(--edge); right: var(--edge); width: auto; bottom: calc(max(var(--edge), env(safe-area-inset-bottom)) + var(--dock-h, var(--chrome-h)) + var(--chrome-h) + 16px + var(--agent-float-h, 0px)); max-height: calc(var(--vh) * 0.5); }
|
|
864
|
+
html.w720 body.agent-busy:not(.has-sidebar) .panel.right { max-height: min(calc(var(--vh) * 0.5), calc(var(--vh) - var(--dock-h, var(--chrome-h)) - var(--chrome-h) - 2 * var(--edge) - var(--brand-h) - 24px - var(--agent-float-h, 0px))); }
|
|
865
|
+
html.w720 body.has-sidebar .panel.right, html.w720 body.has-sidebar .dock { display: none; }
|
|
866
|
+
html.w440 .search-pill-text, html.w440 .search-pill kbd { display: none; } html.w440 .search-pill { padding: 0 9px; }
|
|
867
|
+
/* A full-screen page owns the screen: only the Back pill and the page title stay. */
|
|
868
|
+
body.is-expanded .brand, body.is-expanded .sidebar-foot, body.is-expanded .panel, body.is-expanded .dock, body.is-expanded .crumbs-bar { display: none; }
|
|
869
|
+
/* Phones: the dock keeps tools, zoom, undo and settings; the rest is in Ctrl K and the menus. */ html.w420 .dock .zoom-step { display: none; }
|
|
870
|
+
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; } }
|
|
871
|
+
|
|
872
|
+
/* Fluid rules: a value (key, count, time, tag) is as wide as its text and never wraps or squashes; a label and its control wrap together. */
|
|
873
|
+
.badge, .chip, .times, .dir-tag, .when, .palette-tag, time, .caption.kbd, .dim, .value { flex: none; white-space: nowrap; }
|
|
874
|
+
.hint-unit { display: inline-block; margin-right: 10px; white-space: nowrap; }
|
|
875
|
+
|
|
876
|
+
/* Forced-colors (Windows high contrast): backgrounds are dropped, so fields, pickers and the lit controls get real outlines. */
|
|
877
|
+
@media (forced-colors: active) {
|
|
878
|
+
.vf, .num, .field, .pick, .code-ta, .cls-input, .ask-input, .palette-input, .bm-field, .seg, .segs, .link-button, .settings-actions .tool { border: 1px solid ButtonText; }
|
|
879
|
+
.tool.on, .tab.on, .seg.on, .board.on, .palette-item.on, .menu-item:focus-visible, .menu-item:hover:not(:disabled) { outline: 2px solid Highlight; outline-offset: -2px; }
|
|
880
|
+
.tool:focus-visible, .tab:focus-visible, .pick:focus-visible, button:focus-visible { outline: 2px solid Highlight; outline-offset: 1px; }
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/* Touch: every control is at least 24px in both directions (WCAG 2.5.8) and the common ones are roomier. */
|
|
884
|
+
@media (pointer: coarse) {
|
|
885
|
+
.tool.mini { min-width: 32px; height: 32px; }
|
|
886
|
+
.chip, .bm-link, .link-button, .seg-icon, .agent-chip { min-height: 32px; }
|
|
887
|
+
.seg-icon { min-width: 32px; }
|
|
888
|
+
.seg-icon.solo { width: 32px; height: 32px; }
|
|
889
|
+
.align-cell { min-width: 28px; min-height: 28px; }
|
|
890
|
+
.classes { gap: 6px; padding: 6px; }
|
|
891
|
+
.cls { min-height: 28px; }
|
|
892
|
+
.cls-name { min-height: 28px; }
|
|
893
|
+
.cls-input { height: 28px; }
|
|
894
|
+
.ident-field, .ident { height: 32px; }
|
|
895
|
+
.vf, .num, .pick { min-height: 36px; }
|
|
896
|
+
.boxmodel .bm-sq { --bm-edge: 24px; --bm-field: 24px; padding-top: 28px; padding-bottom: 28px; }
|
|
897
|
+
.boxmodel .bm-cell, .boxmodel .vf.bm-field, .boxmodel .vf.bm-offset, .boxmodel .vf.bm-value { min-height: 24px; height: 24px; }
|
|
898
|
+
.boxmodel .bm-core { font-size: 9px; }
|
|
899
|
+
.boxmodel .bm-expanded-values { padding-top: 104px; }
|
|
900
|
+
.boxmodel .bm-expanded-values > .bm-t { top: 20px; }
|
|
901
|
+
.boxmodel .bm-expanded-values > .bm-l { top: 48px; }
|
|
902
|
+
.boxmodel .bm-expanded-values > .bm-r { top: 76px; }
|
|
903
|
+
@container boxmodel (max-width: 230px) {
|
|
904
|
+
.boxmodel .bm-sq { --bm-edge: 8px; }
|
|
905
|
+
.boxmodel .bm-padding { --bm-edge: 24px; }
|
|
906
|
+
}
|
|
907
|
+
.swatch:not(.plain) { width: 28px; height: 28px; }
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/* Border owns its line, edge widths, colour and radius; Appearance keeps fill and typography. */
|
|
911
|
+
.appearance-box, .border-box { display: grid; gap: 8px; }
|
|
912
|
+
.border-widths { --control-min: max(106px, calc(50% - 3px)); }
|
|
913
|
+
.border-box .color-field { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 4px 6px; padding: 4px 6px; }
|
|
914
|
+
.border-box .color-field > .vf-k { grid-column: 1 / -1; justify-self: start; min-width: 0; padding-left: 0; cursor: default; }
|
|
915
|
+
.appearance-box > .grid2, .typography-controls > .grid2 { align-items: center; }
|
|
916
|
+
.typography-controls { display: grid; gap: 8px; min-width: 0; }
|
|
917
|
+
.font-family-control { display: grid; gap: 4px; min-width: 0; }
|
|
918
|
+
.font-family-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; align-items: center; }
|
|
919
|
+
.font-family-row.with-upload { grid-template-columns: minmax(0, 1fr) auto; }
|
|
920
|
+
.font-upload { position: relative; }
|
|
921
|
+
.font-upload[aria-busy="true"] .icon { visibility: hidden; }
|
|
922
|
+
.font-upload[aria-busy="true"]::after { content: ""; position: absolute; inset: 0; margin: auto; width: 12px; height: 12px; border: 2px solid var(--accent); border-right-color: transparent; border-radius: 50%; animation: spin 1s linear infinite; }
|
|
923
|
+
.font-family-scroll { min-width: 0; max-width: 100%; overflow-x: auto; border-radius: var(--radius-inner); }
|
|
924
|
+
.font-family { width: 100%; min-width: max-content; }
|
|
925
|
+
.border-geometry { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
|
|
926
|
+
.border-geometry > .vf { flex: 0 1 84px; }
|
|
927
|
+
.border-geometry > .radius-presets { flex: 1 1 130px; }
|
|
928
|
+
.radius-presets { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
929
|
+
.radius-presets .chip.on { background: var(--accent-soft); color: var(--accent-ink); }
|
|
930
|
+
.color-field { position: relative; display: flex; align-items: center; gap: 6px; min-width: 0; min-height: 28px; padding: 0 4px 0 0; border-radius: var(--radius-inner); background: var(--field); }
|
|
931
|
+
.color-field:focus-within { outline-offset: 1px; outline: var(--focus-ring) solid var(--accent); }
|
|
932
|
+
.color-field .vf-k { min-width: 30px; }
|
|
933
|
+
.color-field .swatch { flex: none; width: 20px; height: 20px; border-radius: var(--radius-small); }
|
|
934
|
+
.color-field .color-hex { min-width: 0; flex: 1; }
|
|
935
|
+
.color-block { display: grid; gap: 4px; }
|
|
936
|
+
.token-swatches { display: flex; flex-wrap: wrap; gap: 4px; padding-left: 36px; }
|
|
937
|
+
.token-swatch { width: 18px; height: 18px; padding: 0; border: 1px solid var(--hair); border-radius: 50%; cursor: pointer; }
|
|
938
|
+
.token-swatch:hover, .token-swatch:focus-visible { outline: var(--focus-ring) solid var(--accent); outline-offset: 1px; }
|
|
939
|
+
/* A control that lives inside a field wrapper is ringed by the wrapper, never twice. */
|
|
940
|
+
:is(.vf, .num, .code, .classes, .ident-field, .search, .color-field, .bm-field, .settings-output) :is(input, textarea):focus-visible { outline: none; }
|
|
941
|
+
.centre-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
|
|
942
|
+
|
|
943
|
+
@media (pointer: coarse) {
|
|
944
|
+
.radius-presets .chip { min-width: 32px; }
|
|
945
|
+
.color-field { min-height: 36px; }
|
|
946
|
+
.color-field .swatch { width: 28px; height: 28px; }
|
|
947
|
+
.token-swatch { width: 26px; height: 26px; }
|
|
948
|
+
}
|