Skip to main content

max / goingson

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