stimulus-pdf-viewer-rails 0.1.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,2843 @@
1
+ // PDF Viewer Styles for stimulus-pdf-viewer
2
+ //
3
+ // CURSOR ASSETS: This stylesheet references cursor SVG files for annotation tools.
4
+ // Copy the cursor files from `assets/cursors/` to your asset pipeline and update
5
+ // the paths in the cursor sections below (search for `cursor: url(`) to match
6
+ // your asset configuration.
7
+ //
8
+ // Default paths assume: `pdf_viewer/cursor-*.svg` in your asset pipeline.
9
+
10
+ // Fullscreen document layout - prevents dual scroll by filling viewport
11
+ // Uses :has() for progressive enhancement - body overflow hidden when fullscreen viewer is present
12
+ body:has(.document-fullscreen) {
13
+ overflow: hidden;
14
+ margin: 0;
15
+ }
16
+
17
+ html:has(.document-fullscreen) {
18
+ // Prevent iOS Safari visual viewport scrolling
19
+ overflow: hidden;
20
+ }
21
+
22
+ .document-fullscreen {
23
+ display: flex;
24
+ flex-direction: column;
25
+ height: 100vh;
26
+ height: 100dvh; // Dynamic viewport height (accounts for mobile browser UI)
27
+ overflow: hidden;
28
+ // Use fixed positioning to truly lock page on iOS Safari
29
+ position: fixed;
30
+ inset: 0;
31
+ width: 100%;
32
+ overscroll-behavior: none;
33
+
34
+ // Header takes natural height
35
+ .document-header {
36
+ flex-shrink: 0;
37
+ }
38
+
39
+ // PDF viewer fills remaining space
40
+ .pdf-viewer-container {
41
+ flex: 1;
42
+ min-height: 0; // Important: allows flex child to shrink below content size
43
+ }
44
+ }
45
+
46
+ // Compact document header - title, actions, and close
47
+ .document-header {
48
+ display: flex;
49
+ align-items: center;
50
+ padding: 8px 16px;
51
+ background: #fff;
52
+ border-bottom: 1px solid #e3ebf6;
53
+ gap: 12px;
54
+ }
55
+
56
+ .document-header-title {
57
+ margin: 0;
58
+ font-size: 16px;
59
+ font-weight: 600;
60
+ color: #12263f;
61
+ white-space: nowrap;
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ min-width: 0;
65
+ flex: 1;
66
+ }
67
+
68
+ .document-header-actions {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: 4px;
72
+ flex-shrink: 0;
73
+ }
74
+
75
+ .document-header-compare-form {
76
+ display: flex;
77
+ margin: 0;
78
+ }
79
+
80
+ .document-header-select {
81
+ height: 32px;
82
+ padding: 0 28px 0 12px;
83
+ border: 1px solid #d2ddec;
84
+ border-radius: 6px;
85
+ background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2395aac9' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 10px center;
86
+ background-size: 12px;
87
+ color: #12263f;
88
+ font-size: 13px;
89
+ cursor: pointer;
90
+ appearance: none;
91
+ max-width: 180px;
92
+
93
+ &:hover {
94
+ border-color: #95aac9;
95
+ }
96
+
97
+ &:focus {
98
+ outline: none;
99
+ border-color: #2c7be5;
100
+ box-shadow: 0 0 0 2px rgba(44, 123, 229, 0.15);
101
+ }
102
+ }
103
+
104
+ .document-header-btn {
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ width: 32px;
109
+ height: 32px;
110
+ padding: 0;
111
+ border: none;
112
+ border-radius: 6px;
113
+ background: none;
114
+ color: #95aac9;
115
+ cursor: pointer;
116
+ transition: all 0.15s ease;
117
+
118
+ &:hover {
119
+ background: #f9fbfd;
120
+ color: #12263f;
121
+ }
122
+ }
123
+
124
+ .document-header-btn-danger {
125
+ &:hover {
126
+ background: #fef2f2;
127
+ color: #e63757;
128
+ }
129
+ }
130
+
131
+ .document-header-btn-text {
132
+ display: flex;
133
+ align-items: center;
134
+ padding: 6px 12px;
135
+ border-radius: 6px;
136
+ color: #2c7be5;
137
+ font-size: 13px;
138
+ font-weight: 500;
139
+ white-space: nowrap;
140
+ transition: all 0.15s ease;
141
+
142
+ &:hover {
143
+ background: #f0f6ff;
144
+ color: #1a68d1;
145
+ }
146
+ }
147
+
148
+ .document-header-close {
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ width: 32px;
153
+ height: 32px;
154
+ border-radius: 6px;
155
+ color: #95aac9;
156
+ transition: all 0.15s ease;
157
+ flex-shrink: 0;
158
+
159
+ &:hover {
160
+ background: #f9fbfd;
161
+ color: #12263f;
162
+ }
163
+ }
164
+
165
+ // Side-by-side comparison grid for comparing two documents
166
+ .document-comparison-grid {
167
+ display: grid;
168
+ grid-template-columns: 1fr 1fr;
169
+ flex: 1;
170
+ min-height: 0;
171
+ gap: 0;
172
+
173
+ .pdf-viewer-container {
174
+ min-height: 0;
175
+ min-width: 0; // Prevent grid blowout - allows children to shrink below content size
176
+ overflow: hidden;
177
+ }
178
+
179
+ // Compact toolbar for comparison view - hide labels, show icons only
180
+ .pdf-toolbar {
181
+ overflow: hidden;
182
+ }
183
+
184
+ .pdf-tool-btn span {
185
+ display: none;
186
+ }
187
+
188
+ .pdf-tool-btn {
189
+ padding: 6px;
190
+ }
191
+
192
+ // Hide less essential tools in comparison view
193
+ .pdf-tool-btn[data-tool="note"],
194
+ .pdf-tool-btn[data-tool="ink"],
195
+ .pdf-toolbar-colors,
196
+ .pdf-toolbar-separator:nth-of-type(2),
197
+ .pdf-toolbar-separator:nth-of-type(3) {
198
+ display: none;
199
+ }
200
+ }
201
+
202
+ // Container
203
+ .pdf-viewer-container {
204
+ /* Define this variable here and not in :root to avoid to reflow all the UI
205
+ when scaling (see #15929). */
206
+ --scale-factor: 1;
207
+ --page-bg-color: unset;
208
+
209
+ // Global dark theme colors (shared by toolbar, sidebars, find-bar)
210
+ --pdf-dark-bg: #38383d;
211
+ --pdf-dark-bg-secondary: #2a2a2e;
212
+ --pdf-dark-border: #3a3a3e;
213
+ --pdf-dark-text: #f9f9fa;
214
+ --pdf-dark-text-secondary: #b1b1b3;
215
+ --pdf-dark-hover: rgba(255, 255, 255, 0.1);
216
+ --pdf-dark-active: rgba(255, 255, 255, 0.15);
217
+ --pdf-dark-separator: rgba(255, 255, 255, 0.2);
218
+ --pdf-dark-input-bg: #4a4a4f;
219
+ --pdf-dark-input-border: #5a5a5f;
220
+ --pdf-accent: #0060df;
221
+ --pdf-accent-hover: #0250bb;
222
+
223
+ position: relative;
224
+ width: 100%;
225
+ height: 100%;
226
+ display: flex;
227
+ flex-direction: column;
228
+ background-color: #525659;
229
+
230
+ // Global hidden class for all PDF viewer components
231
+ .hidden {
232
+ display: none !important;
233
+ }
234
+ }
235
+
236
+ // Toolbar - Modern dark theme inspired by PDF.js
237
+ .pdf-toolbar {
238
+ --toolbar-bg: var(--pdf-dark-bg);
239
+ --toolbar-border: var(--pdf-dark-bg-secondary);
240
+ --toolbar-text: var(--pdf-dark-text);
241
+ --toolbar-text-secondary: var(--pdf-dark-text-secondary);
242
+ --toolbar-hover: var(--pdf-dark-hover);
243
+ --toolbar-active: var(--pdf-dark-active);
244
+ --toolbar-accent: var(--pdf-accent);
245
+ --toolbar-accent-hover: var(--pdf-accent-hover);
246
+ --toolbar-separator: var(--pdf-dark-separator);
247
+ --toolbar-input-bg: var(--pdf-dark-input-bg);
248
+ --toolbar-input-border: var(--pdf-dark-input-border);
249
+
250
+ display: flex;
251
+ align-items: center;
252
+ justify-content: space-between;
253
+ padding: 6px 12px;
254
+ background-color: var(--toolbar-bg);
255
+ border-bottom: 1px solid var(--toolbar-border);
256
+ min-height: 40px;
257
+ gap: 8px;
258
+ }
259
+
260
+ .pdf-toolbar-section {
261
+ display: flex;
262
+ align-items: center;
263
+ gap: 8px;
264
+ }
265
+
266
+ .pdf-toolbar-left {
267
+ flex: 0 0 auto;
268
+ justify-content: flex-start;
269
+ }
270
+
271
+ .pdf-toolbar-right {
272
+ flex: 1;
273
+ justify-content: flex-end;
274
+ }
275
+
276
+ .pdf-toolbar-group {
277
+ display: flex;
278
+ align-items: center;
279
+ gap: 2px;
280
+ }
281
+
282
+ .pdf-toolbar-separator {
283
+ width: 1px;
284
+ height: 20px;
285
+ background-color: var(--toolbar-separator);
286
+ margin: 0 6px;
287
+ }
288
+
289
+ // Page navigation
290
+ .pdf-toolbar-nav {
291
+ gap: 4px;
292
+ }
293
+
294
+ .pdf-page-input-container {
295
+ display: flex;
296
+ align-items: center;
297
+ gap: 4px;
298
+ font-size: 13px;
299
+ color: var(--toolbar-text);
300
+ }
301
+
302
+ .pdf-page-input {
303
+ width: 40px;
304
+ height: 26px;
305
+ padding: 0 6px;
306
+ border: 1px solid var(--toolbar-input-border);
307
+ border-radius: 4px;
308
+ background: var(--toolbar-input-bg);
309
+ color: var(--toolbar-text);
310
+ font-size: 13px;
311
+ text-align: center;
312
+ -moz-appearance: textfield;
313
+
314
+ &::-webkit-outer-spin-button,
315
+ &::-webkit-inner-spin-button {
316
+ -webkit-appearance: none;
317
+ margin: 0;
318
+ }
319
+
320
+ &:focus {
321
+ outline: none;
322
+ border-color: var(--toolbar-accent);
323
+ box-shadow: 0 0 0 1px var(--toolbar-accent);
324
+ }
325
+ }
326
+
327
+ .pdf-page-separator {
328
+ color: var(--toolbar-text-secondary);
329
+ }
330
+
331
+ .pdf-page-count {
332
+ min-width: 20px;
333
+ color: var(--toolbar-text-secondary);
334
+ }
335
+
336
+ // Zoom controls
337
+ .pdf-toolbar-zoom {
338
+ gap: 4px;
339
+ }
340
+
341
+ .pdf-zoom-select {
342
+ height: 26px;
343
+ padding: 0 24px 0 8px;
344
+ border: 1px solid var(--toolbar-input-border);
345
+ border-radius: 4px;
346
+ background: var(--toolbar-input-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23f9f9fa' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 6px center;
347
+ background-size: 12px;
348
+ color: var(--toolbar-text);
349
+ font-size: 13px;
350
+ cursor: pointer;
351
+ appearance: none;
352
+
353
+ &:hover {
354
+ border-color: #6a6a6f;
355
+ background-color: #5a5a5f;
356
+ }
357
+
358
+ &:focus {
359
+ outline: none;
360
+ border-color: var(--toolbar-accent);
361
+ }
362
+ }
363
+
364
+ // Toolbar buttons (icon only - for nav/zoom)
365
+ .pdf-toolbar-btn {
366
+ display: inline-flex;
367
+ align-items: center;
368
+ justify-content: center;
369
+ width: 28px;
370
+ height: 28px;
371
+ padding: 0;
372
+ border: none;
373
+ border-radius: 4px;
374
+ background: transparent;
375
+ color: var(--toolbar-text);
376
+ cursor: pointer;
377
+ transition: background-color 0.1s ease;
378
+
379
+ &:hover:not(:disabled) {
380
+ background-color: var(--toolbar-hover);
381
+ }
382
+
383
+ &:active:not(:disabled) {
384
+ background-color: var(--toolbar-active);
385
+ }
386
+
387
+ &:disabled {
388
+ opacity: 0.4;
389
+ cursor: not-allowed;
390
+ }
391
+
392
+ svg {
393
+ width: 16px;
394
+ height: 16px;
395
+ flex-shrink: 0;
396
+ }
397
+ }
398
+
399
+ // Tool buttons with text labels (for annotation tools)
400
+ .pdf-tool-btn {
401
+ display: inline-flex;
402
+ align-items: center;
403
+ gap: 6px;
404
+ padding: 6px 12px;
405
+ border: 1px solid transparent;
406
+ border-radius: 6px;
407
+ background: transparent;
408
+ color: var(--toolbar-text);
409
+ font-size: 13px;
410
+ font-weight: 500;
411
+ cursor: pointer;
412
+ transition: all 0.15s ease;
413
+ white-space: nowrap;
414
+
415
+ &:hover:not(:disabled) {
416
+ background-color: var(--toolbar-hover);
417
+ border-color: var(--toolbar-separator);
418
+ }
419
+
420
+ &:active:not(:disabled) {
421
+ background-color: var(--toolbar-active);
422
+ }
423
+
424
+ &:disabled {
425
+ opacity: 0.4;
426
+ cursor: not-allowed;
427
+ }
428
+
429
+ // Active/selected tool state - prominent border like the example
430
+ &.active {
431
+ background-color: rgba(255, 255, 255, 0.95);
432
+ border-color: #333;
433
+ color: #333;
434
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
435
+
436
+ svg {
437
+ stroke: #333;
438
+ }
439
+
440
+ &:hover {
441
+ background-color: #fff;
442
+ }
443
+ }
444
+
445
+ svg {
446
+ width: 18px;
447
+ height: 18px;
448
+ flex-shrink: 0;
449
+ }
450
+
451
+ span {
452
+ line-height: 1;
453
+ }
454
+ }
455
+
456
+ // Tool group with better spacing
457
+ .pdf-toolbar-tools {
458
+ gap: 4px;
459
+ }
460
+
461
+ // Body wrapper (contains sidebar and pages)
462
+ .pdf-viewer-body {
463
+ flex: 1;
464
+ display: flex;
465
+ overflow: hidden;
466
+ position: relative;
467
+ }
468
+
469
+ // Base sidebar class (shared by thumbnail and annotation sidebars)
470
+ .pdf-sidebar {
471
+ --sidebar-bg: var(--pdf-dark-bg-secondary);
472
+ --sidebar-border: var(--pdf-dark-border);
473
+ --sidebar-text: var(--pdf-dark-text);
474
+ --sidebar-text-secondary: var(--pdf-dark-text-secondary);
475
+ --sidebar-accent: var(--pdf-accent);
476
+
477
+ position: relative;
478
+ width: 0;
479
+ flex-shrink: 0;
480
+ background: var(--sidebar-bg);
481
+ display: flex;
482
+ flex-direction: column;
483
+ overflow: hidden;
484
+ transition: width 0.2s ease, visibility 0s ease 0.2s;
485
+ visibility: hidden;
486
+
487
+ &.open {
488
+ width: var(--sidebar-width);
489
+ visibility: visible;
490
+ transition: width 0.2s ease, visibility 0s linear 0s;
491
+ }
492
+
493
+ &.resizing {
494
+ transition: none;
495
+ }
496
+
497
+ // Position-specific borders
498
+ &.is-left {
499
+ border-right: 1px solid var(--sidebar-border);
500
+ }
501
+
502
+ &.is-right {
503
+ border-left: 1px solid var(--sidebar-border);
504
+ }
505
+ }
506
+
507
+ // Thumbnail Sidebar (extends base .pdf-sidebar)
508
+ .pdf-thumbnail-sidebar {
509
+ // Thumbnail-specific variables
510
+ --sidebar-width: 200px;
511
+ --thumbnail-bg: #525659;
512
+ --thumbnail-border: #6a6a6f;
513
+ --thumbnail-active-border: #0060df;
514
+ }
515
+
516
+ .pdf-sidebar-header {
517
+ display: flex;
518
+ align-items: center;
519
+ justify-content: space-between;
520
+ padding: 12px 12px 12px 16px;
521
+ border-bottom: 1px solid var(--sidebar-border);
522
+ flex-shrink: 0;
523
+ }
524
+
525
+ .pdf-sidebar-title {
526
+ font-size: 14px;
527
+ font-weight: 500;
528
+ color: var(--sidebar-text);
529
+ }
530
+
531
+ .pdf-sidebar-close {
532
+ display: flex;
533
+ align-items: center;
534
+ justify-content: center;
535
+ width: 24px;
536
+ height: 24px;
537
+ padding: 0;
538
+ border: none;
539
+ border-radius: 4px;
540
+ background: transparent;
541
+ color: var(--sidebar-text-secondary);
542
+ cursor: pointer;
543
+
544
+ &:hover {
545
+ background: rgba(255, 255, 255, 0.1);
546
+ color: var(--sidebar-text);
547
+ }
548
+
549
+ svg {
550
+ width: 14px;
551
+ height: 14px;
552
+ }
553
+ }
554
+
555
+ .pdf-sidebar-content {
556
+ flex: 1;
557
+ overflow-y: auto;
558
+ overflow-x: hidden;
559
+ padding: 12px;
560
+ display: flex;
561
+ flex-direction: column;
562
+ align-items: center;
563
+ gap: 12px;
564
+ }
565
+
566
+ .pdf-sidebar-resizer {
567
+ position: absolute;
568
+ top: 0;
569
+ width: 6px;
570
+ height: 100%;
571
+ cursor: ew-resize;
572
+ z-index: 5;
573
+
574
+ // Position based on parent sidebar
575
+ .pdf-sidebar.is-left & {
576
+ right: -3px;
577
+ }
578
+
579
+ .pdf-sidebar.is-right & {
580
+ left: -3px;
581
+ }
582
+
583
+ &:hover,
584
+ .pdf-sidebar.resizing & {
585
+ background: var(--sidebar-accent, var(--toolbar-accent, #0060df));
586
+ }
587
+ }
588
+
589
+ // Individual thumbnail
590
+ .thumbnail {
591
+ position: relative;
592
+ display: flex;
593
+ flex-direction: column;
594
+ align-items: center;
595
+ gap: 4px;
596
+ cursor: pointer;
597
+ border-radius: 4px;
598
+ padding: 4px;
599
+ transition: background-color 0.15s ease;
600
+
601
+ &:hover {
602
+ background: rgba(255, 255, 255, 0.05);
603
+ }
604
+
605
+ &:focus {
606
+ outline: 2px solid var(--thumbnail-active-border);
607
+ outline-offset: 2px;
608
+ }
609
+
610
+ &.active {
611
+ .thumbnail-image {
612
+ box-shadow: 0 0 0 2px var(--thumbnail-active-border);
613
+ }
614
+
615
+ .thumbnail-label {
616
+ color: var(--sidebar-text);
617
+ font-weight: 600;
618
+ }
619
+ }
620
+ }
621
+
622
+ .thumbnail-image {
623
+ background: var(--thumbnail-bg);
624
+ border-radius: 2px;
625
+ overflow: hidden;
626
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
627
+ transition: box-shadow 0.15s ease;
628
+
629
+ .thumbnail:hover & {
630
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
631
+ }
632
+ }
633
+
634
+ .thumbnail-canvas {
635
+ display: block;
636
+ }
637
+
638
+ .thumbnail-label {
639
+ font-size: 12px;
640
+ color: var(--sidebar-text-secondary);
641
+ transition: color 0.15s ease;
642
+ }
643
+
644
+ // Pages container
645
+ .pdf-pages-container {
646
+ flex: 1;
647
+ overflow: auto;
648
+ display: flex;
649
+ flex-direction: column;
650
+ align-items: center;
651
+ padding: 1rem;
652
+ gap: 1rem;
653
+ position: relative;
654
+ }
655
+
656
+ // Individual page
657
+ .pdf-page {
658
+ // CSS variables set by viewer.js
659
+ --page-width: 612px; // Default US Letter width
660
+ --page-height: 792px; // Default US Letter height
661
+
662
+ // For PDF.js text layer compatibility
663
+ --user-unit: 1;
664
+ --scale-factor: var(--display-scale, 1);
665
+ --total-scale-factor: var(--display-scale, 1);
666
+
667
+ position: relative;
668
+ flex-shrink: 0; // Prevent pages from collapsing in flex container
669
+ background: white;
670
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
671
+ margin: 0 auto;
672
+
673
+ // Create isolated stacking context for blend modes to work within the page
674
+ isolation: isolate;
675
+
676
+ // Use CSS variables for dimensions, scaled by --display-scale
677
+ width: calc(var(--page-width) * var(--display-scale, 1));
678
+ height: calc(var(--page-height) * var(--display-scale, 1));
679
+
680
+ // PDF canvas is rendered at the correct size - no CSS transform needed
681
+ canvas.pdf-canvas {
682
+ display: block;
683
+ position: absolute;
684
+ top: 0;
685
+ left: 0;
686
+ // Canvas CSS width/height are set by JS to match the displayed size
687
+ }
688
+
689
+ // iOS selection highlight overlay (iOS Safari ignores ::selection CSS)
690
+ // These are created dynamically by JavaScript on iOS devices
691
+ .ios-selection-highlight {
692
+ background-color: rgb(0 100 255 / 0.3);
693
+ border-radius: 2px;
694
+ }
695
+ }
696
+
697
+ .textLayer {
698
+ position: absolute;
699
+ text-align: initial;
700
+ top: 0;
701
+ left: 0;
702
+ // Size matches displayed page (set by PDF.js TextLayer at displayViewport scale)
703
+ width: calc(var(--page-width) * var(--display-scale, 1));
704
+ height: calc(var(--page-height) * var(--display-scale, 1));
705
+ overflow: hidden; // Fallback for Safari 15.x which doesn't support clip
706
+ overflow: clip;
707
+ opacity: 1;
708
+ line-height: 1;
709
+ text-size-adjust: none;
710
+ forced-color-adjust: none;
711
+ caret-color: CanvasText;
712
+ z-index: 0;
713
+
714
+ :is(span, br) {
715
+ color: transparent;
716
+ position: absolute;
717
+ white-space: pre;
718
+ cursor: text;
719
+ transform-origin: 0% 0%;
720
+ }
721
+
722
+ /* We multiply the font size by --min-font-size, and then scale the text
723
+ * elements by 1/--min-font-size. This allows us to effectively ignore the
724
+ * minimum font size enforced by the browser, so that the text layer <span>s
725
+ * can always match the size of the text in the canvas. */
726
+ --min-font-size: 1;
727
+ --text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size));
728
+ --min-font-size-inv: calc(1 / var(--min-font-size));
729
+
730
+ > :not(.markedContent),
731
+ .markedContent span:not(.markedContent) {
732
+ z-index: 1;
733
+
734
+ --font-height: 0; /* set by text_layer.js */
735
+ font-size: calc(var(--text-scale-factor) * var(--font-height));
736
+
737
+ --scale-x: 1;
738
+ --rotate: 0deg;
739
+ transform: rotate(var(--rotate)) scaleX(var(--scale-x))
740
+ scale(var(--min-font-size-inv));
741
+ }
742
+
743
+ .markedContent {
744
+ display: contents;
745
+ }
746
+
747
+ span[role="img"] {
748
+ user-select: none;
749
+ cursor: default;
750
+ }
751
+
752
+ .highlight {
753
+ --highlight-bg-color: rgb(180 0 170 / 0.25);
754
+ --highlight-selected-bg-color: rgb(0 100 0 / 0.25);
755
+ --highlight-backdrop-filter: none;
756
+ --highlight-selected-backdrop-filter: none;
757
+
758
+ @media screen and (forced-colors: active) {
759
+ --highlight-bg-color: transparent;
760
+ --highlight-selected-bg-color: transparent;
761
+ --highlight-backdrop-filter: var(--hcm-highlight-filter);
762
+ --highlight-selected-backdrop-filter: var(
763
+ --hcm-highlight-selected-filter
764
+ );
765
+ }
766
+
767
+ margin: -1px;
768
+ padding: 1px;
769
+ background-color: var(--highlight-bg-color);
770
+ backdrop-filter: var(--highlight-backdrop-filter);
771
+ border-radius: 4px;
772
+
773
+ &.appended {
774
+ position: initial;
775
+ }
776
+
777
+ &.begin {
778
+ border-radius: 4px 0 0 4px;
779
+ }
780
+
781
+ &.end {
782
+ border-radius: 0 4px 4px 0;
783
+ }
784
+
785
+ &.middle {
786
+ border-radius: 0;
787
+ }
788
+
789
+ &.selected {
790
+ background-color: var(--highlight-selected-bg-color);
791
+ backdrop-filter: var(--highlight-selected-backdrop-filter);
792
+ }
793
+ }
794
+
795
+ ::selection {
796
+ // Use highlight color when in highlight mode, otherwise light blue
797
+ background: var(--selection-highlight-color, rgb(0 100 255 / 0.3));
798
+ }
799
+
800
+ /* Avoids https://github.com/mozilla/pdf.js/issues/13840 in Chrome */
801
+ /*#if !MOZCENTRAL*/
802
+ br::selection {
803
+ background: transparent;
804
+ }
805
+ /*#endif*/
806
+
807
+ .endOfContent {
808
+ display: block;
809
+ position: absolute;
810
+ inset: 100% 0 0;
811
+ z-index: 0;
812
+ cursor: default;
813
+ user-select: none;
814
+ }
815
+
816
+ &.selecting .endOfContent {
817
+ top: 0;
818
+ }
819
+ }
820
+
821
+ // SVG layer for highlight rendering - sibling of canvas for blend mode to work
822
+ .highlight-svg-layer {
823
+ position: absolute;
824
+ top: 0;
825
+ left: 0;
826
+ width: 100%;
827
+ height: 100%;
828
+ pointer-events: none;
829
+ // No transform - uses pre-scaled coordinates from JS
830
+ // This allows mix-blend-mode to blend with the canvas below
831
+ mix-blend-mode: multiply;
832
+ overflow: visible;
833
+ }
834
+
835
+ // SVG layer for underline rendering - no blend mode so colors stay true
836
+ .underline-svg-layer {
837
+ position: absolute;
838
+ top: 0;
839
+ left: 0;
840
+ width: 100%;
841
+ height: 100%;
842
+ pointer-events: none;
843
+ overflow: visible;
844
+ }
845
+
846
+ // Annotation layer (above text layer via DOM order)
847
+ .annotation-layer {
848
+ position: absolute;
849
+ top: 0;
850
+ left: 0;
851
+ // Size matches displayed page
852
+ width: calc(var(--page-width) * var(--display-scale, 1));
853
+ height: calc(var(--page-height) * var(--display-scale, 1));
854
+ pointer-events: none;
855
+ // No z-index - rely on DOM order
856
+ }
857
+
858
+ .annotation {
859
+ position: absolute;
860
+ pointer-events: auto;
861
+ cursor: pointer;
862
+
863
+ // Selection and hover states (PDF.js inspired)
864
+ --outline-width: 2px;
865
+ --outline-color: #0060df;
866
+ --outline-around-width: 1px;
867
+ --outline-around-color: #f0f0f4;
868
+ --hover-outline-color: #8f8f9d;
869
+
870
+ // Hover outline (gray) using box-shadow
871
+ &:hover:not(.selected) {
872
+ box-shadow: 0 0 0 var(--outline-width) var(--hover-outline-color);
873
+ border-radius: 2px;
874
+ }
875
+
876
+ // Selected state (blue outline with white outer border) using box-shadow
877
+ &.selected {
878
+ box-shadow:
879
+ 0 0 0 var(--outline-width) var(--outline-color),
880
+ 0 0 0 calc(var(--outline-width) + var(--outline-around-width)) var(--outline-around-color);
881
+ border-radius: 2px;
882
+ z-index: 100 !important;
883
+ }
884
+ }
885
+
886
+ // Highlight annotations - transparent interactive overlay
887
+ // Actual colored highlight is rendered in .highlight-svg-layer
888
+ .annotation-highlight {
889
+ // Transparent - just for click/selection handling
890
+ background: transparent;
891
+ cursor: pointer;
892
+ }
893
+
894
+ // Annotation Edit Toolbar (appears below selected annotations)
895
+ .annotation-edit-toolbar {
896
+ --toolbar-bg: #f0f0f4;
897
+ --toolbar-border: #8f8f9d;
898
+ --toolbar-shadow: 0 2px 6px rgba(58, 57, 68, 0.2);
899
+ --toolbar-height: 28px;
900
+ --toolbar-offset: 6px;
901
+ --toolbar-fg: #2e2e56;
902
+ --toolbar-hover-bg: #e0e0e6;
903
+ --toolbar-focus-color: #0060df;
904
+
905
+ position: absolute;
906
+ top: 100%;
907
+ left: 50%;
908
+ transform: translateX(-50%);
909
+ transform-origin: top center;
910
+ margin-top: var(--toolbar-offset);
911
+
912
+ // Flipped state: position above the annotation when below would be clipped
913
+ &.flipped {
914
+ top: auto;
915
+ bottom: 100%;
916
+ margin-top: 0;
917
+ margin-bottom: var(--toolbar-offset);
918
+ transform-origin: bottom center;
919
+ }
920
+
921
+ z-index: 1000;
922
+ display: flex;
923
+ flex-direction: column;
924
+ background: var(--toolbar-bg);
925
+ border: 1px solid var(--toolbar-border);
926
+ border-radius: 6px;
927
+ box-shadow: var(--toolbar-shadow);
928
+ z-index: 1000;
929
+ pointer-events: auto;
930
+ // Override any tool-mode cursors inherited from parent
931
+ cursor: default;
932
+
933
+ .toolbar-buttons {
934
+ display: flex;
935
+ align-items: center;
936
+ justify-content: flex-end;
937
+ gap: 0;
938
+ height: var(--toolbar-height);
939
+ padding: 2px;
940
+ }
941
+
942
+ .toolbar-note-content {
943
+ min-width: 200px;
944
+ max-width: 320px;
945
+ padding: 8px 12px;
946
+ border-top: 1px solid var(--toolbar-border);
947
+ font-size: 13px;
948
+ line-height: 1.4;
949
+ color: var(--toolbar-fg);
950
+ white-space: pre-wrap;
951
+ word-break: break-word;
952
+ max-height: 120px;
953
+ overflow-y: auto;
954
+ }
955
+
956
+ .toolbar-divider {
957
+ width: 0;
958
+ height: calc(var(--toolbar-height) - 4px);
959
+ border-left: 1px solid var(--toolbar-border);
960
+ margin: 0 2px;
961
+ }
962
+
963
+ .toolbar-btn {
964
+ display: flex;
965
+ align-items: center;
966
+ justify-content: center;
967
+ width: var(--toolbar-height);
968
+ height: var(--toolbar-height);
969
+ padding: 0;
970
+ border: none;
971
+ border-radius: 2px;
972
+ background: transparent;
973
+ color: var(--toolbar-fg);
974
+ cursor: pointer !important;
975
+
976
+ &:hover {
977
+ background: var(--toolbar-hover-bg);
978
+ }
979
+
980
+ &:focus-visible {
981
+ outline: 2px solid var(--toolbar-focus-color);
982
+ outline-offset: -2px;
983
+ }
984
+
985
+ svg {
986
+ width: 16px;
987
+ height: 16px;
988
+ }
989
+ }
990
+
991
+ .color-picker-btn {
992
+ display: flex;
993
+ align-items: center;
994
+ justify-content: center;
995
+ gap: 3px;
996
+ padding: 0 6px 0 8px;
997
+ height: var(--toolbar-height);
998
+ border: none;
999
+ border-radius: 2px;
1000
+ background: transparent;
1001
+ cursor: pointer !important;
1002
+
1003
+ &:hover {
1004
+ background: var(--toolbar-hover-bg);
1005
+ }
1006
+
1007
+ .color-swatch {
1008
+ width: 14px;
1009
+ height: 14px;
1010
+ flex-shrink: 0;
1011
+ border-radius: 50%;
1012
+ border: 1px solid rgba(0, 0, 0, 0.2);
1013
+ }
1014
+ }
1015
+
1016
+ // Color dropdown
1017
+ .color-dropdown {
1018
+ position: absolute;
1019
+ top: calc(100% + 4px);
1020
+ left: 50%;
1021
+ transform: translateX(-50%);
1022
+ display: flex;
1023
+ flex-direction: row;
1024
+ gap: 8px;
1025
+ padding: 8px;
1026
+ background: var(--toolbar-bg);
1027
+ border: 1px solid var(--toolbar-border);
1028
+ border-radius: 6px;
1029
+ box-shadow: var(--toolbar-shadow);
1030
+ white-space: nowrap;
1031
+
1032
+ // When toolbar is flipped, dropdown should also flip to open upward
1033
+ .flipped & {
1034
+ top: auto;
1035
+ bottom: calc(100% + 4px);
1036
+ }
1037
+
1038
+ .color-option {
1039
+ width: auto;
1040
+ height: auto;
1041
+ padding: 0;
1042
+ border: none;
1043
+ background: transparent;
1044
+ cursor: pointer;
1045
+ display: flex;
1046
+ justify-content: center;
1047
+
1048
+ .color-swatch {
1049
+ width: 16px;
1050
+ height: 16px;
1051
+ border-radius: 50%;
1052
+ border: 1px solid rgba(0, 0, 0, 0.15);
1053
+ outline-offset: 2px;
1054
+ }
1055
+
1056
+ &:hover .color-swatch,
1057
+ &:focus .color-swatch {
1058
+ outline: 2px solid var(--toolbar-focus-color);
1059
+ }
1060
+
1061
+ &[aria-selected="true"] .color-swatch {
1062
+ outline: 2px solid var(--toolbar-focus-color);
1063
+ }
1064
+ }
1065
+ }
1066
+ }
1067
+
1068
+ // Underline annotations
1069
+ .annotation-underline {
1070
+ // Container styles - dimensions set by JS
1071
+ }
1072
+
1073
+ // Note annotations - icon only (SVG is rendered in JS)
1074
+ // Width/height are set by JS using percentage-based sizing
1075
+ .annotation-note {
1076
+ cursor: pointer;
1077
+
1078
+ svg {
1079
+ width: 100%;
1080
+ height: 100%;
1081
+ display: block;
1082
+ }
1083
+
1084
+ // Use more rounded corners for the small note icon
1085
+ &:hover:not(.selected),
1086
+ &.selected {
1087
+ border-radius: 6px;
1088
+ }
1089
+ }
1090
+
1091
+ // Ink annotations (container with nested canvas)
1092
+ .annotation-ink {
1093
+ // Container handles click events, canvas renders the strokes
1094
+ .ink-canvas {
1095
+ pointer-events: none;
1096
+ }
1097
+ }
1098
+
1099
+ // Ink drawing canvas (temporary while drawing)
1100
+ .ink-drawing-canvas {
1101
+ position: absolute;
1102
+ top: 0;
1103
+ left: 0;
1104
+ width: 100%;
1105
+ height: 100%;
1106
+ pointer-events: none;
1107
+ z-index: 50;
1108
+ }
1109
+
1110
+ // Watermark layer
1111
+ .pdf-watermark-layer {
1112
+ position: absolute;
1113
+ top: 0;
1114
+ left: 0;
1115
+ right: 0;
1116
+ bottom: 0;
1117
+ pointer-events: none;
1118
+ z-index: 100;
1119
+ }
1120
+
1121
+ // Annotation Popup (appended to pdf-viewer container for cleanup, but uses fixed positioning)
1122
+ .annotation-popup {
1123
+ position: fixed;
1124
+ z-index: 1000;
1125
+ min-width: 200px;
1126
+ max-width: 300px;
1127
+ background: rgba(50, 50, 50, 0.85);
1128
+ border-radius: 8px;
1129
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
1130
+ font-size: 14px;
1131
+ overflow: hidden;
1132
+ backdrop-filter: blur(8px);
1133
+ -webkit-backdrop-filter: blur(8px);
1134
+ }
1135
+
1136
+ .annotation-popup-header {
1137
+ display: flex;
1138
+ align-items: center;
1139
+ gap: 0.5rem;
1140
+ padding: 0.5rem 0.75rem;
1141
+ background: #f5f5f5;
1142
+ border-bottom: 1px solid #e0e0e0;
1143
+ cursor: move;
1144
+ }
1145
+
1146
+ .annotation-popup-date {
1147
+ flex: 1;
1148
+ color: #666;
1149
+ font-size: 12px;
1150
+ }
1151
+
1152
+ .annotation-popup-btn {
1153
+ display: inline-flex;
1154
+ align-items: center;
1155
+ justify-content: center;
1156
+ width: 28px;
1157
+ height: 28px;
1158
+ padding: 0;
1159
+ border: none;
1160
+ border-radius: 4px;
1161
+ background: transparent;
1162
+ color: #666;
1163
+ cursor: pointer;
1164
+
1165
+ &:hover {
1166
+ background-color: #e0e0e0;
1167
+ color: #333;
1168
+ }
1169
+
1170
+ &.delete:hover {
1171
+ background-color: #ffebee;
1172
+ color: #c62828;
1173
+ }
1174
+ }
1175
+
1176
+ .annotation-popup-content {
1177
+ padding: 0.75rem;
1178
+ color: #333;
1179
+ max-height: 200px;
1180
+ overflow-y: auto;
1181
+ white-space: pre-wrap;
1182
+ word-wrap: break-word;
1183
+ }
1184
+
1185
+ // Undo Bar
1186
+ .pdf-undo-bar {
1187
+ position: fixed;
1188
+ bottom: 20px;
1189
+ left: 50%;
1190
+ transform: translateX(-50%);
1191
+ z-index: 1001;
1192
+ display: flex;
1193
+ align-items: center;
1194
+ gap: 1rem;
1195
+ padding: 0.75rem 1rem;
1196
+ background: rgba(50, 50, 50, 0.85);
1197
+ color: white;
1198
+ border-radius: 8px;
1199
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
1200
+ font-size: 14px;
1201
+ opacity: 1;
1202
+ transition: opacity 0.3s ease;
1203
+ backdrop-filter: blur(8px);
1204
+ -webkit-backdrop-filter: blur(8px);
1205
+
1206
+ &.hidden {
1207
+ display: flex !important;
1208
+ opacity: 0;
1209
+ pointer-events: none;
1210
+ }
1211
+ }
1212
+
1213
+ .pdf-undo-bar-message {
1214
+ color: #fff;
1215
+ }
1216
+
1217
+ .pdf-undo-bar-btn {
1218
+ padding: 0.25rem 0.75rem;
1219
+ border: none;
1220
+ border-radius: 4px;
1221
+ background: transparent;
1222
+ color: #64b5f6;
1223
+ font-size: 14px;
1224
+ font-weight: 500;
1225
+ cursor: pointer;
1226
+ text-transform: uppercase;
1227
+
1228
+ &:hover {
1229
+ background: rgba(255, 255, 255, 0.1);
1230
+ }
1231
+ }
1232
+
1233
+ .pdf-undo-bar-dismiss {
1234
+ padding: 0.25rem;
1235
+ border: none;
1236
+ background: transparent;
1237
+ color: #999;
1238
+ cursor: pointer;
1239
+ line-height: 1;
1240
+
1241
+ &:hover {
1242
+ color: #fff;
1243
+ }
1244
+ }
1245
+
1246
+ // Color Picker (toolbar integrated)
1247
+ .color-picker {
1248
+ position: relative;
1249
+ }
1250
+
1251
+ .color-picker-toggle {
1252
+ display: flex;
1253
+ align-items: center;
1254
+ gap: 4px;
1255
+ padding: 4px 8px;
1256
+ border: 1px solid var(--toolbar-input-border, #5a5a5f);
1257
+ border-radius: 4px;
1258
+ background: var(--toolbar-input-bg, #4a4a4f);
1259
+ cursor: pointer;
1260
+ transition: background-color 0.1s ease;
1261
+
1262
+ &:hover {
1263
+ border-color: #6a6a6f;
1264
+ background-color: #5a5a5f;
1265
+ }
1266
+
1267
+ svg {
1268
+ color: var(--toolbar-text, #f9f9fa);
1269
+ opacity: 0.7;
1270
+ }
1271
+ }
1272
+
1273
+ .color-picker-swatch {
1274
+ width: 16px;
1275
+ height: 16px;
1276
+ border-radius: 3px;
1277
+ border: 1px solid rgba(0, 0, 0, 0.2);
1278
+ }
1279
+
1280
+ .color-picker-dropdown {
1281
+ position: absolute;
1282
+ top: 100%;
1283
+ left: 0;
1284
+ margin-top: 4px;
1285
+ padding: 6px;
1286
+ display: flex;
1287
+ gap: 4px;
1288
+ background: var(--toolbar-bg, #38383d);
1289
+ border: 1px solid var(--toolbar-border, #2a2a2e);
1290
+ border-radius: 6px;
1291
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
1292
+ z-index: 1000;
1293
+
1294
+ // On mobile, align to right edge to stay on screen
1295
+ @media (max-width: 600px) {
1296
+ left: auto;
1297
+ right: 0;
1298
+ }
1299
+ }
1300
+
1301
+ .color-picker-option {
1302
+ display: flex;
1303
+ align-items: center;
1304
+ justify-content: center;
1305
+ width: 28px;
1306
+ height: 28px;
1307
+ padding: 0;
1308
+ border: 2px solid transparent;
1309
+ border-radius: 4px;
1310
+ background: transparent;
1311
+ cursor: pointer;
1312
+ transition: transform 0.1s ease, border-color 0.1s ease;
1313
+
1314
+ &:hover {
1315
+ transform: scale(1.1);
1316
+ }
1317
+
1318
+ &.selected {
1319
+ border-color: var(--toolbar-accent, #0060df);
1320
+ }
1321
+
1322
+ .color-picker-swatch {
1323
+ width: 20px;
1324
+ height: 20px;
1325
+ border-radius: 4px;
1326
+ }
1327
+ }
1328
+
1329
+ // Legacy color picker classes (for backwards compatibility)
1330
+ .pdf-color-picker {
1331
+ display: flex;
1332
+ align-items: center;
1333
+ gap: 0.25rem;
1334
+ }
1335
+
1336
+ .pdf-color-btn {
1337
+ width: 24px;
1338
+ height: 24px;
1339
+ padding: 0;
1340
+ border: 2px solid transparent;
1341
+ border-radius: 50%;
1342
+ cursor: pointer;
1343
+ transition: transform 0.15s ease;
1344
+
1345
+ &:hover {
1346
+ transform: scale(1.15);
1347
+ }
1348
+
1349
+ &.active {
1350
+ border-color: #333;
1351
+ box-shadow: 0 0 0 2px white;
1352
+ }
1353
+ }
1354
+
1355
+ // Note Dialog
1356
+ .note-dialog {
1357
+ min-width: 280px;
1358
+ max-width: 350px;
1359
+ background: white;
1360
+ border-radius: 8px;
1361
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
1362
+ font-size: 14px;
1363
+ overflow: hidden;
1364
+ }
1365
+
1366
+ .note-dialog-header {
1367
+ display: flex;
1368
+ align-items: center;
1369
+ justify-content: space-between;
1370
+ padding: 0.75rem 1rem;
1371
+ background: #f5f5f5;
1372
+ border-bottom: 1px solid #e0e0e0;
1373
+ font-weight: 500;
1374
+ }
1375
+
1376
+ .note-dialog-close {
1377
+ display: inline-flex;
1378
+ align-items: center;
1379
+ justify-content: center;
1380
+ width: 28px;
1381
+ height: 28px;
1382
+ padding: 0;
1383
+ border: none;
1384
+ border-radius: 4px;
1385
+ background: transparent;
1386
+ color: #666;
1387
+ cursor: pointer;
1388
+
1389
+ &:hover {
1390
+ background-color: #e0e0e0;
1391
+ }
1392
+ }
1393
+
1394
+ .note-dialog-input {
1395
+ display: block;
1396
+ width: 100%;
1397
+ padding: 0.75rem 1rem;
1398
+ border: none;
1399
+ border-bottom: 1px solid #e0e0e0;
1400
+ font-size: 14px;
1401
+ resize: vertical;
1402
+ min-height: 80px;
1403
+
1404
+ &:focus {
1405
+ outline: none;
1406
+ background-color: #fafafa;
1407
+ }
1408
+ }
1409
+
1410
+ .note-dialog-actions {
1411
+ display: flex;
1412
+ justify-content: flex-end;
1413
+ gap: 0.5rem;
1414
+ padding: 0.75rem 1rem;
1415
+ }
1416
+
1417
+ .note-dialog-save {
1418
+ padding: 0.5rem 1rem;
1419
+ border: none;
1420
+ border-radius: 4px;
1421
+ font-size: 14px;
1422
+ cursor: pointer;
1423
+ background: #0060df;
1424
+ color: white;
1425
+
1426
+ &:hover {
1427
+ background: #0050bf;
1428
+ }
1429
+ }
1430
+
1431
+ // Error display
1432
+ .pdf-viewer-error {
1433
+ position: absolute;
1434
+ top: 50%;
1435
+ left: 50%;
1436
+ transform: translate(-50%, -50%);
1437
+ padding: 2rem;
1438
+ background: #ffebee;
1439
+ border: 1px solid #ef9a9a;
1440
+ border-radius: 8px;
1441
+ color: #c62828;
1442
+ text-align: center;
1443
+ font-size: 16px;
1444
+ }
1445
+
1446
+ // Toast notification for transient errors
1447
+ .pdf-viewer-toast {
1448
+ position: absolute;
1449
+ left: 50%;
1450
+ transform: translateX(-50%) translateY(-10px);
1451
+ top: 60px;
1452
+ max-width: 90%;
1453
+ padding: 12px 20px;
1454
+ background: #323232;
1455
+ color: #fff;
1456
+ border-radius: 8px;
1457
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
1458
+ font-size: 14px;
1459
+ z-index: 1001;
1460
+ opacity: 0;
1461
+ transition: opacity 0.3s ease, transform 0.3s ease;
1462
+ pointer-events: none;
1463
+
1464
+ &.visible {
1465
+ opacity: 1;
1466
+ transform: translateX(-50%) translateY(0);
1467
+ }
1468
+ }
1469
+
1470
+ // Loading state
1471
+ .pdf-page-loading {
1472
+ display: flex;
1473
+ align-items: center;
1474
+ justify-content: center;
1475
+ min-height: 400px;
1476
+ background: #f5f5f5;
1477
+ color: #666;
1478
+ }
1479
+
1480
+ // Disable annotation pointer events during text selection (any mode)
1481
+ .pdf-pages-container.is-selecting-text {
1482
+ .annotation {
1483
+ pointer-events: none !important;
1484
+ }
1485
+ }
1486
+
1487
+ // Highlight tool mode - dynamic cursor based on text layer hover
1488
+ // Shows freehand highlighter cursor by default, text highlighter on text elements
1489
+ // Note: Touch scroll prevention is handled by JavaScript touch event handlers
1490
+ .pdf-pages-container.highlight-mode {
1491
+ .pdf-page {
1492
+ cursor: url('pdf_viewer/cursor-editorFreeHighlight.svg') 0 16, crosshair;
1493
+ }
1494
+
1495
+ .textLayer :is(span, br) {
1496
+ cursor: url('pdf_viewer/cursor-editorTextHighlight.svg') 0 16, text;
1497
+ }
1498
+
1499
+ // Force freehand cursor during active drawing (prevents cursor change on drag)
1500
+ &.is-drawing,
1501
+ &.is-drawing * {
1502
+ cursor: url('pdf_viewer/cursor-editorFreeHighlight.svg') 0 16, crosshair !important;
1503
+ }
1504
+ }
1505
+
1506
+ // Underline tool mode - text cursor for selection
1507
+ // Note: Touch scroll prevention is handled by JavaScript touch event handlers
1508
+ .pdf-pages-container.underline-mode {
1509
+ .pdf-page {
1510
+ cursor: url('pdf_viewer/cursor-editorTextHighlight.svg') 0 16, text;
1511
+ }
1512
+
1513
+ .textLayer :is(span, br) {
1514
+ cursor: url('pdf_viewer/cursor-editorTextHighlight.svg') 0 16, text;
1515
+ }
1516
+ }
1517
+
1518
+ // Ink tool mode - pen cursor for drawing
1519
+ // Hotspot (1, 14) aligns with the pen tip in the SVG icon
1520
+ // Note: Touch scroll prevention is handled by JavaScript touch event handlers
1521
+ .pdf-pages-container.ink-mode {
1522
+ .pdf-page {
1523
+ cursor: url('pdf_viewer/cursor-editorInk.svg') 1 14, crosshair;
1524
+ }
1525
+
1526
+ // Force pen cursor during active drawing
1527
+ &.is-drawing,
1528
+ &.is-drawing * {
1529
+ cursor: url('pdf_viewer/cursor-editorInk.svg') 1 14, crosshair !important;
1530
+ }
1531
+ }
1532
+
1533
+ // Note tool mode - note cursor everywhere
1534
+ .pdf-pages-container.note-mode {
1535
+ .pdf-page,
1536
+ .textLayer,
1537
+ .textLayer * {
1538
+ cursor: url('pdf_viewer/cursor-editorNote.svg') 1 1, crosshair;
1539
+ }
1540
+ }
1541
+
1542
+ // Legacy freehand mode class
1543
+ .pdf-pages-container.freehand-mode {
1544
+ cursor: crosshair;
1545
+ }
1546
+
1547
+ // Freehand highlight preview (shown while drawing)
1548
+ // Uses multiply blend mode so the preview shows the same effect as the final highlight
1549
+ .freehand-preview,
1550
+ .freehand-preview-canvas {
1551
+ position: absolute;
1552
+ top: 0;
1553
+ left: 0;
1554
+ width: 100%;
1555
+ height: 100%;
1556
+ pointer-events: none;
1557
+ z-index: 40;
1558
+ mix-blend-mode: multiply;
1559
+ }
1560
+
1561
+ // Responsive adjustments
1562
+ @media (max-width: 1100px) {
1563
+ // Hide text labels, show icon-only on medium screens
1564
+ .pdf-tool-btn span {
1565
+ display: none;
1566
+ }
1567
+
1568
+ .pdf-tool-btn {
1569
+ padding: 8px;
1570
+ }
1571
+ }
1572
+
1573
+ // Tablets: hide zoom dropdown, use buttons only
1574
+ @media (max-width: 900px) {
1575
+ .pdf-toolbar {
1576
+ flex-wrap: wrap;
1577
+ padding: 6px 8px;
1578
+ }
1579
+
1580
+ .pdf-toolbar-section {
1581
+ flex: 0 0 auto;
1582
+ }
1583
+
1584
+ .pdf-toolbar-left {
1585
+ order: 1;
1586
+ }
1587
+
1588
+ .pdf-toolbar-right {
1589
+ order: 2;
1590
+ }
1591
+
1592
+ .pdf-zoom-select {
1593
+ display: none;
1594
+ }
1595
+ }
1596
+
1597
+ // Small phones: compact layout, hide page nav
1598
+ @media (max-width: 600px) {
1599
+ .pdf-toolbar {
1600
+ flex-wrap: nowrap;
1601
+ padding: 6px 8px;
1602
+ gap: 4px;
1603
+ justify-content: space-between;
1604
+ }
1605
+
1606
+ .pdf-toolbar-section {
1607
+ gap: 4px;
1608
+ }
1609
+
1610
+ // Left section: show thumbnail toggle and zoom buttons
1611
+ .pdf-toolbar-left {
1612
+ flex: 0 0 auto;
1613
+
1614
+ // Hide page nav (available in overflow menu)
1615
+ .pdf-toolbar-nav {
1616
+ display: none;
1617
+ }
1618
+
1619
+ // Show zoom buttons (dropdown already hidden at 900px)
1620
+ .pdf-toolbar-zoom {
1621
+ display: flex;
1622
+ }
1623
+
1624
+ // Hide separators
1625
+ .pdf-toolbar-separator {
1626
+ display: none;
1627
+ }
1628
+ }
1629
+
1630
+ .pdf-toolbar-right {
1631
+ flex: 1;
1632
+ justify-content: flex-end;
1633
+ gap: 4px;
1634
+ }
1635
+
1636
+ .pdf-toolbar-btn {
1637
+ width: 40px;
1638
+ height: 40px;
1639
+ flex-shrink: 0;
1640
+ }
1641
+
1642
+ .pdf-tool-btn {
1643
+ padding: 8px;
1644
+ flex-shrink: 0;
1645
+
1646
+ // Hide labels on mobile
1647
+ span {
1648
+ display: none;
1649
+ }
1650
+
1651
+ svg {
1652
+ width: 22px;
1653
+ height: 22px;
1654
+ }
1655
+ }
1656
+
1657
+ .pdf-toolbar-separator {
1658
+ display: none;
1659
+ }
1660
+
1661
+ // Annotation tools: show select, highlight, note only
1662
+ .pdf-toolbar-tools {
1663
+ display: flex;
1664
+ gap: 2px;
1665
+
1666
+ .pdf-tool-btn[data-tool="underline"],
1667
+ .pdf-tool-btn[data-tool="ink"] {
1668
+ display: none;
1669
+ }
1670
+ }
1671
+
1672
+ // Keep color picker visible
1673
+ .pdf-toolbar-colors {
1674
+ display: flex;
1675
+ flex-shrink: 0;
1676
+ }
1677
+
1678
+ // Actions section
1679
+ .pdf-toolbar-actions {
1680
+ gap: 2px;
1681
+ flex-shrink: 0;
1682
+
1683
+ // Hide search and download
1684
+ > .pdf-toolbar-btn:not([data-action*="toggleAnnotationSidebar"]),
1685
+ > .pdf-tool-btn {
1686
+ display: none;
1687
+ }
1688
+
1689
+ // Show annotation sidebar toggle
1690
+ > .pdf-toolbar-btn[data-action*="toggleAnnotationSidebar"] {
1691
+ display: flex;
1692
+ }
1693
+ }
1694
+
1695
+ // Show overflow menu button
1696
+ .pdf-toolbar-overflow-btn {
1697
+ display: flex !important;
1698
+ flex-shrink: 0;
1699
+ }
1700
+
1701
+ .annotation-popup {
1702
+ max-width: 90vw;
1703
+ }
1704
+
1705
+ .note-dialog {
1706
+ max-width: 90vw;
1707
+ left: 5vw !important;
1708
+ }
1709
+ }
1710
+
1711
+ // Overflow menu button (hidden by default, shown on mobile)
1712
+ .pdf-toolbar-overflow-btn {
1713
+ display: none;
1714
+ align-items: center;
1715
+ justify-content: center;
1716
+ width: 36px;
1717
+ height: 36px;
1718
+ padding: 0;
1719
+ border: none;
1720
+ border-radius: 6px;
1721
+ background: transparent;
1722
+ color: var(--toolbar-text);
1723
+ cursor: pointer;
1724
+ transition: background-color 0.1s ease;
1725
+
1726
+ &:hover {
1727
+ background-color: var(--toolbar-hover);
1728
+ }
1729
+
1730
+ &.active {
1731
+ background-color: var(--toolbar-active);
1732
+ }
1733
+
1734
+ svg {
1735
+ width: 20px;
1736
+ height: 20px;
1737
+ }
1738
+ }
1739
+
1740
+ // Overflow menu dropdown - positioned relative to toolbar
1741
+ .pdf-toolbar-overflow-menu {
1742
+ display: none;
1743
+ position: fixed;
1744
+ top: auto;
1745
+ right: 8px;
1746
+ margin-top: 4px;
1747
+ padding: 8px;
1748
+ min-width: 200px;
1749
+ background: var(--toolbar-bg, #38383d);
1750
+ border: 1px solid var(--toolbar-border, #2a2a2e);
1751
+ border-radius: 8px;
1752
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
1753
+ z-index: 1000;
1754
+
1755
+ &.open {
1756
+ display: block;
1757
+ }
1758
+ }
1759
+
1760
+ .pdf-overflow-section {
1761
+ &:not(:last-child) {
1762
+ margin-bottom: 8px;
1763
+ padding-bottom: 8px;
1764
+ border-bottom: 1px solid var(--toolbar-separator, rgba(255, 255, 255, 0.2));
1765
+ }
1766
+ }
1767
+
1768
+ .pdf-overflow-section-title {
1769
+ font-size: 11px;
1770
+ font-weight: 600;
1771
+ color: var(--toolbar-text-secondary, #b1b1b3);
1772
+ text-transform: uppercase;
1773
+ letter-spacing: 0.5px;
1774
+ padding: 4px 4px 8px;
1775
+ }
1776
+
1777
+ // Page navigation row
1778
+ .pdf-overflow-row {
1779
+ display: flex;
1780
+ align-items: center;
1781
+ justify-content: center;
1782
+ gap: 12px;
1783
+ }
1784
+
1785
+ .pdf-overflow-btn {
1786
+ display: flex;
1787
+ align-items: center;
1788
+ justify-content: center;
1789
+ width: 40px;
1790
+ height: 40px;
1791
+ padding: 0;
1792
+ border: none;
1793
+ border-radius: 6px;
1794
+ background: transparent;
1795
+ color: var(--toolbar-text, #f9f9fa);
1796
+ cursor: pointer;
1797
+ transition: background-color 0.1s ease;
1798
+
1799
+ &:hover {
1800
+ background-color: var(--toolbar-hover, rgba(255, 255, 255, 0.1));
1801
+ }
1802
+
1803
+ &:disabled {
1804
+ opacity: 0.4;
1805
+ cursor: not-allowed;
1806
+ }
1807
+
1808
+ svg {
1809
+ width: 20px;
1810
+ height: 20px;
1811
+ }
1812
+ }
1813
+
1814
+ .pdf-overflow-page-display {
1815
+ display: flex;
1816
+ align-items: center;
1817
+ gap: 4px;
1818
+ font-size: 14px;
1819
+ color: var(--toolbar-text, #f9f9fa);
1820
+ min-width: 50px;
1821
+ justify-content: center;
1822
+ }
1823
+
1824
+ .pdf-overflow-tools {
1825
+ display: flex;
1826
+ gap: 8px;
1827
+ flex-wrap: wrap;
1828
+ }
1829
+
1830
+ .pdf-overflow-tool-btn {
1831
+ display: flex;
1832
+ align-items: center;
1833
+ gap: 8px;
1834
+ padding: 8px 12px;
1835
+ border: 1px solid transparent;
1836
+ border-radius: 6px;
1837
+ background: transparent;
1838
+ color: var(--toolbar-text, #f9f9fa);
1839
+ cursor: pointer;
1840
+ transition: all 0.15s ease;
1841
+ font-size: 13px;
1842
+
1843
+ &:hover {
1844
+ background-color: var(--toolbar-hover, rgba(255, 255, 255, 0.1));
1845
+ border-color: var(--toolbar-separator, rgba(255, 255, 255, 0.2));
1846
+ }
1847
+
1848
+ &.active {
1849
+ background-color: rgba(255, 255, 255, 0.95);
1850
+ border-color: #333;
1851
+ color: #333;
1852
+
1853
+ svg {
1854
+ stroke: #333;
1855
+ }
1856
+ }
1857
+
1858
+ svg {
1859
+ width: 20px;
1860
+ height: 20px;
1861
+ flex-shrink: 0;
1862
+ }
1863
+ }
1864
+
1865
+ .pdf-overflow-actions {
1866
+ display: flex;
1867
+ flex-direction: column;
1868
+ gap: 2px;
1869
+ }
1870
+
1871
+ .pdf-overflow-action-btn {
1872
+ display: flex;
1873
+ align-items: center;
1874
+ gap: 12px;
1875
+ width: 100%;
1876
+ padding: 10px 12px;
1877
+ border: none;
1878
+ border-radius: 6px;
1879
+ background: transparent;
1880
+ color: var(--toolbar-text, #f9f9fa);
1881
+ cursor: pointer;
1882
+ transition: background-color 0.1s ease;
1883
+ font-size: 14px;
1884
+ text-align: left;
1885
+
1886
+ &:hover {
1887
+ background-color: var(--toolbar-hover, rgba(255, 255, 255, 0.1));
1888
+ }
1889
+
1890
+ svg {
1891
+ width: 20px;
1892
+ height: 20px;
1893
+ flex-shrink: 0;
1894
+ }
1895
+ }
1896
+
1897
+ .pdf-overflow-colors {
1898
+ display: flex;
1899
+ gap: 6px;
1900
+ padding: 4px 8px;
1901
+ }
1902
+
1903
+ // Find Bar - Search UI
1904
+ .pdf-find-bar {
1905
+ --find-bar-bg: var(--pdf-dark-bg);
1906
+ --find-bar-border: var(--pdf-dark-bg-secondary);
1907
+ --find-bar-text: var(--pdf-dark-text);
1908
+ --find-bar-text-secondary: var(--pdf-dark-text-secondary);
1909
+ --find-bar-input-bg: var(--pdf-dark-input-bg);
1910
+ --find-bar-input-border: var(--pdf-dark-input-border);
1911
+ --find-bar-accent: var(--pdf-accent);
1912
+ --find-bar-hover: var(--pdf-dark-hover);
1913
+
1914
+ display: flex;
1915
+ flex-direction: column;
1916
+ padding: 8px 12px;
1917
+ background-color: var(--find-bar-bg);
1918
+ border-bottom: 1px solid var(--find-bar-border);
1919
+ }
1920
+
1921
+ .find-bar-content {
1922
+ display: flex;
1923
+ align-items: center;
1924
+ gap: 8px;
1925
+ }
1926
+
1927
+ .find-input-container {
1928
+ position: relative;
1929
+ flex: 1;
1930
+ max-width: 300px;
1931
+ display: flex;
1932
+ align-items: center;
1933
+ }
1934
+
1935
+ .find-input {
1936
+ width: 100%;
1937
+ height: 28px;
1938
+ padding: 0 70px 0 10px;
1939
+ border: 1px solid var(--find-bar-input-border);
1940
+ border-radius: 4px;
1941
+ background: var(--find-bar-input-bg);
1942
+ color: var(--find-bar-text);
1943
+ font-size: 13px;
1944
+
1945
+ &::placeholder {
1946
+ color: var(--find-bar-text-secondary);
1947
+ }
1948
+
1949
+ &:focus {
1950
+ outline: none;
1951
+ border-color: var(--find-bar-accent);
1952
+ box-shadow: 0 0 0 1px var(--find-bar-accent);
1953
+ }
1954
+ }
1955
+
1956
+ .find-results {
1957
+ position: absolute;
1958
+ right: 10px;
1959
+ font-size: 12px;
1960
+ color: var(--find-bar-text-secondary);
1961
+ pointer-events: none;
1962
+ white-space: nowrap;
1963
+
1964
+ &.not-found {
1965
+ color: #ff6b6b;
1966
+ }
1967
+ }
1968
+
1969
+ .find-buttons {
1970
+ display: flex;
1971
+ gap: 2px;
1972
+ }
1973
+
1974
+ .find-btn {
1975
+ display: inline-flex;
1976
+ align-items: center;
1977
+ justify-content: center;
1978
+ width: 28px;
1979
+ height: 28px;
1980
+ padding: 0;
1981
+ border: none;
1982
+ border-radius: 4px;
1983
+ background: transparent;
1984
+ color: var(--find-bar-text);
1985
+ cursor: pointer;
1986
+ transition: background-color 0.1s ease;
1987
+
1988
+ &:hover:not(:disabled) {
1989
+ background-color: var(--find-bar-hover);
1990
+ }
1991
+
1992
+ &:disabled {
1993
+ opacity: 0.4;
1994
+ cursor: not-allowed;
1995
+ }
1996
+
1997
+ svg {
1998
+ width: 16px;
1999
+ height: 16px;
2000
+ }
2001
+ }
2002
+
2003
+ .find-separator {
2004
+ width: 1px;
2005
+ height: 20px;
2006
+ background-color: rgba(255, 255, 255, 0.2);
2007
+ margin: 0 4px;
2008
+ }
2009
+
2010
+ .find-options {
2011
+ display: flex;
2012
+ gap: 4px;
2013
+ }
2014
+
2015
+ .find-option {
2016
+ display: inline-flex;
2017
+ align-items: center;
2018
+ justify-content: center;
2019
+ padding: 4px 8px;
2020
+ border: 1px solid transparent;
2021
+ border-radius: 4px;
2022
+ background: transparent;
2023
+ color: var(--find-bar-text-secondary);
2024
+ font-size: 13px;
2025
+ font-weight: 500;
2026
+ cursor: pointer;
2027
+ transition: all 0.1s ease;
2028
+ user-select: none;
2029
+
2030
+ input[type="checkbox"] {
2031
+ display: none;
2032
+ }
2033
+
2034
+ &:hover {
2035
+ background-color: var(--find-bar-hover);
2036
+ color: var(--find-bar-text);
2037
+ }
2038
+
2039
+ &:has(input:checked) {
2040
+ background-color: var(--find-bar-accent);
2041
+ color: white;
2042
+ border-color: var(--find-bar-accent);
2043
+ }
2044
+ }
2045
+
2046
+ .find-message {
2047
+ padding: 4px 0 0;
2048
+ font-size: 12px;
2049
+ color: var(--find-bar-text-secondary);
2050
+ }
2051
+
2052
+ // Search result highlighting in text layer
2053
+ .textLayer {
2054
+ .search-highlight {
2055
+ background-color: rgb(0 100 255 / 0.3);
2056
+ border-radius: 2px;
2057
+ color: transparent; // Keep text invisible like other text layer content
2058
+
2059
+ &.selected {
2060
+ background-color: rgb(0 100 255 / 0.5);
2061
+ }
2062
+ }
2063
+ }
2064
+
2065
+ // Responsive find bar
2066
+ @media (max-width: 600px) {
2067
+ .find-input-container {
2068
+ max-width: none;
2069
+ }
2070
+
2071
+ .find-options {
2072
+ display: none;
2073
+ }
2074
+
2075
+ .find-separator:nth-of-type(2) {
2076
+ display: none;
2077
+ }
2078
+ }
2079
+
2080
+ // Annotation Sidebar (right-side, extends base .pdf-sidebar)
2081
+ .pdf-annotation-sidebar {
2082
+ // Annotation-specific variables
2083
+ --sidebar-width: 280px;
2084
+ --sidebar-hover: rgba(255, 255, 255, 0.05);
2085
+ --sidebar-active: rgba(255, 255, 255, 0.1);
2086
+ }
2087
+
2088
+ // Annotation sidebar header extensions (left section with count badge)
2089
+ .pdf-sidebar-header-left {
2090
+ display: flex;
2091
+ align-items: center;
2092
+ gap: 8px;
2093
+ }
2094
+
2095
+ .annotation-count-badge {
2096
+ display: inline-flex;
2097
+ align-items: center;
2098
+ justify-content: center;
2099
+ min-width: 20px;
2100
+ height: 20px;
2101
+ padding: 0 6px;
2102
+ font-size: 11px;
2103
+ font-weight: 600;
2104
+ color: var(--sidebar-text);
2105
+ background: rgba(255, 255, 255, 0.15);
2106
+ border-radius: 10px;
2107
+ }
2108
+
2109
+ // Annotation controls wrapper
2110
+ .annotation-controls-wrapper {
2111
+ display: flex;
2112
+ align-items: center;
2113
+ justify-content: space-between;
2114
+ padding: 8px 12px;
2115
+ border-bottom: 1px solid var(--sidebar-border);
2116
+ flex-shrink: 0;
2117
+ gap: 8px;
2118
+ }
2119
+
2120
+ // Sort controls
2121
+ .annotation-sort-controls {
2122
+ display: flex;
2123
+ gap: 2px;
2124
+ background: rgba(0, 0, 0, 0.2);
2125
+ border-radius: 6px;
2126
+ padding: 2px;
2127
+
2128
+ .sort-btn {
2129
+ padding: 4px 10px;
2130
+ border: none;
2131
+ border-radius: 4px;
2132
+ background: transparent;
2133
+ color: var(--sidebar-text-secondary, #b1b1b3);
2134
+ font-size: 12px;
2135
+ font-weight: 500;
2136
+ cursor: pointer;
2137
+ transition: all 0.15s ease;
2138
+ white-space: nowrap;
2139
+
2140
+ &:hover {
2141
+ color: var(--sidebar-text, #f9f9fa);
2142
+ }
2143
+
2144
+ &.active {
2145
+ background: rgba(255, 255, 255, 0.15);
2146
+ color: var(--sidebar-text, #f9f9fa);
2147
+ }
2148
+ }
2149
+ }
2150
+
2151
+ // Filter controls
2152
+ .annotation-filter-controls {
2153
+ .annotation-filter-select {
2154
+ height: 26px;
2155
+ padding: 0 24px 0 8px;
2156
+ border: 1px solid rgba(255, 255, 255, 0.15);
2157
+ border-radius: 4px;
2158
+ background: rgba(0, 0, 0, 0.2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23b1b1b3' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 6px center;
2159
+ background-size: 12px;
2160
+ color: var(--sidebar-text-secondary, #b1b1b3);
2161
+ font-size: 12px;
2162
+ cursor: pointer;
2163
+ appearance: none;
2164
+
2165
+ &:hover {
2166
+ border-color: rgba(255, 255, 255, 0.25);
2167
+ color: var(--sidebar-text, #f9f9fa);
2168
+ }
2169
+
2170
+ &:focus {
2171
+ outline: none;
2172
+ border-color: var(--sidebar-accent, #0060df);
2173
+ }
2174
+ }
2175
+ }
2176
+
2177
+ // Annotation list
2178
+ .annotation-list {
2179
+ flex: 1;
2180
+ overflow-y: auto;
2181
+ overflow-x: hidden;
2182
+ padding: 8px;
2183
+
2184
+ &.empty {
2185
+ display: none;
2186
+ }
2187
+ }
2188
+
2189
+ // Empty state
2190
+ .annotation-empty-state {
2191
+ display: none;
2192
+ flex-direction: column;
2193
+ align-items: center;
2194
+ justify-content: center;
2195
+ padding: 32px 24px;
2196
+ text-align: center;
2197
+ color: var(--sidebar-text-secondary, #b1b1b3);
2198
+
2199
+ &.visible {
2200
+ display: flex;
2201
+ flex: 1;
2202
+ }
2203
+
2204
+ svg {
2205
+ width: 48px;
2206
+ height: 48px;
2207
+ margin-bottom: 16px;
2208
+ opacity: 0.4;
2209
+ }
2210
+
2211
+ p {
2212
+ margin: 0;
2213
+ font-size: 14px;
2214
+
2215
+ &.hint {
2216
+ margin-top: 8px;
2217
+ font-size: 12px;
2218
+ opacity: 0.7;
2219
+ }
2220
+ }
2221
+ }
2222
+
2223
+ // Annotation list item
2224
+ .annotation-list-item {
2225
+ display: flex;
2226
+ align-items: flex-start;
2227
+ gap: 10px;
2228
+ padding: 10px 12px;
2229
+ border-radius: 6px;
2230
+ cursor: pointer;
2231
+ transition: background-color 0.15s ease;
2232
+ position: relative;
2233
+ width: 100%;
2234
+
2235
+ &:hover {
2236
+ background: var(--sidebar-hover, rgba(255, 255, 255, 0.05));
2237
+
2238
+ .annotation-item-hover {
2239
+ opacity: 1;
2240
+ }
2241
+ }
2242
+
2243
+ &:focus {
2244
+ outline: 2px solid var(--sidebar-accent, #0060df);
2245
+ outline-offset: -2px;
2246
+ }
2247
+
2248
+ &.selected {
2249
+ background: var(--sidebar-active, rgba(255, 255, 255, 0.1));
2250
+
2251
+ .annotation-item-label {
2252
+ color: var(--sidebar-text, #f9f9fa);
2253
+ }
2254
+ }
2255
+
2256
+ // Subtle separator between items
2257
+ & + & {
2258
+ margin-top: 2px;
2259
+ }
2260
+ }
2261
+
2262
+ .annotation-item-icon {
2263
+ flex-shrink: 0;
2264
+ width: 20px;
2265
+ height: 20px;
2266
+ margin-top: 2px;
2267
+
2268
+ svg {
2269
+ width: 100%;
2270
+ height: 100%;
2271
+ }
2272
+ }
2273
+
2274
+ .annotation-item-content {
2275
+ flex: 1;
2276
+ min-width: 0;
2277
+ overflow: hidden;
2278
+ }
2279
+
2280
+ .annotation-item-label {
2281
+ font-size: 13px;
2282
+ color: var(--sidebar-text-secondary, #b1b1b3);
2283
+ line-height: 1.4;
2284
+ overflow: hidden;
2285
+ text-overflow: ellipsis;
2286
+ display: -webkit-box;
2287
+ -webkit-line-clamp: 2;
2288
+ -webkit-box-orient: vertical;
2289
+ }
2290
+
2291
+ .annotation-item-meta {
2292
+ display: flex;
2293
+ align-items: center;
2294
+ gap: 4px;
2295
+ margin-top: 4px;
2296
+ font-size: 11px;
2297
+ color: rgba(177, 177, 179, 0.7);
2298
+ }
2299
+
2300
+ .annotation-item-separator {
2301
+ opacity: 0.5;
2302
+ }
2303
+
2304
+ .annotation-item-type {
2305
+ font-weight: 500;
2306
+ }
2307
+
2308
+ .annotation-item-hover {
2309
+ display: flex;
2310
+ align-items: center;
2311
+ gap: 2px;
2312
+ position: absolute;
2313
+ right: 8px;
2314
+ top: 50%;
2315
+ transform: translateY(-50%);
2316
+ padding: 4px 8px;
2317
+ background: var(--sidebar-accent, #0060df);
2318
+ border-radius: 4px;
2319
+ font-size: 11px;
2320
+ font-weight: 500;
2321
+ color: white;
2322
+ opacity: 0;
2323
+ transition: opacity 0.15s ease;
2324
+
2325
+ svg {
2326
+ width: 12px;
2327
+ height: 12px;
2328
+ }
2329
+ }
2330
+
2331
+ // Flash highlight effect for annotations
2332
+ @keyframes annotation-flash {
2333
+ 0%, 100% {
2334
+ box-shadow:
2335
+ 0 0 0 2px var(--outline-color, #0060df),
2336
+ 0 0 0 3px var(--outline-around-color, #f0f0f4);
2337
+ }
2338
+ 50% {
2339
+ box-shadow:
2340
+ 0 0 0 4px var(--outline-color, #0060df),
2341
+ 0 0 0 6px var(--outline-around-color, #f0f0f4),
2342
+ 0 0 20px 4px rgba(0, 96, 223, 0.4);
2343
+ }
2344
+ }
2345
+
2346
+ .annotation.flashing {
2347
+ animation: annotation-flash 0.5s ease-in-out 3;
2348
+ z-index: 100 !important;
2349
+ }
2350
+
2351
+ // Body layout when annotation sidebar is open
2352
+ .pdf-viewer-body.annotation-sidebar-open {
2353
+ // Flexbox handles the layout automatically
2354
+ }
2355
+
2356
+ // Responsive adjustments for annotation sidebar
2357
+ @media (max-width: 900px) {
2358
+ .pdf-annotation-sidebar {
2359
+ --sidebar-width: 240px;
2360
+ }
2361
+
2362
+ .annotation-controls-wrapper {
2363
+ flex-direction: column;
2364
+ align-items: stretch;
2365
+ gap: 8px;
2366
+ }
2367
+
2368
+ .annotation-sort-controls {
2369
+ justify-content: center;
2370
+ }
2371
+
2372
+ .annotation-filter-controls {
2373
+ .annotation-filter-select {
2374
+ width: 100%;
2375
+ }
2376
+ }
2377
+ }
2378
+
2379
+ @media (max-width: 600px) {
2380
+ .pdf-annotation-sidebar {
2381
+ position: absolute;
2382
+ right: 0;
2383
+ top: 0;
2384
+ bottom: 0;
2385
+ z-index: 50;
2386
+ box-shadow: -4px 0 16px rgba(0, 0, 0, 0.3);
2387
+ }
2388
+ }
2389
+
2390
+ // Loading overlay
2391
+ .pdf-loading-overlay {
2392
+ position: absolute;
2393
+ top: 0;
2394
+ left: 0;
2395
+ right: 0;
2396
+ bottom: 0;
2397
+ display: flex;
2398
+ flex-direction: column;
2399
+ align-items: center;
2400
+ justify-content: center;
2401
+ background: rgba(255, 255, 255, 0.95);
2402
+ z-index: 100;
2403
+ transition: opacity 0.3s ease;
2404
+
2405
+ &.hidden {
2406
+ opacity: 0;
2407
+ pointer-events: none;
2408
+ }
2409
+ }
2410
+
2411
+ .pdf-loading-spinner {
2412
+ width: 40px;
2413
+ height: 40px;
2414
+ border: 3px solid #e0e0e0;
2415
+ border-top-color: #3b82f6;
2416
+ border-radius: 50%;
2417
+ animation: pdf-spin 0.8s linear infinite;
2418
+ }
2419
+
2420
+ .pdf-loading-text {
2421
+ margin-top: 16px;
2422
+ font-size: 14px;
2423
+ color: #666;
2424
+ }
2425
+
2426
+ @keyframes pdf-spin {
2427
+ to {
2428
+ transform: rotate(360deg);
2429
+ }
2430
+ }
2431
+
2432
+ // Screen reader only class for aria-live regions
2433
+ // Visually hidden but accessible to screen readers
2434
+ .pdf-viewer-announcer {
2435
+ position: absolute;
2436
+ width: 1px;
2437
+ height: 1px;
2438
+ padding: 0;
2439
+ margin: -1px;
2440
+ overflow: hidden;
2441
+ clip: rect(0, 0, 0, 0);
2442
+ white-space: nowrap;
2443
+ border: 0;
2444
+ }
2445
+
2446
+ // ============================================================================
2447
+ // High Contrast Mode Support
2448
+ // Ensures visibility in Windows High Contrast Mode and other forced-colors
2449
+ // environments by using system colors and visible borders.
2450
+ // ============================================================================
2451
+
2452
+ @media (forced-colors: active) {
2453
+ // Toolbar buttons - ensure visible borders and focus
2454
+ // Use 2px border on all states to prevent layout shift when active
2455
+ .pdf-toolbar-btn,
2456
+ .pdf-tool-btn {
2457
+ border: 2px solid ButtonText;
2458
+ background: Canvas;
2459
+ color: CanvasText;
2460
+
2461
+ &:hover:not(:disabled) {
2462
+ border-color: Highlight;
2463
+ }
2464
+
2465
+ &:focus {
2466
+ outline: 2px solid Highlight;
2467
+ outline-offset: 2px;
2468
+ }
2469
+
2470
+ &:disabled {
2471
+ border-color: GrayText;
2472
+ color: GrayText;
2473
+ }
2474
+ }
2475
+
2476
+ // Active tool button needs forced-color-adjust to override the rgba background
2477
+ .pdf-tool-btn.active {
2478
+ forced-color-adjust: none;
2479
+ background: Highlight;
2480
+ color: HighlightText;
2481
+ border: 2px solid HighlightText;
2482
+ box-shadow: none;
2483
+
2484
+ svg {
2485
+ stroke: HighlightText;
2486
+ }
2487
+
2488
+ // Keep active appearance on hover, just change border to show interaction
2489
+ &:hover {
2490
+ background: Highlight;
2491
+ color: HighlightText;
2492
+ border-color: Canvas;
2493
+
2494
+ svg {
2495
+ stroke: HighlightText;
2496
+ }
2497
+ }
2498
+ }
2499
+
2500
+ // Form controls (inputs, selects)
2501
+ .pdf-page-input,
2502
+ .pdf-zoom-select,
2503
+ .find-input,
2504
+ .annotation-filter-select {
2505
+ border: 1px solid ButtonText;
2506
+ background: Canvas;
2507
+ color: CanvasText;
2508
+
2509
+ &:focus {
2510
+ outline: 2px solid Highlight;
2511
+ outline-offset: 0;
2512
+ }
2513
+ }
2514
+
2515
+ // Sidebar buttons
2516
+ .pdf-sidebar-close,
2517
+ .find-btn {
2518
+ border: 1px solid ButtonText;
2519
+
2520
+ &:hover {
2521
+ border-color: Highlight;
2522
+ }
2523
+
2524
+ &:focus {
2525
+ outline: 2px solid Highlight;
2526
+ }
2527
+ }
2528
+
2529
+ // Thumbnails
2530
+ .thumbnail {
2531
+ border: 1px solid transparent;
2532
+
2533
+ &:focus {
2534
+ outline: 2px solid Highlight;
2535
+ }
2536
+
2537
+ &.active {
2538
+ border-color: Highlight;
2539
+ }
2540
+ }
2541
+
2542
+ .thumbnail-image {
2543
+ border: 1px solid ButtonText;
2544
+ }
2545
+
2546
+ // Annotations
2547
+ .annotation {
2548
+ outline: 1px solid CanvasText;
2549
+
2550
+ &:hover:not(.selected) {
2551
+ outline: 2px solid Highlight;
2552
+ box-shadow: none;
2553
+ }
2554
+
2555
+ &.selected {
2556
+ outline: 2px solid Highlight;
2557
+ box-shadow: none;
2558
+ }
2559
+ }
2560
+
2561
+ // Annotation edit toolbar
2562
+ .annotation-edit-toolbar {
2563
+ border: 1px solid CanvasText;
2564
+
2565
+ .toolbar-btn {
2566
+ border: 1px solid ButtonText;
2567
+
2568
+ &:hover {
2569
+ border-color: Highlight;
2570
+ }
2571
+
2572
+ &:focus-visible {
2573
+ outline: 2px solid Highlight;
2574
+ }
2575
+ }
2576
+
2577
+ .color-picker-btn {
2578
+ border: 1px solid ButtonText;
2579
+
2580
+ &:hover {
2581
+ border-color: Highlight;
2582
+ }
2583
+
2584
+ .color-swatch {
2585
+ forced-color-adjust: none;
2586
+ }
2587
+ }
2588
+
2589
+ .color-dropdown {
2590
+ border: 1px solid CanvasText;
2591
+
2592
+ .color-option {
2593
+ border: 2px solid ButtonText;
2594
+
2595
+ &:hover,
2596
+ &:focus,
2597
+ &[aria-selected="true"] {
2598
+ border-color: Highlight;
2599
+ }
2600
+
2601
+ .color-swatch {
2602
+ forced-color-adjust: none;
2603
+ }
2604
+ }
2605
+ }
2606
+ }
2607
+
2608
+ // Color picker - preserve actual colors for swatches
2609
+ .color-picker-toggle {
2610
+ border: 1px solid ButtonText;
2611
+
2612
+ &:hover {
2613
+ border-color: Highlight;
2614
+ }
2615
+
2616
+ .color-picker-swatch {
2617
+ forced-color-adjust: none;
2618
+ }
2619
+
2620
+ svg {
2621
+ stroke: CanvasText;
2622
+ }
2623
+ }
2624
+
2625
+ .color-picker-option {
2626
+ border: 2px solid ButtonText;
2627
+
2628
+ &:hover,
2629
+ &.selected {
2630
+ border-color: Highlight;
2631
+ }
2632
+
2633
+ .color-picker-swatch {
2634
+ forced-color-adjust: none;
2635
+ }
2636
+ }
2637
+
2638
+ // Popup and dialogs
2639
+ .annotation-popup {
2640
+ border: 1px solid CanvasText;
2641
+ background: Canvas;
2642
+ color: CanvasText;
2643
+
2644
+ .annotation-popup-header {
2645
+ border-bottom: 1px solid CanvasText;
2646
+ }
2647
+
2648
+ .annotation-popup-btn {
2649
+ border: 1px solid ButtonText;
2650
+
2651
+ &:hover {
2652
+ border-color: Highlight;
2653
+ }
2654
+ }
2655
+ }
2656
+
2657
+ .note-dialog {
2658
+ border: 1px solid CanvasText;
2659
+ background: Canvas;
2660
+ color: CanvasText;
2661
+
2662
+ .note-dialog-header {
2663
+ border-bottom: 1px solid CanvasText;
2664
+ }
2665
+
2666
+ .note-dialog-input {
2667
+ border: 1px solid ButtonText;
2668
+ background: Canvas;
2669
+ color: CanvasText;
2670
+
2671
+ &:focus {
2672
+ outline: 2px solid Highlight;
2673
+ }
2674
+ }
2675
+
2676
+ .note-dialog-save {
2677
+ border: 1px solid ButtonText;
2678
+
2679
+ &:hover {
2680
+ border-color: Highlight;
2681
+ }
2682
+ }
2683
+ }
2684
+
2685
+ // Undo bar
2686
+ .pdf-undo-bar {
2687
+ border: 1px solid CanvasText;
2688
+ background: Canvas;
2689
+ color: CanvasText;
2690
+
2691
+ .pdf-undo-bar-btn {
2692
+ border: 1px solid ButtonText;
2693
+
2694
+ &:hover {
2695
+ border-color: Highlight;
2696
+ }
2697
+ }
2698
+
2699
+ .pdf-undo-bar-dismiss {
2700
+ border: 1px solid ButtonText;
2701
+
2702
+ &:hover {
2703
+ border-color: Highlight;
2704
+ }
2705
+ }
2706
+ }
2707
+
2708
+ // Find bar
2709
+ .pdf-find-bar {
2710
+ border-bottom: 1px solid CanvasText;
2711
+
2712
+ .find-results.not-found {
2713
+ color: CanvasText;
2714
+ text-decoration: underline;
2715
+ }
2716
+ }
2717
+
2718
+ .find-option {
2719
+ border: 1px solid ButtonText;
2720
+
2721
+ &:has(input:checked) {
2722
+ background: Highlight;
2723
+ color: HighlightText;
2724
+ border-color: Highlight;
2725
+ }
2726
+ }
2727
+
2728
+ // Annotation sidebar
2729
+ .pdf-annotation-sidebar,
2730
+ .pdf-thumbnail-sidebar {
2731
+ border-color: CanvasText;
2732
+
2733
+ .pdf-sidebar-header {
2734
+ border-bottom: 1px solid CanvasText;
2735
+ }
2736
+ }
2737
+
2738
+ .annotation-list-item {
2739
+ border: 2px solid transparent;
2740
+ background: Canvas;
2741
+ color: CanvasText;
2742
+
2743
+ &:hover {
2744
+ border-color: Highlight;
2745
+ }
2746
+
2747
+ &:focus {
2748
+ outline: 2px solid Highlight;
2749
+ }
2750
+
2751
+ // Selected annotation item
2752
+ &.selected {
2753
+ forced-color-adjust: none;
2754
+ background: Highlight;
2755
+ color: HighlightText;
2756
+ border-color: HighlightText;
2757
+
2758
+ // Ensure all text is readable
2759
+ .annotation-item-label,
2760
+ .annotation-item-meta,
2761
+ .annotation-item-type,
2762
+ .annotation-item-separator {
2763
+ color: HighlightText;
2764
+ }
2765
+
2766
+ // Keep selected appearance on hover
2767
+ &:hover {
2768
+ background: Highlight;
2769
+ color: HighlightText;
2770
+ border-color: Canvas;
2771
+ }
2772
+ }
2773
+ }
2774
+
2775
+ // Use 2px border on all states to prevent layout shift when active
2776
+ .annotation-sort-controls .sort-btn {
2777
+ border: 2px solid ButtonText;
2778
+ background: Canvas;
2779
+ color: CanvasText;
2780
+ }
2781
+
2782
+ // Active sort button needs forced-color-adjust to override the rgba background
2783
+ .annotation-sort-controls .sort-btn.active {
2784
+ forced-color-adjust: none;
2785
+ background: Highlight;
2786
+ color: HighlightText;
2787
+ border-color: HighlightText;
2788
+
2789
+ // Keep active appearance on hover, just change border to show interaction
2790
+ &:hover {
2791
+ background: Highlight;
2792
+ color: HighlightText;
2793
+ border-color: Canvas;
2794
+ }
2795
+ }
2796
+
2797
+ // Loading overlay
2798
+ .pdf-loading-overlay {
2799
+ background: Canvas;
2800
+ color: CanvasText;
2801
+ }
2802
+
2803
+ .pdf-loading-spinner {
2804
+ border-color: GrayText;
2805
+ border-top-color: Highlight;
2806
+ }
2807
+
2808
+ // Error and toast
2809
+ .pdf-viewer-error {
2810
+ border: 2px solid CanvasText;
2811
+ background: Canvas;
2812
+ color: CanvasText;
2813
+ }
2814
+
2815
+ .pdf-viewer-toast {
2816
+ border: 1px solid CanvasText;
2817
+ background: Canvas;
2818
+ color: CanvasText;
2819
+ }
2820
+ }
2821
+
2822
+ .document-comparison-grid {
2823
+ display: grid;
2824
+ grid-template-columns: 1fr 1fr;
2825
+ flex: 1;
2826
+ min-height: 0;
2827
+ gap: 1px; // A thin separator line
2828
+ background-color: var(--pdf-dark-border); // Use border color for the gap
2829
+
2830
+ .pdf-viewer-container {
2831
+ background-color: #525659;
2832
+ overflow: hidden; // The container itself shouldn't scroll
2833
+ display: flex;
2834
+ flex-direction: column;
2835
+ }
2836
+
2837
+ // Target the actual scrollable area defined in your previous CSS
2838
+ .pdf-pages-container {
2839
+ overflow: auto;
2840
+ -webkit-overflow-scrolling: touch;
2841
+ scrollbar-gutter: stable; // Prevents layout shift when scrollbars appear
2842
+ }
2843
+ }