@jjlmoya/utils-tabletop 1.4.0 → 1.6.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 (163) hide show
  1. package/package.json +5 -3
  2. package/src/entries.ts +15 -1
  3. package/src/index.ts +3 -0
  4. package/src/tests/locale_completeness.test.ts +2 -1
  5. package/src/tests/tool_validation.test.ts +2 -1
  6. package/src/tool/decision-wheel/audio.ts +78 -0
  7. package/src/tool/decision-wheel/bibliography.astro +16 -0
  8. package/src/tool/decision-wheel/bibliography.ts +8 -0
  9. package/src/tool/decision-wheel/client.ts +226 -0
  10. package/src/tool/decision-wheel/component.astro +48 -0
  11. package/src/tool/decision-wheel/components/SegmentEditor.astro +22 -0
  12. package/src/tool/decision-wheel/components/SpinHistory.astro +17 -0
  13. package/src/tool/decision-wheel/components/SpinResult.astro +13 -0
  14. package/src/tool/decision-wheel/components/WheelCanvas.astro +23 -0
  15. package/src/tool/decision-wheel/decision-wheel.css +632 -0
  16. package/src/tool/decision-wheel/drawing.ts +144 -0
  17. package/src/tool/decision-wheel/entry.ts +48 -0
  18. package/src/tool/decision-wheel/i18n/de.ts +97 -0
  19. package/src/tool/decision-wheel/i18n/en.ts +251 -0
  20. package/src/tool/decision-wheel/i18n/es.ts +93 -0
  21. package/src/tool/decision-wheel/i18n/fr.ts +93 -0
  22. package/src/tool/decision-wheel/i18n/id.ts +93 -0
  23. package/src/tool/decision-wheel/i18n/it.ts +93 -0
  24. package/src/tool/decision-wheel/i18n/ja.ts +93 -0
  25. package/src/tool/decision-wheel/i18n/ko.ts +93 -0
  26. package/src/tool/decision-wheel/i18n/nl.ts +93 -0
  27. package/src/tool/decision-wheel/i18n/pl.ts +93 -0
  28. package/src/tool/decision-wheel/i18n/pt.ts +93 -0
  29. package/src/tool/decision-wheel/i18n/ru.ts +75 -0
  30. package/src/tool/decision-wheel/i18n/sv.ts +93 -0
  31. package/src/tool/decision-wheel/i18n/tr.ts +93 -0
  32. package/src/tool/decision-wheel/i18n/zh.ts +93 -0
  33. package/src/tool/decision-wheel/index.ts +9 -0
  34. package/src/tool/decision-wheel/logic.test.ts +163 -0
  35. package/src/tool/decision-wheel/logic.ts +145 -0
  36. package/src/tool/decision-wheel/seo.astro +16 -0
  37. package/src/tool/decision-wheel/types.ts +14 -0
  38. package/src/tool/decision-wheel/ui.ts +121 -0
  39. package/src/tool/fantasy-runes-translator/bibliography.astro +16 -0
  40. package/src/tool/fantasy-runes-translator/bibliography.ts +16 -0
  41. package/src/tool/fantasy-runes-translator/client.ts +205 -0
  42. package/src/tool/fantasy-runes-translator/component.astro +95 -0
  43. package/src/tool/fantasy-runes-translator/entry.ts +56 -0
  44. package/src/tool/fantasy-runes-translator/fantasy-runes-translator.css +712 -0
  45. package/src/tool/fantasy-runes-translator/i18n/de.ts +139 -0
  46. package/src/tool/fantasy-runes-translator/i18n/en.ts +139 -0
  47. package/src/tool/fantasy-runes-translator/i18n/es.ts +139 -0
  48. package/src/tool/fantasy-runes-translator/i18n/fr.ts +139 -0
  49. package/src/tool/fantasy-runes-translator/i18n/id.ts +139 -0
  50. package/src/tool/fantasy-runes-translator/i18n/it.ts +139 -0
  51. package/src/tool/fantasy-runes-translator/i18n/ja.ts +139 -0
  52. package/src/tool/fantasy-runes-translator/i18n/ko.ts +139 -0
  53. package/src/tool/fantasy-runes-translator/i18n/nl.ts +139 -0
  54. package/src/tool/fantasy-runes-translator/i18n/pl.ts +139 -0
  55. package/src/tool/fantasy-runes-translator/i18n/pt.ts +139 -0
  56. package/src/tool/fantasy-runes-translator/i18n/ru.ts +139 -0
  57. package/src/tool/fantasy-runes-translator/i18n/sv.ts +139 -0
  58. package/src/tool/fantasy-runes-translator/i18n/tr.ts +139 -0
  59. package/src/tool/fantasy-runes-translator/i18n/zh.ts +139 -0
  60. package/src/tool/fantasy-runes-translator/index.ts +9 -0
  61. package/src/tool/fantasy-runes-translator/logic.ts +174 -0
  62. package/src/tool/fantasy-runes-translator/seo.astro +16 -0
  63. package/src/tool/fantasy-runes-translator/types.ts +26 -0
  64. package/src/tool/investigation-board/bibliography.astro +16 -0
  65. package/src/tool/investigation-board/bibliography.ts +12 -0
  66. package/src/tool/investigation-board/boardContextMenu.ts +64 -0
  67. package/src/tool/investigation-board/client.ts +223 -0
  68. package/src/tool/investigation-board/component.astro +23 -0
  69. package/src/tool/investigation-board/components/BoardCanvas.astro +39 -0
  70. package/src/tool/investigation-board/components/CardDrawer.astro +73 -0
  71. package/src/tool/investigation-board/components/ConnectionModal.astro +49 -0
  72. package/src/tool/investigation-board/components/ContextMenu.astro +26 -0
  73. package/src/tool/investigation-board/components/ControlPanel.astro +57 -0
  74. package/src/tool/investigation-board/connectionModal.ts +60 -0
  75. package/src/tool/investigation-board/dom.ts +89 -0
  76. package/src/tool/investigation-board/drawer.ts +110 -0
  77. package/src/tool/investigation-board/entry.ts +59 -0
  78. package/src/tool/investigation-board/i18n/de.ts +126 -0
  79. package/src/tool/investigation-board/i18n/en.ts +127 -0
  80. package/src/tool/investigation-board/i18n/es.ts +126 -0
  81. package/src/tool/investigation-board/i18n/fr.ts +126 -0
  82. package/src/tool/investigation-board/i18n/id.ts +126 -0
  83. package/src/tool/investigation-board/i18n/it.ts +126 -0
  84. package/src/tool/investigation-board/i18n/ja.ts +126 -0
  85. package/src/tool/investigation-board/i18n/ko.ts +126 -0
  86. package/src/tool/investigation-board/i18n/nl.ts +126 -0
  87. package/src/tool/investigation-board/i18n/pl.ts +126 -0
  88. package/src/tool/investigation-board/i18n/pt.ts +126 -0
  89. package/src/tool/investigation-board/i18n/ru.ts +126 -0
  90. package/src/tool/investigation-board/i18n/sv.ts +126 -0
  91. package/src/tool/investigation-board/i18n/tr.ts +126 -0
  92. package/src/tool/investigation-board/i18n/zh.ts +126 -0
  93. package/src/tool/investigation-board/index.ts +11 -0
  94. package/src/tool/investigation-board/interactDrag.ts +58 -0
  95. package/src/tool/investigation-board/investigation-board.css +799 -0
  96. package/src/tool/investigation-board/layout.ts +16 -0
  97. package/src/tool/investigation-board/logic.test.ts +105 -0
  98. package/src/tool/investigation-board/logic.ts +106 -0
  99. package/src/tool/investigation-board/panzoom.ts +24 -0
  100. package/src/tool/investigation-board/renderer.ts +256 -0
  101. package/src/tool/investigation-board/seo.astro +16 -0
  102. package/src/tool/investigation-board/stateManager.ts +126 -0
  103. package/src/tool/investigation-board/types.ts +26 -0
  104. package/src/tool/rpg-initiative-tracker/bibliography.astro +16 -0
  105. package/src/tool/rpg-initiative-tracker/bibliography.ts +12 -0
  106. package/src/tool/rpg-initiative-tracker/client.ts +201 -0
  107. package/src/tool/rpg-initiative-tracker/component.astro +23 -0
  108. package/src/tool/rpg-initiative-tracker/components/AddForm.astro +49 -0
  109. package/src/tool/rpg-initiative-tracker/components/CombatantList.astro +16 -0
  110. package/src/tool/rpg-initiative-tracker/components/TurnControls.astro +28 -0
  111. package/src/tool/rpg-initiative-tracker/entry.ts +50 -0
  112. package/src/tool/rpg-initiative-tracker/i18n/de.ts +266 -0
  113. package/src/tool/rpg-initiative-tracker/i18n/en.ts +263 -0
  114. package/src/tool/rpg-initiative-tracker/i18n/es.ts +264 -0
  115. package/src/tool/rpg-initiative-tracker/i18n/fr.ts +263 -0
  116. package/src/tool/rpg-initiative-tracker/i18n/id.ts +263 -0
  117. package/src/tool/rpg-initiative-tracker/i18n/it.ts +263 -0
  118. package/src/tool/rpg-initiative-tracker/i18n/ja.ts +263 -0
  119. package/src/tool/rpg-initiative-tracker/i18n/ko.ts +263 -0
  120. package/src/tool/rpg-initiative-tracker/i18n/nl.ts +263 -0
  121. package/src/tool/rpg-initiative-tracker/i18n/pl.ts +264 -0
  122. package/src/tool/rpg-initiative-tracker/i18n/pt.ts +263 -0
  123. package/src/tool/rpg-initiative-tracker/i18n/ru.ts +264 -0
  124. package/src/tool/rpg-initiative-tracker/i18n/sv.ts +263 -0
  125. package/src/tool/rpg-initiative-tracker/i18n/tr.ts +263 -0
  126. package/src/tool/rpg-initiative-tracker/i18n/zh.ts +263 -0
  127. package/src/tool/rpg-initiative-tracker/index.ts +9 -0
  128. package/src/tool/rpg-initiative-tracker/logic.test.ts +121 -0
  129. package/src/tool/rpg-initiative-tracker/logic.ts +122 -0
  130. package/src/tool/rpg-initiative-tracker/rpg-initiative-tracker.css +617 -0
  131. package/src/tool/rpg-initiative-tracker/seo.astro +16 -0
  132. package/src/tool/rpg-initiative-tracker/types.ts +15 -0
  133. package/src/tool/score-tracker/bibliography.astro +16 -0
  134. package/src/tool/score-tracker/bibliography.ts +12 -0
  135. package/src/tool/score-tracker/client.ts +248 -0
  136. package/src/tool/score-tracker/component.astro +34 -0
  137. package/src/tool/score-tracker/components/Leaderboard.astro +19 -0
  138. package/src/tool/score-tracker/components/PlayerSetup.astro +32 -0
  139. package/src/tool/score-tracker/components/RoundScoring.astro +22 -0
  140. package/src/tool/score-tracker/components/ScoreHistory.astro +25 -0
  141. package/src/tool/score-tracker/entry.ts +57 -0
  142. package/src/tool/score-tracker/i18n/de.ts +278 -0
  143. package/src/tool/score-tracker/i18n/en.ts +278 -0
  144. package/src/tool/score-tracker/i18n/es.ts +251 -0
  145. package/src/tool/score-tracker/i18n/fr.ts +278 -0
  146. package/src/tool/score-tracker/i18n/id.ts +278 -0
  147. package/src/tool/score-tracker/i18n/it.ts +278 -0
  148. package/src/tool/score-tracker/i18n/ja.ts +278 -0
  149. package/src/tool/score-tracker/i18n/ko.ts +278 -0
  150. package/src/tool/score-tracker/i18n/nl.ts +278 -0
  151. package/src/tool/score-tracker/i18n/pl.ts +278 -0
  152. package/src/tool/score-tracker/i18n/pt.ts +278 -0
  153. package/src/tool/score-tracker/i18n/ru.ts +278 -0
  154. package/src/tool/score-tracker/i18n/sv.ts +278 -0
  155. package/src/tool/score-tracker/i18n/tr.ts +278 -0
  156. package/src/tool/score-tracker/i18n/zh.ts +278 -0
  157. package/src/tool/score-tracker/index.ts +9 -0
  158. package/src/tool/score-tracker/logic.test.ts +83 -0
  159. package/src/tool/score-tracker/logic.ts +122 -0
  160. package/src/tool/score-tracker/score-tracker.css +1029 -0
  161. package/src/tool/score-tracker/seo.astro +16 -0
  162. package/src/tool/score-tracker/types.ts +17 -0
  163. package/src/tools.ts +11 -0
@@ -0,0 +1,712 @@
1
+ .runes-wrap {
2
+ max-width: 640px;
3
+ margin: 0 auto;
4
+ padding: 1.5rem;
5
+ background: var(--bg-surface);
6
+ border: 1px solid var(--border-color);
7
+ border-radius: 1.25rem;
8
+ box-shadow: 0 10px 30px rgba(0,0,0,0.04);
9
+ position: relative;
10
+ }
11
+
12
+ .runes-top-bar {
13
+ display: flex;
14
+ gap: 0.5rem;
15
+ align-items: flex-start;
16
+ margin-bottom: 1.25rem;
17
+ }
18
+ .alphabet-pills {
19
+ display: flex;
20
+ gap: 0.5rem;
21
+ flex-wrap: wrap;
22
+ flex: 1;
23
+ }
24
+ .pill {
25
+ padding: 0.45rem 0.9rem 0.45rem 0.75rem;
26
+ border: 1.5px solid var(--border-color);
27
+ border-radius: 0.85rem;
28
+ background: var(--bg-page);
29
+ color: var(--text-muted);
30
+ cursor: pointer;
31
+ font-size: 0.65rem;
32
+ font-weight: 800;
33
+ text-transform: uppercase;
34
+ letter-spacing: 0.05em;
35
+ transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
36
+ display: inline-flex;
37
+ align-items: center;
38
+ gap: 0.5rem;
39
+ position: relative;
40
+ overflow: hidden;
41
+ }
42
+ .pill::before {
43
+ content: '';
44
+ position: absolute;
45
+ inset: 0;
46
+ border-radius: inherit;
47
+ opacity: 0;
48
+ background: radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--pill-color, var(--accent)) 15%, transparent), transparent 70%);
49
+ transition: opacity 0.3s ease;
50
+ }
51
+ .pill:hover {
52
+ transform: translateY(-3px);
53
+ box-shadow: 0 6px 24px color-mix(in srgb, var(--pill-color, var(--accent)) 12%, transparent);
54
+ }
55
+ .pill:hover::before {
56
+ opacity: 1;
57
+ }
58
+ .pill:active {
59
+ transform: scale(0.95);
60
+ }
61
+ .pill.active {
62
+ border-color: var(--pill-color, var(--accent));
63
+ color: var(--color-white);
64
+ box-shadow: 0 6px 28px color-mix(in srgb, var(--pill-color, var(--accent)) 25%, transparent),
65
+ inset 0 0 20px color-mix(in srgb, var(--pill-color, var(--accent)) 10%, transparent);
66
+ background: linear-gradient(145deg,
67
+ color-mix(in srgb, var(--pill-color, var(--accent)) 90%, #000) 0%,
68
+ color-mix(in srgb, var(--pill-color, var(--accent)) 50%, var(--bg-page)) 100%);
69
+ }
70
+ .pill-rune {
71
+ font-size: 1.1rem;
72
+ line-height: 1;
73
+ position: relative;
74
+ z-index: 1;
75
+ }
76
+ .pill-label {
77
+ position: relative;
78
+ z-index: 1;
79
+ }
80
+
81
+ .pill[data-alphabet="elder-futhark"] {
82
+ --pill-color: #d97706;
83
+ }
84
+ .pill[data-alphabet="elder-futhark"]:not(.active):hover {
85
+ border-color: #d97706;
86
+ color: var(--pill-color);
87
+ }
88
+
89
+ .pill[data-alphabet="anglo-saxon"] {
90
+ --pill-color: #65a30d;
91
+ }
92
+ .pill[data-alphabet="anglo-saxon"]:not(.active):hover {
93
+ border-color: #65a30d;
94
+ color: var(--pill-color);
95
+ }
96
+
97
+ .pill[data-alphabet="fantasy"] {
98
+ --pill-color: #a78bfa;
99
+ }
100
+ .pill[data-alphabet="fantasy"]:not(.active):hover {
101
+ border-color: #a78bfa;
102
+ color: var(--pill-color);
103
+ }
104
+
105
+ .pill[data-alphabet="theban"] {
106
+ --pill-color: #2dd4bf;
107
+ }
108
+ .pill[data-alphabet="theban"]:not(.active):hover {
109
+ border-color: #2dd4bf;
110
+ color: var(--pill-color);
111
+ }
112
+
113
+ .pill[data-alphabet="enochian"] {
114
+ --pill-color: #60a5fa;
115
+ }
116
+ .pill[data-alphabet="enochian"]:not(.active):hover {
117
+ border-color: #60a5fa;
118
+ color: var(--pill-color);
119
+ }
120
+
121
+ .pill[data-alphabet="daemonic"] {
122
+ --pill-color: #f87171;
123
+ }
124
+ .pill[data-alphabet="daemonic"]:not(.active):hover {
125
+ border-color: #f87171;
126
+ color: var(--pill-color);
127
+ }
128
+
129
+ .pill[data-alphabet="ogham"] {
130
+ --pill-color: #4ade80;
131
+ }
132
+ .pill[data-alphabet="ogham"]:not(.active):hover {
133
+ border-color: #4ade80;
134
+ color: var(--pill-color);
135
+ }
136
+
137
+ .seed-cog {
138
+ width: 1.8rem;
139
+ height: 1.8rem;
140
+ border: 1px solid var(--border-color);
141
+ border-radius: 50%;
142
+ background: none;
143
+ color: var(--text-muted);
144
+ cursor: pointer;
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ font-size: 0.9rem;
149
+ flex-shrink: 0;
150
+ transition: all 0.2s ease;
151
+ margin-top: 0.1rem;
152
+ }
153
+ .seed-cog:hover {
154
+ border-color: var(--accent);
155
+ color: var(--accent);
156
+ transform: rotate(45deg);
157
+ }
158
+
159
+ .seed-drawer {
160
+ max-height: 0;
161
+ overflow: hidden;
162
+ transition: max-height 0.25s ease, opacity 0.2s ease;
163
+ opacity: 0;
164
+ }
165
+ .seed-drawer.open {
166
+ max-height: 60px;
167
+ opacity: 1;
168
+ margin-bottom: 0.75rem;
169
+ }
170
+ .seed-inner {
171
+ display: flex;
172
+ align-items: center;
173
+ gap: 0.5rem;
174
+ }
175
+ .seed-field {
176
+ display: flex;
177
+ align-items: center;
178
+ gap: 0.25rem;
179
+ background: var(--bg-page);
180
+ border: 1px solid var(--border-color);
181
+ border-radius: 99px;
182
+ padding: 0.15rem 0.15rem 0.15rem 0.75rem;
183
+ }
184
+ .seed-field:focus-within {
185
+ border-color: var(--accent);
186
+ }
187
+ #runes-seed {
188
+ width: 4rem;
189
+ padding: 0;
190
+ border: none;
191
+ background: none;
192
+ color: var(--text-base);
193
+ font-size: 0.8rem;
194
+ font-weight: 600;
195
+ outline: none;
196
+ -moz-appearance: textfield;
197
+ }
198
+ #runes-seed::placeholder {
199
+ color: var(--text-muted);
200
+ opacity: 0.4;
201
+ }
202
+ #runes-seed::-webkit-outer-spin-button,
203
+ #runes-seed::-webkit-inner-spin-button {
204
+ -webkit-appearance: none;
205
+ margin: 0;
206
+ }
207
+ .seed-shuffle {
208
+ width: 1.6rem;
209
+ height: 1.6rem;
210
+ border: none;
211
+ border-radius: 50%;
212
+ background: var(--bg-surface);
213
+ color: var(--text-muted);
214
+ cursor: pointer;
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ font-size: 0.85rem;
219
+ transition: all 0.2s ease;
220
+ }
221
+ .seed-shuffle:hover {
222
+ background: var(--accent);
223
+ color: var(--color-white);
224
+ transform: rotate(180deg);
225
+ }
226
+ .seed-tag {
227
+ font-size: 0.6rem;
228
+ font-weight: 700;
229
+ padding: 0.1rem 0.45rem;
230
+ border-radius: 99px;
231
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
232
+ color: var(--accent);
233
+ text-transform: uppercase;
234
+ letter-spacing: 0.04em;
235
+ }
236
+ .seed-hint {
237
+ font-size: 0.7rem;
238
+ color: var(--text-muted);
239
+ opacity: 0.5;
240
+ }
241
+
242
+ .runes-input-area {
243
+ margin-bottom: 1rem;
244
+ }
245
+ #runes-input {
246
+ width: 100%;
247
+ padding: 0.8rem 1rem;
248
+ box-sizing: border-box;
249
+ border: 1px solid var(--border-color);
250
+ border-radius: 1rem;
251
+ background: var(--bg-page);
252
+ color: var(--text-base);
253
+ font-size: 1rem;
254
+ font-weight: 600;
255
+ outline: none;
256
+ transition: all 0.2s ease;
257
+ }
258
+ #runes-input:focus {
259
+ border-color: var(--accent);
260
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 8%, transparent);
261
+ }
262
+ #runes-input::placeholder {
263
+ color: var(--text-muted);
264
+ font-weight: 400;
265
+ opacity: 0.4;
266
+ }
267
+
268
+ .runes-output {
269
+ min-height: 120px;
270
+ border: 1px solid var(--border-color);
271
+ border-radius: 1rem;
272
+ padding: 1.25rem;
273
+ background: var(--bg-page);
274
+ margin-bottom: 0.75rem;
275
+ transition: all 0.3s ease;
276
+ }
277
+ .runes-output.has-chars {
278
+ border-color: var(--accent);
279
+ box-shadow: 0 0 20px color-mix(in srgb, var(--accent) 6%, transparent);
280
+ }
281
+ .runes-output-empty {
282
+ display: flex;
283
+ flex-direction: column;
284
+ align-items: center;
285
+ justify-content: center;
286
+ min-height: 90px;
287
+ gap: 0.4rem;
288
+ color: var(--text-muted);
289
+ }
290
+ .empty-rune {
291
+ font-size: 2rem;
292
+ opacity: 0.2;
293
+ }
294
+ .empty-label {
295
+ font-size: 0.8rem;
296
+ font-weight: 600;
297
+ opacity: 0.4;
298
+ }
299
+
300
+ .runes-grid {
301
+ display: flex;
302
+ flex-wrap: wrap;
303
+ gap: 0.5rem;
304
+ }
305
+ .rune-card {
306
+ display: flex;
307
+ flex-direction: column;
308
+ align-items: center;
309
+ gap: 0.2rem;
310
+ padding: 0.7rem 0.8rem;
311
+ background: var(--bg-surface);
312
+ border: 1px solid var(--border-color);
313
+ border-radius: 0.85rem;
314
+ cursor: pointer;
315
+ min-width: 52px;
316
+ transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
317
+ animation: rc-in 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
318
+ }
319
+
320
+ @keyframes rc-in {
321
+ 0% {
322
+ opacity: 0;
323
+ transform: scale(0.85) translateY(10px);
324
+ }
325
+ 100% {
326
+ opacity: 1;
327
+ transform: scale(1) translateY(0);
328
+ }
329
+ }
330
+ .rune-card:hover {
331
+ border-color: var(--accent);
332
+ transform: translateY(-3px);
333
+ }
334
+ .rune-card.active {
335
+ border-color: var(--accent);
336
+ background: linear-gradient(135deg, var(--bg-surface), color-mix(in srgb, var(--accent) 8%, transparent));
337
+ box-shadow: 0 0 15px color-mix(in srgb, var(--accent) 10%, transparent);
338
+ }
339
+ .rune-card .sym {
340
+ font-size: 1.8rem;
341
+ line-height: 1;
342
+ color: var(--text-base);
343
+ }
344
+ .rune-card .let {
345
+ font-size: 0.55rem;
346
+ color: var(--text-muted);
347
+ text-transform: uppercase;
348
+ font-weight: 700;
349
+ opacity: 0.4;
350
+ }
351
+ .rune-card.active .let {
352
+ opacity: 0.8;
353
+ color: var(--accent);
354
+ }
355
+
356
+ .detail-card {
357
+ border: 1px solid var(--border-color);
358
+ border-radius: 0.85rem;
359
+ padding: 0.75rem 1rem;
360
+ background: var(--bg-surface);
361
+ margin-bottom: 0.75rem;
362
+ display: none;
363
+ gap: 0.5rem;
364
+ }
365
+ .detail-card.vis {
366
+ display: flex;
367
+ flex-wrap: wrap;
368
+ gap: 0.75rem;
369
+ border-color: var(--accent);
370
+ }
371
+ .detail-row {
372
+ display: flex;
373
+ flex-direction: column;
374
+ gap: 0.1rem;
375
+ min-width: 100px;
376
+ flex: 1;
377
+ }
378
+ .detail-lbl {
379
+ font-size: 0.6rem;
380
+ font-weight: 700;
381
+ color: var(--text-muted);
382
+ text-transform: uppercase;
383
+ letter-spacing: 0.06em;
384
+ }
385
+ .detail-val {
386
+ font-size: 0.85rem;
387
+ color: var(--text-base);
388
+ font-weight: 600;
389
+ }
390
+
391
+ .runes-bottom-bar {
392
+ display: flex;
393
+ gap: 0.35rem;
394
+ align-items: center;
395
+ }
396
+ .bot-spacer {
397
+ flex: 1;
398
+ }
399
+ .bot-btn {
400
+ width: 2rem;
401
+ height: 2rem;
402
+ border: 1px solid var(--border-color);
403
+ border-radius: 0.5rem;
404
+ background: none;
405
+ color: var(--text-muted);
406
+ cursor: pointer;
407
+ display: flex;
408
+ align-items: center;
409
+ justify-content: center;
410
+ transition: all 0.2s ease;
411
+ flex-shrink: 0;
412
+ }
413
+ .bot-btn:hover {
414
+ border-color: var(--accent);
415
+ color: var(--accent);
416
+ }
417
+ .bot-btn.gm-reveal {
418
+ width: auto;
419
+ padding: 0.5rem 1rem;
420
+ gap: 0.4rem;
421
+ border-radius: 0.75rem;
422
+ background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 70%, #000));
423
+ border-color: var(--accent);
424
+ color: var(--color-white);
425
+ font-size: 0.8rem;
426
+ font-weight: 800;
427
+ text-transform: uppercase;
428
+ letter-spacing: 0.05em;
429
+ box-shadow: 0 4px 16px color-mix(in srgb, var(--accent) 20%, transparent);
430
+ }
431
+ .bot-btn.gm-reveal:hover {
432
+ transform: translateY(-2px);
433
+ box-shadow: 0 6px 24px color-mix(in srgb, var(--accent) 30%, transparent);
434
+ }
435
+
436
+ .ref-overlay {
437
+ position: fixed;
438
+ inset: 0;
439
+ z-index: 1000;
440
+ display: none;
441
+ flex-direction: column;
442
+ align-items: center;
443
+ justify-content: center;
444
+ background: radial-gradient(ellipse at center, color-mix(in srgb, var(--bg-page) 97%, var(--accent)), var(--bg-page));
445
+ backdrop-filter: blur(12px);
446
+ padding: 2rem;
447
+ animation: gmin 0.4s ease;
448
+ overflow: hidden;
449
+ }
450
+ .ref-overlay::before {
451
+ content: '';
452
+ position: absolute;
453
+ inset: 0;
454
+ background: radial-gradient(circle at 20% 50%, color-mix(in srgb, var(--accent) 4%, transparent) 0%, transparent 60%);
455
+ pointer-events: none;
456
+ }
457
+ .ref-overlay.active {
458
+ display: flex;
459
+ }
460
+ .ref-close {
461
+ position: fixed;
462
+ top: 1rem;
463
+ right: 1rem;
464
+ width: 2.4rem;
465
+ height: 2.4rem;
466
+ border-radius: 50%;
467
+ border: 1px solid var(--border-color);
468
+ background: var(--bg-surface);
469
+ color: var(--text-muted);
470
+ cursor: pointer;
471
+ display: flex;
472
+ align-items: center;
473
+ justify-content: center;
474
+ font-size: 1rem;
475
+ transition: all 0.2s ease;
476
+ z-index: 1001;
477
+ }
478
+ .ref-close:hover {
479
+ border-color: var(--accent);
480
+ color: var(--accent);
481
+ transform: scale(1.1);
482
+ }
483
+ .ref-title {
484
+ font-size: 1.1rem;
485
+ font-weight: 800;
486
+ text-transform: uppercase;
487
+ letter-spacing: 0.08em;
488
+ color: var(--accent);
489
+ margin-bottom: 1.5rem;
490
+ position: relative;
491
+ z-index: 1;
492
+ text-shadow: 0 0 20px color-mix(in srgb, var(--accent) 20%, transparent);
493
+ }
494
+ .ref-grid {
495
+ display: grid;
496
+ grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
497
+ gap: 0.6rem;
498
+ max-width: 650px;
499
+ width: 100%;
500
+ position: relative;
501
+ z-index: 1;
502
+ }
503
+ .ref-cell {
504
+ display: flex;
505
+ flex-direction: column;
506
+ align-items: center;
507
+ gap: 0.25rem;
508
+ padding: 0.7rem 0.4rem;
509
+ background: var(--bg-surface);
510
+ border: 1px solid var(--border-color);
511
+ border-radius: 0.85rem;
512
+ transition: all 0.3s ease;
513
+ position: relative;
514
+ }
515
+ .ref-cell.lit {
516
+ border-color: var(--accent);
517
+ background: linear-gradient(145deg, var(--bg-surface), color-mix(in srgb, var(--accent) 6%, transparent));
518
+ box-shadow: 0 0 16px color-mix(in srgb, var(--accent) 10%, transparent);
519
+ animation: ref-reveal 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
520
+ }
521
+
522
+ @keyframes ref-reveal {
523
+ 0% {
524
+ transform: scale(0.85);
525
+ opacity: 0.5;
526
+ }
527
+ 60% {
528
+ transform: scale(1.05);
529
+ }
530
+ 100% {
531
+ transform: scale(1);
532
+ opacity: 1;
533
+ }
534
+ }
535
+ .ref-cell:not(.lit) {
536
+ opacity: 0.35;
537
+ }
538
+ .ref-cell .ref-sym {
539
+ font-size: 1.8rem;
540
+ line-height: 1;
541
+ color: var(--text-muted);
542
+ }
543
+ .ref-cell.lit .ref-sym {
544
+ color: var(--accent);
545
+ text-shadow: 0 0 12px color-mix(in srgb, var(--accent) 30%, transparent);
546
+ }
547
+ .ref-cell .ref-let {
548
+ font-size: 0.6rem;
549
+ font-weight: 700;
550
+ color: var(--text-muted);
551
+ text-transform: uppercase;
552
+ letter-spacing: 0.06em;
553
+ opacity: 0.5;
554
+ }
555
+ .ref-cell.lit .ref-let {
556
+ opacity: 0.8;
557
+ color: var(--accent);
558
+ }
559
+
560
+ .shimmer {
561
+ position: absolute;
562
+ inset: 0;
563
+ background: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--accent) 6%, transparent) 50%, transparent 100%);
564
+ animation: shim 0.5s ease forwards;
565
+ pointer-events: none;
566
+ }
567
+
568
+ @keyframes shim {
569
+ 0% {
570
+ transform: translateX(-100%);
571
+ }
572
+ 100% {
573
+ transform: translateX(100%);
574
+ }
575
+ }
576
+
577
+ .particle {
578
+ position: fixed;
579
+ pointer-events: none;
580
+ z-index: 200;
581
+ font-size: 1.5rem;
582
+ animation: part 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
583
+ color: var(--accent);
584
+ }
585
+
586
+ @keyframes part {
587
+ 0% {
588
+ transform: translate(-50%, -50%) scale(0.3) rotate(-20deg);
589
+ opacity: 0;
590
+ }
591
+ 20% {
592
+ opacity: 1;
593
+ transform: translate(-50%, -60%) scale(1.2) rotate(10deg);
594
+ }
595
+ 100% {
596
+ transform: translate(-50%, -120%) scale(0.6) rotate(-10deg);
597
+ opacity: 0;
598
+ }
599
+ }
600
+
601
+ .gm-overlay {
602
+ position: fixed;
603
+ inset: 0;
604
+ z-index: 1000;
605
+ display: none;
606
+ flex-direction: column;
607
+ align-items: center;
608
+ justify-content: center;
609
+ background: var(--bg-page);
610
+ padding: 2rem;
611
+ animation: gmin 0.3s ease;
612
+ }
613
+
614
+ @keyframes gmin {
615
+ 0% {
616
+ opacity: 0;
617
+ }
618
+ 100% {
619
+ opacity: 1;
620
+ }
621
+ }
622
+ .gm-overlay.active {
623
+ display: flex;
624
+ }
625
+ .gm-runes {
626
+ font-size: clamp(3rem, 15vw, 8rem);
627
+ line-height: 1.3;
628
+ text-align: center;
629
+ color: var(--text-base);
630
+ letter-spacing: 0.12em;
631
+ text-shadow: 0 0 30px color-mix(in srgb, var(--accent) 15%, transparent);
632
+ animation: gmr 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
633
+ max-width: 90vw;
634
+ word-break: break-all;
635
+ }
636
+
637
+ @keyframes gmr {
638
+ 0% {
639
+ opacity: 0;
640
+ transform: scale(0.6) rotateX(30deg);
641
+ filter: blur(6px);
642
+ }
643
+ 60% {
644
+ transform: scale(1.03);
645
+ filter: blur(0);
646
+ }
647
+ 100% {
648
+ opacity: 1;
649
+ transform: scale(1);
650
+ }
651
+ }
652
+ .gm-subtle {
653
+ margin-top: 1.5rem;
654
+ font-size: 0.75rem;
655
+ color: var(--text-muted);
656
+ font-weight: 600;
657
+ opacity: 0.3;
658
+ letter-spacing: 0.06em;
659
+ }
660
+ .gm-exit {
661
+ position: fixed;
662
+ top: 1rem;
663
+ right: 1rem;
664
+ width: 2.2rem;
665
+ height: 2.2rem;
666
+ border-radius: 50%;
667
+ border: 1px solid var(--border-color);
668
+ background: var(--bg-surface);
669
+ color: var(--text-muted);
670
+ cursor: pointer;
671
+ display: flex;
672
+ align-items: center;
673
+ justify-content: center;
674
+ font-size: 1rem;
675
+ transition: all 0.2s ease;
676
+ z-index: 1001;
677
+ }
678
+ .gm-exit:hover {
679
+ border-color: var(--accent);
680
+ color: var(--accent);
681
+ }
682
+ .gm-particles {
683
+ position: fixed;
684
+ inset: 0;
685
+ pointer-events: none;
686
+ z-index: 999;
687
+ overflow: hidden;
688
+ }
689
+ .gm-float {
690
+ position: absolute;
691
+ font-size: 1.2rem;
692
+ color: var(--accent);
693
+ opacity: 0;
694
+ animation: gmf 4s ease-in-out infinite;
695
+ }
696
+
697
+ @keyframes gmf {
698
+ 0% {
699
+ transform: translateY(100vh) rotate(0deg);
700
+ opacity: 0;
701
+ }
702
+ 20% {
703
+ opacity: 0.3;
704
+ }
705
+ 80% {
706
+ opacity: 0.3;
707
+ }
708
+ 100% {
709
+ transform: translateY(-10vh) rotate(720deg);
710
+ opacity: 0;
711
+ }
712
+ }