Skip to main content

max / goingson

226.7 KB · 9593 lines History Blame Raw
1 /* ============================================================================
2 GoingsOn — Neobrute Theme
3
4 Build new UI by COMPOSING the existing vocabulary, in this order of preference:
5
6 1. Use a UTILITY class for one-off adjustments (.mb-1, .mb-2, .flex-1,
7 .text-sm-secondary, .hidden)
8 2. Use a LAYOUT PRIMITIVE to position content (.row-flex + .row-flex-{2,3,4},
9 .row, .stack-{2,3,4})
10 3. Use a COMPONENT PRIMITIVE for a UI element (.card, .btn, .form-input,
11 .form-select, .modal, .badge,
12 .tag, .toggle-switch)
13 4. Extend a primitive with a modifier (.btn-primary, .btn-sm,
14 .form-select--compact,
15 .subtask-item--linked)
16 5. ONLY THEN consider a new class — and add it to the right
17 BAND below
18
19 A new class is a smell, not a goal. Before writing one:
20 • grep this file for the visual shape you want; almost everything is here
21 • check whether an existing primitive + modifier composes to your shape
22 • page-scoped rules under a feature class (`.day-plan .foo`) are a last
23 resort, not a first move
24
25 WHEN UTILITY-STACKING IS WRONG: A row of mixed-intent elements (one fills,
26 others size to content) belongs in a NAMED LAYOUT with an explicit
27 `grid-template-columns`, not in `.row-flex` + utilities. The utility form
28 encodes intent in browser flex-shrink math rather than in CSS that reads
29 as intent — especially fragile when the row contains a native `<select>`,
30 whose intrinsic-min-content sizing fights `flex: 1`. Smell test: if you
31 find yourself reaching for `.form-select--compact`, `style="width: auto;"`,
32 or `min-width: 0 !important` to make a row lay out right, the layout
33 itself wants a name. See `.email-filter-row`, `.contacts-filter-row`, and
34 `.work-hours-row` (all 2026-05-24) for the canonical form.
35
36 ----------------------------------------------------------------------------
37 FILE STRUCTURE — search by BAND name (uppercase anchors) to navigate.
38 Per-section titles use `=== N. Title ===` headers; numbered for stability,
39 not because order matters. Bands group related sections; cascade order is
40 load-bearing only inside the RESPONSIVE LAYERS and PRINT LAYERS bands.
41
42 BAND: FOUNDATIONS
43 1. Font Face
44 2. CSS Reset & Base
45 3. Design System Variables (Neobrute) — tokens (:root)
46 4. Utility Classes — shadow/hover/border,
47 layout, form sizing,
48 settings, subtask
49
50 BAND: APP SHELL & CHROME
51 5. Body & App Shell
52 6. Header
53 7. Tab Navigation
54 8. Main Content & Page Header
55
56 BAND: COMPONENT PRIMITIVES & WIDGETS
57 9. Buttons — .btn + variants/sizes
58 10. Quick Add Input
59 11. Cards
60 12. Tags & Badges
61 13. Data Table
62 14. Task Table & Rows
63 15. Due Date Badges
64 16. Events
65 17. Email List
66 18. Toast Notifications
67 19. Modals
68 20. Form Elements — .form-input,
69 .form-select, +
70 JS-rendered layout
71 utilities tail
72 21. Footer
73 22. Empty & Error States
74 23. Filter Bar
75
76 BAND: RESPONSIVE LAYER 1 (see RESPONSIVE STRATEGY)
77 24. Responsive - Large Screens & Tablet
78 25. Responsive - Mobile (768px, base pass)
79
80 BAND: A11Y, PAGINATION, FOCUS
81 26. Screen Reader & Accessibility
82 27. Pagination
83 28. Focus & Keyboard Accessibility
84
85 BAND: EMAIL READER
86 29. Source Email Link
87 30. Email Reader Mode
88
89 BAND: OVERLAYS
90 31. Dropdown Menus
91 32. Context Menus
92 33. Scrollbar Styling
93 34. Desktop App Styles (Loading, Skeleton, Spinner)
94
95 BAND: FEATURE SCREENS (A)
96 35. Project Dashboard 41. Settings
97 36. Task Badges 42. Snooze Options
98 37. Progress Bar 43. Bulk Selection
99 38. Day Plan View 44. Time Blocking
100 39. Timeline 45. App Layout
101 40. Unscheduled Tasks 46. Saved Views Sidebar
102 47. Contacts
103
104 BAND: PRINT LAYER 1 (see PRINT STRATEGY)
105 48. Print Styles (global)
106
107 BAND: WEEKLY REVIEW (V1 + V2 coexist)
108 49. Weekly Review (V1, still live)
109 50. Weekly Review V2 - Grid Layout
110 51. Weekly Review Transitions & Keyboard Navigation
111
112 BAND: PRINT LAYER 2
113 52. Weekly Review Print Styles
114
115 BAND: FEATURE SCREENS (B)
116 52b. Monthly Review 55. Toggle Switch
117 53. Import Wizard 56. Project Milestones
118 54. Plugin Manager (57 intentionally unused)
119
120 BAND: MOBILE LAYER (see RESPONSIVE STRATEGY)
121 58. Mobile Navigation (Nav Dot, Dial, Bottom Sheets)
122 59. Mobile Responsive (768px overrides, late pass)
123 60. Touch Device Hover Disable
124
125 BAND: FEATURE SCREENS (C)
126 61. Kanban Board 66. Timer Subview (Time tab pill)
127 62. Timer Widget 67. Task Overview
128 63. Focus Timer (Pomodoro) 68. Plan/Review Toggle Nudge Dot
129 64. Time Summary Panel 69. Finish & Review
130 65. Task Time Tracking UI 70. Calendar Views
131
132 BAND: SCOPED STYLESHEETS
133 Compose window (compose.html standalone Tauri window)
134
135 ----------------------------------------------------------------------------
136 EXISTING VOCABULARY — grep before inventing a new class.
137
138 UTILITIES
139 Layout .flex-1, .row, .row-flex + .row-flex-{2,3,4},
140 .stack-{2,3,4}, .mb-{1,2}
141 Text .text-sm-secondary, .text-xs-secondary, .text-center,
142 .text-left, .text-muted, .text-accent-red
143 Sizing .flex-1, .w-full
144 State .hidden, .is-selected, .is-active
145
146 LAYOUT PRIMITIVES
147 .row-flex (display:flex; align-items:center) + gap modifier .row-flex-N
148 .row (display:flex, no align) + gap modifier .row-flex-N
149 .stack (vertical) + gap modifier
150
151 COMPONENT PRIMITIVES
152 .btn + .btn-primary / -secondary / -danger / -sm
153 .card + .card--list-item / --shell / --muted (compact / container / info-panel)
154 .form-input + .form-input--ghost
155 .form-select + .form-select--compact / --ghost
156 .modal + .modal-overlay
157 .badge + variants ([data-color], --xs / --sm / --filled)
158 .tag + variants ([data-color])
159 .toggle-switch
160 .avatar + .avatar--sm / --lg / --unknown
161 .toast + variants
162 .pagination-controls
163 .filter-bar / .filter-select
164 .dropdown-menu / .context-menu
165 .empty-state
166
167 CONTROL MODIFIERS
168 Sizes: .btn-sm
169 Intents: .btn-primary / -secondary / -danger
170 Shapes: .form-select--compact / --ghost, .form-input--ghost
171
172 ----------------------------------------------------------------------------
173 UI MODE STRATEGY (do not casually merge)
174
175 UI mode is set ONCE at boot by index.html's inline script and exposed
176 as `<html class="ui-mode-desktop">` or `<html class="ui-mode-mobile">`.
177 Viewport width does NOT switch UI mode — desktop binaries stay desktop
178 even when the window is narrowed.
179
180 §25 Mobile (base pass) — early `.ui-mode-mobile` rules; applies before
181 feature CSS so feature rules can override.
182 §59 Mobile (late pass) — late `.ui-mode-mobile` rules; runs AFTER
183 feature CSS so it wins conflicts. Add new
184 mobile overrides here unless you need them
185 early.
186 §60 Touch hover disable — `@media (hover: none)`. INPUT-CAPABILITY axis,
187 not UI mode. Reserved for hover suppression
188 only. Never put visibility or layout rules
189 here — they belong under `.ui-mode-mobile`.
190
191 Intra-mode responsive: `@media (max-width: ...)` queries are allowed
192 INSIDE a UI mode (e.g. `.ui-mode-desktop` rules at narrow desktop
193 widths). Do not use a media query to switch BETWEEN UI modes.
194
195 PRINT STRATEGY
196 §48 Global print rules — early.
197 §52 Weekly Review print — placed after §49/§50 so V2 grid resets win.
198
199 ----------------------------------------------------------------------------
200 WEEKLY REVIEW V1 + V2 COEXISTENCE
201
202 §49 (V1: .weekly-review-content, .weekly-review-header, ...) and
203 §50 (V2: .review-grid, .review-card, ...) are BOTH live. weekly-review.js
204 and mobile.js still render V1 classes; the V2 grid is used by newer
205 review surfaces. Do not delete §49 until those JS render paths migrate.
206
207 ============================================================================ */
208
209 /* ===================================================================
210 1. Font Face
211 =================================================================== */
212 @font-face {
213 font-family: 'Reglo';
214 src: url('../fonts/Reglo-Bold.woff2') format('woff2');
215 font-weight: 700;
216 font-style: normal;
217 font-display: swap;
218 }
219
220 /* ===================================================================
221 2. CSS Reset & Base
222 =================================================================== */
223 *, *::before, *::after {
224 box-sizing: border-box;
225 margin: 0;
226 padding: 0;
227 }
228
229 /* ===================================================================
230 3. Design System Variables (Neobrute)
231 =================================================================== */
232 :root {
233 /* Day-plan timeline slot height (1 slot = 15 min). Mobile bumps this for fat-finger touch.
234 JS reads it via getComputedStyle so the height: in .timeline-slot stays in sync with
235 positioning math in day-planning-render.js / day-planning.js. */
236 --timeline-slot-h: 12px;
237
238 /* === NEOBRUTE DESIGN SYSTEM === */
239 /* Clean neobrutalism: bold borders, flat by default, offset shadows on actions + floats */
240
241 /* Neo-brutalist color palette */
242 /* Themeable: mapped by js/themes.js. Defaults below are the "neobrute" theme. */
243 --bg-primary: #E0E4FA; /* themeable: background.primary */
244 --bg-secondary: #CDD3F0; /* themeable: background.secondary */
245 --bg-tertiary: #BAC2E6; /* themeable: background.tertiary */
246 --bg-card: #FFFFFF; /* themeable: background.surface */
247
248 --text-primary: #000000; /* themeable: foreground.primary */
249 --text-secondary: #2D2D2D; /* themeable: foreground.secondary */
250 --text-muted: #6B6B6B; /* themeable: foreground.muted (WCAG AA 5.7:1 on white) */
251
252 --accent-yellow: #F7D154; /* themeable: accent.yellow */
253 --accent-green: #5CB85C; /* themeable: accent.green */
254 --accent-blue: #6196FF; /* themeable: accent.blue */
255 --accent-purple: #7B68EE; /* themeable: accent.purple */
256 --accent-red: #DC3545; /* themeable: accent.red */
257 --accent-cyan: #17A2B8; /* themeable: accent.cyan */
258
259 --border-color: #000000; /* themeable: border.default */
260 --border-width: 2px; /* theme-invariant */
261 --border-width-sm: 2px; /* theme-invariant */
262
263 /* Derived aliases — automatically follow their upstream tokens, so themes don't need to override them. */
264 --accent-color: var(--accent-blue); /* derived from --accent-blue */
265 --accent-primary: var(--accent-blue); /* derived from --accent-blue */
266 --bg-hover: var(--bg-tertiary); /* derived from --bg-tertiary */
267 --border-light: var(--bg-tertiary); /* derived from --bg-tertiary */
268 --text-on-accent: var(--bg-card); /* derived: relies on accents being saturated mid-tones; review on theme switch */
269
270 /* Shadow offset scale (used by 3D action elements only) */
271 --shadow-offset-xs: 1px;
272 --shadow-offset-md: 3px;
273 --shadow-offset: 4px;
274 --shadow-offset-lg: 6px;
275 --shadow-offset-xl: 8px;
276
277 /* Neobrutalist shadows — actions + floats only */
278 --shadow-brutal-xs: var(--shadow-offset-xs) var(--shadow-offset-xs) 0 var(--border-color);
279 --shadow-brutal-md: var(--shadow-offset-md) var(--shadow-offset-md) 0 var(--border-color);
280 --shadow-brutal-lg: var(--shadow-offset-lg) var(--shadow-offset-lg) 0 var(--border-color);
281 --shadow-brutal-xl: var(--shadow-offset-xl) var(--shadow-offset-xl) 0 var(--border-color);
282
283 /* Border radius scale */
284 --radius-xs: 3px; /* Scrollbars, tiny elements */
285 --radius-sm: 5px; /* Buttons, inputs, small cards */
286 --radius-md: 5px; /* Cards, buttons — uniform */
287 --radius-lg: 10px; /* Modals, large panels */
288 --radius-xl: 20px; /* Pills, capsules */
289 --radius-full: 50%; /* Circles */
290
291 /* Layout widths */
292 --width-container: 1400px;
293 --width-modal: 560px;
294 --width-sidebar: 280px;
295
296 /* Spacing scale */
297 --space-1: 0.25rem;
298 --space-2: 0.5rem;
299 --space-3: 0.75rem;
300 --space-4: 1rem;
301 --space-5: 1.25rem;
302 --space-6: 1.5rem;
303
304 --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
305 --font-serif: Georgia, 'Times New Roman', serif;
306 --font-mono: 'SF Mono', 'Consolas', 'Liberation Mono', monospace;
307 --font-display: 'Reglo', var(--font-serif);
308
309 /* Semantic font aliases */
310 --font-heading: var(--font-sans);
311 --font-body: var(--font-sans);
312
313 /* Typography scale */
314 --font-size-xxs: 0.65rem; /* Tiny badges, indicators */
315 --font-size-xs: 0.7rem; /* Small badges, counts */
316 --font-size-sm: 0.75rem; /* Meta text, timestamps */
317 --font-size-md: 0.8rem; /* Table headers, compact UI */
318 --font-size-base: 0.875rem;/* Body text default */
319 --font-size-lg: 1rem; /* Emphasized body text */
320 --font-size-xl: 1.1rem; /* Subheadings */
321 --font-size-2xl: 1.25rem; /* Section titles */
322 --font-size-3xl: 1.5rem; /* Page titles */
323 --font-size-4xl: 1.75rem; /* Main headings */
324
325 /* Line height scale */
326 --line-height-tight: 1.25;
327 --line-height-normal: 1.5;
328 --line-height-relaxed: 1.75;
329
330 /* Transition timing */
331 --transition-fast: 0.1s;
332 --transition-normal: 0.15s;
333 --transition-slow: 0.3s;
334
335 /* Modal overlay — derived: mixes --text-primary into transparent. On a dark theme this
336 produces a *light* scrim, which is wrong; dark themes should override with their own
337 --overlay-color or this should be reworked to use a dedicated --scrim token. */
338 --overlay-color: color-mix(in srgb, var(--text-primary) 60%, transparent);
339
340 }
341
342 html {
343 font-size: 16px;
344 }
345
346 /* ===================================================================
347 4. Utility Classes (Shadow, Hover, Border)
348 =================================================================== */
349 /* === LAYOUT UTILITIES === */
350 /* Compose: .row-flex + .row-flex-{2,3,4} for align-items:center rows.
351 .row for raw flex with no align. .flex-1 to grow a child. */
352 .flex-1 { flex: 1; }
353 .row { display: flex; }
354 .text-sm-secondary { font-size: 0.875rem; color: var(--text-secondary); }
355 .text-xs-secondary { font-size: 0.75rem; color: var(--text-secondary); }
356 .text-accent-red { color: var(--accent-red); }
357 .mb-1 { margin-bottom: 1rem; }
358 .mb-2 { margin-bottom: var(--space-2); }
359
360 /* === FORM SIZING UTILITIES === */
361 .form-select--compact { width: auto; min-width: 120px; }
362
363 /* === SETTINGS UTILITIES === */
364 .settings-divider { margin-top: 1.5rem; padding-top: 1.5rem; border-top: 2px solid var(--border-color); }
365 .settings-heading { margin-bottom: 1rem; font-family: var(--font-heading); }
366 .settings-desc { font-size: 0.875rem; color: var(--text-secondary); margin-bottom: 1rem; }
367
368 /* === SUBTASK UTILITIES === */
369 /* .subtask-item is the base row; --linked is a modifier for subtasks that
370 reference another task (raised bg + accent border). Use both classes
371 together: <div class="subtask-item subtask-item--linked">. */
372 .subtask-item {
373 display: flex;
374 align-items: center;
375 gap: 0.5rem;
376 padding: 0.5rem;
377 background: var(--bg-secondary);
378 border-radius: 4px;
379 margin-bottom: 0.5rem;
380 }
381 .subtask-item--linked {
382 background: var(--bg-tertiary);
383 border-left: var(--border-width) solid var(--accent-color);
384 }
385 .subtask-checkbox { cursor: pointer; width: 18px; height: 18px; }
386 .subtask-checkbox-disabled { cursor: not-allowed; width: 18px; height: 18px; opacity: 0.5; }
387 .subtask-text-done { text-decoration: line-through; opacity: 0.6; }
388
389 /* ===================================================================
390 5. Body & App Shell
391 =================================================================== */
392 body {
393 font-family: var(--font-sans);
394 background-color: var(--bg-primary);
395 color: var(--text-primary);
396 line-height: 1.6;
397 height: 100vh;
398 overflow: hidden;
399 display: flex;
400 flex-direction: column;
401 }
402
403 /* ===================================================================
404 6. Header (desktop UI only)
405 The top app header is part of desktop layout. Mobile UI hides it
406 wholesale; rules below are scoped so they cannot leak in.
407 =================================================================== */
408 .ui-mode-desktop .app-header {
409 background: var(--bg-card);
410 border-bottom: var(--border-width) solid var(--border-color);
411 padding: 0.75rem 1.5rem;
412 display: flex;
413 justify-content: space-between;
414 align-items: center;
415 }
416
417 .ui-mode-desktop .header-content {
418 display: flex;
419 align-items: center;
420 gap: 0.75rem;
421 }
422
423 .ui-mode-desktop .header-actions {
424 display: flex;
425 align-items: center;
426 gap: 0.5rem;
427 }
428
429 .ui-mode-desktop .app-title {
430 font-family: var(--font-display);
431 font-size: 1.75rem;
432 font-weight: 700;
433 color: var(--text-primary);
434 letter-spacing: -0.02em;
435 }
436
437 .ui-mode-desktop .app-subtitle {
438 font-size: 0.875rem;
439 color: var(--text-muted);
440 font-weight: 500;
441 line-height: 1;
442 }
443
444 .mobile-view-title {
445 display: none;
446 }
447
448 /* ===================================================================
449 7. Tab Navigation (desktop UI only)
450 The top tab strip is desktop-only; mobile UI uses the bottom tab bar.
451 =================================================================== */
452 .ui-mode-desktop .tab-navigation {
453 display: flex;
454 justify-content: center;
455 gap: 0.5rem;
456 }
457
458 .ui-mode-desktop .tab {
459 display: flex;
460 align-items: center;
461 gap: 0.5rem;
462 padding: 0.75rem 1.25rem;
463 text-decoration: none;
464 color: var(--text-primary);
465 background: var(--bg-card);
466 border: var(--border-width) solid var(--border-color);
467 border-radius: var(--radius-md);
468 font-weight: 600;
469 transition: background-color 0.15s ease;
470 }
471
472 .ui-mode-desktop .tab:hover {
473 background: var(--bg-secondary);
474 }
475
476 .ui-mode-desktop .tab.active {
477 background-color: var(--accent-blue);
478 color: var(--text-on-accent);
479 }
480
481 .ui-mode-desktop .tab-icon {
482 font-size: 1.1rem;
483 }
484
485 .ui-mode-desktop .tab-label {
486 font-weight: 600;
487 font-size: 0.9rem;
488 }
489
490 .ui-mode-desktop .tab.tab-right {
491 margin-left: auto;
492 }
493
494 /* --- Tab Groups & Sub-Views (shared) --- */
495 .tab-group .subview.hidden {
496 display: none;
497 }
498
499 /* --- Pill Sub-Navigation (desktop UI only — mobile uses slide menu) --- */
500 .ui-mode-desktop .pill-nav {
501 display: flex;
502 align-items: center;
503 gap: var(--space-1);
504 padding: 0;
505 margin-bottom: 1rem;
506 min-height: 2rem;
507 }
508
509 .ui-mode-desktop .pill {
510 padding: var(--space-1) var(--space-3);
511 border-radius: var(--radius-xl);
512 border: var(--border-width-sm) solid var(--border-color);
513 background: var(--bg-card);
514 font-family: var(--font-sans);
515 font-size: var(--font-size-sm);
516 font-weight: 600;
517 cursor: pointer;
518 transition: background-color var(--transition-fast);
519 }
520
521 .ui-mode-desktop .pill:hover {
522 background: var(--bg-tertiary);
523 }
524
525 .ui-mode-desktop .pill.active {
526 background: var(--text-primary);
527 color: var(--bg-card);
528 border-color: var(--text-primary);
529 }
530
531 /* ===================================================================
532 8. Main Content & Page Header
533 =================================================================== */
534 .main-content {
535 flex: 1;
536 max-width: var(--width-container);
537 width: 100%;
538 margin: 0 auto;
539 padding: 1.5rem 1.75rem 2rem;
540 }
541
542 /* Page Header */
543 .page-header {
544 display: flex;
545 justify-content: space-between;
546 align-items: center;
547 gap: 0.5rem;
548 margin-bottom: 1rem;
549 }
550
551 .page-title {
552 font-family: var(--font-heading);
553 font-size: 1.75rem;
554 font-weight: 700;
555 color: var(--text-primary);
556 }
557
558 /* --- Merged pill + page-header toolbar --- */
559 /* Tab groups use pills as view labels; page-header buttons float right on the same row */
560 .tab-group {
561 position: relative;
562 }
563
564 .tab-group > .subview > .page-header {
565 position: absolute;
566 top: 0;
567 right: 0;
568 margin: 0;
569 z-index: 1;
570 }
571
572 .tab-group .page-header .page-title {
573 display: none;
574 }
575
576 /* Special subviews that need their page-header in normal flow */
577 #project-dashboard-view > .page-header,
578 #day-plan-view > .page-header {
579 position: static;
580 margin-bottom: 1rem;
581 }
582
583 #project-dashboard-view .page-title {
584 display: block;
585 }
586
587 /* ===================================================================
588 9. Buttons
589 =================================================================== */
590 .btn {
591 display: inline-flex;
592 align-items: center;
593 justify-content: center;
594 gap: 0.5rem;
595 padding: 0.625rem 1.25rem;
596 border: var(--border-width) solid var(--border-color);
597 border-radius: var(--radius-sm);
598 font-size: 0.9rem;
599 font-weight: 600;
600 cursor: pointer;
601 transition: background-color 0.15s ease;
602 text-decoration: none;
603 background: var(--bg-card);
604 color: var(--text-primary);
605 }
606
607 .btn:hover {
608 background: var(--bg-secondary);
609 }
610
611 .btn:active {
612 background: var(--bg-tertiary);
613 }
614
615 .btn:disabled {
616 background: var(--bg-tertiary);
617 color: var(--text-muted);
618 cursor: not-allowed;
619 opacity: 0.7;
620 }
621
622 .btn:disabled:hover {
623 background: var(--bg-tertiary);
624 }
625
626 .btn-primary {
627 background-color: var(--accent-blue);
628 color: var(--text-on-accent);
629 }
630
631 .btn-primary:hover {
632 background-color: color-mix(in srgb, var(--accent-blue) 85%, black);
633 }
634
635 .btn-primary:active {
636 background-color: color-mix(in srgb, var(--accent-blue) 70%, black);
637 }
638
639 .btn-secondary {
640 background-color: var(--bg-secondary);
641 color: var(--text-primary);
642 }
643
644 .btn-danger {
645 background-color: var(--accent-red);
646 color: var(--text-on-accent);
647 }
648
649 .btn-danger:hover {
650 background-color: color-mix(in srgb, var(--accent-red) 85%, black);
651 }
652
653 .btn-danger:active {
654 background-color: color-mix(in srgb, var(--accent-red) 70%, black);
655 }
656
657 .btn-sm {
658 padding: 0.375rem 0.75rem;
659 font-size: 0.8rem;
660 }
661
662 /* ===================================================================
663 10. (vacated — Quick Add Input was deleted 2026-05-24; the modal at
664 keyboard.js:openQuickAddModal uses .form-input, not a bespoke
665 primitive. Section number kept for stable navigation.)
666 =================================================================== */
667
668 /* ===================================================================
669 11. Cards
670 =================================================================== */
671 .cards-grid {
672 display: grid;
673 grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
674 gap: 1.25rem;
675 }
676
677 .card {
678 background-color: var(--bg-card);
679 border: var(--border-width) solid var(--border-color);
680 border-radius: var(--radius-md);
681 padding: 1.25rem;
682 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
683 transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
684 cursor: pointer;
685 }
686
687 .card:hover {
688 background-color: var(--bg-secondary);
689 transform: translate(-2px, -2px);
690 box-shadow: calc(var(--shadow-offset) + 2px) calc(var(--shadow-offset) + 2px) 0 var(--border-color);
691 }
692
693 /* Compact card for use in dense vertical lists (e.g. Project Dashboard).
694 Tighter padding, square corners, adds list spacing. */
695 .card--list-item {
696 padding: 0.75rem;
697 border-radius: 0;
698 margin-bottom: 0.5rem;
699 }
700
701 /* Container shell — keeps card chrome (border/radius/shadow) but strips
702 padding/cursor/hover and arranges children as a flex column. For list
703 wrappers like .email-list. */
704 .card--shell {
705 padding: 0;
706 cursor: default;
707 display: flex;
708 flex-direction: column;
709 overflow: hidden;
710 }
711 .card--shell:hover {
712 background-color: var(--bg-card);
713 transform: none;
714 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
715 }
716
717 /* Muted info card — bg-secondary, no border/shadow/cursor/hover. For
718 small read-only info panels (contact info, summary stats). */
719 .card--muted {
720 background: var(--bg-secondary);
721 border: none;
722 box-shadow: none;
723 cursor: default;
724 }
725 .card--muted:hover {
726 background: var(--bg-secondary);
727 transform: none;
728 box-shadow: none;
729 }
730
731 /* Static card — keeps full card chrome (border/shadow/bg) but strips
732 cursor and hover animation. For read-only display cards (review
733 surfaces, monthly summary panels). */
734 .card--static {
735 cursor: default;
736 }
737 .card--static:hover {
738 background-color: var(--bg-card);
739 transform: none;
740 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
741 }
742
743 .card-header {
744 display: flex;
745 justify-content: space-between;
746 align-items: flex-start;
747 margin-bottom: 0.75rem;
748 }
749
750 .card-title {
751 font-family: var(--font-heading);
752 font-size: 1.1rem;
753 font-weight: 700;
754 color: var(--text-primary);
755 }
756
757 .card-description {
758 font-size: 0.9rem;
759 color: var(--text-secondary);
760 margin-bottom: 1rem;
761 }
762
763 .markdown-content {
764 font-size: 0.9rem;
765 color: var(--text-secondary);
766 line-height: 1.5;
767 }
768 .markdown-content p { margin: 0 0 0.5em 0; }
769 .markdown-content p:last-child { margin-bottom: 0; }
770 .markdown-content ul, .markdown-content ol { margin: 0 0 0.5em 1.5em; padding: 0; }
771 .markdown-content code { background: var(--bg-tertiary); padding: 0.1em 0.3em; border-radius: 3px; font-size: 0.85em; }
772 .markdown-content pre { background: var(--bg-tertiary); padding: 0.5em; border-radius: 4px; overflow-x: auto; margin: 0 0 0.5em 0; }
773 .markdown-content pre code { background: none; padding: 0; }
774 .markdown-content a { color: var(--accent-color); }
775 .markdown-content blockquote { border-left: 3px solid var(--border-color); margin: 0 0 0.5em 0; padding-left: 0.75em; color: var(--text-secondary); }
776 .markdown-content h1, .markdown-content h2, .markdown-content h3 { margin: 0.5em 0 0.25em 0; font-size: 1em; font-weight: 600; color: var(--text-primary); }
777 .markdown-content table { border-collapse: collapse; margin: 0.5em 0; }
778 .markdown-content th, .markdown-content td { border: 1px solid var(--border-color); padding: 0.25em 0.5em; }
779 .markdown-content img { max-width: 100%; }
780
781 .card-meta {
782 display: flex;
783 gap: 0.5rem;
784 flex-wrap: wrap;
785 }
786
787 /* ===================================================================
788 12. Tags & Badges
789 =================================================================== */
790
791 .tag, .badge {
792 display: inline-flex;
793 align-items: center;
794 padding: 0.25rem 0.625rem;
795 border: var(--border-width-sm) solid var(--border-color);
796 border-radius: var(--radius-sm);
797 font-size: 0.8125rem;
798 font-weight: 600;
799 background: var(--bg-card);
800 color: var(--text-primary);
801 }
802
803 /* Color variants using data attributes */
804 .badge[data-color="green"], .tag[data-color="green"] {
805 background-color: color-mix(in srgb, var(--accent-green) 20%, var(--bg-card));
806 border-color: var(--accent-green);
807 }
808 .badge[data-color="yellow"], .tag[data-color="yellow"] {
809 background-color: color-mix(in srgb, var(--accent-yellow) 20%, var(--bg-card));
810 border-color: var(--accent-yellow);
811 }
812 .badge[data-color="red"], .tag[data-color="red"] {
813 background-color: color-mix(in srgb, var(--accent-red) 20%, var(--bg-card));
814 border-color: var(--accent-red);
815 }
816 .badge[data-color="cyan"], .tag[data-color="cyan"] {
817 background-color: color-mix(in srgb, var(--accent-cyan) 20%, var(--bg-card));
818 border-color: var(--accent-cyan);
819 }
820 .badge[data-color="purple"], .tag[data-color="purple"] {
821 background-color: color-mix(in srgb, var(--accent-purple) 20%, var(--bg-card));
822 border-color: var(--accent-purple);
823 }
824 .badge[data-color="muted"], .tag[data-color="muted"] {
825 background-color: var(--bg-tertiary);
826 border-color: var(--text-muted);
827 }
828 .badge[data-color="blue"], .tag[data-color="blue"] {
829 background-color: color-mix(in srgb, var(--accent-blue) 20%, var(--bg-card));
830 border-color: var(--accent-blue);
831 }
832
833 /* Size modifiers */
834 .badge--xs { padding: 0.1rem 0.5rem; font-size: 0.75rem; }
835 .badge--sm { padding: 0.15rem 0.55rem; font-size: 0.78rem; }
836
837 /* Filled intent — solid accent fill, no border. Pairs with data-color. */
838 .badge--filled { border: none; }
839 .badge--filled[data-color="green"] { background: var(--accent-green); color: var(--text-on-accent); }
840 .badge--filled[data-color="yellow"] { background: var(--accent-yellow); color: var(--text-primary); }
841 .badge--filled[data-color="red"] { background: var(--accent-red); color: var(--text-on-accent); }
842 .badge--filled[data-color="cyan"] { background: var(--accent-cyan); color: var(--text-on-accent); }
843 .badge--filled[data-color="purple"] { background: var(--accent-purple); color: var(--text-on-accent); }
844 .badge--filled[data-color="blue"] { background: var(--accent-blue); color: var(--text-on-accent); }
845 .badge--filled[data-color="muted"] { background: var(--bg-secondary); color: var(--text-primary); }
846
847 /* Global keyboard-hint badge — small bordered mono pill used inline next
848 to labels ("Search ⌘K"). Relocated from §41 Settings 2026-05-24. */
849 .kbd-hint {
850 display: inline-block;
851 font-family: var(--font-mono, monospace);
852 font-size: 0.65rem;
853 font-weight: 600;
854 padding: 0.1rem 0.35rem;
855 margin-left: 0.35rem;
856 border: 1px solid currentColor;
857 border-radius: 3px;
858 opacity: 0.6;
859 vertical-align: middle;
860 line-height: 1;
861 }
862
863 /* Project status tag colors */
864 .tag.status-active {
865 background-color: color-mix(in srgb, var(--accent-green) 20%, var(--bg-card));
866 border-color: var(--accent-green);
867 }
868 .tag.status-onhold, .tag.status-on_hold {
869 background-color: color-mix(in srgb, var(--accent-yellow) 20%, var(--bg-card));
870 border-color: var(--accent-yellow);
871 }
872 .tag.status-archived {
873 background-color: var(--bg-tertiary);
874 border-color: var(--text-muted);
875 }
876 .tag.status-inactive {
877 background-color: color-mix(in srgb, var(--accent-red) 20%, var(--bg-card));
878 border-color: var(--accent-red);
879 }
880 .tag.status-completed {
881 background-color: color-mix(in srgb, var(--accent-cyan) 20%, var(--bg-card));
882 border-color: var(--accent-cyan);
883 }
884
885 /* ===================================================================
886 13. Data Table
887 =================================================================== */
888 .data-table {
889 width: 100%;
890 border-collapse: separate;
891 border-spacing: 0;
892 background-color: var(--bg-card);
893 border: var(--border-width) solid var(--border-color);
894 border-radius: var(--radius-md);
895 overflow: hidden;
896 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
897 }
898
899 .data-table th,
900 .data-table td {
901 padding: 1rem 1.25rem;
902 text-align: left;
903 border-bottom: 2px solid var(--border-color);
904 }
905
906 .data-table th {
907 background-color: var(--bg-secondary);
908 font-size: 0.8rem;
909 font-weight: 700;
910 text-transform: uppercase;
911 letter-spacing: 0.08em;
912 color: var(--text-primary);
913 }
914
915 .data-table tbody tr {
916 transition: background-color 0.15s ease;
917 }
918
919 .data-table tbody tr:hover {
920 background-color: var(--bg-secondary);
921 }
922
923 .data-table tbody tr:last-child td {
924 border-bottom: none;
925 }
926
927 .data-table tbody tr.selected,
928 .data-table tbody tr.keyboard-selected {
929 background-color: color-mix(in srgb, var(--accent-blue) 25%, var(--bg-card));
930 }
931
932 /* ===================================================================
933 14. Task Table & Rows
934 =================================================================== */
935 .task-table {
936 width: 100%;
937 background: var(--bg-card);
938 border: var(--border-width) solid var(--border-color);
939 border-radius: var(--radius-lg);
940 overflow: hidden;
941 display: flex;
942 flex-direction: column;
943 flex: 1;
944 min-height: 0;
945 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
946 }
947
948 /* Task Grid Column Widths */
949 .task-header-row,
950 .task-row {
951 display: grid;
952 grid-template-columns: 1fr 140px 60px 110px 90px 100px 90px;
953 align-items: center;
954 gap: 0.75rem;
955 }
956
957 /* Task Header Row */
958 .task-header-row {
959 background-color: var(--bg-secondary);
960 border-bottom: 2px solid var(--border-color);
961 padding: 0 1.25rem;
962 }
963
964 .task-header-row .task-cell {
965 padding: 0.75rem 0;
966 font-size: 0.8rem;
967 font-weight: 700;
968 text-transform: uppercase;
969 letter-spacing: 0.05em;
970 color: var(--text-primary);
971 }
972
973 /* Task List Container - Virtual Scrolling */
974 .task-list-container {
975 flex: 1;
976 min-height: 0;
977 overflow-y: auto;
978 position: relative;
979 }
980
981 /* Task Row */
982 .task-row {
983 padding: 0.75rem 1.25rem;
984 border-bottom: 1px solid var(--border-color);
985 transition: background-color 0.15s ease, opacity 0.25s ease, transform 0.25s ease;
986 cursor: pointer;
987 }
988
989 .task-row-removing {
990 opacity: 0;
991 transform: translateX(20px);
992 }
993
994 .task-row:hover {
995 background-color: var(--bg-secondary);
996 }
997
998 .task-row:last-child {
999 border-bottom: none;
1000 }
1001
1002 .task-row.selected,
1003 .task-row.keyboard-selected {
1004 background-color: color-mix(in srgb, var(--accent-blue) 25%, var(--bg-card));
1005 }
1006
1007 /* Task Cell Base */
1008 .task-cell {
1009 overflow: hidden;
1010 text-overflow: ellipsis;
1011 white-space: nowrap;
1012 min-width: 0; /* Allow grid items to shrink below content size */
1013 }
1014
1015 /* Task Actions Header */
1016 .task-actions-header {
1017 text-align: right;
1018 }
1019
1020 /* Event Table - extends .data-table */
1021 .event-table tbody tr {
1022 cursor: pointer;
1023 }
1024
1025 .task-description {
1026 font-weight: 600;
1027 /* Allow description to wrap and show badges on same line */
1028 white-space: normal;
1029 display: flex;
1030 flex-wrap: wrap;
1031 align-items: center;
1032 gap: 0.25rem 0.5rem;
1033 }
1034
1035 .task-description-text {
1036 /* Description text can truncate if very long */
1037 overflow: hidden;
1038 text-overflow: ellipsis;
1039 white-space: nowrap;
1040 max-width: 100%;
1041 }
1042
1043 .task-project {
1044 font-size: 0.85rem;
1045 color: var(--text-secondary);
1046 white-space: nowrap;
1047 }
1048
1049 /* Priority badges - centered in column */
1050 .priority-high,
1051 .priority-medium,
1052 .priority-low {
1053 display: inline-block;
1054 padding: 0.25rem 0.5rem;
1055 border-radius: var(--radius-xs);
1056 font-weight: 700;
1057 text-align: center;
1058 }
1059
1060 .priority-high {
1061 color: var(--accent-red);
1062 background: #fde8ea;
1063 background: color-mix(in srgb, var(--accent-red) 15%, var(--bg-card));
1064 }
1065
1066 .priority-medium {
1067 color: var(--accent-yellow);
1068 background: #fef8e6;
1069 background: color-mix(in srgb, var(--accent-yellow) 15%, var(--bg-card));
1070 }
1071
1072 .priority-low {
1073 color: var(--text-muted);
1074 background: var(--bg-secondary);
1075 }
1076
1077 /* Sortable column headers */
1078 .sortable {
1079 cursor: pointer;
1080 user-select: none;
1081 white-space: nowrap;
1082 }
1083
1084 .sortable:hover {
1085 background: var(--bg-hover);
1086 }
1087
1088 .sort-arrow {
1089 display: inline-block;
1090 width: 0.8em;
1091 margin-left: 0.25rem;
1092 opacity: 0.3;
1093 }
1094
1095 .sort-arrow::after {
1096 content: '\2195'; /* Up-down arrow */
1097 }
1098
1099 .sortable.sort-asc .sort-arrow::after {
1100 content: '\2191'; /* Up arrow */
1101 }
1102
1103 .sortable.sort-desc .sort-arrow::after {
1104 content: '\2193'; /* Down arrow */
1105 }
1106
1107 .sortable.sort-asc .sort-arrow,
1108 .sortable.sort-desc .sort-arrow {
1109 opacity: 1;
1110 }
1111
1112 /* Overdue task highlighting */
1113 .task-overdue .task-description-text {
1114 color: var(--accent-red);
1115 }
1116
1117 .task-overdue .task-due {
1118 color: var(--accent-red);
1119 font-weight: 600;
1120 }
1121
1122 .task-tags {
1123 display: flex;
1124 gap: 0.25rem;
1125 flex-wrap: wrap;
1126 }
1127
1128 .task-tag {
1129 background-color: var(--bg-tertiary);
1130 color: var(--text-primary);
1131 padding: 0.125rem 0.5rem;
1132 border-radius: var(--radius-xs);
1133 font-size: 0.75rem;
1134 font-weight: 600;
1135 border: 1px solid var(--border-color);
1136 }
1137
1138 .recurrence-icon {
1139 color: var(--accent-purple);
1140 font-size: 0.85rem;
1141 font-weight: 700;
1142 }
1143
1144 .annotation-badge {
1145 background-color: var(--accent-yellow);
1146 color: var(--text-primary);
1147 padding: 0.125rem 0.5rem;
1148 border-radius: var(--radius-xs);
1149 font-size: 0.7rem;
1150 font-weight: 700;
1151 border: var(--border-width-sm) solid var(--border-color);
1152 }
1153
1154 .subtask-badge {
1155 background-color: var(--bg-secondary);
1156 color: var(--text-primary);
1157 padding: 0.125rem 0.5rem;
1158 border-radius: var(--radius-xs);
1159 font-size: 0.7rem;
1160 font-weight: 700;
1161 border: var(--border-width-sm) solid var(--border-color);
1162 margin-left: 0.25rem;
1163 }
1164
1165 .task-pending { }
1166 .task-started {
1167 border-left: 4px solid var(--accent-green);
1168 }
1169 .task-completed {
1170 opacity: 0.5;
1171 text-decoration: line-through;
1172 }
1173 .task-deleted { display: none; }
1174
1175 /* ===================================================================
1176 15. Due Date Badges
1177 =================================================================== */
1178 .due-overdue {
1179 color: var(--accent-red);
1180 font-weight: 700;
1181 background: #fde8ea; /* Fallback for browsers without color-mix() */
1182 background: color-mix(in srgb, var(--accent-red) 15%, var(--bg-card));
1183 padding: 0.25rem 0.5rem;
1184 border-radius: var(--radius-xs);
1185 }
1186 .due-today {
1187 color: var(--accent-yellow);
1188 font-weight: 700;
1189 background: #fef8e6; /* Fallback for browsers without color-mix() */
1190 background: color-mix(in srgb, var(--accent-yellow) 15%, var(--bg-card));
1191 padding: 0.25rem 0.5rem;
1192 border-radius: var(--radius-xs);
1193 }
1194 .due-soon { color: var(--text-secondary); }
1195 .due-future { color: var(--text-muted); }
1196
1197 /* ===================================================================
1198 16. Events
1199 =================================================================== */
1200 .events-list {
1201 display: flex;
1202 flex-direction: column;
1203 flex: 1;
1204 min-height: 0;
1205 gap: 1rem;
1206 }
1207
1208 /* Event Table - CSS Grid based for virtual scrolling */
1209 .event-table-virtual {
1210 width: 100%;
1211 background: var(--bg-card);
1212 border: var(--border-width) solid var(--border-color);
1213 border-radius: var(--radius-lg);
1214 overflow: hidden;
1215 display: flex;
1216 flex-direction: column;
1217 flex: 1;
1218 min-height: 0;
1219 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
1220 }
1221
1222 /* Event Grid Column Widths */
1223 .event-header-row,
1224 .event-row-virtual {
1225 display: grid;
1226 grid-template-columns: 100px 80px 1fr 150px 40px;
1227 align-items: center;
1228 gap: 0.5rem;
1229 }
1230
1231 /* Event Header Row */
1232 .event-header-row {
1233 background-color: var(--bg-secondary);
1234 border-bottom: 2px solid var(--border-color);
1235 flex-shrink: 0;
1236 }
1237
1238 .event-header-row .event-cell {
1239 padding: 1rem 1.25rem;
1240 font-size: 0.8rem;
1241 font-weight: 700;
1242 text-transform: uppercase;
1243 letter-spacing: 0.05em;
1244 color: var(--text-primary);
1245 }
1246
1247 /* Event List Container - Virtual Scrolling */
1248 .event-list-container {
1249 flex: 1;
1250 min-height: 0;
1251 overflow-y: auto;
1252 position: relative;
1253 }
1254
1255 /* Event Row */
1256 .event-row-virtual {
1257 padding: 0.75rem 1.25rem;
1258 border-bottom: 1px solid var(--border-color);
1259 transition: background-color 0.15s ease;
1260 cursor: pointer;
1261 }
1262
1263 .event-row-virtual:hover {
1264 background-color: var(--bg-secondary);
1265 }
1266
1267 .event-row-virtual:last-child {
1268 border-bottom: none;
1269 }
1270
1271 .event-row-virtual.event-past {
1272 opacity: 0.7;
1273 }
1274
1275 /* Event Cell Base */
1276 .event-cell {
1277 overflow: hidden;
1278 text-overflow: ellipsis;
1279 }
1280
1281 /* Event Table row styles - base in .data-table */
1282 .event-row {
1283 cursor: pointer;
1284 }
1285
1286 .event-cell-date {
1287 white-space: nowrap;
1288 }
1289
1290 .event-cell-date .event-date-num {
1291 font-weight: 700;
1292 font-size: 0.9rem;
1293 color: var(--text-primary);
1294 margin-right: 0.5rem;
1295 }
1296
1297 .event-date-badge {
1298 display: inline-block;
1299 padding: 0.15rem 0.4rem;
1300 background: var(--accent-green);
1301 color: var(--text-on-accent);
1302 font-size: 0.7rem;
1303 font-weight: 700;
1304 text-transform: uppercase;
1305 border-radius: var(--radius-xs);
1306 margin-right: 0.5rem;
1307 }
1308
1309
1310 .event-cell-time {
1311 font-family: var(--font-mono);
1312 font-size: 0.85rem;
1313 color: var(--text-secondary);
1314 }
1315
1316 .event-cell-title {
1317 font-weight: 600;
1318 }
1319
1320 .event-cell-location {
1321 color: var(--text-secondary);
1322 font-size: 0.875rem;
1323 }
1324
1325 /* Event proximity-based badge colors */
1326 .event-date-badge.event-proximity-today {
1327 background: var(--accent-green);
1328 }
1329 .event-date-badge.event-proximity-tomorrow {
1330 background: var(--accent-yellow);
1331 color: var(--text-primary); /* Yellow needs dark text */
1332 }
1333 .event-date-badge.event-proximity-week {
1334 background: var(--accent-cyan);
1335 }
1336 .event-date-badge.event-proximity-future {
1337 background: var(--accent-blue);
1338 }
1339 .event-date-badge.event-proximity-past {
1340 background: var(--text-muted);
1341 }
1342
1343 /* Past events - muted appearance */
1344 .event-row.event-past {
1345 opacity: 0.7;
1346 }
1347
1348 .no-upcoming-events {
1349 text-align: center;
1350 padding: 2rem;
1351 color: var(--text-secondary);
1352 font-style: italic;
1353 }
1354
1355 /* Past Events Collapsible Section */
1356 .past-events-section {
1357 margin-top: 0.5rem;
1358 }
1359
1360 .past-events-toggle {
1361 display: flex;
1362 align-items: center;
1363 gap: 0.75rem;
1364 padding: 0.75rem 1rem;
1365 background: var(--bg-secondary);
1366 border: var(--border-width-sm) solid var(--border-color);
1367 border-radius: var(--radius-sm);
1368 cursor: pointer;
1369 font-weight: 600;
1370 color: var(--text-secondary);
1371 transition: background-color 0.15s ease, color 0.15s ease;
1372 list-style: none;
1373 }
1374
1375 .past-events-toggle::-webkit-details-marker {
1376 display: none;
1377 }
1378
1379 .past-events-toggle::before {
1380 content: '';
1381 font-size: 0.7rem;
1382 transition: transform 0.15s ease;
1383 }
1384
1385 .past-events-section[open] .past-events-toggle::before {
1386 transform: rotate(90deg);
1387 }
1388
1389 .past-events-toggle:hover {
1390 background: var(--bg-tertiary);
1391 color: var(--text-primary);
1392 }
1393
1394 .past-events-label {
1395 flex: 1;
1396 }
1397
1398 .past-events-count {
1399 background: var(--text-muted);
1400 color: var(--text-on-accent);
1401 font-size: 0.75rem;
1402 padding: 0.15rem 0.5rem;
1403 border-radius: var(--radius-sm);
1404 }
1405
1406 .past-events-section .event-table-past {
1407 margin-top: 0.75rem;
1408 opacity: 0.85;
1409 }
1410
1411 /* Past events container has fixed max height */
1412 .past-events-section .event-list-container {
1413 max-height: 300px;
1414 }
1415
1416 /* Recurring section reuses past-events-section styling but stays expanded by default
1417 and isn't dimmed. */
1418 #recurring-events-section .event-table-virtual {
1419 opacity: 1;
1420 margin-top: 0.75rem;
1421 }
1422 #recurring-events-section .event-list-container {
1423 max-height: 320px;
1424 }
1425 .event-row-virtual.event-recurring .event-recurrence-pattern {
1426 font-weight: 600;
1427 color: var(--accent-primary);
1428 }
1429
1430 /* Plain heading above the Upcoming list */
1431 .events-section-heading {
1432 margin: 1rem 0 0.5rem;
1433 font-size: 0.95rem;
1434 font-weight: 700;
1435 color: var(--text-secondary);
1436 text-transform: uppercase;
1437 letter-spacing: 0.05em;
1438 }
1439
1440 /* Legacy event styles kept for compatibility */
1441 .event-item {
1442 display: flex;
1443 gap: 1rem;
1444 padding: 1rem;
1445 background-color: var(--bg-card);
1446 border: var(--border-width) solid var(--border-color);
1447 border-radius: var(--radius-md);
1448 transition: background-color 0.15s ease;
1449 cursor: pointer;
1450 }
1451
1452 .event-item:hover {
1453 background-color: var(--bg-secondary);
1454 }
1455
1456 .event-date {
1457 flex-shrink: 0;
1458 width: 80px;
1459 text-align: center;
1460 padding: 0.75rem;
1461 background-color: var(--accent-green);
1462 border-radius: var(--radius-sm);
1463 color: var(--text-on-accent);
1464 }
1465
1466 .event-date-day {
1467 font-size: 0.7rem;
1468 font-weight: 700;
1469 text-transform: uppercase;
1470 letter-spacing: 0.05em;
1471 }
1472
1473 .event-date-num {
1474 font-size: 1.5rem;
1475 font-weight: 700;
1476 }
1477
1478 .event-content {
1479 flex: 1;
1480 }
1481
1482 .event-title {
1483 font-family: var(--font-heading);
1484 font-weight: 700;
1485 font-size: 1.1rem;
1486 color: var(--text-primary);
1487 margin-bottom: 0.25rem;
1488 }
1489
1490 .event-details {
1491 font-size: 0.875rem;
1492 color: var(--text-secondary);
1493 display: flex;
1494 gap: 1rem;
1495 }
1496
1497 .event-time, .event-location {
1498 display: flex;
1499 align-items: center;
1500 gap: 0.25rem;
1501 }
1502
1503 .event-project {
1504 margin-top: 0.5rem;
1505 }
1506
1507 /* ===================================================================
1508 17. Email List
1509 =================================================================== */
1510 /* Base chrome from .card.card--shell; only the flex sizing for the
1511 list panel remains here. */
1512 .email-list {
1513 flex: 1;
1514 min-height: 0;
1515 }
1516
1517 /* Email List Container for Virtual Scrolling */
1518 .email-list-container {
1519 flex: 1;
1520 min-height: 0;
1521 overflow-y: auto;
1522 position: relative;
1523 }
1524
1525 .email-item {
1526 display: flex;
1527 gap: 1rem;
1528 padding: 1rem;
1529 border-bottom: 2px solid var(--border-color);
1530 transition: background-color 0.15s ease;
1531 cursor: pointer;
1532 }
1533
1534 .email-item:last-child {
1535 border-bottom: none;
1536 }
1537
1538 .email-item:hover {
1539 background-color: var(--bg-secondary);
1540 }
1541
1542 .email-item.unread {
1543 background-color: color-mix(in srgb, var(--accent-blue) 20%, var(--bg-card));
1544 border-left: 4px solid var(--accent-blue);
1545 }
1546
1547 .email-item.unread .email-subject {
1548 font-weight: 700;
1549 }
1550
1551 .email-item.unread .email-from {
1552 font-weight: 700;
1553 }
1554
1555 .email-item.outgoing {
1556 border-left: 4px solid var(--accent-green);
1557 }
1558
1559 .email-checkbox {
1560 flex-shrink: 0;
1561 margin-top: 0.25rem;
1562 }
1563
1564 .email-content {
1565 flex: 1;
1566 min-width: 0;
1567 }
1568
1569 .email-header {
1570 display: flex;
1571 justify-content: space-between;
1572 margin-bottom: 0.25rem;
1573 align-items: center;
1574 gap: 0.5rem;
1575 }
1576
1577 /* Standalone — does not compose .badge. Smaller font, no border, centered
1578 min-width for thread counts. Audited 2026-05-21: composing .badge here
1579 would require overriding every declaration; net-zero dedup. */
1580 .thread-badge {
1581 background-color: var(--bg-tertiary);
1582 color: var(--text-secondary);
1583 font-size: 0.7rem;
1584 font-weight: 600;
1585 padding: 0.1rem 0.4rem;
1586 border-radius: var(--radius-md);
1587 min-width: 1.25rem;
1588 text-align: center;
1589 }
1590
1591 .email-from {
1592 color: var(--text-primary);
1593 font-size: 0.9rem;
1594 font-weight: 600;
1595 }
1596
1597 .email-date {
1598 color: var(--text-muted);
1599 font-size: 0.8rem;
1600 flex-shrink: 0;
1601 font-weight: 600;
1602 }
1603
1604 .email-subject {
1605 color: var(--text-primary);
1606 font-size: 0.95rem;
1607 margin-bottom: 0.25rem;
1608 white-space: nowrap;
1609 overflow: hidden;
1610 text-overflow: ellipsis;
1611 }
1612
1613 .email-preview {
1614 color: var(--text-muted);
1615 font-size: 0.85rem;
1616 white-space: nowrap;
1617 overflow: hidden;
1618 text-overflow: ellipsis;
1619 }
1620
1621 /* ===================================================================
1622 18. Toast Notifications
1623 =================================================================== */
1624 @keyframes toastSlideIn {
1625 from {
1626 opacity: 0;
1627 transform: translateY(20px);
1628 }
1629 to {
1630 opacity: 1;
1631 transform: translateY(0);
1632 }
1633 }
1634
1635 .toast {
1636 position: fixed;
1637 bottom: var(--space-5);
1638 right: var(--space-5);
1639 padding: var(--space-3) var(--space-5);
1640 background: var(--bg-card);
1641 color: var(--text-primary);
1642 border: var(--border-width) solid var(--border-color);
1643 border-radius: var(--radius-md);
1644 box-shadow: var(--shadow-brutal-md);
1645 z-index: 2000;
1646 font-weight: 600;
1647 display: flex;
1648 align-items: center;
1649 gap: var(--space-3);
1650 animation: toastSlideIn 0.3s ease;
1651 }
1652
1653 .toast.toast-leaving {
1654 opacity: 0;
1655 transform: translateY(10px);
1656 transition: opacity 0.3s ease, transform 0.3s ease;
1657 }
1658
1659 .toast-info {
1660 background: var(--bg-card);
1661 color: var(--text-primary);
1662 }
1663
1664 .toast-success {
1665 background: var(--accent-green);
1666 color: var(--text-on-accent);
1667 }
1668
1669 .toast-error {
1670 background: var(--accent-red);
1671 color: var(--text-on-accent);
1672 }
1673
1674 .toast-action {
1675 background: none;
1676 border: 1px solid currentColor;
1677 border-radius: var(--radius-sm);
1678 color: inherit;
1679 cursor: pointer;
1680 padding: 0.15rem 0.5rem;
1681 font-size: var(--font-size-sm);
1682 font-weight: 600;
1683 font-family: inherit;
1684 }
1685
1686 /* Undo Toast */
1687 .toast-undo {
1688 z-index: 10000;
1689 }
1690
1691 .undo-message {
1692 flex: 1;
1693 }
1694
1695 .undo-countdown {
1696 font-size: var(--font-size-sm);
1697 color: var(--text-muted);
1698 min-width: 2.5rem;
1699 text-align: right;
1700 }
1701
1702 /* ===================================================================
1703 19. Modals
1704 =================================================================== */
1705 @keyframes modalFadeIn {
1706 from {
1707 opacity: 0;
1708 }
1709 to {
1710 opacity: 1;
1711 }
1712 }
1713
1714 @keyframes modalSlideIn {
1715 from {
1716 opacity: 0;
1717 transform: translateY(-20px) scale(0.95);
1718 }
1719 to {
1720 opacity: 1;
1721 transform: translateY(0) scale(1);
1722 }
1723 }
1724
1725 @keyframes modalFadeOut {
1726 from {
1727 opacity: 1;
1728 }
1729 to {
1730 opacity: 0;
1731 }
1732 }
1733
1734 @keyframes modalSlideOut {
1735 from {
1736 opacity: 1;
1737 transform: translateY(0) scale(1);
1738 }
1739 to {
1740 opacity: 0;
1741 transform: translateY(-20px) scale(0.95);
1742 }
1743 }
1744
1745 .modal-overlay {
1746 position: fixed;
1747 top: 0;
1748 left: 0;
1749 right: 0;
1750 bottom: 0;
1751 background-color: var(--overlay-color);
1752 display: flex;
1753 align-items: center;
1754 justify-content: center;
1755 z-index: 1000;
1756 animation: modalFadeIn 0.15s ease-out;
1757 }
1758
1759 .modal-overlay.hidden {
1760 display: none;
1761 }
1762
1763 .modal-overlay.closing {
1764 animation: modalFadeOut 0.15s ease-in forwards;
1765 }
1766
1767 .modal-container {
1768 background-color: var(--bg-card);
1769 border: var(--border-width) solid var(--border-color);
1770 border-radius: var(--radius-lg);
1771 box-shadow: var(--shadow-brutal-xl);
1772 max-width: var(--width-modal);
1773 width: 90%;
1774 /* dvh follows the visible viewport when mobile chrome / keyboard
1775 expand-collapse; subtract safe-area so the modal can't extend behind
1776 the iOS home indicator or notch even when the mobile branch below
1777 doesn't apply (e.g. iPad landscape > 768px). */
1778 max-height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 2rem);
1779 overflow: auto;
1780 animation: modalSlideIn 0.2s ease-out;
1781 }
1782
1783 .modal-container.modal-large {
1784 max-width: calc(100vw - 4rem);
1785 width: calc(100vw - 4rem);
1786 max-height: calc(100vh - 4rem);
1787 height: calc(100vh - 4rem);
1788 display: flex;
1789 flex-direction: column;
1790 }
1791
1792 .modal-container.modal-large .modal-content {
1793 flex: 1;
1794 overflow: auto;
1795 display: flex;
1796 flex-direction: column;
1797 }
1798
1799 .modal-overlay.closing .modal-container {
1800 animation: modalSlideOut 0.15s ease-in forwards;
1801 }
1802
1803 .modal-header {
1804 display: flex;
1805 justify-content: space-between;
1806 align-items: center;
1807 padding: 1rem 1.5rem;
1808 border-bottom: var(--border-width) solid var(--border-color);
1809 background: var(--bg-secondary);
1810 }
1811
1812 .modal-header h2, .modal-title {
1813 font-family: var(--font-heading);
1814 font-size: 1.25rem;
1815 font-weight: 700;
1816 }
1817
1818 .modal-close {
1819 background: var(--bg-card);
1820 border: var(--border-width-sm) solid var(--border-color);
1821 border-radius: var(--radius-sm);
1822 font-size: 1.25rem;
1823 color: var(--text-primary);
1824 cursor: pointer;
1825 line-height: 1;
1826 width: 36px;
1827 height: 36px;
1828 display: flex;
1829 align-items: center;
1830 justify-content: center;
1831 transition: background-color 0.15s ease;
1832 }
1833
1834 .modal-close:hover {
1835 background: var(--accent-blue);
1836 color: var(--text-on-accent);
1837 }
1838
1839 .modal-content {
1840 padding: 1.5rem;
1841 }
1842
1843 /* Pin a form's action row to the bottom of the modal's scroll area so
1844 primary/cancel buttons stay visible even on short viewports. Without
1845 this, on small windows or iOS with the keyboard up the button row sits
1846 below the fold and looks cut off — there's no visible scrollbar on
1847 macOS by default so users don't realize they can scroll to it. */
1848 .modal-content > .form-actions:last-child,
1849 .modal-content form > .form-actions:last-child {
1850 position: sticky;
1851 bottom: 0;
1852 margin-top: 1.5rem;
1853 padding-top: 0.75rem;
1854 padding-bottom: 0.25rem;
1855 background: var(--bg-card);
1856 border-top: var(--border-width-sm) solid var(--border-color);
1857 z-index: 1;
1858 }
1859
1860 /* ===================================================================
1861 20. Form Elements
1862 =================================================================== */
1863 .form-group {
1864 margin-bottom: 1.25rem;
1865 }
1866
1867 .form-more-toggle {
1868 display: block;
1869 background: none;
1870 border: none;
1871 cursor: pointer;
1872 font-size: 0.85rem;
1873 font-weight: 600;
1874 color: var(--accent-blue);
1875 padding: 0.25rem 0;
1876 margin-bottom: 0.75rem;
1877 }
1878
1879 .form-more-toggle::before {
1880 content: '+ ';
1881 }
1882
1883 .form-more-toggle.expanded::before {
1884 content: '- ';
1885 }
1886
1887 .form-extended-fields.hidden {
1888 display: none;
1889 }
1890
1891 .recurrence-weekday-label {
1892 display: inline-flex;
1893 align-items: center;
1894 gap: 0.25rem;
1895 padding: 0.25rem 0.5rem;
1896 font-size: 0.8rem;
1897 border: 1px solid var(--border);
1898 border-radius: var(--radius-sm);
1899 cursor: pointer;
1900 }
1901
1902 .recurrence-weekday-label:has(input:checked) {
1903 background: var(--accent-primary);
1904 color: var(--bg-primary);
1905 border-color: var(--accent-primary);
1906 }
1907
1908 .recurrence-weekday-label input[type="checkbox"] {
1909 display: none;
1910 }
1911
1912 .recurrence-config .form-input,
1913 .recurrence-config .form-select {
1914 font-size: 0.85rem;
1915 padding: 0.25rem 0.5rem;
1916 }
1917
1918 .form-label {
1919 display: block;
1920 font-size: 0.9rem;
1921 font-weight: 700;
1922 color: var(--text-primary);
1923 margin-bottom: 0.5rem;
1924 }
1925
1926 .form-input,
1927 .form-select,
1928 .form-textarea {
1929 width: 100%;
1930 padding: 0.75rem 1rem;
1931 border: var(--border-width-sm) solid var(--border-color);
1932 border-radius: var(--radius-sm);
1933 background-color: var(--bg-card);
1934 color: var(--text-primary);
1935 font-size: 1rem;
1936 box-shadow: none;
1937 }
1938
1939 .form-input:focus,
1940 .form-select:focus,
1941 .form-textarea:focus {
1942 outline: none;
1943 background-color: var(--bg-card);
1944 box-shadow: 0 0 0 2px var(--accent-blue);
1945 }
1946
1947 .form-textarea {
1948 min-height: 100px;
1949 resize: vertical;
1950 }
1951
1952 /* Ghost variants — borderless / transparent inputs used in toolbar
1953 contexts (compose header rows). Strips chrome and reduces padding. */
1954 .form-input--ghost {
1955 background: transparent;
1956 border: none;
1957 padding: 0.5rem;
1958 font-size: 0.875rem;
1959 }
1960 .form-input--ghost:focus { background: transparent; box-shadow: none; }
1961 .form-select--ghost {
1962 background: var(--bg-primary);
1963 padding: 0.5rem;
1964 font-size: 0.875rem;
1965 }
1966
1967 .form-actions {
1968 display: flex;
1969 justify-content: flex-end;
1970 gap: 0.75rem;
1971 margin-top: 1.5rem;
1972 }
1973
1974 /* Form Validation */
1975 .form-input[aria-invalid="true"],
1976 .form-select[aria-invalid="true"],
1977 .form-textarea[aria-invalid="true"] {
1978 border-color: var(--accent-red);
1979 box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-red) 30%, transparent);
1980 }
1981
1982 .form-input[aria-invalid="true"]:focus,
1983 .form-select[aria-invalid="true"]:focus,
1984 .form-textarea[aria-invalid="true"]:focus {
1985 box-shadow: 0 0 0 2px var(--accent-red);
1986 }
1987
1988 .form-error {
1989 color: var(--accent-red);
1990 font-size: 0.8rem;
1991 font-weight: 600;
1992 margin-top: 0.25rem;
1993 display: none;
1994 }
1995
1996 .form-error.visible {
1997 display: block;
1998 }
1999
2000 .form-hint {
2001 font-size: var(--font-size-sm);
2002 color: var(--text-secondary);
2003 margin-top: var(--space-1);
2004 }
2005
2006 .form-hint--preview {
2007 color: var(--accent-primary);
2008 }
2009
2010 .form-checkbox-label {
2011 display: flex;
2012 align-items: center;
2013 gap: var(--space-2);
2014 cursor: pointer;
2015 }
2016
2017 .empty-state-action {
2018 margin-top: var(--space-3);
2019 }
2020
2021 /* ===================================================================
2022 Layout utility classes (used by JS-rendered markup)
2023 =================================================================== */
2024 .stack {
2025 display: flex;
2026 flex-direction: column;
2027 }
2028 .stack-2 { gap: var(--space-2); }
2029 .stack-3 { gap: var(--space-3); }
2030 .stack-4 { gap: var(--space-4); }
2031
2032 .row-flex {
2033 display: flex;
2034 align-items: center;
2035 }
2036 .row-flex-2 { gap: var(--space-2); }
2037 .row-flex-3 { gap: var(--space-3); }
2038 .row-flex-4 { gap: var(--space-4); }
2039
2040 .text-center { text-align: center; }
2041 .text-left { text-align: left; }
2042 .w-full { width: 100%; }
2043 .text-muted { color: var(--text-muted); }
2044 .text-secondary { color: var(--text-secondary); }
2045 .text-danger { color: var(--accent-red); }
2046 .text-sm { font-size: var(--font-size-sm); }
2047 .text-xs { font-size: var(--font-size-xs, 0.75rem); }
2048
2049 .section-divider {
2050 border-top: var(--border-width-sm) solid var(--border-color);
2051 padding-top: var(--space-4);
2052 margin-top: var(--space-4);
2053 }
2054
2055 /* Sync dashboard primitives */
2056 .sync-status-row {
2057 display: flex;
2058 align-items: center;
2059 gap: var(--space-3);
2060 margin-bottom: var(--space-5);
2061 }
2062 .sync-status-dot {
2063 width: 10px;
2064 height: 10px;
2065 border-radius: var(--radius-full);
2066 background: var(--accent-green);
2067 display: inline-block;
2068 }
2069 .sync-stats-grid {
2070 display: grid;
2071 grid-template-columns: 1fr 1fr;
2072 gap: var(--space-4);
2073 margin-bottom: var(--space-5);
2074 }
2075 .sync-stat {
2076 padding: var(--space-3);
2077 background: var(--bg-secondary);
2078 border-radius: var(--radius-md);
2079 }
2080 .sync-stat-label {
2081 font-size: var(--font-size-sm);
2082 color: var(--text-muted);
2083 margin-bottom: var(--space-1);
2084 }
2085 .sync-stat-value {
2086 font-size: var(--font-size-md, 0.9rem);
2087 }
2088 .sync-encryption-error {
2089 color: var(--accent-red);
2090 font-size: var(--font-size-sm);
2091 margin-top: var(--space-2);
2092 display: none;
2093 }
2094 .sync-encryption-error.visible {
2095 display: block;
2096 }
2097 .sync-section-actions {
2098 margin-bottom: var(--space-5);
2099 }
2100 .sync-banner {
2101 padding: var(--space-3);
2102 background: var(--bg-secondary);
2103 border-radius: var(--radius-md);
2104 margin-bottom: var(--space-4);
2105 font-size: var(--font-size-sm);
2106 color: var(--text-secondary);
2107 }
2108 .sync-banner--warning {
2109 background: var(--bg-secondary);
2110 border: 1px solid var(--border-color);
2111 padding: var(--space-4);
2112 }
2113 .sync-empty {
2114 padding: var(--space-5) 0;
2115 }
2116 .sync-empty-message {
2117 margin-bottom: var(--space-5);
2118 }
2119 .sync-hint {
2120 margin-bottom: var(--space-4);
2121 }
2122 .sync-status-label {
2123 font-weight: 500;
2124 }
2125 .sync-account-row {
2126 display: flex;
2127 align-items: baseline;
2128 gap: var(--space-3);
2129 margin-bottom: var(--space-5);
2130 font-size: var(--font-size-sm);
2131 }
2132 .sync-account-label {
2133 color: var(--text-muted);
2134 }
2135 .sync-account-value {
2136 color: var(--text-primary);
2137 }
2138 .sync-account-username {
2139 color: var(--text-muted);
2140 }
2141 .sync-banner-title {
2142 font-weight: 500;
2143 margin: 0 0 var(--space-3) 0;
2144 }
2145 .sync-banner-body {
2146 margin: 0 0 var(--space-2) 0;
2147 font-size: var(--font-size-sm);
2148 color: var(--text-secondary);
2149 }
2150 .sync-banner-tier-line {
2151 margin: 0 0 var(--space-4) 0;
2152 font-size: var(--font-size-sm);
2153 color: var(--text-secondary);
2154 }
2155 .sync-banner-actions {
2156 display: flex;
2157 gap: var(--space-2);
2158 align-items: center;
2159 }
2160
2161 /* Backup / data settings primitives */
2162 .settings-subheading {
2163 margin-bottom: var(--space-3);
2164 font-size: var(--font-size-md, 0.9rem);
2165 }
2166 .settings-desc-block {
2167 font-size: var(--font-size-sm);
2168 color: var(--text-secondary);
2169 margin-bottom: var(--space-4);
2170 }
2171 .settings-actions-row {
2172 display: flex;
2173 flex-wrap: wrap;
2174 gap: var(--space-3);
2175 margin-bottom: var(--space-4);
2176 }
2177 .settings-actions-row--center {
2178 align-items: center;
2179 flex-wrap: nowrap;
2180 margin-top: var(--space-3);
2181 }
2182 .settings-status-text {
2183 font-size: var(--font-size-sm);
2184 color: var(--text-secondary);
2185 }
2186 .settings-section-block {
2187 padding-top: var(--space-4);
2188 border-top: var(--border-width-sm) solid var(--border-color);
2189 }
2190 .form-hint--spaced {
2191 margin-top: var(--space-2);
2192 }
2193 .empty-italic {
2194 color: var(--text-secondary);
2195 font-style: italic;
2196 }
2197
2198 .form-grid-2 {
2199 display: grid;
2200 grid-template-columns: 1fr 1fr;
2201 gap: var(--space-4);
2202 }
2203
2204 /* Email account list / detail primitives */
2205 .email-detect-status {
2206 font-size: var(--font-size-sm);
2207 color: var(--text-secondary);
2208 margin-top: var(--space-1);
2209 }
2210 .email-detect-note {
2211 font-size: var(--font-size-sm);
2212 margin-top: var(--space-2);
2213 padding: var(--space-3) var(--space-3);
2214 background: var(--bg-tertiary);
2215 border-left: 3px solid var(--accent-primary);
2216 border-radius: var(--radius-sm);
2217 line-height: var(--line-height-normal);
2218 }
2219 .account-row {
2220 padding: var(--space-3);
2221 background: var(--bg-secondary);
2222 border-radius: var(--radius-sm);
2223 margin-bottom: var(--space-2);
2224 }
2225 .account-row-header {
2226 display: flex;
2227 justify-content: space-between;
2228 align-items: flex-start;
2229 }
2230 .account-row-name {
2231 font-weight: 600;
2232 }
2233 .account-row-meta {
2234 font-size: var(--font-size-sm);
2235 color: var(--text-secondary);
2236 }
2237 .account-row-sync {
2238 font-size: var(--font-size-sm);
2239 color: var(--text-secondary);
2240 }
2241 .account-row-provider-badge {
2242 font-size: var(--font-size-xs, 0.7rem);
2243 padding: 0.125rem 0.375rem;
2244 background: var(--accent-blue);
2245 color: var(--text-on-accent);
2246 border-radius: var(--radius-xs);
2247 margin-left: var(--space-2);
2248 }
2249 .test-conn-result {
2250 padding: var(--space-2);
2251 background: var(--bg-secondary);
2252 border-radius: var(--radius-sm);
2253 margin-bottom: var(--space-2);
2254 }
2255 .test-conn-result--success { color: var(--accent-green); }
2256 .test-conn-result--error { color: var(--accent-red); }
2257
2258 .folder-list {
2259 max-height: 150px;
2260 overflow-y: auto;
2261 background: var(--bg-secondary);
2262 padding: var(--space-2);
2263 border-radius: var(--radius-sm);
2264 font-family: var(--font-mono);
2265 font-size: var(--font-size-sm);
2266 }
2267 .folder-list-meta {
2268 font-size: var(--font-size-sm);
2269 color: var(--text-secondary);
2270 margin-top: var(--space-2);
2271 }
2272 .error-pre {
2273 background: var(--bg-secondary);
2274 padding: var(--space-2);
2275 border-radius: var(--radius-sm);
2276 font-family: var(--font-mono);
2277 font-size: var(--font-size-sm);
2278 white-space: pre-wrap;
2279 max-height: 150px;
2280 overflow-y: auto;
2281 }
2282 .test-conn-section {
2283 border-top: var(--border-width-sm) solid var(--border-color);
2284 margin: var(--space-4) 0;
2285 padding-top: var(--space-4);
2286 }
2287 .oauth-waiting {
2288 text-align: center;
2289 padding: var(--space-5);
2290 }
2291 .oauth-waiting-title {
2292 font-size: var(--font-size-lg, 1.25rem);
2293 margin-bottom: var(--space-4);
2294 }
2295 .oauth-waiting-body {
2296 color: var(--text-secondary);
2297 margin-bottom: var(--space-5);
2298 }
2299 .oauth-waiting-spinner {
2300 margin: 0 auto var(--space-5);
2301 }
2302
2303 .contact-card-header { gap: var(--space-3); }
2304 .contact-card-body { flex: 1; min-width: 0; }
2305 .contact-detail-header {
2306 display: flex;
2307 align-items: center;
2308 gap: var(--space-4);
2309 margin-bottom: var(--space-5);
2310 }
2311 .contact-detail-name { margin: 0; }
2312 .contact-detail-tags { margin-bottom: var(--space-4); }
2313
2314 .form-actions--spaced { margin-top: var(--space-5); }
2315
2316 .milestones-empty {
2317 color: var(--text-muted);
2318 font-size: var(--font-size-sm);
2319 margin-bottom: var(--space-4);
2320 }
2321
2322 .bulk-modal-prompt {
2323 color: var(--text-secondary);
2324 margin-bottom: var(--space-2);
2325 }
2326 .bulk-modal-prompt--wide {
2327 margin-bottom: var(--space-3);
2328 }
2329 /* Marker class kept for .ui-mode-mobile padding override only. Base styling: .btn.btn-sm + .w-full.text-left. */
2330 .bulk-modal-scroll {
2331 max-height: 300px;
2332 overflow-y: auto;
2333 display: flex;
2334 flex-direction: column;
2335 gap: var(--space-1);
2336 }
2337 .bulk-priority-row {
2338 display: flex;
2339 gap: var(--space-2);
2340 }
2341
2342 .snooze-hint {
2343 font-size: var(--font-size-sm);
2344 color: var(--text-secondary);
2345 margin: 0 0 var(--space-3) 0;
2346 }
2347
2348 .time-tracking-empty {
2349 color: var(--text-secondary);
2350 padding: var(--space-4) 0;
2351 }
2352
2353 .backups-empty {
2354 color: var(--text-secondary);
2355 font-style: italic;
2356 }
2357 .backup-item {
2358 display: flex;
2359 align-items: center;
2360 justify-content: space-between;
2361 padding: var(--space-3);
2362 border: 1px solid var(--border-color);
2363 border-radius: var(--radius-md);
2364 margin-bottom: var(--space-2);
2365 }
2366 .backup-item-meta {
2367 font-size: var(--font-size-sm);
2368 color: var(--text-secondary);
2369 }
2370 .export-desc {
2371 font-size: var(--font-size-sm);
2372 color: var(--text-secondary);
2373 margin-bottom: var(--space-5);
2374 }
2375 .export-note {
2376 margin-top: var(--space-4);
2377 padding: var(--space-3);
2378 background: var(--bg-secondary);
2379 border-radius: var(--radius-sm);
2380 }
2381 .export-note-text {
2382 font-size: var(--font-size-sm);
2383 color: var(--text-secondary);
2384 margin: 0;
2385 }
2386
2387 .paint-time-preview {
2388 font-weight: 600;
2389 color: var(--accent-primary);
2390 margin-bottom: var(--space-2);
2391 }
2392
2393 .recurrence-config {
2394 display: none;
2395 margin-top: var(--space-2);
2396 padding: var(--space-2);
2397 border: 1px solid var(--border-color);
2398 border-radius: var(--radius-sm);
2399 }
2400 .recurrence-config:not(.hidden) {
2401 display: block;
2402 }
2403 .recurrence-preview {
2404 font-size: var(--font-size-sm);
2405 color: var(--accent-primary);
2406 font-weight: 600;
2407 margin-bottom: var(--space-2);
2408 }
2409 .recurrence-sublabel {
2410 font-size: var(--font-size-xs, 0.75rem);
2411 }
2412 .recurrence-unit {
2413 font-size: var(--font-size-sm);
2414 }
2415 .recurrence-day-label {
2416 display: flex;
2417 align-items: center;
2418 gap: var(--space-2);
2419 font-size: var(--font-size-sm);
2420 }
2421 .recurrence-nth-toggle {
2422 font-size: var(--font-size-sm);
2423 margin: var(--space-1) 0;
2424 }
2425 .recurrence-row { margin-bottom: var(--space-2); }
2426 .recurrence-row.recurrence-hidden { display: none; }
2427 .recurrence-interval-row {
2428 display: flex;
2429 align-items: center;
2430 gap: var(--space-2);
2431 }
2432 .recurrence-num { width: 4rem; }
2433 .recurrence-weekdays {
2434 display: flex;
2435 gap: var(--space-1);
2436 flex-wrap: wrap;
2437 }
2438 .recurrence-monthly {
2439 margin-bottom: 0;
2440 }
2441 .recurrence-monthly.recurrence-hidden { display: none; }
2442 .recurrence-monthly-stack {
2443 display: flex;
2444 flex-direction: column;
2445 gap: var(--space-2);
2446 }
2447 .recurrence-monthly-week { width: auto; }
2448
2449 .confirm-message-wrap { margin-bottom: var(--space-5); }
2450 .confirm-message {
2451 color: var(--text-secondary);
2452 line-height: var(--line-height-normal);
2453 }
2454 .review-intro {
2455 color: var(--text-secondary);
2456 font-size: var(--font-size-sm);
2457 margin: 0 0 var(--space-4);
2458 }
2459 .review-intro--weekly {
2460 margin: var(--space-2) 0 var(--space-4);
2461 }
2462 .no-events-day {
2463 color: var(--text-secondary);
2464 }
2465 .loading--error { color: var(--accent-red); }
2466 .project-dashboard-desc {
2467 color: var(--text-secondary);
2468 margin-bottom: var(--space-4);
2469 }
2470
2471 /* Pending-key hint (top-level "go to" prompt) */
2472 .pending-key-hint {
2473 position: fixed;
2474 bottom: var(--space-5);
2475 left: 50%;
2476 transform: translateX(-50%);
2477 padding: var(--space-2) var(--space-4);
2478 background: var(--bg-card);
2479 color: var(--text-primary);
2480 border: var(--border-width) solid var(--border-color);
2481 border-radius: var(--radius-md);
2482 box-shadow: var(--shadow-brutal-md);
2483 z-index: 10000;
2484 font-size: var(--font-size-sm);
2485 white-space: nowrap;
2486 animation: toastSlideIn 0.15s ease;
2487 }
2488 .pending-key-hint-label { opacity: 0.7; }
2489 .pending-key-hint kbd {
2490 background: var(--bg-secondary);
2491 border: 1px solid var(--border-color);
2492 border-radius: var(--radius-xs);
2493 padding: 0.125rem 0.4rem;
2494 font-family: inherit;
2495 font-size: var(--font-size-sm);
2496 }
2497
2498 /* Keyboard shortcuts overlay */
2499 .shortcuts-overlay {
2500 position: fixed;
2501 top: 0; left: 0; right: 0; bottom: 0;
2502 background: var(--overlay-color);
2503 display: flex;
2504 align-items: center;
2505 justify-content: center;
2506 z-index: 3000;
2507 }
2508 .shortcuts-overlay-panel {
2509 background: var(--bg-card);
2510 border-radius: var(--radius-md);
2511 padding: var(--space-5);
2512 max-width: 600px;
2513 max-height: 80vh;
2514 overflow-y: auto;
2515 }
2516 .shortcuts-title {
2517 margin-top: 0;
2518 margin-bottom: var(--space-4);
2519 border-bottom: 1px solid var(--border-color);
2520 padding-bottom: var(--space-2);
2521 }
2522 .shortcuts-grid {
2523 display: grid;
2524 grid-template-columns: 1fr 1fr;
2525 gap: var(--space-5);
2526 }
2527 .shortcuts-group-heading {
2528 color: var(--text-secondary);
2529 font-size: var(--font-size-sm);
2530 margin-bottom: var(--space-2);
2531 }
2532 .shortcuts-group-heading + .shortcut-row {
2533 margin-top: 0;
2534 }
2535 .shortcuts-group-heading-spaced {
2536 color: var(--text-secondary);
2537 font-size: var(--font-size-sm);
2538 margin-bottom: var(--space-2);
2539 margin-top: var(--space-3);
2540 }
2541 .shortcuts-close {
2542 margin-top: var(--space-5);
2543 text-align: center;
2544 }
2545 .shortcut-row {
2546 display: flex;
2547 align-items: center;
2548 gap: var(--space-2);
2549 margin-bottom: var(--space-2);
2550 }
2551 .shortcut-row kbd {
2552 background: var(--bg-secondary);
2553 border: 1px solid var(--border-color);
2554 border-radius: var(--radius-xs);
2555 padding: 0.25rem 0.5rem;
2556 font-family: inherit;
2557 font-size: var(--font-size-sm);
2558 min-width: 1.5rem;
2559 text-align: center;
2560 }
2561 .shortcut-row span {
2562 color: var(--text-secondary);
2563 font-size: var(--font-size-sm);
2564 margin-left: auto;
2565 }
2566
2567 .quick-add-syntax {
2568 font-size: var(--font-size-sm);
2569 color: var(--text-secondary);
2570 margin-top: var(--space-2);
2571 line-height: var(--line-height-relaxed);
2572 }
2573 .quick-add-syntax > span { margin-right: var(--space-3); }
2574 .quick-add-syntax kbd {
2575 font-size: 0.7rem;
2576 padding: 0.1rem 0.3rem;
2577 border: 1px solid var(--border-color);
2578 border-radius: var(--radius-xs);
2579 background: var(--bg-secondary);
2580 }
2581
2582 .virtual-scroller-wrapper {
2583 position: relative;
2584 width: 100%;
2585 }
2586 .virtual-scroller-spacer {
2587 height: 0;
2588 width: 100%;
2589 }
2590
2591 /* Generic helpers used by JS-rendered markup */
2592 .meta-text {
2593 font-size: var(--font-size-sm);
2594 color: var(--text-muted);
2595 }
2596 .meta-text--secondary {
2597 color: var(--text-secondary);
2598 }
2599 .subtasks-empty {
2600 color: var(--text-secondary);
2601 text-align: center;
2602 padding: var(--space-4);
2603 }
2604 .subtask-linked-tag {
2605 color: var(--accent-color);
2606 font-size: var(--font-size-sm);
2607 }
2608 .task-actions-bar {
2609 display: flex;
2610 flex-wrap: wrap;
2611 gap: var(--space-2);
2612 margin-top: var(--space-4);
2613 padding-top: var(--space-3);
2614 border-top: 1px solid var(--border-color);
2615 }
2616 .loading--error { color: var(--accent-red); }
2617 .error-state--padded {
2618 padding: var(--space-4);
2619 }
2620 .event-cell--shrink {
2621 flex: 0 0 auto;
2622 padding-right: 0;
2623 }
2624 .empty-state-content {
2625 /* empty-state already has padding/center; this is a placeholder if more nesting needed */
2626 }
2627
2628 .hr-soft {
2629 border: none;
2630 border-top: 1px solid var(--border-color);
2631 margin: var(--space-2) 0;
2632 }
2633
2634 .card-badge--success {
2635 background: var(--accent-green);
2636 color: var(--text-on-accent);
2637 }
2638 .card-badge--warning { background: var(--accent-yellow); }
2639 .card-badge--info {
2640 background: var(--accent-blue);
2641 color: var(--text-on-accent);
2642 }
2643 .card-badge--danger {
2644 background: var(--accent-red);
2645 color: var(--text-on-accent);
2646 }
2647 .card-badge--neutral { background: var(--bg-secondary); }
2648
2649 .empty-italic--muted {
2650 color: var(--text-muted);
2651 font-style: italic;
2652 }
2653
2654 .review-history-block {
2655 margin-top: var(--space-5);
2656 padding-top: var(--space-4);
2657 border-top: 1px dashed var(--border-color);
2658 }
2659 .review-history-heading {
2660 font-size: var(--font-size-sm);
2661 color: var(--text-muted);
2662 margin-bottom: var(--space-3);
2663 }
2664
2665 /* Email detail / list primitives */
2666 .email-attachment-row {
2667 display: flex;
2668 align-items: center;
2669 gap: var(--space-2);
2670 padding: 0.375rem 0;
2671 }
2672 .email-attachment-size {
2673 font-size: var(--font-size-sm);
2674 color: var(--text-muted);
2675 flex-shrink: 0;
2676 }
2677 .email-attachments-block {
2678 margin-bottom: var(--space-3);
2679 padding: var(--space-2) var(--space-3);
2680 background: var(--bg-secondary);
2681 border-radius: var(--radius-sm);
2682 border: 1px solid var(--border-color);
2683 }
2684 .email-attachments-heading {
2685 font-size: var(--font-size-sm);
2686 font-weight: 600;
2687 color: var(--text-secondary);
2688 margin-bottom: var(--space-1);
2689 }
2690 .email-thread-count {
2691 color: var(--text-muted);
2692 font-size: var(--font-size-sm);
2693 }
2694 .email-subject-line {
2695 font-weight: 600;
2696 font-size: 1.1rem;
2697 }
2698 .email-meta-line {
2699 font-size: var(--font-size-sm);
2700 color: var(--text-secondary);
2701 margin-top: var(--space-1);
2702 }
2703 .email-snoozed-tag { color: var(--accent-yellow); }
2704 .email-actions-bar {
2705 border-top: 1px solid var(--border-color);
2706 padding-top: var(--space-4);
2707 margin-top: auto;
2708 }
2709 .email-attachment-tag {
2710 margin-right: var(--space-2);
2711 }
2712 .email-draft-item {
2713 cursor: pointer;
2714 padding: var(--space-3);
2715 }
2716 .email-draft-meta {
2717 font-size: var(--font-size-sm);
2718 color: var(--text-secondary);
2719 }
2720 .label-existing-line {
2721 font-size: var(--font-size-sm);
2722 color: var(--text-secondary);
2723 margin-top: var(--space-1);
2724 }
2725 .search-no-results {
2726 padding: var(--space-5);
2727 text-align: center;
2728 color: var(--text-secondary);
2729 }
2730 .email-attachment-name {
2731 flex: 1;
2732 min-width: 0;
2733 }
2734 .email-draft-subject { font-weight: 500; }
2735
2736 /* Compose form fields — shared between the desktop compose.html window
2737 and the in-app modal (Phase 7 Tier 6 #3 stage 3). The composeForm.buildFieldsHtml
2738 helper emits markup using these classes; both surfaces render the same
2739 HTML so spacing/typography stays unified. Window-only chrome
2740 (.compose-toolbar, .status-bar, .save-contact-bar, .reply-indicator)
2741 still lives in compose.html since it has no modal analogue yet.
2742
2743 NOTE on naming: .header-row / .header-label refer to the compose
2744 form's "header fields" (To, Cc, Subject), NOT the app header. Don't
2745 rename without grepping composeForm.buildFieldsHtml. The input/select
2746 inside each row use .form-input--ghost / .form-select--ghost. */
2747 .header-row {
2748 display: flex;
2749 align-items: center;
2750 padding: 0.75rem 1rem;
2751 border-bottom: 1px solid var(--border-color);
2752 gap: 0.5rem;
2753 }
2754 .header-row--tight {
2755 padding: 0.25rem 1rem;
2756 }
2757 .header-label {
2758 width: 80px;
2759 color: var(--text-secondary);
2760 font-size: 0.875rem;
2761 flex-shrink: 0;
2762 }
2763 .autocomplete-wrapper {
2764 position: relative;
2765 flex: 1;
2766 background: transparent;
2767 border-radius: var(--radius-sm);
2768 }
2769 .autocomplete-wrapper:focus-within {
2770 background: var(--bg-secondary);
2771 }
2772 .body-container {
2773 flex: 1;
2774 display: flex;
2775 flex-direction: column;
2776 overflow: hidden;
2777 }
2778 .body-textarea {
2779 flex: 1;
2780 min-height: 12rem;
2781 background: var(--bg-card);
2782 border: none;
2783 color: var(--text-primary);
2784 font-size: 0.9375rem;
2785 font-family: inherit;
2786 padding: 1rem;
2787 resize: vertical;
2788 outline: none;
2789 line-height: 1.6;
2790 }
2791 .body-textarea::placeholder { color: var(--text-muted); }
2792 /* Reply indicator — shared between compose.html's toolbar (where it
2793 benefits from align-self:center inside a flex row) and the in-app
2794 compose modal (where it's just an inline label above the form). */
2795 .reply-indicator {
2796 display: none;
2797 color: var(--text-secondary);
2798 font-size: 0.8125rem;
2799 align-self: center;
2800 }
2801
2802 /* Attachment list — rendered into #attachments-bar by composeForm. */
2803 .compose-attachments {
2804 padding: 0.5rem 1rem;
2805 border-top: 1px solid var(--border-color);
2806 background: var(--bg-secondary);
2807 font-size: 0.8125rem;
2808 }
2809 /* Compose with `row-flex row-flex-2` for the row. */
2810 .compose-attachment-item {
2811 padding: 0.25rem 0;
2812 }
2813 .compose-attachment-name {
2814 flex: 1;
2815 overflow: hidden;
2816 text-overflow: ellipsis;
2817 white-space: nowrap;
2818 }
2819 .compose-attachment-size {
2820 color: var(--text-muted);
2821 flex-shrink: 0;
2822 }
2823 .compose-attachment-remove {
2824 background: none;
2825 border: none;
2826 color: var(--accent-red);
2827 cursor: pointer;
2828 font-size: 1rem;
2829 padding: 0 0.25rem;
2830 }
2831 .compose-attachment-total {
2832 display: flex;
2833 gap: var(--space-2);
2834 align-items: baseline;
2835 padding-top: var(--space-2);
2836 margin-top: var(--space-1);
2837 font-size: var(--font-size-sm);
2838 color: var(--text-muted);
2839 border-top: 1px dashed var(--border-color);
2840 }
2841 .compose-attachment-total.over-warn { color: var(--accent-yellow); }
2842 .compose-attachment-total.over-cap { color: var(--accent-red); }
2843 .compose-attachment-warn { font-style: italic; }
2844
2845 /* About section (Settings → About) */
2846 .about-info-list {
2847 display: grid;
2848 grid-template-columns: max-content 1fr;
2849 column-gap: var(--space-4);
2850 row-gap: var(--space-2);
2851 margin: var(--space-4) 0;
2852 font-size: var(--font-size-sm);
2853 }
2854 .about-info-list dt {
2855 font-weight: 600;
2856 color: var(--text-secondary);
2857 }
2858 .about-info-list dd {
2859 margin: 0;
2860 font-family: var(--font-mono);
2861 }
2862 .about-updater-note {
2863 margin-top: var(--space-4);
2864 }
2865
2866 /* Filter-bar result count (Phase 7 Tier 2 #9) */
2867 .filter-count {
2868 font-size: var(--font-size-sm);
2869 color: var(--text-muted);
2870 margin-right: var(--space-2);
2871 white-space: nowrap;
2872 }
2873 .filter-count--capped {
2874 color: var(--accent-yellow);
2875 font-weight: 600;
2876 }
2877
2878 /* Hide the List / Board toggle in mobile UI. Kanban drag-drop has no touch
2879 fallback (Phase 6 #1) — showing the toggle would expose a broken feature.
2880 Keyed off UI mode rather than `hover: none` so a desktop touch laptop
2881 with a working mouse still gets the toggle. Re-enable when touch-drag lands. */
2882 .ui-mode-mobile #task-view-toggle { display: none; }
2883
2884 /* Phase 7 Tier 3 #11 — swipe peek-labels.
2885 Injected into a row on touch start, removed on touch end. Show the action
2886 that will fire when the user releases past threshold. */
2887 .swipe-peek {
2888 position: absolute;
2889 top: 0;
2890 bottom: 0;
2891 display: flex;
2892 align-items: center;
2893 padding: 0 var(--space-3);
2894 font-size: var(--font-size-sm);
2895 font-weight: 600;
2896 color: var(--text-on-accent);
2897 pointer-events: none;
2898 opacity: 0;
2899 transition: opacity 0.1s linear;
2900 z-index: 0;
2901 }
2902 /* Right-swipe reveals what was hidden to the LEFT of the row */
2903 .swipe-peek--right {
2904 left: 0;
2905 background: var(--accent-blue);
2906 justify-content: flex-start;
2907 }
2908 .swipe-peek--left {
2909 right: 0;
2910 background: var(--accent-blue);
2911 justify-content: flex-end;
2912 }
2913 .swipe-peek--success { background: var(--accent-green); }
2914 .swipe-peek--warn { background: var(--accent-yellow); color: var(--text-primary); }
2915 .swipe-peek--danger { background: var(--accent-red); }
2916 .swipe-peek--ready {
2917 /* Stronger visual cue at the action threshold */
2918 box-shadow: inset 0 0 0 2px var(--text-on-accent);
2919 }
2920 /* Ensure rows with peek labels behave as containing block + clip content */
2921 .task-row,
2922 .email-item,
2923 .event-row-virtual {
2924 position: relative;
2925 overflow: hidden;
2926 }
2927
2928 .attachment-item {
2929 display: flex;
2930 align-items: center;
2931 gap: var(--space-3);
2932 padding: var(--space-2) 0;
2933 border-bottom: 1px solid var(--border-color);
2934 }
2935 .attachment-icon { font-size: 1.2rem; }
2936 .attachment-meta {
2937 font-size: var(--font-size-sm);
2938 color: var(--text-muted);
2939 }
2940 .attachment-sync-warning {
2941 font-size: var(--font-size-sm);
2942 color: var(--text-muted);
2943 }
2944 .attachment-info { flex: 1; min-width: 0; }
2945 .attachment-filename {
2946 font-weight: 500;
2947 overflow: hidden;
2948 text-overflow: ellipsis;
2949 white-space: nowrap;
2950 }
2951 .attachment-actions {
2952 display: flex;
2953 gap: var(--space-1);
2954 }
2955 .attachment-attach-row { margin-top: var(--space-4); }
2956
2957 .link-task-item {
2958 display: flex;
2959 align-items: center;
2960 gap: var(--space-2);
2961 padding: var(--space-2);
2962 background: var(--bg-secondary);
2963 border-radius: var(--radius-sm);
2964 margin-bottom: var(--space-2);
2965 cursor: pointer;
2966 }
2967 .link-task-item:hover { background: var(--bg-tertiary); }
2968 .link-task-project {
2969 font-size: var(--font-size-sm);
2970 color: var(--text-secondary);
2971 }
2972 .link-task-prompt {
2973 color: var(--text-secondary);
2974 margin-bottom: var(--space-4);
2975 }
2976 .link-task-desc { flex: 1; }
2977 .link-task-list {
2978 max-height: 400px;
2979 overflow-y: auto;
2980 }
2981 .form-actions--top-spaced { margin-top: var(--space-4); }
2982
2983 /* About + Welcome modals */
2984 .about-panel {
2985 text-align: center;
2986 padding: var(--space-4);
2987 }
2988 .about-title {
2989 font-family: var(--font-display);
2990 margin-bottom: var(--space-4);
2991 }
2992 .about-tagline {
2993 color: var(--text-secondary);
2994 margin-bottom: var(--space-2);
2995 }
2996 .about-version {
2997 color: var(--text-muted);
2998 font-size: var(--font-size-sm);
2999 }
3000
3001 .welcome-panel { line-height: var(--line-height-relaxed); }
3002 .welcome-intro {
3003 color: var(--text-secondary);
3004 margin-bottom: var(--space-4);
3005 }
3006 .welcome-section { margin-bottom: var(--space-4); }
3007 .welcome-subhead {
3008 font-size: var(--font-size-md, 0.9rem);
3009 margin-bottom: var(--space-2);
3010 }
3011 .welcome-subhead--tight { margin-bottom: var(--space-1); }
3012 .welcome-step-stack {
3013 display: flex;
3014 flex-direction: column;
3015 gap: var(--space-2);
3016 }
3017 .welcome-tabs-list {
3018 color: var(--text-secondary);
3019 font-size: var(--font-size-sm);
3020 padding-left: var(--space-4);
3021 margin: 0;
3022 }
3023
3024 .review-more-line {
3025 color: var(--text-muted);
3026 font-size: var(--font-size-sm);
3027 margin-top: var(--space-2);
3028 }
3029
3030 .modal-attachments {
3031 font-size: var(--font-size-sm);
3032 margin-top: var(--space-1);
3033 }
3034
3035 .account-row-info {
3036 flex: 1;
3037 }
3038 .account-row-actions {
3039 display: flex;
3040 align-items: center;
3041 gap: var(--space-2);
3042 margin-bottom: var(--space-2);
3043 }
3044 .account-row-quick {
3045 display: flex;
3046 gap: var(--space-2);
3047 }
3048 .account-row-quick .btn {
3049 flex: 1;
3050 }
3051 .account-list {
3052 margin-bottom: var(--space-4);
3053 max-height: 400px;
3054 overflow-y: auto;
3055 }
3056 .form-actions-spacer { flex: 1; }
3057 .oauth-block {
3058 margin-bottom: var(--space-5);
3059 }
3060 .oauth-block-title {
3061 font-weight: 500;
3062 margin-bottom: var(--space-3);
3063 }
3064 .oauth-buttons {
3065 display: flex;
3066 flex-wrap: wrap;
3067 gap: var(--space-2);
3068 }
3069 .oauth-buttons .btn {
3070 flex: 1;
3071 min-width: 120px;
3072 }
3073 .oauth-helptext {
3074 font-size: var(--font-size-sm);
3075 color: var(--text-secondary);
3076 margin-top: var(--space-2);
3077 }
3078 .imap-block-divider {
3079 border-top: var(--border-width-sm) solid var(--border-color);
3080 margin: var(--space-4) 0;
3081 padding-top: var(--space-4);
3082 }
3083 .imap-block-title {
3084 font-weight: 500;
3085 margin-bottom: var(--space-3);
3086 }
3087 .test-conn-results {
3088 margin-bottom: var(--space-4);
3089 }
3090 .sync-results {
3091 margin-bottom: var(--space-4);
3092 }
3093 .sync-result-banner {
3094 padding: var(--space-3);
3095 background: var(--bg-secondary);
3096 border-radius: var(--radius-sm);
3097 margin-bottom: var(--space-2);
3098 }
3099 .sync-result-grid {
3100 display: grid;
3101 grid-template-columns: 1fr 1fr;
3102 gap: var(--space-2);
3103 margin-bottom: var(--space-2);
3104 }
3105 .sync-result-tile {
3106 padding: var(--space-2);
3107 background: var(--bg-secondary);
3108 border-radius: var(--radius-sm);
3109 }
3110
3111 /* ===================================================================
3112 21. Footer
3113 =================================================================== */
3114 .app-footer {
3115 background-color: var(--bg-card);
3116 border-top: var(--border-width) solid var(--border-color);
3117 padding: 0.75rem 1.5rem;
3118 }
3119
3120 .footer-content {
3121 max-width: var(--width-container);
3122 margin: 0 auto;
3123 display: flex;
3124 justify-content: space-between;
3125 align-items: center;
3126 }
3127
3128 /* Desktop UI only — keyboard hints aren't meaningful in mobile UI. */
3129 .ui-mode-desktop .keyboard-hints {
3130 display: flex;
3131 gap: 1rem;
3132 font-size: 0.8rem;
3133 color: var(--text-muted);
3134 }
3135
3136 kbd {
3137 display: inline-block;
3138 padding: 0.2rem 0.5rem;
3139 background-color: var(--bg-secondary);
3140 border: var(--border-width-sm) solid var(--border-color);
3141 border-radius: var(--radius-xs);
3142 font-family: var(--font-mono);
3143 font-size: 0.75rem;
3144 font-weight: 700;
3145 }
3146
3147 .welcome-hint {
3148 color: var(--text-secondary);
3149 font-size: var(--font-size-sm);
3150 margin-bottom: var(--space-2);
3151 }
3152
3153 .version {
3154 font-size: 0.75rem;
3155 color: var(--text-muted);
3156 font-weight: 600;
3157 }
3158
3159 /* ===================================================================
3160 22. Empty & Error States
3161 =================================================================== */
3162 .empty-state {
3163 text-align: center;
3164 padding: 3rem;
3165 color: var(--text-secondary);
3166 }
3167
3168 .empty-state--compact {
3169 padding: 2rem 1rem;
3170 font-size: var(--font-size-sm);
3171 }
3172
3173 .empty-state--dashboard {
3174 padding: 2rem 1rem;
3175 }
3176
3177 .empty-state--error {
3178 color: var(--accent-red);
3179 }
3180
3181 .empty-state-icon {
3182 font-size: 4rem;
3183 margin-bottom: 1rem;
3184 }
3185
3186 .empty-state-text {
3187 font-size: 1.1rem;
3188 font-weight: 600;
3189 margin-bottom: 1rem;
3190 }
3191
3192 .error-state {
3193 text-align: center;
3194 padding: 2rem;
3195 color: var(--accent-red);
3196 background: color-mix(in srgb, var(--accent-red) 10%, var(--bg-card));
3197 border: var(--border-width-sm) solid var(--accent-red);
3198 border-radius: var(--radius-sm);
3199 font-weight: 600;
3200 }
3201
3202 /* View states */
3203 .view {
3204 display: block;
3205 }
3206
3207 .view.hidden {
3208 display: none;
3209 }
3210
3211 /* ===================================================================
3212 23. Filter Bar
3213 =================================================================== */
3214 .filter-bar {
3215 display: flex;
3216 flex-wrap: wrap;
3217 gap: 0.75rem;
3218 margin-bottom: 1.5rem;
3219 padding: 1rem;
3220 background-color: var(--bg-card);
3221 border: var(--border-width) solid var(--border-color);
3222 border-radius: var(--radius-md);
3223 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
3224 }
3225
3226 .filter-group {
3227 display: flex;
3228 align-items: center;
3229 gap: 0.5rem;
3230 }
3231
3232 .filter-label {
3233 font-size: 0.8rem;
3234 font-weight: 700;
3235 color: var(--text-secondary);
3236 text-transform: uppercase;
3237 letter-spacing: 0.05em;
3238 }
3239
3240 .filter-select {
3241 padding: 0.5rem 0.75rem;
3242 border: var(--border-width-sm) solid var(--border-color);
3243 border-radius: var(--radius-sm);
3244 background-color: var(--bg-card);
3245 color: var(--text-primary);
3246 font-size: 0.875rem;
3247 font-weight: 600;
3248 }
3249
3250 .filter-select:focus {
3251 outline: none;
3252 background-color: var(--accent-blue);
3253 color: var(--text-on-accent);
3254 }
3255
3256 .filter-checkbox {
3257 display: flex;
3258 align-items: center;
3259 gap: 0.4rem;
3260 font-size: 0.875rem;
3261 font-weight: 600;
3262 color: var(--text-primary);
3263 cursor: pointer;
3264 }
3265
3266 .filter-checkbox input[type="checkbox"] {
3267 width: 1rem;
3268 height: 1rem;
3269 cursor: pointer;
3270 }
3271
3272 .btn-link {
3273 background: none;
3274 border: none;
3275 box-shadow: none;
3276 color: var(--text-secondary);
3277 font-size: 0.875rem;
3278 cursor: pointer;
3279 text-decoration: underline;
3280 padding: 0.5rem;
3281 }
3282
3283 .btn-link:hover {
3284 box-shadow: none;
3285 transform: none;
3286 color: var(--text-primary);
3287 }
3288
3289 /* ===================================================================
3290 24. Responsive - Large Screens & Tablet
3291 =================================================================== */
3292
3293 /* Wide desktop — intra-desktop responsive (only desktop UI gets these). */
3294 @media (min-width: 1400px) {
3295 .ui-mode-desktop .main-content {
3296 max-width: 1600px;
3297 }
3298
3299 .ui-mode-desktop .cards-grid {
3300 grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
3301 }
3302
3303 .ui-mode-desktop .project-dashboard-grid {
3304 gap: 2rem;
3305 }
3306
3307 .ui-mode-desktop .day-plan-sidebar {
3308 width: 320px;
3309 }
3310
3311 .ui-mode-desktop .modal-container {
3312 max-width: 640px;
3313 }
3314 }
3315
3316 /* Tablet — intra-desktop responsive (desktop UI on narrow desktops/iPads).
3317 Scoped to .ui-mode-desktop so it never affects mobile UI. */
3318 @media (max-width: 1024px) {
3319 .ui-mode-desktop .saved-views-sidebar {
3320 width: 180px;
3321 }
3322
3323 .ui-mode-desktop .day-plan-sidebar {
3324 width: 240px;
3325 }
3326
3327 .ui-mode-desktop .project-dashboard-grid {
3328 grid-template-columns: 1fr 1fr;
3329 gap: 1rem;
3330 }
3331
3332 .ui-mode-desktop .project-dashboard-grid .dashboard-column:last-child {
3333 grid-column: span 2;
3334 }
3335
3336 .ui-mode-desktop .filter-bar {
3337 flex-wrap: wrap;
3338 }
3339
3340 .ui-mode-desktop .filter-actions {
3341 width: 100%;
3342 justify-content: flex-end;
3343 margin-top: 0.5rem;
3344 }
3345 }
3346
3347 /* ===================================================================
3348 25. Responsive - Mobile (768px)
3349 =================================================================== */
3350 .ui-mode-mobile .tab-navigation {
3351 flex-wrap: wrap;
3352 gap: 0.5rem;
3353 }
3354
3355 .ui-mode-mobile .tab {
3356 flex: 1 1 auto;
3357 min-width: calc(33% - 0.5rem);
3358 justify-content: center;
3359 padding: 0.625rem 0.75rem;
3360 }
3361
3362 .ui-mode-mobile .tab-label {
3363 display: none;
3364 }
3365
3366 .ui-mode-mobile .tab-icon {
3367 font-size: 1.25rem;
3368 }
3369
3370 .ui-mode-mobile .kbd-hint {
3371 display: none;
3372 }
3373
3374 .ui-mode-mobile .cards-grid {
3375 grid-template-columns: 1fr;
3376 }
3377
3378 .ui-mode-mobile .task-table {
3379 font-size: 0.85rem;
3380 }
3381
3382 /* Hide recurrence, progress, and actions columns on mobile */
3383 .ui-mode-mobile .task-header-row,
3384 .ui-mode-mobile .task-row {
3385 grid-template-columns: 1fr 80px 40px 80px;
3386 }
3387
3388 .ui-mode-mobile .task-header-row .task-cell:nth-child(n+5),
3389 .ui-mode-mobile .task-row .task-cell:nth-child(n+5) {
3390 display: none;
3391 }
3392
3393 .ui-mode-mobile .filter-bar {
3394 flex-direction: column;
3395 }
3396
3397 .ui-mode-mobile .keyboard-hints {
3398 display: none;
3399 }
3400
3401 .ui-mode-mobile .page-title {
3402 font-size: 1.5rem;
3403 }
3404
3405 .ui-mode-mobile .saved-views-sidebar {
3406 display: none;
3407 }
3408
3409 .ui-mode-mobile .day-plan-content {
3410 flex-direction: column;
3411 }
3412
3413 .ui-mode-mobile .day-plan-sidebar {
3414 width: 100%;
3415 max-height: 200px;
3416 }
3417
3418 .ui-mode-mobile .project-dashboard-grid {
3419 grid-template-columns: 1fr;
3420 }
3421
3422 .ui-mode-mobile .project-dashboard-grid .dashboard-column:last-child {
3423 grid-column: span 1;
3424 }
3425
3426 .ui-mode-mobile .modal-container {
3427 width: 95%;
3428 max-height: 95vh;
3429 }
3430
3431 .ui-mode-mobile .bulk-actions-bar {
3432 flex-wrap: wrap;
3433 }
3434
3435 .ui-mode-mobile .bulk-select-all {
3436 width: 100%;
3437 margin-top: 0.5rem;
3438 }
3439
3440
3441 /* ===================================================================
3442 26. Screen Reader & Accessibility
3443 =================================================================== */
3444 .sr-only {
3445 position: absolute;
3446 width: 1px;
3447 height: 1px;
3448 padding: 0;
3449 margin: -1px;
3450 overflow: hidden;
3451 clip: rect(0, 0, 0, 0);
3452 white-space: nowrap;
3453 border: 0;
3454 }
3455
3456 /* ===================================================================
3457 27. Pagination
3458 =================================================================== */
3459 .pagination-controls {
3460 display: flex;
3461 align-items: center;
3462 justify-content: center;
3463 gap: 1rem;
3464 padding: 1rem;
3465 margin-top: 1rem;
3466 background: var(--bg-card);
3467 border: var(--border-width) solid var(--border-color);
3468 border-radius: var(--radius-md);
3469 }
3470
3471 .pagination-info {
3472 font-weight: 600;
3473 color: var(--text-secondary);
3474 font-size: 0.9rem;
3475 }
3476
3477 .pagination-controls .btn:disabled {
3478 opacity: 0.5;
3479 cursor: not-allowed;
3480 }
3481
3482 /* ===================================================================
3483 28. Focus & Keyboard Accessibility
3484 =================================================================== */
3485 .tab:focus-visible,
3486 .btn:focus-visible,
3487 .form-input:focus-visible,
3488 .form-select:focus-visible,
3489 .form-textarea:focus-visible,
3490 .card:focus-visible,
3491 .email-item:focus-visible,
3492 .task-row:focus-visible,
3493 .event-row-virtual:focus-visible,
3494 .saved-view-item:focus-visible,
3495 .filter-select:focus-visible,
3496 .modal-close:focus-visible,
3497 .snooze-option:focus-visible,
3498 .unscheduled-task:focus-visible,
3499 .timeline-item:focus-visible,
3500 .card:focus-visible {
3501 outline: 3px solid var(--accent-blue);
3502 outline-offset: 2px;
3503 }
3504
3505 /* Ensure clickable table rows can receive focus */
3506 .task-row-clickable,
3507 .event-row {
3508 cursor: pointer;
3509 }
3510
3511 /* Skip link for keyboard navigation */
3512 .skip-link {
3513 position: absolute;
3514 top: -100px;
3515 left: 0;
3516 background: var(--accent-blue);
3517 color: var(--text-on-accent);
3518 padding: 0.75rem 1.5rem;
3519 z-index: 9999;
3520 font-weight: 700;
3521 border: var(--border-width) solid var(--border-color);
3522 text-decoration: none;
3523 }
3524
3525 .skip-link:focus {
3526 top: 0;
3527 }
3528
3529 /* ===================================================================
3530 29. Source Email Link
3531 =================================================================== */
3532 .source-email-link {
3533 padding: 0.75rem;
3534 background: var(--bg-secondary);
3535 border-radius: var(--radius-sm);
3536 border-left: 4px solid var(--accent-blue);
3537 }
3538
3539 /* ===================================================================
3540 30. Email Reader Mode
3541 =================================================================== */
3542
3543 /* Thread message container */
3544 .thread-message {
3545 margin-bottom: 1rem;
3546 padding: 0.75rem;
3547 background: var(--bg-secondary);
3548 border-radius: var(--radius-sm);
3549 }
3550
3551 .thread-message-latest {
3552 border-left: 3px solid var(--accent-blue);
3553 }
3554
3555 .thread-message-header {
3556 display: flex;
3557 justify-content: space-between;
3558 margin-bottom: 0.5rem;
3559 font-size: 0.8rem;
3560 color: var(--text-secondary);
3561 }
3562
3563 .thread-message-from {
3564 font-weight: 700;
3565 }
3566
3567 /* Reader mode body styling */
3568 .email-reader-body {
3569 white-space: pre-wrap;
3570 font-size: 0.9rem;
3571 line-height: 1.6;
3572 color: var(--text-primary);
3573 word-wrap: break-word;
3574 overflow-wrap: break-word;
3575 }
3576
3577 /* Links extracted from HTML emails - shown as [url] */
3578 .email-reader-body .email-link {
3579 color: var(--accent-blue);
3580 text-decoration: underline;
3581 cursor: pointer;
3582 word-break: break-all;
3583 }
3584
3585 .email-reader-body .email-link:hover {
3586 color: var(--accent-cyan);
3587 }
3588
3589 /* Bullet points from list items */
3590 .email-reader-body {
3591 /* Ensure bullet points align nicely */
3592 }
3593
3594 /* Horizontal rule separators */
3595 .email-reader-body hr {
3596 border: none;
3597 border-top: 2px solid var(--border-color);
3598 margin: 1rem 0;
3599 }
3600
3601 /* Quote blocks if detected */
3602 .email-reader-quote {
3603 border-left: 3px solid var(--text-muted);
3604 padding-left: 1rem;
3605 margin: 0.5rem 0;
3606 color: var(--text-secondary);
3607 font-style: italic;
3608 }
3609
3610 /* Collapsible quoted text */
3611 .email-quote-toggle {
3612 display: inline-block;
3613 color: var(--text-muted);
3614 font-size: 0.8125rem;
3615 cursor: pointer;
3616 padding: 0.25rem 0;
3617 user-select: none;
3618 }
3619
3620 .email-quote-toggle:hover {
3621 color: var(--accent-blue);
3622 }
3623
3624 .email-quote-block {
3625 border-left: 3px solid var(--text-muted);
3626 padding-left: 1rem;
3627 margin: 0.25rem 0 0.5rem;
3628 color: var(--text-secondary);
3629 }
3630
3631 .email-quote-block.hidden {
3632 display: none;
3633 }
3634
3635 /* Email address autocomplete. Shares bg/border/shadow with .dropdown-menu
3636 but uses a different positioning model (parent-relative, shown by default
3637 with max-height) — kept separate intentionally. */
3638 .autocomplete-dropdown {
3639 background: var(--bg-card);
3640 border: 1px solid var(--border-color);
3641 border-radius: var(--radius-sm);
3642 box-shadow: var(--shadow-brutal);
3643 z-index: 100;
3644 max-height: 200px;
3645 overflow-y: auto;
3646 }
3647
3648 .autocomplete-item {
3649 padding: 0.5rem 0.75rem;
3650 cursor: pointer;
3651 font-size: 0.875rem;
3652 }
3653
3654 .autocomplete-item:hover,
3655 .autocomplete-item.active {
3656 background: var(--bg-secondary);
3657 }
3658
3659 .autocomplete-name {
3660 font-weight: 500;
3661 }
3662
3663 .autocomplete-email {
3664 color: var(--text-secondary);
3665 margin-left: 0.25rem;
3666 }
3667
3668 /* Email reader container for large modal */
3669 .email-reader-container {
3670 display: flex;
3671 flex-direction: column;
3672 height: 100%;
3673 min-height: 0;
3674 }
3675
3676 .email-reader-header {
3677 margin-bottom: 1rem;
3678 padding-bottom: 0.75rem;
3679 border-bottom: 1px solid var(--border-color);
3680 }
3681
3682 /* Email sender contact card. Compose with `row-flex row-flex-2` for the row. */
3683 .email-sender-contact {
3684 margin-top: 0.5rem;
3685 padding: 0.4rem 0.5rem;
3686 background: var(--bg-tertiary);
3687 border-radius: 4px;
3688 }
3689
3690 .email-sender-info {
3691 display: flex;
3692 flex-direction: column;
3693 flex: 1;
3694 min-width: 0;
3695 }
3696
3697 .email-sender-name {
3698 font-weight: 600;
3699 font-size: 0.85rem;
3700 }
3701
3702 .email-sender-company {
3703 font-size: 0.75rem;
3704 color: var(--text-secondary);
3705 }
3706
3707 .email-reader-thread {
3708 flex: 1;
3709 overflow-y: auto;
3710 margin-bottom: 1rem;
3711 min-height: 0;
3712 }
3713
3714 /* ===================================================================
3715 31. Dropdown Menus
3716 =================================================================== */
3717 .dropdown {
3718 position: relative;
3719 display: inline-block;
3720 }
3721
3722 .dropdown-menu {
3723 display: none;
3724 position: absolute;
3725 bottom: 100%;
3726 left: 0;
3727 margin-bottom: 0.25rem;
3728 background: var(--bg-card);
3729 border: var(--border-width) solid var(--border-color);
3730 border-radius: var(--radius-md);
3731 box-shadow: var(--shadow-brutal-md);
3732 min-width: 160px;
3733 z-index: 100;
3734 }
3735
3736 .dropdown-menu.show {
3737 display: block;
3738 }
3739
3740 .dropdown-item {
3741 display: block;
3742 width: 100%;
3743 padding: 0.5rem 1rem;
3744 text-align: left;
3745 background: none;
3746 border: none;
3747 cursor: pointer;
3748 font-size: 0.875rem;
3749 color: var(--text-primary);
3750 }
3751
3752 .dropdown-item:hover {
3753 background: var(--bg-secondary);
3754 }
3755
3756 .dropdown-item:first-child {
3757 border-radius: var(--radius-md) var(--radius-md) 0 0;
3758 }
3759
3760 .dropdown-item:last-child {
3761 border-radius: 0 0 var(--radius-md) var(--radius-md);
3762 }
3763
3764 /* ===================================================================
3765 32. Context Menus
3766 =================================================================== */
3767
3768 .context-menu {
3769 position: fixed;
3770 z-index: 10000;
3771 min-width: 180px;
3772 max-width: 280px;
3773 background: var(--bg-card);
3774 border: var(--border-width) solid var(--border-color);
3775 border-radius: var(--radius-sm);
3776 box-shadow: var(--shadow-brutal-lg);
3777 padding: 0.25rem 0;
3778 display: none;
3779 }
3780
3781 .context-menu.visible {
3782 display: block;
3783 }
3784
3785 .context-menu-item {
3786 display: flex;
3787 align-items: center;
3788 gap: 0.75rem;
3789 padding: 0.5rem 1rem;
3790 font-size: 0.875rem;
3791 font-weight: 500;
3792 color: var(--text-primary);
3793 cursor: pointer;
3794 border: none;
3795 background: none;
3796 width: 100%;
3797 text-align: left;
3798 transition: background 0.1s;
3799 }
3800
3801 .context-menu-item:hover,
3802 .context-menu-item:focus {
3803 background: var(--accent-blue);
3804 color: var(--text-on-accent);
3805 outline: none;
3806 }
3807
3808 .context-menu-item:focus-visible {
3809 outline: 2px solid var(--accent-blue);
3810 outline-offset: -2px;
3811 }
3812
3813 .context-menu-header {
3814 font-size: 0.7rem;
3815 font-weight: 700;
3816 color: var(--text-secondary);
3817 text-transform: uppercase;
3818 letter-spacing: 0.05em;
3819 padding: 0.5rem 1rem 0.25rem;
3820 }
3821
3822 .context-menu-item-icon {
3823 width: 1.25rem;
3824 text-align: center;
3825 flex-shrink: 0;
3826 }
3827
3828 .context-menu-item-label {
3829 flex: 1;
3830 }
3831
3832 .context-menu-item-subtitle {
3833 display: block;
3834 font-size: 0.7rem;
3835 color: var(--text-secondary);
3836 font-weight: normal;
3837 }
3838
3839 .context-menu-item-shortcut {
3840 font-size: 0.75rem;
3841 color: var(--text-muted);
3842 font-family: var(--font-mono);
3843 }
3844
3845 .context-menu-item--danger {
3846 color: var(--accent-red);
3847 }
3848
3849 .context-menu-item--danger:hover {
3850 background: var(--accent-red);
3851 color: var(--text-on-accent);
3852 }
3853
3854 .context-menu-separator {
3855 height: 2px;
3856 background: var(--border-color);
3857 margin: 0.25rem 0.5rem;
3858 }
3859
3860 /* Keyboard hint in context menu */
3861 .context-menu-hint {
3862 padding: 0.35rem 1rem;
3863 font-size: 0.7rem;
3864 color: var(--text-muted);
3865 border-top: 1px solid var(--border-color);
3866 margin-top: 0.25rem;
3867 }
3868
3869 /* ===================================================================
3870 33. Scrollbar Styling
3871 =================================================================== */
3872 ::-webkit-scrollbar {
3873 width: 12px;
3874 height: 12px;
3875 }
3876
3877 ::-webkit-scrollbar-track {
3878 background: var(--bg-secondary);
3879 border-left: 2px solid var(--border-color);
3880 }
3881
3882 ::-webkit-scrollbar-thumb {
3883 background: var(--text-muted);
3884 border: var(--border-width-sm) solid var(--border-color);
3885 border-radius: var(--radius-sm);
3886 }
3887
3888 ::-webkit-scrollbar-thumb:hover {
3889 background: var(--text-secondary);
3890 }
3891
3892 /* ===================================================================
3893 34. Desktop App Styles (Loading, Skeleton, Spinner)
3894 =================================================================== */
3895
3896 /* Loading state */
3897 .loading {
3898 display: flex;
3899 justify-content: center;
3900 align-items: center;
3901 height: 200px;
3902 color: var(--text-secondary);
3903 font-family: var(--font-heading);
3904 }
3905
3906 /* Skeleton shimmer loading placeholders */
3907 .skeleton-shimmer {
3908 display: flex;
3909 flex-direction: column;
3910 gap: 1rem;
3911 padding: 1rem;
3912 }
3913
3914 .skeleton-shimmer .skeleton-row {
3915 display: flex;
3916 align-items: center;
3917 gap: 0.75rem;
3918 padding: 0.75rem;
3919 background: var(--bg-card);
3920 border-radius: var(--radius-md);
3921 border: var(--border-width) solid var(--border-color);
3922 }
3923
3924 .skeleton-shimmer .skeleton-avatar {
3925 width: 36px;
3926 height: 36px;
3927 border-radius: var(--radius-full);
3928 background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--bg-tertiary) 50%, var(--bg-secondary) 75%);
3929 background-size: 200% 100%;
3930 animation: skeleton-pulse 1.5s ease-in-out infinite;
3931 flex-shrink: 0;
3932 }
3933
3934 .skeleton-shimmer .skeleton-lines {
3935 flex: 1;
3936 display: flex;
3937 flex-direction: column;
3938 gap: 0.4rem;
3939 }
3940
3941 .skeleton-shimmer .skeleton-line {
3942 height: 0.75rem;
3943 border-radius: var(--radius-sm);
3944 background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--bg-tertiary) 50%, var(--bg-secondary) 75%);
3945 background-size: 200% 100%;
3946 animation: skeleton-pulse 1.5s ease-in-out infinite;
3947 }
3948
3949 .skeleton-shimmer .skeleton-line.short { width: 40%; }
3950 .skeleton-shimmer .skeleton-line.medium { width: 65%; }
3951 .skeleton-shimmer .skeleton-line.long { width: 90%; }
3952
3953 @keyframes skeleton-pulse {
3954 0% { background-position: 200% 0; }
3955 100% { background-position: -200% 0; }
3956 }
3957
3958 /* Spinner animation */
3959 @keyframes spin {
3960 0% { transform: rotate(0deg); }
3961 100% { transform: rotate(360deg); }
3962 }
3963
3964 .spinner {
3965 display: inline-block;
3966 width: 1em;
3967 height: 1em;
3968 border: 2px solid currentColor;
3969 border-top-color: transparent;
3970 border-radius: var(--radius-full);
3971 animation: spin 0.8s linear infinite;
3972 }
3973
3974 /* Button loading state */
3975 .btn-loading {
3976 position: relative;
3977 pointer-events: none;
3978 opacity: 0.8;
3979 }
3980
3981 .btn-loading .btn-text {
3982 visibility: hidden;
3983 }
3984
3985 .btn-loading::after {
3986 content: '';
3987 position: absolute;
3988 left: 50%;
3989 top: 50%;
3990 width: 1em;
3991 height: 1em;
3992 margin-left: -0.5em;
3993 margin-top: -0.5em;
3994 border: 2px solid currentColor;
3995 border-top-color: transparent;
3996 border-radius: var(--radius-full);
3997 animation: spin 0.8s linear infinite;
3998 }
3999
4000 .hidden { display: none !important; }
4001
4002 /* ===================================================================
4003 35. Project Dashboard
4004 =================================================================== */
4005 .project-dashboard-grid {
4006 display: grid;
4007 grid-template-columns: repeat(3, 1fr);
4008 gap: 1.5rem;
4009 flex: 1;
4010 min-height: 0;
4011 }
4012
4013 .dashboard-column {
4014 background: var(--bg-card);
4015 border: var(--border-width) solid var(--border-color);
4016 padding: 1rem;
4017 display: flex;
4018 flex-direction: column;
4019 overflow: hidden;
4020 }
4021
4022 .dashboard-column-header {
4023 display: flex;
4024 justify-content: space-between;
4025 align-items: center;
4026 margin-bottom: 1rem;
4027 padding-bottom: 0.5rem;
4028 border-bottom: 2px solid var(--border-color);
4029 }
4030
4031 .dashboard-column-header h3 {
4032 margin: 0;
4033 font-size: 1rem;
4034 font-family: var(--font-heading);
4035 font-weight: 700;
4036 }
4037
4038 .dashboard-list {
4039 flex: 1;
4040 overflow-y: auto;
4041 }
4042
4043 /* Dashboard list items compose .card + .card--list-item (see Cards section).
4044 .dashboard-item-title / -meta are page-scoped sub-element classes. */
4045 .dashboard-item-title {
4046 font-weight: 600;
4047 margin-bottom: 0.25rem;
4048 }
4049
4050 .dashboard-item-meta {
4051 font-size: 0.75rem;
4052 color: var(--text-secondary);
4053 }
4054
4055 /* ===================================================================
4056 36. Task Badges
4057 =================================================================== */
4058 .task-badges {
4059 display: flex;
4060 gap: 0.25rem;
4061 margin-top: 0.25rem;
4062 }
4063
4064 .task-badge {
4065 font-size: 0.65rem;
4066 padding: 0.15rem 0.4rem;
4067 border: var(--border-width-sm) solid var(--border-color);
4068 background: var(--bg-secondary);
4069 color: var(--text-primary);
4070 font-weight: 600;
4071 }
4072
4073 .task-badge.has-items {
4074 background: var(--accent-blue);
4075 color: var(--text-on-accent);
4076 }
4077
4078 .task-badge.recurrence {
4079 background: var(--accent-purple);
4080 color: var(--text-on-accent);
4081 }
4082
4083 /* Clickable task rows */
4084 .task-row-clickable {
4085 cursor: pointer;
4086 transition: background 0.1s;
4087 }
4088
4089 .task-row-clickable:hover {
4090 background: var(--bg-secondary);
4091 }
4092
4093 /* ===================================================================
4094 37. Progress Bar
4095 =================================================================== */
4096 .task-progress {
4097 /* Width controlled by grid, not explicit value */
4098 }
4099
4100 .progress-bar-container {
4101 width: 100%;
4102 height: 10px;
4103 background: var(--bg-secondary);
4104 border: var(--border-width-sm) solid var(--border-color);
4105 overflow: hidden;
4106 }
4107
4108 .progress-bar {
4109 height: 100%;
4110 background: var(--accent-green);
4111 transition: width 0.3s ease;
4112 }
4113
4114 .no-subtasks {
4115 color: var(--text-secondary);
4116 font-size: 0.875rem;
4117 }
4118
4119 /* ===================================================================
4120 38. Day Plan View
4121 =================================================================== */
4122 #day-plan-view {
4123 display: flex;
4124 flex-direction: column;
4125 flex: 1;
4126 min-height: 0;
4127 }
4128
4129 #day-plan-view .page-header {
4130 flex-shrink: 0;
4131 }
4132
4133 .day-plan-nav {
4134 display: flex;
4135 align-items: center;
4136 gap: 0.5rem;
4137 }
4138
4139 .day-plan-date-picker {
4140 padding: 0.5rem;
4141 background: var(--bg-card);
4142 border: var(--border-width) solid var(--border-color);
4143 border-radius: var(--radius-sm);
4144 color: var(--text-primary);
4145 font-family: var(--font-body);
4146 }
4147
4148 .day-plan-date-display {
4149 font-size: 1.25rem;
4150 font-weight: 700;
4151 margin-left: 1rem;
4152 font-family: var(--font-heading);
4153 line-height: 1;
4154 }
4155
4156 .day-plan-content {
4157 flex: 1;
4158 min-height: 0;
4159 display: flex;
4160 gap: 1.5rem;
4161 }
4162
4163 .day-plan-main {
4164 flex: 1;
4165 min-height: 0;
4166 display: flex;
4167 flex-direction: column;
4168 background: var(--bg-card);
4169 border: var(--border-width) solid var(--border-color);
4170 border-radius: var(--radius-md);
4171 overflow: hidden;
4172 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
4173 }
4174
4175 .day-plan-sidebar {
4176 width: 280px;
4177 flex-shrink: 0;
4178 display: flex;
4179 flex-direction: column;
4180 background: var(--bg-card);
4181 border: var(--border-width) solid var(--border-color);
4182 border-radius: var(--radius-md);
4183 overflow: hidden;
4184 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
4185 }
4186
4187 .sidebar-header {
4188 padding: 1rem;
4189 border-bottom: 2px solid var(--border-color);
4190 flex-shrink: 0;
4191 }
4192
4193 .sidebar-header h3 {
4194 margin: 0;
4195 font-size: 1rem;
4196 font-family: var(--font-heading);
4197 font-weight: 700;
4198 }
4199
4200 .sidebar-task-list {
4201 flex: 1;
4202 overflow-y: auto;
4203 padding: 0.75rem;
4204 display: flex;
4205 flex-direction: column;
4206 gap: 0.5rem;
4207 }
4208
4209 /* ===================================================================
4210 39. Timeline
4211 =================================================================== */
4212 .timeline-container {
4213 flex: 1;
4214 min-height: 0;
4215 overflow-y: auto;
4216 overflow-x: hidden;
4217 }
4218
4219 .timeline-scroll-area {
4220 position: relative;
4221 padding: 0.5rem 1rem 3rem 0.5rem;
4222 min-height: min-content;
4223 }
4224
4225 #timeline-slots {
4226 position: relative;
4227 }
4228
4229 #timeline-items {
4230 position: absolute;
4231 top: 0.5rem;
4232 left: 0.5rem;
4233 right: 1rem;
4234 bottom: 0;
4235 pointer-events: none;
4236 }
4237
4238 #timeline-items .timeline-item {
4239 pointer-events: auto;
4240 }
4241
4242 .timeline-slot {
4243 display: grid;
4244 grid-template-columns: 50px 1fr;
4245 height: var(--timeline-slot-h, 12px);
4246 position: relative;
4247 }
4248
4249 .timeline-slot.hour-start .timeline-slot-area {
4250 border-top: 1px dashed color-mix(in srgb, var(--border-color) 50%, transparent);
4251 }
4252
4253 .timeline-time {
4254 font-size: 0.7rem;
4255 color: var(--text-secondary);
4256 padding-right: 0.5rem;
4257 text-align: right;
4258 font-weight: 500;
4259 transform: translateY(-0.5em);
4260 }
4261
4262 .timeline-hint {
4263 text-align: center;
4264 color: var(--text-secondary);
4265 font-size: 0.85rem;
4266 font-weight: 600;
4267 margin: 0 0 0.5rem;
4268 padding: 0.35rem 0.75rem;
4269 background: var(--bg-secondary);
4270 border-radius: var(--radius-sm);
4271 }
4272
4273 .timeline-slot-area {
4274 position: relative;
4275 cursor: grab;
4276 }
4277
4278 .timeline-slot-area:hover {
4279 background: var(--bg-secondary);
4280 }
4281
4282 .timeline-item {
4283 position: absolute;
4284 left: 60px;
4285 right: 10px;
4286 border: var(--border-width) solid var(--border-color);
4287 border-radius: var(--radius-sm);
4288 padding: 0.25rem 0.5rem;
4289 overflow: hidden;
4290 cursor: grab;
4291 z-index: 10;
4292 transition: opacity 0.15s ease, box-shadow 0.15s ease;
4293 }
4294
4295 .timeline-item.task {
4296 background: var(--accent-green);
4297 color: var(--text-primary);
4298 }
4299
4300 .timeline-item.event {
4301 background: var(--accent-blue);
4302 color: var(--text-on-accent);
4303 }
4304
4305 .timeline-item.block {
4306 opacity: 0.85;
4307 }
4308
4309 .timeline-item.block-free_time {
4310 background: var(--accent-cyan);
4311 color: var(--text-primary);
4312 }
4313
4314 .timeline-item.block-personal {
4315 background: var(--accent-yellow);
4316 color: var(--text-primary);
4317 }
4318
4319 .timeline-item.block-vacation {
4320 background: var(--accent-purple);
4321 color: var(--text-on-accent);
4322 }
4323
4324 .timeline-item.block-focus {
4325 background: var(--accent-red);
4326 color: var(--text-on-accent);
4327 }
4328
4329 .timeline-item.conflict {
4330 box-shadow: 0 0 0 3px var(--accent-red);
4331 }
4332
4333 .timeline-item.selected {
4334 box-shadow: 0 0 0 3px var(--bg-card), 0 0 0 6px var(--accent-blue);
4335 }
4336
4337 .timeline-item-title {
4338 font-weight: 600;
4339 font-size: 0.75rem;
4340 line-height: 1.2;
4341 white-space: nowrap;
4342 overflow: hidden;
4343 text-overflow: ellipsis;
4344 }
4345
4346 .timeline-item-meta {
4347 font-size: 0.65rem;
4348 opacity: 0.85;
4349 line-height: 1.1;
4350 }
4351
4352 .timeline-current-time {
4353 position: absolute;
4354 left: 50px;
4355 right: 0;
4356 height: 2px;
4357 background: var(--accent-red);
4358 z-index: 20;
4359 pointer-events: none;
4360 }
4361
4362 .timeline-current-time::before {
4363 content: '';
4364 position: absolute;
4365 left: -4px;
4366 top: -3px;
4367 width: 8px;
4368 height: 8px;
4369 background: var(--accent-red);
4370 border-radius: var(--radius-full);
4371 }
4372
4373 /* Timeline Painting */
4374 .timeline-paint-preview {
4375 position: absolute;
4376 left: 70px;
4377 right: 10px;
4378 background: var(--accent-blue);
4379 opacity: 0.4;
4380 border: var(--border-width-sm) dashed var(--border-color);
4381 border-radius: var(--radius-sm);
4382 z-index: 5;
4383 pointer-events: none;
4384 }
4385
4386 .timeline-item.dragging {
4387 cursor: grabbing;
4388 opacity: 0.8;
4389 z-index: 100;
4390 box-shadow: var(--shadow-brutal-md, 4px 4px 0 var(--border-color));
4391 }
4392
4393 .timeline-container.is-painting {
4394 cursor: crosshair;
4395 user-select: none;
4396 }
4397
4398 .timeline-container.is-painting .timeline-slot-area {
4399 pointer-events: none;
4400 }
4401
4402 /* ===================================================================
4403 40. Unscheduled Tasks
4404 =================================================================== */
4405 .unscheduled-task {
4406 padding: 0.75rem;
4407 background: var(--bg-card);
4408 border: var(--border-width-sm) solid var(--border-color);
4409 border-left: 6px solid var(--accent-green);
4410 border-radius: var(--radius-sm);
4411 cursor: grab;
4412 transition: background-color 0.1s;
4413 }
4414
4415 .unscheduled-task:hover {
4416 background: var(--bg-secondary);
4417 }
4418
4419
4420 .unscheduled-task.priority-high {
4421 border-left-color: var(--accent-red);
4422 }
4423
4424 .unscheduled-task.priority-medium {
4425 border-left-color: var(--accent-yellow);
4426 }
4427
4428 .unscheduled-task.priority-low {
4429 border-left-color: var(--accent-green);
4430 }
4431
4432 .unscheduled-task-title {
4433 font-weight: 600;
4434 margin-bottom: 0.25rem;
4435 white-space: nowrap;
4436 overflow: hidden;
4437 text-overflow: ellipsis;
4438 }
4439
4440 .unscheduled-task-meta {
4441 font-size: 0.75rem;
4442 color: var(--text-secondary);
4443 }
4444
4445 .empty-unscheduled {
4446 text-align: center;
4447 color: var(--text-secondary);
4448 padding: 2rem 1rem;
4449 }
4450
4451 /* ===================================================================
4452 41. Settings
4453 =================================================================== */
4454 /* Marker class on the header `?` button. Extends .btn with mono font and
4455 a fixed min-width so the single-character glyph stays centered. Mobile
4456 touch passes hide it (see §59 + body.is-touch rule below). */
4457 .shortcut-hint-btn {
4458 font-family: var(--font-mono, monospace);
4459 font-weight: 700;
4460 min-width: 2rem;
4461 padding: 0.5rem;
4462 }
4463
4464 .settings-section h3 {
4465 font-size: 1rem;
4466 color: var(--text-primary);
4467 }
4468
4469 .settings-section .form-hint {
4470 font-size: 0.75rem;
4471 color: var(--text-secondary);
4472 }
4473
4474 /* Settings Overlay (Phase 7 Tier 6 — settings as modeless drawer) -----
4475 The settings panel now floats above whichever view the user came from,
4476 so theme/notification/account changes can be previewed against the
4477 actual app rather than a stand-alone settings page. Card is centered
4478 and keeps the original sidebar+content layout intact. */
4479 .settings-overlay {
4480 position: fixed;
4481 inset: 0;
4482 z-index: 70;
4483 display: flex;
4484 align-items: center;
4485 justify-content: center;
4486 padding: var(--space-4);
4487 }
4488 .settings-overlay.hidden {
4489 display: none;
4490 }
4491 .settings-overlay-backdrop {
4492 position: absolute;
4493 inset: 0;
4494 background: rgba(0, 0, 0, 0.35);
4495 }
4496 .settings-overlay-card {
4497 position: relative;
4498 background: var(--bg-primary);
4499 border: 1px solid var(--border-color);
4500 border-radius: var(--radius-lg, 8px);
4501 box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
4502 width: min(960px, 100%);
4503 height: min(720px, 100%);
4504 max-height: calc(100vh - 2 * var(--space-4));
4505 overflow: hidden;
4506 display: flex;
4507 flex-direction: column;
4508 }
4509 .settings-overlay-card.hidden {
4510 display: none;
4511 }
4512 /* Duplicate of .sr-only (§26) deleted 2026-05-21; use .sr-only. */
4513 .ui-mode-mobile .settings-overlay { padding: 0; }
4514 .ui-mode-mobile .settings-overlay-card {
4515 width: 100%;
4516 height: 100%;
4517 max-height: 100%;
4518 border-radius: 0;
4519 border: none;
4520 }
4521
4522
4523 /* Settings Page Layout */
4524 .settings-page-layout {
4525 display: flex;
4526 min-height: 100%;
4527 }
4528
4529 .settings-sidebar {
4530 width: 200px;
4531 flex-shrink: 0;
4532 border-right: 1px solid var(--border-color);
4533 padding: 1.5rem 0;
4534 display: flex;
4535 flex-direction: column;
4536 gap: 0.25rem;
4537 }
4538
4539 .settings-nav-items {
4540 display: flex;
4541 flex-direction: column;
4542 gap: 0.125rem;
4543 }
4544
4545 .settings-nav-item {
4546 background: none;
4547 border: none;
4548 text-align: left;
4549 padding: 0.5rem 1.25rem;
4550 font-size: 0.875rem;
4551 color: var(--text-secondary);
4552 cursor: pointer;
4553 border-radius: 0;
4554 border-left: 2px solid transparent;
4555 }
4556 .settings-nav-item:hover { background: var(--bg-hover); color: var(--text-primary); }
4557 .settings-nav-item.active {
4558 color: var(--text-primary);
4559 font-weight: 600;
4560 border-left-color: var(--accent-primary);
4561 background: var(--bg-secondary);
4562 }
4563
4564 .settings-content {
4565 flex: 1;
4566 padding: 1.5rem 2rem;
4567 max-width: 640px;
4568 overflow-y: auto;
4569 }
4570
4571 /* Contact Dashboard */
4572 .contact-header-card {
4573 display: flex;
4574 align-items: center;
4575 gap: 1.25rem;
4576 margin-bottom: 1.5rem;
4577 }
4578
4579
4580 /* Base chrome from .card.card--muted; only feature-specific spacing
4581 (gap, margin, tighter padding) remains here. */
4582 .contact-info-section {
4583 display: flex;
4584 flex-direction: column;
4585 gap: 0.375rem;
4586 margin-bottom: 1.5rem;
4587 padding: 1rem;
4588 }
4589
4590 .contact-info-item {
4591 font-size: 0.875rem;
4592 }
4593
4594 .contact-dashboard-summary {
4595 display: flex;
4596 gap: 1.5rem;
4597 margin-bottom: 1.5rem;
4598 }
4599
4600 .contact-summary-stat {
4601 display: flex;
4602 flex-direction: column;
4603 align-items: center;
4604 padding: 0.75rem 1.25rem;
4605 background: var(--bg-secondary);
4606 border-radius: var(--radius-md);
4607 min-width: 80px;
4608 }
4609
4610 .contact-summary-count {
4611 font-size: 1.5rem;
4612 font-weight: 700;
4613 color: var(--text-primary);
4614 }
4615
4616 .contact-summary-label {
4617 font-size: 0.75rem;
4618 color: var(--text-secondary);
4619 margin-top: 0.25rem;
4620 }
4621
4622 .contact-timeline {
4623 display: flex;
4624 flex-direction: column;
4625 gap: 0.25rem;
4626 }
4627
4628 /* Compose with `row-flex row-flex-3` for the row. */
4629 .contact-timeline-item {
4630 padding: 0.5rem 0.75rem;
4631 border-radius: var(--radius-sm);
4632 cursor: pointer;
4633 font-size: 0.875rem;
4634 }
4635
4636 .contact-timeline-item:hover {
4637 background: var(--bg-hover);
4638 }
4639
4640 .contact-timeline-icon {
4641 flex-shrink: 0;
4642 width: 2rem;
4643 text-align: center;
4644 font-size: 0.8rem;
4645 }
4646
4647 .contact-timeline-title {
4648 flex: 1;
4649 overflow: hidden;
4650 text-overflow: ellipsis;
4651 white-space: nowrap;
4652 }
4653
4654 .contact-timeline-date {
4655 flex-shrink: 0;
4656 font-size: 0.75rem;
4657 color: var(--text-secondary);
4658 }
4659
4660 /* Address Highlight Mirror */
4661 .address-highlight-mirror {
4662 position: absolute;
4663 top: 0;
4664 left: 0;
4665 right: 0;
4666 bottom: 0;
4667 pointer-events: none;
4668 white-space: nowrap;
4669 overflow: hidden;
4670 z-index: 0;
4671 display: flex;
4672 align-items: center;
4673 }
4674
4675 .addr-malformed { color: var(--accent-red); }
4676 .addr-contact { color: var(--accent-blue); }
4677 .addr-verified { color: var(--accent-green); }
4678 .addr-ghost { color: var(--text-muted); opacity: 0.5; }
4679
4680 /* Sync Status Indicator */
4681 /* Compose with `row-flex row-flex-2` for the row. */
4682 .sync-indicator {
4683 background: none;
4684 border: none;
4685 cursor: pointer;
4686 padding: 0.25rem 0.5rem;
4687 border-radius: var(--radius-sm);
4688 transition: background var(--transition-fast);
4689 }
4690 .sync-indicator:hover { background: var(--bg-hover); }
4691 .sync-dot {
4692 width: 8px;
4693 height: 8px;
4694 border-radius: var(--radius-full);
4695 background: var(--text-muted);
4696 transition: background var(--transition-slow);
4697 flex-shrink: 0;
4698 }
4699 .sync-dot.connected { background: var(--accent-green); }
4700 .sync-dot.syncing { background: var(--accent-blue); animation: sync-pulse 1s infinite; }
4701 .sync-dot.warn { background: var(--accent-yellow); }
4702 .sync-dot.error { background: var(--accent-red); }
4703
4704 /* Status label — always shown at desktop widths so color isn't the sole signal.
4705 Hidden on narrow widths to save space; hover still surfaces the title attr. */
4706 .sync-label {
4707 font-size: var(--font-size-sm);
4708 color: var(--text-secondary);
4709 white-space: nowrap;
4710 }
4711 /* Sync label hides in mobile UI; desktop keeps it at any width. */
4712 .ui-mode-mobile .sync-label { display: none; }
4713 @keyframes sync-pulse {
4714 0%, 100% { opacity: 1; }
4715 50% { opacity: 0.4; }
4716 }
4717
4718 /* ===================================================================
4719 42. Snooze Options
4720 =================================================================== */
4721 .snooze-options {
4722 display: flex;
4723 flex-direction: column;
4724 gap: 0.5rem;
4725 }
4726
4727 .snooze-option {
4728 display: flex;
4729 justify-content: space-between;
4730 align-items: center;
4731 padding: 0.75rem 1rem;
4732 background: var(--bg-secondary);
4733 border: var(--border-width-sm) solid var(--border-color);
4734 color: var(--text-primary);
4735 cursor: pointer;
4736 transition: background-color 0.1s;
4737 text-align: left;
4738 width: 100%;
4739 }
4740
4741 .snooze-option:hover {
4742 background: var(--accent-blue);
4743 color: var(--text-on-accent);
4744 }
4745
4746 .snooze-option-label {
4747 font-weight: 600;
4748 }
4749
4750 .snooze-option-time {
4751 font-size: 0.75rem;
4752 color: var(--text-secondary);
4753 }
4754
4755 .snooze-option:hover .snooze-option-time {
4756 color: var(--text-on-accent);
4757 }
4758
4759 .snooze-custom {
4760 margin-top: 0.5rem;
4761 padding-top: 0.5rem;
4762 border-top: 2px solid var(--border-color);
4763 }
4764
4765 .snooze-badge {
4766 display: inline-block;
4767 font-size: 0.65rem;
4768 padding: 0.15rem 0.4rem;
4769 border: var(--border-width-sm) solid var(--border-color);
4770 background: var(--accent-yellow);
4771 color: var(--text-primary);
4772 font-weight: 700;
4773 margin-top: 0.25rem;
4774 }
4775
4776 .contact-badge {
4777 display: inline-block;
4778 font-size: 0.65rem;
4779 padding: 0.15rem 0.4rem;
4780 border: var(--border-width-sm) solid var(--border-color);
4781 background: var(--accent-color);
4782 color: var(--bg-primary);
4783 font-weight: 700;
4784 margin-top: 0.25rem;
4785 }
4786
4787 /* ===================================================================
4788 43. Bulk Selection
4789 =================================================================== */
4790 .bulk-checkbox {
4791 width: 18px;
4792 height: 18px;
4793 cursor: pointer;
4794 accent-color: var(--accent-blue);
4795 border: var(--border-width-sm) solid var(--border-color);
4796 }
4797
4798 .task-actions-cell {
4799 text-align: right;
4800 white-space: nowrap;
4801 display: flex;
4802 align-items: center;
4803 justify-content: flex-end;
4804 gap: 0.5rem;
4805 }
4806
4807 .task-actions-cell .bulk-checkbox {
4808 margin-right: 0.5rem;
4809 }
4810
4811 /* Kebab menu button — extends .btn-icon with hover-reveal + bigger font. */
4812 .kebab-btn {
4813 font-size: 1.1rem;
4814 padding: 0.2rem 0.4rem;
4815 border-radius: var(--radius-sm);
4816 color: var(--text-secondary);
4817 opacity: 0;
4818 transition: opacity 0.15s ease;
4819 }
4820
4821 .task-row:hover .kebab-btn,
4822 .task-row:focus-within .kebab-btn,
4823 .email-item:hover .kebab-btn,
4824 .email-item:focus-within .kebab-btn,
4825 .event-row-virtual:hover .kebab-btn,
4826 .event-row-virtual:focus-within .kebab-btn {
4827 opacity: 1;
4828 }
4829
4830 .kebab-btn:hover {
4831 background: var(--bg-hover);
4832 }
4833
4834 .task-recurrence {
4835 font-size: 0.85rem;
4836 color: var(--text-secondary);
4837 }
4838
4839 .task-due {
4840 white-space: nowrap;
4841 }
4842
4843 .bulk-actions-bar {
4844 display: flex;
4845 align-items: center;
4846 gap: 0.5rem;
4847 padding: 0.75rem 1rem;
4848 background: var(--accent-blue);
4849 color: var(--text-on-accent);
4850 border: var(--border-width) solid var(--border-color);
4851 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
4852 margin-bottom: 1rem;
4853 }
4854
4855 .bulk-actions-bar.hidden {
4856 display: none;
4857 }
4858
4859 .bulk-count {
4860 font-weight: 700;
4861 margin-right: 1rem;
4862 font-family: var(--font-heading);
4863 }
4864
4865 .bulk-actions-bar .btn {
4866 background: var(--bg-card);
4867 border: var(--border-width-sm) solid var(--border-color);
4868 color: var(--text-primary);
4869 }
4870
4871 .bulk-actions-bar .btn:hover {
4872 background: var(--bg-secondary);
4873 }
4874
4875 .bulk-select-all {
4876 margin-left: auto;
4877 }
4878
4879 .email-checkbox-cell {
4880 padding: 0.75rem 0.5rem;
4881 display: flex;
4882 align-items: center;
4883 }
4884
4885 .email-item-with-checkbox {
4886 display: flex;
4887 align-items: flex-start;
4888 }
4889
4890 .email-item-with-checkbox .email-content {
4891 flex: 1;
4892 }
4893
4894 /* ===================================================================
4895 44. Time Blocking
4896 =================================================================== */
4897 .time-block-form {
4898 display: flex;
4899 flex-direction: column;
4900 gap: 1rem;
4901 }
4902
4903 .time-block-quick-options {
4904 display: grid;
4905 grid-template-columns: repeat(3, 1fr);
4906 gap: 0.5rem;
4907 }
4908
4909 /* Selected state for quick-pick time slots. Base styling comes from .btn.btn-sm.btn-secondary. */
4910 .time-block-quick-btn.selected {
4911 background: var(--accent-blue);
4912 color: var(--text-on-accent);
4913 box-shadow: inset 0 0 0 2px var(--border-color);
4914 }
4915
4916 .duration-presets {
4917 display: flex;
4918 gap: 0.5rem;
4919 flex-wrap: wrap;
4920 }
4921
4922 .duration-preset {
4923 padding: 0.35rem 0.75rem;
4924 background: var(--bg-secondary);
4925 border: var(--border-width-sm) solid var(--border-color);
4926 color: var(--text-primary);
4927 cursor: pointer;
4928 font-size: 0.75rem;
4929 font-weight: 600;
4930 transition: background-color 0.1s;
4931 }
4932
4933 .duration-preset:hover {
4934 background: var(--bg-tertiary);
4935 }
4936
4937 .duration-preset.selected {
4938 background: var(--accent-blue);
4939 color: var(--text-on-accent);
4940 }
4941
4942 .conflict-warning {
4943 padding: 0.75rem;
4944 background: var(--accent-red);
4945 border: var(--border-width) solid var(--border-color);
4946 color: var(--text-on-accent);
4947 font-size: 0.875rem;
4948 font-weight: 600;
4949 margin-top: 0.5rem;
4950 }
4951
4952 /* ===================================================================
4953 45. App Layout
4954 =================================================================== */
4955 .app-body {
4956 display: flex;
4957 flex: 1;
4958 min-height: 0;
4959 overflow: hidden;
4960 }
4961
4962 /* Adjust main content to work with sidebar */
4963 .app-body .main-content {
4964 flex: 1;
4965 min-width: 0;
4966 display: flex;
4967 flex-direction: column;
4968 overflow-x: visible;
4969 overflow-y: auto;
4970 }
4971
4972 /* All views fill available space */
4973 #tasks-view,
4974 #events-view,
4975 #projects-view,
4976 #emails-view {
4977 padding-bottom: 2.5rem;
4978 }
4979
4980 /* Task view fills available height */
4981 #tasks-view {
4982 display: flex;
4983 flex-direction: column;
4984 flex: 1;
4985 min-height: 0;
4986 }
4987
4988 #tasks-view .page-header,
4989 #tasks-view .bulk-actions-bar,
4990 #tasks-view .filter-bar {
4991 flex-shrink: 0;
4992 }
4993
4994 /* Events view fills available height */
4995 #events-view {
4996 display: flex;
4997 flex-direction: column;
4998 flex: 1;
4999 min-height: 0;
5000 }
5001
5002 #events-view .page-header {
5003 flex-shrink: 0;
5004 }
5005
5006 /* Emails view fills available height */
5007 #emails-view {
5008 display: flex;
5009 flex-direction: column;
5010 flex: 1;
5011 min-height: 0;
5012 }
5013
5014 /* Email filter row: search input flexes; selects + count are content-sized.
5015 Grid columns make the geometry explicit and immune to <select> intrinsic
5016 min-content shenanigans that flex layout exposes. */
5017 .email-filter-row {
5018 display: grid;
5019 grid-template-columns: minmax(0, 1fr) auto auto auto;
5020 gap: var(--space-2);
5021 align-items: center;
5022 }
5023 .email-filter-row > .form-input,
5024 .email-filter-row > .form-select {
5025 width: 100%;
5026 min-width: 0;
5027 }
5028 .email-filter-row > .form-select {
5029 width: 9rem;
5030 }
5031
5032 /* Contacts filter row: same shape as .email-filter-row (search fills,
5033 filter sizes to content, action button sizes to content). Tag filter
5034 uses .filter-select rather than .form-select, but the layout rule is
5035 identical. */
5036 .contacts-filter-row {
5037 display: grid;
5038 grid-template-columns: minmax(0, 1fr) auto auto;
5039 gap: var(--space-2);
5040 align-items: center;
5041 }
5042 .contacts-filter-row > .form-input {
5043 width: 100%;
5044 min-width: 0;
5045 }
5046 .contacts-filter-row > .filter-select {
5047 width: 9rem;
5048 min-width: 0;
5049 }
5050
5051 /* Work-hours row in Settings: two small selects with a "to" label
5052 between. Same lens as .email-filter-row — selects size to their
5053 short content; the grid columns express the intent explicitly. */
5054 .work-hours-row {
5055 display: grid;
5056 grid-template-columns: auto auto auto;
5057 gap: var(--space-2);
5058 align-items: center;
5059 }
5060 .work-hours-row > .form-select {
5061 width: auto;
5062 }
5063
5064 #emails-view .page-header,
5065 #emails-view .bulk-actions-bar {
5066 flex-shrink: 0;
5067 }
5068
5069 /* ===================================================================
5070 46. Saved Views Sidebar (desktop UI only — hidden on mobile)
5071 =================================================================== */
5072 .ui-mode-desktop .saved-views-sidebar {
5073 width: 200px;
5074 flex-shrink: 0;
5075 background: var(--bg-card);
5076 border-right: var(--border-width) solid var(--border-color);
5077 display: flex;
5078 flex-direction: column;
5079 overflow: hidden;
5080 }
5081
5082 .sidebar-section {
5083 display: flex;
5084 flex-direction: column;
5085 flex: 1;
5086 min-height: 0;
5087 }
5088
5089 .sidebar-section-header {
5090 display: flex;
5091 justify-content: space-between;
5092 align-items: center;
5093 padding: 0.75rem 1rem;
5094 font-size: 0.75rem;
5095 font-weight: 700;
5096 text-transform: uppercase;
5097 letter-spacing: 0.05em;
5098 color: var(--text-secondary);
5099 border-bottom: 2px solid var(--border-color);
5100 background: var(--bg-secondary);
5101 }
5102
5103 .btn-icon {
5104 background: none;
5105 border: none;
5106 color: var(--text-muted);
5107 cursor: pointer;
5108 padding: 0.25rem;
5109 font-size: 0.875rem;
5110 line-height: 1;
5111 }
5112
5113 .btn-icon:hover {
5114 color: var(--text-primary);
5115 }
5116
5117 .pinned-views-list {
5118 flex: 1;
5119 overflow-y: auto;
5120 padding: 0.5rem;
5121 }
5122
5123 .sidebar-empty {
5124 text-align: center;
5125 padding: 1.5rem 0.5rem;
5126 color: var(--text-muted);
5127 font-size: 0.8rem;
5128 }
5129
5130 .saved-view-item {
5131 display: flex;
5132 align-items: center;
5133 gap: 0.5rem;
5134 padding: 0.5rem 0.75rem;
5135 margin-bottom: 0.5rem;
5136 background: var(--bg-card);
5137 border: var(--border-width-sm) solid var(--border-color);
5138 border-radius: var(--radius-sm);
5139 cursor: pointer;
5140 font-size: 0.85rem;
5141 font-weight: 600;
5142 color: var(--text-primary);
5143 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
5144 transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease, color 0.15s ease;
5145 }
5146
5147 .saved-view-item:hover {
5148 background: var(--accent-blue);
5149 color: var(--text-on-accent);
5150 }
5151
5152 .saved-view-item.active {
5153 background: var(--accent-blue);
5154 color: var(--text-on-accent);
5155 box-shadow: inset 0 0 0 2px var(--border-color);
5156 }
5157
5158 .saved-view-item .view-icon {
5159 font-size: 0.75rem;
5160 }
5161
5162 .saved-view-item .view-name {
5163 flex: 1;
5164 white-space: nowrap;
5165 overflow: hidden;
5166 text-overflow: ellipsis;
5167 }
5168
5169 .saved-view-item .view-actions {
5170 opacity: 0;
5171 transition: opacity 0.1s;
5172 }
5173
5174 .saved-view-item:hover .view-actions {
5175 opacity: 1;
5176 }
5177
5178 /* Filter actions in filter bar */
5179 .filter-actions {
5180 display: flex;
5181 gap: 0.5rem;
5182 margin-left: auto;
5183 }
5184
5185 /* ===================================================================
5186 47. Contacts
5187 =================================================================== */
5188 /* Avatar primitive — circular badge with initials. Default 40px with
5189 border; size + unknown modifiers compose. */
5190 .avatar {
5191 width: 40px;
5192 height: 40px;
5193 min-width: 40px;
5194 border-radius: 50%;
5195 background-color: var(--accent-blue);
5196 color: var(--text-on-accent);
5197 display: flex;
5198 align-items: center;
5199 justify-content: center;
5200 font-weight: 700;
5201 font-size: 0.85rem;
5202 font-family: var(--font-heading);
5203 border: var(--border-width-sm) solid var(--border-color);
5204 flex-shrink: 0;
5205 }
5206 .avatar--sm { width: 32px; height: 32px; min-width: 32px; font-size: 0.75rem; border: none; }
5207 .avatar--lg { width: 60px; height: 60px; min-width: 60px; font-size: 1.2rem; }
5208 .avatar--unknown { background: var(--bg-secondary); color: var(--text-secondary); }
5209
5210 .contact-card .card-header {
5211 display: flex;
5212 align-items: center;
5213 }
5214
5215 .contact-nickname {
5216 display: block;
5217 font-size: 0.85rem;
5218 color: var(--text-secondary);
5219 font-style: italic;
5220 }
5221
5222 .contact-company {
5223 display: block;
5224 font-size: 0.85rem;
5225 color: var(--text-secondary);
5226 }
5227
5228 .contact-email {
5229 font-size: 0.85rem;
5230 color: var(--text-secondary);
5231 }
5232
5233 .contact-detail .detail-row {
5234 margin-bottom: 0.5rem;
5235 font-size: 0.9rem;
5236 }
5237
5238 .contact-detail .contact-info-section {
5239 margin-bottom: 1rem;
5240 padding-bottom: 1rem;
5241 border-bottom: 1px solid var(--border-light);
5242 }
5243
5244 .contact-detail .contact-notes {
5245 margin-bottom: 1.5rem;
5246 }
5247
5248 .contact-detail .contact-notes p {
5249 margin-top: 0.25rem;
5250 white-space: pre-wrap;
5251 color: var(--text-secondary);
5252 }
5253
5254 .sub-collection {
5255 margin-bottom: 1.25rem;
5256 }
5257
5258 .sub-collection-header {
5259 display: flex;
5260 justify-content: space-between;
5261 align-items: center;
5262 margin-bottom: 0.5rem;
5263 }
5264
5265 .sub-collection-header h4 {
5266 margin: 0;
5267 font-size: 0.95rem;
5268 font-weight: 600;
5269 }
5270
5271 .sub-item {
5272 display: flex;
5273 justify-content: space-between;
5274 align-items: center;
5275 padding: 0.4rem 0;
5276 border-bottom: 1px solid var(--border-light);
5277 font-size: 0.9rem;
5278 }
5279
5280 .sub-item:last-child {
5281 border-bottom: none;
5282 }
5283
5284 .sub-empty {
5285 font-size: 0.85rem;
5286 color: var(--text-secondary);
5287 font-style: italic;
5288 padding: 0.25rem 0;
5289 }
5290
5291 /* Edit form sub-collection summaries */
5292 .edit-sub-collections {
5293 border-top: 1px solid var(--border-color);
5294 padding-top: 1rem;
5295 margin-bottom: 0.5rem;
5296 }
5297
5298 .edit-sub-section {
5299 margin-bottom: 0.75rem;
5300 }
5301
5302 .edit-sub-header {
5303 display: flex;
5304 justify-content: space-between;
5305 align-items: center;
5306 margin-bottom: 0.25rem;
5307 }
5308
5309 .sub-item-compact {
5310 font-size: 0.85rem;
5311 color: var(--text-secondary);
5312 padding: 0.125rem 0;
5313 display: flex;
5314 align-items: center;
5315 gap: var(--space-2);
5316 justify-content: space-between;
5317 }
5318 .sub-item-actions {
5319 display: inline-flex;
5320 gap: var(--space-1);
5321 flex-shrink: 0;
5322 }
5323 .reminder-options {
5324 display: flex;
5325 flex-wrap: wrap;
5326 gap: var(--space-2) var(--space-4);
5327 margin-top: var(--space-2);
5328 }
5329 .reminder-option {
5330 display: inline-flex;
5331 align-items: center;
5332 gap: var(--space-2);
5333 font-size: var(--font-size-sm);
5334 color: var(--text-secondary);
5335 cursor: pointer;
5336 }
5337
5338 /* Task detail drawer (Phase 7 Tier 6) ---------------------------------
5339 Right-anchored slide-in overlay so users can scan the list and read
5340 one task's full detail without losing list scroll position. Falls back
5341 to a full-screen sheet on narrow viewports. */
5342 .task-drawer {
5343 position: fixed;
5344 top: 0;
5345 right: 0;
5346 bottom: 0;
5347 width: min(480px, 100vw);
5348 background: var(--bg-primary);
5349 border-left: 1px solid var(--border-color);
5350 box-shadow: -4px 0 18px rgba(0, 0, 0, 0.18);
5351 transform: translateX(100%);
5352 transition: transform 180ms ease-out;
5353 z-index: 60;
5354 display: flex;
5355 flex-direction: column;
5356 overflow: hidden;
5357 }
5358 .task-drawer.visible {
5359 transform: translateX(0);
5360 }
5361 .task-drawer-header {
5362 display: flex;
5363 align-items: center;
5364 gap: var(--space-3);
5365 padding: var(--space-3) var(--space-4);
5366 border-bottom: 1px solid var(--border-color);
5367 background: var(--bg-secondary);
5368 flex-shrink: 0;
5369 }
5370 .task-drawer-title {
5371 flex: 1;
5372 margin: 0;
5373 font-size: var(--font-size-lg, 1.05rem);
5374 font-weight: 500;
5375 overflow: hidden;
5376 text-overflow: ellipsis;
5377 white-space: nowrap;
5378 }
5379 .task-drawer-close {
5380 flex-shrink: 0;
5381 }
5382 .task-drawer-actions {
5383 display: flex;
5384 gap: var(--space-2);
5385 flex-shrink: 0;
5386 }
5387 .task-drawer-content {
5388 flex: 1;
5389 overflow-y: auto;
5390 padding: var(--space-4);
5391 }
5392 /* Mark the row whose task is currently open in the drawer. */
5393 .task-row--active {
5394 background: var(--bg-accent, var(--bg-secondary));
5395 box-shadow: inset 3px 0 0 var(--accent-color, var(--text-primary));
5396 }
5397 .ui-mode-mobile .task-drawer {
5398 width: 100vw;
5399 border-left: none;
5400 }
5401
5402
5403 /* ===================================================================
5404 48. Print Styles (global + weekly review)
5405 ===================================================================
5406 All `@media print` rules live here. Weekly-review-specific print
5407 styles consolidated from former §52 on 2026-05-24. */
5408 @media print {
5409 /* ----- Global chrome ----- */
5410
5411 /* Hide navigation and interactive elements */
5412 .sidebar,
5413 .header,
5414 .tabs,
5415 .tab-nav,
5416 .filter-bar,
5417 .pagination,
5418 .btn,
5419 .modal-overlay,
5420 .toast,
5421 .context-menu,
5422 .keyboard-hints,
5423 .review-actions-grid,
5424 .focus-section .btn,
5425 .focus-slot .btn,
5426 .tab-badge,
5427 .tab-status-dot,
5428 .card-badge,
5429 .virtual-scroller-spacer {
5430 display: none !important;
5431 }
5432
5433 /* Reset body + main content to full width */
5434 body {
5435 background: white;
5436 color: black;
5437 }
5438
5439 .main-content,
5440 .weekly-review-content {
5441 margin: 0;
5442 padding: 0;
5443 max-width: 100%;
5444 width: 100%;
5445 }
5446
5447 .view {
5448 padding: 0;
5449 }
5450
5451 /* Ensure text is readable */
5452 a {
5453 color: black;
5454 text-decoration: underline;
5455 }
5456
5457 /* ----- Tables ----- */
5458
5459 .data-table,
5460 .task-table {
5461 border: 1px solid #333;
5462 box-shadow: none;
5463 }
5464
5465 .data-table {
5466 page-break-inside: avoid;
5467 }
5468
5469 .data-table th,
5470 .data-table td {
5471 border: 1px solid #ccc;
5472 padding: 0.5rem;
5473 display: table-cell !important;
5474 }
5475
5476 .data-table tbody tr:hover,
5477 .task-row:hover {
5478 background: none;
5479 }
5480
5481 .task-list-container {
5482 height: auto !important;
5483 overflow: visible !important;
5484 }
5485
5486 .task-header-row,
5487 .task-row {
5488 grid-template-columns: 1fr 100px 40px 80px 60px 80px 60px !important;
5489 }
5490
5491 .task-header-row .task-cell,
5492 .task-row .task-cell {
5493 display: block !important;
5494 border: 1px solid #ccc;
5495 padding: 0.25rem 0.5rem;
5496 }
5497
5498 .view-header {
5499 page-break-after: avoid;
5500 }
5501
5502 /* ----- Weekly review ----- */
5503
5504 /* Reset backgrounds for print */
5505 body,
5506 .weekly-review-content,
5507 .review-card,
5508 .focus-slot,
5509 .reflection-prompt,
5510 .project-health,
5511 .event-item {
5512 background: white !important;
5513 color: black !important;
5514 -webkit-print-color-adjust: exact;
5515 print-color-adjust: exact;
5516 }
5517
5518 /* Print-friendly card chrome */
5519 .review-card {
5520 border: 1px solid #ccc !important;
5521 box-shadow: none !important;
5522 page-break-inside: avoid;
5523 margin-bottom: 1rem;
5524 }
5525
5526 .focus-slot {
5527 border: 1px solid #999 !important;
5528 }
5529
5530 .focus-slot.primary {
5531 border: 2px solid #f7d154 !important;
5532 background: #fffbea !important;
5533 }
5534
5535 /* Two-column print layout */
5536 .review-grid {
5537 display: block !important;
5538 }
5539
5540 .review-card {
5541 display: inline-block;
5542 vertical-align: top;
5543 width: 48%;
5544 margin-right: 2%;
5545 }
5546
5547 .focus-section.full-width,
5548 .reflection-section,
5549 .week-timeline,
5550 .week-timeline-events {
5551 width: 100% !important;
5552 display: block !important;
5553 }
5554
5555 /* Print header */
5556 .weekly-review-header {
5557 border-bottom: 2px solid #333;
5558 padding-bottom: 1rem;
5559 margin-bottom: 1.5rem;
5560 }
5561
5562 .week-dates {
5563 font-size: 1.5rem;
5564 font-weight: bold;
5565 }
5566
5567 /* Timeline dots print in color */
5568 .day-dot {
5569 -webkit-print-color-adjust: exact;
5570 print-color-adjust: exact;
5571 }
5572
5573 .day-dot.completed {
5574 background: #5cb85c !important;
5575 }
5576
5577 .day-dot.event {
5578 background: #9b59b6 !important;
5579 }
5580
5581 .day-dot.overdue {
5582 background: #d9534f !important;
5583 }
5584
5585 /* Project health colors */
5586 .project-health {
5587 border-left: 4px solid #337ab7 !important;
5588 }
5589
5590 .project-health.warning {
5591 border-left-color: #f7d154 !important;
5592 }
5593
5594 .project-health.danger {
5595 border-left-color: #d9534f !important;
5596 }
5597
5598 /* Focus grid for print */
5599 .focus-grid {
5600 display: flex !important;
5601 gap: 1rem;
5602 }
5603
5604 .focus-slot {
5605 flex: 1;
5606 }
5607
5608 /* Reflection prompts */
5609 .reflection-prompts {
5610 display: flex !important;
5611 gap: 1rem;
5612 }
5613
5614 .reflection-prompt {
5615 flex: 1;
5616 }
5617
5618 .prompt-input {
5619 border: 1px solid #ccc !important;
5620 min-height: 80px;
5621 }
5622
5623 /* Page break hints */
5624 .focus-section {
5625 page-break-before: auto;
5626 }
5627
5628 .reflection-section {
5629 page-break-before: always;
5630 }
5631 }
5632
5633 /* ===================================================================
5634 49. Weekly Review — chrome around the V2 grid + tab indicators
5635 ===================================================================
5636 The V1 grid layout (stat cards, review sections, focus toggle, notes
5637 textarea, etc.) was removed 2026-05-24 after V2 took over rendering
5638 in `weekly-review-render.js`. What remains here is the outer chrome
5639 (header, status pill, focus background gradient) still composed by
5640 `weekly-review.js`, plus tab indicators (`.tab-badge`,
5641 `.tab-status-dot`) consumed by tab nav + events.js. */
5642
5643 .weekly-review-content {
5644 max-width: 900px;
5645 margin: 0 auto;
5646 padding: 1rem;
5647 }
5648
5649 .weekly-review-header {
5650 display: flex;
5651 justify-content: space-between;
5652 align-items: center;
5653 margin-bottom: 1.5rem;
5654 padding-bottom: 1rem;
5655 border-bottom: var(--border-width-sm) solid var(--border-color);
5656 }
5657
5658 .week-dates {
5659 font-family: var(--font-heading);
5660 font-size: 1.25rem;
5661 font-weight: 700;
5662 color: var(--text-primary);
5663 }
5664
5665 .review-status {
5666 padding: 0.25rem 0.75rem;
5667 border-radius: var(--radius-xs);
5668 font-size: 0.875rem;
5669 font-weight: 600;
5670 border: var(--border-width-sm) solid var(--border-color);
5671 }
5672
5673 .review-status.completed {
5674 background: var(--accent-green);
5675 color: var(--text-on-accent);
5676 }
5677
5678 .review-status.pending {
5679 background: var(--accent-yellow);
5680 color: var(--text-primary);
5681 }
5682
5683 .review-status.unreviewed {
5684 background: var(--bg-secondary);
5685 color: var(--text-muted);
5686 }
5687
5688 /* Event time pill — used in the week timeline + finish-review timeline event list. */
5689 .event-time {
5690 font-size: 0.875rem;
5691 font-weight: 600;
5692 color: var(--text-muted);
5693 min-width: 80px;
5694 }
5695
5696 /* Focus section background — applied on top of the .card.card--static.review-card
5697 composition for the focus scope card in the V2 grid. */
5698 .focus-section {
5699 background: linear-gradient(135deg, var(--bg-card) 0%, color-mix(in srgb, var(--accent-yellow) 15%, var(--bg-card)) 100%);
5700 }
5701
5702 /* Tab Badge (for nudge) */
5703 .tab-badge {
5704 display: inline-block;
5705 width: 8px;
5706 height: 8px;
5707 background: var(--accent-red);
5708 border-radius: var(--radius-full);
5709 margin-left: 0.5rem;
5710 vertical-align: middle;
5711 animation: pulse-badge 2s infinite;
5712 }
5713
5714 @keyframes pulse-badge {
5715 0%, 100% {
5716 opacity: 1;
5717 transform: scale(1);
5718 }
5719 50% {
5720 opacity: 0.6;
5721 transform: scale(0.8);
5722 }
5723 }
5724
5725 .tab-status-dot {
5726 width: 8px;
5727 height: 8px;
5728 border-radius: 50%;
5729 display: inline-block;
5730 margin-left: 0.5rem;
5731 vertical-align: middle;
5732 transition: background-color 0.3s ease;
5733 }
5734 .tab-status-dot.status-none { display: none; }
5735 .tab-status-dot.status-green { background-color: var(--accent-green); }
5736 .tab-status-dot.status-yellow { background-color: var(--accent-yellow); animation: pulse-badge 2s ease-in-out infinite; }
5737 .tab-status-dot.status-red { background-color: var(--accent-red); animation: pulse-badge 1.5s ease-in-out infinite; }
5738
5739 /* ===================================================================
5740 50. Weekly Review V2 - Grid Layout
5741 =================================================================== */
5742
5743 /* Main Grid Layout */
5744 .review-grid {
5745 display: grid;
5746 grid-template-columns: 1fr 1fr;
5747 gap: 1.5rem;
5748 max-width: 1200px;
5749 margin: 0 auto;
5750 }
5751
5752 /* Review Cards — marker class for review-specific scoping. Callsites compose
5753 `.card .card--static .review-card`; chrome inherits from .card. Only the
5754 padding bump (+0.25rem) and the review-scoped descendants live here. */
5755 .review-card {
5756 padding: 1.5rem;
5757 }
5758
5759 .review-card .card-header {
5760 align-items: center;
5761 padding-bottom: 0.75rem;
5762 border-bottom: var(--border-width-sm) solid var(--bg-secondary);
5763 }
5764
5765 .review-card .card-title {
5766 display: flex;
5767 align-items: center;
5768 gap: 0.5rem;
5769 }
5770
5771 .review-card .card-icon {
5772 font-size: 1.25rem;
5773 }
5774
5775 .review-card .card-badge {
5776 font-size: 0.8rem;
5777 padding: 0.25rem 0.75rem;
5778 border-radius: var(--radius-md);
5779 font-weight: 600;
5780 }
5781
5782 /* Week Timeline - spans full width */
5783 .week-timeline {
5784 grid-column: 1 / -1;
5785 }
5786
5787 .timeline-visual {
5788 display: flex;
5789 gap: 0.5rem;
5790 margin-top: 1rem;
5791 }
5792
5793 .timeline-day {
5794 flex: 1;
5795 text-align: center;
5796 padding: 0.75rem 0.5rem;
5797 background: var(--bg-secondary);
5798 border-radius: var(--radius-md);
5799 border: 1px solid var(--border-color);
5800 position: relative;
5801 }
5802
5803 .timeline-day.today {
5804 background: var(--accent-blue);
5805 color: var(--text-on-accent);
5806 border-width: 2px;
5807 font-weight: 700;
5808 }
5809
5810 .timeline-day.past {
5811 opacity: 0.7;
5812 }
5813
5814 .timeline-day.future {
5815 background: var(--bg-card);
5816 }
5817
5818 .timeline-day .day-name {
5819 font-size: 0.7rem;
5820 font-weight: 600;
5821 text-transform: uppercase;
5822 color: var(--text-muted);
5823 }
5824
5825 .timeline-day .day-number {
5826 font-size: 1.1rem;
5827 font-weight: 700;
5828 }
5829
5830 .day-dots {
5831 display: flex;
5832 justify-content: center;
5833 gap: 3px;
5834 margin-top: 0.5rem;
5835 min-height: 8px;
5836 }
5837
5838 .day-dot {
5839 width: 8px;
5840 height: 8px;
5841 border-radius: var(--radius-full);
5842 }
5843
5844 .day-dot.task { background: var(--accent-blue); }
5845 .day-dot.event { background: var(--accent-purple); }
5846 .day-dot.completed { background: var(--accent-green); }
5847 .day-dot.overdue { background: var(--accent-red); }
5848 .day-dot.vacation-off {
5849 background: var(--text-muted);
5850 opacity: 0.5;
5851 width: 12px;
5852 height: 4px;
5853 border-radius: 2px;
5854 }
5855
5856 /* Day Events (inline on timeline strip) */
5857 .day-events {
5858 display: flex;
5859 flex-direction: column;
5860 gap: 2px;
5861 margin-top: 0.5rem;
5862 text-align: left;
5863 }
5864
5865 .day-event {
5866 font-size: 0.6rem;
5867 line-height: 1.3;
5868 padding: 1px 4px;
5869 border-left: 2px solid var(--accent-purple);
5870 white-space: nowrap;
5871 overflow: hidden;
5872 text-overflow: ellipsis;
5873 color: var(--text-secondary);
5874 }
5875
5876 .day-event .event-time {
5877 font-size: 0.55rem;
5878 font-weight: 600;
5879 color: var(--accent-purple);
5880 margin-right: 2px;
5881 min-width: auto;
5882 }
5883
5884 .day-event-more {
5885 font-size: 0.55rem;
5886 color: var(--text-muted);
5887 padding: 1px 4px;
5888 font-style: italic;
5889 }
5890
5891 /* Week's Events Card (below timeline) */
5892 .week-timeline-events {
5893 grid-column: 1 / -1;
5894 }
5895
5896 .timeline-events-day {
5897 margin-bottom: 0.75rem;
5898 }
5899
5900 .timeline-events-day:last-child {
5901 margin-bottom: 0;
5902 }
5903
5904 .timeline-events-day-label {
5905 font-family: var(--font-heading);
5906 font-size: 0.8rem;
5907 font-weight: 700;
5908 color: var(--text-secondary);
5909 margin-bottom: 0.25rem;
5910 text-transform: uppercase;
5911 }
5912
5913 /* Vacation Day Toggles */
5914 .vacation-toggles-section {
5915 margin-top: 1rem;
5916 padding-top: 1rem;
5917 border-top: 2px solid var(--border-color);
5918 }
5919
5920 .vacation-toggles-section h3 {
5921 margin: 0 0 0.75rem 0;
5922 font-size: 0.9rem;
5923 font-family: var(--font-heading);
5924 font-weight: 700;
5925 }
5926
5927 .vacation-toggles {
5928 display: flex;
5929 gap: 0.5rem;
5930 }
5931
5932 .vacation-toggle {
5933 width: 2.5rem;
5934 height: 2.5rem;
5935 border-radius: var(--radius-sm);
5936 border: var(--border-width) solid var(--border-color);
5937 background: var(--bg-secondary);
5938 font-family: var(--font-heading);
5939 font-weight: 700;
5940 font-size: 0.8rem;
5941 cursor: pointer;
5942 transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
5943 display: flex;
5944 align-items: center;
5945 justify-content: center;
5946 }
5947
5948 .vacation-toggle:hover {
5949 background: var(--bg-hover);
5950 }
5951
5952 .vacation-toggle.active {
5953 background: var(--accent-purple);
5954 color: var(--text-on-accent);
5955 border-color: var(--accent-purple);
5956 }
5957
5958 /* Vacation Timeline Day */
5959 .timeline-day.vacation {
5960 opacity: 0.5;
5961 }
5962
5963 .timeline-day.vacation .day-name {
5964 text-decoration: line-through;
5965 }
5966
5967 /* Vacation Day Banner (Day Plan) */
5968 .vacation-day-banner {
5969 text-align: center;
5970 padding: 0.5rem 1rem;
5971 background: color-mix(in srgb, var(--accent-purple) 15%, var(--bg-secondary));
5972 border: var(--border-width-sm) solid var(--accent-purple);
5973 border-radius: var(--radius-sm);
5974 font-family: var(--font-heading);
5975 font-weight: 700;
5976 font-size: 0.85rem;
5977 color: var(--accent-purple);
5978 margin-bottom: 0.75rem;
5979 }
5980
5981 /* Stats Row */
5982 .stats-row {
5983 display: flex;
5984 gap: 1rem;
5985 margin-bottom: 1rem;
5986 }
5987
5988 .stat-box {
5989 flex: 1;
5990 text-align: center;
5991 padding: 1rem;
5992 background: var(--bg-secondary);
5993 border-radius: var(--radius-md);
5994 }
5995
5996 .stat-box .stat-number {
5997 font-family: var(--font-heading);
5998 font-size: 2rem;
5999 font-weight: 800;
6000 line-height: 1;
6001 }
6002
6003 .stat-box .stat-number.green { color: var(--accent-green); }
6004 .stat-box .stat-number.red { color: var(--accent-red); }
6005 .stat-box .stat-number.blue { color: var(--accent-blue); }
6006 .stat-box .stat-number.purple { color: var(--accent-purple); }
6007
6008 .stat-box .stat-label {
6009 font-size: 0.75rem;
6010 text-transform: uppercase;
6011 color: var(--text-muted);
6012 font-weight: 600;
6013 margin-top: 0.25rem;
6014 }
6015
6016 /* Task Lists in Review Cards */
6017 .task-list {
6018 list-style: none;
6019 max-height: 200px;
6020 overflow-y: auto;
6021 }
6022
6023 .task-item {
6024 display: flex;
6025 align-items: center;
6026 gap: 0.75rem;
6027 padding: 0.75rem;
6028 margin-bottom: 0.5rem;
6029 background: var(--bg-secondary);
6030 border-radius: var(--radius-md);
6031 cursor: pointer;
6032 transition: background-color var(--transition-normal);
6033 }
6034
6035 .task-item:hover {
6036 background: var(--accent-blue);
6037 color: var(--text-on-accent);
6038 }
6039
6040 .task-item.completed {
6041 opacity: 0.6;
6042 text-decoration: line-through;
6043 }
6044
6045 .task-checkbox {
6046 width: 20px;
6047 height: 20px;
6048 border: 2px solid var(--border-color);
6049 border-radius: var(--radius-xs);
6050 display: flex;
6051 align-items: center;
6052 justify-content: center;
6053 flex-shrink: 0;
6054 }
6055
6056 .task-checkbox.checked {
6057 background: var(--accent-green);
6058 color: var(--text-on-accent);
6059 }
6060
6061 .task-text {
6062 flex: 1;
6063 font-size: 0.9rem;
6064 }
6065
6066 .task-project {
6067 font-size: 0.75rem;
6068 padding: 0.2rem 0.5rem;
6069 background: var(--bg-card);
6070 border-radius: var(--radius-xs);
6071 color: var(--text-muted);
6072 }
6073
6074 .task-due {
6075 font-size: 0.75rem;
6076 color: var(--text-muted);
6077 }
6078
6079 .task-due.overdue {
6080 color: var(--accent-red);
6081 font-weight: 600;
6082 }
6083
6084 /* Focus Section - spans full width */
6085 .focus-section.full-width {
6086 grid-column: 1 / -1;
6087 }
6088
6089 /* Shared scope-slot frame — used by Week's Focus card and Month's Goals card.
6090 View-specific styling layers on top (e.g. `.focus-slot.primary`, `.scope-slot.done`). */
6091 .scope-slots {
6092 display: grid;
6093 grid-template-columns: 1fr 1fr 1fr;
6094 gap: 1rem;
6095 margin-top: 1rem;
6096 }
6097
6098 .scope-slot {
6099 padding: 1.25rem;
6100 background: var(--bg-secondary);
6101 border: 2px dashed var(--border-color);
6102 border-radius: var(--radius-md);
6103 min-height: 100px;
6104 display: flex;
6105 flex-direction: column;
6106 gap: 0.5rem;
6107 transition: background 0.15s, border-color 0.15s;
6108 }
6109
6110 .scope-slot.filled {
6111 border-style: solid;
6112 background: var(--bg-card);
6113 }
6114
6115 .scope-slot.empty {
6116 cursor: pointer;
6117 }
6118
6119 .scope-slot.empty:hover {
6120 border-color: var(--accent-primary);
6121 background: var(--bg-tertiary);
6122 }
6123
6124 .scope-slot-label {
6125 font-size: 0.7rem;
6126 text-transform: uppercase;
6127 letter-spacing: 0.05em;
6128 color: var(--text-muted);
6129 font-weight: 600;
6130 }
6131
6132 .scope-slot-title {
6133 font-weight: 600;
6134 font-size: 0.95rem;
6135 }
6136
6137 .scope-slot-meta {
6138 font-size: 0.8rem;
6139 color: var(--text-secondary);
6140 }
6141
6142 .scope-slot-empty {
6143 color: var(--text-muted);
6144 font-style: italic;
6145 font-size: 0.9rem;
6146 }
6147
6148 /* Focus-specific overlay: primary-priority highlight */
6149 .focus-slot.primary {
6150 border-color: var(--accent-yellow);
6151 background: linear-gradient(135deg, var(--bg-card) 0%, color-mix(in srgb, var(--accent-yellow) 10%, var(--bg-card)) 100%);
6152 }
6153
6154 /* Legacy aliases — keep so existing JS selectors and styles still apply.
6155 New code should use the .scope-slot* classes. */
6156 .focus-grid { /* alias of .scope-slots */ }
6157 .focus-slot { /* alias of .scope-slot */ }
6158 .focus-label { /* alias of .scope-slot-label */ }
6159 .focus-task { /* alias of .scope-slot-title */ }
6160 .focus-meta { /* alias of .scope-slot-meta */ }
6161 .focus-empty { /* alias of .scope-slot-empty */ }
6162
6163 /* Projects Health */
6164 .projects-grid {
6165 display: grid;
6166 grid-template-columns: repeat(3, 1fr);
6167 gap: 0.75rem;
6168 margin-top: 0.5rem;
6169 }
6170
6171 .project-health {
6172 padding: 0.75rem;
6173 background: var(--bg-secondary);
6174 border-radius: var(--radius-md);
6175 border-left: 4px solid var(--accent-blue);
6176 }
6177
6178 .project-health.warning {
6179 border-left-color: var(--accent-yellow);
6180 }
6181
6182 .project-health.danger {
6183 border-left-color: var(--accent-red);
6184 }
6185
6186 .project-name {
6187 font-weight: 600;
6188 font-size: 0.85rem;
6189 margin-bottom: 0.25rem;
6190 }
6191
6192 .project-stats {
6193 font-size: 0.75rem;
6194 color: var(--text-muted);
6195 }
6196
6197 /* Reflection Section */
6198 .reflection-section {
6199 grid-column: 1 / -1;
6200 }
6201
6202 .reflection-prompts {
6203 display: grid;
6204 grid-template-columns: 1fr 1fr;
6205 gap: 1rem;
6206 margin-top: 1rem;
6207 }
6208
6209 .reflection-prompt {
6210 padding: 1rem;
6211 background: var(--bg-secondary);
6212 border-radius: var(--radius-md);
6213 }
6214
6215 .prompt-label {
6216 font-size: 0.8rem;
6217 font-weight: 600;
6218 color: var(--text-secondary);
6219 margin-bottom: 0.5rem;
6220 }
6221
6222 .prompt-input,
6223 .reflection-textarea {
6224 width: 100%;
6225 padding: 0.75rem;
6226 border: var(--border-width-sm) solid var(--border-color);
6227 border-radius: var(--radius-md);
6228 font-size: 0.9rem;
6229 font-family: inherit;
6230 resize: none;
6231 background: var(--bg-card);
6232 }
6233
6234 .prompt-input:focus,
6235 .reflection-textarea:focus {
6236 outline: none;
6237 border-color: var(--accent-blue);
6238 }
6239
6240 /* Review Actions in Grid */
6241 .review-actions-grid {
6242 grid-column: 1 / -1;
6243 display: flex;
6244 justify-content: flex-end;
6245 gap: 1rem;
6246 padding-top: 1rem;
6247 }
6248
6249 /* Event items */
6250 .event-item {
6251 display: flex;
6252 align-items: center;
6253 gap: 0.75rem;
6254 padding: 0.75rem;
6255 margin-bottom: 0.5rem;
6256 background: var(--bg-secondary);
6257 border-radius: var(--radius-md);
6258 border-left: 3px solid var(--accent-purple);
6259 }
6260
6261 .event-item .event-time {
6262 font-size: 0.8rem;
6263 font-weight: 600;
6264 color: var(--accent-purple);
6265 min-width: 100px;
6266 }
6267
6268 .event-item .event-title {
6269 flex: 1;
6270 font-size: 0.9rem;
6271 }
6272
6273 /* Accomplishment celebration */
6274 .accomplishment-highlight {
6275 background: linear-gradient(135deg, color-mix(in srgb, var(--accent-green) 10%, var(--bg-card)) 0%, color-mix(in srgb, var(--accent-green) 5%, var(--bg-card)) 100%);
6276 border: 2px solid var(--accent-green);
6277 padding: 1rem;
6278 border-radius: var(--radius-md);
6279 margin-bottom: 1rem;
6280 display: flex;
6281 align-items: center;
6282 gap: 1rem;
6283 }
6284
6285 .accomplishment-icon {
6286 font-size: 2rem;
6287 }
6288
6289 .accomplishment-text {
6290 font-size: 1rem;
6291 }
6292
6293 .accomplishment-text strong {
6294 color: var(--accent-green);
6295 }
6296
6297 /* Scrollbar styling for task lists */
6298 .task-list::-webkit-scrollbar {
6299 width: 6px;
6300 }
6301
6302 .task-list::-webkit-scrollbar-track {
6303 background: var(--bg-secondary);
6304 border-radius: var(--radius-xs);
6305 }
6306
6307 .task-list::-webkit-scrollbar-thumb {
6308 background: var(--border-color);
6309 border-radius: var(--radius-xs);
6310 }
6311
6312 /* Weekly Review Grid in mobile UI — collapse to single column. */
6313 .ui-mode-mobile .review-grid {
6314 grid-template-columns: 1fr;
6315 }
6316
6317 .ui-mode-mobile .week-timeline,
6318 .ui-mode-mobile .week-timeline-events,
6319 .ui-mode-mobile .focus-section.full-width,
6320 .ui-mode-mobile .reflection-section {
6321 grid-column: 1;
6322 }
6323
6324 .ui-mode-mobile .focus-grid {
6325 grid-template-columns: 1fr;
6326 }
6327
6328 .ui-mode-mobile .reflection-prompts {
6329 grid-template-columns: 1fr;
6330 }
6331
6332 .ui-mode-mobile .projects-grid {
6333 grid-template-columns: 1fr 1fr;
6334 }
6335
6336 /* Weekly Review extras — mobile UI: stack stat cards and project grid. */
6337 .ui-mode-mobile .stat-cards {
6338 flex-direction: column;
6339 }
6340
6341 .ui-mode-mobile .stat-card {
6342 max-width: none;
6343 }
6344
6345 .ui-mode-mobile .week-info {
6346 flex-direction: column;
6347 align-items: flex-start;
6348 gap: 0.5rem;
6349 }
6350
6351 .ui-mode-mobile .projects-grid {
6352 grid-template-columns: 1fr;
6353 }
6354
6355 /* ===================================================================
6356 51. Weekly Review Transitions & Keyboard Navigation
6357 =================================================================== */
6358
6359 /* Smooth transitions for focus slots */
6360 .focus-slot {
6361 transition: background-color 0.2s ease-out, border-color 0.2s ease-out;
6362 }
6363
6364 .focus-slot.filled {
6365 animation: focusSlotFill 0.3s ease-out;
6366 }
6367
6368 @keyframes focusSlotFill {
6369 0% {
6370 transform: scale(0.95);
6371 opacity: 0.7;
6372 }
6373 100% {
6374 transform: scale(1);
6375 opacity: 1;
6376 }
6377 }
6378
6379 /* Keyboard focus states */
6380 .focus-slot:focus-within,
6381 .focus-slot:focus {
6382 outline: 2px solid var(--accent-blue);
6383 outline-offset: 2px;
6384 }
6385
6386 .focus-slot[tabindex]:focus {
6387 outline: 2px solid var(--accent-blue);
6388 outline-offset: 2px;
6389 }
6390
6391 /* Suggested task buttons transitions */
6392 .focus-section .btn {
6393 transition: transform 0.15s ease-out, opacity 0.15s ease-out;
6394 }
6395
6396 .focus-section .btn:active {
6397 transform: scale(0.97);
6398 }
6399
6400 /* §52 vacated 2026-05-24 — weekly-review print styles consolidated into §48. */
6401
6402
6403 /* ===================================================================
6404 52b. Monthly Review
6405 =================================================================== */
6406
6407 .monthly-review-nav,
6408 .weekly-review-nav {
6409 display: flex;
6410 align-items: center;
6411 gap: 0.5rem;
6412 }
6413
6414 .weekly-review-nav .week-dates {
6415 font-family: var(--font-heading);
6416 font-size: 1.25rem;
6417 font-weight: 700;
6418 color: var(--text-primary);
6419 margin-left: 0.5rem;
6420 }
6421
6422 .monthly-review-month-display {
6423 font-family: var(--font-heading);
6424 font-size: 1.25rem;
6425 font-weight: 700;
6426 color: var(--text-primary);
6427 margin-left: 0.5rem;
6428 }
6429
6430 .monthly-review-content {
6431 max-width: 900px;
6432 margin: 0 auto;
6433 padding: 1rem;
6434 }
6435
6436 /* Heat Map Calendar */
6437 .month-heatmap {
6438 margin-bottom: 1.5rem;
6439 border: var(--border-width-sm) solid var(--border-color);
6440 border-radius: var(--radius-md);
6441 padding: 1rem;
6442 background: var(--bg-secondary);
6443 }
6444
6445 .month-heatmap-header {
6446 display: grid;
6447 grid-template-columns: repeat(7, 1fr);
6448 text-align: center;
6449 margin-bottom: 0.5rem;
6450 }
6451
6452 .month-heatmap-day-header {
6453 font-family: var(--font-heading);
6454 font-size: 0.75rem;
6455 font-weight: 600;
6456 color: var(--text-secondary);
6457 text-transform: uppercase;
6458 }
6459
6460 .month-heatmap-grid {
6461 display: grid;
6462 grid-template-columns: repeat(7, 1fr);
6463 gap: 3px;
6464 }
6465
6466 .month-heatmap-cell {
6467 aspect-ratio: 1;
6468 display: flex;
6469 flex-direction: column;
6470 align-items: center;
6471 justify-content: center;
6472 border-radius: var(--radius-xs);
6473 cursor: pointer;
6474 transition: transform 0.1s ease;
6475 border: var(--border-width-sm) solid transparent;
6476 position: relative;
6477 min-height: 40px;
6478 }
6479
6480 .month-heatmap-cell:not(.empty):hover {
6481 transform: scale(1.1);
6482 border-color: var(--border-color);
6483 z-index: 1;
6484 }
6485
6486 .month-heatmap-cell.empty {
6487 cursor: default;
6488 background: transparent;
6489 }
6490
6491 .month-heatmap-cell.intensity-0 { background: var(--bg-primary); }
6492 .month-heatmap-cell.intensity-1 { background: color-mix(in srgb, var(--accent-green) 20%, var(--bg-primary)); }
6493 .month-heatmap-cell.intensity-2 { background: color-mix(in srgb, var(--accent-green) 40%, var(--bg-primary)); }
6494 .month-heatmap-cell.intensity-3 { background: color-mix(in srgb, var(--accent-green) 60%, var(--bg-primary)); }
6495
6496 .month-heatmap-cell.vacation {
6497 background: var(--bg-tertiary);
6498 opacity: 0.6;
6499 }
6500
6501 .month-heatmap-cell.today {
6502 border-color: var(--accent-primary);
6503 border-width: 2px;
6504 }
6505
6506 .month-heatmap-cell.past.intensity-0 {
6507 background: var(--bg-tertiary);
6508 }
6509
6510 .month-heatmap-day-number {
6511 font-family: var(--font-heading);
6512 font-size: 0.8rem;
6513 font-weight: 600;
6514 color: var(--text-primary);
6515 }
6516
6517 .month-heatmap-dots {
6518 display: flex;
6519 gap: 2px;
6520 margin-top: 2px;
6521 }
6522
6523 .month-dot {
6524 font-size: 0.6rem;
6525 font-weight: 700;
6526 border-radius: var(--radius-xs);
6527 padding: 0 3px;
6528 line-height: 1.3;
6529 }
6530
6531 .month-dot.completed { color: var(--accent-green); }
6532 .month-dot.event { color: var(--accent-purple); }
6533
6534 /* Cards Grid */
6535 .monthly-review-cards {
6536 display: grid;
6537 grid-template-columns: 1fr 1fr;
6538 gap: 1rem;
6539 }
6540
6541 .review-card.month-stats-card {
6542 grid-column: span 1;
6543 }
6544
6545 .review-card.month-goals-card {
6546 margin-bottom: 1rem;
6547 }
6548
6549 .review-card.month-pulse-card,
6550 .review-card.month-patterns-card {
6551 grid-column: span 1;
6552 }
6553
6554 .review-card.month-reflection-card {
6555 grid-column: 1 / -1;
6556 }
6557
6558 .review-card-title {
6559 font-family: var(--font-heading);
6560 font-size: 1rem;
6561 font-weight: 700;
6562 margin-bottom: 0.75rem;
6563 color: var(--text-primary);
6564 }
6565
6566 /* Stats */
6567 .month-stats-grid {
6568 display: grid;
6569 grid-template-columns: 1fr 1fr;
6570 gap: 0.5rem;
6571 }
6572
6573 .month-stat-item {
6574 display: flex;
6575 flex-direction: column;
6576 align-items: center;
6577 padding: 0.5rem;
6578 border-radius: var(--radius-xs);
6579 background: var(--bg-primary);
6580 border: var(--border-width-sm) solid var(--border-color);
6581 }
6582
6583 .month-stat-value {
6584 font-family: var(--font-heading);
6585 font-size: 1.5rem;
6586 font-weight: 700;
6587 color: var(--text-primary);
6588 }
6589
6590 .month-stat-label {
6591 font-size: 0.75rem;
6592 color: var(--text-secondary);
6593 text-transform: uppercase;
6594 font-weight: 600;
6595 }
6596
6597 .month-stats-highlights {
6598 display: flex;
6599 gap: 1rem;
6600 margin-top: 0.5rem;
6601 justify-content: center;
6602 }
6603
6604 .stat-highlight {
6605 font-size: 0.8rem;
6606 color: var(--text-secondary);
6607 }
6608
6609 /* Project Pulse */
6610 .month-pulse-list {
6611 display: flex;
6612 flex-direction: column;
6613 gap: 0.5rem;
6614 }
6615
6616 .month-pulse-item {
6617 display: flex;
6618 align-items: center;
6619 gap: 0.5rem;
6620 padding: 0.5rem;
6621 border-radius: var(--radius-xs);
6622 background: var(--bg-primary);
6623 border: var(--border-width-sm) solid var(--border-color);
6624 }
6625
6626 .pulse-name {
6627 font-weight: 600;
6628 flex: 1;
6629 font-size: 0.875rem;
6630 }
6631
6632 .pulse-stats {
6633 font-size: 0.75rem;
6634 color: var(--text-secondary);
6635 }
6636
6637 .pulse-arrow {
6638 font-size: 1rem;
6639 font-weight: 700;
6640 }
6641
6642 .month-pulse-item.positive .pulse-arrow { color: var(--accent-green); }
6643 .month-pulse-item.negative .pulse-arrow { color: var(--accent-red); }
6644 .month-pulse-item.neutral .pulse-arrow { color: var(--text-secondary); }
6645
6646 /* Goals — scope-slot frame is shared with Focus; goal-specific bits below.
6647 .month-goals-list is now just a hook for legacy selectors; layout comes from .scope-slots. */
6648 .month-goals-list { /* layout inherited from .scope-slots */ }
6649
6650 .month-goal-body {
6651 display: flex;
6652 align-items: center;
6653 gap: 0.5rem;
6654 flex: 1;
6655 }
6656
6657 .month-goal-item.done {
6658 opacity: 0.7;
6659 }
6660
6661 .month-goal-item.done .month-goal-text {
6662 text-decoration: line-through;
6663 }
6664
6665 .month-goal-item.abandoned {
6666 opacity: 0.5;
6667 }
6668
6669 .month-goal-item.abandoned .month-goal-text {
6670 text-decoration: line-through;
6671 }
6672
6673 /* Extends .btn-icon with bigger font, fixed width, and parent-driven color overrides. */
6674 .month-goal-status-btn {
6675 font-size: 1rem;
6676 padding: 0;
6677 color: var(--text-secondary);
6678 width: 24px;
6679 text-align: center;
6680 }
6681
6682 .month-goal-item.done .month-goal-status-btn { color: var(--accent-green); }
6683 .month-goal-item.abandoned .month-goal-status-btn { color: var(--accent-red); }
6684
6685 .month-goal-text {
6686 flex: 1;
6687 font-size: 0.875rem;
6688 }
6689
6690 /* Extends .btn-icon with hover-reveal opacity and tertiary color. */
6691 .month-goal-delete-btn {
6692 color: var(--text-tertiary);
6693 padding: 0 4px;
6694 font-size: 0.75rem;
6695 opacity: 0;
6696 transition: opacity 0.15s;
6697 }
6698
6699 .month-goal-item:hover .month-goal-delete-btn {
6700 opacity: 1;
6701 }
6702
6703 .month-goal-placeholder {
6704 color: var(--text-tertiary);
6705 font-size: 0.875rem;
6706 }
6707
6708 /* Reflection */
6709 .month-reflection-fields {
6710 display: flex;
6711 flex-direction: column;
6712 gap: 0.5rem;
6713 }
6714
6715 .month-reflection-label {
6716 font-size: 0.875rem;
6717 font-weight: 600;
6718 color: var(--text-secondary);
6719 }
6720
6721 .month-reflection-textarea {
6722 width: 100%;
6723 padding: 0.5rem;
6724 border: var(--border-width-sm) solid var(--border-color);
6725 border-radius: var(--radius-xs);
6726 background: var(--bg-primary);
6727 color: var(--text-primary);
6728 font-family: var(--font-body);
6729 font-size: 0.875rem;
6730 resize: vertical;
6731 }
6732
6733 .month-reflection-textarea:focus {
6734 outline: 2px solid var(--accent-primary);
6735 outline-offset: -1px;
6736 }
6737
6738 /* Patterns */
6739 .month-patterns-list {
6740 list-style: none;
6741 padding: 0;
6742 margin: 0;
6743 display: flex;
6744 flex-direction: column;
6745 gap: 0.5rem;
6746 }
6747
6748 .month-pattern-item {
6749 font-size: 0.875rem;
6750 color: var(--text-secondary);
6751 padding: 0.5rem;
6752 background: var(--bg-primary);
6753 border-radius: var(--radius-xs);
6754 border: var(--border-width-sm) solid var(--border-color);
6755 }
6756
6757 /* Monthly Review in mobile UI — collapse to single column, denser heatmap. */
6758 .ui-mode-mobile .monthly-review-cards {
6759 grid-template-columns: 1fr;
6760 }
6761
6762 .ui-mode-mobile .review-card.month-stats-card,
6763 .ui-mode-mobile .review-card.month-goals-card,
6764 .ui-mode-mobile .review-card.month-pulse-card,
6765 .ui-mode-mobile .review-card.month-patterns-card {
6766 grid-column: span 1;
6767 }
6768
6769 .ui-mode-mobile .month-heatmap-cell {
6770 min-height: 32px;
6771 }
6772
6773 .ui-mode-mobile .month-heatmap-day-number {
6774 font-size: 0.7rem;
6775 }
6776
6777 .ui-mode-mobile .month-heatmap-dots {
6778 display: none;
6779 }
6780
6781 /* ===================================================================
6782 53. Import Wizard
6783 =================================================================== */
6784 .import-wizard {
6785 display: flex;
6786 flex-direction: column;
6787 gap: 1.5rem;
6788 }
6789
6790 .import-step {
6791 padding: 1rem;
6792 background: var(--bg-secondary);
6793 border: var(--border-width) solid var(--border-color);
6794 border-radius: var(--radius-md);
6795 }
6796
6797 .import-step h3 {
6798 margin: 0 0 1rem 0;
6799 font-size: var(--font-size-md);
6800 font-weight: 600;
6801 }
6802
6803 .plugin-selector {
6804 display: grid;
6805 grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
6806 gap: 0.75rem;
6807 }
6808
6809 .plugin-option {
6810 display: flex;
6811 flex-direction: column;
6812 align-items: flex-start;
6813 padding: 0.75rem 1rem;
6814 background: var(--bg-card);
6815 border: var(--border-width) solid var(--border-color);
6816 border-radius: var(--radius-sm);
6817 cursor: pointer;
6818 text-align: left;
6819 transition: border-color var(--transition-fast), background var(--transition-fast);
6820 }
6821
6822 .plugin-option:hover {
6823 border-color: var(--accent-primary);
6824 background: var(--bg-hover);
6825 }
6826
6827 .plugin-option.selected {
6828 border-color: var(--accent-primary);
6829 background: color-mix(in srgb, var(--accent-primary) 10%, var(--bg-card));
6830 box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-primary) 30%, transparent);
6831 }
6832
6833 .plugin-option .plugin-name {
6834 font-weight: 600;
6835 margin-bottom: 0.25rem;
6836 }
6837
6838 .plugin-option .plugin-meta {
6839 display: flex;
6840 gap: 0.5rem;
6841 font-size: var(--font-size-sm);
6842 color: var(--text-muted);
6843 margin-bottom: 0.25rem;
6844 }
6845
6846 .plugin-option .plugin-extensions {
6847 color: var(--accent-cyan);
6848 }
6849
6850 .plugin-option .plugin-types {
6851 color: var(--text-secondary);
6852 }
6853
6854 .plugin-option .plugin-description {
6855 font-size: var(--font-size-sm);
6856 color: var(--text-secondary);
6857 line-height: 1.4;
6858 }
6859
6860 .file-selector {
6861 display: flex;
6862 align-items: center;
6863 gap: 1rem;
6864 }
6865
6866 .selected-file-name {
6867 color: var(--text-secondary);
6868 font-family: monospace;
6869 font-size: var(--font-size-sm);
6870 }
6871
6872 .import-preview-container {
6873 min-height: 100px;
6874 }
6875
6876 .import-preview-table-wrapper {
6877 max-height: 300px;
6878 overflow: auto;
6879 border: 1px solid var(--border-color);
6880 border-radius: var(--radius-sm);
6881 }
6882
6883 .import-preview-table {
6884 font-size: var(--font-size-sm);
6885 margin: 0;
6886 }
6887
6888 .import-preview-table th {
6889 position: sticky;
6890 top: 0;
6891 background: var(--bg-secondary);
6892 z-index: 1;
6893 }
6894
6895 .import-preview-table td {
6896 max-width: 200px;
6897 overflow: hidden;
6898 text-overflow: ellipsis;
6899 white-space: nowrap;
6900 }
6901
6902 .import-summary {
6903 margin: 0 0 0.75rem 0;
6904 color: var(--text-primary);
6905 }
6906
6907 .import-more {
6908 margin: 0.5rem 0 0 0;
6909 color: var(--text-muted);
6910 font-style: italic;
6911 font-size: var(--font-size-sm);
6912 }
6913
6914 .import-empty,
6915 .import-error {
6916 padding: 2rem;
6917 text-align: center;
6918 color: var(--text-muted);
6919 }
6920
6921 .import-error {
6922 color: var(--accent-red);
6923 }
6924
6925 .import-warnings {
6926 margin-top: 1rem;
6927 padding: 0.75rem;
6928 background: color-mix(in srgb, var(--accent-yellow) 10%, var(--bg-card));
6929 border: 1px solid var(--accent-yellow);
6930 border-radius: var(--radius-sm);
6931 font-size: var(--font-size-sm);
6932 }
6933
6934 .import-warnings ul {
6935 margin: 0.5rem 0 0 1.25rem;
6936 padding: 0;
6937 }
6938
6939 .import-warnings li {
6940 margin-bottom: 0.25rem;
6941 }
6942
6943 .import-external-types {
6944 display: flex;
6945 gap: 1rem;
6946 margin-bottom: 1.5rem;
6947 }
6948
6949 .import-type-card {
6950 flex: 1;
6951 display: flex;
6952 flex-direction: column;
6953 align-items: center;
6954 gap: 0.5rem;
6955 padding: 1.5rem 1rem;
6956 background: var(--bg-card);
6957 border: 2px solid var(--border-color);
6958 border-radius: var(--radius-md);
6959 cursor: pointer;
6960 transition: border-color 0.15s, background 0.15s;
6961 }
6962
6963 .import-type-card:hover {
6964 border-color: var(--accent-primary);
6965 background: var(--bg-secondary);
6966 }
6967
6968 .import-type-icon {
6969 font-size: 2rem;
6970 }
6971
6972 .import-type-label {
6973 font-weight: 600;
6974 color: var(--text-primary);
6975 }
6976
6977 .import-type-desc {
6978 font-size: var(--font-size-sm);
6979 color: var(--text-muted);
6980 }
6981
6982 /* ===================================================================
6983 54. Plugin Manager
6984 =================================================================== */
6985 .plugin-list {
6986 display: flex;
6987 flex-direction: column;
6988 gap: 0.75rem;
6989 }
6990
6991 .plugin-item {
6992 display: flex;
6993 justify-content: space-between;
6994 align-items: center;
6995 padding: 1rem;
6996 background: var(--bg-card);
6997 border: var(--border-width) solid var(--border-color);
6998 border-radius: var(--radius-md);
6999 }
7000
7001 .plugin-item .plugin-info {
7002 flex: 1;
7003 }
7004
7005 .plugin-item .plugin-name {
7006 font-weight: 600;
7007 }
7008
7009 .plugin-item .plugin-version {
7010 color: var(--text-muted);
7011 font-size: var(--font-size-sm);
7012 margin-left: 0.5rem;
7013 }
7014
7015 .plugin-item .plugin-description {
7016 margin: 0.25rem 0;
7017 color: var(--text-secondary);
7018 font-size: var(--font-size-sm);
7019 }
7020
7021 .plugin-item .plugin-extensions {
7022 font-size: var(--font-size-xs);
7023 color: var(--text-muted);
7024 }
7025
7026 .plugin-item .plugin-actions {
7027 margin-left: 1rem;
7028 }
7029
7030 /* ===================================================================
7031 55. Toggle Switch
7032 =================================================================== */
7033 .toggle-switch {
7034 position: relative;
7035 display: inline-block;
7036 width: 44px;
7037 height: 24px;
7038 }
7039
7040 .toggle-switch input {
7041 opacity: 0;
7042 width: 0;
7043 height: 0;
7044 }
7045
7046 .toggle-slider {
7047 position: absolute;
7048 cursor: pointer;
7049 top: 0;
7050 left: 0;
7051 right: 0;
7052 bottom: 0;
7053 background-color: var(--bg-tertiary);
7054 border: 2px solid var(--border-color);
7055 border-radius: var(--radius-xl);
7056 transition: background-color var(--transition-fast), border-color var(--transition-fast);
7057 }
7058
7059 .toggle-slider:before {
7060 position: absolute;
7061 content: "";
7062 height: 16px;
7063 width: 16px;
7064 left: 2px;
7065 bottom: 2px;
7066 background-color: var(--text-muted);
7067 border-radius: var(--radius-full);
7068 transition: transform var(--transition-fast), background-color var(--transition-fast);
7069 }
7070
7071 .toggle-switch input:checked + .toggle-slider {
7072 background-color: var(--accent-primary);
7073 border-color: var(--accent-primary);
7074 }
7075
7076 .toggle-switch input:checked + .toggle-slider:before {
7077 transform: translateX(20px);
7078 background-color: var(--bg-card);
7079 }
7080
7081 .toggle-switch input:focus + .toggle-slider {
7082 box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-primary) 30%, transparent);
7083 }
7084
7085 /* ===================================================================
7086 56. Project Milestones
7087 =================================================================== */
7088 .milestones-section {
7089 margin-bottom: 1.5rem;
7090 }
7091
7092 .milestones-header {
7093 display: flex;
7094 justify-content: space-between;
7095 align-items: center;
7096 margin-bottom: 1rem;
7097 padding-bottom: 0.5rem;
7098 border-bottom: 2px solid var(--border-color);
7099 }
7100
7101 .milestones-header h3 {
7102 margin: 0;
7103 font-size: 1rem;
7104 font-family: var(--font-heading);
7105 font-weight: 700;
7106 }
7107
7108 .milestone-card {
7109 background: var(--bg-card);
7110 border: var(--border-width) solid var(--border-color);
7111 border-radius: var(--radius-md);
7112 padding: 1rem;
7113 margin-bottom: 0.75rem;
7114 transition: background-color 0.1s;
7115 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
7116 }
7117
7118 .milestone-card:hover {
7119 background: var(--bg-secondary);
7120 }
7121
7122 .milestone-card-header {
7123 display: flex;
7124 justify-content: space-between;
7125 align-items: flex-start;
7126 margin-bottom: 0.5rem;
7127 }
7128
7129 .milestone-card-header h4 {
7130 margin: 0;
7131 font-size: 0.95rem;
7132 font-family: var(--font-heading);
7133 font-weight: 700;
7134 }
7135
7136 .milestone-card-header .milestone-status {
7137 font-size: 0.7rem;
7138 font-weight: 700;
7139 text-transform: uppercase;
7140 padding: 0.15rem 0.4rem;
7141 border-radius: var(--radius-sm);
7142 background: var(--bg-secondary);
7143 color: var(--text-muted);
7144 }
7145
7146 .milestone-card-header .milestone-status.completed {
7147 background: color-mix(in srgb, var(--accent-green) 15%, var(--bg-secondary));
7148 color: var(--accent-green);
7149 }
7150
7151 .milestone-meta {
7152 display: flex;
7153 gap: 1rem;
7154 font-size: 0.8rem;
7155 color: var(--text-muted);
7156 margin-bottom: 0.5rem;
7157 }
7158
7159 .milestone-progress {
7160 height: 6px;
7161 background: var(--bg-secondary);
7162 border-radius: var(--radius-full);
7163 overflow: hidden;
7164 border: var(--border-width-sm) solid var(--border-color);
7165 }
7166
7167 .milestone-progress-fill {
7168 height: 100%;
7169 background: var(--accent-green);
7170 border-radius: var(--radius-full);
7171 transition: width var(--transition-fast);
7172 }
7173
7174 .milestone-actions {
7175 display: flex;
7176 gap: 0.5rem;
7177 margin-top: 0.5rem;
7178 }
7179
7180 .milestone-actions button {
7181 font-size: 0.75rem;
7182 padding: 0.2rem 0.5rem;
7183 background: var(--bg-secondary);
7184 border: var(--border-width-sm) solid var(--border-color);
7185 border-radius: var(--radius-sm);
7186 cursor: pointer;
7187 color: var(--text-secondary);
7188 transition: background var(--transition-fast);
7189 }
7190
7191 .milestone-actions button:hover {
7192 background: var(--bg-hover);
7193 }
7194
7195 .milestone-actions button.danger:hover {
7196 background: color-mix(in srgb, var(--accent-red) 15%, var(--bg-secondary));
7197 color: var(--accent-red);
7198 }
7199
7200 button.milestone-reorder-btn.btn {
7201 font-size: 0.65rem;
7202 padding: 0.15rem 0.35rem;
7203 line-height: 1;
7204 min-width: 1.5rem;
7205 text-align: center;
7206 }
7207
7208 .milestones-completed-section {
7209 margin-top: 0.75rem;
7210 }
7211
7212 .milestones-completed-toggle {
7213 font-size: 0.8rem;
7214 color: var(--text-secondary);
7215 padding: 0.25rem 0;
7216 }
7217
7218 .milestone-card-summary {
7219 padding: 0.5rem 0.75rem;
7220 opacity: 0.7;
7221 }
7222
7223 .milestone-card-summary .milestone-info {
7224 display: flex;
7225 align-items: center;
7226 gap: 0.5rem;
7227 }
7228
7229 .milestone-complete-badge {
7230 font-size: 0.7rem;
7231 font-weight: 700;
7232 padding: 0.1rem 0.4rem;
7233 border-radius: var(--radius-sm);
7234 background: color-mix(in srgb, var(--accent-green) 15%, var(--bg-secondary));
7235 color: var(--accent-green);
7236 }
7237
7238 /* ===================================================================
7239 58. Mobile Navigation (Nav Dot, Dial, Bottom Sheets)
7240 =================================================================== */
7241
7242 /* --- Mobile Tab Bar (hidden on desktop, shown <=768px) --- */
7243 .mobile-tab-bar {
7244 display: none;
7245 position: fixed;
7246 bottom: 0;
7247 left: 0;
7248 right: 0;
7249 z-index: 1100;
7250 background: var(--bg-card);
7251 border-top: var(--border-width) solid var(--border-color);
7252 padding-bottom: env(safe-area-inset-bottom, 0px);
7253 height: calc(52px + env(safe-area-inset-bottom, 0px));
7254 }
7255
7256 .mobile-tab {
7257 flex: 1;
7258 display: flex;
7259 align-items: center;
7260 justify-content: center;
7261 height: 52px;
7262 background: none;
7263 border: none;
7264 color: var(--text-muted);
7265 font-size: 0.7rem;
7266 font-weight: 700;
7267 font-family: var(--font-sans);
7268 text-transform: uppercase;
7269 letter-spacing: 0.05em;
7270 cursor: pointer;
7271 -webkit-tap-highlight-color: transparent;
7272 transition: color 0.15s ease;
7273 }
7274
7275 .mobile-tab.active {
7276 color: var(--accent-blue);
7277 }
7278
7279 .mobile-tab:active {
7280 background: var(--bg-secondary);
7281 }
7282
7283 .mobile-tab-create {
7284 font-size: 1.4rem;
7285 font-weight: 400;
7286 color: var(--accent-green);
7287 letter-spacing: 0;
7288 text-transform: none;
7289 }
7290
7291 /* --- Tab Long-press Slide Menu ---
7292 Anchored above a mobile tab. JS sets left/bottom inline. Origin is
7293 bottom-center so the scale-in reads as "growing up out of the tab". */
7294 .mobile-tab-slide-menu {
7295 position: fixed;
7296 z-index: 1102;
7297 min-width: 140px;
7298 background: var(--bg-card);
7299 border: var(--border-width) solid var(--border-color);
7300 border-radius: var(--radius-md);
7301 box-shadow: var(--shadow-brutal-md);
7302 padding: 0.25rem;
7303 display: flex;
7304 flex-direction: column;
7305 opacity: 0;
7306 transform: scale(0.92);
7307 transform-origin: 50% 100%;
7308 transition: opacity 120ms ease-out, transform 120ms ease-out;
7309 }
7310
7311 .mobile-tab-slide-menu.is-open {
7312 opacity: 1;
7313 transform: scale(1);
7314 }
7315
7316 .mobile-tab-slide-item {
7317 padding: 0.7rem 0.9rem;
7318 min-height: 44px;
7319 display: flex;
7320 align-items: center;
7321 justify-content: center;
7322 font-size: var(--font-size-sm);
7323 font-weight: 700;
7324 text-transform: uppercase;
7325 letter-spacing: 0.05em;
7326 color: var(--text-primary);
7327 border-radius: var(--radius-sm);
7328 transition: background 80ms ease, transform 80ms ease;
7329 }
7330
7331 .mobile-tab-slide-item.is-highlighted {
7332 background: var(--accent-blue);
7333 color: var(--text-on-accent);
7334 transform: scale(1.03);
7335 }
7336
7337 /* --- Action Bottom Sheet --- */
7338 .action-sheet {
7339 position: fixed;
7340 inset: 0;
7341 z-index: 10001;
7342 display: flex;
7343 flex-direction: column;
7344 justify-content: flex-end;
7345 }
7346
7347 .action-sheet.hidden {
7348 display: none;
7349 }
7350
7351 .action-sheet-backdrop {
7352 position: absolute;
7353 inset: 0;
7354 background: rgba(0, 0, 0, 0.4);
7355 }
7356
7357 .action-sheet-container {
7358 position: relative;
7359 background: var(--bg-card);
7360 border-top: var(--border-width) solid var(--border-color);
7361 border-radius: var(--radius-lg) var(--radius-lg) 0 0;
7362 padding: 0.5rem 1rem calc(0.5rem + env(safe-area-inset-bottom, 0px));
7363 max-height: 60vh;
7364 overflow-y: auto;
7365 animation: sheetSlideUp 0.25s ease-out;
7366 }
7367
7368 .action-sheet-handle {
7369 width: 36px;
7370 height: 4px;
7371 border-radius: 2px;
7372 background: var(--text-muted);
7373 margin: 0 auto 0.75rem;
7374 opacity: 0.4;
7375 }
7376
7377 .action-sheet-content button {
7378 display: flex;
7379 align-items: center;
7380 gap: 0.75rem;
7381 width: 100%;
7382 padding: 0.875rem 0.5rem;
7383 background: none;
7384 border: none;
7385 border-bottom: 1px solid var(--bg-secondary);
7386 font-size: var(--font-size-base);
7387 font-weight: 600;
7388 color: var(--text-primary);
7389 text-align: left;
7390 cursor: pointer;
7391 }
7392
7393 .action-sheet-content button:last-child {
7394 border-bottom: none;
7395 }
7396
7397 .action-sheet-content button:active {
7398 background: var(--bg-secondary);
7399 }
7400
7401 .action-sheet-content button.danger {
7402 color: var(--accent-red);
7403 }
7404
7405 .action-sheet-cancel {
7406 display: block;
7407 width: 100%;
7408 padding: 0.875rem;
7409 margin-top: 0.5rem;
7410 background: var(--bg-secondary);
7411 border: var(--border-width-sm) solid var(--border-color);
7412 border-radius: var(--radius-md);
7413 font-size: var(--font-size-base);
7414 font-weight: 700;
7415 color: var(--text-primary);
7416 text-align: center;
7417 cursor: pointer;
7418 }
7419
7420 .action-sheet-cancel:active {
7421 background: var(--bg-tertiary);
7422 }
7423
7424 /* --- Modal Drag Handle (mobile swipe-to-dismiss) --- */
7425 .modal-drag-handle {
7426 display: none;
7427 width: 36px;
7428 height: 4px;
7429 border-radius: 2px;
7430 background: var(--text-muted);
7431 margin: 0.5rem auto 0;
7432 opacity: 0.4;
7433 }
7434
7435 /* --- Mobile Sort Dropdown (replaces clickable column headers) --- */
7436 .mobile-sort-bar {
7437 display: none;
7438 gap: 0.5rem;
7439 padding: 0.5rem 0;
7440 align-items: center;
7441 }
7442
7443 .mobile-sort-bar select {
7444 flex: 1;
7445 font-size: var(--font-size-sm);
7446 }
7447
7448 /* --- Mobile Filter Toggle --- */
7449 .mobile-filter-toggle {
7450 display: none;
7451 }
7452
7453 /* --- Swipe Action Layer --- */
7454 .swipe-actions-container {
7455 position: relative;
7456 overflow: hidden;
7457 }
7458
7459 .swipe-actions-bg {
7460 position: absolute;
7461 top: 0;
7462 bottom: 0;
7463 display: flex;
7464 align-items: center;
7465 padding: 0 1rem;
7466 font-weight: 700;
7467 font-size: var(--font-size-sm);
7468 color: var(--text-on-accent);
7469 }
7470
7471 .swipe-actions-bg.swipe-left {
7472 right: 0;
7473 background: var(--accent-green);
7474 }
7475
7476 .swipe-actions-bg.swipe-right {
7477 left: 0;
7478 background: var(--accent-red);
7479 }
7480
7481 .swipe-content {
7482 position: relative;
7483 background: var(--bg-card);
7484 transition: transform 0.15s ease;
7485 }
7486
7487 /* --- Pull to Refresh --- */
7488 .pull-to-refresh-indicator {
7489 display: none;
7490 text-align: center;
7491 padding: 0.75rem;
7492 font-size: var(--font-size-sm);
7493 color: var(--text-muted);
7494 font-weight: 600;
7495 }
7496
7497 .pull-to-refresh-indicator.visible {
7498 display: block;
7499 }
7500
7501 /* --- Event Date Group Headers (mobile) --- */
7502 .event-date-group-header {
7503 display: none;
7504 }
7505
7506 /* --- Day Plan Collapsible Sidebar (mobile) --- */
7507 .day-plan-sidebar-toggle {
7508 display: none;
7509 }
7510
7511 @keyframes sheetSlideUp {
7512 from { transform: translateY(100%); }
7513 to { transform: translateY(0); }
7514 }
7515
7516 @keyframes sheetSlideDown {
7517 from { transform: translateY(0); }
7518 to { transform: translateY(100%); }
7519 }
7520
7521 @keyframes dialFadeIn {
7522 from { opacity: 0; }
7523 to { opacity: 1; }
7524 }
7525
7526 /* ===================================================================
7527 59. Mobile Responsive (768px overrides)
7528 =================================================================== */
7529
7530 /* --- Safe area padding + room for mobile tab bar --- */
7531 html.ui-mode-mobile, .ui-mode-mobile body {
7532 overflow-x: hidden;
7533 max-width: 100vw;
7534 touch-action: pan-y;
7535 overscroll-behavior-x: none;
7536 }
7537 .ui-mode-mobile body {
7538 padding-top: env(safe-area-inset-top, 0px);
7539 padding-bottom: calc(52px + env(safe-area-inset-bottom, 0px));
7540 padding-left: env(safe-area-inset-left, 0px);
7541 padding-right: env(safe-area-inset-right, 0px);
7542 }
7543 /* Fixed-position UI must extend edge-to-edge under the notch in landscape */
7544 .ui-mode-mobile .mobile-tab-bar,
7545 .ui-mode-mobile .timer-widget {
7546 padding-left: env(safe-area-inset-left, 0px);
7547 padding-right: env(safe-area-inset-right, 0px);
7548 }
7549
7550 .ui-mode-mobile .mobile-tab-bar {
7551 display: flex;
7552 }
7553
7554 /* --- Hide desktop tab navigation --- */
7555 .ui-mode-mobile .tab-navigation {
7556 display: none !important;
7557 }
7558
7559 .ui-mode-mobile .app-header {
7560 display: none;
7561 }
7562
7563 /* Pill nav is replaced on mobile by the bottom tab bar's long-press
7564 slide menu — hide the in-page sub-tab strip. */
7565 .ui-mode-mobile .pill-nav {
7566 display: none;
7567 }
7568
7569 /* === Mobile toolbar grids ===
7570 Toolbar rows become equal-column grids on mobile so children share
7571 the row predictably (no orphans, no ragged wrapping). Search inputs
7572 always span the full grid row. */
7573 .ui-mode-mobile #emails-view > div.row-flex.mb-2,
7574 .ui-mode-mobile #tasks-view .page-header > .row-flex,
7575 .ui-mode-mobile #tasks-view .mobile-sort-bar,
7576 .ui-mode-mobile #contacts-view .page-header > .row-flex {
7577 display: grid;
7578 grid-auto-flow: row;
7579 grid-template-columns: repeat(2, 1fr);
7580 gap: var(--space-2);
7581 align-items: center;
7582 }
7583
7584 /* Tasks page-header: Quick Add + New Task are hidden on mobile (see
7585 .mobile-hide / .btn-primary rules), so only the view-toggle remains
7586 and takes the full row. */
7587 .ui-mode-mobile #tasks-view .page-header > .row-flex {
7588 grid-template-columns: 1fr;
7589 }
7590
7591 /* Mobile-hide utility: marker class on controls that don't belong in
7592 the mobile layout (Drafts, Quick Add). Surfaced elsewhere instead
7593 (slide menu, bottom bar). */
7594 .ui-mode-mobile .mobile-hide {
7595 display: none !important;
7596 }
7597
7598 /* Status badges in the day/week/month page-headers are informational
7599 and visible inside their respective review subviews anyway. */
7600 .ui-mode-mobile #day-review-status-badge,
7601 .ui-mode-mobile #week-review-status-badge,
7602 .ui-mode-mobile #month-review-status-badge {
7603 display: none !important;
7604 }
7605
7606 /* Day-plan timeline: drag-paint and its hint don't apply on mobile —
7607 tap-to-add is the touch path. Suppress the hover affordance and
7608 grab cursor too. */
7609 .ui-mode-mobile #day-plan-view .timeline-hint {
7610 display: none;
7611 }
7612 .ui-mode-mobile #day-plan-view .timeline-slot-area {
7613 cursor: default;
7614 }
7615 .ui-mode-mobile #day-plan-view .timeline-slot-area:hover {
7616 background: transparent;
7617 }
7618
7619 /* Day-plan nav: keep ← Today → + date input on one row when there's
7620 width; wrap the date input below only if the row would overflow.
7621 The inline date-display span is redundant with the date input. */
7622 .ui-mode-mobile #day-plan-view .day-plan-nav {
7623 display: flex;
7624 flex-wrap: wrap;
7625 column-gap: var(--space-2);
7626 row-gap: var(--space-3);
7627 align-items: center;
7628 }
7629 /* Restore per-button borders/radii — the desktop segmented-strip rule
7630 (no right border, square corners) doesn't apply here on mobile. */
7631 .ui-mode-mobile #day-plan-view .day-plan-nav .btn {
7632 flex: 0 0 auto;
7633 border-radius: var(--radius-sm);
7634 border-right-width: var(--border-width);
7635 }
7636 .ui-mode-mobile #day-plan-view .day-plan-nav .day-plan-date-picker {
7637 flex: 1 1 120px;
7638 min-width: 0;
7639 }
7640 .ui-mode-mobile #day-plan-view .day-plan-date-display {
7641 display: none;
7642 }
7643
7644 /* Search inputs always span the full grid row. */
7645 .ui-mode-mobile #email-search,
7646 .ui-mode-mobile #contacts-search {
7647 grid-column: 1 / -1;
7648 width: 100%;
7649 min-width: 0;
7650 }
7651
7652 /* The email-count span ("48 threads") is inside the grid row — hide
7653 on mobile; will get a tidier home in layer-2 trims. */
7654 .ui-mode-mobile #email-count {
7655 display: none;
7656 }
7657
7658 /* Inside the new grid cells, undo the segmented-button styling (no
7659 right border, square corners) inherited from the desktop page-header
7660 rule — grid already gives equal sizing. */
7661 .ui-mode-mobile #tasks-view .page-header > .row-flex .btn,
7662 .ui-mode-mobile #contacts-view .page-header > .row-flex .btn {
7663 border-radius: var(--radius-sm);
7664 border-right-width: var(--border-width);
7665 }
7666
7667 /* View-toggle inside the tasks grid should fill its cell. */
7668 .ui-mode-mobile #tasks-view .page-header .view-toggle {
7669 display: flex;
7670 width: 100%;
7671 }
7672 .ui-mode-mobile #tasks-view .page-header .view-toggle .view-toggle-btn {
7673 flex: 1 1 0;
7674 }
7675
7676 /* Undo absolute positioning on mobile — page-header buttons are hidden anyway */
7677 .ui-mode-mobile .tab-group > .subview > .page-header {
7678 position: static;
7679 }
7680
7681 /* --- Main content adjustments --- */
7682 .ui-mode-mobile .main-content {
7683 padding: 0.75rem;
7684 }
7685
7686 .ui-mode-mobile .page-header {
7687 flex-wrap: wrap;
7688 gap: 0.5rem;
7689 }
7690
7691 .ui-mode-mobile .page-header .btn-primary {
7692 display: none;
7693 }
7694
7695 .ui-mode-mobile .page-title {
7696 display: none;
7697 }
7698
7699 /* Compact toolbar buttons: collapse into a single segmented block so the
7700 button text has more room without crowding the row. Stretch each segment
7701 to share row width so the block reads as one unified control. */
7702 .ui-mode-mobile .page-header > div,
7703 .ui-mode-mobile #emails-view .page-header > div,
7704 .ui-mode-mobile #contacts-view .page-header > div {
7705 gap: 0 !important;
7706 flex-wrap: wrap;
7707 }
7708 .ui-mode-mobile .page-header > div .btn,
7709 .ui-mode-mobile #emails-view .page-header > div .btn,
7710 .ui-mode-mobile #contacts-view .page-header > div .btn,
7711 .ui-mode-mobile .bulk-actions-bar .btn {
7712 flex: 1 1 0;
7713 min-width: 0;
7714 padding: 0.4rem 0.5rem;
7715 font-size: 0.75rem;
7716 border-radius: 0;
7717 border-right-width: 0;
7718 white-space: nowrap;
7719 }
7720 .ui-mode-mobile .page-header > div .btn:first-child,
7721 .ui-mode-mobile #emails-view .page-header > div .btn:first-child,
7722 .ui-mode-mobile #contacts-view .page-header > div .btn:first-child,
7723 .ui-mode-mobile .bulk-actions-bar .btn:first-of-type {
7724 border-top-left-radius: var(--radius-sm);
7725 border-bottom-left-radius: var(--radius-sm);
7726 }
7727 /* Right-cap the visually-last button. `.btn-primary` (Compose) is hidden
7728 on mobile via display:none but stays in the DOM, so `:last-child` would
7729 pick the hidden one. Cover both: actual last child, or the button
7730 immediately before a hidden primary. */
7731 .ui-mode-mobile .page-header > div .btn:last-child,
7732 .ui-mode-mobile .page-header > div .btn:has(+ .btn-primary),
7733 .ui-mode-mobile #emails-view .page-header > div .btn:last-child,
7734 .ui-mode-mobile #emails-view .page-header > div .btn:has(+ .btn-primary),
7735 .ui-mode-mobile #contacts-view .page-header > div .btn:last-child,
7736 .ui-mode-mobile #contacts-view .page-header > div .btn:has(+ .btn-primary) {
7737 border-top-right-radius: var(--radius-sm);
7738 border-bottom-right-radius: var(--radius-sm);
7739 border-right-width: var(--border-width);
7740 }
7741 /* Bulk-actions: 4 contiguous buttons form a block; bulk-select-all is
7742 pushed right by margin-left:auto so it stays standalone. */
7743 .ui-mode-mobile .bulk-actions-bar {
7744 gap: 0;
7745 }
7746 .ui-mode-mobile .bulk-actions-bar .bulk-count {
7747 margin-right: 0.5rem;
7748 }
7749 .ui-mode-mobile .bulk-actions-bar .btn:not(.bulk-select-all) + .bulk-select-all {
7750 border-right-width: var(--border-width);
7751 border-radius: var(--radius-sm);
7752 }
7753 .ui-mode-mobile .bulk-actions-bar .btn:not(.bulk-select-all):nth-last-of-type(2) {
7754 border-top-right-radius: var(--radius-sm);
7755 border-bottom-right-radius: var(--radius-sm);
7756 border-right-width: var(--border-width);
7757 }
7758 .ui-mode-mobile .bulk-select-all {
7759 margin-left: auto;
7760 }
7761
7762 /* Email filter row: let selects shrink and wrap instead of forcing 120px. */
7763 .ui-mode-mobile #emails-view .form-select[id^="email-"] {
7764 min-width: 0 !important;
7765 flex: 1;
7766 }
7767
7768 /* Compact form controls. Keep font-size at 1rem (16px) — iOS Safari/WKWebView
7769 auto-zooms when a focused input is below 16px. Only shave padding. */
7770 .ui-mode-mobile .form-input,
7771 .ui-mode-mobile .form-select,
7772 .ui-mode-mobile .form-textarea {
7773 padding: 0.45rem 0.65rem;
7774 }
7775 .ui-mode-mobile .form-textarea {
7776 min-height: 72px;
7777 }
7778 .ui-mode-mobile .form-group {
7779 margin-bottom: 0.75rem;
7780 }
7781 .ui-mode-mobile .form-label {
7782 margin-bottom: 0.25rem;
7783 }
7784 .ui-mode-mobile .form-actions {
7785 gap: 0.5rem;
7786 margin-top: 1rem;
7787 }
7788 .ui-mode-mobile .quick-add-input {
7789 padding: 0.55rem 0.75rem;
7790 }
7791 .ui-mode-mobile .quick-add {
7792 gap: 0.5rem;
7793 margin-bottom: 1rem;
7794 }
7795
7796 /* Snooze + bulk-modal option rows (date/snooze pickers) — tighten the
7797 generous stacked-row padding so more options fit above the keyboard. */
7798 .ui-mode-mobile .snooze-option,
7799 .ui-mode-mobile .bulk-modal-option-btn {
7800 padding: 0.55rem 0.75rem;
7801 }
7802 .ui-mode-mobile .snooze-options {
7803 gap: 0.35rem;
7804 }
7805
7806 /* Modal chrome: trim header + content padding so date/snooze/compose
7807 modals reclaim ~24px of vertical room above the keyboard. */
7808 .ui-mode-mobile .modal-header {
7809 padding: 0.6rem 0.9rem;
7810 }
7811 .ui-mode-mobile .modal-header h2, .ui-mode-mobile .modal-title {
7812 font-size: 1.05rem;
7813 }
7814 .ui-mode-mobile .modal-content {
7815 padding: 0.9rem;
7816 }
7817 .ui-mode-mobile .modal-content > .form-actions:last-child,
7818 .ui-mode-mobile .modal-content form > .form-actions:last-child {
7819 margin-top: 0.9rem;
7820 padding-top: 0.5rem;
7821 }
7822
7823 /* --- Modal → Bottom Sheet --- */
7824 /* Lift the entire overlay above the mobile tab bar so bottom-sheet modals
7825 and their content aren't clipped behind it. */
7826 .ui-mode-mobile .modal-overlay {
7827 align-items: flex-end;
7828 bottom: calc(52px + env(safe-area-inset-bottom, 0px));
7829 }
7830
7831 .ui-mode-mobile .modal-container {
7832 width: 100% !important;
7833 max-width: 100% !important;
7834 max-height: calc(100vh - 52px - env(safe-area-inset-bottom, 0px) - env(safe-area-inset-top, 0px));
7835 border-radius: var(--radius-lg) var(--radius-lg) 0 0;
7836 margin: 0;
7837 border-bottom: none;
7838 padding-bottom: 0;
7839 }
7840
7841 .ui-mode-mobile .modal-container.modal-large {
7842 max-width: 100% !important;
7843 width: 100% !important;
7844 max-height: calc(100vh - 52px - env(safe-area-inset-bottom, 0px) - env(safe-area-inset-top, 0px));
7845 border-radius: var(--radius-lg) var(--radius-lg) 0 0;
7846 }
7847
7848 .ui-mode-mobile .modal-drag-handle {
7849 display: block;
7850 }
7851
7852 .ui-mode-mobile .modal-header {
7853 padding: 0.75rem 1rem;
7854 }
7855
7856 .ui-mode-mobile .modal-content {
7857 padding: 1rem;
7858 }
7859
7860 /* Mobile uses different modal animations (slide up/down from bottom rather
7861 than fade-and-scale). @keyframes can't be scoped — defined globally under
7862 distinct names and applied via animation-name override below. */
7863 @keyframes modalSlideInMobile {
7864 from { transform: translateY(100%); }
7865 to { transform: translateY(0); }
7866 }
7867
7868 @keyframes modalSlideOutMobile {
7869 from { transform: translateY(0); }
7870 to { transform: translateY(100%); }
7871 }
7872
7873 .ui-mode-mobile .modal-container {
7874 animation-name: modalSlideInMobile;
7875 }
7876 .ui-mode-mobile .modal-overlay.closing .modal-container {
7877 animation-name: modalSlideOutMobile;
7878 }
7879
7880 /* --- Toast repositioning for mobile --- */
7881 .ui-mode-mobile .toast,
7882 .ui-mode-mobile .toast-undo {
7883 bottom: calc(env(safe-area-inset-bottom, 0px) + 4.5rem) !important;
7884 left: 1rem !important;
7885 right: 1rem !important;
7886 max-width: none !important;
7887 }
7888
7889 /* --- Task View: Card Reflow --- */
7890 .ui-mode-mobile .task-table {
7891 border: none;
7892 box-shadow: none;
7893 background: transparent;
7894 }
7895
7896 .ui-mode-mobile .task-header-row {
7897 display: none !important;
7898 }
7899
7900 .ui-mode-mobile .task-row {
7901 display: flex !important;
7902 flex-direction: column;
7903 gap: 0.25rem;
7904 padding: 0.75rem 1rem;
7905 margin-bottom: 0.5rem;
7906 background: var(--bg-card);
7907 border: var(--border-width-sm) solid var(--border-color);
7908 border-radius: var(--radius-md);
7909 border-left: 4px solid var(--text-muted);
7910 }
7911
7912 .ui-mode-mobile .task-row.task-pending { border-left-color: var(--text-muted); }
7913 .ui-mode-mobile .task-row .task-cell.priority-h ~ .task-cell:first-child,
7914 .ui-mode-mobile .task-row:has(.priority-h) { border-left-color: var(--accent-red); }
7915 .ui-mode-mobile .task-row:has(.priority-m) { border-left-color: var(--accent-yellow); }
7916 .ui-mode-mobile .task-row:has(.priority-l) { border-left-color: var(--text-muted); }
7917
7918 .ui-mode-mobile .task-row .task-cell {
7919 display: flex !important;
7920 overflow: visible;
7921 padding: 0;
7922 }
7923
7924 .ui-mode-mobile .task-cell.task-description {
7925 font-weight: 600;
7926 font-size: var(--font-size-base);
7927 }
7928
7929 .ui-mode-mobile .task-cell.task-project,
7930 .ui-mode-mobile .task-cell.task-due {
7931 font-size: var(--font-size-sm);
7932 color: var(--text-secondary);
7933 }
7934
7935 /* Show project and due inline */
7936 .ui-mode-mobile .task-row .task-cell.task-project::before {
7937 content: none;
7938 }
7939
7940 /* Hide priority letter (shown via left border color), recurrence, progress columns */
7941 .ui-mode-mobile .task-row .task-cell:nth-child(3),
7942 .ui-mode-mobile .task-cell.task-recurrence,
7943 .ui-mode-mobile .task-cell.task-progress {
7944 display: none !important;
7945 }
7946
7947 /* Task meta row: project + due side-by-side */
7948 .ui-mode-mobile .task-cell.task-project {
7949 order: 2;
7950 }
7951 .ui-mode-mobile .task-cell.task-due {
7952 order: 3;
7953 }
7954 .ui-mode-mobile .task-cell.task-description {
7955 order: 1;
7956 }
7957 .ui-mode-mobile .task-cell.task-actions-cell {
7958 order: 4;
7959 justify-content: flex-end;
7960 }
7961
7962 /* Show subtask progress inline if present */
7963 .ui-mode-mobile .task-cell.task-progress:has(.progress-bar-container) {
7964 display: flex !important;
7965 order: 5;
7966 }
7967
7968 .ui-mode-mobile .task-actions-cell .bulk-checkbox {
7969 display: none;
7970 }
7971
7972 .ui-mode-mobile .kebab-btn {
7973 opacity: 1;
7974 }
7975
7976 /* --- Mobile Sort & Filter --- */
7977 .ui-mode-mobile .mobile-sort-bar {
7978 display: flex;
7979 }
7980
7981 .ui-mode-mobile .mobile-filter-toggle {
7982 display: inline-flex;
7983 align-items: center;
7984 gap: 0.25rem;
7985 padding: 0.5rem 0.75rem;
7986 background: var(--bg-card);
7987 border: var(--border-width-sm) solid var(--border-color);
7988 border-radius: var(--radius-sm);
7989 font-size: var(--font-size-sm);
7990 font-weight: 600;
7991 cursor: pointer;
7992 }
7993
7994 .ui-mode-mobile .filter-bar {
7995 display: none !important;
7996 }
7997
7998 .ui-mode-mobile .filter-bar.mobile-visible {
7999 display: flex !important;
8000 flex-direction: column;
8001 position: fixed;
8002 bottom: calc(52px + env(safe-area-inset-bottom, 0px));
8003 left: 0;
8004 right: 0;
8005 background: var(--bg-card);
8006 border-top: var(--border-width) solid var(--border-color);
8007 border-radius: var(--radius-lg) var(--radius-lg) 0 0;
8008 padding: 1rem;
8009 z-index: 1050;
8010 box-shadow: 0 -4px 12px rgba(0,0,0,0.1);
8011 }
8012
8013 /* --- Events View: List Reflow --- */
8014 .ui-mode-mobile .event-header-row {
8015 display: none !important;
8016 }
8017
8018 .ui-mode-mobile .event-row-virtual {
8019 display: flex !important;
8020 flex-direction: column;
8021 gap: 0.125rem;
8022 padding: 0.75rem 1rem;
8023 border-bottom: 1px solid var(--bg-secondary);
8024 }
8025
8026 .ui-mode-mobile .event-cell-date {
8027 font-weight: 700;
8028 font-size: var(--font-size-sm);
8029 color: var(--text-secondary);
8030 }
8031
8032 .ui-mode-mobile .event-cell-time {
8033 font-size: var(--font-size-sm);
8034 color: var(--text-muted);
8035 }
8036
8037 .ui-mode-mobile .event-cell-title {
8038 font-weight: 600;
8039 font-size: var(--font-size-base);
8040 }
8041
8042 .ui-mode-mobile .event-cell-location {
8043 font-size: var(--font-size-sm);
8044 color: var(--text-secondary);
8045 }
8046
8047 .ui-mode-mobile .event-date-group-header {
8048 display: flex;
8049 position: sticky;
8050 top: 0;
8051 z-index: 5;
8052 padding: 0.5rem 1rem;
8053 background: var(--bg-secondary);
8054 font-weight: 700;
8055 font-size: var(--font-size-sm);
8056 text-transform: uppercase;
8057 letter-spacing: 0.05em;
8058 color: var(--text-primary);
8059 border-bottom: var(--border-width-sm) solid var(--border-color);
8060 }
8061
8062 /* --- Emails: Tighter mobile layout --- */
8063 .ui-mode-mobile .email-item {
8064 padding: 0.625rem 0.75rem;
8065 }
8066
8067 .ui-mode-mobile .email-from {
8068 font-size: var(--font-size-sm);
8069 }
8070
8071 .ui-mode-mobile .email-subject {
8072 font-size: var(--font-size-base);
8073 }
8074
8075 .ui-mode-mobile .email-preview {
8076 display: none;
8077 }
8078
8079 .ui-mode-mobile .email-date {
8080 font-size: var(--font-size-xs);
8081 }
8082
8083 .ui-mode-mobile .email-item .bulk-checkbox {
8084 display: none;
8085 }
8086
8087 /* --- Day Plan --- */
8088 .ui-mode-mobile .day-plan-content {
8089 flex-direction: column;
8090 }
8091
8092 .ui-mode-mobile .day-plan-sidebar {
8093 width: 100%;
8094 max-height: none;
8095 border-top: var(--border-width-sm) solid var(--border-color);
8096 order: 2;
8097 }
8098
8099 .ui-mode-mobile .day-plan-sidebar.collapsed .sidebar-task-list {
8100 display: none;
8101 }
8102
8103 .ui-mode-mobile .day-plan-sidebar-toggle {
8104 display: flex;
8105 align-items: center;
8106 justify-content: space-between;
8107 width: 100%;
8108 padding: 0.625rem 0.75rem;
8109 background: var(--bg-secondary);
8110 border: none;
8111 border-bottom: 1px solid var(--border-color);
8112 font-size: var(--font-size-sm);
8113 font-weight: 700;
8114 cursor: pointer;
8115 color: var(--text-primary);
8116 }
8117
8118 .ui-mode-mobile .day-plan-main {
8119 order: 1;
8120 }
8121
8122 .ui-mode-mobile .day-plan-nav {
8123 flex-wrap: wrap;
8124 gap: 0.25rem;
8125 }
8126
8127 /* --- Weekly Review --- */
8128 .ui-mode-mobile .weekly-review-content {
8129 padding: 0;
8130 }
8131
8132 /* --- Monthly Review --- */
8133 .ui-mode-mobile .monthly-review-content {
8134 padding: 0;
8135 }
8136
8137 /* --- Review textareas: auto-grow friendly --- */
8138 .ui-mode-mobile .month-reflection-textarea,
8139 .ui-mode-mobile .prompt-input {
8140 resize: none;
8141 overflow: hidden;
8142 }
8143
8144 .ui-mode-mobile .monthly-review-nav {
8145 flex-wrap: wrap;
8146 gap: 0.25rem;
8147 }
8148
8149 .ui-mode-mobile .monthly-review-month-display {
8150 font-size: 1rem;
8151 }
8152
8153 /* --- Day Summary Sheet --- */
8154 .ui-mode-mobile .day-summary-sheet {
8155 padding: 0.5rem 0;
8156 }
8157
8158 .ui-mode-mobile .day-summary-date {
8159 font-size: 1rem;
8160 font-weight: 700;
8161 margin-bottom: 0.75rem;
8162 color: var(--text-primary);
8163 }
8164
8165 .ui-mode-mobile .day-summary-stats {
8166 display: flex;
8167 gap: 0.5rem;
8168 margin-bottom: 1rem;
8169 }
8170
8171 .ui-mode-mobile .day-summary-chip {
8172 padding: 0.25rem 0.75rem;
8173 background: var(--bg-secondary);
8174 border-radius: var(--radius-sm);
8175 font-size: var(--font-size-sm);
8176 font-weight: 600;
8177 color: var(--text-secondary);
8178 }
8179
8180 .ui-mode-mobile .day-summary-list {
8181 list-style: none;
8182 padding: 0;
8183 margin: 0 0 1rem 0;
8184 }
8185
8186 .ui-mode-mobile .day-summary-item {
8187 padding: 0.5rem 0;
8188 border-bottom: 1px solid var(--bg-secondary);
8189 font-size: var(--font-size-sm);
8190 color: var(--text-primary);
8191 }
8192
8193 .ui-mode-mobile .day-summary-time {
8194 font-weight: 600;
8195 color: var(--text-secondary);
8196 margin-right: 0.5rem;
8197 }
8198
8199 .ui-mode-mobile .day-summary-more {
8200 color: var(--text-muted);
8201 font-style: italic;
8202 }
8203
8204 .ui-mode-mobile .day-summary-empty {
8205 color: var(--text-muted);
8206 font-size: var(--font-size-sm);
8207 margin: 0.5rem 0 1rem;
8208 }
8209
8210 .ui-mode-mobile .day-summary-go-btn {
8211 width: 100%;
8212 margin-top: 0.5rem;
8213 }
8214
8215 /* --- Bulk Actions --- */
8216 .ui-mode-mobile .bulk-actions-bar {
8217 position: fixed;
8218 bottom: calc(52px + env(safe-area-inset-bottom, 0px));
8219 left: 0;
8220 right: 0;
8221 z-index: 1050;
8222 border-radius: var(--radius-lg) var(--radius-lg) 0 0;
8223 box-shadow: 0 -4px 12px rgba(0,0,0,0.15);
8224 }
8225
8226 /* --- Pagination --- */
8227 .ui-mode-mobile .pagination-controls {
8228 padding: 0.5rem;
8229 }
8230
8231 .ui-mode-mobile .pagination-controls .btn {
8232 padding: 0.5rem 0.75rem;
8233 font-size: var(--font-size-sm);
8234 }
8235
8236
8237 /* ===================================================================
8238 60. Touch Device Hover Disable
8239 =================================================================== */
8240
8241 @media (hover: none) {
8242 .task-row:hover {
8243 background-color: transparent;
8244 }
8245
8246 .task-row-clickable:hover {
8247 background: transparent;
8248 }
8249
8250 .event-row-virtual:hover {
8251 background-color: transparent;
8252 }
8253
8254 .email-item:hover {
8255 background-color: transparent;
8256 }
8257
8258 .card:hover {
8259 background-color: var(--bg-card);
8260 transform: none;
8261 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
8262 }
8263
8264 .btn:hover {
8265 background: var(--bg-card);
8266 }
8267
8268 .btn-primary:hover {
8269 background-color: var(--accent-blue);
8270 }
8271
8272 .btn-danger:hover {
8273 background-color: var(--accent-red);
8274 }
8275
8276 .card:hover {
8277 background-color: var(--bg-card);
8278 transform: none;
8279 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
8280 }
8281
8282 .kanban-card:hover {
8283 background: var(--bg-card);
8284 transform: none;
8285 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
8286 }
8287
8288 .saved-view-item:hover {
8289 background: var(--bg-card);
8290 color: var(--text-primary);
8291 transform: none;
8292 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
8293 }
8294
8295 .context-menu-item:hover {
8296 background: transparent;
8297 color: var(--text-primary);
8298 }
8299
8300 .modal-close:hover {
8301 background: var(--bg-card);
8302 color: var(--text-primary);
8303 }
8304
8305 .month-heatmap-cell:hover {
8306 background: transparent;
8307 transform: none;
8308 }
8309
8310 /* Row-action kebabs are hover-revealed on desktop; on touch always show them */
8311 .task-row .kebab-btn,
8312 .email-item .kebab-btn,
8313 .event-row-virtual .kebab-btn {
8314 opacity: 1;
8315 }
8316
8317 /* No physical keyboard on touch — hide the `?` shortcuts entry points */
8318 .shortcut-hint-btn {
8319 display: none;
8320 }
8321
8322 /* Stack the time-block picker and presets vertically; enforce 44px touch targets */
8323 .time-block-quick-options {
8324 grid-template-columns: 1fr;
8325 }
8326 .time-block-quick-btn,
8327 .duration-preset {
8328 min-height: 44px;
8329 padding: 0.75rem;
8330 font-size: 1rem;
8331 }
8332 }
8333
8334 /* Touch-device body class (set by touch.js) — equivalent guards for browsers
8335 that report (hover: hover) but are still touch-first (e.g. some Chromebooks). */
8336 body.is-touch .task-row .kebab-btn,
8337 body.is-touch .email-item .kebab-btn,
8338 body.is-touch .event-row-virtual .kebab-btn {
8339 opacity: 1;
8340 }
8341 body.is-touch .shortcut-hint-btn {
8342 display: none;
8343 }
8344
8345 /* ===================================================================
8346 61. Kanban Board
8347 =================================================================== */
8348
8349 /* View Toggle */
8350 .view-toggle {
8351 display: flex;
8352 gap: 0;
8353 margin-left: auto;
8354 }
8355
8356 .view-toggle-btn {
8357 padding: 0.35rem 0.75rem;
8358 border: var(--border-width-sm) solid var(--border-color);
8359 background: var(--bg-secondary);
8360 font-family: var(--font-body);
8361 font-size: var(--font-size-md);
8362 cursor: pointer;
8363 transition: background var(--transition-fast), box-shadow var(--transition-fast);
8364 }
8365
8366 .view-toggle-btn.active {
8367 background: var(--bg-card);
8368 font-weight: 600;
8369 }
8370
8371 .view-toggle-btn:first-child { border-radius: var(--radius-xs) 0 0 var(--radius-xs); }
8372 .view-toggle-btn:last-child { border-radius: 0 var(--radius-xs) var(--radius-xs) 0; border-left: none; }
8373
8374 /* Kanban Board */
8375 .kanban-board {
8376 display: grid;
8377 grid-template-columns: repeat(3, 1fr);
8378 gap: 1rem;
8379 padding: 0.5rem 0;
8380 min-height: 400px;
8381 }
8382
8383 .kanban-column {
8384 background: var(--bg-card);
8385 border: var(--border-width) solid var(--border-color);
8386 display: flex;
8387 flex-direction: column;
8388 min-height: 300px;
8389 max-height: calc(100vh - 200px);
8390 }
8391
8392 .kanban-column-header {
8393 padding: 0.75rem 1rem;
8394 border-bottom: 2px solid var(--border-color);
8395 font-family: var(--font-heading);
8396 font-weight: 700;
8397 display: flex;
8398 justify-content: space-between;
8399 align-items: center;
8400 }
8401
8402 .kanban-column-count {
8403 font-family: var(--font-body);
8404 font-size: var(--font-size-sm);
8405 color: var(--text-secondary);
8406 }
8407
8408 .kanban-column-body {
8409 flex: 1;
8410 overflow-y: auto;
8411 padding: 0.5rem;
8412 display: flex;
8413 flex-direction: column;
8414 gap: 0.5rem;
8415 }
8416
8417 .kanban-column.drag-over {
8418 background-color: var(--bg-tertiary);
8419 }
8420
8421 /* Kanban Cards — marker class for kanban-specific scoping. Callsites compose
8422 `.card .kanban-card`; chrome + hover transform inherit from .card. Deltas:
8423 thinner border, square corners, tighter padding, grab cursor, priority
8424 left-border hook. */
8425 .kanban-card {
8426 padding: 0.75rem;
8427 border-width: var(--border-width-sm);
8428 border-radius: 0;
8429 cursor: grab;
8430 border-left: 4px solid transparent;
8431 }
8432
8433 .kanban-card.dragging { opacity: 0.5; cursor: grabbing; }
8434 .kanban-card.priority-high { border-left-color: var(--accent-red); }
8435 .kanban-card.priority-medium { border-left-color: var(--accent-yellow); }
8436 .kanban-card.priority-low { border-left-color: var(--accent-green); }
8437
8438 .kanban-card-title { font-weight: 600; margin-bottom: 0.25rem; }
8439 .kanban-card-meta { font-size: var(--font-size-sm); color: var(--text-secondary); display: flex; gap: 0.5rem; flex-wrap: wrap; }
8440 .kanban-card-due.overdue { color: var(--accent-red); font-weight: 600; }
8441
8442 .progress-bar-mini { height: 3px; background: var(--bg-tertiary); border-radius: 2px; margin-top: 0.5rem; }
8443 .progress-bar-mini .progress-fill { height: 100%; background: var(--accent-green); border-radius: 2px; }
8444
8445 /* Kanban Responsive */
8446 .ui-mode-mobile .kanban-board { grid-template-columns: 1fr; }
8447 .ui-mode-mobile .kanban-column { max-height: none; }
8448
8449
8450 /* ===================================================================
8451 62. Timer Widget (Floating Bottom Bar)
8452 =================================================================== */
8453
8454 .timer-widget {
8455 position: fixed;
8456 bottom: 0;
8457 left: 0;
8458 right: 0;
8459 z-index: 900;
8460 background: var(--bg-primary);
8461 border-top: var(--border-width) solid var(--border-color);
8462 box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
8463 padding: 0.5rem 1rem;
8464 transition: transform 0.2s ease;
8465 }
8466
8467 .timer-widget.hidden {
8468 transform: translateY(100%);
8469 pointer-events: none;
8470 }
8471
8472 .timer-widget-inner {
8473 display: flex;
8474 align-items: center;
8475 gap: 1rem;
8476 max-width: 800px;
8477 margin: 0 auto;
8478 }
8479
8480 .timer-task-name {
8481 flex: 1;
8482 font-weight: 600;
8483 overflow: hidden;
8484 text-overflow: ellipsis;
8485 white-space: nowrap;
8486 }
8487
8488 .timer-elapsed {
8489 font-family: var(--font-mono, monospace);
8490 font-size: 1.125rem;
8491 font-weight: 700;
8492 color: var(--accent-color);
8493 min-width: 5rem;
8494 text-align: center;
8495 }
8496
8497 .timer-actions {
8498 display: flex;
8499 gap: 0.5rem;
8500 }
8501
8502 /* ===================================================================
8503 63. Focus Timer (Pomodoro Overlay)
8504 =================================================================== */
8505
8506 .focus-overlay {
8507 position: fixed;
8508 inset: 0;
8509 z-index: 1000;
8510 background: var(--bg-primary);
8511 display: flex;
8512 align-items: center;
8513 justify-content: center;
8514 transition: opacity 0.3s ease;
8515 }
8516
8517 .focus-overlay.hidden {
8518 opacity: 0;
8519 pointer-events: none;
8520 }
8521
8522 .focus-overlay-content {
8523 text-align: center;
8524 max-width: 400px;
8525 width: 100%;
8526 padding: 2rem;
8527 }
8528
8529 .focus-header {
8530 display: flex;
8531 align-items: center;
8532 justify-content: space-between;
8533 margin-bottom: 2rem;
8534 }
8535
8536 .focus-label {
8537 font-family: var(--font-heading);
8538 font-size: 1.25rem;
8539 font-weight: 700;
8540 }
8541
8542 .focus-presets {
8543 display: flex;
8544 gap: 0.5rem;
8545 }
8546
8547 .focus-preset-btn.active {
8548 background: var(--accent-color);
8549 color: var(--bg-primary);
8550 border-color: var(--accent-color);
8551 }
8552
8553 .focus-countdown {
8554 font-family: var(--font-mono, monospace);
8555 font-size: 4rem;
8556 font-weight: 700;
8557 line-height: 1;
8558 margin-bottom: 1.5rem;
8559 color: var(--text-primary);
8560 }
8561
8562 .focus-progress-bar {
8563 height: 6px;
8564 background: var(--bg-tertiary);
8565 border-radius: 3px;
8566 margin-bottom: 1.5rem;
8567 overflow: hidden;
8568 }
8569
8570 .focus-progress-fill {
8571 height: 100%;
8572 background: var(--accent-color);
8573 border-radius: 3px;
8574 transition: width 1s linear;
8575 }
8576
8577 .focus-task-name {
8578 color: var(--text-secondary);
8579 margin-bottom: 2rem;
8580 font-size: 0.9rem;
8581 }
8582
8583 .focus-actions {
8584 display: flex;
8585 gap: 1rem;
8586 justify-content: center;
8587 }
8588
8589 /* ===================================================================
8590 64. Time Summary Panel (Day View)
8591 =================================================================== */
8592
8593 .time-summary-section {
8594 margin-bottom: 1rem;
8595 }
8596
8597 .time-summary-toggle {
8598 display: flex;
8599 align-items: center;
8600 gap: 0.5rem;
8601 width: 100%;
8602 padding: 0.5rem;
8603 background: none;
8604 border: none;
8605 font-family: var(--font-heading);
8606 font-size: 0.875rem;
8607 font-weight: 700;
8608 color: var(--text-primary);
8609 cursor: pointer;
8610 text-align: left;
8611 }
8612
8613 .time-summary-toggle:hover {
8614 color: var(--accent-color);
8615 }
8616
8617 .time-summary-toggle-icon {
8618 font-size: 0.625rem;
8619 transition: transform 0.15s ease;
8620 }
8621
8622 .time-summary-body {
8623 padding: 0.5rem;
8624 overflow: hidden;
8625 transition: max-height 0.2s ease;
8626 max-height: 500px;
8627 }
8628
8629 .time-summary-body.collapsed {
8630 max-height: 0;
8631 padding: 0 0.5rem;
8632 }
8633
8634 .time-summary-today {
8635 display: flex;
8636 justify-content: space-between;
8637 align-items: center;
8638 padding: 0.5rem 0;
8639 border-bottom: 1px solid var(--border-color);
8640 margin-bottom: 0.5rem;
8641 }
8642
8643 .time-summary-today-label {
8644 font-weight: 600;
8645 font-size: 0.875rem;
8646 }
8647
8648 .time-summary-today-value {
8649 font-family: var(--font-mono, monospace);
8650 font-weight: 700;
8651 font-size: 1rem;
8652 color: var(--accent-color);
8653 }
8654
8655 .time-summary-week-header {
8656 font-size: 0.75rem;
8657 font-weight: 700;
8658 text-transform: uppercase;
8659 letter-spacing: 0.05em;
8660 color: var(--text-secondary);
8661 margin-bottom: 0.5rem;
8662 }
8663
8664 .time-summary-project {
8665 margin-bottom: 0.5rem;
8666 }
8667
8668 .time-summary-project-info {
8669 display: flex;
8670 justify-content: space-between;
8671 align-items: center;
8672 font-size: 0.8125rem;
8673 margin-bottom: 0.25rem;
8674 }
8675
8676 .time-summary-project-name {
8677 color: var(--text-primary);
8678 overflow: hidden;
8679 text-overflow: ellipsis;
8680 white-space: nowrap;
8681 flex: 1;
8682 }
8683
8684 .time-summary-project-time {
8685 font-family: var(--font-mono, monospace);
8686 font-weight: 600;
8687 font-size: 0.75rem;
8688 color: var(--text-secondary);
8689 margin-left: 0.5rem;
8690 flex-shrink: 0;
8691 }
8692
8693 .time-summary-bar {
8694 height: 4px;
8695 background: var(--bg-tertiary);
8696 border-radius: 2px;
8697 overflow: hidden;
8698 }
8699
8700 .time-summary-bar-fill {
8701 height: 100%;
8702 background: var(--accent-color);
8703 border-radius: 2px;
8704 }
8705
8706 /* ===================================================================
8707 65. Task Time Tracking UI
8708 =================================================================== */
8709
8710 /* Inline action buttons in day sidebar unscheduled tasks */
8711 .unscheduled-task-actions {
8712 display: flex;
8713 gap: 0.25rem;
8714 margin-top: 0.375rem;
8715 }
8716
8717 .unscheduled-task-actions .btn {
8718 font-size: 0.7rem;
8719 padding: 0.125rem 0.375rem;
8720 min-height: auto;
8721 line-height: 1.4;
8722 }
8723
8724 /* Compact time badge in task rows */
8725 .task-time-badge {
8726 display: inline-block;
8727 font-family: var(--font-mono, monospace);
8728 font-size: 0.7rem;
8729 font-weight: 600;
8730 color: var(--text-secondary);
8731 background: var(--bg-secondary);
8732 border: var(--border-width-sm) solid var(--border-color);
8733 border-radius: var(--radius-sm);
8734 padding: 0.05rem 0.35rem;
8735 margin-left: 0.375rem;
8736 vertical-align: middle;
8737 white-space: nowrap;
8738 }
8739
8740 .task-time-badge.over-estimate {
8741 color: var(--accent-red);
8742 border-color: var(--accent-red);
8743 }
8744
8745 /* Play icon for started tasks — entry point into time tracking */
8746 .task-started-icon {
8747 display: inline-block;
8748 width: 0;
8749 height: 0;
8750 border-style: solid;
8751 border-width: 5px 0 5px 8px;
8752 border-color: transparent transparent transparent var(--accent-green);
8753 margin-right: 0.375rem;
8754 vertical-align: middle;
8755 cursor: pointer;
8756 opacity: 0.8;
8757 flex-shrink: 0;
8758 }
8759 .task-started-icon:hover {
8760 opacity: 1;
8761 }
8762
8763 /* Pulsing indicator for running timer */
8764 .task-timer-active {
8765 display: inline-block;
8766 width: 8px;
8767 height: 8px;
8768 background: var(--accent-red);
8769 border-radius: var(--radius-full);
8770 margin-left: 0.375rem;
8771 vertical-align: middle;
8772 animation: timer-pulse 1.5s ease-in-out infinite;
8773 }
8774
8775 @keyframes timer-pulse {
8776 0%, 100% { opacity: 1; transform: scale(1); }
8777 50% { opacity: 0.4; transform: scale(0.8); }
8778 }
8779
8780 /* Timer widget mobile adjustment */
8781 .ui-mode-mobile .timer-widget {
8782 bottom: calc(52px + env(safe-area-inset-bottom, 0px));
8783 }
8784 .ui-mode-mobile .focus-countdown {
8785 font-size: 3rem;
8786 }
8787
8788
8789 /* ===================================================================
8790 66. Timer Subview (Time tab pill)
8791 =================================================================== */
8792
8793 .timer-active-banner {
8794 display: flex;
8795 align-items: center;
8796 gap: 1rem;
8797 padding: 0.875rem 1rem;
8798 background: var(--bg-secondary);
8799 border: var(--border-width) solid var(--accent-color);
8800 border-radius: var(--radius-md);
8801 margin-bottom: 1.5rem;
8802 }
8803
8804 .timer-active-info {
8805 flex: 1;
8806 min-width: 0;
8807 }
8808
8809 .timer-active-label {
8810 display: block;
8811 font-size: 0.75rem;
8812 font-weight: 700;
8813 text-transform: uppercase;
8814 letter-spacing: 0.05em;
8815 color: var(--accent-color);
8816 margin-bottom: 0.125rem;
8817 }
8818
8819 .timer-active-task {
8820 display: block;
8821 font-weight: 600;
8822 overflow: hidden;
8823 text-overflow: ellipsis;
8824 white-space: nowrap;
8825 }
8826
8827 .timer-active-elapsed {
8828 font-family: var(--font-mono, monospace);
8829 font-size: 1.25rem;
8830 font-weight: 700;
8831 color: var(--accent-color);
8832 min-width: 5rem;
8833 text-align: center;
8834 }
8835
8836 .timer-active-actions {
8837 display: flex;
8838 gap: 0.5rem;
8839 }
8840
8841 .timer-focus-split {
8842 display: flex;
8843 align-items: center;
8844 gap: 0.375rem;
8845 padding: 0.5rem 0;
8846 margin-bottom: 0.5rem;
8847 }
8848
8849 .timer-focus-split-label {
8850 font-size: 0.8125rem;
8851 color: var(--text-secondary);
8852 font-weight: 600;
8853 margin-right: 0.25rem;
8854 }
8855
8856 .timer-split-input {
8857 width: 3.5rem;
8858 padding: 0.25rem 0.375rem;
8859 font-size: 0.875rem;
8860 font-family: var(--font-mono, monospace);
8861 text-align: center;
8862 border: var(--border-width) solid var(--border-color);
8863 border-radius: var(--radius-sm);
8864 background: var(--bg-primary);
8865 color: var(--text-primary);
8866 }
8867
8868 .timer-focus-split-sep {
8869 font-size: 0.8125rem;
8870 color: var(--text-secondary);
8871 }
8872
8873 .timer-task-list {
8874 display: flex;
8875 flex-direction: column;
8876 gap: 0;
8877 }
8878
8879 .timer-task-item {
8880 display: flex;
8881 align-items: center;
8882 gap: 1rem;
8883 padding: 0.75rem 0.5rem;
8884 border-bottom: 1px solid var(--border-color);
8885 }
8886
8887 .timer-task-item:last-child {
8888 border-bottom: none;
8889 }
8890
8891 .timer-task-info {
8892 flex: 1;
8893 min-width: 0;
8894 }
8895
8896 .timer-task-desc {
8897 display: block;
8898 font-weight: 500;
8899 overflow: hidden;
8900 text-overflow: ellipsis;
8901 white-space: nowrap;
8902 }
8903
8904 .timer-task-meta {
8905 display: flex;
8906 gap: 0.5rem;
8907 flex-wrap: wrap;
8908 margin-top: 0.25rem;
8909 font-size: 0.8125rem;
8910 color: var(--text-secondary);
8911 }
8912
8913 .timer-task-project {
8914 font-weight: 600;
8915 }
8916
8917 .timer-task-priority {
8918 font-weight: 600;
8919 }
8920
8921 .timer-task-priority.priority-h,
8922 .timer-task-priority.priority-high {
8923 color: var(--accent-red);
8924 }
8925
8926 .timer-task-priority.priority-m,
8927 .timer-task-priority.priority-medium {
8928 color: var(--accent-yellow, var(--accent-color));
8929 }
8930
8931 .timer-task-estimate,
8932 .timer-task-tracked {
8933 font-family: var(--font-mono, monospace);
8934 font-size: 0.75rem;
8935 }
8936
8937 .timer-task-actions {
8938 display: flex;
8939 gap: 0.375rem;
8940 flex-shrink: 0;
8941 }
8942
8943 .ui-mode-mobile .timer-active-banner {
8944 flex-wrap: wrap;
8945 }
8946 .ui-mode-mobile .timer-active-elapsed {
8947 font-size: 1rem;
8948 }
8949 .ui-mode-mobile .timer-task-item {
8950 flex-wrap: wrap;
8951 }
8952 .ui-mode-mobile .timer-task-actions {
8953 width: 100%;
8954 justify-content: flex-end;
8955 }
8956
8957
8958 /* ===================================================================
8959 67. Task Overview
8960 =================================================================== */
8961
8962 .task-overview-section {
8963 margin-bottom: 1.5rem;
8964 padding: 1rem;
8965 background: var(--bg-card);
8966 border: var(--border-width) solid var(--border-color);
8967 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
8968 }
8969
8970 .task-overview-section-title {
8971 font-family: var(--font-heading);
8972 font-size: 1rem;
8973 font-weight: 700;
8974 margin-bottom: 0.75rem;
8975 display: flex;
8976 align-items: center;
8977 gap: 0.5rem;
8978 }
8979
8980 .task-overview-count {
8981 font-weight: 400;
8982 font-size: 0.85rem;
8983 color: var(--text-secondary);
8984 }
8985
8986 .task-overview-stats {
8987 display: grid;
8988 grid-template-columns: repeat(4, 1fr);
8989 gap: 0.75rem;
8990 margin-bottom: 1rem;
8991 }
8992
8993 .task-overview-stat {
8994 text-align: center;
8995 padding: 0.5rem;
8996 background: var(--bg-secondary);
8997 border: var(--border-width-sm) solid var(--border-color);
8998 }
8999
9000 .task-overview-stat-value {
9001 font-family: var(--font-heading);
9002 font-size: 1.25rem;
9003 font-weight: 700;
9004 }
9005
9006 .task-overview-stat-label {
9007 font-size: 0.75rem;
9008 color: var(--text-secondary);
9009 margin-top: 0.25rem;
9010 }
9011
9012 .task-overview-heatmap-nav {
9013 display: flex;
9014 align-items: center;
9015 justify-content: center;
9016 gap: 1rem;
9017 margin-bottom: 0.75rem;
9018 font-family: var(--font-heading);
9019 font-weight: 700;
9020 }
9021
9022 .task-overview-meta {
9023 display: flex;
9024 flex-direction: column;
9025 gap: 0.5rem;
9026 }
9027
9028 .task-overview-badges {
9029 display: flex;
9030 flex-wrap: wrap;
9031 gap: 0.5rem;
9032 margin-bottom: 0.25rem;
9033 }
9034
9035 .task-overview-details {
9036 display: flex;
9037 flex-direction: column;
9038 gap: 0.25rem;
9039 color: var(--text-secondary);
9040 font-size: 0.9rem;
9041 }
9042
9043 .task-overview-subtask-list {
9044 display: flex;
9045 flex-direction: column;
9046 gap: 0.25rem;
9047 margin-bottom: 0.75rem;
9048 }
9049
9050 .task-overview-subtask {
9051 display: flex;
9052 align-items: center;
9053 gap: 0.5rem;
9054 padding: 0.25rem 0;
9055 }
9056
9057 .completed-text {
9058 text-decoration: line-through;
9059 color: var(--text-secondary);
9060 }
9061
9062 .task-overview-add-form {
9063 display: flex;
9064 gap: 0.5rem;
9065 margin-top: 0.5rem;
9066 }
9067
9068 .task-overview-add-form .form-input {
9069 flex: 1;
9070 }
9071
9072 .task-overview-sessions {
9073 display: flex;
9074 flex-direction: column;
9075 gap: 0.25rem;
9076 font-size: 0.9rem;
9077 color: var(--text-secondary);
9078 }
9079
9080 .task-overview-session {
9081 padding: 0.25rem 0;
9082 border-bottom: var(--border-width-sm) solid var(--border-color);
9083 }
9084
9085 .task-overview-annotations {
9086 display: flex;
9087 flex-direction: column;
9088 gap: 0.5rem;
9089 margin-bottom: 0.75rem;
9090 }
9091
9092 .task-overview-annotation {
9093 padding: 0.5rem;
9094 background: var(--bg-secondary);
9095 border: var(--border-width-sm) solid var(--border-color);
9096 }
9097
9098 .task-overview-annotation-date {
9099 font-size: 0.75rem;
9100 color: var(--text-secondary);
9101 margin-bottom: 0.25rem;
9102 }
9103
9104 .task-overview-completion-list {
9105 margin-top: 0.75rem;
9106 font-size: 0.9rem;
9107 color: var(--text-secondary);
9108 }
9109
9110 .task-overview-completion-item {
9111 padding: 0.25rem 0;
9112 border-bottom: var(--border-width-sm) solid var(--border-color);
9113 }
9114
9115 .progress-bar {
9116 height: 6px;
9117 background: var(--bg-secondary);
9118 border: var(--border-width-sm) solid var(--border-color);
9119 margin-bottom: 0.75rem;
9120 overflow: hidden;
9121 }
9122
9123 .progress-fill {
9124 height: 100%;
9125 background: var(--accent-green);
9126 transition: width 0.3s ease;
9127 }
9128
9129 .progress-bar.over-estimate .progress-fill {
9130 background: var(--accent-red);
9131 }
9132
9133
9134 /* Task overview stats in mobile UI — 2 columns instead of 4. */
9135 .ui-mode-mobile .task-overview-stats {
9136 grid-template-columns: repeat(2, 1fr);
9137 }
9138
9139 /* ===================================================================
9140 68. Plan/Review Toggle Nudge Dot
9141 =================================================================== */
9142
9143 .toggle-nudge-dot {
9144 display: inline-block;
9145 width: 7px;
9146 height: 7px;
9147 background: var(--accent-red);
9148 border-radius: var(--radius-full);
9149 margin-left: 0.35rem;
9150 vertical-align: middle;
9151 animation: pulse-badge 2s infinite;
9152 }
9153
9154 .view-toggle-btn {
9155 position: relative;
9156 }
9157
9158 /* ===================================================================
9159 69. Finish & Review
9160 =================================================================== */
9161
9162 .finish-review-bar {
9163 display: flex;
9164 justify-content: flex-end;
9165 padding: 1.5rem 0 1rem;
9166 margin-top: 1.5rem;
9167 border-top: 1px dashed var(--border-color);
9168 }
9169
9170 .finish-review-btn {
9171 position: relative;
9172 font-size: var(--font-size-lg);
9173 padding: 0.65rem 1.5rem;
9174 }
9175
9176 .finish-review-modal-content {
9177 display: flex;
9178 flex-direction: column;
9179 gap: 1.25rem;
9180 }
9181
9182 .past-review-banner {
9183 padding: 0.75rem 1rem;
9184 border: var(--border-width-sm) dashed var(--border-color);
9185 border-radius: var(--radius-md);
9186 background: var(--bg-secondary);
9187 color: var(--text-secondary);
9188 font-size: 0.9rem;
9189 }
9190
9191 .day-accomplished-inline {
9192 margin-top: 1.5rem;
9193 }
9194
9195 .day-accomplished-inline:empty {
9196 display: none;
9197 }
9198
9199 .day-accomplished-stats {
9200 font-size: 0.8rem;
9201 color: var(--text-secondary);
9202 margin-bottom: 0.5rem;
9203 }
9204
9205 /* ===================================================================
9206 70. Calendar Views
9207 =================================================================== */
9208
9209 .events-calendar-container {
9210 padding: 0;
9211 }
9212
9213 .calendar-nav {
9214 display: flex;
9215 align-items: center;
9216 gap: 0.5rem;
9217 margin-bottom: 1rem;
9218 }
9219
9220 .calendar-nav-label {
9221 font-family: var(--font-heading);
9222 font-size: 1.1rem;
9223 font-weight: 700;
9224 margin-left: 0.5rem;
9225 }
9226
9227 /* Month Grid */
9228 .cal-month-grid {
9229 border: var(--border-width) solid var(--border-color);
9230 overflow: hidden;
9231 background: var(--bg-card);
9232 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
9233 }
9234
9235 .cal-month-header,
9236 .cal-month-cells {
9237 display: grid;
9238 grid-template-columns: repeat(7, 1fr);
9239 }
9240
9241 .cal-month-day-header {
9242 font-family: var(--font-heading);
9243 font-size: 0.75rem;
9244 font-weight: 600;
9245 text-align: center;
9246 padding: 0.5rem;
9247 text-transform: uppercase;
9248 background: var(--bg-secondary);
9249 border-bottom: var(--border-width-sm) solid var(--border-color);
9250 }
9251
9252 .cal-month-cell {
9253 min-height: 90px;
9254 border: var(--border-width-sm) solid var(--border-color);
9255 padding: 0.25rem;
9256 cursor: pointer;
9257 transition: background var(--transition-fast);
9258 }
9259
9260 .cal-month-cell:hover {
9261 background: var(--bg-secondary);
9262 }
9263
9264 .cal-month-cell.other-month {
9265 opacity: 0.4;
9266 }
9267
9268 .cal-month-cell.today {
9269 border-color: var(--accent-primary);
9270 border-width: 2px;
9271 }
9272
9273 .cal-month-cell-header {
9274 margin-bottom: 0.15rem;
9275 }
9276
9277 .cal-day-number {
9278 font-family: var(--font-heading);
9279 font-size: 0.8rem;
9280 font-weight: 600;
9281 }
9282
9283 .cal-event-chip {
9284 font-size: 0.7rem;
9285 padding: 1px 4px;
9286 margin-top: 2px;
9287 border-radius: var(--radius-xs);
9288 background: var(--accent-blue);
9289 color: var(--text-on-accent);
9290 white-space: nowrap;
9291 overflow: hidden;
9292 text-overflow: ellipsis;
9293 cursor: pointer;
9294 }
9295
9296 .cal-event-chip:hover {
9297 opacity: 0.85;
9298 }
9299
9300 .cal-event-chip.block-focus { background: var(--accent-red); }
9301 .cal-event-chip.block-personal { background: var(--accent-yellow); color: var(--text-primary); }
9302 .cal-event-chip.block-free_time { background: var(--accent-green); color: var(--text-primary); }
9303
9304 .cal-event-more {
9305 font-size: 0.65rem;
9306 color: var(--text-secondary);
9307 padding: 1px 4px;
9308 }
9309
9310 /* Month Day Detail */
9311 .month-day-detail {
9312 margin-top: 1rem;
9313 border: var(--border-width) solid var(--border-color);
9314 padding: 1rem;
9315 background: var(--bg-card);
9316 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
9317 }
9318
9319 .cal-day-detail-event {
9320 display: flex;
9321 gap: 0.75rem;
9322 padding: 0.5rem 0;
9323 border-bottom: 1px solid var(--border-color);
9324 cursor: pointer;
9325 }
9326
9327 .cal-day-detail-event:hover {
9328 background: var(--bg-secondary);
9329 }
9330
9331 .cal-detail-time {
9332 font-weight: 600;
9333 white-space: nowrap;
9334 min-width: 100px;
9335 }
9336
9337 .cal-detail-location {
9338 color: var(--text-secondary);
9339 font-size: 0.85rem;
9340 }
9341
9342 /* Week Grid */
9343 .cal-week-grid {
9344 border: var(--border-width) solid var(--border-color);
9345 overflow: hidden;
9346 background: var(--bg-card);
9347 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color);
9348 }
9349
9350 .cal-week-header {
9351 display: grid;
9352 grid-template-columns: 60px repeat(7, 1fr);
9353 border-bottom: var(--border-width-sm) solid var(--border-color);
9354 background: var(--bg-secondary);
9355 }
9356
9357 .cal-week-day-header {
9358 text-align: center;
9359 padding: 0.5rem;
9360 font-family: var(--font-heading);
9361 }
9362
9363 .cal-week-day-header.today {
9364 background: color-mix(in srgb, var(--accent-primary) 15%, transparent);
9365 }
9366
9367 .cal-week-day-name {
9368 font-size: 0.75rem;
9369 text-transform: uppercase;
9370 font-weight: 600;
9371 }
9372
9373 .cal-week-day-num {
9374 font-size: 1rem;
9375 font-weight: 700;
9376 display: block;
9377 }
9378
9379 .cal-week-allday-row {
9380 display: grid;
9381 grid-template-columns: 60px repeat(7, 1fr);
9382 border-bottom: var(--border-width-sm) solid var(--border-color);
9383 min-height: 28px;
9384 }
9385
9386 .cal-allday-label {
9387 font-size: 0.7rem;
9388 color: var(--text-secondary);
9389 display: flex;
9390 align-items: center;
9391 justify-content: center;
9392 }
9393
9394 .cal-week-allday-cell {
9395 padding: 2px;
9396 border-left: 1px solid var(--border-color);
9397 }
9398
9399 .cal-week-body {
9400 display: grid;
9401 grid-template-columns: 60px repeat(7, 1fr);
9402 position: relative;
9403 overflow-y: auto;
9404 max-height: 70vh;
9405 }
9406
9407 .cal-week-time-gutter {
9408 position: relative;
9409 }
9410
9411 .cal-week-hour-label {
9412 position: absolute;
9413 right: 0.5rem;
9414 font-size: 0.7rem;
9415 color: var(--text-secondary);
9416 transform: translateY(-0.5em);
9417 }
9418
9419 .cal-week-day-col {
9420 position: relative;
9421 border-left: 1px solid var(--border-color);
9422 }
9423
9424 .cal-week-day-col.today {
9425 background: color-mix(in srgb, var(--accent-primary) 5%, transparent);
9426 }
9427
9428 .cal-week-hour-line {
9429 position: absolute;
9430 left: 0;
9431 right: 0;
9432 border-top: 1px dashed color-mix(in srgb, var(--border-color) 50%, transparent);
9433 }
9434
9435 .cal-week-event {
9436 position: absolute;
9437 left: 2px;
9438 right: 2px;
9439 border: var(--border-width-sm) solid var(--border-color);
9440 border-radius: var(--radius-sm);
9441 padding: 2px 4px;
9442 background: var(--accent-blue);
9443 color: var(--text-on-accent);
9444 overflow: hidden;
9445 cursor: pointer;
9446 z-index: 10;
9447 font-size: 0.7rem;
9448 }
9449
9450 .cal-week-event:hover {
9451 opacity: 0.85;
9452 }
9453
9454 .cal-week-event-title {
9455 font-weight: 600;
9456 }
9457
9458 .cal-week-event-time {
9459 font-size: 0.65rem;
9460 opacity: 0.85;
9461 }
9462
9463 .cal-week-event.block-focus { background: var(--accent-red); }
9464 .cal-week-event.block-personal { background: var(--accent-yellow); color: var(--text-primary); }
9465 .cal-week-event.block-free_time { background: var(--accent-green); color: var(--text-primary); }
9466
9467 /* Calendar in mobile UI — single-day swipe carousel, denser timeline. */
9468 html.ui-mode-mobile {
9469 --timeline-slot-h: 22px;
9470 }
9471
9472 .ui-mode-mobile .cal-month-cell {
9473 min-height: 64px;
9474 padding: 4px;
9475 }
9476 .ui-mode-mobile .cal-day-number {
9477 font-size: 0.95rem;
9478 font-weight: 600;
9479 }
9480 .ui-mode-mobile .cal-event-chip {
9481 font-size: 0.65rem;
9482 }
9483 .ui-mode-mobile .cal-week-body {
9484 max-height: 60vh;
9485 }
9486
9487 /* Single-day swipe carousel for week view */
9488 .ui-mode-mobile .cal-mobile-day {
9489 display: flex;
9490 flex-direction: column;
9491 height: 70vh;
9492 user-select: none;
9493 }
9494 .ui-mode-mobile .cal-mobile-day-header {
9495 padding: 0.75rem;
9496 font-weight: 600;
9497 text-align: center;
9498 border-bottom: 1px solid var(--border-color);
9499 }
9500 .ui-mode-mobile .cal-mobile-day-header.today {
9501 color: var(--accent-primary);
9502 }
9503 .ui-mode-mobile .cal-mobile-allday {
9504 padding: 0.5rem;
9505 display: flex;
9506 flex-direction: column;
9507 gap: 0.25rem;
9508 border-bottom: 1px solid var(--border-color);
9509 }
9510 .ui-mode-mobile .cal-mobile-day-body {
9511 position: relative;
9512 flex: 1;
9513 overflow-y: auto;
9514 display: grid;
9515 grid-template-columns: 48px 1fr;
9516 }
9517 .ui-mode-mobile .cal-mobile-day-col {
9518 position: relative;
9519 border-left: 1px solid var(--border-color);
9520 }
9521
9522 /* Settings Page — Mobile */
9523 .ui-mode-mobile .settings-page-layout { flex-direction: column; }
9524 .ui-mode-mobile .settings-sidebar {
9525 width: 100%;
9526 border-right: none;
9527 border-bottom: 1px solid var(--border-color);
9528 padding: 0.75rem;
9529 flex-direction: row;
9530 flex-wrap: wrap;
9531 align-items: center;
9532 }
9533 .ui-mode-mobile .settings-back { margin-bottom: 0; margin-right: 0.5rem; padding: 0.5rem; }
9534 .ui-mode-mobile .settings-nav-items { flex-direction: row; flex-wrap: wrap; gap: 0.25rem; }
9535 .ui-mode-mobile .settings-nav-item { padding: 0.5rem 0.75rem; border-left: none; border-radius: var(--radius-sm); }
9536 .ui-mode-mobile .settings-nav-item.active { border-left-color: transparent; }
9537 .ui-mode-mobile .settings-content { padding: 1rem; }
9538
9539
9540 /* ============================================================
9541 Compose window (compose.html — standalone Tauri window)
9542 Scoped under body.compose-window so it does not leak to the
9543 main app shell.
9544 ============================================================ */
9545
9546 body.compose-window {
9547 height: 100vh;
9548 display: flex;
9549 flex-direction: column;
9550 overflow: hidden;
9551 }
9552
9553 body.compose-window .compose-toolbar {
9554 display: flex;
9555 gap: 0.5rem;
9556 padding: 0.75rem 1rem;
9557 background: var(--bg-secondary);
9558 border-bottom: 1px solid var(--border-color);
9559 }
9560
9561 body.compose-window .toolbar-spacer {
9562 flex: 1;
9563 }
9564
9565 body.compose-window .compose-form {
9566 flex: 1;
9567 display: flex;
9568 flex-direction: column;
9569 overflow: hidden;
9570 background: var(--bg-card);
9571 }
9572
9573 body.compose-window .status-bar {
9574 padding: 0.5rem 1rem;
9575 background: var(--bg-secondary);
9576 border-top: 1px solid var(--border-color);
9577 font-size: 0.8125rem;
9578 color: var(--text-secondary);
9579 }
9580
9581 body.compose-window .status-bar.error {
9582 color: var(--accent-red);
9583 }
9584
9585 body.compose-window .status-bar.success {
9586 color: var(--accent-green);
9587 }
9588
9589 body.compose-window .compose-loading {
9590 opacity: 0.6;
9591 pointer-events: none;
9592 }
9593