@noobsociety/nsds 0.3.0 → 0.4.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/CHANGELOG.md +46 -1
- package/CONTRIBUTING.md +43 -2
- package/README.md +87 -36
- package/SECURITY.md +38 -4
- package/dist/client/index.cjs +1 -0
- package/dist/client/index.d.cts +6 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +5 -0
- package/dist/components/_card-base.css +99 -0
- package/dist/components/hud/HUDBar.d.ts +16 -3
- package/dist/components/hud/HUDChat.d.ts +26 -0
- package/dist/components/hud/HUDJoystick.d.ts +21 -0
- package/dist/components/hud/HUDMinimap.d.ts +14 -0
- package/dist/components/hud/HUDPanel.d.ts +25 -0
- package/dist/components/hud/HUDTabWindow.d.ts +37 -0
- package/dist/components/hud-editor.css +197 -0
- package/dist/components/icons/RPGIcon.d.ts +15 -11
- package/dist/components/icons/registry.d.ts +37 -0
- package/dist/components/primitives.css +50 -20
- package/dist/components/react/index.d.ts +12 -2
- package/dist/components/scene-builder.css +740 -0
- package/dist/components/scene-builder.js +3039 -0
- package/dist/components/shared/constants.d.ts +41 -0
- package/dist/components/shared/styles.d.ts +1 -42
- package/dist/index.cjs +1 -1
- package/dist/index.js +6173 -1821
- package/dist/registry-BizUEm6W.js +136 -0
- package/dist/registry-Cyq-qspU.cjs +1 -0
- package/dist/styles.css +1 -0
- package/dist/tailwind/preset.cjs +108 -0
- package/dist/tailwind/preset.d.cts +3 -3
- package/dist/tokens/base.css +17 -4
- package/dist/tokens/colors.css +57 -53
- package/dist/tokens/hud.css +119 -78
- package/dist/tokens/motion.css +57 -23
- package/dist/tokens/spacing.css +39 -39
- package/dist/tokens/typography.css +20 -20
- package/package.json +41 -12
- package/dist/tailwind/package.json +0 -1
- package/dist/tailwind/preset.d.ts +0 -4
- package/dist/tailwind/preset.js +0 -144
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
/* NoobSociety — Scene Builder canvas chrome.
|
|
2
|
+
The in-canvas editing affordances for the HUD composer: world-grid
|
|
3
|
+
checkerboard, draggable HUD elements, 8-way resize handles, delete buttons,
|
|
4
|
+
alignment bar, colour swatches, ghost, drag overlay and tooltips — plus the
|
|
5
|
+
side-panel toolbar/IO buttons that the .ns-hud-* rail (components/hud-editor.css)
|
|
6
|
+
does not cover.
|
|
7
|
+
|
|
8
|
+
Token-driven (see --hud-edit-* in tokens/hud.css). Linked directly by the
|
|
9
|
+
Scene Builder card; NOT auto-imported through styles.css, because the Game
|
|
10
|
+
View template intentionally ships its own diverged copy of this chrome.
|
|
11
|
+
|
|
12
|
+
Geometry (--hud-col / --hud-row / canvas size) is supplied by the host page,
|
|
13
|
+
so this sheet adapts to whatever canvas it is dropped into. */
|
|
14
|
+
|
|
15
|
+
.grid-hidden .ig {
|
|
16
|
+
border-color: transparent !important;
|
|
17
|
+
}
|
|
18
|
+
.grid-hidden .cell-l {
|
|
19
|
+
display: none !important;
|
|
20
|
+
}
|
|
21
|
+
.grid-hidden .cell-d {
|
|
22
|
+
display: none !important;
|
|
23
|
+
}
|
|
24
|
+
/* The grid toggle only controls the grid LINES — editing chrome (resize handles,
|
|
25
|
+
delete buttons, alignment bar, selection outline, color swatches) stays available
|
|
26
|
+
whether the grid is shown or hidden. */
|
|
27
|
+
.world-bg {
|
|
28
|
+
position: absolute;
|
|
29
|
+
inset: 0;
|
|
30
|
+
display: grid;
|
|
31
|
+
grid-template-columns: repeat(
|
|
32
|
+
var(--ns-world-zones),
|
|
33
|
+
calc(var(--ns-world-w) / var(--ns-world-zones))
|
|
34
|
+
);
|
|
35
|
+
grid-template-rows: repeat(
|
|
36
|
+
var(--ns-world-zones),
|
|
37
|
+
calc(var(--ns-world-h) / var(--ns-world-zones))
|
|
38
|
+
);
|
|
39
|
+
width: var(--ns-world-w);
|
|
40
|
+
height: var(--ns-world-h);
|
|
41
|
+
}
|
|
42
|
+
.cell-l {
|
|
43
|
+
background: rgb(var(--ns-green-rgb) / 0.1);
|
|
44
|
+
}
|
|
45
|
+
.cell-d {
|
|
46
|
+
background: rgb(var(--ns-bg-2-rgb) / 0.75);
|
|
47
|
+
}
|
|
48
|
+
.inner {
|
|
49
|
+
width: 100%;
|
|
50
|
+
height: 100%;
|
|
51
|
+
display: grid;
|
|
52
|
+
grid-template-columns: repeat(8, 1fr);
|
|
53
|
+
grid-template-rows: repeat(8, 1fr);
|
|
54
|
+
}
|
|
55
|
+
.ig {
|
|
56
|
+
border-right: 1px dotted rgb(var(--ns-gold-rgb) / 0.55);
|
|
57
|
+
border-bottom: 1px dotted rgb(var(--ns-gold-rgb) / 0.55);
|
|
58
|
+
}
|
|
59
|
+
.ig:nth-child(8n + 1) {
|
|
60
|
+
border-left: 1px dotted rgb(var(--ns-gold-rgb) / 0.55);
|
|
61
|
+
}
|
|
62
|
+
.ig:nth-child(-n + 8) {
|
|
63
|
+
border-top: 1px dotted rgb(var(--ns-gold-rgb) / 0.55);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* ── HUD layer ──────────────────────────────────── */
|
|
67
|
+
.hud {
|
|
68
|
+
position: absolute;
|
|
69
|
+
inset: 0;
|
|
70
|
+
display: grid;
|
|
71
|
+
grid-template-columns: repeat(var(--hud-grid-cols), 1fr);
|
|
72
|
+
grid-template-rows: repeat(var(--hud-grid-rows), 1fr);
|
|
73
|
+
font-family: var(--hud-font);
|
|
74
|
+
color: var(--hud-text);
|
|
75
|
+
pointer-events: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* ── Card grid ──────────────────────────────────── */
|
|
79
|
+
.hud-card {
|
|
80
|
+
position: absolute;
|
|
81
|
+
top: 0;
|
|
82
|
+
left: 0;
|
|
83
|
+
width: var(--ns-world-w);
|
|
84
|
+
height: var(--ns-world-h);
|
|
85
|
+
display: grid;
|
|
86
|
+
grid-template-columns: repeat(var(--hud-grid-cols), 1fr);
|
|
87
|
+
grid-template-rows: repeat(var(--hud-grid-rows), 1fr);
|
|
88
|
+
gap: 0;
|
|
89
|
+
pointer-events: auto;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* ── Base element ───────────────────────────────── */
|
|
93
|
+
.hud-card > [data-grid] {
|
|
94
|
+
cursor: grab;
|
|
95
|
+
user-select: none;
|
|
96
|
+
position: relative;
|
|
97
|
+
padding: 0;
|
|
98
|
+
margin: 0;
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
z-index: 1;
|
|
104
|
+
}
|
|
105
|
+
.hud-card > [data-backdrop] {
|
|
106
|
+
z-index: 0;
|
|
107
|
+
}
|
|
108
|
+
.hud-card > [data-grid].dragging {
|
|
109
|
+
cursor: grabbing;
|
|
110
|
+
opacity: 0.35;
|
|
111
|
+
}
|
|
112
|
+
.hud-card > [data-grid].selected {
|
|
113
|
+
outline: 1px solid rgb(var(--ns-gold-rgb) / 0.7);
|
|
114
|
+
outline-offset: -1px;
|
|
115
|
+
z-index: 30;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* ── Resize handles (8-direction) ──────────────── */
|
|
119
|
+
.rz {
|
|
120
|
+
position: absolute;
|
|
121
|
+
width: var(--hud-edit-handle);
|
|
122
|
+
height: var(--hud-edit-handle);
|
|
123
|
+
background: var(--hud-edit-handle-fill);
|
|
124
|
+
box-shadow: var(--hud-edit-handle-ring);
|
|
125
|
+
z-index: 20;
|
|
126
|
+
pointer-events: auto;
|
|
127
|
+
display: none;
|
|
128
|
+
}
|
|
129
|
+
.selected .rz {
|
|
130
|
+
display: block;
|
|
131
|
+
}
|
|
132
|
+
/* Handles sit 1px inside the element so edge-of-grid objects never clip them */
|
|
133
|
+
.rz[data-rz='nw'] {
|
|
134
|
+
top: 1px;
|
|
135
|
+
left: 1px;
|
|
136
|
+
cursor: nw-resize;
|
|
137
|
+
}
|
|
138
|
+
.rz[data-rz='n'] {
|
|
139
|
+
top: 1px;
|
|
140
|
+
left: calc(50% - 2.5px);
|
|
141
|
+
cursor: n-resize;
|
|
142
|
+
}
|
|
143
|
+
.rz[data-rz='ne'] {
|
|
144
|
+
top: 1px;
|
|
145
|
+
right: 1px;
|
|
146
|
+
cursor: ne-resize;
|
|
147
|
+
}
|
|
148
|
+
.rz[data-rz='e'] {
|
|
149
|
+
top: calc(50% - 2.5px);
|
|
150
|
+
right: 1px;
|
|
151
|
+
cursor: e-resize;
|
|
152
|
+
}
|
|
153
|
+
.rz[data-rz='se'] {
|
|
154
|
+
bottom: 1px;
|
|
155
|
+
right: 1px;
|
|
156
|
+
cursor: se-resize;
|
|
157
|
+
clip-path: none;
|
|
158
|
+
}
|
|
159
|
+
.rz[data-rz='s'] {
|
|
160
|
+
bottom: 1px;
|
|
161
|
+
left: calc(50% - 2.5px);
|
|
162
|
+
cursor: s-resize;
|
|
163
|
+
}
|
|
164
|
+
.rz[data-rz='sw'] {
|
|
165
|
+
bottom: 1px;
|
|
166
|
+
left: 1px;
|
|
167
|
+
cursor: sw-resize;
|
|
168
|
+
}
|
|
169
|
+
.rz[data-rz='w'] {
|
|
170
|
+
top: calc(50% - 2.5px);
|
|
171
|
+
left: 1px;
|
|
172
|
+
cursor: w-resize;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* ── Delete button ──────────────────────────────── */
|
|
176
|
+
.del-btn {
|
|
177
|
+
position: absolute;
|
|
178
|
+
top: 1px;
|
|
179
|
+
right: 1px;
|
|
180
|
+
width: var(--hud-edit-del);
|
|
181
|
+
height: var(--hud-edit-del);
|
|
182
|
+
background: rgb(var(--ns-pink-rgb) / 0.85);
|
|
183
|
+
color: var(--ns-ink);
|
|
184
|
+
font-family: var(--hud-font);
|
|
185
|
+
font-size: var(--hud-text-sm);
|
|
186
|
+
display: none;
|
|
187
|
+
align-items: center;
|
|
188
|
+
justify-content: center;
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
z-index: 30;
|
|
191
|
+
line-height: 1;
|
|
192
|
+
pointer-events: auto;
|
|
193
|
+
}
|
|
194
|
+
/* The per-element × is replaced by the floating delete button (#del-floater),
|
|
195
|
+
which sits on the cell NEXT TO the selection so it never covers the object
|
|
196
|
+
or its resize handles. The node is kept (hidden) so the Tab Window close
|
|
197
|
+
button can still trigger it programmatically. */
|
|
198
|
+
.selected .del-btn {
|
|
199
|
+
display: none;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* ── Floating delete button (sits beside the selection) ── */
|
|
203
|
+
#del-floater {
|
|
204
|
+
position: absolute;
|
|
205
|
+
width: var(--hud-edit-del);
|
|
206
|
+
height: var(--hud-edit-del);
|
|
207
|
+
background: rgb(var(--ns-pink-rgb) / 0.9);
|
|
208
|
+
color: var(--ns-ink);
|
|
209
|
+
font-family: var(--hud-font);
|
|
210
|
+
font-size: var(--hud-text-md);
|
|
211
|
+
line-height: 1;
|
|
212
|
+
display: none;
|
|
213
|
+
align-items: center;
|
|
214
|
+
justify-content: center;
|
|
215
|
+
cursor: pointer;
|
|
216
|
+
z-index: 80;
|
|
217
|
+
pointer-events: auto;
|
|
218
|
+
border-radius: var(--ns-radius-sm, 2px);
|
|
219
|
+
box-shadow: 0 0 0 1px var(--hud-edit-ring);
|
|
220
|
+
}
|
|
221
|
+
#del-floater:hover {
|
|
222
|
+
background: rgb(var(--ns-pink-rgb) / 1);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* ── Backdrop panels fill cell edge-to-edge ──── */
|
|
226
|
+
.hud-card > [data-backdrop] {
|
|
227
|
+
width: 100% !important;
|
|
228
|
+
height: 100% !important;
|
|
229
|
+
align-self: stretch !important;
|
|
230
|
+
justify-self: stretch !important;
|
|
231
|
+
align-items: stretch !important;
|
|
232
|
+
justify-content: stretch !important;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* ── Tab window container override ─────────────── */
|
|
236
|
+
.hud-card > [data-comp-el='tabwin'] {
|
|
237
|
+
display: flex !important;
|
|
238
|
+
flex-direction: column !important;
|
|
239
|
+
align-items: stretch !important;
|
|
240
|
+
justify-content: flex-start !important;
|
|
241
|
+
overflow: hidden !important;
|
|
242
|
+
width: 100% !important;
|
|
243
|
+
height: 100% !important;
|
|
244
|
+
align-self: stretch !important;
|
|
245
|
+
}
|
|
246
|
+
/* Tab bar fills width, buttons fill height */
|
|
247
|
+
.hud-card > [data-comp-el='tabwin'] > [data-tab-bar] {
|
|
248
|
+
display: flex !important;
|
|
249
|
+
flex-shrink: 0 !important;
|
|
250
|
+
width: 100% !important;
|
|
251
|
+
}
|
|
252
|
+
.hud-card > [data-comp-el='tabwin'] > [data-tab-bar] > button {
|
|
253
|
+
height: 100% !important;
|
|
254
|
+
flex-shrink: 0;
|
|
255
|
+
}
|
|
256
|
+
/* Pane fills remaining space */
|
|
257
|
+
.hud-card > [data-comp-el='tabwin'] > div:not([data-tab-bar]) {
|
|
258
|
+
flex: 1 !important;
|
|
259
|
+
overflow: hidden !important;
|
|
260
|
+
}
|
|
261
|
+
#ghost {
|
|
262
|
+
background: rgb(var(--ns-gold-rgb) / 0.1);
|
|
263
|
+
border: 1px dashed rgb(var(--ns-gold-rgb) / 0.65);
|
|
264
|
+
pointer-events: none;
|
|
265
|
+
z-index: 80;
|
|
266
|
+
display: none;
|
|
267
|
+
}
|
|
268
|
+
#ghost.active {
|
|
269
|
+
display: block;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* ── Dragging mode grid overlay ─────────────────── */
|
|
273
|
+
.hud-card.drag-mode::after {
|
|
274
|
+
content: '';
|
|
275
|
+
position: absolute;
|
|
276
|
+
inset: 0;
|
|
277
|
+
background-image:
|
|
278
|
+
repeating-linear-gradient(to right, var(--hud-grid-overlay) 0 1px, transparent 1px 100%),
|
|
279
|
+
repeating-linear-gradient(to bottom, var(--hud-grid-overlay) 0 1px, transparent 1px 100%);
|
|
280
|
+
background-size: var(--hud-col) var(--hud-row);
|
|
281
|
+
pointer-events: none;
|
|
282
|
+
z-index: 70;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* ── Text elements ──────────────────────────────── */
|
|
286
|
+
.hud-card > [data-grid].ns-text,
|
|
287
|
+
.hud-card > [data-grid][data-custom] {
|
|
288
|
+
font-size: var(--hud-text-sm);
|
|
289
|
+
white-space: nowrap;
|
|
290
|
+
overflow: hidden;
|
|
291
|
+
justify-content: flex-start;
|
|
292
|
+
padding-left: 3px;
|
|
293
|
+
z-index: 3;
|
|
294
|
+
}
|
|
295
|
+
.et {
|
|
296
|
+
/* editable-text span */
|
|
297
|
+
outline: none;
|
|
298
|
+
pointer-events: none;
|
|
299
|
+
min-width: 1px;
|
|
300
|
+
}
|
|
301
|
+
.et[contenteditable='true'] {
|
|
302
|
+
pointer-events: auto;
|
|
303
|
+
cursor: text;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* ── Color swatch panel ────────────────────────────── */
|
|
307
|
+
#color-swatches {
|
|
308
|
+
position: absolute;
|
|
309
|
+
z-index: 4000;
|
|
310
|
+
display: none;
|
|
311
|
+
flex-wrap: wrap;
|
|
312
|
+
gap: 2px;
|
|
313
|
+
background: var(--hud-bg-strong);
|
|
314
|
+
border: 1px solid var(--ns-line-strong);
|
|
315
|
+
padding: 4px;
|
|
316
|
+
width: 56px;
|
|
317
|
+
}
|
|
318
|
+
#color-swatches.show {
|
|
319
|
+
display: flex;
|
|
320
|
+
}
|
|
321
|
+
.cs-dot {
|
|
322
|
+
width: 10px;
|
|
323
|
+
height: 10px;
|
|
324
|
+
border-radius: 50%;
|
|
325
|
+
cursor: pointer;
|
|
326
|
+
flex-shrink: 0;
|
|
327
|
+
border: 1px solid var(--ns-line);
|
|
328
|
+
}
|
|
329
|
+
.cs-dot:hover {
|
|
330
|
+
transform: scale(1.25);
|
|
331
|
+
}
|
|
332
|
+
.cs-dot.on {
|
|
333
|
+
outline: 1.5px solid var(--ns-ink);
|
|
334
|
+
outline-offset: 1px;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* ── Align toolbar ──────────────────────────────── */
|
|
338
|
+
#align-bar {
|
|
339
|
+
position: absolute;
|
|
340
|
+
display: none;
|
|
341
|
+
grid-template-columns: repeat(5, var(--hud-col));
|
|
342
|
+
grid-auto-rows: var(--hud-row);
|
|
343
|
+
gap: 0;
|
|
344
|
+
place-items: stretch;
|
|
345
|
+
z-index: 200;
|
|
346
|
+
pointer-events: auto;
|
|
347
|
+
padding: 0;
|
|
348
|
+
background: var(--hud-bg-strong);
|
|
349
|
+
border: none;
|
|
350
|
+
overflow: visible;
|
|
351
|
+
}
|
|
352
|
+
#align-bar.show {
|
|
353
|
+
display: grid;
|
|
354
|
+
}
|
|
355
|
+
.ab.is-disabled {
|
|
356
|
+
opacity: 0.25;
|
|
357
|
+
pointer-events: none;
|
|
358
|
+
}
|
|
359
|
+
#align-bar .ab {
|
|
360
|
+
height: 100%;
|
|
361
|
+
padding: 0;
|
|
362
|
+
font-size: var(--hud-text-sm);
|
|
363
|
+
border-radius: 0;
|
|
364
|
+
}
|
|
365
|
+
.ab {
|
|
366
|
+
height: 10px;
|
|
367
|
+
padding: 0 3px;
|
|
368
|
+
background: var(--hud-edit-hover);
|
|
369
|
+
border: 1px solid var(--ns-line);
|
|
370
|
+
color: rgb(var(--ns-ink-rgb) / 0.55);
|
|
371
|
+
font-family: var(--hud-font);
|
|
372
|
+
font-size: 3px;
|
|
373
|
+
display: flex;
|
|
374
|
+
align-items: center;
|
|
375
|
+
justify-content: center;
|
|
376
|
+
cursor: pointer;
|
|
377
|
+
user-select: none;
|
|
378
|
+
flex-shrink: 0;
|
|
379
|
+
border-radius: 1px;
|
|
380
|
+
white-space: nowrap;
|
|
381
|
+
}
|
|
382
|
+
.ab:hover {
|
|
383
|
+
background: var(--hud-edit-overlay);
|
|
384
|
+
border-color: rgb(var(--ns-gold-rgb) / 0.8);
|
|
385
|
+
color: var(--ns-ink);
|
|
386
|
+
}
|
|
387
|
+
.ab.on {
|
|
388
|
+
background: rgb(var(--ns-gold-rgb) / 0.22);
|
|
389
|
+
border-color: var(--hud-gold);
|
|
390
|
+
color: var(--hud-gold);
|
|
391
|
+
}
|
|
392
|
+
.ab-sep {
|
|
393
|
+
width: 1px;
|
|
394
|
+
height: 8px;
|
|
395
|
+
background: var(--ns-line-strong);
|
|
396
|
+
flex-shrink: 0;
|
|
397
|
+
}
|
|
398
|
+
#align-bar .color-btn {
|
|
399
|
+
width: 12px;
|
|
400
|
+
height: 12px;
|
|
401
|
+
border-radius: 50%;
|
|
402
|
+
flex-shrink: 0;
|
|
403
|
+
place-self: center;
|
|
404
|
+
background: var(--ns-ink-dim);
|
|
405
|
+
border: 1px solid var(--ns-line);
|
|
406
|
+
padding: 0;
|
|
407
|
+
display: flex;
|
|
408
|
+
align-items: center;
|
|
409
|
+
justify-content: center;
|
|
410
|
+
font-size: 4px;
|
|
411
|
+
font-weight: bold;
|
|
412
|
+
line-height: 1;
|
|
413
|
+
color: #fff;
|
|
414
|
+
text-shadow:
|
|
415
|
+
0 0 1px rgba(0, 0, 0, 0.95),
|
|
416
|
+
0 1px 1px rgba(0, 0, 0, 0.95);
|
|
417
|
+
}
|
|
418
|
+
#align-bar .color-btn:hover {
|
|
419
|
+
transform: scale(1.15);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/* Baked HUD element SVGs — fixed icon size to prevent 300x150 default */
|
|
423
|
+
.hud-card > [data-grid] > svg {
|
|
424
|
+
width: 22px;
|
|
425
|
+
height: 22px;
|
|
426
|
+
flex-shrink: 0;
|
|
427
|
+
image-rendering: pixelated;
|
|
428
|
+
pointer-events: none;
|
|
429
|
+
overflow: visible;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/* ── Text readability: white + dark stroke on all HUD text ── */
|
|
433
|
+
.hud .et {
|
|
434
|
+
color: var(--ns-ink);
|
|
435
|
+
text-shadow: var(--hud-edit-stroke);
|
|
436
|
+
}
|
|
437
|
+
.hud .bar-text {
|
|
438
|
+
text-shadow: var(--hud-edit-stroke-bar);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* ── Icon palette: styling provided by .ns-hud-* classes in the design system ── */
|
|
442
|
+
|
|
443
|
+
/* ── HUD tooltip ─────────────────────── */
|
|
444
|
+
#hud-tooltip {
|
|
445
|
+
position: fixed;
|
|
446
|
+
display: none;
|
|
447
|
+
font-family: var(--hud-font);
|
|
448
|
+
font-size: var(--hud-text-sm);
|
|
449
|
+
color: var(--ns-ink);
|
|
450
|
+
background: var(--hud-bg-strong);
|
|
451
|
+
border: 1px solid var(--ns-line-strong);
|
|
452
|
+
padding: 3px 6px;
|
|
453
|
+
pointer-events: none;
|
|
454
|
+
z-index: 9999;
|
|
455
|
+
white-space: nowrap;
|
|
456
|
+
letter-spacing: 0.5px;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* ── UI chrome tooltip (buttons / toggles) ─────────────── */
|
|
460
|
+
#ui-tooltip {
|
|
461
|
+
position: fixed;
|
|
462
|
+
left: 0;
|
|
463
|
+
top: 0;
|
|
464
|
+
display: none;
|
|
465
|
+
font-family: var(--hud-font);
|
|
466
|
+
font-size: var(--hud-text-sm);
|
|
467
|
+
line-height: 1.4;
|
|
468
|
+
letter-spacing: 0.5px;
|
|
469
|
+
color: var(--ns-ink);
|
|
470
|
+
background: var(--hud-bg-strong, #14161b);
|
|
471
|
+
border: 1px solid var(--ns-line-strong);
|
|
472
|
+
border-radius: 3px;
|
|
473
|
+
padding: 4px 7px;
|
|
474
|
+
max-width: none;
|
|
475
|
+
white-space: nowrap;
|
|
476
|
+
pointer-events: none;
|
|
477
|
+
z-index: 10000;
|
|
478
|
+
box-shadow: 0 3px 10px var(--hud-edit-ring);
|
|
479
|
+
opacity: 0;
|
|
480
|
+
transform: translateY(2px);
|
|
481
|
+
transition:
|
|
482
|
+
opacity 0.12s ease,
|
|
483
|
+
transform 0.12s ease;
|
|
484
|
+
}
|
|
485
|
+
#ui-tooltip.show {
|
|
486
|
+
opacity: 1;
|
|
487
|
+
transform: translateY(0);
|
|
488
|
+
}
|
|
489
|
+
#ui-tooltip::after {
|
|
490
|
+
content: '';
|
|
491
|
+
position: absolute;
|
|
492
|
+
left: var(--arrow-x, 50%);
|
|
493
|
+
transform: translateX(-50%);
|
|
494
|
+
border: 4px solid transparent;
|
|
495
|
+
}
|
|
496
|
+
#ui-tooltip:not(.below)::after {
|
|
497
|
+
top: 100%;
|
|
498
|
+
border-top-color: var(--ns-line-strong);
|
|
499
|
+
} /* tooltip above element → caret points down */
|
|
500
|
+
#ui-tooltip.below::after {
|
|
501
|
+
bottom: 100%;
|
|
502
|
+
border-bottom-color: var(--ns-line-strong);
|
|
503
|
+
} /* tooltip below element → caret points up */
|
|
504
|
+
|
|
505
|
+
/* GRID / BG / HUD toggles — one type level smaller, equal width & height */
|
|
506
|
+
#side-panel .ns-hud-toolbar {
|
|
507
|
+
display: flex;
|
|
508
|
+
gap: var(--ns-space-1);
|
|
509
|
+
}
|
|
510
|
+
#side-panel .ns-hud-toolbar .ns-hud-tool {
|
|
511
|
+
font-size: var(--hud-text-sm);
|
|
512
|
+
flex: 1 1 0;
|
|
513
|
+
min-width: 0;
|
|
514
|
+
height: var(--hud-edit-toggle-h);
|
|
515
|
+
min-height: var(--hud-edit-toggle-h);
|
|
516
|
+
padding: 0;
|
|
517
|
+
display: inline-flex;
|
|
518
|
+
align-items: center;
|
|
519
|
+
justify-content: center;
|
|
520
|
+
}
|
|
521
|
+
#bg-toggle:disabled {
|
|
522
|
+
opacity: 0.35;
|
|
523
|
+
cursor: default;
|
|
524
|
+
pointer-events: none;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/* Background action button (header) — upload when empty, obvious delete when set */
|
|
528
|
+
#bg-action {
|
|
529
|
+
position: relative;
|
|
530
|
+
flex-shrink: 0;
|
|
531
|
+
display: inline-flex;
|
|
532
|
+
align-items: center;
|
|
533
|
+
justify-content: center;
|
|
534
|
+
width: var(--hud-edit-btn);
|
|
535
|
+
height: var(--hud-edit-btn);
|
|
536
|
+
padding: 0;
|
|
537
|
+
color: var(--ns-ink-faint);
|
|
538
|
+
background: transparent;
|
|
539
|
+
border: 1px solid var(--ns-line-strong);
|
|
540
|
+
border-radius: var(--ns-radius-sm, 2px);
|
|
541
|
+
cursor: pointer;
|
|
542
|
+
transition:
|
|
543
|
+
color 0.12s,
|
|
544
|
+
border-color 0.12s,
|
|
545
|
+
background 0.12s;
|
|
546
|
+
}
|
|
547
|
+
#bg-action:hover {
|
|
548
|
+
color: var(--ns-ink);
|
|
549
|
+
border-color: var(--ns-ink-faint);
|
|
550
|
+
background: var(--hud-edit-hover);
|
|
551
|
+
}
|
|
552
|
+
#bg-action.is-delete {
|
|
553
|
+
color: var(--ns-pink, #e0607e);
|
|
554
|
+
border-color: rgb(var(--ns-pink-rgb, 224 96 126) / 0.6);
|
|
555
|
+
}
|
|
556
|
+
#bg-action.is-delete:hover {
|
|
557
|
+
color: var(--ns-pink, #e0607e);
|
|
558
|
+
border-color: var(--ns-pink, #e0607e);
|
|
559
|
+
background: rgb(var(--ns-pink-rgb, 224 96 126) / 0.16);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/* Panel header label is informational, not interactive — keep it neutral
|
|
563
|
+
(gold is reserved for buttons/active states) and give it a real line-height
|
|
564
|
+
so it stays legible if it ever wraps to two lines. */
|
|
565
|
+
.ns-hud-panel__head .ns-hud-eyebrow {
|
|
566
|
+
color: var(--ns-ink);
|
|
567
|
+
line-height: 1.35;
|
|
568
|
+
}
|
|
569
|
+
.ns-hud-eyebrow,
|
|
570
|
+
.ns-hud-hint,
|
|
571
|
+
#palette-tabs .ns-hud-tab .tab-label {
|
|
572
|
+
line-height: 1.35;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/* Export / Import buttons */
|
|
576
|
+
#export-snapshot,
|
|
577
|
+
#import-snapshot,
|
|
578
|
+
#undo-btn,
|
|
579
|
+
#redo-btn {
|
|
580
|
+
position: relative;
|
|
581
|
+
flex-shrink: 0;
|
|
582
|
+
display: inline-flex;
|
|
583
|
+
align-items: center;
|
|
584
|
+
justify-content: center;
|
|
585
|
+
width: var(--hud-edit-btn);
|
|
586
|
+
height: var(--hud-edit-btn);
|
|
587
|
+
padding: 0;
|
|
588
|
+
background: transparent;
|
|
589
|
+
color: var(--ns-ink-faint);
|
|
590
|
+
border: 1px solid var(--ns-line-strong);
|
|
591
|
+
border-radius: var(--ns-radius-sm, 2px);
|
|
592
|
+
cursor: pointer;
|
|
593
|
+
transition:
|
|
594
|
+
color 0.12s,
|
|
595
|
+
border-color 0.12s,
|
|
596
|
+
background 0.12s,
|
|
597
|
+
opacity 0.12s;
|
|
598
|
+
}
|
|
599
|
+
#import-snapshot:hover {
|
|
600
|
+
color: var(--ns-ink);
|
|
601
|
+
border-color: var(--ns-ink-faint);
|
|
602
|
+
background: var(--hud-edit-hover);
|
|
603
|
+
}
|
|
604
|
+
#undo-btn:hover:not(:disabled),
|
|
605
|
+
#redo-btn:hover:not(:disabled) {
|
|
606
|
+
color: var(--ns-ink);
|
|
607
|
+
border-color: var(--ns-ink-faint);
|
|
608
|
+
background: var(--hud-edit-hover);
|
|
609
|
+
}
|
|
610
|
+
#undo-btn:disabled,
|
|
611
|
+
#redo-btn:disabled {
|
|
612
|
+
opacity: 0.3;
|
|
613
|
+
cursor: default;
|
|
614
|
+
pointer-events: none;
|
|
615
|
+
}
|
|
616
|
+
/* Export — clean / nothing new to export → muted & inert */
|
|
617
|
+
#export-snapshot:disabled {
|
|
618
|
+
opacity: 0.4;
|
|
619
|
+
cursor: default;
|
|
620
|
+
}
|
|
621
|
+
/* Export — unsaved changes → gold + pulsing dot badge */
|
|
622
|
+
#export-snapshot.is-dirty {
|
|
623
|
+
color: var(--hud-gold);
|
|
624
|
+
border-color: var(--hud-gold);
|
|
625
|
+
background: rgb(var(--ns-gold-rgb) / 0.12);
|
|
626
|
+
}
|
|
627
|
+
#export-snapshot.is-dirty:hover {
|
|
628
|
+
background: rgb(var(--ns-gold-rgb) / 0.22);
|
|
629
|
+
}
|
|
630
|
+
#export-snapshot.is-dirty::after {
|
|
631
|
+
content: '';
|
|
632
|
+
position: absolute;
|
|
633
|
+
top: -3px;
|
|
634
|
+
right: -3px;
|
|
635
|
+
width: 6px;
|
|
636
|
+
height: 6px;
|
|
637
|
+
border-radius: 50%;
|
|
638
|
+
background: var(--hud-gold);
|
|
639
|
+
box-shadow: 0 0 0 1.5px var(--ns-bg-1, #1b1d22);
|
|
640
|
+
animation: save-pulse 1.4s ease-in-out infinite;
|
|
641
|
+
}
|
|
642
|
+
@keyframes save-pulse {
|
|
643
|
+
0%,
|
|
644
|
+
100% {
|
|
645
|
+
opacity: 1;
|
|
646
|
+
}
|
|
647
|
+
50% {
|
|
648
|
+
opacity: 0.35;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
/* Just exported / imported — green confirm, no dot */
|
|
652
|
+
#export-snapshot.just-saved,
|
|
653
|
+
#import-snapshot.just-saved {
|
|
654
|
+
color: var(--ns-green, #5dcaa5);
|
|
655
|
+
border-color: var(--ns-green, #5dcaa5);
|
|
656
|
+
background: rgb(var(--ns-green-rgb, 93 202 165) / 0.16);
|
|
657
|
+
opacity: 1;
|
|
658
|
+
}
|
|
659
|
+
#export-snapshot.just-saved::after {
|
|
660
|
+
display: none;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/* Category tabs — two columns, each label centered both axes */
|
|
664
|
+
#palette-tabs {
|
|
665
|
+
display: grid;
|
|
666
|
+
grid-template-columns: 1fr 1fr;
|
|
667
|
+
gap: var(--ns-space-1);
|
|
668
|
+
}
|
|
669
|
+
#palette-tabs .ns-hud-tab {
|
|
670
|
+
display: flex;
|
|
671
|
+
align-items: center;
|
|
672
|
+
justify-content: flex-start;
|
|
673
|
+
gap: var(--ns-space-1);
|
|
674
|
+
text-align: left;
|
|
675
|
+
font-size: var(--hud-text-sm);
|
|
676
|
+
}
|
|
677
|
+
#palette-tabs .ns-hud-tab .tab-glyph {
|
|
678
|
+
flex: 0 0 auto;
|
|
679
|
+
width: 11px;
|
|
680
|
+
height: 11px;
|
|
681
|
+
display: inline-flex;
|
|
682
|
+
align-items: center;
|
|
683
|
+
justify-content: center;
|
|
684
|
+
image-rendering: pixelated;
|
|
685
|
+
opacity: 0.95;
|
|
686
|
+
}
|
|
687
|
+
#palette-tabs .ns-hud-tab .tab-glyph svg {
|
|
688
|
+
width: 11px;
|
|
689
|
+
height: 11px;
|
|
690
|
+
overflow: visible;
|
|
691
|
+
display: block;
|
|
692
|
+
}
|
|
693
|
+
#palette-tabs .ns-hud-tab .tab-label {
|
|
694
|
+
overflow: hidden;
|
|
695
|
+
text-overflow: ellipsis;
|
|
696
|
+
white-space: nowrap;
|
|
697
|
+
line-height: 1;
|
|
698
|
+
}
|
|
699
|
+
#palette-icons .ns-hud-hint {
|
|
700
|
+
text-align: center;
|
|
701
|
+
}
|
|
702
|
+
.ns-elements-head {
|
|
703
|
+
display: block;
|
|
704
|
+
width: 100%;
|
|
705
|
+
text-align: center;
|
|
706
|
+
}
|
|
707
|
+
/* divider removed between toggles & Elements — reclaim the gap it used to occupy */
|
|
708
|
+
#side-panel .ns-hud-section {
|
|
709
|
+
padding-top: 0;
|
|
710
|
+
}
|
|
711
|
+
/* Palette scrolls; the hint stays pinned at the bottom of the panel */
|
|
712
|
+
#side-panel .ns-hud-section {
|
|
713
|
+
min-height: 0;
|
|
714
|
+
}
|
|
715
|
+
#palette-icons {
|
|
716
|
+
flex: 1 1 auto;
|
|
717
|
+
min-height: 0;
|
|
718
|
+
overflow-y: auto;
|
|
719
|
+
align-content: flex-start;
|
|
720
|
+
}
|
|
721
|
+
.palette-hint {
|
|
722
|
+
flex: 0 0 auto;
|
|
723
|
+
text-align: center;
|
|
724
|
+
margin-top: var(--ns-space-1);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/* ── Keyboard focus: contained gold ring for the editor's action buttons ──
|
|
728
|
+
The DS global :focus-visible (tokens/base.css) halos at ~7px with a 3px
|
|
729
|
+
offset + 4px outer ring — sized for full-page controls, it clips against
|
|
730
|
+
.ns-hud-panel's overflow:hidden and dwarfs the 18–22px chrome. Scope a
|
|
731
|
+
proportionate ring drawn INSIDE the box (negative offset) so it reads
|
|
732
|
+
crisply on the dark rail and never clips. Gold keeps it on the system's
|
|
733
|
+
focus convention. Palette tabs/slots and the align bar are mouse-only
|
|
734
|
+
<div>s (no tabindex) and are intentionally not in scope here. */
|
|
735
|
+
#side-panel .ns-hud-toolbar .ns-hud-tool:focus-visible,
|
|
736
|
+
#side-panel .ns-hud-io button:focus-visible {
|
|
737
|
+
outline: 2px solid var(--hud-gold);
|
|
738
|
+
outline-offset: -2px;
|
|
739
|
+
box-shadow: none;
|
|
740
|
+
}
|