/* ============================================================================ GoingsOn — Neobrute Theme Build new UI by COMPOSING the existing vocabulary, in this order of preference: 1. Use a UTILITY class for one-off adjustments (.mb-1, .mb-2, .flex-1, .text-sm-secondary, .hidden) 2. Use a LAYOUT PRIMITIVE to position content (.row-flex + .row-flex-{2,3,4}, .row, .stack-{2,3,4}) 3. Use a COMPONENT PRIMITIVE for a UI element (.card, .btn, .form-input, .form-select, .modal, .badge, .tag, .toggle-switch) 4. Extend a primitive with a modifier (.btn-primary, .btn-sm, .form-select--compact, .subtask-item--linked) 5. ONLY THEN consider a new class — and add it to the right BAND below A new class is a smell, not a goal. Before writing one: • grep this file for the visual shape you want; almost everything is here • check whether an existing primitive + modifier composes to your shape • page-scoped rules under a feature class (`.day-plan .foo`) are a last resort, not a first move WHEN UTILITY-STACKING IS WRONG: A row of mixed-intent elements (one fills, others size to content) belongs in a NAMED LAYOUT with an explicit `grid-template-columns`, not in `.row-flex` + utilities. The utility form encodes intent in browser flex-shrink math rather than in CSS that reads as intent — especially fragile when the row contains a native ` intrinsic min-content shenanigans that flex layout exposes. */ .email-filter-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; gap: var(--space-2); align-items: center; } .email-filter-row > .form-input, .email-filter-row > .form-select { width: 100%; min-width: 0; } .email-filter-row > .form-select { width: 9rem; } /* Contacts filter row: same shape as .email-filter-row (search fills, filter sizes to content, action button sizes to content). Tag filter uses .filter-select rather than .form-select, but the layout rule is identical. */ .contacts-filter-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: var(--space-2); align-items: center; } .contacts-filter-row > .form-input { width: 100%; min-width: 0; } .contacts-filter-row > .filter-select { width: 9rem; min-width: 0; } /* Work-hours row in Settings: two small selects with a "to" label between. Same lens as .email-filter-row — selects size to their short content; the grid columns express the intent explicitly. */ .work-hours-row { display: grid; grid-template-columns: auto auto auto; gap: var(--space-2); align-items: center; } .work-hours-row > .form-select { width: auto; } #emails-view .page-header, #emails-view .bulk-actions-bar { flex-shrink: 0; } /* =================================================================== 46. Saved Views Sidebar (desktop UI only — hidden on mobile) =================================================================== */ .ui-mode-desktop .saved-views-sidebar { width: 200px; flex-shrink: 0; background: var(--bg-card); border-right: var(--border-width) solid var(--border-color); display: flex; flex-direction: column; overflow: hidden; } .sidebar-section { display: flex; flex-direction: column; flex: 1; min-height: 0; } .sidebar-section-header { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem 1rem; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-secondary); border-bottom: 2px solid var(--border-color); background: var(--bg-secondary); } .btn-icon { background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 0.25rem; font-size: 0.875rem; line-height: 1; } .btn-icon:hover { color: var(--text-primary); } .pinned-views-list { flex: 1; overflow-y: auto; padding: 0.5rem; } .sidebar-empty { text-align: center; padding: 1.5rem 0.5rem; color: var(--text-muted); font-size: 0.8rem; } .saved-view-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.75rem; margin-bottom: 0.5rem; background: var(--bg-card); border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-sm); cursor: pointer; font-size: 0.85rem; font-weight: 600; color: var(--text-primary); box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease, color 0.15s ease; } .saved-view-item:hover { background: var(--accent-blue); color: var(--text-on-accent); } .saved-view-item.active { background: var(--accent-blue); color: var(--text-on-accent); box-shadow: inset 0 0 0 2px var(--border-color); } .saved-view-item .view-icon { font-size: 0.75rem; } .saved-view-item .view-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .saved-view-item .view-actions { opacity: 0; transition: opacity 0.1s; } .saved-view-item:hover .view-actions { opacity: 1; } /* Filter actions in filter bar */ .filter-actions { display: flex; gap: 0.5rem; margin-left: auto; } /* =================================================================== 47. Contacts =================================================================== */ /* Avatar primitive — circular badge with initials. Default 40px with border; size + unknown modifiers compose. */ .avatar { width: 40px; height: 40px; min-width: 40px; border-radius: 50%; background-color: var(--accent-blue); color: var(--text-on-accent); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.85rem; font-family: var(--font-heading); border: var(--border-width-sm) solid var(--border-color); flex-shrink: 0; } .avatar--sm { width: 32px; height: 32px; min-width: 32px; font-size: 0.75rem; border: none; } .avatar--lg { width: 60px; height: 60px; min-width: 60px; font-size: 1.2rem; } .avatar--unknown { background: var(--bg-secondary); color: var(--text-secondary); } .contact-card .card-header { display: flex; align-items: center; } .contact-nickname { display: block; font-size: 0.85rem; color: var(--text-secondary); font-style: italic; } .contact-company { display: block; font-size: 0.85rem; color: var(--text-secondary); } .contact-email { font-size: 0.85rem; color: var(--text-secondary); } .contact-detail .detail-row { margin-bottom: 0.5rem; font-size: 0.9rem; } .contact-detail .contact-info-section { margin-bottom: 1rem; padding-bottom: 1rem; border-bottom: 1px solid var(--border-light); } .contact-detail .contact-notes { margin-bottom: 1.5rem; } .contact-detail .contact-notes p { margin-top: 0.25rem; white-space: pre-wrap; color: var(--text-secondary); } .sub-collection { margin-bottom: 1.25rem; } .sub-collection-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; } .sub-collection-header h4 { margin: 0; font-size: 0.95rem; font-weight: 600; } .sub-item { display: flex; justify-content: space-between; align-items: center; padding: 0.4rem 0; border-bottom: 1px solid var(--border-light); font-size: 0.9rem; } .sub-item:last-child { border-bottom: none; } .sub-empty { font-size: 0.85rem; color: var(--text-secondary); font-style: italic; padding: 0.25rem 0; } /* Edit form sub-collection summaries */ .edit-sub-collections { border-top: 1px solid var(--border-color); padding-top: 1rem; margin-bottom: 0.5rem; } .edit-sub-section { margin-bottom: 0.75rem; } .edit-sub-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.25rem; } .sub-item-compact { font-size: 0.85rem; color: var(--text-secondary); padding: 0.125rem 0; display: flex; align-items: center; gap: var(--space-2); justify-content: space-between; } .sub-item-actions { display: inline-flex; gap: var(--space-1); flex-shrink: 0; } .reminder-options { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin-top: var(--space-2); } .reminder-option { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-sm); color: var(--text-secondary); cursor: pointer; } /* Task detail drawer (Phase 7 Tier 6) --------------------------------- Right-anchored slide-in overlay so users can scan the list and read one task's full detail without losing list scroll position. Falls back to a full-screen sheet on narrow viewports. */ .task-drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(480px, 100vw); background: var(--bg-primary); border-left: 1px solid var(--border-color); box-shadow: -4px 0 18px rgba(0, 0, 0, 0.18); transform: translateX(100%); transition: transform 180ms ease-out; z-index: 60; display: flex; flex-direction: column; overflow: hidden; } .task-drawer.visible { transform: translateX(0); } .task-drawer-header { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border-color); background: var(--bg-secondary); flex-shrink: 0; } .task-drawer-title { flex: 1; margin: 0; font-size: var(--font-size-lg, 1.05rem); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .task-drawer-close { flex-shrink: 0; } .task-drawer-actions { display: flex; gap: var(--space-2); flex-shrink: 0; } .task-drawer-content { flex: 1; overflow-y: auto; padding: var(--space-4); } /* Mark the row whose task is currently open in the drawer. */ .task-row--active { background: var(--bg-accent, var(--bg-secondary)); box-shadow: inset 3px 0 0 var(--accent-color, var(--text-primary)); } .ui-mode-mobile .task-drawer { width: 100vw; border-left: none; } /* =================================================================== 48. Print Styles (global + weekly review) =================================================================== All `@media print` rules live here. Weekly-review-specific print styles consolidated from former §52 on 2026-05-24. */ @media print { /* ----- Global chrome ----- */ /* Hide navigation and interactive elements */ .sidebar, .header, .tabs, .tab-nav, .filter-bar, .pagination, .btn, .modal-overlay, .toast, .context-menu, .keyboard-hints, .review-actions-grid, .focus-section .btn, .focus-slot .btn, .tab-badge, .tab-status-dot, .card-badge, .virtual-scroller-spacer { display: none !important; } /* Reset body + main content to full width */ body { background: white; color: black; } .main-content, .weekly-review-content { margin: 0; padding: 0; max-width: 100%; width: 100%; } .view { padding: 0; } /* Ensure text is readable */ a { color: black; text-decoration: underline; } /* ----- Tables ----- */ .data-table, .task-table { border: 1px solid #333; box-shadow: none; } .data-table { page-break-inside: avoid; } .data-table th, .data-table td { border: 1px solid #ccc; padding: 0.5rem; display: table-cell !important; } .data-table tbody tr:hover, .task-row:hover { background: none; } .task-list-container { height: auto !important; overflow: visible !important; } .task-header-row, .task-row { grid-template-columns: 1fr 100px 40px 80px 60px 80px 60px !important; } .task-header-row .task-cell, .task-row .task-cell { display: block !important; border: 1px solid #ccc; padding: 0.25rem 0.5rem; } .view-header { page-break-after: avoid; } /* ----- Weekly review ----- */ /* Reset backgrounds for print */ body, .weekly-review-content, .review-card, .focus-slot, .reflection-prompt, .project-health, .event-item { background: white !important; color: black !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } /* Print-friendly card chrome */ .review-card { border: 1px solid #ccc !important; box-shadow: none !important; page-break-inside: avoid; margin-bottom: 1rem; } .focus-slot { border: 1px solid #999 !important; } .focus-slot.primary { border: 2px solid #f7d154 !important; background: #fffbea !important; } /* Two-column print layout */ .review-grid { display: block !important; } .review-card { display: inline-block; vertical-align: top; width: 48%; margin-right: 2%; } .focus-section.full-width, .reflection-section, .week-timeline, .week-timeline-events { width: 100% !important; display: block !important; } /* Print header */ .weekly-review-header { border-bottom: 2px solid #333; padding-bottom: 1rem; margin-bottom: 1.5rem; } .week-dates { font-size: 1.5rem; font-weight: bold; } /* Timeline dots print in color */ .day-dot { -webkit-print-color-adjust: exact; print-color-adjust: exact; } .day-dot.completed { background: #5cb85c !important; } .day-dot.event { background: #9b59b6 !important; } .day-dot.overdue { background: #d9534f !important; } /* Project health colors */ .project-health { border-left: 4px solid #337ab7 !important; } .project-health.warning { border-left-color: #f7d154 !important; } .project-health.danger { border-left-color: #d9534f !important; } /* Focus grid for print */ .focus-grid { display: flex !important; gap: 1rem; } .focus-slot { flex: 1; } /* Reflection prompts */ .reflection-prompts { display: flex !important; gap: 1rem; } .reflection-prompt { flex: 1; } .prompt-input { border: 1px solid #ccc !important; min-height: 80px; } /* Page break hints */ .focus-section { page-break-before: auto; } .reflection-section { page-break-before: always; } } /* =================================================================== 49. Weekly Review — chrome around the V2 grid + tab indicators =================================================================== The V1 grid layout (stat cards, review sections, focus toggle, notes textarea, etc.) was removed 2026-05-24 after V2 took over rendering in `weekly-review-render.js`. What remains here is the outer chrome (header, status pill, focus background gradient) still composed by `weekly-review.js`, plus tab indicators (`.tab-badge`, `.tab-status-dot`) consumed by tab nav + events.js. */ .weekly-review-content { max-width: 900px; margin: 0 auto; padding: 1rem; } .weekly-review-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; padding-bottom: 1rem; border-bottom: var(--border-width-sm) solid var(--border-color); } .week-dates { font-family: var(--font-heading); font-size: 1.25rem; font-weight: 700; color: var(--text-primary); } .review-status { padding: 0.25rem 0.75rem; border-radius: var(--radius-xs); font-size: 0.875rem; font-weight: 600; border: var(--border-width-sm) solid var(--border-color); } .review-status.completed { background: var(--accent-green); color: var(--text-on-accent); } .review-status.pending { background: var(--accent-yellow); color: var(--text-primary); } .review-status.unreviewed { background: var(--bg-secondary); color: var(--text-muted); } /* Event time pill — used in the week timeline + finish-review timeline event list. */ .event-time { font-size: 0.875rem; font-weight: 600; color: var(--text-muted); min-width: 80px; } /* Focus section background — applied on top of the .card.card--static.review-card composition for the focus scope card in the V2 grid. */ .focus-section { background: linear-gradient(135deg, var(--bg-card) 0%, color-mix(in srgb, var(--accent-yellow) 15%, var(--bg-card)) 100%); } /* Tab Badge (for nudge) */ .tab-badge { display: inline-block; width: 8px; height: 8px; background: var(--accent-red); border-radius: var(--radius-full); margin-left: 0.5rem; vertical-align: middle; animation: pulse-badge 2s infinite; } @keyframes pulse-badge { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.6; transform: scale(0.8); } } .tab-status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-left: 0.5rem; vertical-align: middle; transition: background-color 0.3s ease; } .tab-status-dot.status-none { display: none; } .tab-status-dot.status-green { background-color: var(--accent-green); } .tab-status-dot.status-yellow { background-color: var(--accent-yellow); animation: pulse-badge 2s ease-in-out infinite; } .tab-status-dot.status-red { background-color: var(--accent-red); animation: pulse-badge 1.5s ease-in-out infinite; } /* =================================================================== 50. Weekly Review V2 - Grid Layout =================================================================== */ /* Main Grid Layout */ .review-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; max-width: 1200px; margin: 0 auto; } /* Review Cards — marker class for review-specific scoping. Callsites compose `.card .card--static .review-card`; chrome inherits from .card. Only the padding bump (+0.25rem) and the review-scoped descendants live here. */ .review-card { padding: 1.5rem; } .review-card .card-header { align-items: center; padding-bottom: 0.75rem; border-bottom: var(--border-width-sm) solid var(--bg-secondary); } .review-card .card-title { display: flex; align-items: center; gap: 0.5rem; } .review-card .card-icon { font-size: 1.25rem; } .review-card .card-badge { font-size: 0.8rem; padding: 0.25rem 0.75rem; border-radius: var(--radius-md); font-weight: 600; } /* Week Timeline - spans full width */ .week-timeline { grid-column: 1 / -1; } .timeline-visual { display: flex; gap: 0.5rem; margin-top: 1rem; } .timeline-day { flex: 1; text-align: center; padding: 0.75rem 0.5rem; background: var(--bg-secondary); border-radius: var(--radius-md); border: 1px solid var(--border-color); position: relative; } .timeline-day.today { background: var(--accent-blue); color: var(--text-on-accent); border-width: 2px; font-weight: 700; } .timeline-day.past { opacity: 0.7; } .timeline-day.future { background: var(--bg-card); } .timeline-day .day-name { font-size: 0.7rem; font-weight: 600; text-transform: uppercase; color: var(--text-muted); } .timeline-day .day-number { font-size: 1.1rem; font-weight: 700; } .day-dots { display: flex; justify-content: center; gap: 3px; margin-top: 0.5rem; min-height: 8px; } .day-dot { width: 8px; height: 8px; border-radius: var(--radius-full); } .day-dot.task { background: var(--accent-blue); } .day-dot.event { background: var(--accent-purple); } .day-dot.completed { background: var(--accent-green); } .day-dot.overdue { background: var(--accent-red); } .day-dot.vacation-off { background: var(--text-muted); opacity: 0.5; width: 12px; height: 4px; border-radius: 2px; } /* Day Events (inline on timeline strip) */ .day-events { display: flex; flex-direction: column; gap: 2px; margin-top: 0.5rem; text-align: left; } .day-event { font-size: 0.6rem; line-height: 1.3; padding: 1px 4px; border-left: 2px solid var(--accent-purple); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-secondary); } .day-event .event-time { font-size: 0.55rem; font-weight: 600; color: var(--accent-purple); margin-right: 2px; min-width: auto; } .day-event-more { font-size: 0.55rem; color: var(--text-muted); padding: 1px 4px; font-style: italic; } /* Week's Events Card (below timeline) */ .week-timeline-events { grid-column: 1 / -1; } .timeline-events-day { margin-bottom: 0.75rem; } .timeline-events-day:last-child { margin-bottom: 0; } .timeline-events-day-label { font-family: var(--font-heading); font-size: 0.8rem; font-weight: 700; color: var(--text-secondary); margin-bottom: 0.25rem; text-transform: uppercase; } /* Vacation Day Toggles */ .vacation-toggles-section { margin-top: 1rem; padding-top: 1rem; border-top: 2px solid var(--border-color); } .vacation-toggles-section h3 { margin: 0 0 0.75rem 0; font-size: 0.9rem; font-family: var(--font-heading); font-weight: 700; } .vacation-toggles { display: flex; gap: 0.5rem; } .vacation-toggle { width: 2.5rem; height: 2.5rem; border-radius: var(--radius-sm); border: var(--border-width) solid var(--border-color); background: var(--bg-secondary); font-family: var(--font-heading); font-weight: 700; font-size: 0.8rem; cursor: pointer; transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); display: flex; align-items: center; justify-content: center; } .vacation-toggle:hover { background: var(--bg-hover); } .vacation-toggle.active { background: var(--accent-purple); color: var(--text-on-accent); border-color: var(--accent-purple); } /* Vacation Timeline Day */ .timeline-day.vacation { opacity: 0.5; } .timeline-day.vacation .day-name { text-decoration: line-through; } /* Vacation Day Banner (Day Plan) */ .vacation-day-banner { text-align: center; padding: 0.5rem 1rem; background: color-mix(in srgb, var(--accent-purple) 15%, var(--bg-secondary)); border: var(--border-width-sm) solid var(--accent-purple); border-radius: var(--radius-sm); font-family: var(--font-heading); font-weight: 700; font-size: 0.85rem; color: var(--accent-purple); margin-bottom: 0.75rem; } /* Stats Row */ .stats-row { display: flex; gap: 1rem; margin-bottom: 1rem; } .stat-box { flex: 1; text-align: center; padding: 1rem; background: var(--bg-secondary); border-radius: var(--radius-md); } .stat-box .stat-number { font-family: var(--font-heading); font-size: 2rem; font-weight: 800; line-height: 1; } .stat-box .stat-number.green { color: var(--accent-green); } .stat-box .stat-number.red { color: var(--accent-red); } .stat-box .stat-number.blue { color: var(--accent-blue); } .stat-box .stat-number.purple { color: var(--accent-purple); } .stat-box .stat-label { font-size: 0.75rem; text-transform: uppercase; color: var(--text-muted); font-weight: 600; margin-top: 0.25rem; } /* Task Lists in Review Cards */ .task-list { list-style: none; max-height: 200px; overflow-y: auto; } .task-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; margin-bottom: 0.5rem; background: var(--bg-secondary); border-radius: var(--radius-md); cursor: pointer; transition: background-color var(--transition-normal); } .task-item:hover { background: var(--accent-blue); color: var(--text-on-accent); } .task-item.completed { opacity: 0.6; text-decoration: line-through; } .task-checkbox { width: 20px; height: 20px; border: 2px solid var(--border-color); border-radius: var(--radius-xs); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .task-checkbox.checked { background: var(--accent-green); color: var(--text-on-accent); } .task-text { flex: 1; font-size: 0.9rem; } .task-project { font-size: 0.75rem; padding: 0.2rem 0.5rem; background: var(--bg-card); border-radius: var(--radius-xs); color: var(--text-muted); } .task-due { font-size: 0.75rem; color: var(--text-muted); } .task-due.overdue { color: var(--accent-red); font-weight: 600; } /* Focus Section - spans full width */ .focus-section.full-width { grid-column: 1 / -1; } /* Shared scope-slot frame — used by Week's Focus card and Month's Goals card. View-specific styling layers on top (e.g. `.focus-slot.primary`, `.scope-slot.done`). */ .scope-slots { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; margin-top: 1rem; } .scope-slot { padding: 1.25rem; background: var(--bg-secondary); border: 2px dashed var(--border-color); border-radius: var(--radius-md); min-height: 100px; display: flex; flex-direction: column; gap: 0.5rem; transition: background 0.15s, border-color 0.15s; } .scope-slot.filled { border-style: solid; background: var(--bg-card); } .scope-slot.empty { cursor: pointer; } .scope-slot.empty:hover { border-color: var(--accent-primary); background: var(--bg-tertiary); } .scope-slot-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: 600; } .scope-slot-title { font-weight: 600; font-size: 0.95rem; } .scope-slot-meta { font-size: 0.8rem; color: var(--text-secondary); } .scope-slot-empty { color: var(--text-muted); font-style: italic; font-size: 0.9rem; } /* Focus-specific overlay: primary-priority highlight */ .focus-slot.primary { border-color: var(--accent-yellow); background: linear-gradient(135deg, var(--bg-card) 0%, color-mix(in srgb, var(--accent-yellow) 10%, var(--bg-card)) 100%); } /* Legacy aliases — keep so existing JS selectors and styles still apply. New code should use the .scope-slot* classes. */ .focus-grid { /* alias of .scope-slots */ } .focus-slot { /* alias of .scope-slot */ } .focus-label { /* alias of .scope-slot-label */ } .focus-task { /* alias of .scope-slot-title */ } .focus-meta { /* alias of .scope-slot-meta */ } .focus-empty { /* alias of .scope-slot-empty */ } /* Projects Health */ .projects-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.75rem; margin-top: 0.5rem; } .project-health { padding: 0.75rem; background: var(--bg-secondary); border-radius: var(--radius-md); border-left: 4px solid var(--accent-blue); } .project-health.warning { border-left-color: var(--accent-yellow); } .project-health.danger { border-left-color: var(--accent-red); } .project-name { font-weight: 600; font-size: 0.85rem; margin-bottom: 0.25rem; } .project-stats { font-size: 0.75rem; color: var(--text-muted); } /* Reflection Section */ .reflection-section { grid-column: 1 / -1; } .reflection-prompts { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1rem; } .reflection-prompt { padding: 1rem; background: var(--bg-secondary); border-radius: var(--radius-md); } .prompt-label { font-size: 0.8rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 0.5rem; } .prompt-input, .reflection-textarea { width: 100%; padding: 0.75rem; border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-md); font-size: 0.9rem; font-family: inherit; resize: none; background: var(--bg-card); } .prompt-input:focus, .reflection-textarea:focus { outline: none; border-color: var(--accent-blue); } /* Review Actions in Grid */ .review-actions-grid { grid-column: 1 / -1; display: flex; justify-content: flex-end; gap: 1rem; padding-top: 1rem; } /* Event items */ .event-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; margin-bottom: 0.5rem; background: var(--bg-secondary); border-radius: var(--radius-md); border-left: 3px solid var(--accent-purple); } .event-item .event-time { font-size: 0.8rem; font-weight: 600; color: var(--accent-purple); min-width: 100px; } .event-item .event-title { flex: 1; font-size: 0.9rem; } /* Accomplishment celebration */ .accomplishment-highlight { 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%); border: 2px solid var(--accent-green); padding: 1rem; border-radius: var(--radius-md); margin-bottom: 1rem; display: flex; align-items: center; gap: 1rem; } .accomplishment-icon { font-size: 2rem; } .accomplishment-text { font-size: 1rem; } .accomplishment-text strong { color: var(--accent-green); } /* Scrollbar styling for task lists */ .task-list::-webkit-scrollbar { width: 6px; } .task-list::-webkit-scrollbar-track { background: var(--bg-secondary); border-radius: var(--radius-xs); } .task-list::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: var(--radius-xs); } /* Weekly Review Grid in mobile UI — collapse to single column. */ .ui-mode-mobile .review-grid { grid-template-columns: 1fr; } .ui-mode-mobile .week-timeline, .ui-mode-mobile .week-timeline-events, .ui-mode-mobile .focus-section.full-width, .ui-mode-mobile .reflection-section { grid-column: 1; } .ui-mode-mobile .focus-grid { grid-template-columns: 1fr; } .ui-mode-mobile .reflection-prompts { grid-template-columns: 1fr; } .ui-mode-mobile .projects-grid { grid-template-columns: 1fr 1fr; } /* Weekly Review extras — mobile UI: stack stat cards and project grid. */ .ui-mode-mobile .stat-cards { flex-direction: column; } .ui-mode-mobile .stat-card { max-width: none; } .ui-mode-mobile .week-info { flex-direction: column; align-items: flex-start; gap: 0.5rem; } .ui-mode-mobile .projects-grid { grid-template-columns: 1fr; } /* =================================================================== 51. Weekly Review Transitions & Keyboard Navigation =================================================================== */ /* Smooth transitions for focus slots */ .focus-slot { transition: background-color 0.2s ease-out, border-color 0.2s ease-out; } .focus-slot.filled { animation: focusSlotFill 0.3s ease-out; } @keyframes focusSlotFill { 0% { transform: scale(0.95); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } /* Keyboard focus states */ .focus-slot:focus-within, .focus-slot:focus { outline: 2px solid var(--accent-blue); outline-offset: 2px; } .focus-slot[tabindex]:focus { outline: 2px solid var(--accent-blue); outline-offset: 2px; } /* Suggested task buttons transitions */ .focus-section .btn { transition: transform 0.15s ease-out, opacity 0.15s ease-out; } .focus-section .btn:active { transform: scale(0.97); } /* §52 vacated 2026-05-24 — weekly-review print styles consolidated into §48. */ /* =================================================================== 52b. Monthly Review =================================================================== */ .monthly-review-nav, .weekly-review-nav { display: flex; align-items: center; gap: 0.5rem; } .weekly-review-nav .week-dates { font-family: var(--font-heading); font-size: 1.25rem; font-weight: 700; color: var(--text-primary); margin-left: 0.5rem; } .monthly-review-month-display { font-family: var(--font-heading); font-size: 1.25rem; font-weight: 700; color: var(--text-primary); margin-left: 0.5rem; } .monthly-review-content { max-width: 900px; margin: 0 auto; padding: 1rem; } /* Heat Map Calendar */ .month-heatmap { margin-bottom: 1.5rem; border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-md); padding: 1rem; background: var(--bg-secondary); } .month-heatmap-header { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; margin-bottom: 0.5rem; } .month-heatmap-day-header { font-family: var(--font-heading); font-size: 0.75rem; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; } .month-heatmap-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; } .month-heatmap-cell { aspect-ratio: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; border-radius: var(--radius-xs); cursor: pointer; transition: transform 0.1s ease; border: var(--border-width-sm) solid transparent; position: relative; min-height: 40px; } .month-heatmap-cell:not(.empty):hover { transform: scale(1.1); border-color: var(--border-color); z-index: 1; } .month-heatmap-cell.empty { cursor: default; background: transparent; } .month-heatmap-cell.intensity-0 { background: var(--bg-primary); } .month-heatmap-cell.intensity-1 { background: color-mix(in srgb, var(--accent-green) 20%, var(--bg-primary)); } .month-heatmap-cell.intensity-2 { background: color-mix(in srgb, var(--accent-green) 40%, var(--bg-primary)); } .month-heatmap-cell.intensity-3 { background: color-mix(in srgb, var(--accent-green) 60%, var(--bg-primary)); } .month-heatmap-cell.vacation { background: var(--bg-tertiary); opacity: 0.6; } .month-heatmap-cell.today { border-color: var(--accent-primary); border-width: 2px; } .month-heatmap-cell.past.intensity-0 { background: var(--bg-tertiary); } .month-heatmap-day-number { font-family: var(--font-heading); font-size: 0.8rem; font-weight: 600; color: var(--text-primary); } .month-heatmap-dots { display: flex; gap: 2px; margin-top: 2px; } .month-dot { font-size: 0.6rem; font-weight: 700; border-radius: var(--radius-xs); padding: 0 3px; line-height: 1.3; } .month-dot.completed { color: var(--accent-green); } .month-dot.event { color: var(--accent-purple); } /* Cards Grid */ .monthly-review-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; } .review-card.month-stats-card { grid-column: span 1; } .review-card.month-goals-card { margin-bottom: 1rem; } .review-card.month-pulse-card, .review-card.month-patterns-card { grid-column: span 1; } .review-card.month-reflection-card { grid-column: 1 / -1; } .review-card-title { font-family: var(--font-heading); font-size: 1rem; font-weight: 700; margin-bottom: 0.75rem; color: var(--text-primary); } /* Stats */ .month-stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; } .month-stat-item { display: flex; flex-direction: column; align-items: center; padding: 0.5rem; border-radius: var(--radius-xs); background: var(--bg-primary); border: var(--border-width-sm) solid var(--border-color); } .month-stat-value { font-family: var(--font-heading); font-size: 1.5rem; font-weight: 700; color: var(--text-primary); } .month-stat-label { font-size: 0.75rem; color: var(--text-secondary); text-transform: uppercase; font-weight: 600; } .month-stats-highlights { display: flex; gap: 1rem; margin-top: 0.5rem; justify-content: center; } .stat-highlight { font-size: 0.8rem; color: var(--text-secondary); } /* Project Pulse */ .month-pulse-list { display: flex; flex-direction: column; gap: 0.5rem; } .month-pulse-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem; border-radius: var(--radius-xs); background: var(--bg-primary); border: var(--border-width-sm) solid var(--border-color); } .pulse-name { font-weight: 600; flex: 1; font-size: 0.875rem; } .pulse-stats { font-size: 0.75rem; color: var(--text-secondary); } .pulse-arrow { font-size: 1rem; font-weight: 700; } .month-pulse-item.positive .pulse-arrow { color: var(--accent-green); } .month-pulse-item.negative .pulse-arrow { color: var(--accent-red); } .month-pulse-item.neutral .pulse-arrow { color: var(--text-secondary); } /* Goals — scope-slot frame is shared with Focus; goal-specific bits below. .month-goals-list is now just a hook for legacy selectors; layout comes from .scope-slots. */ .month-goals-list { /* layout inherited from .scope-slots */ } .month-goal-body { display: flex; align-items: center; gap: 0.5rem; flex: 1; } .month-goal-item.done { opacity: 0.7; } .month-goal-item.done .month-goal-text { text-decoration: line-through; } .month-goal-item.abandoned { opacity: 0.5; } .month-goal-item.abandoned .month-goal-text { text-decoration: line-through; } /* Extends .btn-icon with bigger font, fixed width, and parent-driven color overrides. */ .month-goal-status-btn { font-size: 1rem; padding: 0; color: var(--text-secondary); width: 24px; text-align: center; } .month-goal-item.done .month-goal-status-btn { color: var(--accent-green); } .month-goal-item.abandoned .month-goal-status-btn { color: var(--accent-red); } .month-goal-text { flex: 1; font-size: 0.875rem; } /* Extends .btn-icon with hover-reveal opacity and tertiary color. */ .month-goal-delete-btn { color: var(--text-tertiary); padding: 0 4px; font-size: 0.75rem; opacity: 0; transition: opacity 0.15s; } .month-goal-item:hover .month-goal-delete-btn { opacity: 1; } .month-goal-placeholder { color: var(--text-tertiary); font-size: 0.875rem; } /* Reflection */ .month-reflection-fields { display: flex; flex-direction: column; gap: 0.5rem; } .month-reflection-label { font-size: 0.875rem; font-weight: 600; color: var(--text-secondary); } .month-reflection-textarea { width: 100%; padding: 0.5rem; border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-xs); background: var(--bg-primary); color: var(--text-primary); font-family: var(--font-body); font-size: 0.875rem; resize: vertical; } .month-reflection-textarea:focus { outline: 2px solid var(--accent-primary); outline-offset: -1px; } /* Patterns */ .month-patterns-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.5rem; } .month-pattern-item { font-size: 0.875rem; color: var(--text-secondary); padding: 0.5rem; background: var(--bg-primary); border-radius: var(--radius-xs); border: var(--border-width-sm) solid var(--border-color); } /* Monthly Review in mobile UI — collapse to single column, denser heatmap. */ .ui-mode-mobile .monthly-review-cards { grid-template-columns: 1fr; } .ui-mode-mobile .review-card.month-stats-card, .ui-mode-mobile .review-card.month-goals-card, .ui-mode-mobile .review-card.month-pulse-card, .ui-mode-mobile .review-card.month-patterns-card { grid-column: span 1; } .ui-mode-mobile .month-heatmap-cell { min-height: 32px; } .ui-mode-mobile .month-heatmap-day-number { font-size: 0.7rem; } .ui-mode-mobile .month-heatmap-dots { display: none; } /* =================================================================== 53. Import Wizard =================================================================== */ .import-wizard { display: flex; flex-direction: column; gap: 1.5rem; } .import-step { padding: 1rem; background: var(--bg-secondary); border: var(--border-width) solid var(--border-color); border-radius: var(--radius-md); } .import-step h3 { margin: 0 0 1rem 0; font-size: var(--font-size-md); font-weight: 600; } .plugin-selector { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.75rem; } .plugin-option { display: flex; flex-direction: column; align-items: flex-start; padding: 0.75rem 1rem; background: var(--bg-card); border: var(--border-width) solid var(--border-color); border-radius: var(--radius-sm); cursor: pointer; text-align: left; transition: border-color var(--transition-fast), background var(--transition-fast); } .plugin-option:hover { border-color: var(--accent-primary); background: var(--bg-hover); } .plugin-option.selected { border-color: var(--accent-primary); background: color-mix(in srgb, var(--accent-primary) 10%, var(--bg-card)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-primary) 30%, transparent); } .plugin-option .plugin-name { font-weight: 600; margin-bottom: 0.25rem; } .plugin-option .plugin-meta { display: flex; gap: 0.5rem; font-size: var(--font-size-sm); color: var(--text-muted); margin-bottom: 0.25rem; } .plugin-option .plugin-extensions { color: var(--accent-cyan); } .plugin-option .plugin-types { color: var(--text-secondary); } .plugin-option .plugin-description { font-size: var(--font-size-sm); color: var(--text-secondary); line-height: 1.4; } .file-selector { display: flex; align-items: center; gap: 1rem; } .selected-file-name { color: var(--text-secondary); font-family: monospace; font-size: var(--font-size-sm); } .import-preview-container { min-height: 100px; } .import-preview-table-wrapper { max-height: 300px; overflow: auto; border: 1px solid var(--border-color); border-radius: var(--radius-sm); } .import-preview-table { font-size: var(--font-size-sm); margin: 0; } .import-preview-table th { position: sticky; top: 0; background: var(--bg-secondary); z-index: 1; } .import-preview-table td { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .import-summary { margin: 0 0 0.75rem 0; color: var(--text-primary); } .import-more { margin: 0.5rem 0 0 0; color: var(--text-muted); font-style: italic; font-size: var(--font-size-sm); } .import-empty, .import-error { padding: 2rem; text-align: center; color: var(--text-muted); } .import-error { color: var(--accent-red); } .import-warnings { margin-top: 1rem; padding: 0.75rem; background: color-mix(in srgb, var(--accent-yellow) 10%, var(--bg-card)); border: 1px solid var(--accent-yellow); border-radius: var(--radius-sm); font-size: var(--font-size-sm); } .import-warnings ul { margin: 0.5rem 0 0 1.25rem; padding: 0; } .import-warnings li { margin-bottom: 0.25rem; } .import-external-types { display: flex; gap: 1rem; margin-bottom: 1.5rem; } .import-type-card { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1.5rem 1rem; background: var(--bg-card); border: 2px solid var(--border-color); border-radius: var(--radius-md); cursor: pointer; transition: border-color 0.15s, background 0.15s; } .import-type-card:hover { border-color: var(--accent-primary); background: var(--bg-secondary); } .import-type-icon { font-size: 2rem; } .import-type-label { font-weight: 600; color: var(--text-primary); } .import-type-desc { font-size: var(--font-size-sm); color: var(--text-muted); } /* =================================================================== 54. Plugin Manager =================================================================== */ .plugin-list { display: flex; flex-direction: column; gap: 0.75rem; } .plugin-item { display: flex; justify-content: space-between; align-items: center; padding: 1rem; background: var(--bg-card); border: var(--border-width) solid var(--border-color); border-radius: var(--radius-md); } .plugin-item .plugin-info { flex: 1; } .plugin-item .plugin-name { font-weight: 600; } .plugin-item .plugin-version { color: var(--text-muted); font-size: var(--font-size-sm); margin-left: 0.5rem; } .plugin-item .plugin-description { margin: 0.25rem 0; color: var(--text-secondary); font-size: var(--font-size-sm); } .plugin-item .plugin-extensions { font-size: var(--font-size-xs); color: var(--text-muted); } .plugin-item .plugin-actions { margin-left: 1rem; } /* =================================================================== 55. Toggle Switch =================================================================== */ .toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; } .toggle-switch input { opacity: 0; width: 0; height: 0; } .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--bg-tertiary); border: 2px solid var(--border-color); border-radius: var(--radius-xl); transition: background-color var(--transition-fast), border-color var(--transition-fast); } .toggle-slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: var(--text-muted); border-radius: var(--radius-full); transition: transform var(--transition-fast), background-color var(--transition-fast); } .toggle-switch input:checked + .toggle-slider { background-color: var(--accent-primary); border-color: var(--accent-primary); } .toggle-switch input:checked + .toggle-slider:before { transform: translateX(20px); background-color: var(--bg-card); } .toggle-switch input:focus + .toggle-slider { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-primary) 30%, transparent); } /* =================================================================== 56. Project Milestones =================================================================== */ .milestones-section { margin-bottom: 1.5rem; } .milestones-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 2px solid var(--border-color); } .milestones-header h3 { margin: 0; font-size: 1rem; font-family: var(--font-heading); font-weight: 700; } .milestone-card { background: var(--bg-card); border: var(--border-width) solid var(--border-color); border-radius: var(--radius-md); padding: 1rem; margin-bottom: 0.75rem; transition: background-color 0.1s; box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .milestone-card:hover { background: var(--bg-secondary); } .milestone-card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 0.5rem; } .milestone-card-header h4 { margin: 0; font-size: 0.95rem; font-family: var(--font-heading); font-weight: 700; } .milestone-card-header .milestone-status { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; padding: 0.15rem 0.4rem; border-radius: var(--radius-sm); background: var(--bg-secondary); color: var(--text-muted); } .milestone-card-header .milestone-status.completed { background: color-mix(in srgb, var(--accent-green) 15%, var(--bg-secondary)); color: var(--accent-green); } .milestone-meta { display: flex; gap: 1rem; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.5rem; } .milestone-progress { height: 6px; background: var(--bg-secondary); border-radius: var(--radius-full); overflow: hidden; border: var(--border-width-sm) solid var(--border-color); } .milestone-progress-fill { height: 100%; background: var(--accent-green); border-radius: var(--radius-full); transition: width var(--transition-fast); } .milestone-actions { display: flex; gap: 0.5rem; margin-top: 0.5rem; } .milestone-actions button { font-size: 0.75rem; padding: 0.2rem 0.5rem; background: var(--bg-secondary); border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-sm); cursor: pointer; color: var(--text-secondary); transition: background var(--transition-fast); } .milestone-actions button:hover { background: var(--bg-hover); } .milestone-actions button.danger:hover { background: color-mix(in srgb, var(--accent-red) 15%, var(--bg-secondary)); color: var(--accent-red); } button.milestone-reorder-btn.btn { font-size: 0.65rem; padding: 0.15rem 0.35rem; line-height: 1; min-width: 1.5rem; text-align: center; } .milestones-completed-section { margin-top: 0.75rem; } .milestones-completed-toggle { font-size: 0.8rem; color: var(--text-secondary); padding: 0.25rem 0; } .milestone-card-summary { padding: 0.5rem 0.75rem; opacity: 0.7; } .milestone-card-summary .milestone-info { display: flex; align-items: center; gap: 0.5rem; } .milestone-complete-badge { font-size: 0.7rem; font-weight: 700; padding: 0.1rem 0.4rem; border-radius: var(--radius-sm); background: color-mix(in srgb, var(--accent-green) 15%, var(--bg-secondary)); color: var(--accent-green); } /* =================================================================== 58. Mobile Navigation (Nav Dot, Dial, Bottom Sheets) =================================================================== */ /* --- Mobile Tab Bar (hidden on desktop, shown <=768px) --- */ .mobile-tab-bar { display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1100; background: var(--bg-card); border-top: var(--border-width) solid var(--border-color); padding-bottom: env(safe-area-inset-bottom, 0px); height: calc(52px + env(safe-area-inset-bottom, 0px)); } .mobile-tab { flex: 1; display: flex; align-items: center; justify-content: center; height: 52px; background: none; border: none; color: var(--text-muted); font-size: 0.7rem; font-weight: 700; font-family: var(--font-sans); text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: color 0.15s ease; } .mobile-tab.active { color: var(--accent-blue); } .mobile-tab:active { background: var(--bg-secondary); } .mobile-tab-create { font-size: 1.4rem; font-weight: 400; color: var(--accent-green); letter-spacing: 0; text-transform: none; } /* --- Tab Long-press Slide Menu --- Anchored above a mobile tab. JS sets left/bottom inline. Origin is bottom-center so the scale-in reads as "growing up out of the tab". */ .mobile-tab-slide-menu { position: fixed; z-index: 1102; min-width: 140px; background: var(--bg-card); border: var(--border-width) solid var(--border-color); border-radius: var(--radius-md); box-shadow: var(--shadow-brutal-md); padding: 0.25rem; display: flex; flex-direction: column; opacity: 0; transform: scale(0.92); transform-origin: 50% 100%; transition: opacity 120ms ease-out, transform 120ms ease-out; } .mobile-tab-slide-menu.is-open { opacity: 1; transform: scale(1); } .mobile-tab-slide-item { padding: 0.7rem 0.9rem; min-height: 44px; display: flex; align-items: center; justify-content: center; font-size: var(--font-size-sm); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-primary); border-radius: var(--radius-sm); transition: background 80ms ease, transform 80ms ease; } .mobile-tab-slide-item.is-highlighted { background: var(--accent-blue); color: var(--text-on-accent); transform: scale(1.03); } /* --- Action Bottom Sheet --- */ .action-sheet { position: fixed; inset: 0; z-index: 10001; display: flex; flex-direction: column; justify-content: flex-end; } .action-sheet.hidden { display: none; } .action-sheet-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.4); } .action-sheet-container { position: relative; background: var(--bg-card); border-top: var(--border-width) solid var(--border-color); border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: 0.5rem 1rem calc(0.5rem + env(safe-area-inset-bottom, 0px)); max-height: 60vh; overflow-y: auto; animation: sheetSlideUp 0.25s ease-out; } .action-sheet-handle { width: 36px; height: 4px; border-radius: 2px; background: var(--text-muted); margin: 0 auto 0.75rem; opacity: 0.4; } .action-sheet-content button { display: flex; align-items: center; gap: 0.75rem; width: 100%; padding: 0.875rem 0.5rem; background: none; border: none; border-bottom: 1px solid var(--bg-secondary); font-size: var(--font-size-base); font-weight: 600; color: var(--text-primary); text-align: left; cursor: pointer; } .action-sheet-content button:last-child { border-bottom: none; } .action-sheet-content button:active { background: var(--bg-secondary); } .action-sheet-content button.danger { color: var(--accent-red); } .action-sheet-cancel { display: block; width: 100%; padding: 0.875rem; margin-top: 0.5rem; background: var(--bg-secondary); border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-md); font-size: var(--font-size-base); font-weight: 700; color: var(--text-primary); text-align: center; cursor: pointer; } .action-sheet-cancel:active { background: var(--bg-tertiary); } /* --- Modal Drag Handle (mobile swipe-to-dismiss) --- */ .modal-drag-handle { display: none; width: 36px; height: 4px; border-radius: 2px; background: var(--text-muted); margin: 0.5rem auto 0; opacity: 0.4; } /* --- Mobile Sort Dropdown (replaces clickable column headers) --- */ .mobile-sort-bar { display: none; gap: 0.5rem; padding: 0.5rem 0; align-items: center; } .mobile-sort-bar select { flex: 1; font-size: var(--font-size-sm); } /* --- Mobile Filter Toggle --- */ .mobile-filter-toggle { display: none; } /* --- Swipe Action Layer --- */ .swipe-actions-container { position: relative; overflow: hidden; } .swipe-actions-bg { position: absolute; top: 0; bottom: 0; display: flex; align-items: center; padding: 0 1rem; font-weight: 700; font-size: var(--font-size-sm); color: var(--text-on-accent); } .swipe-actions-bg.swipe-left { right: 0; background: var(--accent-green); } .swipe-actions-bg.swipe-right { left: 0; background: var(--accent-red); } .swipe-content { position: relative; background: var(--bg-card); transition: transform 0.15s ease; } /* --- Pull to Refresh --- */ .pull-to-refresh-indicator { display: none; text-align: center; padding: 0.75rem; font-size: var(--font-size-sm); color: var(--text-muted); font-weight: 600; } .pull-to-refresh-indicator.visible { display: block; } /* --- Event Date Group Headers (mobile) --- */ .event-date-group-header { display: none; } /* --- Day Plan Collapsible Sidebar (mobile) --- */ .day-plan-sidebar-toggle { display: none; } @keyframes sheetSlideUp { from { transform: translateY(100%); } to { transform: translateY(0); } } @keyframes sheetSlideDown { from { transform: translateY(0); } to { transform: translateY(100%); } } @keyframes dialFadeIn { from { opacity: 0; } to { opacity: 1; } } /* =================================================================== 59. Mobile Responsive (768px overrides) =================================================================== */ /* --- Safe area padding + room for mobile tab bar --- */ html.ui-mode-mobile, .ui-mode-mobile body { overflow-x: hidden; max-width: 100vw; touch-action: pan-y; overscroll-behavior-x: none; } .ui-mode-mobile body { padding-top: env(safe-area-inset-top, 0px); padding-bottom: calc(52px + env(safe-area-inset-bottom, 0px)); padding-left: env(safe-area-inset-left, 0px); padding-right: env(safe-area-inset-right, 0px); } /* Fixed-position UI must extend edge-to-edge under the notch in landscape */ .ui-mode-mobile .mobile-tab-bar, .ui-mode-mobile .timer-widget { padding-left: env(safe-area-inset-left, 0px); padding-right: env(safe-area-inset-right, 0px); } .ui-mode-mobile .mobile-tab-bar { display: flex; } /* --- Hide desktop tab navigation --- */ .ui-mode-mobile .tab-navigation { display: none !important; } .ui-mode-mobile .app-header { display: none; } /* Pill nav is replaced on mobile by the bottom tab bar's long-press slide menu — hide the in-page sub-tab strip. */ .ui-mode-mobile .pill-nav { display: none; } /* === Mobile toolbar grids === Toolbar rows become equal-column grids on mobile so children share the row predictably (no orphans, no ragged wrapping). Search inputs always span the full grid row. */ .ui-mode-mobile #emails-view > div.row-flex.mb-2, .ui-mode-mobile #tasks-view .page-header > .row-flex, .ui-mode-mobile #tasks-view .mobile-sort-bar, .ui-mode-mobile #contacts-view .page-header > .row-flex { display: grid; grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); gap: var(--space-2); align-items: center; } /* Tasks page-header: Quick Add + New Task are hidden on mobile (see .mobile-hide / .btn-primary rules), so only the view-toggle remains and takes the full row. */ .ui-mode-mobile #tasks-view .page-header > .row-flex { grid-template-columns: 1fr; } /* Mobile-hide utility: marker class on controls that don't belong in the mobile layout (Drafts, Quick Add). Surfaced elsewhere instead (slide menu, bottom bar). */ .ui-mode-mobile .mobile-hide { display: none !important; } /* Status badges in the day/week/month page-headers are informational and visible inside their respective review subviews anyway. */ .ui-mode-mobile #day-review-status-badge, .ui-mode-mobile #week-review-status-badge, .ui-mode-mobile #month-review-status-badge { display: none !important; } /* Day-plan timeline: drag-paint and its hint don't apply on mobile — tap-to-add is the touch path. Suppress the hover affordance and grab cursor too. */ .ui-mode-mobile #day-plan-view .timeline-hint { display: none; } .ui-mode-mobile #day-plan-view .timeline-slot-area { cursor: default; } .ui-mode-mobile #day-plan-view .timeline-slot-area:hover { background: transparent; } /* Day-plan nav: keep ← Today → + date input on one row when there's width; wrap the date input below only if the row would overflow. The inline date-display span is redundant with the date input. */ .ui-mode-mobile #day-plan-view .day-plan-nav { display: flex; flex-wrap: wrap; column-gap: var(--space-2); row-gap: var(--space-3); align-items: center; } /* Restore per-button borders/radii — the desktop segmented-strip rule (no right border, square corners) doesn't apply here on mobile. */ .ui-mode-mobile #day-plan-view .day-plan-nav .btn { flex: 0 0 auto; border-radius: var(--radius-sm); border-right-width: var(--border-width); } .ui-mode-mobile #day-plan-view .day-plan-nav .day-plan-date-picker { flex: 1 1 120px; min-width: 0; } .ui-mode-mobile #day-plan-view .day-plan-date-display { display: none; } /* Search inputs always span the full grid row. */ .ui-mode-mobile #email-search, .ui-mode-mobile #contacts-search { grid-column: 1 / -1; width: 100%; min-width: 0; } /* The email-count span ("48 threads") is inside the grid row — hide on mobile; will get a tidier home in layer-2 trims. */ .ui-mode-mobile #email-count { display: none; } /* Inside the new grid cells, undo the segmented-button styling (no right border, square corners) inherited from the desktop page-header rule — grid already gives equal sizing. */ .ui-mode-mobile #tasks-view .page-header > .row-flex .btn, .ui-mode-mobile #contacts-view .page-header > .row-flex .btn { border-radius: var(--radius-sm); border-right-width: var(--border-width); } /* View-toggle inside the tasks grid should fill its cell. */ .ui-mode-mobile #tasks-view .page-header .view-toggle { display: flex; width: 100%; } .ui-mode-mobile #tasks-view .page-header .view-toggle .view-toggle-btn { flex: 1 1 0; } /* Undo absolute positioning on mobile — page-header buttons are hidden anyway */ .ui-mode-mobile .tab-group > .subview > .page-header { position: static; } /* --- Main content adjustments --- */ .ui-mode-mobile .main-content { padding: 0.75rem; } .ui-mode-mobile .page-header { flex-wrap: wrap; gap: 0.5rem; } .ui-mode-mobile .page-header .btn-primary { display: none; } .ui-mode-mobile .page-title { display: none; } /* Compact toolbar buttons: collapse into a single segmented block so the button text has more room without crowding the row. Stretch each segment to share row width so the block reads as one unified control. */ .ui-mode-mobile .page-header > div, .ui-mode-mobile #emails-view .page-header > div, .ui-mode-mobile #contacts-view .page-header > div { gap: 0 !important; flex-wrap: wrap; } .ui-mode-mobile .page-header > div .btn, .ui-mode-mobile #emails-view .page-header > div .btn, .ui-mode-mobile #contacts-view .page-header > div .btn, .ui-mode-mobile .bulk-actions-bar .btn { flex: 1 1 0; min-width: 0; padding: 0.4rem 0.5rem; font-size: 0.75rem; border-radius: 0; border-right-width: 0; white-space: nowrap; } .ui-mode-mobile .page-header > div .btn:first-child, .ui-mode-mobile #emails-view .page-header > div .btn:first-child, .ui-mode-mobile #contacts-view .page-header > div .btn:first-child, .ui-mode-mobile .bulk-actions-bar .btn:first-of-type { border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); } /* Right-cap the visually-last button. `.btn-primary` (Compose) is hidden on mobile via display:none but stays in the DOM, so `:last-child` would pick the hidden one. Cover both: actual last child, or the button immediately before a hidden primary. */ .ui-mode-mobile .page-header > div .btn:last-child, .ui-mode-mobile .page-header > div .btn:has(+ .btn-primary), .ui-mode-mobile #emails-view .page-header > div .btn:last-child, .ui-mode-mobile #emails-view .page-header > div .btn:has(+ .btn-primary), .ui-mode-mobile #contacts-view .page-header > div .btn:last-child, .ui-mode-mobile #contacts-view .page-header > div .btn:has(+ .btn-primary) { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); border-right-width: var(--border-width); } /* Bulk-actions: 4 contiguous buttons form a block; bulk-select-all is pushed right by margin-left:auto so it stays standalone. */ .ui-mode-mobile .bulk-actions-bar { gap: 0; } .ui-mode-mobile .bulk-actions-bar .bulk-count { margin-right: 0.5rem; } .ui-mode-mobile .bulk-actions-bar .btn:not(.bulk-select-all) + .bulk-select-all { border-right-width: var(--border-width); border-radius: var(--radius-sm); } .ui-mode-mobile .bulk-actions-bar .btn:not(.bulk-select-all):nth-last-of-type(2) { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); border-right-width: var(--border-width); } .ui-mode-mobile .bulk-select-all { margin-left: auto; } /* Email filter row: let selects shrink and wrap instead of forcing 120px. */ .ui-mode-mobile #emails-view .form-select[id^="email-"] { min-width: 0 !important; flex: 1; } /* Compact form controls. Keep font-size at 1rem (16px) — iOS Safari/WKWebView auto-zooms when a focused input is below 16px. Only shave padding. */ .ui-mode-mobile .form-input, .ui-mode-mobile .form-select, .ui-mode-mobile .form-textarea { padding: 0.45rem 0.65rem; } .ui-mode-mobile .form-textarea { min-height: 72px; } .ui-mode-mobile .form-group { margin-bottom: 0.75rem; } .ui-mode-mobile .form-label { margin-bottom: 0.25rem; } .ui-mode-mobile .form-actions { gap: 0.5rem; margin-top: 1rem; } .ui-mode-mobile .quick-add-input { padding: 0.55rem 0.75rem; } .ui-mode-mobile .quick-add { gap: 0.5rem; margin-bottom: 1rem; } /* Snooze + bulk-modal option rows (date/snooze pickers) — tighten the generous stacked-row padding so more options fit above the keyboard. */ .ui-mode-mobile .snooze-option, .ui-mode-mobile .bulk-modal-option-btn { padding: 0.55rem 0.75rem; } .ui-mode-mobile .snooze-options { gap: 0.35rem; } /* Modal chrome: trim header + content padding so date/snooze/compose modals reclaim ~24px of vertical room above the keyboard. */ .ui-mode-mobile .modal-header { padding: 0.6rem 0.9rem; } .ui-mode-mobile .modal-header h2, .ui-mode-mobile .modal-title { font-size: 1.05rem; } .ui-mode-mobile .modal-content { padding: 0.9rem; } .ui-mode-mobile .modal-content > .form-actions:last-child, .ui-mode-mobile .modal-content form > .form-actions:last-child { margin-top: 0.9rem; padding-top: 0.5rem; } /* --- Modal → Bottom Sheet --- */ /* Lift the entire overlay above the mobile tab bar so bottom-sheet modals and their content aren't clipped behind it. */ .ui-mode-mobile .modal-overlay { align-items: flex-end; bottom: calc(52px + env(safe-area-inset-bottom, 0px)); } .ui-mode-mobile .modal-container { width: 100% !important; max-width: 100% !important; max-height: calc(100vh - 52px - env(safe-area-inset-bottom, 0px) - env(safe-area-inset-top, 0px)); border-radius: var(--radius-lg) var(--radius-lg) 0 0; margin: 0; border-bottom: none; padding-bottom: 0; } .ui-mode-mobile .modal-container.modal-large { max-width: 100% !important; width: 100% !important; max-height: calc(100vh - 52px - env(safe-area-inset-bottom, 0px) - env(safe-area-inset-top, 0px)); border-radius: var(--radius-lg) var(--radius-lg) 0 0; } .ui-mode-mobile .modal-drag-handle { display: block; } .ui-mode-mobile .modal-header { padding: 0.75rem 1rem; } .ui-mode-mobile .modal-content { padding: 1rem; } /* Mobile uses different modal animations (slide up/down from bottom rather than fade-and-scale). @keyframes can't be scoped — defined globally under distinct names and applied via animation-name override below. */ @keyframes modalSlideInMobile { from { transform: translateY(100%); } to { transform: translateY(0); } } @keyframes modalSlideOutMobile { from { transform: translateY(0); } to { transform: translateY(100%); } } .ui-mode-mobile .modal-container { animation-name: modalSlideInMobile; } .ui-mode-mobile .modal-overlay.closing .modal-container { animation-name: modalSlideOutMobile; } /* --- Toast repositioning for mobile --- */ .ui-mode-mobile .toast, .ui-mode-mobile .toast-undo { bottom: calc(env(safe-area-inset-bottom, 0px) + 4.5rem) !important; left: 1rem !important; right: 1rem !important; max-width: none !important; } /* --- Task View: Card Reflow --- */ .ui-mode-mobile .task-table { border: none; box-shadow: none; background: transparent; } .ui-mode-mobile .task-header-row { display: none !important; } .ui-mode-mobile .task-row { display: flex !important; flex-direction: column; gap: 0.25rem; padding: 0.75rem 1rem; margin-bottom: 0.5rem; background: var(--bg-card); border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-md); border-left: 4px solid var(--text-muted); } .ui-mode-mobile .task-row.task-pending { border-left-color: var(--text-muted); } .ui-mode-mobile .task-row .task-cell.priority-h ~ .task-cell:first-child, .ui-mode-mobile .task-row:has(.priority-h) { border-left-color: var(--accent-red); } .ui-mode-mobile .task-row:has(.priority-m) { border-left-color: var(--accent-yellow); } .ui-mode-mobile .task-row:has(.priority-l) { border-left-color: var(--text-muted); } .ui-mode-mobile .task-row .task-cell { display: flex !important; overflow: visible; padding: 0; } .ui-mode-mobile .task-cell.task-description { font-weight: 600; font-size: var(--font-size-base); } .ui-mode-mobile .task-cell.task-project, .ui-mode-mobile .task-cell.task-due { font-size: var(--font-size-sm); color: var(--text-secondary); } /* Show project and due inline */ .ui-mode-mobile .task-row .task-cell.task-project::before { content: none; } /* Hide priority letter (shown via left border color), recurrence, progress columns */ .ui-mode-mobile .task-row .task-cell:nth-child(3), .ui-mode-mobile .task-cell.task-recurrence, .ui-mode-mobile .task-cell.task-progress { display: none !important; } /* Task meta row: project + due side-by-side */ .ui-mode-mobile .task-cell.task-project { order: 2; } .ui-mode-mobile .task-cell.task-due { order: 3; } .ui-mode-mobile .task-cell.task-description { order: 1; } .ui-mode-mobile .task-cell.task-actions-cell { order: 4; justify-content: flex-end; } /* Show subtask progress inline if present */ .ui-mode-mobile .task-cell.task-progress:has(.progress-bar-container) { display: flex !important; order: 5; } .ui-mode-mobile .task-actions-cell .bulk-checkbox { display: none; } .ui-mode-mobile .kebab-btn { opacity: 1; } /* --- Mobile Sort & Filter --- */ .ui-mode-mobile .mobile-sort-bar { display: flex; } .ui-mode-mobile .mobile-filter-toggle { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.5rem 0.75rem; background: var(--bg-card); border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-sm); font-size: var(--font-size-sm); font-weight: 600; cursor: pointer; } .ui-mode-mobile .filter-bar { display: none !important; } .ui-mode-mobile .filter-bar.mobile-visible { display: flex !important; flex-direction: column; position: fixed; bottom: calc(52px + env(safe-area-inset-bottom, 0px)); left: 0; right: 0; background: var(--bg-card); border-top: var(--border-width) solid var(--border-color); border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: 1rem; z-index: 1050; box-shadow: 0 -4px 12px rgba(0,0,0,0.1); } /* --- Events View: List Reflow --- */ .ui-mode-mobile .event-header-row { display: none !important; } .ui-mode-mobile .event-row-virtual { display: flex !important; flex-direction: column; gap: 0.125rem; padding: 0.75rem 1rem; border-bottom: 1px solid var(--bg-secondary); } .ui-mode-mobile .event-cell-date { font-weight: 700; font-size: var(--font-size-sm); color: var(--text-secondary); } .ui-mode-mobile .event-cell-time { font-size: var(--font-size-sm); color: var(--text-muted); } .ui-mode-mobile .event-cell-title { font-weight: 600; font-size: var(--font-size-base); } .ui-mode-mobile .event-cell-location { font-size: var(--font-size-sm); color: var(--text-secondary); } .ui-mode-mobile .event-date-group-header { display: flex; position: sticky; top: 0; z-index: 5; padding: 0.5rem 1rem; background: var(--bg-secondary); font-weight: 700; font-size: var(--font-size-sm); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-primary); border-bottom: var(--border-width-sm) solid var(--border-color); } /* --- Emails: Tighter mobile layout --- */ .ui-mode-mobile .email-item { padding: 0.625rem 0.75rem; } .ui-mode-mobile .email-from { font-size: var(--font-size-sm); } .ui-mode-mobile .email-subject { font-size: var(--font-size-base); } .ui-mode-mobile .email-preview { display: none; } .ui-mode-mobile .email-date { font-size: var(--font-size-xs); } .ui-mode-mobile .email-item .bulk-checkbox { display: none; } /* --- Day Plan --- */ .ui-mode-mobile .day-plan-content { flex-direction: column; } .ui-mode-mobile .day-plan-sidebar { width: 100%; max-height: none; border-top: var(--border-width-sm) solid var(--border-color); order: 2; } .ui-mode-mobile .day-plan-sidebar.collapsed .sidebar-task-list { display: none; } .ui-mode-mobile .day-plan-sidebar-toggle { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 0.625rem 0.75rem; background: var(--bg-secondary); border: none; border-bottom: 1px solid var(--border-color); font-size: var(--font-size-sm); font-weight: 700; cursor: pointer; color: var(--text-primary); } .ui-mode-mobile .day-plan-main { order: 1; } .ui-mode-mobile .day-plan-nav { flex-wrap: wrap; gap: 0.25rem; } /* --- Weekly Review --- */ .ui-mode-mobile .weekly-review-content { padding: 0; } /* --- Monthly Review --- */ .ui-mode-mobile .monthly-review-content { padding: 0; } /* --- Review textareas: auto-grow friendly --- */ .ui-mode-mobile .month-reflection-textarea, .ui-mode-mobile .prompt-input { resize: none; overflow: hidden; } .ui-mode-mobile .monthly-review-nav { flex-wrap: wrap; gap: 0.25rem; } .ui-mode-mobile .monthly-review-month-display { font-size: 1rem; } /* --- Day Summary Sheet --- */ .ui-mode-mobile .day-summary-sheet { padding: 0.5rem 0; } .ui-mode-mobile .day-summary-date { font-size: 1rem; font-weight: 700; margin-bottom: 0.75rem; color: var(--text-primary); } .ui-mode-mobile .day-summary-stats { display: flex; gap: 0.5rem; margin-bottom: 1rem; } .ui-mode-mobile .day-summary-chip { padding: 0.25rem 0.75rem; background: var(--bg-secondary); border-radius: var(--radius-sm); font-size: var(--font-size-sm); font-weight: 600; color: var(--text-secondary); } .ui-mode-mobile .day-summary-list { list-style: none; padding: 0; margin: 0 0 1rem 0; } .ui-mode-mobile .day-summary-item { padding: 0.5rem 0; border-bottom: 1px solid var(--bg-secondary); font-size: var(--font-size-sm); color: var(--text-primary); } .ui-mode-mobile .day-summary-time { font-weight: 600; color: var(--text-secondary); margin-right: 0.5rem; } .ui-mode-mobile .day-summary-more { color: var(--text-muted); font-style: italic; } .ui-mode-mobile .day-summary-empty { color: var(--text-muted); font-size: var(--font-size-sm); margin: 0.5rem 0 1rem; } .ui-mode-mobile .day-summary-go-btn { width: 100%; margin-top: 0.5rem; } /* --- Bulk Actions --- */ .ui-mode-mobile .bulk-actions-bar { position: fixed; bottom: calc(52px + env(safe-area-inset-bottom, 0px)); left: 0; right: 0; z-index: 1050; border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: 0 -4px 12px rgba(0,0,0,0.15); } /* --- Pagination --- */ .ui-mode-mobile .pagination-controls { padding: 0.5rem; } .ui-mode-mobile .pagination-controls .btn { padding: 0.5rem 0.75rem; font-size: var(--font-size-sm); } /* =================================================================== 60. Touch Device Hover Disable =================================================================== */ @media (hover: none) { .task-row:hover { background-color: transparent; } .task-row-clickable:hover { background: transparent; } .event-row-virtual:hover { background-color: transparent; } .email-item:hover { background-color: transparent; } .card:hover { background-color: var(--bg-card); transform: none; box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .btn:hover { background: var(--bg-card); } .btn-primary:hover { background-color: var(--accent-blue); } .btn-danger:hover { background-color: var(--accent-red); } .card:hover { background-color: var(--bg-card); transform: none; box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .kanban-card:hover { background: var(--bg-card); transform: none; box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .saved-view-item:hover { background: var(--bg-card); color: var(--text-primary); transform: none; box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .context-menu-item:hover { background: transparent; color: var(--text-primary); } .modal-close:hover { background: var(--bg-card); color: var(--text-primary); } .month-heatmap-cell:hover { background: transparent; transform: none; } /* Row-action kebabs are hover-revealed on desktop; on touch always show them */ .task-row .kebab-btn, .email-item .kebab-btn, .event-row-virtual .kebab-btn { opacity: 1; } /* No physical keyboard on touch — hide the `?` shortcuts entry points */ .shortcut-hint-btn { display: none; } /* Stack the time-block picker and presets vertically; enforce 44px touch targets */ .time-block-quick-options { grid-template-columns: 1fr; } .time-block-quick-btn, .duration-preset { min-height: 44px; padding: 0.75rem; font-size: 1rem; } } /* Touch-device body class (set by touch.js) — equivalent guards for browsers that report (hover: hover) but are still touch-first (e.g. some Chromebooks). */ body.is-touch .task-row .kebab-btn, body.is-touch .email-item .kebab-btn, body.is-touch .event-row-virtual .kebab-btn { opacity: 1; } body.is-touch .shortcut-hint-btn { display: none; } /* =================================================================== 61. Kanban Board =================================================================== */ /* View Toggle */ .view-toggle { display: flex; gap: 0; margin-left: auto; } .view-toggle-btn { padding: 0.35rem 0.75rem; border: var(--border-width-sm) solid var(--border-color); background: var(--bg-secondary); font-family: var(--font-body); font-size: var(--font-size-md); cursor: pointer; transition: background var(--transition-fast), box-shadow var(--transition-fast); } .view-toggle-btn.active { background: var(--bg-card); font-weight: 600; } .view-toggle-btn:first-child { border-radius: var(--radius-xs) 0 0 var(--radius-xs); } .view-toggle-btn:last-child { border-radius: 0 var(--radius-xs) var(--radius-xs) 0; border-left: none; } /* Kanban Board */ .kanban-board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; padding: 0.5rem 0; min-height: 400px; } .kanban-column { background: var(--bg-card); border: var(--border-width) solid var(--border-color); display: flex; flex-direction: column; min-height: 300px; max-height: calc(100vh - 200px); } .kanban-column-header { padding: 0.75rem 1rem; border-bottom: 2px solid var(--border-color); font-family: var(--font-heading); font-weight: 700; display: flex; justify-content: space-between; align-items: center; } .kanban-column-count { font-family: var(--font-body); font-size: var(--font-size-sm); color: var(--text-secondary); } .kanban-column-body { flex: 1; overflow-y: auto; padding: 0.5rem; display: flex; flex-direction: column; gap: 0.5rem; } .kanban-column.drag-over { background-color: var(--bg-tertiary); } /* Kanban Cards — marker class for kanban-specific scoping. Callsites compose `.card .kanban-card`; chrome + hover transform inherit from .card. Deltas: thinner border, square corners, tighter padding, grab cursor, priority left-border hook. */ .kanban-card { padding: 0.75rem; border-width: var(--border-width-sm); border-radius: 0; cursor: grab; border-left: 4px solid transparent; } .kanban-card.dragging { opacity: 0.5; cursor: grabbing; } .kanban-card.priority-high { border-left-color: var(--accent-red); } .kanban-card.priority-medium { border-left-color: var(--accent-yellow); } .kanban-card.priority-low { border-left-color: var(--accent-green); } .kanban-card-title { font-weight: 600; margin-bottom: 0.25rem; } .kanban-card-meta { font-size: var(--font-size-sm); color: var(--text-secondary); display: flex; gap: 0.5rem; flex-wrap: wrap; } .kanban-card-due.overdue { color: var(--accent-red); font-weight: 600; } .progress-bar-mini { height: 3px; background: var(--bg-tertiary); border-radius: 2px; margin-top: 0.5rem; } .progress-bar-mini .progress-fill { height: 100%; background: var(--accent-green); border-radius: 2px; } /* Kanban Responsive */ .ui-mode-mobile .kanban-board { grid-template-columns: 1fr; } .ui-mode-mobile .kanban-column { max-height: none; } /* =================================================================== 62. Timer Widget (Floating Bottom Bar) =================================================================== */ .timer-widget { position: fixed; bottom: 0; left: 0; right: 0; z-index: 900; background: var(--bg-primary); border-top: var(--border-width) solid var(--border-color); box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); padding: 0.5rem 1rem; transition: transform 0.2s ease; } .timer-widget.hidden { transform: translateY(100%); pointer-events: none; } .timer-widget-inner { display: flex; align-items: center; gap: 1rem; max-width: 800px; margin: 0 auto; } .timer-task-name { flex: 1; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .timer-elapsed { font-family: var(--font-mono, monospace); font-size: 1.125rem; font-weight: 700; color: var(--accent-color); min-width: 5rem; text-align: center; } .timer-actions { display: flex; gap: 0.5rem; } /* =================================================================== 63. Focus Timer (Pomodoro Overlay) =================================================================== */ .focus-overlay { position: fixed; inset: 0; z-index: 1000; background: var(--bg-primary); display: flex; align-items: center; justify-content: center; transition: opacity 0.3s ease; } .focus-overlay.hidden { opacity: 0; pointer-events: none; } .focus-overlay-content { text-align: center; max-width: 400px; width: 100%; padding: 2rem; } .focus-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2rem; } .focus-label { font-family: var(--font-heading); font-size: 1.25rem; font-weight: 700; } .focus-presets { display: flex; gap: 0.5rem; } .focus-preset-btn.active { background: var(--accent-color); color: var(--bg-primary); border-color: var(--accent-color); } .focus-countdown { font-family: var(--font-mono, monospace); font-size: 4rem; font-weight: 700; line-height: 1; margin-bottom: 1.5rem; color: var(--text-primary); } .focus-progress-bar { height: 6px; background: var(--bg-tertiary); border-radius: 3px; margin-bottom: 1.5rem; overflow: hidden; } .focus-progress-fill { height: 100%; background: var(--accent-color); border-radius: 3px; transition: width 1s linear; } .focus-task-name { color: var(--text-secondary); margin-bottom: 2rem; font-size: 0.9rem; } .focus-actions { display: flex; gap: 1rem; justify-content: center; } /* =================================================================== 64. Time Summary Panel (Day View) =================================================================== */ .time-summary-section { margin-bottom: 1rem; } .time-summary-toggle { display: flex; align-items: center; gap: 0.5rem; width: 100%; padding: 0.5rem; background: none; border: none; font-family: var(--font-heading); font-size: 0.875rem; font-weight: 700; color: var(--text-primary); cursor: pointer; text-align: left; } .time-summary-toggle:hover { color: var(--accent-color); } .time-summary-toggle-icon { font-size: 0.625rem; transition: transform 0.15s ease; } .time-summary-body { padding: 0.5rem; overflow: hidden; transition: max-height 0.2s ease; max-height: 500px; } .time-summary-body.collapsed { max-height: 0; padding: 0 0.5rem; } .time-summary-today { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 0; border-bottom: 1px solid var(--border-color); margin-bottom: 0.5rem; } .time-summary-today-label { font-weight: 600; font-size: 0.875rem; } .time-summary-today-value { font-family: var(--font-mono, monospace); font-weight: 700; font-size: 1rem; color: var(--accent-color); } .time-summary-week-header { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-secondary); margin-bottom: 0.5rem; } .time-summary-project { margin-bottom: 0.5rem; } .time-summary-project-info { display: flex; justify-content: space-between; align-items: center; font-size: 0.8125rem; margin-bottom: 0.25rem; } .time-summary-project-name { color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; } .time-summary-project-time { font-family: var(--font-mono, monospace); font-weight: 600; font-size: 0.75rem; color: var(--text-secondary); margin-left: 0.5rem; flex-shrink: 0; } .time-summary-bar { height: 4px; background: var(--bg-tertiary); border-radius: 2px; overflow: hidden; } .time-summary-bar-fill { height: 100%; background: var(--accent-color); border-radius: 2px; } /* =================================================================== 65. Task Time Tracking UI =================================================================== */ /* Inline action buttons in day sidebar unscheduled tasks */ .unscheduled-task-actions { display: flex; gap: 0.25rem; margin-top: 0.375rem; } .unscheduled-task-actions .btn { font-size: 0.7rem; padding: 0.125rem 0.375rem; min-height: auto; line-height: 1.4; } /* Compact time badge in task rows */ .task-time-badge { display: inline-block; font-family: var(--font-mono, monospace); font-size: 0.7rem; font-weight: 600; color: var(--text-secondary); background: var(--bg-secondary); border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-sm); padding: 0.05rem 0.35rem; margin-left: 0.375rem; vertical-align: middle; white-space: nowrap; } .task-time-badge.over-estimate { color: var(--accent-red); border-color: var(--accent-red); } /* Play icon for started tasks — entry point into time tracking */ .task-started-icon { display: inline-block; width: 0; height: 0; border-style: solid; border-width: 5px 0 5px 8px; border-color: transparent transparent transparent var(--accent-green); margin-right: 0.375rem; vertical-align: middle; cursor: pointer; opacity: 0.8; flex-shrink: 0; } .task-started-icon:hover { opacity: 1; } /* Pulsing indicator for running timer */ .task-timer-active { display: inline-block; width: 8px; height: 8px; background: var(--accent-red); border-radius: var(--radius-full); margin-left: 0.375rem; vertical-align: middle; animation: timer-pulse 1.5s ease-in-out infinite; } @keyframes timer-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.8); } } /* Timer widget mobile adjustment */ .ui-mode-mobile .timer-widget { bottom: calc(52px + env(safe-area-inset-bottom, 0px)); } .ui-mode-mobile .focus-countdown { font-size: 3rem; } /* =================================================================== 66. Timer Subview (Time tab pill) =================================================================== */ .timer-active-banner { display: flex; align-items: center; gap: 1rem; padding: 0.875rem 1rem; background: var(--bg-secondary); border: var(--border-width) solid var(--accent-color); border-radius: var(--radius-md); margin-bottom: 1.5rem; } .timer-active-info { flex: 1; min-width: 0; } .timer-active-label { display: block; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--accent-color); margin-bottom: 0.125rem; } .timer-active-task { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .timer-active-elapsed { font-family: var(--font-mono, monospace); font-size: 1.25rem; font-weight: 700; color: var(--accent-color); min-width: 5rem; text-align: center; } .timer-active-actions { display: flex; gap: 0.5rem; } .timer-focus-split { display: flex; align-items: center; gap: 0.375rem; padding: 0.5rem 0; margin-bottom: 0.5rem; } .timer-focus-split-label { font-size: 0.8125rem; color: var(--text-secondary); font-weight: 600; margin-right: 0.25rem; } .timer-split-input { width: 3.5rem; padding: 0.25rem 0.375rem; font-size: 0.875rem; font-family: var(--font-mono, monospace); text-align: center; border: var(--border-width) solid var(--border-color); border-radius: var(--radius-sm); background: var(--bg-primary); color: var(--text-primary); } .timer-focus-split-sep { font-size: 0.8125rem; color: var(--text-secondary); } .timer-task-list { display: flex; flex-direction: column; gap: 0; } .timer-task-item { display: flex; align-items: center; gap: 1rem; padding: 0.75rem 0.5rem; border-bottom: 1px solid var(--border-color); } .timer-task-item:last-child { border-bottom: none; } .timer-task-info { flex: 1; min-width: 0; } .timer-task-desc { display: block; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .timer-task-meta { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.25rem; font-size: 0.8125rem; color: var(--text-secondary); } .timer-task-project { font-weight: 600; } .timer-task-priority { font-weight: 600; } .timer-task-priority.priority-h, .timer-task-priority.priority-high { color: var(--accent-red); } .timer-task-priority.priority-m, .timer-task-priority.priority-medium { color: var(--accent-yellow, var(--accent-color)); } .timer-task-estimate, .timer-task-tracked { font-family: var(--font-mono, monospace); font-size: 0.75rem; } .timer-task-actions { display: flex; gap: 0.375rem; flex-shrink: 0; } .ui-mode-mobile .timer-active-banner { flex-wrap: wrap; } .ui-mode-mobile .timer-active-elapsed { font-size: 1rem; } .ui-mode-mobile .timer-task-item { flex-wrap: wrap; } .ui-mode-mobile .timer-task-actions { width: 100%; justify-content: flex-end; } /* =================================================================== 67. Task Overview =================================================================== */ .task-overview-section { margin-bottom: 1.5rem; padding: 1rem; background: var(--bg-card); border: var(--border-width) solid var(--border-color); box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .task-overview-section-title { font-family: var(--font-heading); font-size: 1rem; font-weight: 700; margin-bottom: 0.75rem; display: flex; align-items: center; gap: 0.5rem; } .task-overview-count { font-weight: 400; font-size: 0.85rem; color: var(--text-secondary); } .task-overview-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.75rem; margin-bottom: 1rem; } .task-overview-stat { text-align: center; padding: 0.5rem; background: var(--bg-secondary); border: var(--border-width-sm) solid var(--border-color); } .task-overview-stat-value { font-family: var(--font-heading); font-size: 1.25rem; font-weight: 700; } .task-overview-stat-label { font-size: 0.75rem; color: var(--text-secondary); margin-top: 0.25rem; } .task-overview-heatmap-nav { display: flex; align-items: center; justify-content: center; gap: 1rem; margin-bottom: 0.75rem; font-family: var(--font-heading); font-weight: 700; } .task-overview-meta { display: flex; flex-direction: column; gap: 0.5rem; } .task-overview-badges { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.25rem; } .task-overview-details { display: flex; flex-direction: column; gap: 0.25rem; color: var(--text-secondary); font-size: 0.9rem; } .task-overview-subtask-list { display: flex; flex-direction: column; gap: 0.25rem; margin-bottom: 0.75rem; } .task-overview-subtask { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0; } .completed-text { text-decoration: line-through; color: var(--text-secondary); } .task-overview-add-form { display: flex; gap: 0.5rem; margin-top: 0.5rem; } .task-overview-add-form .form-input { flex: 1; } .task-overview-sessions { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.9rem; color: var(--text-secondary); } .task-overview-session { padding: 0.25rem 0; border-bottom: var(--border-width-sm) solid var(--border-color); } .task-overview-annotations { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.75rem; } .task-overview-annotation { padding: 0.5rem; background: var(--bg-secondary); border: var(--border-width-sm) solid var(--border-color); } .task-overview-annotation-date { font-size: 0.75rem; color: var(--text-secondary); margin-bottom: 0.25rem; } .task-overview-completion-list { margin-top: 0.75rem; font-size: 0.9rem; color: var(--text-secondary); } .task-overview-completion-item { padding: 0.25rem 0; border-bottom: var(--border-width-sm) solid var(--border-color); } .progress-bar { height: 6px; background: var(--bg-secondary); border: var(--border-width-sm) solid var(--border-color); margin-bottom: 0.75rem; overflow: hidden; } .progress-fill { height: 100%; background: var(--accent-green); transition: width 0.3s ease; } .progress-bar.over-estimate .progress-fill { background: var(--accent-red); } /* Task overview stats in mobile UI — 2 columns instead of 4. */ .ui-mode-mobile .task-overview-stats { grid-template-columns: repeat(2, 1fr); } /* =================================================================== 68. Plan/Review Toggle Nudge Dot =================================================================== */ .toggle-nudge-dot { display: inline-block; width: 7px; height: 7px; background: var(--accent-red); border-radius: var(--radius-full); margin-left: 0.35rem; vertical-align: middle; animation: pulse-badge 2s infinite; } .view-toggle-btn { position: relative; } /* =================================================================== 69. Finish & Review =================================================================== */ .finish-review-bar { display: flex; justify-content: flex-end; padding: 1.5rem 0 1rem; margin-top: 1.5rem; border-top: 1px dashed var(--border-color); } .finish-review-btn { position: relative; font-size: var(--font-size-lg); padding: 0.65rem 1.5rem; } .finish-review-modal-content { display: flex; flex-direction: column; gap: 1.25rem; } .past-review-banner { padding: 0.75rem 1rem; border: var(--border-width-sm) dashed var(--border-color); border-radius: var(--radius-md); background: var(--bg-secondary); color: var(--text-secondary); font-size: 0.9rem; } .day-accomplished-inline { margin-top: 1.5rem; } .day-accomplished-inline:empty { display: none; } .day-accomplished-stats { font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.5rem; } /* =================================================================== 70. Calendar Views =================================================================== */ .events-calendar-container { padding: 0; } .calendar-nav { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem; } .calendar-nav-label { font-family: var(--font-heading); font-size: 1.1rem; font-weight: 700; margin-left: 0.5rem; } /* Month Grid */ .cal-month-grid { border: var(--border-width) solid var(--border-color); overflow: hidden; background: var(--bg-card); box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .cal-month-header, .cal-month-cells { display: grid; grid-template-columns: repeat(7, 1fr); } .cal-month-day-header { font-family: var(--font-heading); font-size: 0.75rem; font-weight: 600; text-align: center; padding: 0.5rem; text-transform: uppercase; background: var(--bg-secondary); border-bottom: var(--border-width-sm) solid var(--border-color); } .cal-month-cell { min-height: 90px; border: var(--border-width-sm) solid var(--border-color); padding: 0.25rem; cursor: pointer; transition: background var(--transition-fast); } .cal-month-cell:hover { background: var(--bg-secondary); } .cal-month-cell.other-month { opacity: 0.4; } .cal-month-cell.today { border-color: var(--accent-primary); border-width: 2px; } .cal-month-cell-header { margin-bottom: 0.15rem; } .cal-day-number { font-family: var(--font-heading); font-size: 0.8rem; font-weight: 600; } .cal-event-chip { font-size: 0.7rem; padding: 1px 4px; margin-top: 2px; border-radius: var(--radius-xs); background: var(--accent-blue); color: var(--text-on-accent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; } .cal-event-chip:hover { opacity: 0.85; } .cal-event-chip.block-focus { background: var(--accent-red); } .cal-event-chip.block-personal { background: var(--accent-yellow); color: var(--text-primary); } .cal-event-chip.block-free_time { background: var(--accent-green); color: var(--text-primary); } .cal-event-more { font-size: 0.65rem; color: var(--text-secondary); padding: 1px 4px; } /* Month Day Detail */ .month-day-detail { margin-top: 1rem; border: var(--border-width) solid var(--border-color); padding: 1rem; background: var(--bg-card); box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .cal-day-detail-event { display: flex; gap: 0.75rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border-color); cursor: pointer; } .cal-day-detail-event:hover { background: var(--bg-secondary); } .cal-detail-time { font-weight: 600; white-space: nowrap; min-width: 100px; } .cal-detail-location { color: var(--text-secondary); font-size: 0.85rem; } /* Week Grid */ .cal-week-grid { border: var(--border-width) solid var(--border-color); overflow: hidden; background: var(--bg-card); box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--border-color); } .cal-week-header { display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: var(--border-width-sm) solid var(--border-color); background: var(--bg-secondary); } .cal-week-day-header { text-align: center; padding: 0.5rem; font-family: var(--font-heading); } .cal-week-day-header.today { background: color-mix(in srgb, var(--accent-primary) 15%, transparent); } .cal-week-day-name { font-size: 0.75rem; text-transform: uppercase; font-weight: 600; } .cal-week-day-num { font-size: 1rem; font-weight: 700; display: block; } .cal-week-allday-row { display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: var(--border-width-sm) solid var(--border-color); min-height: 28px; } .cal-allday-label { font-size: 0.7rem; color: var(--text-secondary); display: flex; align-items: center; justify-content: center; } .cal-week-allday-cell { padding: 2px; border-left: 1px solid var(--border-color); } .cal-week-body { display: grid; grid-template-columns: 60px repeat(7, 1fr); position: relative; overflow-y: auto; max-height: 70vh; } .cal-week-time-gutter { position: relative; } .cal-week-hour-label { position: absolute; right: 0.5rem; font-size: 0.7rem; color: var(--text-secondary); transform: translateY(-0.5em); } .cal-week-day-col { position: relative; border-left: 1px solid var(--border-color); } .cal-week-day-col.today { background: color-mix(in srgb, var(--accent-primary) 5%, transparent); } .cal-week-hour-line { position: absolute; left: 0; right: 0; border-top: 1px dashed color-mix(in srgb, var(--border-color) 50%, transparent); } .cal-week-event { position: absolute; left: 2px; right: 2px; border: var(--border-width-sm) solid var(--border-color); border-radius: var(--radius-sm); padding: 2px 4px; background: var(--accent-blue); color: var(--text-on-accent); overflow: hidden; cursor: pointer; z-index: 10; font-size: 0.7rem; } .cal-week-event:hover { opacity: 0.85; } .cal-week-event-title { font-weight: 600; } .cal-week-event-time { font-size: 0.65rem; opacity: 0.85; } .cal-week-event.block-focus { background: var(--accent-red); } .cal-week-event.block-personal { background: var(--accent-yellow); color: var(--text-primary); } .cal-week-event.block-free_time { background: var(--accent-green); color: var(--text-primary); } /* Calendar in mobile UI — single-day swipe carousel, denser timeline. */ html.ui-mode-mobile { --timeline-slot-h: 22px; } .ui-mode-mobile .cal-month-cell { min-height: 64px; padding: 4px; } .ui-mode-mobile .cal-day-number { font-size: 0.95rem; font-weight: 600; } .ui-mode-mobile .cal-event-chip { font-size: 0.65rem; } .ui-mode-mobile .cal-week-body { max-height: 60vh; } /* Single-day swipe carousel for week view */ .ui-mode-mobile .cal-mobile-day { display: flex; flex-direction: column; height: 70vh; user-select: none; } .ui-mode-mobile .cal-mobile-day-header { padding: 0.75rem; font-weight: 600; text-align: center; border-bottom: 1px solid var(--border-color); } .ui-mode-mobile .cal-mobile-day-header.today { color: var(--accent-primary); } .ui-mode-mobile .cal-mobile-allday { padding: 0.5rem; display: flex; flex-direction: column; gap: 0.25rem; border-bottom: 1px solid var(--border-color); } .ui-mode-mobile .cal-mobile-day-body { position: relative; flex: 1; overflow-y: auto; display: grid; grid-template-columns: 48px 1fr; } .ui-mode-mobile .cal-mobile-day-col { position: relative; border-left: 1px solid var(--border-color); } /* Settings Page — Mobile */ .ui-mode-mobile .settings-page-layout { flex-direction: column; } .ui-mode-mobile .settings-sidebar { width: 100%; border-right: none; border-bottom: 1px solid var(--border-color); padding: 0.75rem; flex-direction: row; flex-wrap: wrap; align-items: center; } .ui-mode-mobile .settings-back { margin-bottom: 0; margin-right: 0.5rem; padding: 0.5rem; } .ui-mode-mobile .settings-nav-items { flex-direction: row; flex-wrap: wrap; gap: 0.25rem; } .ui-mode-mobile .settings-nav-item { padding: 0.5rem 0.75rem; border-left: none; border-radius: var(--radius-sm); } .ui-mode-mobile .settings-nav-item.active { border-left-color: transparent; } .ui-mode-mobile .settings-content { padding: 1rem; } /* ============================================================ Compose window (compose.html — standalone Tauri window) Scoped under body.compose-window so it does not leak to the main app shell. ============================================================ */ body.compose-window { height: 100vh; display: flex; flex-direction: column; overflow: hidden; } body.compose-window .compose-toolbar { display: flex; gap: 0.5rem; padding: 0.75rem 1rem; background: var(--bg-secondary); border-bottom: 1px solid var(--border-color); } body.compose-window .toolbar-spacer { flex: 1; } body.compose-window .compose-form { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: var(--bg-card); } body.compose-window .status-bar { padding: 0.5rem 1rem; background: var(--bg-secondary); border-top: 1px solid var(--border-color); font-size: 0.8125rem; color: var(--text-secondary); } body.compose-window .status-bar.error { color: var(--accent-red); } body.compose-window .status-bar.success { color: var(--accent-green); } body.compose-window .compose-loading { opacity: 0.6; pointer-events: none; }