@jjlmoya/utils-tabletop 1.26.0 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +4 -0
  3. package/src/entries.ts +4 -0
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +1 -1
  6. package/src/tests/tool_validation.test.ts +1 -1
  7. package/src/tool/mus-scoreboard/bibliography.astro +16 -0
  8. package/src/tool/mus-scoreboard/bibliography.ts +12 -0
  9. package/src/tool/mus-scoreboard/component.astro +169 -0
  10. package/src/tool/mus-scoreboard/controller.ts +178 -0
  11. package/src/tool/mus-scoreboard/dom-views.ts +87 -0
  12. package/src/tool/mus-scoreboard/entry.ts +27 -0
  13. package/src/tool/mus-scoreboard/evaluator.ts +27 -0
  14. package/src/tool/mus-scoreboard/i18n/de.ts +187 -0
  15. package/src/tool/mus-scoreboard/i18n/en.ts +187 -0
  16. package/src/tool/mus-scoreboard/i18n/es.ts +187 -0
  17. package/src/tool/mus-scoreboard/i18n/fr.ts +187 -0
  18. package/src/tool/mus-scoreboard/i18n/id.ts +187 -0
  19. package/src/tool/mus-scoreboard/i18n/it.ts +187 -0
  20. package/src/tool/mus-scoreboard/i18n/ja.ts +187 -0
  21. package/src/tool/mus-scoreboard/i18n/ko.ts +187 -0
  22. package/src/tool/mus-scoreboard/i18n/nl.ts +187 -0
  23. package/src/tool/mus-scoreboard/i18n/pl.ts +187 -0
  24. package/src/tool/mus-scoreboard/i18n/pt.ts +187 -0
  25. package/src/tool/mus-scoreboard/i18n/ru.ts +187 -0
  26. package/src/tool/mus-scoreboard/i18n/sv.ts +187 -0
  27. package/src/tool/mus-scoreboard/i18n/tr.ts +187 -0
  28. package/src/tool/mus-scoreboard/i18n/zh.ts +187 -0
  29. package/src/tool/mus-scoreboard/index.ts +11 -0
  30. package/src/tool/mus-scoreboard/logic.test.ts +82 -0
  31. package/src/tool/mus-scoreboard/logic.ts +122 -0
  32. package/src/tool/mus-scoreboard/online-mus-scoreboard.css +740 -0
  33. package/src/tool/mus-scoreboard/seo.astro +16 -0
  34. package/src/tool/mus-scoreboard/storage.ts +29 -0
  35. package/src/tool/mus-scoreboard/ui.ts +63 -0
  36. package/src/tool/token-stamp-studio/bibliography.astro +16 -0
  37. package/src/tool/token-stamp-studio/bibliography.ts +12 -0
  38. package/src/tool/token-stamp-studio/component.astro +91 -0
  39. package/src/tool/token-stamp-studio/controller.ts +179 -0
  40. package/src/tool/token-stamp-studio/dom-views.ts +266 -0
  41. package/src/tool/token-stamp-studio/entry.ts +27 -0
  42. package/src/tool/token-stamp-studio/evaluator.ts +6 -0
  43. package/src/tool/token-stamp-studio/i18n/de.ts +132 -0
  44. package/src/tool/token-stamp-studio/i18n/en.ts +132 -0
  45. package/src/tool/token-stamp-studio/i18n/es.ts +132 -0
  46. package/src/tool/token-stamp-studio/i18n/fr.ts +132 -0
  47. package/src/tool/token-stamp-studio/i18n/id.ts +132 -0
  48. package/src/tool/token-stamp-studio/i18n/it.ts +132 -0
  49. package/src/tool/token-stamp-studio/i18n/ja.ts +132 -0
  50. package/src/tool/token-stamp-studio/i18n/ko.ts +132 -0
  51. package/src/tool/token-stamp-studio/i18n/nl.ts +132 -0
  52. package/src/tool/token-stamp-studio/i18n/pl.ts +132 -0
  53. package/src/tool/token-stamp-studio/i18n/pt.ts +132 -0
  54. package/src/tool/token-stamp-studio/i18n/ru.ts +132 -0
  55. package/src/tool/token-stamp-studio/i18n/sv.ts +132 -0
  56. package/src/tool/token-stamp-studio/i18n/tr.ts +132 -0
  57. package/src/tool/token-stamp-studio/i18n/zh.ts +132 -0
  58. package/src/tool/token-stamp-studio/index.ts +11 -0
  59. package/src/tool/token-stamp-studio/logic.test.ts +36 -0
  60. package/src/tool/token-stamp-studio/logic.ts +127 -0
  61. package/src/tool/token-stamp-studio/seo.astro +16 -0
  62. package/src/tool/token-stamp-studio/storage.ts +69 -0
  63. package/src/tool/token-stamp-studio/store.ts +139 -0
  64. package/src/tool/token-stamp-studio/token-stamp-studio.css +646 -0
  65. package/src/tool/token-stamp-studio/types.ts +65 -0
  66. package/src/tool/token-stamp-studio/ui.ts +50 -0
  67. package/src/tool/token-stamp-studio/workspace-media.ts +36 -0
  68. package/src/tool/token-stamp-studio/workspace.ts +83 -0
  69. package/src/tools.ts +4 -0
@@ -0,0 +1,646 @@
1
+ :root {
2
+ --n-ink: #202a39;
3
+ --n-muted: #687386;
4
+ --n-surface: #fffdf8;
5
+ --n-surface-soft: #f4eee5;
6
+ --n-line: #ded4c6;
7
+ --n-stage: #111720;
8
+ --n-stage-soft: #273242;
9
+ --n-accent: #d89555;
10
+ --n-accent-soft: #f4d8ad;
11
+ --n-success: #4eaa83;
12
+ --n-danger: #be625a;
13
+ --n-shadow: rgba(32, 42, 57, 0.14);
14
+ --n-stage-text: #b9c5d6;
15
+ --n-stage-highlight: #fff4d6;
16
+ --n-accent-ink: #202a39;
17
+ }
18
+
19
+ .theme-dark {
20
+ --n-ink: #f6f0e5;
21
+ --n-muted: #aab4c4;
22
+ --n-surface: #202a39;
23
+ --n-surface-soft: #293547;
24
+ --n-line: #405066;
25
+ --n-stage: #0c1118;
26
+ --n-stage-soft: #273242;
27
+ --n-accent: #e1a263;
28
+ --n-accent-soft: #4d3a2c;
29
+ --n-success: #70c29b;
30
+ --n-danger: #e77e73;
31
+ --n-shadow: rgba(0, 0, 0, 0.28);
32
+ --n-stage-text: #b9c5d6;
33
+ --n-stage-highlight: #fff4d6;
34
+ --n-accent-ink: #202a39;
35
+ }
36
+
37
+ .token-stamp-studio {
38
+ --n-card: var(--n-surface);
39
+ --n-card-soft: var(--n-surface-soft);
40
+ --n-text: var(--n-ink);
41
+ --n-secondary: var(--n-muted);
42
+ --n-border: var(--n-line);
43
+ --n-focus: var(--n-accent);
44
+
45
+ color: var(--n-text);
46
+ display: grid;
47
+ gap: 1rem;
48
+ }
49
+ .foundry-shell {
50
+ background: var(--n-card);
51
+ border: 1px solid var(--n-border);
52
+ box-shadow: 0 1rem 2rem var(--n-shadow);
53
+ overflow: hidden;
54
+ }
55
+ .foundry-layout {
56
+ align-items: stretch;
57
+ display: grid;
58
+ grid-template-columns: minmax(0, 1.38fr) minmax(19rem, 0.62fr);
59
+ }
60
+ .foundry-stage-panel,
61
+ .foundry-inspector,
62
+ .batch-dock,
63
+ .marker-library {
64
+ background: transparent;
65
+ border: 0;
66
+ box-shadow: none;
67
+ }
68
+ .foundry-stage-panel {
69
+ min-width: 0;
70
+ padding: clamp(1rem, 2vw, 1.5rem);
71
+ }
72
+ .foundry-inspector {
73
+ border-left: 1px solid var(--n-border);
74
+ display: grid;
75
+ gap: 0;
76
+ overflow: hidden;
77
+ }
78
+ .panel-heading,
79
+ .block-heading,
80
+ .stage-actions,
81
+ .workspace-actions,
82
+ .editor-actions,
83
+ .batch-dock,
84
+ .batch-actions {
85
+ align-items: center;
86
+ display: flex;
87
+ justify-content: space-between;
88
+ gap: 0.75rem;
89
+ }
90
+ .panel-heading {
91
+ margin-bottom: 1rem;
92
+ }
93
+ .eyebrow {
94
+ color: var(--n-accent);
95
+ font-size: 0.68rem;
96
+ font-weight: 800;
97
+ letter-spacing: 0.16em;
98
+ margin: 0 0 0.25rem;
99
+ text-transform: uppercase;
100
+ }
101
+ .panel-heading h2,
102
+ .block-heading h3,
103
+ .batch-dock h3 {
104
+ color: var(--n-text);
105
+ margin: 0;
106
+ }
107
+ .panel-heading h2 {
108
+ font-size: clamp(1.2rem, 2vw, 1.65rem);
109
+ }
110
+ .block-heading h3 {
111
+ font-size: 1.05rem;
112
+ }
113
+ .block-mark {
114
+ color: var(--n-accent);
115
+ font-size: 1.3rem;
116
+ }
117
+ .micro-action {
118
+ background: transparent;
119
+ border: 1px solid var(--n-border);
120
+ color: var(--n-secondary);
121
+ cursor: pointer;
122
+ font-size: 0.68rem;
123
+ padding: 0.35rem 0.5rem;
124
+ }
125
+ .micro-action:hover,
126
+ .micro-action:focus-visible {
127
+ border-color: var(--n-accent);
128
+ color: var(--n-text);
129
+ outline: 2px solid var(--n-accent);
130
+ outline-offset: 2px;
131
+ }
132
+ .status-pill {
133
+ align-items: center;
134
+ background: var(--n-card-soft);
135
+ border: 1px solid var(--n-border);
136
+ color: var(--n-secondary);
137
+ display: flex;
138
+ font-size: 0.78rem;
139
+ gap: 0.45rem;
140
+ padding: 0.45rem 0.6rem;
141
+ }
142
+ .status-pill[data-tone="ready"] {
143
+ color: var(--n-success);
144
+ }
145
+ .status-dot {
146
+ background: var(--n-danger);
147
+ border-radius: 50%;
148
+ height: 0.55rem;
149
+ width: 0.55rem;
150
+ }
151
+ .status-pill[data-tone="ready"] .status-dot {
152
+ background: var(--n-success);
153
+ }
154
+ .token-stage {
155
+ background: var(--n-stage);
156
+ border: 1px solid var(--n-stage-soft);
157
+ padding: clamp(0.75rem, 4vw, 2.2rem);
158
+ position: relative;
159
+ }
160
+ .token-stage canvas {
161
+ aspect-ratio: 1;
162
+ cursor: grab;
163
+ display: block;
164
+ height: auto;
165
+ image-rendering: auto;
166
+ max-width: 100%;
167
+ touch-action: none;
168
+ width: 100%;
169
+ }
170
+ .token-stage canvas:active {
171
+ cursor: grabbing;
172
+ }
173
+ .stage-caption {
174
+ color: var(--n-stage-text);
175
+ display: flex;
176
+ font-size: 0.72rem;
177
+ justify-content: space-between;
178
+ margin: 0.65rem 0 0;
179
+ }
180
+ .stage-caption span:last-child {
181
+ color: var(--n-stage-highlight);
182
+ max-width: 55%;
183
+ overflow: hidden;
184
+ text-overflow: ellipsis;
185
+ white-space: nowrap;
186
+ }
187
+ .stage-actions {
188
+ justify-content: flex-start;
189
+ margin-top: 1rem;
190
+ flex-wrap: wrap;
191
+ }
192
+ .export-hint,
193
+ .block-hint,
194
+ .batch-dock p {
195
+ color: var(--n-secondary);
196
+ font-size: 0.78rem;
197
+ line-height: 1.5;
198
+ margin: 0.6rem 0 0;
199
+ }
200
+ .export-hint {
201
+ margin-bottom: 0;
202
+ }
203
+ .inspector-block {
204
+ border-bottom: 1px solid var(--n-border);
205
+ padding: 1rem;
206
+ }
207
+ .inspector-block:last-child {
208
+ border-bottom: 0;
209
+ }
210
+ .block-hint {
211
+ margin-bottom: 0.8rem;
212
+ }
213
+ .frame-gallery {
214
+ display: grid;
215
+ gap: 0.45rem;
216
+ grid-template-columns: repeat(3, minmax(0, 1fr));
217
+ margin-top: 0.8rem;
218
+ }
219
+ .frame-choice {
220
+ align-items: center;
221
+ background: var(--n-card-soft);
222
+ border: 1px solid var(--n-border);
223
+ color: var(--n-secondary);
224
+ cursor: pointer;
225
+ display: flex;
226
+ flex-direction: column;
227
+ font-size: 0.67rem;
228
+ gap: 0.35rem;
229
+ padding: 0.45rem 0.2rem;
230
+ }
231
+ .frame-choice:hover,
232
+ .frame-choice:focus-visible,
233
+ .frame-choice.is-selected {
234
+ border-color: var(--n-accent);
235
+ color: var(--n-text);
236
+ outline: 0;
237
+ }
238
+ .frame-choice.is-selected {
239
+ box-shadow: inset 0 -0.2rem 0 var(--n-accent);
240
+ }
241
+ .frame-swatch {
242
+ background: var(--n-stage);
243
+ border: 0;
244
+ display: block;
245
+ height: 2.15rem;
246
+ width: 2.15rem;
247
+ }
248
+ .frame-shape-circle,
249
+ .frame-shape-cloud,
250
+ .frame-shape-scallop {
251
+ border-radius: 50%;
252
+ }
253
+ .frame-shape-hexagon,
254
+ .frame-shape-octagon,
255
+ .frame-shape-star,
256
+ .frame-shape-diamond,
257
+ .frame-shape-ticket {
258
+ clip-path: polygon(50% 0%, 93% 25%, 93% 75%, 50% 100%, 7% 75%, 7% 25%);
259
+ }
260
+ .frame-shape-octagon {
261
+ clip-path: polygon(
262
+ 28% 0%,
263
+ 72% 0%,
264
+ 100% 28%,
265
+ 100% 72%,
266
+ 72% 100%,
267
+ 28% 100%,
268
+ 0% 72%,
269
+ 0% 28%
270
+ );
271
+ }
272
+ .frame-shape-star {
273
+ clip-path: polygon(
274
+ 50% 0%,
275
+ 61% 34%,
276
+ 98% 35%,
277
+ 68% 56%,
278
+ 79% 92%,
279
+ 50% 70%,
280
+ 21% 92%,
281
+ 32% 56%,
282
+ 2% 35%,
283
+ 39% 34%
284
+ );
285
+ }
286
+ .frame-shape-diamond {
287
+ clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
288
+ }
289
+ .frame-shape-ticket {
290
+ clip-path: polygon(
291
+ 18% 0%,
292
+ 82% 0%,
293
+ 100% 18%,
294
+ 100% 82%,
295
+ 82% 100%,
296
+ 18% 100%,
297
+ 0% 82%,
298
+ 0% 18%
299
+ );
300
+ }
301
+ .color-grid {
302
+ display: grid;
303
+ gap: 0.5rem;
304
+ grid-template-columns: repeat(4, 1fr);
305
+ margin-top: 0.9rem;
306
+ }
307
+ .color-control {
308
+ color: var(--n-secondary);
309
+ display: grid;
310
+ font-size: 0.68rem;
311
+ gap: 0.35rem;
312
+ }
313
+ .color-control input {
314
+ background: var(--n-card-soft);
315
+ border: 1px solid var(--n-border);
316
+ cursor: pointer;
317
+ height: 2.1rem;
318
+ padding: 0.2rem;
319
+ width: 100%;
320
+ }
321
+ .range-control {
322
+ color: var(--n-secondary);
323
+ display: grid;
324
+ font-size: 0.72rem;
325
+ gap: 0.35rem;
326
+ margin-top: 0.75rem;
327
+ }
328
+ .range-control span {
329
+ display: flex;
330
+ justify-content: space-between;
331
+ }
332
+ .range-control output {
333
+ color: var(--n-text);
334
+ font-variant-numeric: tabular-nums;
335
+ }
336
+ .range-control input {
337
+ accent-color: var(--n-accent);
338
+ width: 100%;
339
+ }
340
+ .text-layer-list {
341
+ display: grid;
342
+ gap: 0.35rem;
343
+ margin-bottom: 0.7rem;
344
+ }
345
+ .text-layer-choice,
346
+ .text-empty {
347
+ background: var(--n-card-soft);
348
+ border: 1px solid var(--n-border);
349
+ color: var(--n-secondary);
350
+ font-size: 0.78rem;
351
+ margin: 0;
352
+ padding: 0.55rem;
353
+ text-align: left;
354
+ }
355
+ .text-layer-choice {
356
+ cursor: pointer;
357
+ }
358
+ .text-layer-choice.is-selected {
359
+ border-color: var(--n-accent);
360
+ color: var(--n-text);
361
+ }
362
+ .text-editor {
363
+ border-top: 1px solid var(--n-border);
364
+ padding-top: 0.7rem;
365
+ }
366
+ .text-editor > input {
367
+ background: var(--n-card-soft);
368
+ border: 1px solid var(--n-border);
369
+ color: var(--n-text);
370
+ font: inherit;
371
+ min-height: 2.45rem;
372
+ padding: 0.55rem 0.65rem;
373
+ width: 100%;
374
+ }
375
+ .text-editor > input:focus,
376
+ .button:focus-visible,
377
+ .align-actions button:focus-visible,
378
+ .frame-choice:focus-visible,
379
+ .text-layer-choice:focus-visible {
380
+ border-color: var(--n-focus);
381
+ outline: 2px solid var(--n-focus);
382
+ outline-offset: 2px;
383
+ }
384
+ .align-actions {
385
+ display: flex;
386
+ gap: 0.35rem;
387
+ margin: 0.75rem 0 0.85rem;
388
+ }
389
+ .align-actions button {
390
+ background: var(--n-card-soft);
391
+ border: 1px solid var(--n-border);
392
+ color: var(--n-text);
393
+ cursor: pointer;
394
+ flex: 1;
395
+ font-size: 1.05rem;
396
+ min-height: 2.2rem;
397
+ min-width: 2.2rem;
398
+ }
399
+ .marker-name-field {
400
+ color: var(--n-secondary);
401
+ display: grid;
402
+ font-size: 0.72rem;
403
+ gap: 0.35rem;
404
+ max-width: 24rem;
405
+ }
406
+ .marker-name-field input {
407
+ background: var(--n-card-soft);
408
+ border: 1px solid var(--n-border);
409
+ color: var(--n-text);
410
+ font: inherit;
411
+ min-height: 2.35rem;
412
+ padding: 0.5rem 0.65rem;
413
+ width: 100%;
414
+ }
415
+ .marker-name-field input:focus {
416
+ border-color: var(--n-focus);
417
+ outline: 2px solid var(--n-focus);
418
+ outline-offset: 2px;
419
+ }
420
+ .marker-name-stage {
421
+ margin-bottom: 0.85rem;
422
+ max-width: 18rem;
423
+ }
424
+ .button {
425
+ align-items: center;
426
+ border: 1px solid var(--n-border);
427
+ cursor: pointer;
428
+ display: inline-flex;
429
+ font: inherit;
430
+ font-size: 0.78rem;
431
+ justify-content: center;
432
+ min-height: 2.45rem;
433
+ padding: 0.5rem 0.85rem;
434
+ text-decoration: none;
435
+ }
436
+ .button-primary {
437
+ background: var(--n-accent);
438
+ border-color: var(--n-accent);
439
+ color: var(--n-accent-ink);
440
+ font-weight: 800;
441
+ }
442
+ .button-quiet {
443
+ background: var(--n-card-soft);
444
+ color: var(--n-text);
445
+ }
446
+ .button-danger {
447
+ background: var(--n-card-soft);
448
+ border-color: var(--n-danger);
449
+ color: var(--n-danger);
450
+ }
451
+ .button:disabled {
452
+ cursor: not-allowed;
453
+ opacity: 0.45;
454
+ }
455
+ .batch-dock,
456
+ .marker-library {
457
+ align-items: flex-start;
458
+ padding: 1rem 1.25rem;
459
+ }
460
+ .marker-library {
461
+ border-bottom: 1px solid var(--n-border);
462
+ display: grid;
463
+ gap: 0.8rem;
464
+ }
465
+ .batch-dock {
466
+ background: var(--n-card-soft);
467
+ border-top: 1px solid var(--n-border);
468
+ }
469
+ .marker-library-header {
470
+ align-items: center;
471
+ display: block;
472
+ }
473
+ .marker-library-header .marker-library-grid {
474
+ grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
475
+ }
476
+ .batch-advanced {
477
+ border-top: 1px solid var(--n-border);
478
+ }
479
+ .batch-advanced summary {
480
+ color: var(--n-secondary);
481
+ cursor: pointer;
482
+ font-size: 0.76rem;
483
+ list-style-position: inside;
484
+ padding: 0.7rem 1.25rem;
485
+ }
486
+ .batch-advanced summary:hover,
487
+ .batch-advanced summary:focus-visible {
488
+ color: var(--n-text);
489
+ outline: 2px solid var(--n-focus);
490
+ outline-offset: -2px;
491
+ }
492
+ .batch-dock h3 {
493
+ font-size: 1rem;
494
+ }
495
+ .batch-actions {
496
+ align-self: center;
497
+ flex-wrap: wrap;
498
+ justify-content: flex-end;
499
+ }
500
+ .library-heading {
501
+ align-items: center;
502
+ display: flex;
503
+ justify-content: space-between;
504
+ gap: 1rem;
505
+ }
506
+ .library-heading h3 {
507
+ color: var(--n-text);
508
+ font-size: 1.1rem;
509
+ margin: 0;
510
+ }
511
+ .library-heading p:last-child {
512
+ color: var(--n-secondary);
513
+ font-size: 0.78rem;
514
+ margin: 0;
515
+ }
516
+ .marker-library-grid {
517
+ display: grid;
518
+ gap: 0.65rem;
519
+ grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
520
+ }
521
+ .library-empty {
522
+ color: var(--n-secondary);
523
+ font-size: 0.82rem;
524
+ margin: 0;
525
+ }
526
+ .marker-card {
527
+ background: var(--n-card-soft);
528
+ border: 1px solid var(--n-border);
529
+ display: grid;
530
+ min-width: 0;
531
+ position: relative;
532
+ }
533
+ .marker-card.is-active {
534
+ border-color: var(--n-accent);
535
+ box-shadow: inset 0 -0.2rem 0 var(--n-accent);
536
+ }
537
+ .marker-card-new {
538
+ align-items: center;
539
+ color: var(--n-secondary);
540
+ cursor: pointer;
541
+ font: inherit;
542
+ justify-content: center;
543
+ min-height: 4.5rem;
544
+ }
545
+ .marker-card-new:hover,
546
+ .marker-card-new:focus-visible {
547
+ border-color: var(--n-accent);
548
+ color: var(--n-text);
549
+ outline: 2px solid var(--n-focus);
550
+ outline-offset: -2px;
551
+ }
552
+ .marker-card-main {
553
+ align-items: center;
554
+ background: transparent;
555
+ border: 0;
556
+ color: var(--n-text);
557
+ cursor: pointer;
558
+ display: grid;
559
+ gap: 0.65rem;
560
+ grid-template-columns: 3.5rem minmax(0, 1fr);
561
+ min-width: 0;
562
+ padding: 0.6rem;
563
+ text-align: left;
564
+ }
565
+ .marker-card-main:focus-visible,
566
+ .marker-card-main:hover {
567
+ outline: 2px solid var(--n-focus);
568
+ outline-offset: -2px;
569
+ }
570
+ .marker-card-preview {
571
+ background: var(--n-stage);
572
+ display: block;
573
+ height: 3.2rem;
574
+ overflow: hidden;
575
+ width: 3.2rem;
576
+ }
577
+ .marker-card-details {
578
+ display: grid;
579
+ gap: 0.15rem;
580
+ min-width: 0;
581
+ }
582
+ .marker-card-details strong {
583
+ overflow: hidden;
584
+ text-overflow: ellipsis;
585
+ white-space: nowrap;
586
+ }
587
+ .marker-card-details small {
588
+ color: var(--n-secondary);
589
+ font-size: 0.68rem;
590
+ }
591
+ .marker-card-delete {
592
+ background: var(--n-card);
593
+ border: 0;
594
+ color: var(--n-secondary);
595
+ cursor: pointer;
596
+ font-size: 1rem;
597
+ line-height: 1;
598
+ padding: 0.2rem 0.35rem;
599
+ position: absolute;
600
+ right: 0.15rem;
601
+ top: 0.15rem;
602
+ }
603
+ .marker-card-delete:hover,
604
+ .marker-card-delete:focus-visible {
605
+ color: var(--n-danger);
606
+ outline: 2px solid var(--n-danger);
607
+ }
608
+
609
+ @media (max-width: 850px) {
610
+ .foundry-layout {
611
+ grid-template-columns: 1fr;
612
+ }
613
+ .foundry-inspector {
614
+ grid-template-columns: repeat(2, minmax(0, 1fr));
615
+ border-left: 0;
616
+ border-top: 1px solid var(--n-border);
617
+ }
618
+ .inspector-block {
619
+ border-right: 1px solid var(--n-border);
620
+ }
621
+ .inspector-block:nth-child(2n) {
622
+ border-right: 0;
623
+ }
624
+ }
625
+
626
+ @media (max-width: 600px) {
627
+ .foundry-inspector {
628
+ display: block;
629
+ }
630
+ .inspector-block {
631
+ border-right: 0;
632
+ }
633
+ .panel-heading,
634
+ .batch-dock,
635
+ .library-heading {
636
+ align-items: flex-start;
637
+ flex-direction: column;
638
+ }
639
+ .marker-library-header {
640
+ display: block;
641
+ }
642
+ .batch-actions {
643
+ align-self: stretch;
644
+ justify-content: flex-start;
645
+ }
646
+ }
@@ -0,0 +1,65 @@
1
+ export type FrameShape = 'circle' | 'square' | 'hexagon' | 'octagon' | 'star' | 'diamond' | 'ticket' | 'cloud' | 'scallop';
2
+
3
+ export interface FramePreset {
4
+ id: string;
5
+ name: string;
6
+ shortName: string;
7
+ description: string;
8
+ shape: FrameShape;
9
+ accent: string;
10
+ }
11
+
12
+ export type TextAlign = 'left' | 'center' | 'right';
13
+
14
+ export interface TextLayer {
15
+ id: string;
16
+ text: string;
17
+ x: number;
18
+ y: number;
19
+ size: number;
20
+ align: TextAlign;
21
+ }
22
+
23
+ export interface TokenStampState {
24
+ markerName?: string;
25
+ frameId: string;
26
+ background: string;
27
+ border: string;
28
+ borderWidth: number;
29
+ borderOpacity: number;
30
+ overlay: string;
31
+ overlayOpacity: number;
32
+ imageSrc: string | null;
33
+ imageName: string;
34
+ imageX: number;
35
+ imageY: number;
36
+ imageZoom: number;
37
+ scale: number;
38
+ textColor: string;
39
+ texts: TextLayer[];
40
+ selectedTextId: string | null;
41
+ }
42
+
43
+ export interface FrameGeometry {
44
+ kind: 'circle' | 'polygon';
45
+ points?: Array<{ x: number; y: number }>;
46
+ }
47
+
48
+ export interface TokenStampStatus {
49
+ tone: 'ready' | 'attention';
50
+ message: string;
51
+ }
52
+
53
+ export interface SavedMarker {
54
+ id: string;
55
+ name: string;
56
+ updatedAt: number;
57
+ state: TokenStampState;
58
+ }
59
+
60
+ export interface TokenPalette {
61
+ background: string;
62
+ border: string;
63
+ text: string;
64
+ overlay: string;
65
+ }