@openpresentation/opf-editor 0.24.0 → 0.24.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.
@@ -0,0 +1,3339 @@
1
+ /*
2
+ * OPF editor UI tokens (RR-98). Every other file in this stylesheet uses only these `--opf-ui-*` variables.
3
+ * Values copy the openpresentation.org design system. The host loads Inter and Geist Mono; nothing here fetches a font.
4
+ * Light is the default. Dark applies under `.dark .opf-ui`, `.opf-ui.dark`, `[data-theme=dark]` (on the root or on any ancestor) and `:root.dark`.
5
+ */
6
+ :root,
7
+ .opf-ui {
8
+ --opf-ui-bg: hsl(210 30% 98%);
9
+ --opf-ui-surface: hsl(0 0% 100%);
10
+ --opf-ui-muted: hsl(214 28% 93%);
11
+ --opf-ui-muted-2: hsl(214 28% 96%);
12
+ --opf-ui-fg: hsl(220 28% 11%);
13
+ --opf-ui-muted-fg: hsl(218 14% 38%);
14
+ --opf-ui-accent: hsl(214 57% 28%);
15
+ --opf-ui-accent-fg: hsl(0 0% 100%);
16
+ --opf-ui-accent-strong: hsl(214 57% 28%);
17
+ --opf-ui-border: hsl(214 22% 83%);
18
+ --opf-ui-border-strong: hsl(214 22% 72%);
19
+ --opf-ui-ring: hsl(214 57% 28%);
20
+ --opf-ui-danger: hsl(0 72% 45%);
21
+ --opf-ui-warn: hsl(28 75% 38%);
22
+ --opf-ui-success: hsl(152 76% 26%);
23
+ --opf-ui-code-bg: hsl(220 30% 96%);
24
+ --opf-ui-code-border: hsl(214 18% 84%);
25
+
26
+ --opf-ui-font: Inter, system-ui, sans-serif;
27
+ --opf-ui-mono: "Geist Mono", ui-monospace, Menlo, monospace;
28
+
29
+ --opf-ui-radius-sm: 4px;
30
+ --opf-ui-radius: 6px;
31
+ --opf-ui-radius-md: 8px;
32
+ --opf-ui-radius-lg: 12px;
33
+
34
+ --opf-ui-control-h: 32px;
35
+ --opf-ui-shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.1);
36
+ --opf-ui-ease: 120ms ease;
37
+
38
+ color-scheme: light;
39
+ }
40
+
41
+ :root.dark,
42
+ .dark .opf-ui,
43
+ .opf-ui.dark,
44
+ [data-theme="dark"],
45
+ [data-theme="dark"] .opf-ui {
46
+ --opf-ui-bg: hsl(220 24% 9%);
47
+ --opf-ui-surface: hsl(220 22% 11%);
48
+ --opf-ui-muted: hsl(220 18% 16%);
49
+ --opf-ui-muted-2: hsl(220 18% 13%);
50
+ --opf-ui-fg: hsl(210 28% 92%);
51
+ --opf-ui-muted-fg: hsl(215 13% 68%);
52
+ --opf-ui-accent: hsl(214 57% 52%);
53
+ --opf-ui-accent-fg: hsl(220 24% 9%);
54
+ --opf-ui-accent-strong: hsl(214 74% 72%);
55
+ --opf-ui-border: hsl(220 17% 24%);
56
+ --opf-ui-border-strong: hsl(220 17% 34%);
57
+ --opf-ui-ring: hsl(214 57% 62%);
58
+ --opf-ui-danger: hsl(0 65% 56%);
59
+ --opf-ui-warn: hsl(32 80% 70%);
60
+ --opf-ui-success: hsl(152 60% 70%);
61
+ --opf-ui-code-bg: hsl(222 22% 13%);
62
+ --opf-ui-code-border: hsl(220 16% 24%);
63
+
64
+ --opf-ui-shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.4);
65
+
66
+ color-scheme: dark;
67
+ }
68
+
69
+ /* Touch density: controls grow to 40px, as in the mobile design. */
70
+ .opf-ui[data-density="touch"],
71
+ [data-density="touch"] .opf-ui {
72
+ --opf-ui-control-h: 40px;
73
+ }
74
+
75
+ /* Base rules for a mounted component or a whole editor surface. */
76
+ .opf-ui {
77
+ font-family: var(--opf-ui-font);
78
+ font-size: 13px;
79
+ line-height: 1.5;
80
+ color: var(--opf-ui-fg);
81
+ -webkit-font-smoothing: antialiased;
82
+ }
83
+
84
+ .opf-ui *,
85
+ .opf-ui *::before,
86
+ .opf-ui *::after {
87
+ box-sizing: border-box;
88
+ }
89
+
90
+ .opf-ui :focus-visible {
91
+ outline: 2px solid var(--opf-ui-ring);
92
+ outline-offset: 2px;
93
+ }
94
+
95
+ /* Motion is color and border only, and it is off when the person asks for less. */
96
+ @media (prefers-reduced-motion: reduce) {
97
+ :root,
98
+ .opf-ui {
99
+ --opf-ui-ease: 0s linear;
100
+ }
101
+
102
+ .opf-ui,
103
+ .opf-ui *,
104
+ .opf-ui *::before,
105
+ .opf-ui *::after {
106
+ transition: none !important;
107
+ animation: none !important;
108
+ scroll-behavior: auto !important;
109
+ }
110
+ }
111
+
112
+ /* export-menu.css */
113
+ /* RR-98: the Export menu (src/export-menu.js). Only --opf-ui-* tokens, no color literals (test/styles.mjs). */
114
+ .opf-export,
115
+ .opf-export *,
116
+ .opf-export *::before,
117
+ .opf-export *::after { box-sizing: border-box; }
118
+ .opf-export [hidden] { display: none !important; }
119
+
120
+ .opf-export {
121
+ position: relative;
122
+ display: inline-flex;
123
+ font-family: var(--opf-ui-font);
124
+ font-size: 13px;
125
+ line-height: 1.4;
126
+ color: var(--opf-ui-fg);
127
+ }
128
+ :where(.opf-export button) { font: inherit; color: inherit; margin: 0; }
129
+ .opf-export .opf-icon { flex: none; }
130
+
131
+ .opf-export button:focus-visible {
132
+ outline: 2px solid var(--opf-ui-ring);
133
+ outline-offset: 2px;
134
+ }
135
+
136
+ /* ---- trigger --------------------------------------------------------------------------------------------------------------------------- */
137
+ .opf-export .opf-export-trigger {
138
+ display: inline-flex;
139
+ align-items: center;
140
+ gap: 6px;
141
+ height: var(--opf-ui-control-h);
142
+ padding: 0 8px 0 12px;
143
+ border: 1px solid var(--opf-ui-accent);
144
+ border-radius: var(--opf-ui-radius);
145
+ background: var(--opf-ui-accent);
146
+ color: var(--opf-ui-accent-fg);
147
+ font-weight: 500;
148
+ white-space: nowrap;
149
+ cursor: pointer;
150
+ transition: opacity var(--opf-ui-ease);
151
+ }
152
+ .opf-export .opf-export-trigger:hover { opacity: 0.92; }
153
+ .opf-export .opf-export-trigger[aria-expanded="true"] { opacity: 0.92; }
154
+
155
+ /* ---- the menu (a popover under the trigger) ------------------------------------------------------------------------------------------ */
156
+ .opf-export .opf-export-popover,
157
+ .opf-export .opf-export-status {
158
+ position: absolute;
159
+ top: calc(100% + 4px);
160
+ right: 0;
161
+ z-index: 40;
162
+ background: var(--opf-ui-surface);
163
+ border: 1px solid var(--opf-ui-border);
164
+ border-radius: var(--opf-ui-radius-lg);
165
+ box-shadow: var(--opf-ui-shadow-pop);
166
+ }
167
+ .opf-export .opf-export-popover { width: 264px; padding: 4px; border-radius: var(--opf-ui-radius-md); }
168
+ .opf-export[data-align="start"] .opf-export-popover,
169
+ .opf-export[data-align="start"] .opf-export-status { right: auto; left: 0; }
170
+
171
+ .opf-export .opf-export-menu { display: flex; flex-direction: column; }
172
+ .opf-export .opf-export-group + .opf-export-group {
173
+ margin-top: 4px;
174
+ border-top: 1px solid var(--opf-ui-border);
175
+ }
176
+ .opf-export .opf-export-group-label {
177
+ padding: 6px 10px 4px;
178
+ font: 500 10.5px/1.4 var(--opf-ui-mono);
179
+ letter-spacing: 0.08em;
180
+ text-transform: uppercase;
181
+ color: var(--opf-ui-muted-fg);
182
+ }
183
+ .opf-export .opf-export-group + .opf-export-group .opf-export-group-label { padding-top: 8px; }
184
+
185
+ .opf-export .opf-export-item {
186
+ display: flex;
187
+ align-items: center;
188
+ gap: 10px;
189
+ width: 100%;
190
+ padding: 7px 10px;
191
+ border: 0;
192
+ border-radius: var(--opf-ui-radius-sm);
193
+ background: transparent;
194
+ text-align: left;
195
+ font-size: 13px;
196
+ font-weight: 500;
197
+ cursor: pointer;
198
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease);
199
+ }
200
+ .opf-export .opf-export-item .opf-icon { color: var(--opf-ui-accent-strong); }
201
+ .opf-export .opf-export-item-label { flex: 1; min-width: 0; }
202
+ .opf-export .opf-export-item-meta {
203
+ font: 400 11px/1.4 var(--opf-ui-mono);
204
+ color: var(--opf-ui-muted-fg);
205
+ }
206
+ .opf-export .opf-export-item:hover { background: var(--opf-ui-muted); }
207
+ .opf-export .opf-export-item:focus-visible { background: var(--opf-ui-muted); }
208
+ .opf-export .opf-export-item[aria-disabled="true"] { cursor: not-allowed; }
209
+ .opf-export .opf-export-item[aria-disabled="true"] > * { opacity: 0.5; }
210
+ .opf-export .opf-export-item[aria-disabled="true"]:hover { background: transparent; }
211
+
212
+ /* ---- the bottom sheet -------------------------------------------------------------------------------------------------------------------- */
213
+ .opf-export .opf-export-scrim {
214
+ position: fixed;
215
+ inset: 0;
216
+ z-index: 50;
217
+ background: color-mix(in srgb, var(--opf-ui-fg) 32%, transparent);
218
+ }
219
+ .opf-export .opf-export-sheet {
220
+ position: fixed;
221
+ left: 0;
222
+ right: 0;
223
+ bottom: 0;
224
+ z-index: 51;
225
+ max-height: 85vh;
226
+ overflow: auto;
227
+ padding: 8px 8px max(20px, env(safe-area-inset-bottom));
228
+ background: var(--opf-ui-surface);
229
+ border-top: 1px solid var(--opf-ui-border);
230
+ border-radius: var(--opf-ui-radius-lg) var(--opf-ui-radius-lg) 0 0;
231
+ box-shadow: var(--opf-ui-shadow-pop);
232
+ }
233
+ .opf-export .opf-export-handle {
234
+ width: 36px;
235
+ height: 4px;
236
+ margin: 2px auto 10px;
237
+ border-radius: 2px;
238
+ background: var(--opf-ui-border-strong);
239
+ }
240
+ .opf-export .opf-export-sheet-head { display: flex; align-items: center; padding: 0 8px 6px; }
241
+ .opf-export .opf-export-sheet-title { font-size: 15px; font-weight: 600; }
242
+ .opf-export .opf-export-close {
243
+ display: grid;
244
+ place-items: center;
245
+ width: 40px;
246
+ height: 40px;
247
+ margin-left: auto;
248
+ border: 0;
249
+ border-radius: var(--opf-ui-radius);
250
+ background: transparent;
251
+ color: var(--opf-ui-muted-fg);
252
+ cursor: pointer;
253
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease);
254
+ }
255
+ .opf-export .opf-export-close:hover { background: var(--opf-ui-muted); color: var(--opf-ui-fg); }
256
+ .opf-export[data-mode="sheet"] .opf-export-sheet .opf-export-item { gap: 12px; min-height: 44px; padding: 0 12px; font-size: 14px; border-radius: var(--opf-ui-radius); }
257
+ .opf-export .opf-export-sheet .opf-export-group-label { padding: 6px 12px 4px; }
258
+ .opf-export .opf-export-sheet .opf-export-group + .opf-export-group .opf-export-group-label { padding-top: 10px; }
259
+
260
+ /* ---- density ----------------------------------------------------------------------------------------------------------------------------- */
261
+ .opf-export[data-density="touch"] .opf-export-trigger { height: max(var(--opf-ui-control-h), 40px); }
262
+ .opf-export[data-density="touch"] .opf-export-item { min-height: 40px; }
263
+
264
+ /* ---- progress, result and notes ----------------------------------------------------------------------------------------------------- */
265
+ .opf-export .opf-export-status {
266
+ width: 300px;
267
+ max-width: calc(100vw - 16px);
268
+ padding: 10px 12px;
269
+ border-radius: var(--opf-ui-radius-md);
270
+ z-index: 30;
271
+ }
272
+ .opf-export .opf-export-status-row { display: flex; align-items: flex-start; gap: 8px; }
273
+ .opf-export .opf-export-status-icon { display: inline-flex; padding-top: 2px; }
274
+ .opf-export .opf-export-status-icon:empty { display: none; }
275
+ .opf-export .opf-export-status[data-state="success"] .opf-export-status-icon { color: var(--opf-ui-success); }
276
+ .opf-export .opf-export-status[data-state="error"] .opf-export-status-icon { color: var(--opf-ui-danger); }
277
+ .opf-export .opf-export-status-text {
278
+ flex: 1;
279
+ min-width: 0;
280
+ margin: 0;
281
+ font-size: 12.5px;
282
+ overflow-wrap: anywhere;
283
+ }
284
+ .opf-export .opf-export-status[data-state="error"] .opf-export-status-text { color: var(--opf-ui-danger); }
285
+ .opf-export .opf-export-status[data-state="busy"] .opf-export-status-text,
286
+ .opf-export .opf-export-status[data-state="cancelled"] .opf-export-status-text { color: var(--opf-ui-muted-fg); }
287
+ .opf-export .opf-export-status-action {
288
+ flex: none;
289
+ height: 24px;
290
+ padding: 0 8px;
291
+ border: 0;
292
+ border-radius: var(--opf-ui-radius-sm);
293
+ background: transparent;
294
+ color: var(--opf-ui-accent-strong);
295
+ font-size: 12px;
296
+ font-weight: 500;
297
+ cursor: pointer;
298
+ transition: background-color var(--opf-ui-ease);
299
+ }
300
+ .opf-export .opf-export-status-action:hover { background: var(--opf-ui-muted); }
301
+
302
+ .opf-export .opf-export-progress {
303
+ display: block;
304
+ width: 100%;
305
+ height: 4px;
306
+ margin-top: 8px;
307
+ border: 0;
308
+ border-radius: 2px;
309
+ appearance: none;
310
+ -webkit-appearance: none;
311
+ overflow: hidden;
312
+ background: var(--opf-ui-muted);
313
+ color: var(--opf-ui-accent);
314
+ }
315
+ .opf-export .opf-export-progress::-webkit-progress-bar { background: var(--opf-ui-muted); }
316
+ .opf-export .opf-export-progress::-webkit-progress-value { background: var(--opf-ui-accent); }
317
+ .opf-export .opf-export-progress::-moz-progress-bar { background: var(--opf-ui-accent); }
318
+
319
+ .opf-export .opf-export-notes {
320
+ max-height: 140px;
321
+ margin: 8px 0 0;
322
+ padding: 8px 0 0 18px;
323
+ overflow: auto;
324
+ border-top: 1px solid var(--opf-ui-border);
325
+ font-size: 12px;
326
+ color: var(--opf-ui-warn);
327
+ overflow-wrap: anywhere;
328
+ }
329
+ .opf-export .opf-export-notes li + li { margin-top: 4px; }
330
+
331
+ /* The live region is for assistive technology only. */
332
+ .opf-export .opf-export-live {
333
+ position: absolute;
334
+ width: 1px;
335
+ height: 1px;
336
+ margin: -1px;
337
+ padding: 0;
338
+ overflow: hidden;
339
+ clip: rect(0 0 0 0);
340
+ clip-path: inset(50%);
341
+ white-space: nowrap;
342
+ border: 0;
343
+ }
344
+
345
+ /* On a phone the status sits at the bottom, where the sheet was. */
346
+ .opf-export[data-mode="sheet"] .opf-export-status {
347
+ position: fixed;
348
+ top: auto;
349
+ left: 8px;
350
+ right: 8px;
351
+ bottom: max(8px, env(safe-area-inset-bottom));
352
+ width: auto;
353
+ max-width: none;
354
+ }
355
+
356
+ @media (prefers-reduced-motion: reduce) {
357
+ .opf-export *,
358
+ .opf-export *::before,
359
+ .opf-export *::after { transition: none !important; animation: none !important; }
360
+ }
361
+
362
+ /* handoff.css */
363
+ /* RR-98: the agent handoff dialog (src/agent-handoff-dialog.js). Only --opf-ui-* tokens, no color literals (test/styles.mjs). */
364
+ .opf-handoff,
365
+ .opf-handoff *,
366
+ .opf-handoff *::before,
367
+ .opf-handoff *::after { box-sizing: border-box; }
368
+ .opf-handoff [hidden] { display: none !important; }
369
+
370
+ .opf-handoff {
371
+ position: fixed;
372
+ inset: 0;
373
+ z-index: 60;
374
+ display: grid;
375
+ grid-template-columns: minmax(0, 680px);
376
+ justify-content: center;
377
+ align-content: center;
378
+ padding: 16px;
379
+ background: color-mix(in srgb, var(--opf-ui-fg) 32%, transparent);
380
+ font-family: var(--opf-ui-font);
381
+ font-size: 13px;
382
+ line-height: 1.5;
383
+ color: var(--opf-ui-fg);
384
+ }
385
+ :where(.opf-handoff button, .opf-handoff textarea) { font: inherit; color: inherit; margin: 0; }
386
+ .opf-handoff button:focus-visible,
387
+ .opf-handoff textarea:focus-visible {
388
+ outline: 2px solid var(--opf-ui-ring);
389
+ outline-offset: 2px;
390
+ }
391
+
392
+ .opf-handoff .opf-handoff-dialog {
393
+ display: flex;
394
+ flex-direction: column;
395
+ width: 100%;
396
+ max-height: min(760px, calc(100vh - 32px));
397
+ overflow: hidden;
398
+ background: var(--opf-ui-surface);
399
+ border: 1px solid var(--opf-ui-border);
400
+ border-radius: var(--opf-ui-radius-lg);
401
+ box-shadow: var(--opf-ui-shadow-pop);
402
+ }
403
+ .opf-handoff .opf-handoff-dialog:focus { outline: none; }
404
+
405
+ .opf-handoff .opf-handoff-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 18px 14px 20px; }
406
+ .opf-handoff .opf-handoff-intro { flex: 1; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
407
+ .opf-handoff .opf-handoff-title { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
408
+ .opf-handoff .opf-handoff-description { margin: 0; line-height: 1.55; color: var(--opf-ui-muted-fg); text-wrap: pretty; }
409
+ .opf-handoff .opf-handoff-description code,
410
+ .opf-handoff .opf-handoff-note code {
411
+ font: 12px var(--opf-ui-mono);
412
+ color: var(--opf-ui-fg);
413
+ }
414
+ .opf-handoff .opf-handoff-x {
415
+ display: grid;
416
+ place-items: center;
417
+ flex: none;
418
+ width: 30px;
419
+ height: 30px;
420
+ border: 0;
421
+ border-radius: var(--opf-ui-radius);
422
+ background: transparent;
423
+ color: var(--opf-ui-muted-fg);
424
+ cursor: pointer;
425
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease);
426
+ }
427
+ .opf-handoff .opf-handoff-x:hover { background: var(--opf-ui-muted); color: var(--opf-ui-fg); }
428
+
429
+ /* ---- the target switch ---------------------------------------------------------------------------------------------------------------- */
430
+ .opf-handoff .opf-handoff-targets { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 0 20px 12px; }
431
+ .opf-handoff .opf-handoff-render { margin-right: 2px; font-size: 12px; color: var(--opf-ui-muted-fg); }
432
+ .opf-handoff .opf-handoff-segments { display: flex; flex-wrap: wrap; gap: 8px; }
433
+ .opf-handoff .opf-handoff-target {
434
+ display: inline-flex;
435
+ align-items: center;
436
+ height: 28px;
437
+ padding: 0 10px;
438
+ border: 1px solid var(--opf-ui-border);
439
+ border-radius: 999px;
440
+ background: transparent;
441
+ color: var(--opf-ui-muted-fg);
442
+ font-size: 12.5px;
443
+ font-weight: 500;
444
+ cursor: pointer;
445
+ transition: background-color var(--opf-ui-ease), border-color var(--opf-ui-ease), color var(--opf-ui-ease);
446
+ }
447
+ .opf-handoff .opf-handoff-target:hover { background: var(--opf-ui-muted); color: var(--opf-ui-fg); }
448
+ .opf-handoff .opf-handoff-target[aria-checked="true"] {
449
+ border-color: color-mix(in srgb, var(--opf-ui-accent) 35%, transparent);
450
+ background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent);
451
+ color: var(--opf-ui-accent-strong);
452
+ }
453
+
454
+ /* ---- the prompt ------------------------------------------------------------------------------------------------------------------------- */
455
+ .opf-handoff .opf-handoff-box {
456
+ display: flex;
457
+ flex-direction: column;
458
+ flex: 1 1 auto;
459
+ min-height: 0;
460
+ margin: 0 20px;
461
+ overflow: hidden;
462
+ background: var(--opf-ui-code-bg);
463
+ border: 1px solid var(--opf-ui-code-border);
464
+ border-radius: var(--opf-ui-radius-md);
465
+ }
466
+ .opf-handoff .opf-handoff-box-head {
467
+ display: flex;
468
+ flex: none;
469
+ align-items: center;
470
+ justify-content: space-between;
471
+ gap: 12px;
472
+ height: 34px;
473
+ padding: 0 12px;
474
+ border-bottom: 1px solid var(--opf-ui-code-border);
475
+ font: 500 12px var(--opf-ui-mono);
476
+ }
477
+ .opf-handoff .opf-handoff-count { font-weight: 400; color: var(--opf-ui-muted-fg); }
478
+ .opf-handoff .opf-handoff-prompt {
479
+ display: block;
480
+ flex: 1 1 auto;
481
+ width: 100%;
482
+ min-height: 220px;
483
+ padding: 12px 14px;
484
+ border: 0;
485
+ border-radius: 0;
486
+ background: transparent;
487
+ color: var(--opf-ui-fg);
488
+ font: 400 12.5px/1.6 var(--opf-ui-mono);
489
+ white-space: pre-wrap;
490
+ resize: none;
491
+ }
492
+ .opf-handoff .opf-handoff-prompt:focus-visible { outline-offset: -2px; }
493
+ .opf-handoff .opf-handoff-note { margin: 8px 20px 0; font-size: 12px; line-height: 1.5; color: var(--opf-ui-muted-fg); }
494
+
495
+ /* ---- the footer --------------------------------------------------------------------------------------------------------------------------- */
496
+ .opf-handoff .opf-handoff-foot {
497
+ display: flex;
498
+ flex: none;
499
+ align-items: center;
500
+ justify-content: flex-end;
501
+ flex-wrap: wrap;
502
+ gap: 8px;
503
+ margin-top: 16px;
504
+ padding: 12px 20px;
505
+ border-top: 1px solid var(--opf-ui-border);
506
+ background: var(--opf-ui-muted-2);
507
+ }
508
+ .opf-handoff .opf-handoff-button {
509
+ display: inline-flex;
510
+ flex: none;
511
+ align-items: center;
512
+ justify-content: center;
513
+ gap: 6px;
514
+ height: var(--opf-ui-control-h);
515
+ padding: 0 12px;
516
+ border: 1px solid var(--opf-ui-border);
517
+ border-radius: var(--opf-ui-radius);
518
+ background: var(--opf-ui-surface);
519
+ font-size: 13px;
520
+ font-weight: 500;
521
+ white-space: nowrap;
522
+ cursor: pointer;
523
+ transition: background-color var(--opf-ui-ease), border-color var(--opf-ui-ease), color var(--opf-ui-ease), opacity var(--opf-ui-ease);
524
+ }
525
+ .opf-handoff .opf-handoff-button:hover { border-color: var(--opf-ui-border-strong); }
526
+ .opf-handoff .opf-handoff-close {
527
+ margin-right: auto;
528
+ border-color: transparent;
529
+ background: transparent;
530
+ color: var(--opf-ui-muted-fg);
531
+ }
532
+ .opf-handoff .opf-handoff-close:hover { border-color: transparent; background: var(--opf-ui-muted); color: var(--opf-ui-fg); }
533
+ .opf-handoff .opf-handoff-button[data-primary] {
534
+ min-width: 124px;
535
+ border-color: var(--opf-ui-accent);
536
+ background: var(--opf-ui-accent);
537
+ color: var(--opf-ui-accent-fg);
538
+ }
539
+ .opf-handoff .opf-handoff-button[data-primary]:hover { opacity: 0.92; border-color: var(--opf-ui-accent); }
540
+
541
+ .opf-handoff .opf-handoff-live {
542
+ position: absolute;
543
+ width: 1px;
544
+ height: 1px;
545
+ margin: -1px;
546
+ padding: 0;
547
+ overflow: hidden;
548
+ clip: rect(0 0 0 0);
549
+ clip-path: inset(50%);
550
+ white-space: nowrap;
551
+ border: 0;
552
+ }
553
+
554
+ /* ---- density and small screens ----------------------------------------------------------------------------------------------------- */
555
+ .opf-handoff[data-density="touch"] .opf-handoff-button { height: max(var(--opf-ui-control-h), 40px); }
556
+ .opf-handoff[data-density="touch"] .opf-handoff-target { height: 40px; padding: 0 14px; }
557
+ .opf-handoff[data-density="touch"] .opf-handoff-x { width: 40px; height: 40px; }
558
+ @media (max-width: 520px) {
559
+ .opf-handoff { padding: 8px; }
560
+ .opf-handoff .opf-handoff-head { padding: 14px 10px 12px 14px; }
561
+ .opf-handoff .opf-handoff-targets,
562
+ .opf-handoff .opf-handoff-foot { padding-left: 14px; padding-right: 14px; }
563
+ .opf-handoff .opf-handoff-box,
564
+ .opf-handoff .opf-handoff-note { margin-left: 14px; margin-right: 14px; }
565
+ .opf-handoff .opf-handoff-prompt { min-height: 160px; }
566
+ }
567
+ @media (prefers-reduced-motion: reduce) {
568
+ .opf-handoff *,
569
+ .opf-handoff *::before,
570
+ .opf-handoff *::after { transition: none !important; animation: none !important; }
571
+ }
572
+
573
+ /* navigator.css */
574
+ /* Slide navigator (RR-98). Uses only --opf-ui-* tokens. */
575
+ .opf-nav {
576
+ display: inline-flex;
577
+ align-items: center;
578
+ gap: 4px;
579
+ color: var(--opf-ui-muted-fg);
580
+ font-family: var(--opf-ui-font);
581
+ }
582
+ .opf-nav-button {
583
+ display: inline-grid;
584
+ place-items: center;
585
+ box-sizing: border-box;
586
+ width: var(--opf-ui-control-h);
587
+ height: var(--opf-ui-control-h);
588
+ min-height: 0;
589
+ padding: 0;
590
+ border: 0;
591
+ border-radius: var(--opf-ui-radius);
592
+ background: transparent;
593
+ color: inherit;
594
+ font: inherit;
595
+ cursor: pointer;
596
+ transition: color var(--opf-ui-ease), background-color var(--opf-ui-ease);
597
+ }
598
+ .opf-nav[data-density="touch"] .opf-nav-button {
599
+ width: 40px;
600
+ height: 40px;
601
+ }
602
+ .opf-nav-button:hover:not(:disabled) {
603
+ background: var(--opf-ui-muted);
604
+ color: var(--opf-ui-fg);
605
+ }
606
+ .opf-nav-button:disabled {
607
+ opacity: 0.4;
608
+ cursor: default;
609
+ }
610
+ .opf-nav-button:focus-visible {
611
+ outline: 2px solid var(--opf-ui-ring);
612
+ outline-offset: 2px;
613
+ }
614
+ .opf-nav-icon {
615
+ width: 18px;
616
+ height: 18px;
617
+ }
618
+ .opf-nav[data-density="touch"] .opf-nav-icon {
619
+ width: 20px;
620
+ height: 20px;
621
+ }
622
+ .opf-nav-counter {
623
+ min-width: 64px;
624
+ text-align: center;
625
+ font: 500 12px/1 var(--opf-ui-mono);
626
+ font-variant-numeric: tabular-nums;
627
+ color: var(--opf-ui-fg);
628
+ }
629
+ @media (prefers-reduced-motion: reduce) {
630
+ .opf-nav-button {
631
+ transition: none;
632
+ }
633
+ }
634
+
635
+ /* panels.css */
636
+ /*
637
+ * The existing editor panels, styled to the design system with only the --opf-ui-* tokens (RR-98).
638
+ *
639
+ * Specificity: the find, review, crop and data-grid components still inject a small fallback stylesheet of their own, so a host that
640
+ * never loads styles.css looks as it did before. Rules here for those four start with `:root`, which wins over the injected rules
641
+ * whichever <style> comes last in the document. Dimensions and touch rules of those components are kept; this file changes color,
642
+ * border, radius and type.
643
+ *
644
+ * Tints are color-mix() of an accent, warning or danger token at 6-16% over transparent, as the visual rules ask.
645
+ */
646
+
647
+ /* ---------------------------------------------------------------- shared controls */
648
+
649
+ :where(
650
+ .opf-design-controls,
651
+ .opf-review,
652
+ .opf-template-panel,
653
+ .opf-numbering-panel,
654
+ .opf-chart-options,
655
+ .opf-sm-dialog,
656
+ .opf-layout-dialog,
657
+ .opf-grid-dialog
658
+ ) {
659
+ font-family: var(--opf-ui-font);
660
+ color: var(--opf-ui-fg);
661
+ }
662
+
663
+ :where(
664
+ .opf-design-controls,
665
+ .opf-template-panel,
666
+ .opf-numbering-panel,
667
+ .opf-chart-options,
668
+ .opf-sm-dialog,
669
+ .opf-layout-dialog,
670
+ .opf-grid-dialog
671
+ )
672
+ :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"]), select, textarea) {
673
+ min-height: var(--opf-ui-control-h);
674
+ padding: 4px 8px;
675
+ font: 13px/1.4 var(--opf-ui-font);
676
+ color: var(--opf-ui-fg);
677
+ background: var(--opf-ui-surface);
678
+ border: 1px solid var(--opf-ui-border);
679
+ border-radius: var(--opf-ui-radius);
680
+ transition:
681
+ border-color var(--opf-ui-ease),
682
+ color var(--opf-ui-ease);
683
+ }
684
+
685
+ :where(
686
+ .opf-design-controls,
687
+ .opf-template-panel,
688
+ .opf-numbering-panel,
689
+ .opf-chart-options,
690
+ .opf-sm-dialog,
691
+ .opf-layout-dialog,
692
+ .opf-grid-dialog
693
+ )
694
+ :is(input, select, textarea):hover:not(:disabled) {
695
+ border-color: var(--opf-ui-border-strong);
696
+ }
697
+
698
+ :where(
699
+ .opf-design-controls,
700
+ .opf-template-panel,
701
+ .opf-numbering-panel,
702
+ .opf-chart-options,
703
+ .opf-sm-dialog,
704
+ .opf-layout-dialog,
705
+ .opf-grid-dialog
706
+ )
707
+ :is(input, select, textarea):focus-visible {
708
+ border-color: var(--opf-ui-ring);
709
+ outline: 2px solid var(--opf-ui-ring);
710
+ outline-offset: 2px;
711
+ }
712
+
713
+ :where(
714
+ .opf-design-controls,
715
+ .opf-template-panel,
716
+ .opf-numbering-panel,
717
+ .opf-chart-options,
718
+ .opf-sm-dialog,
719
+ .opf-layout-dialog,
720
+ .opf-grid-dialog
721
+ )
722
+ :is(input[type="checkbox"], input[type="radio"], input[type="range"]) {
723
+ accent-color: var(--opf-ui-accent);
724
+ }
725
+
726
+ :where(
727
+ .opf-design-controls,
728
+ .opf-template-panel,
729
+ .opf-numbering-panel,
730
+ .opf-chart-options,
731
+ .opf-sm-dialog,
732
+ .opf-layout-dialog,
733
+ .opf-grid-dialog,
734
+ .opf-review
735
+ )
736
+ button:not([class*="opf-"]) {
737
+ display: inline-flex;
738
+ align-items: center;
739
+ justify-content: center;
740
+ gap: 6px;
741
+ min-height: var(--opf-ui-control-h);
742
+ padding: 0 12px;
743
+ font: 500 13px/1.2 var(--opf-ui-font);
744
+ color: var(--opf-ui-fg);
745
+ background: var(--opf-ui-surface);
746
+ border: 1px solid var(--opf-ui-border);
747
+ border-radius: var(--opf-ui-radius);
748
+ cursor: pointer;
749
+ transition:
750
+ background-color var(--opf-ui-ease),
751
+ border-color var(--opf-ui-ease),
752
+ color var(--opf-ui-ease);
753
+ }
754
+
755
+ :where(
756
+ .opf-design-controls,
757
+ .opf-template-panel,
758
+ .opf-numbering-panel,
759
+ .opf-chart-options,
760
+ .opf-sm-dialog,
761
+ .opf-layout-dialog,
762
+ .opf-grid-dialog,
763
+ .opf-review
764
+ )
765
+ button:not([class*="opf-"]):hover:not(:disabled) {
766
+ background: var(--opf-ui-muted);
767
+ border-color: var(--opf-ui-border-strong);
768
+ }
769
+
770
+ :where(
771
+ .opf-design-controls,
772
+ .opf-template-panel,
773
+ .opf-numbering-panel,
774
+ .opf-chart-options,
775
+ .opf-sm-dialog,
776
+ .opf-layout-dialog,
777
+ .opf-grid-dialog,
778
+ .opf-review
779
+ )
780
+ button:not([class*="opf-"]):disabled {
781
+ opacity: 0.45;
782
+ cursor: default;
783
+ }
784
+
785
+ :where(
786
+ .opf-design-controls,
787
+ .opf-template-panel,
788
+ .opf-numbering-panel,
789
+ .opf-chart-options,
790
+ .opf-sm-dialog,
791
+ .opf-layout-dialog,
792
+ .opf-grid-dialog,
793
+ .opf-review
794
+ )
795
+ button:not([class*="opf-"]).primary {
796
+ color: var(--opf-ui-accent-fg);
797
+ background: var(--opf-ui-accent);
798
+ border-color: var(--opf-ui-accent);
799
+ }
800
+
801
+ :where(
802
+ .opf-design-controls,
803
+ .opf-template-panel,
804
+ .opf-numbering-panel,
805
+ .opf-chart-options,
806
+ .opf-sm-dialog,
807
+ .opf-layout-dialog,
808
+ .opf-grid-dialog,
809
+ .opf-review
810
+ )
811
+ button:not([class*="opf-"]).primary:hover:not(:disabled) {
812
+ background: var(--opf-ui-accent);
813
+ border-color: var(--opf-ui-accent);
814
+ filter: brightness(1.08);
815
+ }
816
+
817
+ :where(
818
+ .opf-design-controls,
819
+ .opf-template-panel,
820
+ .opf-numbering-panel,
821
+ .opf-chart-options,
822
+ .opf-sm-dialog,
823
+ .opf-layout-dialog,
824
+ .opf-grid-dialog,
825
+ .opf-review
826
+ )
827
+ button:not([class*="opf-"]).quiet {
828
+ color: var(--opf-ui-muted-fg);
829
+ background: transparent;
830
+ border-color: transparent;
831
+ }
832
+
833
+ :where(
834
+ .opf-design-controls,
835
+ .opf-template-panel,
836
+ .opf-numbering-panel,
837
+ .opf-chart-options,
838
+ .opf-sm-dialog,
839
+ .opf-layout-dialog,
840
+ .opf-grid-dialog,
841
+ .opf-review
842
+ )
843
+ button:not([class*="opf-"]).quiet:hover:not(:disabled) {
844
+ color: var(--opf-ui-fg);
845
+ background: var(--opf-ui-muted);
846
+ border-color: transparent;
847
+ }
848
+
849
+ /* ---------------------------------------------------------------- design controls (opf-dc-*) */
850
+
851
+ .opf-design-controls {
852
+ display: block;
853
+ font-size: 13px;
854
+ }
855
+
856
+ .opf-dc-group {
857
+ border-top: 1px solid var(--opf-ui-border);
858
+ padding: 8px 0;
859
+ }
860
+
861
+ .opf-dc-group > summary {
862
+ padding: 5px 0;
863
+ font: 500 11px/1.4 var(--opf-ui-mono);
864
+ letter-spacing: 0.08em;
865
+ text-transform: uppercase;
866
+ color: var(--opf-ui-muted-fg);
867
+ cursor: pointer;
868
+ list-style-position: inside;
869
+ transition: color var(--opf-ui-ease);
870
+ }
871
+
872
+ .opf-dc-group > summary:hover,
873
+ .opf-dc-group[open] > summary {
874
+ color: var(--opf-ui-fg);
875
+ }
876
+
877
+ .opf-dc-body {
878
+ padding: 6px 0 4px;
879
+ }
880
+
881
+ .opf-dc-field {
882
+ display: flex;
883
+ flex-direction: column;
884
+ gap: 4px;
885
+ margin: 0 0 11px;
886
+ }
887
+
888
+ .opf-dc-field > label {
889
+ display: block;
890
+ margin: 0;
891
+ font-size: 12px;
892
+ font-weight: 500;
893
+ color: var(--opf-ui-fg);
894
+ }
895
+
896
+ .opf-dc-field input[type="text"],
897
+ .opf-dc-field input[type="number"],
898
+ .opf-dc-field input[type="url"] {
899
+ width: 100%;
900
+ }
901
+
902
+ .opf-dc-field select[multiple] {
903
+ padding: 2px;
904
+ }
905
+
906
+ .opf-dc-field input[type="file"] {
907
+ width: 100%;
908
+ min-height: 0;
909
+ padding: 0;
910
+ font-size: 11.5px;
911
+ color: var(--opf-ui-muted-fg);
912
+ background: transparent;
913
+ border: 0;
914
+ }
915
+
916
+ .opf-dc-check {
917
+ flex-direction: row;
918
+ flex-wrap: wrap;
919
+ align-items: center;
920
+ gap: 4px 8px;
921
+ }
922
+
923
+ .opf-dc-check > label {
924
+ font-weight: 400;
925
+ }
926
+
927
+ .opf-dc-check .opf-dc-help {
928
+ flex-basis: 100%;
929
+ }
930
+
931
+ .opf-dc-note {
932
+ font-weight: 400;
933
+ color: var(--opf-ui-muted-fg);
934
+ }
935
+
936
+ .opf-dc-help {
937
+ margin: 0;
938
+ font-size: 11.5px;
939
+ line-height: 1.55;
940
+ color: var(--opf-ui-muted-fg);
941
+ }
942
+
943
+ .opf-dc-fieldset {
944
+ margin: 0 0 10px;
945
+ padding: 6px 10px 2px;
946
+ border: 1px solid var(--opf-ui-border);
947
+ border-radius: var(--opf-ui-radius);
948
+ }
949
+
950
+ .opf-dc-fieldset > legend {
951
+ padding: 0 4px;
952
+ font-size: 11.5px;
953
+ font-weight: 600;
954
+ color: var(--opf-ui-muted-fg);
955
+ }
956
+
957
+ .opf-dc-actions {
958
+ display: flex;
959
+ flex-wrap: wrap;
960
+ gap: 8px;
961
+ margin: 0 0 11px;
962
+ }
963
+
964
+ .opf-dc-actions-block {
965
+ display: flex;
966
+ flex-direction: column;
967
+ gap: 8px;
968
+ margin: 0 0 11px;
969
+ }
970
+
971
+ .opf-dc-actions-block[hidden],
972
+ .opf-dc-action[hidden] {
973
+ display: none;
974
+ }
975
+
976
+ .opf-dc-action {
977
+ display: flex;
978
+ flex-direction: column;
979
+ gap: 3px;
980
+ }
981
+
982
+ .opf-dc-action > button {
983
+ align-self: flex-start;
984
+ }
985
+
986
+ .opf-dc-action > button:disabled {
987
+ opacity: 0.55;
988
+ cursor: not-allowed;
989
+ }
990
+
991
+ .opf-dc-status {
992
+ min-height: 1.2em;
993
+ margin: 10px 0 0;
994
+ font: 11.5px/1.4 var(--opf-ui-mono);
995
+ color: var(--opf-ui-success);
996
+ }
997
+
998
+ .opf-dc-error {
999
+ margin: 6px 0 0;
1000
+ font-size: 11.5px;
1001
+ color: var(--opf-ui-danger);
1002
+ }
1003
+
1004
+ .opf-dc-error:empty,
1005
+ .opf-dc-warnings:empty {
1006
+ display: none;
1007
+ }
1008
+
1009
+ .opf-dc-warnings {
1010
+ margin: 0 0 10px;
1011
+ padding-left: 18px;
1012
+ font-size: 11.5px;
1013
+ color: var(--opf-ui-warn);
1014
+ }
1015
+
1016
+ .opf-dc-cell {
1017
+ margin-top: 10px;
1018
+ padding-top: 10px;
1019
+ border-top: 1px dashed var(--opf-ui-border);
1020
+ }
1021
+
1022
+ .opf-dc-cluster {
1023
+ margin: 0 0 8px;
1024
+ }
1025
+
1026
+ .opf-dc-summary {
1027
+ margin: 0 0 10px;
1028
+ padding-left: 18px;
1029
+ font-size: 11.5px;
1030
+ color: var(--opf-ui-muted-fg);
1031
+ }
1032
+
1033
+ .opf-dc-stop {
1034
+ margin-top: 4px;
1035
+ padding-top: 8px;
1036
+ border-top: 1px dashed var(--opf-ui-border);
1037
+ }
1038
+
1039
+ .opf-dc-stop button {
1040
+ margin-bottom: 8px;
1041
+ }
1042
+
1043
+ .opf-dc-variants {
1044
+ display: grid;
1045
+ grid-template-columns: repeat(4, 1fr);
1046
+ gap: 6px;
1047
+ margin: 0 0 8px;
1048
+ }
1049
+
1050
+ .opf-dc-variant {
1051
+ display: flex;
1052
+ flex-direction: column;
1053
+ align-items: flex-start;
1054
+ justify-content: space-between;
1055
+ gap: 6px;
1056
+ min-height: 56px;
1057
+ padding: 6px;
1058
+ font: inherit;
1059
+ color: var(--opf-ui-fg);
1060
+ background: var(--opf-ui-surface);
1061
+ border: 1px solid var(--opf-ui-border);
1062
+ border-radius: var(--opf-ui-radius-md);
1063
+ cursor: pointer;
1064
+ transition:
1065
+ background-color var(--opf-ui-ease),
1066
+ border-color var(--opf-ui-ease);
1067
+ }
1068
+
1069
+ .opf-dc-variant:hover:not(:disabled) {
1070
+ background: var(--opf-ui-muted);
1071
+ border-color: var(--opf-ui-border-strong);
1072
+ }
1073
+
1074
+ .opf-dc-variant[aria-checked="true"] {
1075
+ color: var(--opf-ui-accent-strong);
1076
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
1077
+ border-color: var(--opf-ui-accent);
1078
+ outline: 2px solid var(--opf-ui-accent);
1079
+ outline-offset: -1px;
1080
+ }
1081
+
1082
+ .opf-dc-variant-text {
1083
+ font-size: 15px;
1084
+ font-weight: 700;
1085
+ line-height: 1;
1086
+ }
1087
+
1088
+ .opf-dc-variant-chips {
1089
+ display: flex;
1090
+ gap: 3px;
1091
+ }
1092
+
1093
+ .opf-dc-variant-chip {
1094
+ width: 9px;
1095
+ height: 9px;
1096
+ border: 1px solid var(--opf-ui-border-strong);
1097
+ border-radius: 50%;
1098
+ }
1099
+
1100
+ /* ---------------------------------------------------------------- review panel (opf-review-*) */
1101
+
1102
+ :root .opf-review {
1103
+ font-size: 12px;
1104
+ color: var(--opf-ui-fg);
1105
+ }
1106
+
1107
+ :root .opf-review-head h2 {
1108
+ font-size: 13px;
1109
+ font-weight: 600;
1110
+ }
1111
+
1112
+ :root .opf-review-counts,
1113
+ :root .opf-review-meta,
1114
+ :root .opf-review-help,
1115
+ :root .opf-review-empty {
1116
+ font-family: var(--opf-ui-mono);
1117
+ font-size: 11.5px;
1118
+ color: var(--opf-ui-muted-fg);
1119
+ }
1120
+
1121
+ :root .opf-review-category-title {
1122
+ font: 500 11px/1.4 var(--opf-ui-mono);
1123
+ letter-spacing: 0.08em;
1124
+ text-transform: uppercase;
1125
+ color: var(--opf-ui-muted-fg);
1126
+ }
1127
+
1128
+ :root .opf-review-item {
1129
+ border-top: 1px solid var(--opf-ui-border);
1130
+ }
1131
+
1132
+ :root .opf-review-item[aria-current="true"] {
1133
+ background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent);
1134
+ }
1135
+
1136
+ :root .opf-review-item[aria-current="true"] .opf-review-goto {
1137
+ color: var(--opf-ui-accent-strong);
1138
+ }
1139
+
1140
+ :root .opf-review-goto {
1141
+ border-radius: var(--opf-ui-radius-sm);
1142
+ transition:
1143
+ background-color var(--opf-ui-ease),
1144
+ color var(--opf-ui-ease);
1145
+ }
1146
+
1147
+ :root .opf-review-goto:hover {
1148
+ background: var(--opf-ui-muted);
1149
+ }
1150
+
1151
+ :root .opf-review-goto:focus-visible,
1152
+ :root .opf-review-fix:focus-visible,
1153
+ :root .opf-review-alt input:focus-visible {
1154
+ outline: 2px solid var(--opf-ui-ring);
1155
+ outline-offset: 2px;
1156
+ }
1157
+
1158
+ :root .opf-review-sev {
1159
+ font: 500 10.5px/16px var(--opf-ui-mono);
1160
+ letter-spacing: 0.04em;
1161
+ border-radius: var(--opf-ui-radius-sm);
1162
+ background: color-mix(in srgb, currentColor 8%, transparent);
1163
+ }
1164
+
1165
+ :root .opf-review-item[data-severity="error"] .opf-review-sev {
1166
+ color: var(--opf-ui-danger);
1167
+ }
1168
+
1169
+ :root .opf-review-item[data-severity="warning"] .opf-review-sev {
1170
+ color: var(--opf-ui-warn);
1171
+ }
1172
+
1173
+ :root .opf-review-item[data-severity="info"] .opf-review-sev {
1174
+ color: var(--opf-ui-accent-strong);
1175
+ }
1176
+
1177
+ :root .opf-review-fix {
1178
+ min-height: 0;
1179
+ padding: 3px 8px;
1180
+ font: 500 12px/1.3 var(--opf-ui-font);
1181
+ color: var(--opf-ui-fg);
1182
+ background: var(--opf-ui-surface);
1183
+ border: 1px solid var(--opf-ui-border);
1184
+ border-radius: var(--opf-ui-radius);
1185
+ }
1186
+
1187
+ :root .opf-review-fix:hover:not(:disabled) {
1188
+ background: var(--opf-ui-muted);
1189
+ border-color: var(--opf-ui-border-strong);
1190
+ }
1191
+
1192
+ :root .opf-review-fix.quiet {
1193
+ color: var(--opf-ui-muted-fg);
1194
+ background: none;
1195
+ border-color: transparent;
1196
+ }
1197
+
1198
+ :root .opf-review-fix.quiet:hover:not(:disabled) {
1199
+ color: var(--opf-ui-fg);
1200
+ background: none;
1201
+ }
1202
+
1203
+ :root .opf-review-alt input {
1204
+ color: var(--opf-ui-fg);
1205
+ background: var(--opf-ui-surface);
1206
+ border: 1px solid var(--opf-ui-border);
1207
+ border-radius: var(--opf-ui-radius);
1208
+ }
1209
+
1210
+ :root .opf-review-error {
1211
+ color: var(--opf-ui-danger);
1212
+ }
1213
+
1214
+ /* ---------------------------------------------------------------- slide manager (opf-slides, opf-sm-*, opf-menu) */
1215
+
1216
+ .opf-slides .slide-card {
1217
+ position: relative;
1218
+ display: grid;
1219
+ grid-template-columns: 18px minmax(0, 1fr);
1220
+ align-items: start;
1221
+ justify-content: start;
1222
+ gap: 8px;
1223
+ width: 100%;
1224
+ margin: 0 0 5px;
1225
+ padding: 8px 7px;
1226
+ font: inherit;
1227
+ text-align: left;
1228
+ white-space: normal;
1229
+ color: var(--opf-ui-muted-fg);
1230
+ background: transparent;
1231
+ border: 1px solid transparent;
1232
+ border-radius: var(--opf-ui-radius-md);
1233
+ cursor: pointer;
1234
+ transition:
1235
+ background-color var(--opf-ui-ease),
1236
+ border-color var(--opf-ui-ease),
1237
+ color var(--opf-ui-ease);
1238
+ }
1239
+
1240
+ .opf-slides .slide-card:hover {
1241
+ color: var(--opf-ui-fg);
1242
+ background: var(--opf-ui-muted);
1243
+ }
1244
+
1245
+ .opf-slides .slide-card[data-selected="true"] {
1246
+ background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent);
1247
+ border-color: color-mix(in srgb, var(--opf-ui-accent) 30%, transparent);
1248
+ }
1249
+
1250
+ .opf-slides .slide-card[aria-current="true"] {
1251
+ color: var(--opf-ui-accent-strong);
1252
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
1253
+ border-color: color-mix(in srgb, var(--opf-ui-accent) 40%, transparent);
1254
+ }
1255
+
1256
+ .opf-slides .slide-card[aria-current="true"][data-selected="true"] {
1257
+ background: color-mix(in srgb, var(--opf-ui-accent) 14%, transparent);
1258
+ }
1259
+
1260
+ .opf-slides .slide-card[data-hidden="true"] .thumbnail {
1261
+ opacity: 0.55;
1262
+ }
1263
+
1264
+ .opf-slides .slide-card.is-drag-source {
1265
+ opacity: 0.45;
1266
+ }
1267
+
1268
+ .opf-slides .slide-card:focus-visible,
1269
+ .section-toggle:focus-visible,
1270
+ .section-more:focus-visible,
1271
+ .slide-tool:focus-visible,
1272
+ .outline-input:focus-visible {
1273
+ outline: 2px solid var(--opf-ui-ring);
1274
+ outline-offset: 2px;
1275
+ }
1276
+
1277
+ .opf-slides .thumbnail-number {
1278
+ padding-top: 3px;
1279
+ font: 10.5px/1.4 var(--opf-ui-mono);
1280
+ font-variant-numeric: tabular-nums;
1281
+ }
1282
+
1283
+ .opf-slides .thumbnail-content {
1284
+ min-width: 0;
1285
+ }
1286
+
1287
+ .opf-slides .thumbnail {
1288
+ display: flex;
1289
+ align-items: center;
1290
+ justify-content: center;
1291
+ aspect-ratio: 16 / 9;
1292
+ overflow: hidden;
1293
+ background: var(--opf-ui-surface);
1294
+ border: 1px solid var(--opf-ui-border);
1295
+ border-radius: var(--opf-ui-radius-sm);
1296
+ pointer-events: none;
1297
+ }
1298
+
1299
+ .opf-slides .thumbnail svg {
1300
+ display: block;
1301
+ width: 100%;
1302
+ height: auto;
1303
+ }
1304
+
1305
+ .opf-slides .slide-card[aria-current="true"] .thumbnail {
1306
+ border-color: var(--opf-ui-accent);
1307
+ box-shadow: 0 0 0 1px var(--opf-ui-accent);
1308
+ }
1309
+
1310
+ .opf-slides .thumbnail-title {
1311
+ display: block;
1312
+ margin-top: 7px;
1313
+ overflow: hidden;
1314
+ font-size: 11px;
1315
+ line-height: 1.5;
1316
+ font-weight: 500;
1317
+ text-overflow: ellipsis;
1318
+ white-space: nowrap;
1319
+ }
1320
+
1321
+ .slide-badge {
1322
+ display: inline-block;
1323
+ margin-top: 5px;
1324
+ padding: 0 6px;
1325
+ font: 500 10px/16px var(--opf-ui-mono);
1326
+ letter-spacing: 0.02em;
1327
+ color: var(--opf-ui-muted-fg);
1328
+ background: var(--opf-ui-muted);
1329
+ border-radius: var(--opf-ui-radius-sm);
1330
+ }
1331
+
1332
+ .slide-toolbar {
1333
+ display: flex;
1334
+ gap: 2px;
1335
+ margin: 0 11px 6px;
1336
+ padding: 0 0 0 2px;
1337
+ }
1338
+
1339
+ .slide-toolbar:empty {
1340
+ display: none;
1341
+ }
1342
+
1343
+ .slide-tool,
1344
+ .section-more {
1345
+ display: inline-flex;
1346
+ align-items: center;
1347
+ justify-content: center;
1348
+ padding: 0;
1349
+ color: var(--opf-ui-muted-fg);
1350
+ background: transparent;
1351
+ border: 0;
1352
+ border-radius: var(--opf-ui-radius);
1353
+ cursor: pointer;
1354
+ transition:
1355
+ background-color var(--opf-ui-ease),
1356
+ color var(--opf-ui-ease);
1357
+ }
1358
+
1359
+ .slide-tool {
1360
+ width: 30px;
1361
+ height: 28px;
1362
+ }
1363
+
1364
+ .section-more {
1365
+ width: 24px;
1366
+ height: 24px;
1367
+ }
1368
+
1369
+ .slide-tool:hover:not(:disabled),
1370
+ .section-more:hover {
1371
+ color: var(--opf-ui-fg);
1372
+ background: var(--opf-ui-muted);
1373
+ }
1374
+
1375
+ .slide-tool:disabled {
1376
+ opacity: 0.4;
1377
+ cursor: default;
1378
+ }
1379
+
1380
+ .slide-tool .icon,
1381
+ .section-more .icon {
1382
+ width: 16px;
1383
+ height: 16px;
1384
+ }
1385
+
1386
+ .slide-section {
1387
+ display: flex;
1388
+ align-items: center;
1389
+ gap: 2px;
1390
+ margin: 8px 0 4px;
1391
+ padding: 0 2px;
1392
+ }
1393
+
1394
+ .slide-section:first-child {
1395
+ margin-top: 0;
1396
+ }
1397
+
1398
+ .section-toggle {
1399
+ display: inline-flex;
1400
+ align-items: center;
1401
+ flex: 1;
1402
+ min-width: 0;
1403
+ justify-content: flex-start;
1404
+ gap: 6px;
1405
+ padding: 3px 4px;
1406
+ font: 500 11px/1.4 var(--opf-ui-mono);
1407
+ letter-spacing: 0.08em;
1408
+ text-transform: uppercase;
1409
+ text-align: left;
1410
+ color: var(--opf-ui-muted-fg);
1411
+ background: transparent;
1412
+ border: 0;
1413
+ border-radius: var(--opf-ui-radius);
1414
+ cursor: pointer;
1415
+ transition:
1416
+ background-color var(--opf-ui-ease),
1417
+ color var(--opf-ui-ease);
1418
+ }
1419
+
1420
+ .section-toggle:hover {
1421
+ color: var(--opf-ui-fg);
1422
+ background: var(--opf-ui-muted);
1423
+ }
1424
+
1425
+ .section-name {
1426
+ overflow: hidden;
1427
+ text-overflow: ellipsis;
1428
+ white-space: nowrap;
1429
+ }
1430
+
1431
+ .slide-section[data-unnamed="true"] .section-name {
1432
+ font-style: italic;
1433
+ }
1434
+
1435
+ .section-count,
1436
+ .section-caret {
1437
+ color: var(--opf-ui-muted-fg);
1438
+ }
1439
+
1440
+ .section-caret {
1441
+ width: 10px;
1442
+ }
1443
+
1444
+ .slide-section.drop-into {
1445
+ background: color-mix(in srgb, var(--opf-ui-accent) 12%, transparent);
1446
+ outline: 2px dashed var(--opf-ui-accent);
1447
+ outline-offset: -2px;
1448
+ border-radius: var(--opf-ui-radius);
1449
+ }
1450
+
1451
+ .opf-slides .slide-card.drop-before::before,
1452
+ .opf-slides .slide-card.drop-after::after {
1453
+ content: "";
1454
+ position: absolute;
1455
+ background: var(--opf-ui-accent);
1456
+ border-radius: 2px;
1457
+ pointer-events: none;
1458
+ }
1459
+
1460
+ .opf-slides[data-variant="navigator"] .slide-card.drop-before::before {
1461
+ left: 4px;
1462
+ right: 4px;
1463
+ top: -4px;
1464
+ height: 3px;
1465
+ }
1466
+
1467
+ .opf-slides[data-variant="navigator"] .slide-card.drop-after::after {
1468
+ left: 4px;
1469
+ right: 4px;
1470
+ bottom: -4px;
1471
+ height: 3px;
1472
+ }
1473
+
1474
+ .opf-slides[data-variant="sorter"] .slide-card.drop-before::before {
1475
+ top: 4px;
1476
+ bottom: 4px;
1477
+ left: -7px;
1478
+ width: 3px;
1479
+ }
1480
+
1481
+ .opf-slides[data-variant="sorter"] .slide-card.drop-after::after {
1482
+ top: 4px;
1483
+ bottom: 4px;
1484
+ right: -7px;
1485
+ width: 3px;
1486
+ }
1487
+
1488
+ .opf-drag-badge {
1489
+ position: fixed;
1490
+ top: -100px;
1491
+ left: -100px;
1492
+ padding: 4px 10px;
1493
+ font: 500 12px var(--opf-ui-font);
1494
+ color: var(--opf-ui-accent-fg);
1495
+ background: var(--opf-ui-accent);
1496
+ border-radius: var(--opf-ui-radius-lg);
1497
+ }
1498
+
1499
+ /* The sorter: the same cards in a grid. */
1500
+
1501
+ .slide-sorter {
1502
+ display: grid;
1503
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1504
+ gap: 18px 16px;
1505
+ align-content: start;
1506
+ }
1507
+
1508
+ .slide-sorter .slide-section {
1509
+ grid-column: 1 / -1;
1510
+ margin: 6px 0 -4px;
1511
+ }
1512
+
1513
+ .slide-sorter .slide-card {
1514
+ display: block;
1515
+ margin: 0;
1516
+ padding: 8px;
1517
+ background: var(--opf-ui-surface);
1518
+ border: 1px solid var(--opf-ui-border);
1519
+ border-radius: var(--opf-ui-radius-md);
1520
+ }
1521
+
1522
+ .slide-sorter .slide-card:hover {
1523
+ background: var(--opf-ui-muted-2);
1524
+ }
1525
+
1526
+ .slide-sorter .slide-card[data-selected="true"] {
1527
+ background: color-mix(in srgb, var(--opf-ui-accent) 8%, var(--opf-ui-surface));
1528
+ border-color: var(--opf-ui-accent);
1529
+ }
1530
+
1531
+ .slide-sorter .thumbnail-number {
1532
+ position: absolute;
1533
+ left: 12px;
1534
+ bottom: 11px;
1535
+ padding: 0;
1536
+ font-size: 11px;
1537
+ font-weight: 500;
1538
+ color: var(--opf-ui-muted-fg);
1539
+ }
1540
+
1541
+ .slide-sorter .thumbnail-title {
1542
+ margin-top: 8px;
1543
+ padding-left: 24px;
1544
+ font-size: 12px;
1545
+ }
1546
+
1547
+ .slide-sorter .slide-badge {
1548
+ position: absolute;
1549
+ top: 10px;
1550
+ right: 12px;
1551
+ }
1552
+
1553
+ /* The outline view. */
1554
+
1555
+ .opf-outline {
1556
+ max-width: 860px;
1557
+ margin: 0 auto;
1558
+ font-family: var(--opf-ui-font);
1559
+ color: var(--opf-ui-fg);
1560
+ }
1561
+
1562
+ .outline-toolbar {
1563
+ position: sticky;
1564
+ top: -20px;
1565
+ z-index: 2;
1566
+ display: flex;
1567
+ flex-wrap: wrap;
1568
+ gap: 6px;
1569
+ margin: 0 0 8px;
1570
+ padding: 8px 0;
1571
+ background: var(--opf-ui-bg);
1572
+ }
1573
+
1574
+ .outline-toolbar button {
1575
+ display: inline-flex;
1576
+ align-items: center;
1577
+ min-height: var(--opf-ui-control-h);
1578
+ padding: 0 12px;
1579
+ font: 500 13px/1.2 var(--opf-ui-font);
1580
+ color: var(--opf-ui-fg);
1581
+ background: var(--opf-ui-surface);
1582
+ border: 1px solid var(--opf-ui-border);
1583
+ border-radius: var(--opf-ui-radius);
1584
+ cursor: pointer;
1585
+ transition:
1586
+ background-color var(--opf-ui-ease),
1587
+ border-color var(--opf-ui-ease);
1588
+ }
1589
+
1590
+ .outline-toolbar button:hover:not(:disabled) {
1591
+ background: var(--opf-ui-muted);
1592
+ border-color: var(--opf-ui-border-strong);
1593
+ }
1594
+
1595
+ .outline-toolbar button:disabled {
1596
+ opacity: 0.45;
1597
+ cursor: default;
1598
+ }
1599
+
1600
+ .outline-help {
1601
+ margin: 0 0 14px;
1602
+ font-size: 11.5px;
1603
+ color: var(--opf-ui-muted-fg);
1604
+ }
1605
+
1606
+ .outline-list {
1607
+ margin: 0;
1608
+ padding: 0;
1609
+ list-style: none;
1610
+ }
1611
+
1612
+ .outline-row {
1613
+ display: flex;
1614
+ align-items: center;
1615
+ gap: 8px;
1616
+ padding: 1px 0 1px calc(var(--level, 0) * 26px);
1617
+ }
1618
+
1619
+ .outline-row[data-kind="slide"] {
1620
+ margin-top: 14px;
1621
+ }
1622
+
1623
+ .outline-row[data-kind="slide"]:first-child {
1624
+ margin-top: 0;
1625
+ }
1626
+
1627
+ .outline-number {
1628
+ display: inline-flex;
1629
+ align-items: center;
1630
+ justify-content: center;
1631
+ flex: 0 0 26px;
1632
+ height: 26px;
1633
+ font: 500 11px/1 var(--opf-ui-mono);
1634
+ color: var(--opf-ui-accent-strong);
1635
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
1636
+ border-radius: var(--opf-ui-radius-sm);
1637
+ }
1638
+
1639
+ .outline-bullet {
1640
+ flex: 0 0 12px;
1641
+ text-align: center;
1642
+ color: var(--opf-ui-muted-fg);
1643
+ }
1644
+
1645
+ .outline-input {
1646
+ flex: 1;
1647
+ min-width: 0;
1648
+ padding: 4px 8px;
1649
+ font: 13px/1.4 var(--opf-ui-font);
1650
+ color: var(--opf-ui-fg);
1651
+ background: transparent;
1652
+ border: 1px solid transparent;
1653
+ border-radius: var(--opf-ui-radius);
1654
+ transition:
1655
+ background-color var(--opf-ui-ease),
1656
+ border-color var(--opf-ui-ease);
1657
+ }
1658
+
1659
+ .outline-row[data-kind="slide"] .outline-input {
1660
+ font-size: 15px;
1661
+ font-weight: 600;
1662
+ }
1663
+
1664
+ .outline-row[data-kind="other"] .outline-input,
1665
+ .outline-input[readonly] {
1666
+ font-style: italic;
1667
+ color: var(--opf-ui-muted-fg);
1668
+ }
1669
+
1670
+ .outline-input:hover {
1671
+ background: var(--opf-ui-surface);
1672
+ border-color: var(--opf-ui-border);
1673
+ }
1674
+
1675
+ .outline-input:focus {
1676
+ background: var(--opf-ui-surface);
1677
+ border-color: var(--opf-ui-ring);
1678
+ }
1679
+
1680
+ .outline-section {
1681
+ margin: 18px 0 4px;
1682
+ padding: 3px 6px;
1683
+ font: 500 11px/1.4 var(--opf-ui-mono);
1684
+ letter-spacing: 0.08em;
1685
+ text-transform: uppercase;
1686
+ color: var(--opf-ui-muted-fg);
1687
+ border-bottom: 1px solid var(--opf-ui-border);
1688
+ }
1689
+
1690
+ /* The slide actions menu. */
1691
+
1692
+ .opf-menu {
1693
+ position: fixed;
1694
+ z-index: 1000;
1695
+ min-width: 220px;
1696
+ max-width: min(320px, 92vw);
1697
+ max-height: 80dvh;
1698
+ padding: 4px;
1699
+ overflow: auto;
1700
+ font-family: var(--opf-ui-font);
1701
+ color: var(--opf-ui-fg);
1702
+ background: var(--opf-ui-surface);
1703
+ border: 1px solid var(--opf-ui-border);
1704
+ border-radius: var(--opf-ui-radius-md);
1705
+ box-shadow: var(--opf-ui-shadow-pop);
1706
+ }
1707
+
1708
+ .opf-menu-item {
1709
+ display: flex;
1710
+ justify-content: space-between;
1711
+ gap: 18px;
1712
+ width: 100%;
1713
+ padding: 6px 10px;
1714
+ font: 13px/1.4 var(--opf-ui-font);
1715
+ text-align: left;
1716
+ color: var(--opf-ui-fg);
1717
+ background: transparent;
1718
+ border: 0;
1719
+ border-radius: var(--opf-ui-radius-sm);
1720
+ cursor: pointer;
1721
+ transition: background-color var(--opf-ui-ease);
1722
+ }
1723
+
1724
+ .opf-menu-item kbd {
1725
+ font: 11px var(--opf-ui-mono);
1726
+ color: var(--opf-ui-muted-fg);
1727
+ }
1728
+
1729
+ .opf-menu-item:hover:not(:disabled),
1730
+ .opf-menu-item:focus-visible {
1731
+ background: var(--opf-ui-muted);
1732
+ outline: none;
1733
+ }
1734
+
1735
+ .opf-menu-item:focus-visible {
1736
+ box-shadow: inset 0 0 0 2px var(--opf-ui-ring);
1737
+ }
1738
+
1739
+ .opf-menu-item:disabled {
1740
+ opacity: 0.45;
1741
+ cursor: default;
1742
+ }
1743
+
1744
+ .opf-menu-separator {
1745
+ height: 1px;
1746
+ margin: 4px 2px;
1747
+ background: var(--opf-ui-border);
1748
+ }
1749
+
1750
+ /* The slide manager dialogs (name, move, layout). */
1751
+
1752
+ .opf-sm-dialog,
1753
+ .opf-layout-dialog,
1754
+ .opf-grid-dialog {
1755
+ padding: 0;
1756
+ color: var(--opf-ui-fg);
1757
+ background: var(--opf-ui-surface);
1758
+ border: 1px solid var(--opf-ui-border);
1759
+ border-radius: var(--opf-ui-radius-lg);
1760
+ box-shadow: var(--opf-ui-shadow-pop);
1761
+ }
1762
+
1763
+ .opf-sm-dialog::backdrop,
1764
+ .opf-layout-dialog::backdrop,
1765
+ .opf-grid-dialog::backdrop {
1766
+ background: color-mix(in srgb, var(--opf-ui-bg) 70%, transparent);
1767
+ }
1768
+
1769
+ .opf-sm-dialog {
1770
+ width: min(440px, 92vw);
1771
+ }
1772
+
1773
+ .opf-layout-dialog {
1774
+ width: min(760px, 94vw);
1775
+ }
1776
+
1777
+ .opf-grid-dialog {
1778
+ width: min(850px, 95vw);
1779
+ max-height: 90vh;
1780
+ }
1781
+
1782
+ .opf-sm-dialog form {
1783
+ display: flex;
1784
+ flex-direction: column;
1785
+ gap: 8px;
1786
+ padding: 20px 22px;
1787
+ }
1788
+
1789
+ .opf-sm-dialog h2,
1790
+ .opf-grid-dialog h2 {
1791
+ margin: 0 0 4px;
1792
+ font-size: 14px;
1793
+ font-weight: 600;
1794
+ color: var(--opf-ui-fg);
1795
+ }
1796
+
1797
+ .opf-sm-dialog input,
1798
+ .opf-sm-dialog select {
1799
+ width: 100%;
1800
+ }
1801
+
1802
+ .opf-sm-dialog .field-help {
1803
+ margin: 0;
1804
+ font-size: 11.5px;
1805
+ color: var(--opf-ui-muted-fg);
1806
+ }
1807
+
1808
+ .opf-sm-dialog select[size] {
1809
+ min-height: 190px;
1810
+ }
1811
+
1812
+ .opf-sm-error {
1813
+ min-height: 1em;
1814
+ margin: 0;
1815
+ font-size: 11.5px;
1816
+ color: var(--opf-ui-danger);
1817
+ }
1818
+
1819
+ .opf-sm-actions {
1820
+ display: flex;
1821
+ justify-content: flex-end;
1822
+ gap: 8px;
1823
+ margin-top: 6px;
1824
+ }
1825
+
1826
+ .opf-layout-preview {
1827
+ display: grid;
1828
+ grid-template-columns: 1fr 1fr;
1829
+ gap: 8px;
1830
+ min-height: 150px;
1831
+ }
1832
+
1833
+ .opf-layout-preview-item {
1834
+ min-width: 0;
1835
+ padding: 8px;
1836
+ background: var(--opf-ui-muted-2);
1837
+ border: 1px solid var(--opf-ui-border);
1838
+ border-radius: var(--opf-ui-radius);
1839
+ }
1840
+
1841
+ .opf-layout-preview-item strong {
1842
+ display: block;
1843
+ margin-bottom: 5px;
1844
+ font: 500 11px/1.4 var(--opf-ui-mono);
1845
+ letter-spacing: 0.08em;
1846
+ text-transform: uppercase;
1847
+ color: var(--opf-ui-muted-fg);
1848
+ }
1849
+
1850
+ .opf-layout-preview svg,
1851
+ .opf-layout-preview img {
1852
+ display: block;
1853
+ width: 100%;
1854
+ height: auto;
1855
+ max-height: 220px;
1856
+ object-fit: contain;
1857
+ }
1858
+
1859
+ .opf-layout-diagram {
1860
+ display: grid;
1861
+ gap: 3px;
1862
+ aspect-ratio: 16 / 9;
1863
+ }
1864
+
1865
+ .opf-layout-diagram span {
1866
+ display: grid;
1867
+ place-items: center;
1868
+ min-width: 0;
1869
+ overflow: hidden;
1870
+ font: 11px var(--opf-ui-mono);
1871
+ color: var(--opf-ui-accent-strong);
1872
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
1873
+ border: 1px solid color-mix(in srgb, var(--opf-ui-accent) 40%, transparent);
1874
+ border-radius: var(--opf-ui-radius-sm);
1875
+ }
1876
+
1877
+ /* ---------------------------------------------------------------- custom layout editor (opf-grid-dialog) */
1878
+
1879
+ .opf-grid-body {
1880
+ display: grid;
1881
+ gap: 8px;
1882
+ overflow: auto;
1883
+ }
1884
+
1885
+ .opf-grid-field {
1886
+ display: grid;
1887
+ gap: 4px;
1888
+ font-size: 12px;
1889
+ }
1890
+
1891
+ .opf-grid-dimensions {
1892
+ display: grid;
1893
+ grid-template-columns: 90px 90px 1fr;
1894
+ gap: 10px;
1895
+ }
1896
+
1897
+ .opf-custom-layout-grid {
1898
+ display: grid;
1899
+ gap: 2px;
1900
+ padding: 8px;
1901
+ background: var(--opf-ui-muted);
1902
+ border-radius: var(--opf-ui-radius);
1903
+ }
1904
+
1905
+ .opf-grid-cell {
1906
+ min-width: 38px;
1907
+ min-height: 38px;
1908
+ padding: 2px;
1909
+ font: 11px var(--opf-ui-mono);
1910
+ color: var(--opf-ui-fg);
1911
+ background: var(--opf-ui-surface);
1912
+ border: 1px solid var(--opf-ui-border-strong);
1913
+ border-radius: var(--opf-ui-radius-sm);
1914
+ cursor: crosshair;
1915
+ }
1916
+
1917
+ .opf-grid-cell[data-area="title"] {
1918
+ color: var(--opf-ui-accent-strong);
1919
+ background: color-mix(in srgb, var(--opf-ui-accent) 12%, var(--opf-ui-surface));
1920
+ }
1921
+
1922
+ .opf-grid-cell[data-area="."] {
1923
+ color: var(--opf-ui-muted-fg);
1924
+ background: var(--opf-ui-muted-2);
1925
+ }
1926
+
1927
+ .opf-grid-regions {
1928
+ display: grid;
1929
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
1930
+ gap: 8px;
1931
+ }
1932
+
1933
+ .opf-grid-region {
1934
+ min-width: 0;
1935
+ border: 1px solid var(--opf-ui-border);
1936
+ border-radius: var(--opf-ui-radius);
1937
+ }
1938
+
1939
+ .opf-grid-kinds {
1940
+ display: grid;
1941
+ grid-template-columns: repeat(3, 1fr);
1942
+ gap: 2px;
1943
+ font-size: 11.5px;
1944
+ }
1945
+
1946
+ .opf-grid-kinds label {
1947
+ display: flex;
1948
+ align-items: center;
1949
+ gap: 3px;
1950
+ }
1951
+
1952
+ .opf-grid-kinds input {
1953
+ width: auto;
1954
+ }
1955
+
1956
+ .opf-region-drop[data-drop-active="true"] {
1957
+ background: color-mix(in srgb, var(--opf-ui-accent) 16%, transparent) !important;
1958
+ border-color: var(--opf-ui-accent) !important;
1959
+ }
1960
+
1961
+ /* ---------------------------------------------------------------- find (opf-find-*) */
1962
+
1963
+ :root .opf-find {
1964
+ min-height: 0;
1965
+ font-family: var(--opf-ui-font);
1966
+ color: var(--opf-ui-fg);
1967
+ background: var(--opf-ui-surface);
1968
+ border: 1px solid var(--opf-ui-border);
1969
+ border-radius: var(--opf-ui-radius-lg);
1970
+ box-shadow: var(--opf-ui-shadow-pop);
1971
+ }
1972
+
1973
+ :root .opf-find-field > span,
1974
+ :root .opf-find-where,
1975
+ :root .opf-find-more,
1976
+ :root .opf-find-count {
1977
+ font-family: var(--opf-ui-mono);
1978
+ font-size: 11.5px;
1979
+ color: var(--opf-ui-muted-fg);
1980
+ }
1981
+
1982
+ :root .opf-find input[type="text"] {
1983
+ min-height: var(--opf-ui-control-h);
1984
+ color: var(--opf-ui-fg);
1985
+ background: var(--opf-ui-surface);
1986
+ border: 1px solid var(--opf-ui-border);
1987
+ border-radius: var(--opf-ui-radius);
1988
+ transition: border-color var(--opf-ui-ease);
1989
+ }
1990
+
1991
+ :root .opf-find input[type="text"]:hover {
1992
+ border-color: var(--opf-ui-border-strong);
1993
+ }
1994
+
1995
+ :root .opf-find input[type="text"][aria-invalid="true"] {
1996
+ border-color: var(--opf-ui-danger);
1997
+ }
1998
+
1999
+ :root .opf-find button {
2000
+ min-height: var(--opf-ui-control-h);
2001
+ color: var(--opf-ui-fg);
2002
+ background: var(--opf-ui-surface);
2003
+ border: 1px solid var(--opf-ui-border);
2004
+ border-radius: var(--opf-ui-radius);
2005
+ transition:
2006
+ background-color var(--opf-ui-ease),
2007
+ border-color var(--opf-ui-ease),
2008
+ color var(--opf-ui-ease);
2009
+ }
2010
+
2011
+ :root .opf-find button:hover:not(:disabled) {
2012
+ background: var(--opf-ui-muted);
2013
+ border-color: var(--opf-ui-border-strong);
2014
+ }
2015
+
2016
+ :root .opf-find button.opf-find-primary {
2017
+ color: var(--opf-ui-accent-fg);
2018
+ background: var(--opf-ui-accent);
2019
+ border-color: var(--opf-ui-accent);
2020
+ }
2021
+
2022
+ :root .opf-find button.opf-find-primary:hover:not(:disabled) {
2023
+ background: var(--opf-ui-accent);
2024
+ border-color: var(--opf-ui-accent);
2025
+ filter: brightness(1.08);
2026
+ }
2027
+
2028
+ :root .opf-find button.opf-find-close {
2029
+ color: var(--opf-ui-muted-fg);
2030
+ background: transparent;
2031
+ border-color: transparent;
2032
+ }
2033
+
2034
+ :root .opf-find button.opf-find-close:hover:not(:disabled) {
2035
+ color: var(--opf-ui-fg);
2036
+ background: var(--opf-ui-muted);
2037
+ }
2038
+
2039
+ :root .opf-find button:focus-visible,
2040
+ :root .opf-find input:focus-visible,
2041
+ :root .opf-find-result:focus-visible {
2042
+ outline: 2px solid var(--opf-ui-ring);
2043
+ outline-offset: 2px;
2044
+ }
2045
+
2046
+ :root .opf-find-opt {
2047
+ color: var(--opf-ui-fg);
2048
+ border: 1px solid var(--opf-ui-border);
2049
+ border-radius: var(--opf-ui-radius);
2050
+ transition:
2051
+ background-color var(--opf-ui-ease),
2052
+ border-color var(--opf-ui-ease);
2053
+ }
2054
+
2055
+ :root .opf-find-opt:has(input:checked) {
2056
+ color: var(--opf-ui-accent-strong);
2057
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
2058
+ border-color: var(--opf-ui-accent);
2059
+ }
2060
+
2061
+ :root .opf-find-opt input {
2062
+ accent-color: var(--opf-ui-accent);
2063
+ }
2064
+
2065
+ :root .opf-find-error {
2066
+ font-size: 11.5px;
2067
+ color: var(--opf-ui-danger);
2068
+ }
2069
+
2070
+ :root .opf-find-results {
2071
+ border: 1px solid var(--opf-ui-border);
2072
+ border-radius: var(--opf-ui-radius);
2073
+ }
2074
+
2075
+ :root .opf-find-results li {
2076
+ border-top: 1px solid var(--opf-ui-border);
2077
+ }
2078
+
2079
+ :root .opf-find-results li:first-child {
2080
+ border-top: 0;
2081
+ }
2082
+
2083
+ :root .opf-find button.opf-find-result {
2084
+ color: var(--opf-ui-fg);
2085
+ background: transparent;
2086
+ border: 0;
2087
+ border-radius: 0;
2088
+ }
2089
+
2090
+ :root .opf-find button.opf-find-result:hover:not(:disabled) {
2091
+ background: var(--opf-ui-muted);
2092
+ }
2093
+
2094
+ :root .opf-find button.opf-find-result[aria-current="true"] {
2095
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
2096
+ }
2097
+
2098
+ :root .opf-find-text mark {
2099
+ color: inherit;
2100
+ background: color-mix(in srgb, var(--opf-ui-warn) 30%, transparent);
2101
+ border-radius: var(--opf-ui-radius-sm);
2102
+ }
2103
+
2104
+ @media (pointer: coarse) {
2105
+ :root .opf-find input[type="text"] {
2106
+ font-size: 16px;
2107
+ }
2108
+
2109
+ :root .opf-find button,
2110
+ :root .opf-find-opt {
2111
+ min-height: 44px;
2112
+ }
2113
+
2114
+ :root .opf-find button.opf-find-close {
2115
+ min-width: 44px;
2116
+ }
2117
+ }
2118
+
2119
+ /* ---------------------------------------------------------------- template panel (opf-template-*) */
2120
+
2121
+ .opf-template-panel {
2122
+ font-size: 13px;
2123
+ }
2124
+
2125
+ .opf-template-summary {
2126
+ margin-bottom: 10px;
2127
+ font-size: 11.5px;
2128
+ color: var(--opf-ui-muted-fg);
2129
+ }
2130
+
2131
+ .opf-template-mode {
2132
+ display: flex;
2133
+ align-items: center;
2134
+ gap: 8px;
2135
+ margin-bottom: 14px;
2136
+ font-weight: 400;
2137
+ }
2138
+
2139
+ .opf-template-fields {
2140
+ display: grid;
2141
+ grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
2142
+ gap: 14px 22px;
2143
+ }
2144
+
2145
+ .opf-template-field {
2146
+ display: flex;
2147
+ flex-direction: column;
2148
+ gap: 5px;
2149
+ padding: 10px 12px;
2150
+ background: var(--opf-ui-surface);
2151
+ border: 1px solid var(--opf-ui-border);
2152
+ border-radius: var(--opf-ui-radius-md);
2153
+ }
2154
+
2155
+ .opf-template-field label {
2156
+ display: block;
2157
+ margin: 0;
2158
+ font-size: 12px;
2159
+ font-weight: 600;
2160
+ color: var(--opf-ui-fg);
2161
+ }
2162
+
2163
+ .opf-template-field :is(input[type="text"], input[type="url"], input[type="date"], textarea) {
2164
+ width: 100%;
2165
+ font-size: 13px;
2166
+ }
2167
+
2168
+ .opf-template-field textarea {
2169
+ min-height: 84px;
2170
+ resize: vertical;
2171
+ }
2172
+
2173
+ .opf-template-kind,
2174
+ .opf-template-help {
2175
+ font: 400 11px/1.5 var(--opf-ui-mono);
2176
+ color: var(--opf-ui-muted-fg);
2177
+ }
2178
+
2179
+ .opf-template-status {
2180
+ font: 11px/1.4 var(--opf-ui-mono);
2181
+ color: var(--opf-ui-muted-fg);
2182
+ }
2183
+
2184
+ .opf-required {
2185
+ color: var(--opf-ui-danger);
2186
+ }
2187
+
2188
+ .opf-template-field[data-status="unfilled"] {
2189
+ background: color-mix(in srgb, var(--opf-ui-warn) 6%, var(--opf-ui-surface));
2190
+ border-color: color-mix(in srgb, var(--opf-ui-warn) 45%, var(--opf-ui-border));
2191
+ }
2192
+
2193
+ .opf-template-field[data-status="unfilled"] .opf-template-status {
2194
+ color: var(--opf-ui-warn);
2195
+ }
2196
+
2197
+ .opf-template-field[data-status="filled"] {
2198
+ border-color: color-mix(in srgb, var(--opf-ui-success) 45%, var(--opf-ui-border));
2199
+ }
2200
+
2201
+ .opf-template-field[data-status="filled"] .opf-template-status {
2202
+ color: var(--opf-ui-success);
2203
+ }
2204
+
2205
+ .opf-template-error {
2206
+ font-size: 11.5px;
2207
+ color: var(--opf-ui-danger);
2208
+ }
2209
+
2210
+ .opf-template-error[hidden] {
2211
+ display: none;
2212
+ }
2213
+
2214
+ .opf-template-actions {
2215
+ display: flex;
2216
+ flex-wrap: wrap;
2217
+ gap: 8px;
2218
+ margin: 16px 0 8px;
2219
+ }
2220
+
2221
+ .opf-template-live {
2222
+ min-height: 1.5em;
2223
+ font-size: 11.5px;
2224
+ color: var(--opf-ui-muted-fg);
2225
+ }
2226
+
2227
+ .opf-template-live[data-error="true"] {
2228
+ color: var(--opf-ui-danger);
2229
+ }
2230
+
2231
+ .opf-template-preview-section,
2232
+ .opf-template-insert-section {
2233
+ margin-top: 14px;
2234
+ padding-top: 12px;
2235
+ border-top: 1px solid var(--opf-ui-border);
2236
+ }
2237
+
2238
+ .opf-template-preview-section select {
2239
+ max-width: 420px;
2240
+ }
2241
+
2242
+ .opf-template-insert-section summary {
2243
+ font: 500 11px/1.4 var(--opf-ui-mono);
2244
+ letter-spacing: 0.08em;
2245
+ text-transform: uppercase;
2246
+ color: var(--opf-ui-muted-fg);
2247
+ cursor: pointer;
2248
+ }
2249
+
2250
+ .opf-template-new-variable {
2251
+ margin-top: 12px;
2252
+ padding: 8px 12px;
2253
+ border: 1px solid var(--opf-ui-border);
2254
+ border-radius: var(--opf-ui-radius);
2255
+ }
2256
+
2257
+ .opf-template-preview {
2258
+ padding: 16px;
2259
+ background: var(--opf-ui-muted-2);
2260
+ border: 1px solid var(--opf-ui-border);
2261
+ border-radius: var(--opf-ui-radius-md);
2262
+ }
2263
+
2264
+ .opf-template-preview svg {
2265
+ display: block;
2266
+ width: 100%;
2267
+ max-width: 640px;
2268
+ height: auto;
2269
+ margin: auto;
2270
+ border: 1px solid var(--opf-ui-border);
2271
+ }
2272
+
2273
+ .opf-template-preview-status {
2274
+ margin-bottom: 8px;
2275
+ font-size: 11.5px;
2276
+ color: var(--opf-ui-muted-fg);
2277
+ }
2278
+
2279
+ .opf-template-empty {
2280
+ font-size: 12px;
2281
+ color: var(--opf-ui-muted-fg);
2282
+ }
2283
+
2284
+ /* ---------------------------------------------------------------- numbering panel (opf-numbering-*) */
2285
+
2286
+ .opf-numbering-panel {
2287
+ font-size: 13px;
2288
+ }
2289
+
2290
+ .opf-numbering-list {
2291
+ display: flex;
2292
+ flex-direction: column;
2293
+ gap: 4px;
2294
+ margin: 0 0 12px;
2295
+ }
2296
+
2297
+ .opf-numbering-toggle {
2298
+ display: flex;
2299
+ align-items: center;
2300
+ gap: 8px;
2301
+ margin: 0 0 12px;
2302
+ }
2303
+
2304
+ .opf-numbering-toggle label {
2305
+ margin: 0;
2306
+ font-size: 12px;
2307
+ font-weight: 500;
2308
+ color: var(--opf-ui-fg);
2309
+ }
2310
+
2311
+ .opf-numbering-levels {
2312
+ display: flex;
2313
+ flex-direction: column;
2314
+ gap: 10px;
2315
+ margin: 0 0 12px;
2316
+ }
2317
+
2318
+ .opf-numbering-level {
2319
+ display: grid;
2320
+ grid-template-columns: auto 1fr;
2321
+ align-items: center;
2322
+ gap: 5px 10px;
2323
+ padding: 9px 12px;
2324
+ background: var(--opf-ui-surface);
2325
+ border: 1px solid var(--opf-ui-border);
2326
+ border-radius: var(--opf-ui-radius-md);
2327
+ }
2328
+
2329
+ .opf-numbering-level label {
2330
+ margin: 0;
2331
+ font-size: 12px;
2332
+ color: var(--opf-ui-muted-fg);
2333
+ }
2334
+
2335
+ .opf-numbering-level-name {
2336
+ grid-column: 1 / -1;
2337
+ font-size: 12px;
2338
+ font-weight: 600;
2339
+ color: var(--opf-ui-fg);
2340
+ }
2341
+
2342
+ .opf-numbering-level :is(select, input) {
2343
+ width: 100%;
2344
+ }
2345
+
2346
+ .opf-numbering-preview {
2347
+ min-height: 1.5em;
2348
+ margin: 4px 0 12px;
2349
+ padding: 8px 12px;
2350
+ font: 14px/1.5 var(--opf-ui-mono);
2351
+ letter-spacing: 0.02em;
2352
+ color: var(--opf-ui-fg);
2353
+ background: var(--opf-ui-code-bg);
2354
+ border: 1px solid var(--opf-ui-code-border);
2355
+ border-radius: var(--opf-ui-radius-md);
2356
+ }
2357
+
2358
+ .opf-numbering-note,
2359
+ .opf-numbering-help,
2360
+ .opf-numbering-empty {
2361
+ font-size: 11.5px;
2362
+ color: var(--opf-ui-muted-fg);
2363
+ }
2364
+
2365
+ .opf-numbering-entry {
2366
+ display: flex;
2367
+ flex-direction: column;
2368
+ gap: 4px;
2369
+ padding-top: 10px;
2370
+ border-top: 1px solid var(--opf-ui-border);
2371
+ }
2372
+
2373
+ .opf-numbering-entry input {
2374
+ max-width: 140px;
2375
+ }
2376
+
2377
+ .opf-numbering-live {
2378
+ min-height: 1.4em;
2379
+ margin: 10px 0 0;
2380
+ font: 11.5px/1.4 var(--opf-ui-mono);
2381
+ color: var(--opf-ui-success);
2382
+ }
2383
+
2384
+ .opf-numbering-live[data-error="true"] {
2385
+ color: var(--opf-ui-danger);
2386
+ }
2387
+
2388
+ /* ---------------------------------------------------------------- chart options (opf-chart-*, opf-co-*) */
2389
+
2390
+ .opf-chart-options {
2391
+ margin: 8px 0;
2392
+ padding: 8px 0;
2393
+ border-top: 1px solid var(--opf-ui-border);
2394
+ }
2395
+
2396
+ .opf-chart-options[hidden] {
2397
+ display: none;
2398
+ }
2399
+
2400
+ .opf-co-title {
2401
+ margin: 0 0 8px;
2402
+ font: 500 11px/1.4 var(--opf-ui-mono);
2403
+ letter-spacing: 0.08em;
2404
+ text-transform: uppercase;
2405
+ color: var(--opf-ui-muted-fg);
2406
+ }
2407
+
2408
+ .opf-co-group {
2409
+ margin: 0 0 8px;
2410
+ }
2411
+
2412
+ .opf-co-row {
2413
+ display: flex;
2414
+ flex-direction: column;
2415
+ gap: 3px;
2416
+ margin: 0 0 6px;
2417
+ font-size: 12px;
2418
+ color: var(--opf-ui-fg);
2419
+ }
2420
+
2421
+ .opf-co-row :is(input[type="text"], select) {
2422
+ width: 100%;
2423
+ }
2424
+
2425
+ .opf-co-check {
2426
+ display: flex;
2427
+ flex-direction: row;
2428
+ align-items: center;
2429
+ gap: 6px;
2430
+ font-size: 12px;
2431
+ color: var(--opf-ui-fg);
2432
+ }
2433
+
2434
+ .opf-co-content,
2435
+ .opf-co-highlight,
2436
+ .opf-co-colors {
2437
+ margin: 0 0 6px;
2438
+ padding: 0;
2439
+ border: 0;
2440
+ }
2441
+
2442
+ .opf-co-content {
2443
+ display: flex;
2444
+ flex-wrap: wrap;
2445
+ gap: 4px 12px;
2446
+ }
2447
+
2448
+ .opf-co-colors {
2449
+ margin-bottom: 8px;
2450
+ }
2451
+
2452
+ .opf-co-content legend,
2453
+ .opf-co-highlight legend,
2454
+ .opf-co-colors legend {
2455
+ margin: 0 0 3px;
2456
+ padding: 0;
2457
+ font-size: 12px;
2458
+ color: var(--opf-ui-fg);
2459
+ }
2460
+
2461
+ .opf-co-choices {
2462
+ display: flex;
2463
+ flex-direction: column;
2464
+ gap: 2px;
2465
+ max-height: 120px;
2466
+ overflow: auto;
2467
+ }
2468
+
2469
+ .opf-co-color-row {
2470
+ gap: 4px;
2471
+ }
2472
+
2473
+ .opf-co-swatches {
2474
+ display: flex;
2475
+ flex-wrap: wrap;
2476
+ gap: 4px;
2477
+ }
2478
+
2479
+ .opf-co-swatch {
2480
+ min-width: 22px;
2481
+ height: 22px;
2482
+ min-height: 22px;
2483
+ padding: 0 4px;
2484
+ font: 11px var(--opf-ui-mono);
2485
+ color: var(--opf-ui-fg);
2486
+ background: var(--opf-ui-surface);
2487
+ border: 1px solid var(--opf-ui-border-strong);
2488
+ border-radius: var(--opf-ui-radius-sm);
2489
+ cursor: pointer;
2490
+ }
2491
+
2492
+ .opf-co-swatch:hover:not(:disabled) {
2493
+ background: var(--opf-ui-muted);
2494
+ }
2495
+
2496
+ .opf-co-swatch[aria-pressed="true"] {
2497
+ color: var(--opf-ui-accent-strong);
2498
+ outline: 2px solid var(--opf-ui-ring);
2499
+ outline-offset: 1px;
2500
+ }
2501
+
2502
+ .opf-co-hex {
2503
+ width: 100%;
2504
+ }
2505
+
2506
+ /* ---------------------------------------------------------------- data grid (opf-grid-*) */
2507
+
2508
+ :root .opf-grid {
2509
+ --g-border: var(--opf-ui-border);
2510
+ --g-ruler: var(--opf-ui-muted-2);
2511
+ --g-text: var(--opf-ui-fg);
2512
+ --g-muted: var(--opf-ui-muted-fg);
2513
+ --g-select: var(--opf-ui-muted);
2514
+ --g-focus: var(--opf-ui-ring);
2515
+ --g-error: var(--opf-ui-danger);
2516
+ --g-warn: var(--opf-ui-warn);
2517
+ --g-gap: var(--opf-ui-muted-fg);
2518
+ font-family: var(--opf-ui-font);
2519
+ }
2520
+
2521
+ :root .opf-grid-path,
2522
+ :root .opf-grid-help,
2523
+ :root .opf-grid td.opf-grid-gap::before {
2524
+ font-family: var(--opf-ui-mono);
2525
+ }
2526
+
2527
+ :root .opf-grid-toolbar button,
2528
+ :root .opf-grid-toolbar select,
2529
+ :root .opf-grid-dataset button,
2530
+ :root .opf-grid-format button,
2531
+ :root .opf-grid-format input,
2532
+ :root .opf-grid-mapping select {
2533
+ color: var(--opf-ui-fg);
2534
+ background: var(--opf-ui-surface);
2535
+ border-radius: var(--opf-ui-radius);
2536
+ transition:
2537
+ background-color var(--opf-ui-ease),
2538
+ border-color var(--opf-ui-ease);
2539
+ }
2540
+
2541
+ :root .opf-grid-toolbar button:hover,
2542
+ :root .opf-grid-dataset button:hover,
2543
+ :root .opf-grid-format button:hover {
2544
+ background: var(--opf-ui-muted);
2545
+ border-color: var(--opf-ui-border-strong);
2546
+ }
2547
+
2548
+ :root .opf-grid-toolbar [aria-disabled="true"]:hover {
2549
+ background: var(--opf-ui-surface);
2550
+ border-color: var(--g-border);
2551
+ }
2552
+
2553
+ :root .opf-grid-scroll {
2554
+ background: var(--opf-ui-surface);
2555
+ border-radius: var(--opf-ui-radius);
2556
+ }
2557
+
2558
+ :root .opf-grid td {
2559
+ background: var(--opf-ui-surface);
2560
+ }
2561
+
2562
+ :root .opf-grid td textarea {
2563
+ color: var(--opf-ui-fg);
2564
+ background: var(--opf-ui-surface);
2565
+ }
2566
+
2567
+ :root .opf-grid td.opf-grid-header {
2568
+ background: var(--opf-ui-muted-2);
2569
+ }
2570
+
2571
+ :root .opf-grid td[aria-selected="true"] {
2572
+ background: var(--opf-ui-muted);
2573
+ }
2574
+
2575
+ :root .opf-grid td.opf-grid-merged {
2576
+ background-image: linear-gradient(135deg, transparent 92%, var(--opf-ui-border-strong) 92%);
2577
+ }
2578
+
2579
+ :root .opf-grid-status {
2580
+ font-family: var(--opf-ui-mono);
2581
+ color: var(--opf-ui-success);
2582
+ }
2583
+
2584
+ :root .opf-grid details textarea {
2585
+ color: var(--opf-ui-fg);
2586
+ background: var(--opf-ui-code-bg);
2587
+ border: 1px solid var(--opf-ui-code-border);
2588
+ border-radius: var(--opf-ui-radius);
2589
+ font-family: var(--opf-ui-mono);
2590
+ }
2591
+
2592
+ /* ---------------------------------------------------------------- image crop (opf-crop-*) */
2593
+
2594
+ :root .opf-crop-pill {
2595
+ color: var(--opf-ui-accent-fg);
2596
+ background: var(--opf-ui-accent);
2597
+ border: 1px solid var(--opf-ui-surface);
2598
+ font-family: var(--opf-ui-font);
2599
+ box-shadow: var(--opf-ui-shadow-pop);
2600
+ }
2601
+
2602
+ :root .opf-crop-pill:focus-visible,
2603
+ :root .opf-crop-rect:focus-visible,
2604
+ :root .opf-crop button:focus-visible,
2605
+ :root .opf-crop select:focus-visible,
2606
+ :root .opf-crop input:focus-visible {
2607
+ outline: 2px solid var(--opf-ui-ring);
2608
+ outline-offset: 2px;
2609
+ }
2610
+
2611
+ :root .opf-crop {
2612
+ color: var(--opf-ui-fg);
2613
+ background: color-mix(in srgb, var(--opf-ui-bg) 94%, transparent);
2614
+ font-family: var(--opf-ui-font);
2615
+ }
2616
+
2617
+ :root .opf-crop-rect {
2618
+ outline: 2px solid var(--opf-ui-surface);
2619
+ box-shadow: 0 0 0 9999px color-mix(in srgb, var(--opf-ui-bg) 62%, transparent);
2620
+ }
2621
+
2622
+ :root .opf-crop-handle {
2623
+ background: var(--opf-ui-surface);
2624
+ border: 2px solid var(--opf-ui-accent);
2625
+ border-radius: var(--opf-ui-radius-sm);
2626
+ }
2627
+
2628
+ :root .opf-crop-focus {
2629
+ border-color: var(--opf-ui-warn);
2630
+ box-shadow: 0 0 0 2px var(--opf-ui-surface);
2631
+ }
2632
+
2633
+ :root .opf-crop-focus::before,
2634
+ :root .opf-crop-focus::after {
2635
+ background: var(--opf-ui-warn);
2636
+ }
2637
+
2638
+ :root .opf-crop-bar {
2639
+ background: var(--opf-ui-surface);
2640
+ border-top: 1px solid var(--opf-ui-border);
2641
+ }
2642
+
2643
+ :root .opf-crop select,
2644
+ :root .opf-crop input[type="number"] {
2645
+ min-height: var(--opf-ui-control-h);
2646
+ color: var(--opf-ui-fg);
2647
+ background: var(--opf-ui-surface);
2648
+ border: 1px solid var(--opf-ui-border);
2649
+ border-radius: var(--opf-ui-radius);
2650
+ }
2651
+
2652
+ :root .opf-crop input[type="range"] {
2653
+ accent-color: var(--opf-ui-accent);
2654
+ }
2655
+
2656
+ :root .opf-crop button {
2657
+ min-height: var(--opf-ui-control-h);
2658
+ color: var(--opf-ui-fg);
2659
+ background: var(--opf-ui-surface);
2660
+ border: 1px solid var(--opf-ui-border);
2661
+ border-radius: var(--opf-ui-radius);
2662
+ font-weight: 500;
2663
+ transition:
2664
+ background-color var(--opf-ui-ease),
2665
+ border-color var(--opf-ui-ease),
2666
+ color var(--opf-ui-ease);
2667
+ }
2668
+
2669
+ :root .opf-crop button:hover:not(:disabled) {
2670
+ background: var(--opf-ui-muted);
2671
+ border-color: var(--opf-ui-border-strong);
2672
+ }
2673
+
2674
+ :root .opf-crop button[aria-pressed="true"] {
2675
+ color: var(--opf-ui-accent-strong);
2676
+ background: color-mix(in srgb, var(--opf-ui-accent) 12%, var(--opf-ui-surface));
2677
+ border-color: var(--opf-ui-accent);
2678
+ }
2679
+
2680
+ :root .opf-crop button.opf-crop-apply {
2681
+ color: var(--opf-ui-accent-fg);
2682
+ background: var(--opf-ui-accent);
2683
+ border-color: var(--opf-ui-accent);
2684
+ }
2685
+
2686
+ :root .opf-crop-readout {
2687
+ font-family: var(--opf-ui-mono);
2688
+ font-size: 11.5px;
2689
+ color: var(--opf-ui-muted-fg);
2690
+ }
2691
+
2692
+ :root .opf-crop-error {
2693
+ color: var(--opf-ui-danger);
2694
+ }
2695
+
2696
+ @media (pointer: coarse) {
2697
+ :root .opf-crop button,
2698
+ :root .opf-crop select,
2699
+ :root .opf-crop input[type="number"] {
2700
+ min-height: 44px;
2701
+ }
2702
+ }
2703
+
2704
+ /* ---------------------------------------------------------------- JSON editor (CodeMirror, opf-json / opf-code) */
2705
+ /* The editor ships no CSS of its own. Put it in an `.opf-ui`, `.opf-json` or `.opf-code` element (or the component that holds it) to get this look. */
2706
+
2707
+ :is(.opf-ui, .opf-json, .opf-code) .cm-editor {
2708
+ font: 12.5px/1.65 var(--opf-ui-mono);
2709
+ color: var(--opf-ui-fg);
2710
+ background: var(--opf-ui-code-bg);
2711
+ border: 1px solid var(--opf-ui-code-border);
2712
+ border-radius: var(--opf-ui-radius-md);
2713
+ }
2714
+
2715
+ :is(.opf-ui, .opf-json, .opf-code) .cm-editor.cm-focused {
2716
+ outline: 2px solid var(--opf-ui-ring);
2717
+ outline-offset: 2px;
2718
+ }
2719
+
2720
+ :is(.opf-ui, .opf-json, .opf-code) .cm-scroller,
2721
+ :is(.opf-ui, .opf-json, .opf-code) .cm-content {
2722
+ font-family: var(--opf-ui-mono);
2723
+ }
2724
+
2725
+ :is(.opf-ui, .opf-json, .opf-code) .cm-content {
2726
+ caret-color: var(--opf-ui-fg);
2727
+ }
2728
+
2729
+ :is(.opf-ui, .opf-json, .opf-code) .cm-cursor,
2730
+ :is(.opf-ui, .opf-json, .opf-code) .cm-dropCursor {
2731
+ border-left-color: var(--opf-ui-fg);
2732
+ }
2733
+
2734
+ :is(.opf-ui, .opf-json, .opf-code) .cm-gutters {
2735
+ color: var(--opf-ui-muted-fg);
2736
+ background: var(--opf-ui-code-bg);
2737
+ border-right: 1px solid var(--opf-ui-code-border);
2738
+ }
2739
+
2740
+ :is(.opf-ui, .opf-json, .opf-code) .cm-activeLine,
2741
+ :is(.opf-ui, .opf-json, .opf-code) .cm-line.is-hover {
2742
+ background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent);
2743
+ }
2744
+
2745
+ :is(.opf-ui, .opf-json, .opf-code) .cm-activeLineGutter {
2746
+ color: var(--opf-ui-fg);
2747
+ background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent);
2748
+ }
2749
+
2750
+ :is(.opf-ui, .opf-json, .opf-code) .cm-selectionBackground,
2751
+ :is(.opf-ui, .opf-json, .opf-code) .cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground {
2752
+ background: color-mix(in srgb, var(--opf-ui-accent) 20%, transparent);
2753
+ }
2754
+
2755
+ :is(.opf-ui, .opf-json, .opf-code) .cm-selectionMatch {
2756
+ background: color-mix(in srgb, var(--opf-ui-warn) 25%, transparent);
2757
+ }
2758
+
2759
+ :is(.opf-ui, .opf-json, .opf-code) .cm-matchingBracket {
2760
+ background: color-mix(in srgb, var(--opf-ui-accent) 16%, transparent);
2761
+ outline: 1px solid var(--opf-ui-accent);
2762
+ }
2763
+
2764
+ :is(.opf-ui, .opf-json, .opf-code) .tok-key {
2765
+ color: var(--opf-ui-accent-strong);
2766
+ }
2767
+
2768
+ :is(.opf-ui, .opf-json, .opf-code) .tok-str {
2769
+ color: var(--opf-ui-fg);
2770
+ }
2771
+
2772
+ :is(.opf-ui, .opf-json, .opf-code) .tok-num {
2773
+ color: var(--opf-ui-warn);
2774
+ }
2775
+
2776
+ :is(.opf-ui, .opf-json, .opf-code) .tok-punct,
2777
+ :is(.opf-ui, .opf-json, .opf-code) .tok-brace {
2778
+ color: var(--opf-ui-muted-fg);
2779
+ }
2780
+
2781
+ :is(.opf-ui, .opf-json, .opf-code) .code-key.is-active {
2782
+ background: color-mix(in srgb, var(--opf-ui-accent) 14%, transparent);
2783
+ border-radius: var(--opf-ui-radius-sm);
2784
+ }
2785
+
2786
+ :is(.opf-ui, .opf-json, .opf-code) .cm-panels {
2787
+ color: var(--opf-ui-fg);
2788
+ background: var(--opf-ui-surface);
2789
+ border-color: var(--opf-ui-border);
2790
+ font-family: var(--opf-ui-font);
2791
+ }
2792
+
2793
+ :is(.opf-ui, .opf-json, .opf-code) .cm-panels input,
2794
+ :is(.opf-ui, .opf-json, .opf-code) .cm-panels button {
2795
+ font: 12px var(--opf-ui-font);
2796
+ color: var(--opf-ui-fg);
2797
+ background: var(--opf-ui-surface);
2798
+ border: 1px solid var(--opf-ui-border);
2799
+ border-radius: var(--opf-ui-radius-sm);
2800
+ }
2801
+
2802
+ :is(.opf-ui, .opf-json, .opf-code) .cm-tooltip {
2803
+ color: var(--opf-ui-fg);
2804
+ background: var(--opf-ui-surface);
2805
+ border: 1px solid var(--opf-ui-border);
2806
+ border-radius: var(--opf-ui-radius-md);
2807
+ box-shadow: var(--opf-ui-shadow-pop);
2808
+ }
2809
+
2810
+ :is(.opf-ui, .opf-json, .opf-code) .cm-diagnostic-error {
2811
+ border-left-color: var(--opf-ui-danger);
2812
+ }
2813
+
2814
+ :is(.opf-ui, .opf-json, .opf-code) .cm-diagnostic-warning {
2815
+ border-left-color: var(--opf-ui-warn);
2816
+ }
2817
+
2818
+ /* The field-options popover. Its inline style uses system colors; color-scheme follows the theme, and these keep it on the tokens. */
2819
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-menu {
2820
+ color: var(--opf-ui-fg) !important;
2821
+ background: var(--opf-ui-surface) !important;
2822
+ border-color: var(--opf-ui-border) !important;
2823
+ border-radius: var(--opf-ui-radius-lg) !important;
2824
+ box-shadow: var(--opf-ui-shadow-pop) !important;
2825
+ font-family: var(--opf-ui-font) !important;
2826
+ }
2827
+
2828
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-menu button[role="option"]:hover,
2829
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-menu button.is-highlighted {
2830
+ background: var(--opf-ui-muted) !important;
2831
+ }
2832
+
2833
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-menu input {
2834
+ color: var(--opf-ui-fg);
2835
+ background: var(--opf-ui-surface);
2836
+ border: 1px solid var(--opf-ui-border);
2837
+ border-radius: var(--opf-ui-radius);
2838
+ }
2839
+
2840
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-hint,
2841
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-footnote,
2842
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-regions,
2843
+ :is(.opf-ui, .opf-json, .opf-code) .json-field-group {
2844
+ color: var(--opf-ui-muted-fg) !important;
2845
+ }
2846
+
2847
+ /* ---------------------------------------------------------------- persistence banner (restore prompt) */
2848
+ /* `createPersistenceUi` fills a host element; give that element the class `restore-banner` (the playground does). */
2849
+
2850
+ .restore-banner {
2851
+ display: flex;
2852
+ flex-wrap: wrap;
2853
+ align-items: center;
2854
+ gap: 8px 16px;
2855
+ padding: 8px 16px;
2856
+ font-family: var(--opf-ui-font);
2857
+ color: var(--opf-ui-fg);
2858
+ background: color-mix(in srgb, var(--opf-ui-warn) 10%, var(--opf-ui-surface));
2859
+ border-bottom: 1px solid color-mix(in srgb, var(--opf-ui-warn) 40%, var(--opf-ui-border));
2860
+ }
2861
+
2862
+ .restore-banner[hidden] {
2863
+ display: none;
2864
+ }
2865
+
2866
+ .restore-text {
2867
+ flex: 1 1 320px;
2868
+ margin: 0;
2869
+ font-size: 13px;
2870
+ }
2871
+
2872
+ .restore-note {
2873
+ flex: 1 1 100%;
2874
+ margin: 0;
2875
+ font: 11.5px/1.4 var(--opf-ui-mono);
2876
+ color: var(--opf-ui-muted-fg);
2877
+ }
2878
+
2879
+ .restore-actions {
2880
+ display: flex;
2881
+ flex-wrap: wrap;
2882
+ gap: 8px;
2883
+ }
2884
+
2885
+ .restore-banner button {
2886
+ display: inline-flex;
2887
+ align-items: center;
2888
+ justify-content: center;
2889
+ min-height: var(--opf-ui-control-h);
2890
+ padding: 0 12px;
2891
+ font: 500 13px/1.2 var(--opf-ui-font);
2892
+ color: var(--opf-ui-fg);
2893
+ background: var(--opf-ui-surface);
2894
+ border: 1px solid var(--opf-ui-border);
2895
+ border-radius: var(--opf-ui-radius);
2896
+ cursor: pointer;
2897
+ transition:
2898
+ background-color var(--opf-ui-ease),
2899
+ border-color var(--opf-ui-ease);
2900
+ }
2901
+
2902
+ .restore-banner button:hover:not(:disabled) {
2903
+ background: var(--opf-ui-muted);
2904
+ border-color: var(--opf-ui-border-strong);
2905
+ }
2906
+
2907
+ .restore-banner button.primary {
2908
+ color: var(--opf-ui-accent-fg);
2909
+ background: var(--opf-ui-accent);
2910
+ border-color: var(--opf-ui-accent);
2911
+ }
2912
+
2913
+ .restore-banner button:focus-visible {
2914
+ outline: 2px solid var(--opf-ui-ring);
2915
+ outline-offset: 2px;
2916
+ }
2917
+
2918
+ .restore-banner button:disabled {
2919
+ opacity: 0.45;
2920
+ cursor: default;
2921
+ }
2922
+
2923
+ /* Motion is color and border only; it is off when the person asks for less. */
2924
+ @media (prefers-reduced-motion: reduce) {
2925
+ :root .opf-find *,
2926
+ :root .opf-crop *,
2927
+ :root .opf-grid *,
2928
+ :root .opf-review *,
2929
+ .opf-design-controls *,
2930
+ .opf-template-panel *,
2931
+ .opf-numbering-panel *,
2932
+ .opf-chart-options *,
2933
+ .opf-slides *,
2934
+ .opf-menu *,
2935
+ .opf-outline *,
2936
+ .restore-banner * {
2937
+ transition: none !important;
2938
+ }
2939
+ }
2940
+
2941
+ /* source-pane.css */
2942
+ /* Source pane (RR-98). Only --opf-ui-* tokens (src/styles/tokens.css). */
2943
+ .opf-source {
2944
+ --_h: var(--opf-ui-control-h);
2945
+ --_bar: 40px;
2946
+ position: relative;
2947
+ display: flex;
2948
+ flex-direction: column;
2949
+ min-width: 0;
2950
+ min-height: 0;
2951
+ height: 100%;
2952
+ background: var(--opf-ui-code-bg);
2953
+ color: var(--opf-ui-fg);
2954
+ font-family: var(--opf-ui-font);
2955
+ font-size: 13px;
2956
+ }
2957
+ .opf-source[data-density="touch"] { --_h: 40px; --_bar: 48px; }
2958
+ .opf-source [hidden] { display: none !important; }
2959
+ .opf-source button { font: inherit; color: inherit; }
2960
+
2961
+ /* Bar: file name, format menu, actions */
2962
+ .opf-source-bar {
2963
+ display: flex;
2964
+ align-items: center;
2965
+ gap: 14px;
2966
+ flex: none;
2967
+ min-height: var(--_bar);
2968
+ padding: 0 8px 0 14px;
2969
+ border-bottom: 1px solid var(--opf-ui-code-border);
2970
+ }
2971
+ .opf-source-file {
2972
+ position: relative;
2973
+ display: flex;
2974
+ align-items: center;
2975
+ gap: 2px;
2976
+ min-width: 0;
2977
+ font: 500 13px var(--opf-ui-mono);
2978
+ white-space: nowrap;
2979
+ }
2980
+ .opf-source-name,
2981
+ .opf-source-format {
2982
+ display: inline-flex;
2983
+ align-items: center;
2984
+ gap: 3px;
2985
+ min-height: calc(var(--_h) - 6px);
2986
+ padding: 2px 4px;
2987
+ border: 0;
2988
+ border-radius: var(--opf-ui-radius-sm);
2989
+ background: transparent;
2990
+ font: inherit;
2991
+ cursor: pointer;
2992
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease);
2993
+ }
2994
+ .opf-source-name { margin-left: -4px; color: var(--opf-ui-fg); cursor: text; overflow: hidden; text-overflow: ellipsis; max-width: 24ch; }
2995
+ .opf-source-name:disabled { cursor: default; }
2996
+ .opf-source-format { padding-left: 5px; color: var(--opf-ui-muted-fg); }
2997
+ .opf-source-name:not(:disabled):hover,
2998
+ .opf-source-format:hover { background: var(--opf-ui-muted); }
2999
+ .opf-source-format:hover,
3000
+ .opf-source-format[aria-expanded="true"] { color: var(--opf-ui-fg); }
3001
+ .opf-source-format[aria-expanded="true"] { background: var(--opf-ui-muted); }
3002
+ .opf-source-name-input {
3003
+ box-sizing: content-box;
3004
+ min-height: calc(var(--_h) - 10px);
3005
+ margin-left: -5px;
3006
+ padding: 2px 4px;
3007
+ border: 1px solid var(--opf-ui-ring);
3008
+ border-radius: var(--opf-ui-radius-sm);
3009
+ background: var(--opf-ui-surface);
3010
+ color: var(--opf-ui-fg);
3011
+ font: inherit;
3012
+ outline: none;
3013
+ }
3014
+ .opf-source-actions { display: flex; gap: 2px; margin-left: auto; }
3015
+ .opf-source-action {
3016
+ display: grid;
3017
+ place-items: center;
3018
+ width: var(--_h);
3019
+ height: var(--_h);
3020
+ padding: 0;
3021
+ border: 0;
3022
+ border-radius: var(--opf-ui-radius);
3023
+ background: transparent;
3024
+ color: var(--opf-ui-muted-fg);
3025
+ cursor: pointer;
3026
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease);
3027
+ }
3028
+ .opf-source-action:hover { background: var(--opf-ui-muted); color: var(--opf-ui-fg); }
3029
+ .opf-source-action:disabled { opacity: 0.4; cursor: default; }
3030
+ .opf-source-action:disabled:hover { background: transparent; color: var(--opf-ui-muted-fg); }
3031
+ .opf-source-icon { flex: none; }
3032
+ .opf-source[data-density="touch"] .opf-source-icon-braces,
3033
+ .opf-source[data-density="touch"] .opf-source-icon-copy,
3034
+ .opf-source[data-density="touch"] .opf-source-icon-download,
3035
+ .opf-source[data-density="touch"] .opf-source-icon-check { width: 16px; height: 16px; }
3036
+
3037
+ :where(.opf-source button, .opf-source input):focus-visible { outline: 2px solid var(--opf-ui-ring); outline-offset: 2px; }
3038
+ .opf-source-name-input:focus-visible { outline-offset: 0; }
3039
+
3040
+ /* Format menu */
3041
+ .opf-source-menu {
3042
+ position: absolute;
3043
+ top: calc(100% + 4px);
3044
+ left: 0;
3045
+ z-index: 6;
3046
+ width: 264px;
3047
+ padding: 4px;
3048
+ border: 1px solid var(--opf-ui-border);
3049
+ border-radius: var(--opf-ui-radius-md);
3050
+ background: var(--opf-ui-surface);
3051
+ box-shadow: var(--opf-ui-shadow-pop);
3052
+ font-family: var(--opf-ui-font);
3053
+ white-space: normal;
3054
+ }
3055
+ .opf-source-menu-heading {
3056
+ padding: 6px 10px 4px;
3057
+ color: var(--opf-ui-muted-fg);
3058
+ font: 500 10.5px var(--opf-ui-mono);
3059
+ letter-spacing: 0.08em;
3060
+ text-transform: uppercase;
3061
+ }
3062
+ .opf-source-menu-item {
3063
+ display: flex;
3064
+ align-items: flex-start;
3065
+ gap: 8px;
3066
+ width: 100%;
3067
+ min-height: var(--_h);
3068
+ padding: 7px 10px;
3069
+ border: 0;
3070
+ border-radius: 5px;
3071
+ background: transparent;
3072
+ text-align: left;
3073
+ cursor: pointer;
3074
+ transition: background-color var(--opf-ui-ease);
3075
+ }
3076
+ .opf-source-menu-item:hover,
3077
+ .opf-source-menu-item:focus-visible { background: var(--opf-ui-muted); }
3078
+ .opf-source-menu-item[aria-checked="true"] { background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent); }
3079
+ .opf-source-menu-item[aria-checked="true"]:hover { background: color-mix(in srgb, var(--opf-ui-accent) 14%, transparent); }
3080
+ .opf-source-menu-item:focus-visible { outline-offset: -2px; }
3081
+ .opf-source-menu-check { display: grid; place-items: center; width: 14px; height: 18px; color: var(--opf-ui-accent-strong); visibility: hidden; }
3082
+ .opf-source-menu-item[aria-checked="true"] .opf-source-menu-check { visibility: visible; }
3083
+ .opf-source-menu-body { display: flex; flex: 1; flex-direction: column; gap: 1px; min-width: 0; }
3084
+ .opf-source-menu-label { font-size: 13px; font-weight: 500; line-height: 18px; }
3085
+ .opf-source-menu-description { color: var(--opf-ui-muted-fg); font-size: 12px; line-height: 16px; }
3086
+ .opf-source-menu-extension { color: var(--opf-ui-muted-fg); font: 11px/18px var(--opf-ui-mono); }
3087
+
3088
+ /* Code */
3089
+ .opf-source-code { position: relative; flex: 1; min-height: 0; overflow: hidden; display: flex; }
3090
+ .opf-source-code > .cm-editor { flex: 1; min-width: 0; height: 100%; background: transparent; color: var(--opf-ui-fg); }
3091
+ .opf-source-code .cm-editor.cm-focused { outline: none; }
3092
+ .opf-source-code .cm-scroller { overflow: auto; font: 400 13.5px/22px var(--opf-ui-mono); }
3093
+ .opf-source[data-density="touch"] .opf-source-code .cm-scroller { font-size: 13px; line-height: 21px; }
3094
+ .opf-source-code .cm-content { padding: 16px 16px 16px 4px; caret-color: var(--opf-ui-fg); }
3095
+ .opf-source-code .cm-line { padding: 0 2px; }
3096
+ .opf-source-code .cm-gutters { border: 0; background: transparent; color: color-mix(in srgb, var(--opf-ui-muted-fg) 60%, transparent); }
3097
+ .opf-source-code .cm-lineNumbers .cm-gutterElement { min-width: 30px; padding: 0 12px 0 0; text-align: right; font-size: 11px; }
3098
+ .opf-source-code .cm-activeLine { background: transparent; }
3099
+ .opf-source-code .cm-selectionBackground,
3100
+ .opf-source-code .cm-focused .cm-selectionBackground { background: color-mix(in srgb, var(--opf-ui-accent) 16%, transparent); }
3101
+ .opf-source-code .cm-cursor { border-left-color: var(--opf-ui-fg); }
3102
+ .opf-source-code .tok-key { color: var(--opf-ui-accent-strong); }
3103
+ .opf-source-code .tok-str { color: var(--opf-ui-fg); }
3104
+ .opf-source-code .tok-num { color: var(--opf-ui-warn); }
3105
+ .opf-source-code .tok-punct,
3106
+ .opf-source-code .tok-brace,
3107
+ .opf-source-code .tok-comment,
3108
+ .opf-source-code .tok-meta { color: var(--opf-ui-muted-fg); }
3109
+ .opf-source-code .tok-head { color: var(--opf-ui-accent-strong); font-weight: 600; }
3110
+ .opf-source-code .tok-comment { font-style: italic; }
3111
+ .opf-source-code .code-key.is-active { background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent); border-radius: var(--opf-ui-radius-sm); }
3112
+ .opf-source-code .cm-line.is-hover { background: color-mix(in srgb, var(--opf-ui-accent) 6%, transparent); }
3113
+ .opf-source-code .cm-panels { background: var(--opf-ui-surface); color: var(--opf-ui-fg); border-color: var(--opf-ui-border); }
3114
+ .opf-source-code .cm-tooltip { background: var(--opf-ui-surface); border: 1px solid var(--opf-ui-border); border-radius: var(--opf-ui-radius); color: var(--opf-ui-fg); }
3115
+ .opf-source-code .cm-lintRange-error { background-image: none; text-decoration: underline wavy var(--opf-ui-danger); }
3116
+
3117
+ /* Findings under the code */
3118
+ .opf-source-findings {
3119
+ flex: none;
3120
+ border-top: 1px solid var(--opf-ui-code-border);
3121
+ background: color-mix(in srgb, var(--opf-ui-danger) 5%, transparent);
3122
+ max-height: 40%;
3123
+ display: flex;
3124
+ flex-direction: column;
3125
+ }
3126
+ .opf-source-findings[data-tone="warning"] { background: color-mix(in srgb, var(--opf-ui-warn) 6%, transparent); }
3127
+ .opf-source-findings[data-tone="info"] { background: var(--opf-ui-muted-2); }
3128
+ .opf-source-findings-toggle {
3129
+ display: flex;
3130
+ align-items: center;
3131
+ gap: 8px;
3132
+ flex: none;
3133
+ width: 100%;
3134
+ min-height: var(--_h);
3135
+ padding: 0 10px 0 14px;
3136
+ border: 0;
3137
+ background: transparent;
3138
+ color: var(--opf-ui-danger);
3139
+ font-size: 12px;
3140
+ font-weight: 500;
3141
+ text-align: left;
3142
+ cursor: pointer;
3143
+ }
3144
+ .opf-source-findings[data-tone="warning"] .opf-source-findings-toggle { color: var(--opf-ui-warn); }
3145
+ .opf-source-findings[data-tone="info"] .opf-source-findings-toggle { color: var(--opf-ui-muted-fg); }
3146
+ .opf-source-findings-toggle > .opf-source-icon { margin-left: auto; transition: transform var(--opf-ui-ease); }
3147
+ .opf-source-findings-toggle[aria-expanded="false"] > .opf-source-icon { transform: rotate(-90deg); }
3148
+ .opf-source-findings-icon { display: inline-grid; place-items: center; }
3149
+ .opf-source-findings-list { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0 8px 8px; list-style: none; overflow: auto; }
3150
+ .opf-source-finding {
3151
+ display: flex;
3152
+ align-items: baseline;
3153
+ gap: 8px;
3154
+ width: 100%;
3155
+ min-height: calc(var(--_h) - 4px);
3156
+ padding: 3px 6px;
3157
+ border: 0;
3158
+ border-radius: var(--opf-ui-radius-sm);
3159
+ background: transparent;
3160
+ font-size: 12.5px;
3161
+ text-align: left;
3162
+ cursor: pointer;
3163
+ transition: background-color var(--opf-ui-ease);
3164
+ }
3165
+ .opf-source-finding:hover { background: var(--opf-ui-muted); }
3166
+ .opf-source-finding-path {
3167
+ flex: none;
3168
+ padding: 1px 5px;
3169
+ border-radius: var(--opf-ui-radius-sm);
3170
+ background: color-mix(in srgb, var(--opf-ui-danger) 10%, transparent);
3171
+ color: var(--opf-ui-danger);
3172
+ font: 12px var(--opf-ui-mono);
3173
+ }
3174
+ .opf-source-finding[data-severity="warning"] .opf-source-finding-path { background: color-mix(in srgb, var(--opf-ui-warn) 12%, transparent); color: var(--opf-ui-warn); }
3175
+ .opf-source-finding[data-severity="info"] .opf-source-finding-path { background: var(--opf-ui-muted); color: var(--opf-ui-muted-fg); }
3176
+ .opf-source-finding-message { min-width: 0; color: var(--opf-ui-muted-fg); overflow-wrap: anywhere; }
3177
+ .opf-source-finding-line { flex: none; margin-left: auto; color: var(--opf-ui-muted-fg); font: 11px var(--opf-ui-mono); }
3178
+ .opf-source-finding-more { padding: 3px 6px; color: var(--opf-ui-muted-fg); font-size: 12px; }
3179
+
3180
+ .opf-source-status { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
3181
+
3182
+ @media (prefers-reduced-motion: reduce) {
3183
+ .opf-source *,
3184
+ .opf-source *::before { transition: none !important; }
3185
+ }
3186
+
3187
+ /* thumbnails.css */
3188
+ /* Thumbnail strip (RR-98). Uses only --opf-ui-* tokens. */
3189
+ .opf-thumbs {
3190
+ position: relative;
3191
+ box-sizing: border-box;
3192
+ min-width: 0;
3193
+ min-height: 0;
3194
+ font-family: var(--opf-ui-font);
3195
+ color: var(--opf-ui-fg);
3196
+ scrollbar-width: thin;
3197
+ }
3198
+ .opf-thumbs[data-orientation="horizontal"] {
3199
+ overflow-x: auto;
3200
+ overflow-y: hidden;
3201
+ }
3202
+ .opf-thumbs[data-orientation="vertical"] {
3203
+ overflow-x: hidden;
3204
+ overflow-y: auto;
3205
+ }
3206
+ .opf-thumbs-list {
3207
+ display: flex;
3208
+ gap: 12px;
3209
+ margin: 0;
3210
+ /* Room for the 2px ring and its 2px offset, which the scroll container would otherwise clip. */
3211
+ padding: 6px 6px 6px;
3212
+ list-style: none;
3213
+ }
3214
+ .opf-thumbs[data-orientation="horizontal"] .opf-thumbs-list {
3215
+ flex-direction: row;
3216
+ align-items: flex-start;
3217
+ width: max-content;
3218
+ }
3219
+ .opf-thumbs[data-orientation="vertical"] .opf-thumbs-list {
3220
+ flex-direction: column;
3221
+ }
3222
+ .opf-thumbs[data-density="touch"] .opf-thumbs-list {
3223
+ gap: 16px;
3224
+ }
3225
+ .opf-thumbs-slot {
3226
+ flex: none;
3227
+ width: var(--opf-thumbs-w);
3228
+ }
3229
+ .opf-thumbs-item {
3230
+ display: flex;
3231
+ flex-direction: column;
3232
+ align-items: stretch;
3233
+ justify-content: flex-start;
3234
+ gap: 6px;
3235
+ box-sizing: border-box;
3236
+ width: 100%;
3237
+ min-height: 0;
3238
+ margin: 0;
3239
+ padding: 0;
3240
+ font-weight: 400;
3241
+ white-space: normal;
3242
+ border: 0;
3243
+ border-radius: var(--opf-ui-radius-sm);
3244
+ background: transparent;
3245
+ color: var(--opf-ui-muted-fg);
3246
+ font: inherit;
3247
+ text-align: left;
3248
+ cursor: pointer;
3249
+ transition: color var(--opf-ui-ease);
3250
+ }
3251
+ .opf-thumbs-item:hover {
3252
+ color: var(--opf-ui-fg);
3253
+ }
3254
+ .opf-thumbs-item[aria-current="true"] {
3255
+ color: var(--opf-ui-accent-strong);
3256
+ }
3257
+ .opf-thumbs-item:focus-visible {
3258
+ outline: 2px solid var(--opf-ui-ring);
3259
+ outline-offset: 2px;
3260
+ }
3261
+ .opf-thumbs-frame {
3262
+ display: block;
3263
+ box-sizing: border-box;
3264
+ width: 100%;
3265
+ overflow: hidden;
3266
+ aspect-ratio: var(--opf-thumbs-ratio);
3267
+ border-radius: 3px;
3268
+ background: var(--opf-ui-muted-2);
3269
+ box-shadow: 0 0 0 1px var(--opf-ui-border);
3270
+ outline: 2px solid transparent;
3271
+ outline-offset: 2px;
3272
+ transition: outline-color var(--opf-ui-ease);
3273
+ pointer-events: none;
3274
+ }
3275
+ .opf-thumbs-item[aria-current="true"] .opf-thumbs-frame {
3276
+ outline-color: var(--opf-ui-accent);
3277
+ }
3278
+ .opf-thumbs-frame > svg {
3279
+ display: block;
3280
+ width: 100%;
3281
+ height: auto;
3282
+ }
3283
+ .opf-thumbs-frame[data-state="error"] {
3284
+ display: grid;
3285
+ place-items: center;
3286
+ padding: 4px;
3287
+ font: 11.5px/1.3 var(--opf-ui-mono);
3288
+ text-align: center;
3289
+ color: var(--opf-ui-muted-fg);
3290
+ }
3291
+ .opf-thumbs-item[data-hidden="true"] .opf-thumbs-frame {
3292
+ opacity: 0.55;
3293
+ }
3294
+ .opf-thumbs-label {
3295
+ position: relative;
3296
+ display: flex;
3297
+ gap: 6px;
3298
+ width: 100%;
3299
+ min-width: 0;
3300
+ font-size: 12px;
3301
+ line-height: 1.4;
3302
+ white-space: nowrap;
3303
+ }
3304
+ .opf-thumbs-index {
3305
+ flex: none;
3306
+ font-family: var(--opf-ui-mono);
3307
+ }
3308
+ .opf-thumbs-title {
3309
+ min-width: 0;
3310
+ overflow: hidden;
3311
+ text-overflow: ellipsis;
3312
+ }
3313
+ .opf-thumbs-title[data-untitled="true"] {
3314
+ font-style: italic;
3315
+ }
3316
+ /* The "hidden" note is for assistive technology; the dimmed thumbnail shows it visually. */
3317
+ .opf-thumbs-note {
3318
+ position: absolute;
3319
+ width: 1px;
3320
+ height: 1px;
3321
+ margin: -1px;
3322
+ padding: 0;
3323
+ overflow: hidden;
3324
+ clip: rect(0, 0, 0, 0);
3325
+ white-space: nowrap;
3326
+ border: 0;
3327
+ }
3328
+ .opf-thumbs[data-density="touch"] .opf-thumbs-item {
3329
+ min-height: 40px;
3330
+ }
3331
+ .opf-thumbs[data-density="touch"] .opf-thumbs-label {
3332
+ font-size: 12.5px;
3333
+ }
3334
+ @media (prefers-reduced-motion: reduce) {
3335
+ .opf-thumbs-item,
3336
+ .opf-thumbs-frame {
3337
+ transition: none;
3338
+ }
3339
+ }