sitedrift 0.1.0 → 0.3.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,779 @@
1
+ /* sitedrift viewer — dark review chrome around two site panes.
2
+ Tokenised, nested, logical-property CSS; values preserved 1:1 from the
3
+ original inline styles. The SEO panel (§ SEO) intentionally keeps Google's
4
+ own SERP palette inline rather than tokenising it. */
5
+
6
+ /* ── Tokens ─────────────────────────────────────────────────────────── */
7
+ :root {
8
+ color-scheme: dark;
9
+
10
+ --bg: #090a0c; /* app background */
11
+ --panel: #111318; /* label bar / drawer */
12
+ --surface: #191c22; /* buttons, icon controls, note cards */
13
+ --raised: #20242b; /* hover state */
14
+ --field: #090b0e; /* text inputs */
15
+ --card: #15181e; /* floating cards + segmented control */
16
+ --line: #2a2e37; /* hairline borders */
17
+ --card-line: #343945; /* floating-card + mobile-pane borders */
18
+
19
+ --text: #f5f7fa;
20
+ --control: #dce1e9; /* button label text */
21
+ --muted: #8b93a3;
22
+ --on-accent: #0b0d10; /* dark text on bright badges */
23
+
24
+ --dev: #71d99e;
25
+ --live: #86a8ff; /* also the focus-ring colour */
26
+ --warn: #e8c468;
27
+ --err: #e0556b;
28
+ --active: #283044; /* pressed/active control fill */
29
+ --active-line: #4f6081;
30
+
31
+ --ctl: 34px; /* control height */
32
+ --r: 7px; /* control radius */
33
+ --r-sm: 6px;
34
+ --r-card: 10px;
35
+ --pill: 999px;
36
+
37
+ --t: .2s;
38
+ --t-fast: .15s;
39
+ --ease: ease;
40
+
41
+ --drawer: min(420px, calc(100vw - 24px));
42
+ --shadow-pop: 0 18px 50px rgb(0 0 0 / 60%);
43
+
44
+ --split: 50%;
45
+ font: 13px/1.4 Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
46
+ }
47
+
48
+ /* ── Reset + element defaults ───────────────────────────────────────── */
49
+ * { box-sizing: border-box; }
50
+
51
+ html, body {
52
+ block-size: 100%;
53
+ margin: 0;
54
+ overflow: hidden;
55
+ background: var(--bg);
56
+ color: var(--text);
57
+ }
58
+
59
+ button, input { font: inherit; }
60
+
61
+ button, summary, .label, .compactbar, .divider, .mark, .pill, .icon-control {
62
+ user-select: none;
63
+ -webkit-user-select: none;
64
+ -webkit-tap-highlight-color: transparent;
65
+ }
66
+ button, summary, .open-side { -webkit-touch-callout: none; }
67
+
68
+ button:focus, summary:focus { outline: none; }
69
+ button:focus-visible, summary:focus-visible {
70
+ outline: 2px solid var(--live);
71
+ outline-offset: 2px;
72
+ }
73
+
74
+ .sr-only {
75
+ position: absolute;
76
+ inline-size: 1px;
77
+ block-size: 1px;
78
+ padding: 0;
79
+ margin: -1px;
80
+ overflow: hidden;
81
+ clip-path: inset(50%);
82
+ white-space: nowrap;
83
+ border: 0;
84
+ }
85
+
86
+ /* ── App shell ──────────────────────────────────────────────────────── */
87
+ .app {
88
+ block-size: 100%;
89
+ display: grid;
90
+ grid-template-rows: 52px 46px minmax(0, 1fr);
91
+ transition: padding-right var(--t) var(--ease);
92
+
93
+ &.drawer-dock {
94
+ padding-right: var(--drawer);
95
+ & .mark strong { display: none; }
96
+ }
97
+
98
+ &.compact {
99
+ grid-template-rows: 38px minmax(0, 1fr);
100
+ & .toolbar, & .labels { display: none; }
101
+ & .compactbar { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto minmax(0, 1fr) auto; }
102
+ & .caret svg { transform: rotate(180deg); }
103
+ }
104
+ &.compact.solo .compactbar { grid-template-columns: 30px minmax(0, 1fr) auto auto; }
105
+ }
106
+
107
+ /* ── Toolbar + compact bar ──────────────────────────────────────────── */
108
+ .toolbar {
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 8px;
112
+ padding: 8px 12px;
113
+ background: rgb(17 19 24 / 96%);
114
+ border-bottom: 1px solid var(--line);
115
+
116
+ /* Only the route box (and the spacer) absorb width; controls keep their size. */
117
+ & > .mark,
118
+ & > button,
119
+ & > .modes,
120
+ & > .overlay-slider,
121
+ & > details { flex-shrink: 0; }
122
+ }
123
+
124
+ .toolbar-spacer { flex: 1 1 0; min-inline-size: 0; }
125
+
126
+ .compactbar {
127
+ display: none;
128
+ min-inline-size: 0;
129
+ align-items: center;
130
+ gap: 8px;
131
+ padding: 3px 8px;
132
+ background: rgb(17 19 24 / 98%);
133
+ border-bottom: 1px solid var(--line);
134
+ }
135
+ .compact-side { min-inline-size: 0; display: flex; align-items: center; gap: 6px; }
136
+ .compact-title { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 650; }
137
+ .compact-controls { display: flex; align-items: center; gap: 8px; justify-self: center; }
138
+
139
+ .caret {
140
+ inline-size: 30px;
141
+ block-size: 30px;
142
+ padding: 0;
143
+ font-size: 16px;
144
+
145
+ & svg { display: block; inline-size: 14px; block-size: 14px; margin: auto; transition: transform .18s var(--ease); }
146
+ }
147
+
148
+ /* ── Brand + route field ────────────────────────────────────────────── */
149
+ .mark {
150
+ display: flex;
151
+ align-items: center;
152
+ gap: 9px;
153
+ margin-right: 5px;
154
+ white-space: nowrap;
155
+
156
+ & strong { letter-spacing: -.01em; font-size: 14px; }
157
+ }
158
+ .mark-icon { display: block; inline-size: 20px; block-size: 20px; border-radius: 5px; box-shadow: 0 0 16px rgb(113 217 158 / 33%); }
159
+
160
+ .route {
161
+ min-inline-size: 52px;
162
+ flex: 0 1 220px;
163
+ block-size: var(--ctl);
164
+ padding: 0 11px;
165
+ color: var(--text);
166
+ background: var(--field);
167
+ border: 1px solid var(--line);
168
+ border-radius: var(--r);
169
+ outline: none;
170
+ transition: flex-basis var(--t) var(--ease);
171
+
172
+ &:focus { flex-basis: min(560px, 55vw); border-color: #65718a; box-shadow: 0 0 0 3px rgb(101 113 138 / 13%); }
173
+ }
174
+
175
+ /* ── Buttons ────────────────────────────────────────────────────────── */
176
+ button {
177
+ block-size: var(--ctl);
178
+ padding: 0 11px;
179
+ color: var(--control);
180
+ background: var(--surface);
181
+ border: 1px solid var(--line);
182
+ border-radius: var(--r);
183
+ cursor: pointer;
184
+
185
+ &:hover { background: #222630; border-color: #3b414d; }
186
+ &.active { color: #fff; background: var(--active); border-color: var(--active-line); }
187
+
188
+ &.icon { inline-size: var(--ctl); padding: 0; font-size: 15px; }
189
+ &.icon svg { display: block; inline-size: 16px; block-size: 16px; margin: auto; }
190
+ }
191
+
192
+ .icon-control {
193
+ display: grid;
194
+ inline-size: var(--ctl);
195
+ block-size: var(--ctl);
196
+ padding: 0;
197
+ place-items: center;
198
+ color: var(--control);
199
+ background: var(--surface);
200
+ border: 1px solid var(--line);
201
+ border-radius: var(--r);
202
+
203
+ & svg { display: block; inline-size: 16px; block-size: 16px; margin: auto; }
204
+ }
205
+
206
+ button[data-action="notes"] {
207
+ position: relative;
208
+
209
+ & .count {
210
+ position: absolute;
211
+ top: -5px;
212
+ right: -5px;
213
+ display: inline-grid;
214
+ place-items: center;
215
+ min-inline-size: 16px;
216
+ block-size: 16px;
217
+ padding: 0 4px;
218
+ color: var(--on-accent);
219
+ background: var(--control);
220
+ border-radius: 9px;
221
+ font-size: 10px;
222
+ font-weight: 800;
223
+ }
224
+ }
225
+
226
+ /* Segmented Split/Solo/Overlay control. */
227
+ .modes {
228
+ display: inline-flex;
229
+ align-items: center;
230
+ border: 1px solid var(--line);
231
+ border-radius: 8px;
232
+ overflow: hidden;
233
+
234
+ & button {
235
+ block-size: var(--ctl);
236
+ padding: 0 12px;
237
+ color: var(--muted);
238
+ background: var(--card);
239
+ border: 0;
240
+ border-radius: 0;
241
+ font-weight: 600;
242
+ }
243
+ & button + button { border-left: 1px solid var(--line); }
244
+ & button:hover { background: var(--raised); color: var(--text); }
245
+ & button.active { background: var(--active); color: #fff; }
246
+ }
247
+ .compactbar .modes button { block-size: 30px; padding: 0 9px; }
248
+
249
+ /* Overlay opacity slider + difference-blend toggle. */
250
+ .overlay-slider {
251
+ display: none;
252
+ align-items: center;
253
+ gap: 8px;
254
+ padding: 0 2px;
255
+
256
+ & input[type="range"] { inline-size: 120px; accent-color: var(--live); transition: opacity var(--t-fast) var(--ease); }
257
+ }
258
+ .overlay-blend.active { color: #fff; background: var(--active); border-color: var(--active-line); }
259
+
260
+ /* ── Label bar (per-pane identity + meta) ───────────────────────────── */
261
+ .labels {
262
+ position: relative;
263
+ z-index: 20;
264
+ display: grid;
265
+ grid-template-columns: var(--split) 1fr;
266
+ background: var(--panel);
267
+ border-bottom: 1px solid var(--line);
268
+ }
269
+
270
+ .label {
271
+ position: relative;
272
+ min-inline-size: 0;
273
+ display: flex;
274
+ align-items: center;
275
+ justify-content: space-between;
276
+ gap: 12px;
277
+ padding: 0 12px;
278
+ border-right: 1px solid var(--line);
279
+
280
+ &:last-child { border-right: 0; }
281
+ }
282
+
283
+ .identity { min-inline-size: 0; display: grid; grid-template-columns: auto 24px minmax(0, 1fr); align-items: center; gap: 9px; }
284
+ .pill { font-size: 10px; font-weight: 800; letter-spacing: .11em; }
285
+ .pill.dev { color: var(--dev); }
286
+ .pill.live { color: var(--live); }
287
+ .favicon { inline-size: 24px; block-size: 24px; object-fit: contain; }
288
+
289
+ .page-meta { min-inline-size: 0; display: flex; flex-direction: column; line-height: 1.2; }
290
+ .page-heading { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; color: var(--text); font-weight: 650; white-space: nowrap; }
291
+ .origin { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; color: var(--muted); white-space: nowrap; font-size: 11px; }
292
+
293
+ .label-actions { display: flex; align-items: center; gap: 5px; }
294
+ .open-side {
295
+ display: inline-flex;
296
+ align-items: center;
297
+ gap: 4px;
298
+ color: var(--muted);
299
+ text-decoration: none;
300
+ font-size: 12px;
301
+
302
+ &:hover { color: var(--text); }
303
+ & svg { inline-size: 12px; block-size: 12px; }
304
+ }
305
+
306
+ .hint { color: var(--muted); white-space: nowrap; font-size: 11px; }
307
+
308
+ /* HTTP status + metadata-diff badges. */
309
+ .status-badge {
310
+ display: none;
311
+ align-items: center;
312
+ block-size: 18px;
313
+ padding: 0 6px;
314
+ border-radius: var(--r-sm);
315
+ font-size: 10px;
316
+ font-weight: 800;
317
+ letter-spacing: .04em;
318
+
319
+ &.show { display: inline-flex; }
320
+ }
321
+ .status-ok { color: var(--on-accent); background: var(--dev); }
322
+ .status-warn { color: var(--on-accent); background: var(--warn); }
323
+ .status-err { color: #fff; background: var(--err); }
324
+ .compact-side .status-badge { block-size: 16px; }
325
+
326
+ .meta-diff {
327
+ display: none;
328
+ align-items: center;
329
+ block-size: 18px;
330
+ padding: 0 7px;
331
+ color: var(--on-accent);
332
+ background: var(--warn);
333
+ border-radius: var(--r-sm);
334
+ font-size: 10px;
335
+ font-weight: 800;
336
+ cursor: default;
337
+
338
+ &.show { display: inline-flex; }
339
+ }
340
+
341
+ /* ── Popovers: details menus, settings + help cards ─────────────────── */
342
+ details { position: relative; }
343
+ summary {
344
+ list-style: none;
345
+ padding: 5px 7px;
346
+ color: var(--muted);
347
+ border: 1px solid transparent;
348
+ border-radius: var(--r-sm);
349
+ cursor: pointer;
350
+ white-space: nowrap;
351
+ user-select: none;
352
+
353
+ &::-webkit-details-marker { display: none; }
354
+ }
355
+ summary:hover, details[open] summary { color: var(--text); background: var(--raised); border-color: var(--line); }
356
+
357
+ .settings-card {
358
+ position: fixed;
359
+ z-index: 65;
360
+ top: 48px;
361
+ right: 52px;
362
+ inline-size: 230px;
363
+ padding: 8px;
364
+ background: var(--card);
365
+ border: 1px solid var(--card-line);
366
+ border-radius: var(--r-card);
367
+ box-shadow: var(--shadow-pop);
368
+ }
369
+ .setting-row {
370
+ inline-size: 100%;
371
+ display: flex;
372
+ align-items: center;
373
+ justify-content: space-between;
374
+ block-size: 38px;
375
+ padding: 0 10px;
376
+ background: transparent;
377
+ border-color: transparent;
378
+ text-align: left;
379
+
380
+ &:hover { background: var(--raised); }
381
+ & .state { color: var(--muted); font-size: 11px; }
382
+ &.active .state { color: var(--dev); }
383
+ }
384
+
385
+ .help-card {
386
+ position: fixed;
387
+ z-index: 65;
388
+ top: 48px;
389
+ right: 8px;
390
+ inline-size: 300px;
391
+ padding: 14px;
392
+ background: var(--card);
393
+ border: 1px solid var(--card-line);
394
+ border-radius: var(--r-card);
395
+ box-shadow: var(--shadow-pop);
396
+
397
+ & strong { display: block; margin-bottom: 9px; }
398
+ }
399
+ .help-blurb {
400
+ margin: 0 0 12px;
401
+ color: var(--muted);
402
+ line-height: 1.5;
403
+
404
+ & b { color: var(--text); font-weight: 650; }
405
+ }
406
+ .help-credit {
407
+ margin-top: 13px;
408
+ padding-top: 11px;
409
+ border-top: 1px solid var(--line);
410
+ color: var(--muted);
411
+ font-size: 11px;
412
+
413
+ & a { color: var(--text); text-decoration: none; }
414
+ & a:hover { color: var(--live); text-decoration: underline; }
415
+ }
416
+ .shortcut-list {
417
+ display: grid;
418
+ grid-template-columns: auto 1fr;
419
+ gap: 7px 12px;
420
+ margin: 0;
421
+
422
+ & dt { color: #fff; font-weight: 650; }
423
+ & dd { margin: 0; color: var(--muted); }
424
+ }
425
+ kbd { padding: 1px 5px; color: #e8ebf0; background: #242932; border: 1px solid #3d4552; border-radius: 4px; font: 11px ui-monospace, monospace; }
426
+
427
+ /* ── SEO panel (Google SERP preview — keeps Google's own palette) ───── */
428
+ .seo-summary { display: inline-flex; align-items: center; gap: 4px; }
429
+ .seo-summary svg { inline-size: 11px; block-size: 11px; }
430
+ .seo-flag {
431
+ display: inline-grid;
432
+ place-items: center;
433
+ min-inline-size: 15px;
434
+ block-size: 15px;
435
+ padding: 0 4px;
436
+ border-radius: 8px;
437
+ background: var(--warn);
438
+ color: var(--on-accent);
439
+ font-size: 9px;
440
+ font-weight: 800;
441
+ }
442
+ .seo-flag[hidden] { display: none; }
443
+
444
+ .seo-card {
445
+ position: fixed;
446
+ z-index: 60;
447
+ top: 108px;
448
+ left: 12px;
449
+ inline-size: min(520px, calc(100vw - 24px));
450
+ max-block-size: calc(100vh - 128px);
451
+ overflow: auto;
452
+ padding: 18px 20px;
453
+ color: #202124;
454
+ background: #fff;
455
+ border: 1px solid #dfe1e5;
456
+ border-radius: var(--r-card);
457
+ box-shadow: 0 18px 55px rgb(0 0 0 / 47%);
458
+ font-family: Arial, sans-serif;
459
+ }
460
+ .seo-eyebrow { margin-bottom: 12px; color: #5f6368; font: 11px/1.2 Inter, sans-serif; letter-spacing: .08em; text-transform: uppercase; }
461
+ .seo-source { display: grid; grid-template-columns: 28px minmax(0, 1fr) 20px; align-items: center; gap: 10px; }
462
+ .seo-favicon { inline-size: 28px; block-size: 28px; padding: 4px; object-fit: contain; background: #f1f3f4; border-radius: 50%; }
463
+ .seo-site { color: #202124; font-size: 14px; line-height: 18px; }
464
+ .seo-url { color: #4d5156; font-size: 12px; line-height: 16px; }
465
+ .seo-menu { color: #4d5156; font-size: 20px; line-height: 1; letter-spacing: 1px; }
466
+ .seo-title { margin-top: 5px; color: #1a0dab; font-size: 20px; line-height: 26px; font-weight: 400; }
467
+ .seo-description { margin-top: 3px; color: #4d5156; font-size: 14px; line-height: 22px; }
468
+ .seo-empty { color: #b3261e; font-style: italic; }
469
+ .seo-diff { background: #fdeec9; outline: 2px solid #f0b429; outline-offset: 1px; border-radius: 3px; }
470
+
471
+ .seo-checks { margin-top: 16px; padding-top: 13px; border-top: 1px solid #e6e8eb; }
472
+ .seo-checks-head {
473
+ display: flex;
474
+ align-items: center;
475
+ justify-content: space-between;
476
+ margin-bottom: 9px;
477
+ color: #5f6368;
478
+ font: 600 11px/1.2 Inter, sans-serif;
479
+ letter-spacing: .06em;
480
+ text-transform: uppercase;
481
+
482
+ & .bad { color: #c5221f; }
483
+ & .good { color: #137333; }
484
+ }
485
+ .seo-check {
486
+ display: grid;
487
+ grid-template-columns: 15px 1fr auto;
488
+ align-items: baseline;
489
+ gap: 9px;
490
+ padding: 3px 0;
491
+ font-size: 13px;
492
+ line-height: 18px;
493
+
494
+ &.ok .seo-check-mark { color: #137333; }
495
+ &.bad .seo-check-mark { color: #c5221f; }
496
+ &.bad .seo-check-label { color: #c5221f; }
497
+ }
498
+ .seo-check-mark { font-weight: 800; text-align: center; }
499
+ .seo-check-note { color: #80868b; font-size: 11px; white-space: nowrap; }
500
+
501
+ /* ── Stage: panes, divider, frames ──────────────────────────────────── */
502
+ .stage { position: relative; display: grid; grid-template-columns: var(--split) 1fr; min-block-size: 0; }
503
+ .pane {
504
+ position: relative;
505
+ min-inline-size: 0;
506
+ overflow: hidden;
507
+ background: #fff;
508
+
509
+ &:first-child { border-right: 1px solid var(--line); }
510
+ }
511
+ iframe { display: block; inline-size: 100%; block-size: 100%; border: 0; background: #fff; }
512
+
513
+ .divider {
514
+ position: absolute;
515
+ z-index: 10;
516
+ top: 0;
517
+ bottom: 0;
518
+ left: var(--split);
519
+ inline-size: 17px;
520
+ transform: translateX(-50%);
521
+ cursor: col-resize;
522
+ touch-action: none;
523
+
524
+ &:focus { outline: none; }
525
+ &:focus-visible { outline: 2px solid var(--live); outline-offset: -2px; }
526
+ &::before { content: ""; position: absolute; top: 0; bottom: 0; left: 8px; inline-size: 1px; background: #596171; }
527
+ }
528
+ .grip {
529
+ position: absolute;
530
+ top: 50%;
531
+ left: 50%;
532
+ inline-size: 24px;
533
+ block-size: 54px;
534
+ transform: translate(-50%, -50%);
535
+ border: 1px solid #454c59;
536
+ border-radius: 12px;
537
+ background: #171a20;
538
+ box-shadow: 0 8px 30px rgb(0 0 0 / 53%);
539
+
540
+ &::after { content: ""; position: absolute; inset: 15px 8px; background: repeating-linear-gradient(90deg, #788190 0 1px, transparent 1px 4px); }
541
+ }
542
+ .dragging iframe { pointer-events: none; }
543
+
544
+ /* ── Layout modes: mobile, solo, overlay ────────────────────────────── */
545
+ .app.mobile {
546
+ & .stage {
547
+ grid-template-columns: repeat(2, minmax(320px, 390px));
548
+ justify-content: center;
549
+ align-items: stretch;
550
+ gap: 22px;
551
+ overflow-x: auto;
552
+ padding: 14px 22px;
553
+ background: #08090b;
554
+ }
555
+ & .pane { border: 1px solid var(--card-line); border-radius: 13px; box-shadow: 0 14px 42px rgb(0 0 0 / 53%); }
556
+ & .divider { display: none; }
557
+ & .labels { grid-template-columns: 1fr 1fr; padding-inline: max(0px, calc((100% - 802px) / 2)); }
558
+ }
559
+ .app.mobile.solo .stage { grid-template-columns: minmax(320px, 390px); }
560
+
561
+ .app.solo {
562
+ & .stage { grid-template-columns: minmax(0, 1fr); }
563
+ & .labels { grid-template-columns: minmax(0, 1fr); }
564
+ & .divider { display: none; }
565
+
566
+ &[data-focus="dev"] [data-pane="live"],
567
+ &[data-focus="live"] [data-pane="dev"] {
568
+ position: absolute;
569
+ inset: 0;
570
+ visibility: hidden;
571
+ pointer-events: none;
572
+ }
573
+ &[data-focus="dev"] .label[data-label="live"],
574
+ &[data-focus="live"] .label[data-label="dev"],
575
+ &[data-focus="dev"] [data-compact-side="live"],
576
+ &[data-focus="live"] [data-compact-side="dev"] { display: none; }
577
+ }
578
+
579
+ .app.overlay {
580
+ & .stage { grid-template-columns: minmax(0, 1fr); }
581
+ & .pane { position: absolute; inset: 0; }
582
+ & .pane:first-child { border-right: 0; }
583
+ & .overlay-top { opacity: var(--overlay, .5); }
584
+ & .divider { display: none; }
585
+ & .labels { grid-template-columns: 1fr 1fr; }
586
+ & .overlay-slider { display: flex; }
587
+
588
+ &.diff .stage { background: #000; }
589
+ &.diff .overlay-top { opacity: 1; mix-blend-mode: difference; }
590
+ &.diff .overlay-slider input[type="range"] { opacity: .4; pointer-events: none; }
591
+ &.diff .diff-legend { display: block; }
592
+ }
593
+
594
+ .diff-legend {
595
+ display: none;
596
+ position: fixed;
597
+ z-index: 40;
598
+ left: 50%;
599
+ bottom: 16px;
600
+ transform: translateX(-50%);
601
+ padding: 6px 13px;
602
+ color: #cdd3dd;
603
+ background: rgb(17 19 24 / 92%);
604
+ border: 1px solid var(--line);
605
+ border-radius: var(--pill);
606
+ font-size: 11px;
607
+ pointer-events: none;
608
+ white-space: nowrap;
609
+ }
610
+
611
+ /* ── Review-notes drawer ────────────────────────────────────────────── */
612
+ .review-drawer {
613
+ position: fixed;
614
+ z-index: 50;
615
+ top: 0;
616
+ right: 0;
617
+ bottom: 0;
618
+ inline-size: var(--drawer);
619
+ display: grid;
620
+ grid-template-rows: auto minmax(0, 1fr) auto;
621
+ color: var(--text);
622
+ background: var(--panel);
623
+ border-left: 1px solid var(--line);
624
+ box-shadow: -18px 0 55px rgb(0 0 0 / 60%);
625
+ transform: translateX(102%);
626
+ transition: transform var(--t) var(--ease);
627
+
628
+ &.open { transform: translateX(0); }
629
+ }
630
+ .review-drawer:has(.local-notes-notice:not([hidden])) {
631
+ grid-template-rows: auto auto minmax(0, 1fr) auto;
632
+ }
633
+ .drawer-head {
634
+ display: flex;
635
+ align-items: center;
636
+ gap: 8px;
637
+ padding: 14px 16px;
638
+ border-bottom: 1px solid var(--line);
639
+
640
+ & strong { flex: 1; font-size: 14px; }
641
+ & .icon { inline-size: 30px; block-size: 30px; }
642
+ & .icon.active { color: #fff; background: var(--active); border-color: var(--active-line); }
643
+ }
644
+ .local-notes-notice {
645
+ margin: 12px 16px 0;
646
+ padding: 9px 10px;
647
+ color: var(--muted);
648
+ background: color-mix(in srgb, var(--field) 82%, transparent);
649
+ border: 1px solid var(--line);
650
+ border-radius: var(--r);
651
+ font-size: 12px;
652
+ line-height: 1.45;
653
+ }
654
+
655
+ .note-list {
656
+ margin: 0;
657
+ padding: 14px 16px 14px 38px;
658
+ overflow: auto;
659
+
660
+ & li {
661
+ position: relative;
662
+ margin-bottom: 10px;
663
+ padding: 9px 92px 9px 11px;
664
+ background: var(--surface);
665
+ border: 1px solid var(--line);
666
+ border-radius: 8px;
667
+ }
668
+ & li.done { opacity: .55; }
669
+ & li.done .note-text { text-decoration: line-through; }
670
+ &:empty::after { content: "No review notes yet."; display: block; margin-left: -22px; color: var(--muted); }
671
+ }
672
+
673
+ .note-meta { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
674
+ .note-author {
675
+ padding: 1px 6px;
676
+ border-radius: 5px;
677
+ font-size: 10px;
678
+ font-weight: 800;
679
+ letter-spacing: .05em;
680
+ text-transform: uppercase;
681
+ }
682
+ .note-author.joe { color: var(--on-accent); background: var(--live); }
683
+ .note-author.claude { color: var(--on-accent); background: #d8a0ff; }
684
+ .note-author.other { color: var(--on-accent); background: #9aa3b2; }
685
+ .note-where { color: var(--muted); font-size: 10px; }
686
+ .note-text { white-space: pre-wrap; word-break: break-word; }
687
+ .note-go { cursor: pointer; }
688
+ .note-go:hover { color: var(--live); text-decoration: underline; }
689
+
690
+ /* Square icon buttons docked inside a note card. */
691
+ .remove-note { position: absolute; top: 5px; right: 5px; inline-size: 26px; block-size: 26px; padding: 0; }
692
+ .note-toggle { position: absolute; top: 5px; right: 34px; inline-size: 26px; block-size: 26px; padding: 0; }
693
+ .note-copy { position: absolute; top: 5px; right: 63px; inline-size: 26px; block-size: 26px; padding: 0; }
694
+ .note-copy svg { display: block; inline-size: 14px; block-size: 14px; margin: auto; }
695
+
696
+ .note-compose { display: grid; gap: 8px; padding: 14px 16px; border-top: 1px solid var(--line); }
697
+ .note-compose textarea {
698
+ inline-size: 100%;
699
+ min-block-size: 76px;
700
+ resize: none;
701
+ overflow-y: hidden;
702
+ padding: 9px 10px;
703
+ color: var(--text);
704
+ background: var(--field);
705
+ border: 1px solid var(--line);
706
+ border-radius: var(--r);
707
+ font: inherit;
708
+ }
709
+ .note-grip {
710
+ block-size: 9px;
711
+ margin: -2px 0 1px;
712
+ cursor: ns-resize;
713
+ touch-action: none;
714
+
715
+ &::before { content: ""; display: block; inline-size: 34px; block-size: 3px; margin: 3px auto 0; border-radius: 2px; background: var(--line); }
716
+ &:hover::before { background: var(--muted); }
717
+ }
718
+ .note-input { position: relative; }
719
+ .note-input textarea { padding-right: 44px; }
720
+ .note-submit { position: absolute; right: 8px; bottom: 8px; inline-size: 30px; block-size: 30px; padding: 0; }
721
+ .note-submit svg { display: block; inline-size: 16px; block-size: 16px; margin: auto; }
722
+ .note-actions { display: flex; flex-wrap: wrap; gap: 8px; }
723
+ .note-actions button { flex: 1; }
724
+ .note-actions:empty { display: none; }
725
+
726
+ /* ── Toast ──────────────────────────────────────────────────────────── */
727
+ .toast {
728
+ position: fixed;
729
+ z-index: 70;
730
+ left: 50%;
731
+ bottom: 18px;
732
+ padding: 8px 12px;
733
+ color: #fff;
734
+ background: #252a33;
735
+ border: 1px solid #414957;
736
+ border-radius: 8px;
737
+ box-shadow: 0 8px 28px rgb(0 0 0 / 53%);
738
+ opacity: 0;
739
+ transform: translate(-50%, 8px);
740
+ pointer-events: none;
741
+ transition: .18s var(--ease);
742
+
743
+ &.show { opacity: 1; transform: translate(-50%, 0); }
744
+ }
745
+
746
+ /* ── Responsive + motion ────────────────────────────────────────────── */
747
+ @media (width <= 820px) {
748
+ .mark strong, .hint, button[data-wide] .control-label { display: none; }
749
+ .toolbar { padding-inline: 8px; }
750
+ .open-side { display: none; }
751
+ .app.mobile .stage { justify-content: start; }
752
+ }
753
+
754
+ @media (width <= 600px) {
755
+ .app, .toolbar { min-inline-size: 0; }
756
+ .toolbar { gap: 6px; }
757
+ .toolbar .mark { margin-right: 0; }
758
+ .toolbar .route { inline-size: 0; flex: 1 1 auto; }
759
+ .toolbar-spacer,
760
+ .toolbar > .caret,
761
+ .toolbar > [data-action="go"],
762
+ .toolbar > .overlay-slider,
763
+ .toolbar > [data-action="reload"],
764
+ .toolbar > [data-action="scroll"],
765
+ .toolbar > [data-action="notes"],
766
+ .toolbar > details { display: none; }
767
+ .toolbar > .modes button { padding-inline: 8px; }
768
+ .label { gap: 6px; padding-inline: 8px; }
769
+ .identity { grid-template-columns: auto minmax(0, 1fr); gap: 6px; }
770
+ .identity .favicon { display: none; }
771
+ .label-actions > :not(.status-badge) { display: none; }
772
+ }
773
+
774
+ @media (prefers-reduced-motion: reduce) {
775
+ *, *::before, *::after {
776
+ transition-duration: .01ms !important;
777
+ animation-duration: .01ms !important;
778
+ }
779
+ }