pdf-presenter 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,669 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ html,
6
+ body {
7
+ margin: 0;
8
+ padding: 0;
9
+ height: 100%;
10
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui,
11
+ "Helvetica Neue", sans-serif;
12
+ background: #000;
13
+ color: #f5f5f5;
14
+ overflow: hidden;
15
+ }
16
+
17
+ /* ==========================================================================
18
+ Audience view
19
+ ========================================================================== */
20
+
21
+ body.audience {
22
+ background: #000;
23
+ }
24
+
25
+ .stage {
26
+ position: fixed;
27
+ inset: 0;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ overflow: hidden;
32
+ }
33
+
34
+ #slide-canvas {
35
+ max-width: 100%;
36
+ max-height: 100%;
37
+ box-shadow: 0 0 60px rgba(0, 0, 0, 0.6);
38
+ }
39
+
40
+ .overlay {
41
+ position: fixed;
42
+ inset: 0;
43
+ background: #000;
44
+ pointer-events: none;
45
+ }
46
+
47
+ .overlay.hidden {
48
+ display: none;
49
+ }
50
+
51
+ .freeze-indicator {
52
+ position: fixed;
53
+ top: 16px;
54
+ right: 16px;
55
+ padding: 4px 10px;
56
+ background: rgba(255, 255, 255, 0.12);
57
+ color: #fff;
58
+ font-size: 12px;
59
+ letter-spacing: 0.1em;
60
+ border-radius: 4px;
61
+ }
62
+
63
+ .freeze-indicator.hidden {
64
+ display: none;
65
+ }
66
+
67
+ .status {
68
+ position: fixed;
69
+ bottom: 16px;
70
+ right: 16px;
71
+ font-size: 12px;
72
+ color: rgba(255, 255, 255, 0.35);
73
+ font-variant-numeric: tabular-nums;
74
+ }
75
+
76
+ /* ==========================================================================
77
+ Presenter view
78
+ ========================================================================== */
79
+
80
+ body.presenter {
81
+ background: #0b0d10;
82
+ color: #e6e6e6;
83
+ }
84
+
85
+ .layout {
86
+ display: grid;
87
+ height: 100vh;
88
+ width: 100vw;
89
+ padding: 12px;
90
+ grid-template-columns: var(--col-left, 66%) 10px 1fr;
91
+ grid-template-rows: 1fr;
92
+ /* no gap — the 10px divider column is the visual separator */
93
+ }
94
+
95
+ /* Each column is its own nested grid so the horizontal split is independent
96
+ of the other column. The row split is driven by a CSS var scoped to the
97
+ column element, which resizable-layout.js writes on mouse-drag. */
98
+ .col {
99
+ display: grid;
100
+ min-width: 0;
101
+ min-height: 0;
102
+ }
103
+ .col-left {
104
+ grid-column: 1;
105
+ grid-template-rows: var(--row-top-left, 60%) 10px 1fr;
106
+ }
107
+ .col-right {
108
+ grid-column: 3;
109
+ grid-template-rows: var(--row-top-right, 60%) 10px 1fr;
110
+ }
111
+
112
+ .current {
113
+ grid-row: 1;
114
+ }
115
+ .next {
116
+ grid-row: 1;
117
+ }
118
+ .notes {
119
+ grid-row: 3;
120
+ }
121
+ .meta {
122
+ grid-row: 3;
123
+ }
124
+
125
+ /* Draggable split handles. Visual is a small green grip centered in the
126
+ 10px divider track; the track itself extends across the full row/column
127
+ so the hit area is the entire line, not just the grip. The col divider
128
+ sits in the OUTER grid, the row dividers sit INSIDE their respective
129
+ .col-left / .col-right nested grids — they never overlap, so no
130
+ z-index gymnastics are needed. */
131
+ .divider-col {
132
+ grid-column: 2;
133
+ grid-row: 1;
134
+ cursor: col-resize;
135
+ position: relative;
136
+ background: transparent;
137
+ }
138
+ .divider-col::before {
139
+ content: "";
140
+ position: absolute;
141
+ top: 50%;
142
+ left: 50%;
143
+ transform: translate(-50%, -50%);
144
+ width: 2px;
145
+ height: 48px;
146
+ background: #2d333b;
147
+ border-radius: 1px;
148
+ transition: background 0.1s ease, height 0.1s ease;
149
+ }
150
+ .divider-col:hover::before,
151
+ .divider-col.dragging::before {
152
+ background: #7fd4a0;
153
+ height: 64px;
154
+ }
155
+
156
+ .divider-row {
157
+ grid-row: 2;
158
+ cursor: row-resize;
159
+ position: relative;
160
+ background: transparent;
161
+ }
162
+ .divider-row::before {
163
+ content: "";
164
+ position: absolute;
165
+ top: 50%;
166
+ left: 50%;
167
+ transform: translate(-50%, -50%);
168
+ width: 48px;
169
+ height: 2px;
170
+ background: #2d333b;
171
+ border-radius: 1px;
172
+ transition: background 0.1s ease, width 0.1s ease;
173
+ }
174
+ .divider-row:hover::before,
175
+ .divider-row.dragging::before {
176
+ background: #7fd4a0;
177
+ width: 64px;
178
+ }
179
+
180
+ .current,
181
+ .next,
182
+ .notes,
183
+ .meta {
184
+ background: #15181d;
185
+ border: 1px solid #23272e;
186
+ border-radius: 8px;
187
+ display: flex;
188
+ flex-direction: column;
189
+ overflow: hidden;
190
+ }
191
+
192
+ .panel-title {
193
+ padding: 8px 12px;
194
+ font-size: 11px;
195
+ text-transform: uppercase;
196
+ letter-spacing: 0.15em;
197
+ color: #7a8291;
198
+ border-bottom: 1px solid #23272e;
199
+ background: #11141a;
200
+ display: flex;
201
+ align-items: center;
202
+ gap: 12px;
203
+ }
204
+
205
+ .notes-status {
206
+ font-size: 10px;
207
+ letter-spacing: 0.1em;
208
+ color: #5a6270;
209
+ min-width: 60px;
210
+ }
211
+
212
+ .notes-status.saving {
213
+ color: #e8c36a;
214
+ }
215
+ .notes-status.saved {
216
+ color: #7fd4a0;
217
+ }
218
+ .notes-status.error {
219
+ color: #e87a7a;
220
+ }
221
+
222
+ .notes-hint {
223
+ flex: 1;
224
+ font-size: 10px;
225
+ font-style: italic;
226
+ color: #5a6270;
227
+ letter-spacing: 0;
228
+ text-transform: none;
229
+ text-align: right;
230
+ white-space: nowrap;
231
+ overflow: hidden;
232
+ text-overflow: ellipsis;
233
+ }
234
+
235
+ .canvas-wrap {
236
+ flex: 1;
237
+ display: flex;
238
+ align-items: center;
239
+ justify-content: center;
240
+ padding: 12px;
241
+ overflow: hidden;
242
+ background: #000;
243
+ }
244
+
245
+ #current-canvas,
246
+ #next-canvas {
247
+ max-width: 100%;
248
+ max-height: 100%;
249
+ }
250
+
251
+ textarea.notes-body {
252
+ flex: 1;
253
+ width: 100%;
254
+ padding: 16px 20px;
255
+ font-size: 18px;
256
+ line-height: 1.55;
257
+ color: #e6e6e6;
258
+ background: #15181d;
259
+ border: none;
260
+ outline: none;
261
+ resize: none;
262
+ font-family: inherit;
263
+ white-space: pre-wrap;
264
+ }
265
+
266
+ textarea.notes-body::placeholder {
267
+ color: #3e4550;
268
+ font-style: italic;
269
+ }
270
+
271
+ textarea.notes-body:focus {
272
+ background: #181c22;
273
+ box-shadow: inset 0 0 0 1px #2d333b;
274
+ }
275
+
276
+ .meta {
277
+ display: grid;
278
+ grid-template-columns: 1fr auto;
279
+ grid-auto-rows: auto;
280
+ gap: 10px 14px;
281
+ padding: 14px 16px 12px;
282
+ align-content: start;
283
+ }
284
+
285
+ .meta > .timer-row {
286
+ grid-column: 1;
287
+ grid-row: 1;
288
+ display: flex;
289
+ align-items: center;
290
+ gap: 10px;
291
+ }
292
+
293
+ button.timer {
294
+ appearance: none;
295
+ background: transparent;
296
+ border: none;
297
+ padding: 2px 4px 2px 0;
298
+ margin: 0;
299
+ font-size: 44px;
300
+ line-height: 0.95;
301
+ font-weight: 600;
302
+ font-variant-numeric: tabular-nums;
303
+ letter-spacing: 0.02em;
304
+ color: #7fd4a0;
305
+ text-align: left;
306
+ font-family: inherit;
307
+ cursor: pointer;
308
+ border-radius: 4px;
309
+ transition: color 0.1s ease, background 0.1s ease;
310
+ }
311
+
312
+ button.timer:hover {
313
+ background: rgba(127, 212, 160, 0.08);
314
+ }
315
+
316
+ button.timer:focus-visible {
317
+ outline: 1px solid #2d333b;
318
+ outline-offset: 2px;
319
+ }
320
+
321
+ .timer.warn {
322
+ color: #e8c36a;
323
+ }
324
+
325
+ .timer.danger {
326
+ color: #e87a7a;
327
+ }
328
+
329
+ .timer.paused {
330
+ color: #6b7380;
331
+ }
332
+
333
+ .timer.paused:hover {
334
+ background: rgba(107, 115, 128, 0.1);
335
+ }
336
+
337
+ .timer-reset {
338
+ appearance: none;
339
+ width: 28px;
340
+ height: 28px;
341
+ background: #1d222a;
342
+ color: #9aa3b0;
343
+ border: 1px solid #2d333b;
344
+ border-radius: 50%;
345
+ font-size: 16px;
346
+ line-height: 1;
347
+ cursor: pointer;
348
+ padding: 0;
349
+ display: flex;
350
+ align-items: center;
351
+ justify-content: center;
352
+ transition: background 0.1s ease, border-color 0.1s ease, color 0.1s ease;
353
+ font-family: inherit;
354
+ }
355
+
356
+ .timer-reset:hover {
357
+ background: #252b35;
358
+ border-color: #3a4049;
359
+ color: #d0d4dc;
360
+ }
361
+
362
+ .timer-reset:active {
363
+ background: #161a20;
364
+ }
365
+
366
+ .meta > .counter {
367
+ grid-column: 2;
368
+ grid-row: 1;
369
+ align-self: end;
370
+ font-size: 16px;
371
+ font-variant-numeric: tabular-nums;
372
+ color: #c0c6d0;
373
+ padding-bottom: 4px;
374
+ }
375
+
376
+ .meta > .notes-actions {
377
+ grid-column: 1 / -1;
378
+ display: grid;
379
+ grid-template-columns: 1fr 1fr;
380
+ gap: 6px;
381
+ max-width: none;
382
+ width: auto;
383
+ }
384
+
385
+ .notes-actions .notes-action-status {
386
+ grid-column: 1 / -1;
387
+ }
388
+
389
+ .btn {
390
+ appearance: none;
391
+ background: #1d222a;
392
+ color: #d7dbe3;
393
+ border: 1px solid #2d333b;
394
+ border-radius: 4px;
395
+ padding: 9px 10px;
396
+ font-size: 12px;
397
+ font-family: inherit;
398
+ cursor: pointer;
399
+ transition: background 0.1s ease, border-color 0.1s ease;
400
+ }
401
+
402
+ .btn:hover {
403
+ background: #252b35;
404
+ border-color: #3a4049;
405
+ }
406
+
407
+ .btn:active {
408
+ background: #161a20;
409
+ }
410
+
411
+ .btn:disabled {
412
+ opacity: 0.5;
413
+ cursor: not-allowed;
414
+ }
415
+
416
+ .notes-action-status {
417
+ font-size: 10px;
418
+ letter-spacing: 0.05em;
419
+ color: #5a6270;
420
+ text-align: center;
421
+ min-height: 12px;
422
+ }
423
+
424
+ .notes-action-status.ok {
425
+ color: #7fd4a0;
426
+ }
427
+
428
+ .notes-action-status.error {
429
+ color: #e87a7a;
430
+ }
431
+
432
+ /* ==========================================================================
433
+ Recording controls
434
+ ========================================================================== */
435
+
436
+ .meta > .record-panel {
437
+ grid-column: 1 / -1;
438
+ display: flex;
439
+ flex-direction: column;
440
+ gap: 6px;
441
+ padding: 8px 10px;
442
+ border: 1px solid #23272e;
443
+ border-radius: 4px;
444
+ background: #10131a;
445
+ }
446
+
447
+ .record-header {
448
+ display: flex;
449
+ align-items: center;
450
+ gap: 8px;
451
+ font-size: 10px;
452
+ color: #9aa3b0;
453
+ letter-spacing: 0.08em;
454
+ text-transform: uppercase;
455
+ }
456
+
457
+ .record-indicator {
458
+ width: 8px;
459
+ height: 8px;
460
+ border-radius: 50%;
461
+ background: #3d4450;
462
+ }
463
+
464
+ .record-indicator.active {
465
+ background: #e87a7a;
466
+ animation: record-pulse 1.2s ease-in-out infinite;
467
+ }
468
+
469
+ .record-indicator.paused {
470
+ background: #e8c36a;
471
+ animation: none;
472
+ }
473
+
474
+ @keyframes record-pulse {
475
+ 0%, 100% { opacity: 1; }
476
+ 50% { opacity: 0.3; }
477
+ }
478
+
479
+ .record-label {
480
+ flex: 1;
481
+ text-transform: uppercase;
482
+ }
483
+
484
+ .record-elapsed {
485
+ font-variant-numeric: tabular-nums;
486
+ color: #c0c6d0;
487
+ font-size: 12px;
488
+ }
489
+
490
+ .record-buttons {
491
+ display: grid;
492
+ grid-template-columns: 1.2fr 1fr 1fr;
493
+ gap: 5px;
494
+ }
495
+
496
+ .record-buttons .btn {
497
+ padding: 8px 6px;
498
+ font-size: 12px;
499
+ font-weight: 500;
500
+ }
501
+
502
+ .btn-record {
503
+ color: #e87a7a;
504
+ border-color: #3a2d30;
505
+ }
506
+
507
+ .btn-record:hover:not(:disabled) {
508
+ background: #2a1e20;
509
+ border-color: #55383c;
510
+ }
511
+
512
+ /* ==========================================================================
513
+ Modal dialog
514
+ ========================================================================== */
515
+
516
+ .modal {
517
+ position: fixed;
518
+ inset: 0;
519
+ background: rgba(0, 0, 0, 0.65);
520
+ display: flex;
521
+ align-items: center;
522
+ justify-content: center;
523
+ z-index: 1000;
524
+ }
525
+
526
+ .modal.hidden {
527
+ display: none;
528
+ }
529
+
530
+ .modal-card {
531
+ background: #15181d;
532
+ border: 1px solid #2d333b;
533
+ border-radius: 8px;
534
+ padding: 24px 28px;
535
+ min-width: 420px;
536
+ max-width: 560px;
537
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
538
+ }
539
+
540
+ .modal-title {
541
+ margin: 0 0 16px 0;
542
+ font-size: 16px;
543
+ font-weight: 600;
544
+ color: #e6e6e6;
545
+ }
546
+
547
+ .modal-info {
548
+ display: grid;
549
+ grid-template-columns: 90px 1fr;
550
+ gap: 6px 12px;
551
+ margin: 0 0 16px 0;
552
+ font-size: 13px;
553
+ }
554
+
555
+ .modal-info dt {
556
+ color: #7a8291;
557
+ text-transform: uppercase;
558
+ font-size: 10px;
559
+ letter-spacing: 0.1em;
560
+ align-self: center;
561
+ }
562
+
563
+ .modal-info dd {
564
+ margin: 0;
565
+ color: #e6e6e6;
566
+ font-variant-numeric: tabular-nums;
567
+ word-break: break-all;
568
+ }
569
+
570
+ .segment-list {
571
+ list-style: none;
572
+ margin: 0;
573
+ padding: 0;
574
+ max-height: 140px;
575
+ overflow-y: auto;
576
+ border: 1px solid #23272e;
577
+ border-radius: 4px;
578
+ background: #0f1218;
579
+ }
580
+
581
+ .segment-list:empty::before {
582
+ content: "No segments recorded";
583
+ display: block;
584
+ padding: 8px 10px;
585
+ color: #5a6270;
586
+ font-style: italic;
587
+ font-size: 12px;
588
+ }
589
+
590
+ .segment-list li {
591
+ display: grid;
592
+ grid-template-columns: auto 1fr auto;
593
+ gap: 10px;
594
+ padding: 5px 10px;
595
+ font-size: 12px;
596
+ font-variant-numeric: tabular-nums;
597
+ border-bottom: 1px solid #171b21;
598
+ color: #d0d4dc;
599
+ }
600
+
601
+ .segment-list li:last-child {
602
+ border-bottom: none;
603
+ }
604
+
605
+ .segment-list .seg-slide {
606
+ color: #7fd4a0;
607
+ font-weight: 600;
608
+ min-width: 44px;
609
+ }
610
+
611
+ .segment-list .seg-range {
612
+ color: #9aa3b0;
613
+ }
614
+
615
+ .segment-list .seg-dur {
616
+ color: #5a6270;
617
+ font-size: 11px;
618
+ }
619
+
620
+ .modal-error {
621
+ background: #2a1a1c;
622
+ border: 1px solid #55383c;
623
+ color: #f5b5b5;
624
+ padding: 8px 10px;
625
+ border-radius: 4px;
626
+ font-size: 12px;
627
+ margin-bottom: 12px;
628
+ }
629
+
630
+ .modal-error.hidden {
631
+ display: none;
632
+ }
633
+
634
+ .modal-actions {
635
+ display: flex;
636
+ justify-content: flex-end;
637
+ gap: 8px;
638
+ }
639
+
640
+ .btn-primary {
641
+ background: #2b5f3e;
642
+ border-color: #3d7a52;
643
+ color: #e6f5ea;
644
+ }
645
+
646
+ .btn-primary:hover:not(:disabled) {
647
+ background: #347049;
648
+ border-color: #498f63;
649
+ }
650
+
651
+ .meta > .hints {
652
+ grid-column: 1 / -1;
653
+ font-size: 10px;
654
+ color: #5a6270;
655
+ text-align: left;
656
+ line-height: 1.8;
657
+ margin-top: 2px;
658
+ }
659
+
660
+ .hints span {
661
+ display: inline-block;
662
+ padding: 0 5px;
663
+ margin: 0 1px;
664
+ border: 1px solid #2d323b;
665
+ border-radius: 3px;
666
+ color: #9aa3b0;
667
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
668
+ font-size: 9px;
669
+ }