Skip to main content

max / goingson

43.5 KB · 703 lines History Blame Raw
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
6 <!-- Phase 7 Tier 3 #13 — iOS / PWA chrome integration.
7 theme-color is updated by js/themes.js when the theme changes so the
8 iOS status bar and Android browser chrome match the active surface. -->
9 <meta name="theme-color" content="#E0E4FA" id="meta-theme-color">
10 <meta name="apple-mobile-web-app-capable" content="yes">
11 <meta name="apple-mobile-web-app-status-bar-style" content="default">
12 <meta name="apple-mobile-web-app-title" content="GoingsOn">
13 <title>GoingsOn</title>
14 <link rel="icon" type="image/svg+xml" href="favicon.svg">
15 <link rel="icon" type="image/png" sizes="32x32" href="../icons/32x32.png">
16 <link rel="apple-touch-icon" href="../icons/128x128.png">
17
18 <!-- UI mode detection. Runs BEFORE the stylesheet so the class is on
19 <html> when CSS evaluates (no flash). Precedence:
20 1. ?ui=mobile|desktop URL param (dev/testing, bug repros)
21 2. localStorage.goingson.uiMode (dev Settings toggle)
22 3. navigator.userAgentData.mobile (UA Client Hints, modern)
23 4. UA regex with iPad-as-Mac fallback (Safari iOS/iPadOS, legacy)
24 Works in both browser dev and Tauri-mobile webviews: WKWebView (iOS)
25 and Android WebView both expose iOS/Android in the UA string. iPad
26 on Safari 13+ reports as Mac by default; the maxTouchPoints branch
27 catches that. Production lockdown of overrides is deferred to
28 phase 5 of ui_mode_separation_plan.md. -->
29 <script src="js/bootstrap-uimode.js"></script>
30
31 <link rel="stylesheet" href="css/styles.min.css">
32 </head>
33 <body>
34 <a href="#main-content" class="skip-link">Skip to main content</a>
35 <header class="app-header">
36 <div class="header-content">
37 <h1 class="app-title">GoingsOn</h1>
38 <span class="app-subtitle">Personal Productivity</span>
39 <span class="mobile-view-title" id="mobile-view-title"></span>
40 </div>
41 <nav class="tab-navigation" role="tablist" aria-label="Main navigation">
42 <a href="#" class="tab active" data-view="work" role="tab" aria-selected="true" aria-label="Work: tasks and projects">
43 <span class="tab-label">Work</span>
44 </a>
45 <a href="#" class="tab" data-view="time" role="tab" aria-selected="false" aria-label="Time: day planning, calendar, reviews">
46 <span class="tab-label">Time</span>
47 </a>
48 <a href="#" class="tab" data-view="messages" role="tab" aria-selected="false" aria-label="Messages: email and contacts">
49 <span class="tab-label">Messages</span>
50 </a>
51 </nav>
52 <div class="header-actions">
53 <button class="sync-indicator row-flex row-flex-2 hidden" id="sync-indicator" data-act="settings.openCloudSync" title="Cloud Sync" aria-label="Cloud sync status">
54 <span class="sync-dot" id="sync-dot"></span>
55 <span class="sync-label" id="sync-label"></span>
56 </button>
57 <button class="btn" data-act="settings.open" title="Settings" aria-label="Open settings">Settings</button>
58 <button class="btn shortcut-hint-btn" data-act="keyboard.showShortcuts" title="Keyboard shortcuts (?)" aria-label="Show keyboard shortcuts">?</button>
59 </div>
60 </header>
61
62 <div class="app-body">
63 <main id="main-content" class="main-content">
64 <!-- Work Tab Group -->
65 <div id="work-view" class="view tab-group">
66 <div class="pill-nav" role="tablist" aria-label="Work views">
67 <button class="pill active" data-subview="tasks">Tasks</button>
68 <button class="pill" data-subview="projects">Projects</button>
69 </div>
70
71 <!-- Tasks Sub-View -->
72 <div id="tasks-view" class="subview">
73 <div class="page-header">
74 <h2 class="page-title">Tasks</h2>
75 <div class="row-flex row-flex-4">
76 <div class="view-toggle" id="task-view-toggle">
77 <button class="view-toggle-btn active" data-mode="list" data-act="tasks.setViewMode" data-a1="list">List</button>
78 <button class="view-toggle-btn" data-mode="board" data-act="tasks.setViewMode" data-a1="board">Board</button>
79 </div>
80 <button class="btn btn-secondary mobile-hide" data-act="keyboard.openQuickAddModal" title="Quick add (q)">Quick Add</button>
81 <button class="btn btn-primary" data-act="tasks.openNew" title="New task (n)">+ New Task <kbd class="kbd-hint">n</kbd></button>
82 </div>
83 </div>
84 <div id="task-bulk-actions" class="bulk-actions-bar hidden" role="toolbar" aria-label="Bulk task actions">
85 <span id="task-bulk-count" class="bulk-count">0 selected</span>
86 <button class="btn btn-sm" data-act="bulk.completeTasks">Complete</button>
87 <button class="btn btn-sm" data-act="bulk.setProjectTasks">Set Project</button>
88 <button class="btn btn-sm" data-act="bulk.setPriorityTasks">Set Priority</button>
89 <button class="btn btn-sm" data-act="bulk.snoozeTasks">Snooze</button>
90 <button class="btn btn-sm btn-danger" data-act="bulk.deleteTasks">Delete</button>
91 <button class="btn btn-sm bulk-select-all" data-act="bulk.selectAllTasks">Select All</button>
92 </div>
93 <div class="mobile-sort-bar" id="task-mobile-sort">
94 <button class="mobile-filter-toggle" data-act="tasks.toggleMobileFilters">Filters</button>
95 <select class="filter-select" data-change="tasks.mobileSortChange">
96 <option value="urgency">Sort: Urgency</option>
97 <option value="description">Sort: Name</option>
98 <option value="project">Sort: Project</option>
99 <option value="priority">Sort: Priority</option>
100 <option value="due">Sort: Due Date</option>
101 </select>
102 </div>
103 <div class="filter-bar" id="task-filter-bar" role="search" aria-label="Task filters">
104 <select id="filter-status" class="filter-select" data-change="tasks.applyFilters">
105 <option value="">All Status</option>
106 <option value="pending" selected>Pending</option>
107 <option value="started">Started</option>
108 <option value="completed">Completed</option>
109 </select>
110 <select id="filter-project" class="filter-select" data-change="tasks.applyFilters">
111 <option value="">All Projects</option>
112 </select>
113 <select id="filter-priority" class="filter-select" data-change="tasks.applyFilters">
114 <option value="">All Priority</option>
115 <option value="H">High</option>
116 <option value="M">Medium</option>
117 <option value="L">Low</option>
118 </select>
119 <select id="filter-milestone" class="filter-select hidden" data-change="tasks.applyFilters">
120 <option value="">All Milestones</option>
121 </select>
122 <label class="filter-checkbox" title="Include tasks hidden until a later date">
123 <input type="checkbox" id="filter-snoozed" data-change="tasks.applyFilters">
124 Show Snoozed
125 </label>
126 <label class="filter-checkbox" title="Tasks waiting on someone else to respond">
127 <input type="checkbox" id="filter-waiting" data-change="tasks.applyFilters">
128 Waiting Only
129 </label>
130 <div class="filter-actions">
131 <span id="task-count" class="filter-count" aria-live="polite"></span>
132 <button class="btn btn-link" data-act="tasks.clearFilters">Clear filters</button>
133 </div>
134 </div>
135 <div class="task-table" id="task-table" role="grid" aria-label="Tasks list">
136 <div class="task-header-row" role="row">
137 <div class="task-cell sortable" data-sort="description" data-act="tasks.sort" data-a1="description" role="columnheader" tabindex="0">
138 Description <span class="sort-arrow"></span>
139 </div>
140 <div class="task-cell sortable" data-sort="project" data-act="tasks.sort" data-a1="project" role="columnheader" tabindex="0">
141 Project <span class="sort-arrow"></span>
142 </div>
143 <div class="task-cell sortable" data-sort="priority" data-act="tasks.sort" data-a1="priority" role="columnheader" tabindex="0" aria-label="Priority">
144 Priority <span class="sort-arrow"></span>
145 </div>
146 <div class="task-cell sortable" data-sort="due" data-act="tasks.sort" data-a1="due" role="columnheader" tabindex="0">
147 Due <span class="sort-arrow"></span>
148 </div>
149 <div class="task-cell" role="columnheader">Recurs</div>
150 <div class="task-cell" role="columnheader">Progress</div>
151 <div class="task-cell task-actions-header" role="columnheader"><span class="sr-only">Actions</span></div>
152 </div>
153 <div class="task-list-container" id="task-list-container" aria-live="polite">
154 <div class="skeleton-shimmer" aria-label="Loading tasks">
155 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line short"></div></div></div>
156 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line long"></div></div></div>
157 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
158 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line short"></div><div class="skeleton-line long"></div></div></div>
159 </div>
160 </div>
161 </div>
162 <div id="task-kanban-board" class="kanban-board hidden" role="region" aria-label="Task board">
163 <!-- Rendered by tasks-kanban.js -->
164 </div>
165 <!-- Pagination -->
166 <div id="task-pagination" class="pagination-controls hidden" role="navigation" aria-label="Task list pagination">
167 <button class="btn btn-sm" id="task-prev-page" data-act="tasks.goToPage" data-a1="prev" disabled aria-label="Previous page">&larr; Previous</button>
168 <span id="task-page-info" class="pagination-info">Page 1 of 1</span>
169 <button class="btn btn-sm" id="task-next-page" data-act="tasks.goToPage" data-a1="next" disabled aria-label="Next page">Next &rarr;</button>
170 </div>
171 </div>
172
173 <!-- Projects Sub-View -->
174 <div id="projects-view" class="subview hidden" role="tabpanel" aria-labelledby="projects-tab">
175 <div class="page-header">
176 <h2 class="page-title">Projects</h2>
177 <button class="btn btn-primary" data-act="projects.openNew" title="New project (n)">+ New Project <kbd class="kbd-hint">n</kbd></button>
178 </div>
179 <div class="cards-grid" id="projects-grid">
180 <div class="skeleton-shimmer" aria-label="Loading projects">
181 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
182 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line short"></div></div></div>
183 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line long"></div></div></div>
184 </div>
185 </div>
186 </div>
187
188 <!-- Project Dashboard Sub-View -->
189 <div id="project-dashboard-view" class="subview hidden">
190 <div class="page-header">
191 <div class="row-flex row-flex-4">
192 <button class="btn btn-secondary" data-act="projects.closeDashboard">&larr; Back</button>
193 <h2 class="page-title" id="project-dashboard-title">Project</h2>
194 </div>
195 <button class="btn btn-secondary" id="edit-project-btn" data-act="projects.editCurrent">Edit Project</button>
196 </div>
197 <p id="project-dashboard-description" class="project-dashboard-desc"></p>
198 <div id="project-milestones-section" class="milestones-section"></div>
199 <div class="project-dashboard-grid">
200 <div class="dashboard-column">
201 <div class="dashboard-column-header">
202 <h3>Tasks</h3>
203 <button class="btn btn-sm btn-primary" data-act="projects.addTask">+ Add</button>
204 </div>
205 <div id="project-tasks-list" class="dashboard-list">
206 <div class="skeleton-shimmer" aria-label="Loading tasks"><div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line short"></div></div></div><div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line long"></div></div></div></div>
207 </div>
208 </div>
209 <div class="dashboard-column">
210 <div class="dashboard-column-header">
211 <h3>Events</h3>
212 <button class="btn btn-sm btn-primary" data-act="projects.addEvent">+ Add</button>
213 </div>
214 <div id="project-events-list" class="dashboard-list">
215 <div class="skeleton-shimmer" aria-label="Loading events"><div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line short"></div></div></div><div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div></div>
216 </div>
217 </div>
218 <div class="dashboard-column">
219 <div class="dashboard-column-header">
220 <h3>Emails</h3>
221 <button class="btn btn-sm btn-primary" data-act="projects.linkEmail">+ Link</button>
222 </div>
223 <div id="project-emails-list" class="dashboard-list">
224 <div class="skeleton-shimmer" aria-label="Loading emails"><div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div><div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line short"></div><div class="skeleton-line long"></div></div></div></div>
225 </div>
226 </div>
227 <div class="dashboard-column">
228 <div class="dashboard-column-header">
229 <h3>Attachments</h3>
230 <button class="btn btn-sm btn-primary" id="project-attach-btn">+ Attach</button>
231 </div>
232 <div id="project-attachments-list" class="dashboard-list">
233 <div class="empty-state empty-state--dashboard">No attachments</div>
234 </div>
235 </div>
236 </div>
237 </div>
238 <!-- Task Overview Sub-View -->
239 <div id="task-overview-view" class="subview hidden">
240 <div class="page-header">
241 <div class="row-flex row-flex-4">
242 <button class="btn btn-secondary" data-act="taskOverview.close">&larr; Back</button>
243 <h2 class="page-title" id="task-overview-title">Task Overview</h2>
244 </div>
245 <div id="task-overview-actions"></div>
246 </div>
247 <div id="task-overview-content">
248 <div class="skeleton-shimmer" aria-label="Loading task overview">
249 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
250 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line short"></div></div></div>
251 </div>
252 </div>
253 </div>
254
255 </div><!-- /work-view -->
256
257 <!-- Time Tab Group -->
258 <div id="time-view" class="view tab-group hidden">
259 <div class="pill-nav" role="tablist" aria-label="Time views">
260 <button class="pill active" data-subview="day-plan">Day</button>
261 <button class="pill" data-subview="weekly-review">Week</button>
262 <button class="pill" data-subview="monthly-review">Month</button>
263 <button class="pill" data-subview="timer" title="Pomodoro-style focus sessions">Timer</button>
264 <button class="pill" data-subview="events">Events</button>
265 </div>
266
267 <!-- Day Plan Sub-View -->
268 <div id="day-plan-view" class="subview" role="tabpanel" aria-labelledby="day-plan-tab">
269 <div class="page-header">
270 <div class="day-plan-nav">
271 <button class="btn btn-secondary" data-act="dayPlan.previousDay" title="Previous day ([)">&larr;</button>
272 <button class="btn btn-secondary" data-act="dayPlan.goToToday">Today</button>
273 <button class="btn btn-secondary" data-act="dayPlan.nextDay" title="Next day (])">&rarr;</button>
274 <input type="date" id="day-plan-date" class="day-plan-date-picker" data-change="dayPlan.onDatePickerChange">
275 <span id="day-plan-date-display" class="day-plan-date-display"></span>
276 </div>
277 <span id="day-review-status-badge" class="review-status hidden"></span>
278 </div>
279 <div class="day-plan-content">
280 <div class="day-plan-main" id="day-plan-container">
281 <p class="timeline-hint">Click and drag across time slots to schedule blocks</p>
282 <div class="timeline-container" id="timeline-container">
283 <div class="timeline-scroll-area">
284 <div class="timeline-current-time" id="timeline-current-time"></div>
285 <div id="timeline-slots"></div>
286 <div id="timeline-items"></div>
287 </div>
288 </div>
289 </div>
290 <div class="day-plan-sidebar">
291 <div id="time-summary-container"></div>
292 <button class="day-plan-sidebar-toggle" data-act="dayPlan.toggleSidebar">
293 <span>Tasks to Schedule</span>
294 <span class="toggle-arrow">&#x25BC;</span>
295 </button>
296 <div class="sidebar-header">
297 <h3>Tasks to Schedule</h3>
298 </div>
299 <div id="unscheduled-tasks" class="sidebar-task-list" role="list">
300 <!-- Virtual scroller renders items here -->
301 </div>
302 <div id="day-accomplished-inline" class="day-accomplished-inline"></div>
303 </div>
304 </div>
305 <div class="finish-review-bar">
306 <button class="btn btn-primary finish-review-btn" id="day-finish-review-btn" data-act="dayPlanSchedule.openFinishReviewModal">
307 Finish &amp; Review
308 </button>
309 </div>
310 </div>
311
312 <!-- Weekly Review Sub-View -->
313 <div id="weekly-review-view" class="subview hidden" role="tabpanel" aria-labelledby="weekly-review-tab">
314 <div class="page-header">
315 <h2 class="page-title">Weekly Review</h2>
316 </div>
317 <div id="weekly-review-content" class="weekly-review-content">
318 <div class="skeleton-shimmer" aria-label="Loading weekly review">
319 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
320 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line long"></div></div></div>
321 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line short"></div><div class="skeleton-line long"></div></div></div>
322 </div>
323 </div>
324 </div>
325
326 <!-- Monthly Review Sub-View -->
327 <div id="monthly-review-view" class="subview hidden" role="tabpanel" aria-labelledby="monthly-review-tab">
328 <div class="page-header">
329 <div class="monthly-review-nav">
330 <button class="btn btn-secondary" data-act="monthlyReview.previousMonth" title="Previous month">&larr;</button>
331 <button class="btn btn-secondary" data-act="monthlyReview.goToCurrentMonth">This Month</button>
332 <button class="btn btn-secondary" data-act="monthlyReview.nextMonth" title="Next month">&rarr;</button>
333 <span id="monthly-review-month-display" class="monthly-review-month-display"></span>
334 </div>
335 <span id="month-review-status-badge" class="review-status hidden"></span>
336 </div>
337 <div id="monthly-review-content" class="monthly-review-content">
338 <div class="skeleton-shimmer" aria-label="Loading monthly review">
339 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
340 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line long"></div></div></div>
341 </div>
342 </div>
343 </div>
344
345 <!-- Timer Sub-View -->
346 <div id="timer-view" class="subview hidden" role="tabpanel">
347 <div class="page-header">
348 <h2 class="page-title">Timer</h2>
349 </div>
350 <div id="timer-subview-content">
351 <!-- Rendered by time-tracking.js -->
352 </div>
353 </div>
354
355 <!-- Events Sub-View (accessible via keyboard/URL, not shown in pill nav) -->
356 <div id="events-view" class="subview hidden" role="tabpanel" aria-labelledby="events-tab">
357 <div class="page-header">
358 <h2 class="page-title">Events</h2>
359 <button class="btn btn-primary" data-act="events.openNew" title="New event (n)">+ New Event <kbd class="kbd-hint">n</kbd></button>
360 </div>
361 <div class="filter-bar" id="events-filter-bar">
362 <label class="filter-checkbox" title="Include events hidden until a later date">
363 <input type="checkbox" id="filter-events-snoozed" data-change="events.onFilterChange">
364 Show Snoozed
365 </label>
366 </div>
367 <div id="events-bulk-bar" class="bulk-actions-bar hidden">
368 <span class="bulk-count">0 selected</span>
369 <button class="btn btn-sm" data-act="events.selectAllEvents">Select All</button>
370 <button class="btn btn-sm btn-danger" data-act="events.bulkDelete">Delete</button>
371 <button class="btn btn-sm" data-act="events.clearEventSelection">Cancel</button>
372 </div>
373 <div class="events-list" id="events-list">
374 <details class="past-events-section hidden" id="recurring-events-section" open>
375 <summary class="past-events-toggle">
376 <span class="past-events-label">Recurring</span>
377 <span class="past-events-count" id="recurring-events-count">0</span>
378 </summary>
379 <div class="event-table-virtual" id="recurring-event-table">
380 <div class="event-header-row" role="row">
381 <div class="event-cell" role="columnheader">Pattern</div>
382 <div class="event-cell" role="columnheader">Time</div>
383 <div class="event-cell" role="columnheader">Event</div>
384 <div class="event-cell" role="columnheader">Location</div>
385 <div class="event-cell" role="columnheader"></div>
386 </div>
387 <div class="event-list-container" id="recurring-event-list-container"></div>
388 </div>
389 </details>
390 <h3 class="events-section-heading hidden" id="future-events-heading">Upcoming</h3>
391 <div class="event-table-virtual" id="event-table" role="grid" aria-label="Upcoming events">
392 <div class="event-header-row" role="row">
393 <div class="event-cell" role="columnheader">Date</div>
394 <div class="event-cell" role="columnheader">Time</div>
395 <div class="event-cell" role="columnheader">Event</div>
396 <div class="event-cell" role="columnheader">Location</div>
397 <div class="event-cell" role="columnheader"></div>
398 </div>
399 <div class="event-list-container" id="event-list-container" aria-live="polite">
400 <div class="skeleton-shimmer" aria-label="Loading events">
401 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line short"></div></div></div>
402 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
403 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line short"></div><div class="skeleton-line long"></div></div></div>
404 </div>
405 </div>
406 </div>
407 <details class="past-events-section hidden" id="past-events-section">
408 <summary class="past-events-toggle">
409 <span class="past-events-label">Past Events</span>
410 <span class="past-events-count" id="past-events-count">0</span>
411 </summary>
412 <div class="event-table-virtual event-table-past" id="past-event-table">
413 <div class="event-header-row" role="row">
414 <div class="event-cell" role="columnheader">Date</div>
415 <div class="event-cell" role="columnheader">Time</div>
416 <div class="event-cell" role="columnheader">Event</div>
417 <div class="event-cell" role="columnheader">Location</div>
418 </div>
419 <div class="event-list-container" id="past-event-list-container">
420 </div>
421 </div>
422 </details>
423 </div>
424 </div>
425 </div><!-- /time-view -->
426
427 <!-- Messages Tab Group -->
428 <div id="messages-view" class="view tab-group hidden">
429 <div class="pill-nav" role="tablist" aria-label="Messages views">
430 <button class="pill active" data-subview="emails">Email</button>
431 <button class="pill" data-subview="contacts">Contacts</button>
432 </div>
433
434 <!-- Emails Sub-View -->
435 <div id="emails-view" class="subview" role="tabpanel" aria-labelledby="emails-tab">
436 <div class="page-header">
437 <h2 class="page-title">Emails</h2>
438 <div class="row-flex row-flex-2">
439 <button class="btn btn-secondary mobile-hide" data-act="emails.openDrafts">Drafts</button>
440 <button class="btn btn-primary" data-act="emails.openCompose" title="Compose email (n)">+ Compose</button>
441 </div>
442 </div>
443 <div class="email-filter-row mb-2">
444 <input type="text" class="form-input" id="email-search" placeholder="Search emails..." data-input="emails.search">
445 <select class="form-select" id="email-folder-filter" data-change="emails.filterByFolder">
446 <option value="">All folders</option>
447 </select>
448 <select class="form-select" id="email-label-filter" data-change="emails.filterByLabel">
449 <option value="">All labels</option>
450 </select>
451 <span id="email-count" class="filter-count" aria-live="polite"></span>
452 </div>
453 <div id="email-bulk-actions" class="bulk-actions-bar hidden" role="toolbar" aria-label="Bulk email actions">
454 <span id="email-bulk-count" class="bulk-count">0 selected</span>
455 <button class="btn btn-sm" data-act="bulk.markEmailsRead">Mark Read</button>
456 <button class="btn btn-sm" data-act="bulk.archiveEmails">Archive</button>
457 <button class="btn btn-sm" data-act="bulk.snoozeEmails">Snooze</button>
458 <button class="btn btn-sm btn-danger" data-act="bulk.deleteEmails">Delete</button>
459 <button class="btn btn-sm bulk-select-all" data-act="bulk.selectAllEmails">Select All</button>
460 </div>
461 <div class="card card--shell email-list" id="email-list-wrapper" role="list">
462 <div class="email-list-container" id="email-list" aria-live="polite">
463 <div class="skeleton-shimmer" aria-label="Loading emails">
464 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
465 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line short"></div></div></div>
466 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line long"></div></div></div>
467 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line short"></div><div class="skeleton-line medium"></div></div></div>
468 </div>
469 </div>
470 </div>
471 <!-- Pagination -->
472 <div id="email-pagination" class="pagination-controls hidden" role="navigation" aria-label="Email list pagination">
473 <button class="btn btn-sm" id="email-prev-page" data-act="emails.goToPage" data-a1="prev" disabled aria-label="Previous page">&larr; Previous</button>
474 <span id="email-page-info" class="pagination-info">Page 1 of 1</span>
475 <button class="btn btn-sm" id="email-next-page" data-act="emails.goToPage" data-a1="next" disabled aria-label="Next page">Next &rarr;</button>
476 </div>
477 </div>
478
479 <!-- Contacts Sub-View -->
480 <div id="contacts-view" class="subview hidden" role="tabpanel" aria-labelledby="contacts-tab">
481 <div class="page-header">
482 <h2 class="page-title">Contacts</h2>
483 <div class="contacts-filter-row">
484 <input type="text" class="form-input" id="contacts-search" placeholder="Search contacts..." data-input="contacts.filterBySearch">
485 <select class="filter-select" id="contacts-tag-filter" data-change="contacts.filterByTag">
486 <option value="">All Tags</option>
487 </select>
488 <button class="btn btn-primary" data-act="contacts.openNew" title="New contact (n)">+ New Contact <kbd class="kbd-hint">n</kbd></button>
489 </div>
490 </div>
491 <div id="contacts-bulk-bar" class="bulk-actions-bar hidden">
492 <span class="bulk-count">0 selected</span>
493 <button class="btn btn-sm" data-act="contacts.selectAll">Select All</button>
494 <button class="btn btn-sm" data-act="contacts.bulkTag">Tag</button>
495 <button class="btn btn-sm btn-danger" data-act="contacts.bulkDelete">Delete</button>
496 <button class="btn btn-sm" data-act="contacts.clearSelection">Cancel</button>
497 </div>
498 <div class="cards-grid" id="contacts-grid">
499 <div class="skeleton-shimmer" aria-label="Loading contacts">
500 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line short"></div></div></div>
501 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line long"></div></div></div>
502 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
503 </div>
504 </div>
505 </div>
506 <!-- Contact Dashboard Sub-View -->
507 <div id="contact-dashboard-view" class="subview hidden">
508 <div class="page-header">
509 <div class="row-flex row-flex-4">
510 <button class="btn btn-secondary" data-act="contactDashboard.close">&larr; Back</button>
511 <h2 class="page-title" id="contact-dashboard-title">Contact</h2>
512 </div>
513 <div id="contact-dashboard-actions"></div>
514 </div>
515 <div id="contact-dashboard-content">
516 <div class="skeleton-shimmer" aria-label="Loading contact">
517 <div class="skeleton-row"><div class="skeleton-avatar"></div><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
518 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line short"></div></div></div>
519 </div>
520 </div>
521 </div>
522
523 </div><!-- /messages-view -->
524
525 <!-- Settings View (standalone, not a tab group) -->
526 </main>
527 </div><!-- /app-body -->
528
529 <!-- Settings Overlay (Phase 7 Tier 6 — settings as modeless drawer) -->
530 <div id="settings-overlay" class="settings-overlay hidden" role="dialog" aria-modal="true" aria-labelledby="settings-overlay-title" aria-hidden="true">
531 <div class="settings-overlay-backdrop" data-act="settings.goBack" aria-hidden="true"></div>
532 <div id="settings-view" class="view settings-overlay-card">
533 <div class="settings-page-layout">
534 <nav class="settings-sidebar">
535 <button class="btn-link mb-1 settings-back" data-act="settings.goBack" aria-label="Close settings">&larr; Close</button>
536 <h2 class="sr-only" id="settings-overlay-title">Settings</h2>
537 <div class="settings-nav-items">
538 <button class="settings-nav-item active" data-section="appearance" data-act="settings.showSection" data-a1="appearance">Appearance</button>
539 <button class="settings-nav-item" data-section="notifications" data-act="settings.showSection" data-a1="notifications">Notifications</button>
540 <button class="settings-nav-item" data-section="email" data-act="settings.showSection" data-a1="email">Email Accounts</button>
541 <button class="settings-nav-item" data-section="planning" data-act="settings.showSection" data-a1="planning">Planning &amp; Review</button>
542 <button class="settings-nav-item" data-section="sync" data-act="settings.showSection" data-a1="sync">Cloud Sync</button>
543 <button class="settings-nav-item" data-section="data" data-act="settings.showSection" data-a1="data">Import &amp; Export</button>
544 <button class="settings-nav-item" data-section="about" data-act="settings.showSection" data-a1="about">About</button>
545 </div>
546 </nav>
547 <div class="settings-content" id="settings-content">
548 <!-- Populated by JS -->
549 </div>
550 </div>
551 </div>
552 </div><!-- /settings-overlay -->
553
554 <!-- Modal -->
555 <div id="modal-overlay" class="modal-overlay hidden" role="dialog" aria-modal="true" aria-labelledby="modal-title">
556 <div id="modal-container" class="modal-container">
557 <div class="modal-drag-handle"></div>
558 <div class="modal-header">
559 <h2 id="modal-title">Modal Title</h2>
560 <button class="modal-close" data-act="ui.closeModal" aria-label="Close modal">&times;</button>
561 </div>
562 <div id="modal-content" class="modal-content"></div>
563 </div>
564 </div>
565
566 <!-- Context Menu -->
567 <div id="context-menu" class="context-menu" role="menu" aria-label="Context menu" aria-hidden="true">
568 <!-- Content populated dynamically by JS -->
569 </div>
570
571 <!-- Task Detail Drawer (Phase 7 Tier 6 — side-drawer task detail) -->
572 <aside id="task-detail-drawer" class="task-drawer" role="dialog" aria-modal="false" aria-labelledby="task-drawer-title" aria-hidden="true">
573 <div class="task-drawer-header">
574 <button class="btn btn-sm btn-secondary task-drawer-close" data-act="taskOverview.close" title="Close (Esc)" aria-label="Close task detail">&times;</button>
575 <h2 class="task-drawer-title" id="task-drawer-title">Task</h2>
576 <div class="task-drawer-actions" id="task-drawer-actions"></div>
577 </div>
578 <div class="task-drawer-content" id="task-drawer-content">
579 <div class="skeleton-shimmer" aria-label="Loading task detail">
580 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div>
581 <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line short"></div></div></div>
582 </div>
583 </div>
584 </aside>
585
586 <!-- Mobile Bottom Tab Bar (hidden on desktop) -->
587 <nav id="mobile-tab-bar" class="mobile-tab-bar" role="tablist" aria-label="Mobile navigation">
588 <button class="mobile-tab active" data-view="work" role="tab" aria-selected="true">
589 <span class="mobile-tab-label">Work</span>
590 </button>
591 <button class="mobile-tab" data-view="time" role="tab" aria-selected="false">
592 <span class="mobile-tab-label">Time</span>
593 </button>
594 <button class="mobile-tab" data-view="messages" role="tab" aria-selected="false">
595 <span class="mobile-tab-label">Messages</span>
596 </button>
597 <button class="mobile-tab mobile-tab-create" id="mobile-create-btn" aria-label="Create new item">+</button>
598 </nav>
599
600 <!-- Action Bottom Sheet (mobile context menus) -->
601 <div id="action-sheet" class="action-sheet hidden" role="dialog" aria-modal="true" aria-label="Actions">
602 <div class="action-sheet-backdrop"></div>
603 <div class="action-sheet-container">
604 <div class="action-sheet-handle"></div>
605 <div class="action-sheet-content" id="action-sheet-content"></div>
606 <button class="action-sheet-cancel" data-act="ui.hideActionSheet">Cancel</button>
607 </div>
608 </div>
609
610
611 <!-- Namespace (must load first) -->
612 <script src="js/goingson.js"></script>
613 <script src="js/dispatch.js"></script>
614 <script src="js/viewport.js"></script>
615
616 <!-- Core Layer -->
617 <script src="js/api.js"></script>
618 <script src="js/state.js"></script>
619 <script src="js/escape.js"></script>
620 <script src="js/utils.js"></script>
621 <script src="js/components-modal.js"></script>
622 <script src="js/components.js"></script>
623 <script src="js/form-modal.js"></script>
624 <script src="js/themes.js"></script>
625 <script src="js/query-state.js"></script>
626
627 <!-- Utility Managers -->
628 <script src="js/cache.js"></script>
629 <script src="js/selection-manager.js"></script>
630 <script src="js/pagination-manager.js"></script>
631 <script src="js/virtual-scroller.js"></script>
632
633 <!-- Features (no domain dependencies) -->
634 <script src="js/router.js"></script>
635 <script src="js/navigation.js"></script>
636 <script src="js/snooze.js"></script>
637 <script src="js/touch.js"></script>
638 <!-- Domain render modules (load before their parent domains) -->
639 <script src="js/projects-render.js"></script>
640 <script src="js/tasks-render.js"></script>
641 <script src="js/tasks-kanban.js"></script>
642 <script src="js/contacts-render.js"></script>
643 <script src="js/day-planning-render.js"></script>
644 <script src="js/day-planning-paint.js"></script>
645 <script src="js/day-planning-schedule.js"></script>
646 <script src="js/weekly-review-render.js"></script>
647 <script src="js/monthly-review-render.js"></script>
648 <!-- Domains -->
649 <script src="js/projects.js"></script>
650 <script src="js/tasks-filter.js"></script>
651 <script src="js/task-forms.js"></script>
652 <script src="js/task-board.js"></script>
653 <script src="js/attachments.js"></script>
654 <script src="js/autocomplete.js"></script>
655 <script src="js/address-highlight.js"></script>
656 <script src="js/compose-form.js"></script>
657 <script src="js/tasks.js"></script>
658 <script src="js/task-overview.js"></script>
659 <script src="js/events.js"></script>
660 <script src="js/events-calendar.js"></script>
661 <script src="js/emails-render.js"></script>
662 <script src="js/emails-compose.js"></script>
663 <script src="js/emails.js"></script>
664 <script src="js/email-accounts.js"></script>
665 <script src="js/contacts.js"></script>
666 <script src="js/contact-dashboard.js"></script>
667 <script src="js/plan-review-toggle.js"></script>
668 <script src="js/day-planning.js"></script>
669 <script src="js/weekly-review.js"></script>
670 <script src="js/monthly-review.js"></script>
671 <!-- Time Tracking -->
672 <script src="js/time-tracking.js"></script>
673 <script src="js/focus-timer.js"></script>
674 <script src="js/time-summary.js"></script>
675
676 <!-- Features (with domain dependencies) -->
677 <script src="js/bulk-actions.js"></script>
678 <script src="js/saved-views.js"></script>
679 <script src="js/search.js"></script>
680 <script src="js/keyboard.js"></script>
681
682 <!-- UI -->
683 <script src="js/settings.js"></script>
684 <script src="js/settings-sync.js"></script>
685 <script src="js/export.js"></script>
686 <script src="js/import.js"></script>
687 <script src="js/import-external.js"></script>
688 <script src="js/context-menus.js"></script>
689
690 <!-- Mobile interaction wiring (no-op on desktop) -->
691 <script src="js/mobile.js"></script>
692
693 <!-- OTA update notifications -->
694 <script src="js/shared-updater.js"></script>
695 <script src="js/updater.js"></script>
696 <script src="js/whats-new.js"></script>
697
698 <!-- Bootstrap -->
699 <script src="js/app.js"></script>
700 <script src="js/seed-data.js"></script>
701 </body>
702 </html>
703