Skip to main content

max / goingson

Rename the btn class family to the makeover-webview vocabulary makeover-webview emits .button; GoingsOn's class was .btn, so the two never collided and adoption would have been a silent no-op. This moves GO onto the shared name. btn -> button btn-<var> -> button--<var> Ten variants, not the four the stylesheet's own index listed: primary, secondary, sm, danger, icon, link, loading, ghost, text, and small. The double dash matches the .card--* and .badge--* convention already in use; .btn-primary's single dash was the odd one out. Only class contexts moved. "btn" is also a JS loop parameter and local const in around forty places, and per-feature ids like kebab-btn and view-toggle-btn merely end in the same three letters. Neither is the shared button class and neither was touched. btn-small had no CSS rule at all, so its three call sites were never small. They are button--sm now and will render small, which is the one visible change here and wants an eyeball. Regenerates styles.min.css, which is what index.html actually loads.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-29 20:36 UTC
Signed with PGP, not checked
Commit: 42ad3bc5a9cd084257e85422a22e39903a4f05fd
Parent: eb803f9
48 files changed, +394 insertions, -394 deletions
M Cargo.lock +4 -4
@@ -3390,15 +3390,15 @@
3390 3390
3391 3391 [[package]]
3392 3392 name = "makeover-layout"
3393 - version = "0.1.0"
3393 + version = "0.2.0"
3394 3394 source = "registry+https://github.com/rust-lang/crates.io-index"
3395 - checksum = "c6342972c67cb6a54ce0ae661e2a4060b548de16113578cac71ca5f7316991bb"
3395 + checksum = "a3ee0e7ee1b959eed5d3628ef7ca8901f00f5f62ae4c5601272fdd9a4d05052b"
3396 3396
3397 3397 [[package]]
3398 3398 name = "makeover-webview"
3399 - version = "0.1.0"
3399 + version = "0.2.0"
3400 3400 source = "registry+https://github.com/rust-lang/crates.io-index"
3401 - checksum = "5741881d62fc10d2ab194f5dd6aec2fc41e436dea2ea4bc9b2db12fded9b6a2d"
3401 + checksum = "30a958bd1d5ba4e8d292d3c90f40dbcc59e9e1ebb96e03c97c3f7d30ed713199"
3402 3402 dependencies = [
3403 3403 "makeover-layout",
3404 3404 ]
@@ -9,12 +9,12 @@
9 9 </head>
10 10 <body class="compose-window">
11 11 <div class="compose-toolbar">
12 - <button class="btn btn-primary" id="send-btn">Send</button>
12 + <button class="button button--primary" id="send-btn">Send</button>
13 13 <span id="reply-indicator" class="reply-indicator"></span>
14 - <button class="btn btn-secondary" id="save-draft-btn">Save Draft</button>
15 - <button class="btn btn-secondary" id="attach-btn">Attach</button>
14 + <button class="button button--secondary" id="save-draft-btn">Save Draft</button>
15 + <button class="button button--secondary" id="attach-btn">Attach</button>
16 16 <div class="toolbar-spacer"></div>
17 - <button class="btn btn-secondary" id="discard-btn">Discard</button>
17 + <button class="button button--secondary" id="discard-btn">Discard</button>
18 18 </div>
19 19
20 20 <!-- Fields rendered at DOMContentLoaded by composeForm.buildFieldsHtml.
@@ -56,8 +56,8 @@
56 56 <span class="sync-dot" id="sync-dot"></span>
57 57 <span class="sync-label" id="sync-label"></span>
58 58 </button>
59 - <button class="btn" data-act="settings.open" title="Settings" aria-label="Open settings">Settings</button>
60 - <button class="btn shortcut-hint-btn" data-act="keyboard.showShortcuts" title="Keyboard shortcuts (?)" aria-label="Show keyboard shortcuts">?</button>
59 + <button class="button" data-act="settings.open" title="Settings" aria-label="Open settings">Settings</button>
60 + <button class="button shortcut-hint-btn" data-act="keyboard.showShortcuts" title="Keyboard shortcuts (?)" aria-label="Show keyboard shortcuts">?</button>
61 61 </div>
62 62 </header>
63 63
@@ -80,18 +80,18 @@
80 80 <button class="view-toggle-btn active" data-mode="list" data-act="tasks.setViewMode" data-a1="list">List</button>
81 81 <button class="view-toggle-btn" data-mode="board" data-act="tasks.setViewMode" data-a1="board">Board</button>
82 82 </div>
83 - <button class="btn btn-secondary mobile-hide" data-act="keyboard.openQuickAddModal" title="Quick add (q)">Quick Add</button>
84 - <button class="btn btn-primary" data-act="tasks.openNew" title="New task (n)">+ New Task <kbd class="kbd-hint">n</kbd></button>
83 + <button class="button button--secondary mobile-hide" data-act="keyboard.openQuickAddModal" title="Quick add (q)">Quick Add</button>
84 + <button class="button button--primary" data-act="tasks.openNew" title="New task (n)">+ New Task <kbd class="kbd-hint">n</kbd></button>
85 85 </div>
86 86 </div>
87 87 <div id="task-bulk-actions" class="bulk-actions-bar hidden" role="toolbar" aria-label="Bulk task actions">
88 88 <span id="task-bulk-count" class="bulk-count">0 selected</span>
89 - <button class="btn btn-sm" data-act="bulk.completeTasks">Complete</button>
90 - <button class="btn btn-sm" data-act="bulk.setProjectTasks">Set Project</button>
91 - <button class="btn btn-sm" data-act="bulk.setPriorityTasks">Set Priority</button>
92 - <button class="btn btn-sm" data-act="bulk.snoozeTasks">Snooze</button>
93 - <button class="btn btn-sm btn-danger" data-act="bulk.deleteTasks">Delete</button>
94 - <button class="btn btn-sm bulk-select-all" data-act="bulk.selectAllTasks">Select All</button>
89 + <button class="button button--sm" data-act="bulk.completeTasks">Complete</button>
90 + <button class="button button--sm" data-act="bulk.setProjectTasks">Set Project</button>
91 + <button class="button button--sm" data-act="bulk.setPriorityTasks">Set Priority</button>
92 + <button class="button button--sm" data-act="bulk.snoozeTasks">Snooze</button>
93 + <button class="button button--sm button--danger" data-act="bulk.deleteTasks">Delete</button>
94 + <button class="button button--sm bulk-select-all" data-act="bulk.selectAllTasks">Select All</button>
95 95 </div>
96 96 <div class="mobile-sort-bar" id="task-mobile-sort">
97 97 <button class="mobile-filter-toggle" data-act="tasks.toggleMobileFilters">Filters</button>
@@ -132,8 +132,8 @@
132 132 </label>
133 133 <div class="filter-actions">
134 134 <span id="task-count" class="filter-count" aria-live="polite"></span>
135 - <button class="btn btn-link" data-act="search.open" title="Search with is:overdue, tag:work, in:Project and more">Advanced search</button>
136 - <button class="btn btn-link" data-act="tasks.clearFilters">Clear filters</button>
135 + <button class="button button--link" data-act="search.open" title="Search with is:overdue, tag:work, in:Project and more">Advanced search</button>
136 + <button class="button button--link" data-act="tasks.clearFilters">Clear filters</button>
137 137 </div>
138 138 </div>
139 139 <div class="task-table" id="task-table" role="grid" aria-label="Tasks list">
@@ -168,9 +168,9 @@
168 168 </div>
169 169 <!-- Pagination -->
170 170 <div id="task-pagination" class="pagination-controls hidden" role="navigation" aria-label="Task list pagination">
171 - <button class="btn btn-sm" id="task-prev-page" data-act="tasks.goToPage" data-a1="prev" disabled aria-label="Previous page">&larr; Previous</button>
171 + <button class="button button--sm" id="task-prev-page" data-act="tasks.goToPage" data-a1="prev" disabled aria-label="Previous page">&larr; Previous</button>
172 172 <span id="task-page-info" class="pagination-info">Page 1 of 1</span>
173 - <button class="btn btn-sm" id="task-next-page" data-act="tasks.goToPage" data-a1="next" disabled aria-label="Next page">Next &rarr;</button>
173 + <button class="button button--sm" id="task-next-page" data-act="tasks.goToPage" data-a1="next" disabled aria-label="Next page">Next &rarr;</button>
174 174 </div>
175 175 </div>
176 176
@@ -180,7 +180,7 @@
180 180 <h2 class="page-title">Projects</h2>
181 181 <div class="row-flex row-flex-peer">
182 182 <span id="projects-filter-slot"></span>
183 - <button class="btn btn-primary" data-act="projects.openNew" title="New project (n)">+ New Project <kbd class="kbd-hint">n</kbd></button>
183 + <button class="button button--primary" data-act="projects.openNew" title="New project (n)">+ New Project <kbd class="kbd-hint">n</kbd></button>
184 184 </div>
185 185 </div>
186 186 <div class="cards-grid" id="projects-grid">
@@ -207,8 +207,8 @@
207 207 <option value="Resolved">Resolved</option>
208 208 <option value="all">All</option>
209 209 </select>
210 - <button class="btn btn-secondary" id="problems-refresh" data-act="problems.pull" title="Pull the latest from every configured source">Refresh</button>
211 - <button class="btn btn-secondary" data-act="problems.configure" title="Configure the wam endpoint">Sources</button>
210 + <button class="button button--secondary" id="problems-refresh" data-act="problems.pull" title="Pull the latest from every configured source">Refresh</button>
211 + <button class="button button--secondary" data-act="problems.configure" title="Configure the wam endpoint">Sources</button>
212 212 </div>
213 213 </div>
214 214 <p class="view-hint">Candidates, not work. Ranked by painhours, so anything left untriaged climbs on its own. Promote the ones worth doing.</p>
@@ -224,10 +224,10 @@
224 224 <div id="project-dashboard-view" class="subview hidden">
225 225 <div class="page-header">
226 226 <div class="row-flex row-flex-section">
227 - <button class="btn btn-secondary" data-act="projects.closeDashboard">&larr; Back</button>
227 + <button class="button button--secondary" data-act="projects.closeDashboard">&larr; Back</button>
228 228 <h2 class="page-title" id="project-dashboard-title">Project</h2>
229 229 </div>
230 - <button class="btn btn-secondary" id="edit-project-btn" data-act="projects.editCurrent">Edit Project</button>
230 + <button class="button button--secondary" id="edit-project-btn" data-act="projects.editCurrent">Edit Project</button>
231 231 </div>
232 232 <p id="project-dashboard-description" class="project-dashboard-desc"></p>
233 233 <div id="project-milestones-section" class="milestones-section"></div>
@@ -235,7 +235,7 @@
235 235 <div class="dashboard-column">
236 236 <div class="dashboard-column-header">
237 237 <h3>Tasks</h3>
238 - <button class="btn btn-sm btn-primary" data-act="projects.addTask">+ Add</button>
238 + <button class="button button--sm button--primary" data-act="projects.addTask">+ Add</button>
239 239 </div>
240 240 <div id="project-tasks-list" class="dashboard-list">
241 241 <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>
@@ -244,7 +244,7 @@
244 244 <div class="dashboard-column">
245 245 <div class="dashboard-column-header">
246 246 <h3>Events</h3>
247 - <button class="btn btn-sm btn-primary" data-act="projects.addEvent">+ Add</button>
247 + <button class="button button--sm button--primary" data-act="projects.addEvent">+ Add</button>
248 248 </div>
249 249 <div id="project-events-list" class="dashboard-list">
250 250 <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>
@@ -253,7 +253,7 @@
253 253 <div class="dashboard-column">
254 254 <div class="dashboard-column-header">
255 255 <h3>Emails</h3>
256 - <button class="btn btn-sm btn-primary" data-act="projects.linkEmail">+ Link</button>
256 + <button class="button button--sm button--primary" data-act="projects.linkEmail">+ Link</button>
257 257 </div>
258 258 <div id="project-emails-list" class="dashboard-list">
259 259 <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>
@@ -262,7 +262,7 @@
262 262 <div class="dashboard-column">
263 263 <div class="dashboard-column-header">
264 264 <h3>Attachments</h3>
265 - <button class="btn btn-sm btn-primary" id="project-attach-btn">+ Attach</button>
265 + <button class="button button--sm button--primary" id="project-attach-btn">+ Attach</button>
266 266 </div>
267 267 <div id="project-attachments-list" class="dashboard-list">
268 268 <div class="empty-state empty-state--dashboard">No attachments</div>
@@ -274,7 +274,7 @@
274 274 <div id="task-overview-view" class="subview hidden">
275 275 <div class="page-header">
276 276 <div class="row-flex row-flex-section">
277 - <button class="btn btn-secondary" data-act="taskOverview.close">&larr; Back</button>
277 + <button class="button button--secondary" data-act="taskOverview.close">&larr; Back</button>
278 278 <h2 class="page-title" id="task-overview-title">Task Overview</h2>
279 279 </div>
280 280 <div id="task-overview-actions"></div>
@@ -303,9 +303,9 @@
303 303 <div id="day-plan-view" class="subview" role="tabpanel" aria-labelledby="day-plan-tab">
304 304 <div class="page-header">
305 305 <div class="day-plan-nav">
306 - <button class="btn btn-secondary" data-act="dayPlan.previousDay" title="Previous day ([)">&larr;</button>
307 - <button class="btn btn-secondary" data-act="dayPlan.goToToday">Today</button>
308 - <button class="btn btn-secondary" data-act="dayPlan.nextDay" title="Next day (])">&rarr;</button>
306 + <button class="button button--secondary" data-act="dayPlan.previousDay" title="Previous day ([)">&larr;</button>
307 + <button class="button button--secondary" data-act="dayPlan.goToToday">Today</button>
308 + <button class="button button--secondary" data-act="dayPlan.nextDay" title="Next day (])">&rarr;</button>
309 309 <input type="date" id="day-plan-date" class="day-plan-date-picker" data-change="dayPlan.onDatePickerChange">
310 310 <span id="day-plan-date-display" class="day-plan-date-display"></span>
311 311 </div>
@@ -340,7 +340,7 @@
340 340 </div>
341 341 </div>
342 342 <div class="finish-review-bar">
343 - <button class="btn btn-primary finish-review-btn" id="day-finish-review-btn" data-act="dayPlanSchedule.openFinishReviewModal">
343 + <button class="button button--primary finish-review-btn" id="day-finish-review-btn" data-act="dayPlanSchedule.openFinishReviewModal">
344 344 Finish &amp; Review
345 345 </button>
346 346 </div>
@@ -364,9 +364,9 @@
364 364 <div id="monthly-review-view" class="subview hidden" role="tabpanel" aria-labelledby="monthly-review-tab">
365 365 <div class="page-header">
366 366 <div class="monthly-review-nav">
367 - <button class="btn btn-secondary" data-act="monthlyReview.previousMonth" title="Previous month">&larr;</button>
368 - <button class="btn btn-secondary" data-act="monthlyReview.goToCurrentMonth">This Month</button>
369 - <button class="btn btn-secondary" data-act="monthlyReview.nextMonth" title="Next month">&rarr;</button>
367 + <button class="button button--secondary" data-act="monthlyReview.previousMonth" title="Previous month">&larr;</button>
368 + <button class="button button--secondary" data-act="monthlyReview.goToCurrentMonth">This Month</button>
369 + <button class="button button--secondary" data-act="monthlyReview.nextMonth" title="Next month">&rarr;</button>
370 370 <span id="monthly-review-month-display" class="monthly-review-month-display"></span>
371 371 </div>
372 372 <span id="month-review-status-badge" class="review-status hidden"></span>
@@ -393,7 +393,7 @@
393 393 <div id="events-view" class="subview hidden" role="tabpanel" aria-labelledby="events-tab">
394 394 <div class="page-header">
395 395 <h2 class="page-title">Events</h2>
396 - <button class="btn btn-primary" data-act="events.openNew" title="New event (n)">+ New Event <kbd class="kbd-hint">n</kbd></button>
396 + <button class="button button--primary" data-act="events.openNew" title="New event (n)">+ New Event <kbd class="kbd-hint">n</kbd></button>
397 397 </div>
398 398 <div class="filter-bar" id="events-filter-bar">
399 399 <label class="filter-checkbox" title="Include events hidden until a later date">
@@ -403,9 +403,9 @@
403 403 </div>
404 404 <div id="events-bulk-bar" class="bulk-actions-bar hidden">
405 405 <span class="bulk-count">0 selected</span>
406 - <button class="btn btn-sm" data-act="events.selectAllEvents">Select All</button>
407 - <button class="btn btn-sm btn-danger" data-act="events.bulkDelete">Delete</button>
408 - <button class="btn btn-sm" data-act="events.clearEventSelection">Cancel</button>
406 + <button class="button button--sm" data-act="events.selectAllEvents">Select All</button>
407 + <button class="button button--sm button--danger" data-act="events.bulkDelete">Delete</button>
408 + <button class="button button--sm" data-act="events.clearEventSelection">Cancel</button>
409 409 </div>
410 410 <div class="events-list" id="events-list">
411 411 <details class="past-events-section hidden" id="recurring-events-section" open>
@@ -473,8 +473,8 @@
473 473 <div class="page-header">
474 474 <h2 class="page-title">Emails</h2>
475 475 <div class="row-flex row-flex-peer">
476 - <button class="btn btn-secondary mobile-hide" data-act="emails.openDrafts">Drafts</button>
477 - <button class="btn btn-primary" data-act="emails.openCompose" title="Compose email (n)">+ Compose</button>
476 + <button class="button button--secondary mobile-hide" data-act="emails.openDrafts">Drafts</button>
477 + <button class="button button--primary" data-act="emails.openCompose" title="Compose email (n)">+ Compose</button>
478 478 </div>
479 479 </div>
480 480 <div class="email-filter-row mb-peer">
@@ -489,11 +489,11 @@
489 489 </div>
490 490 <div id="email-bulk-actions" class="bulk-actions-bar hidden" role="toolbar" aria-label="Bulk email actions">
491 491 <span id="email-bulk-count" class="bulk-count">0 selected</span>
492 - <button class="btn btn-sm" data-act="bulk.markEmailsRead">Mark Read</button>
493 - <button class="btn btn-sm" data-act="bulk.archiveEmails">Archive</button>
494 - <button class="btn btn-sm" data-act="bulk.snoozeEmails">Snooze</button>
495 - <button class="btn btn-sm btn-danger" data-act="bulk.deleteEmails">Delete</button>
496 - <button class="btn btn-sm bulk-select-all" data-act="bulk.selectAllEmails">Select All</button>
492 + <button class="button button--sm" data-act="bulk.markEmailsRead">Mark Read</button>
493 + <button class="button button--sm" data-act="bulk.archiveEmails">Archive</button>
494 + <button class="button button--sm" data-act="bulk.snoozeEmails">Snooze</button>
495 + <button class="button button--sm button--danger" data-act="bulk.deleteEmails">Delete</button>
496 + <button class="button button--sm bulk-select-all" data-act="bulk.selectAllEmails">Select All</button>
497 497 </div>
498 498 <div class="card card--shell email-list" id="email-list-wrapper" role="list">
499 499 <div class="email-list-container well" id="email-list" aria-live="polite">
@@ -507,9 +507,9 @@
507 507 </div>
508 508 <!-- Pagination -->
509 509 <div id="email-pagination" class="pagination-controls hidden" role="navigation" aria-label="Email list pagination">
510 - <button class="btn btn-sm" id="email-prev-page" data-act="emails.goToPage" data-a1="prev" disabled aria-label="Previous page">&larr; Previous</button>
510 + <button class="button button--sm" id="email-prev-page" data-act="emails.goToPage" data-a1="prev" disabled aria-label="Previous page">&larr; Previous</button>
511 511 <span id="email-page-info" class="pagination-info">Page 1 of 1</span>
512 - <button class="btn btn-sm" id="email-next-page" data-act="emails.goToPage" data-a1="next" disabled aria-label="Next page">Next &rarr;</button>
512 + <button class="button button--sm" id="email-next-page" data-act="emails.goToPage" data-a1="next" disabled aria-label="Next page">Next &rarr;</button>
513 513 </div>
514 514 </div>
515 515
@@ -522,15 +522,15 @@
522 522 <select class="filter-select" id="contacts-tag-filter" data-change="contacts.filterByTag">
523 523 <option value="">All Tags</option>
524 524 </select>
525 - <button class="btn btn-primary" data-act="contacts.openNew" title="New contact (n)">+ New Contact <kbd class="kbd-hint">n</kbd></button>
525 + <button class="button button--primary" data-act="contacts.openNew" title="New contact (n)">+ New Contact <kbd class="kbd-hint">n</kbd></button>
526 526 </div>
527 527 </div>
528 528 <div id="contacts-bulk-bar" class="bulk-actions-bar hidden">
529 529 <span class="bulk-count">0 selected</span>
530 - <button class="btn btn-sm" data-act="contacts.selectAll">Select All</button>
531 - <button class="btn btn-sm" data-act="contacts.bulkTag">Tag</button>
532 - <button class="btn btn-sm btn-danger" data-act="contacts.bulkDelete">Delete</button>
533 - <button class="btn btn-sm" data-act="contacts.clearSelection">Cancel</button>
530 + <button class="button button--sm" data-act="contacts.selectAll">Select All</button>
531 + <button class="button button--sm" data-act="contacts.bulkTag">Tag</button>
532 + <button class="button button--sm button--danger" data-act="contacts.bulkDelete">Delete</button>
533 + <button class="button button--sm" data-act="contacts.clearSelection">Cancel</button>
534 534 </div>
535 535 <div class="cards-grid-scroll well" id="contacts-grid">
536 536 <div class="skeleton-shimmer" aria-label="Loading contacts">
@@ -544,7 +544,7 @@
544 544 <div id="contact-dashboard-view" class="subview hidden">
545 545 <div class="page-header">
546 546 <div class="row-flex row-flex-section">
547 - <button class="btn btn-secondary" data-act="contactDashboard.close">&larr; Back</button>
547 + <button class="button button--secondary" data-act="contactDashboard.close">&larr; Back</button>
548 548 <h2 class="page-title" id="contact-dashboard-title">Contact</h2>
549 549 </div>
550 550 <div id="contact-dashboard-actions"></div>
@@ -569,7 +569,7 @@
569 569 <div id="settings-view" class="settings-overlay-card">
570 570 <div class="settings-page-layout">
571 571 <nav class="settings-sidebar">
572 - <button class="btn-link mb-section settings-back" data-act="settings.goBack" aria-label="Close settings">&larr; Close</button>
572 + <button class="button--link mb-section settings-back" data-act="settings.goBack" aria-label="Close settings">&larr; Close</button>
573 573 <h2 class="sr-only" id="settings-overlay-title">Settings</h2>
574 574 <div class="settings-nav-items">
575 575 <button class="settings-nav-item active" data-section="appearance" data-act="settings.showSection" data-a1="appearance"><span class="settings-nav-label">Appearance</span><span class="settings-nav-desc">Theme</span></button>
@@ -609,7 +609,7 @@
609 609 <!-- Task Detail Drawer (Phase 7 Tier 6: side-drawer task detail) -->
610 610 <aside id="task-detail-drawer" class="task-drawer" role="dialog" aria-modal="false" aria-labelledby="task-drawer-title" aria-hidden="true">
611 611 <div class="task-drawer-header">
612 - <button class="btn btn-sm btn-secondary task-drawer-close" data-act="taskOverview.close" title="Close (Esc)" aria-label="Close task detail">&times;</button>
612 + <button class="button button--sm button--secondary task-drawer-close" data-act="taskOverview.close" title="Close (Esc)" aria-label="Close task detail">&times;</button>
613 613 <h2 class="task-drawer-title" id="task-drawer-title">Task</h2>
614 614 <div class="task-drawer-actions" id="task-drawer-actions"></div>
615 615 </div>
@@ -8,10 +8,10 @@
8 8 2. Use a LAYOUT PRIMITIVE to position content (.row-flex + .row-flex-{peer,
9 9 group,section}, .row,
10 10 .stack-{peer,group,section})
11 - 3. Use a COMPONENT PRIMITIVE for a UI element (.card, .btn, .form-input,
11 + 3. Use a COMPONENT PRIMITIVE for a UI element (.card, .button, .form-input,
12 12 .form-select, .modal, .badge,
13 13 .tag, .toggle-switch)
14 - 4. Extend a primitive with a modifier (.btn-primary, .btn-sm,
14 + 4. Extend a primitive with a modifier (.button--primary, .button--sm,
15 15 .form-select--compact,
16 16 .subtask-item--linked)
17 17 5. ONLY THEN consider a new class | and add it to the right
@@ -55,7 +55,7 @@
55 55 8. Main Content & Page Header
56 56
57 57 BAND: COMPONENT PRIMITIVES & WIDGETS
58 - 9. Buttons | .btn + variants/sizes
58 + 9. Buttons | .button + variants/sizes
59 59 10. Quick Add Input
60 60 11. Cards
61 61 12. Tags & Badges
@@ -149,7 +149,7 @@
149 149 .stack (vertical) + gap modifier
150 150
151 151 COMPONENT PRIMITIVES
152 - .btn + .btn-primary / -secondary / -danger / -sm
152 + .button + .button--primary / --secondary / --danger / --sm
153 153 .card + .card--list-item / --shell / --muted (compact / container / info-panel)
154 154 .form-input + .form-input--ghost
155 155 .form-select + .form-select--compact / --ghost
@@ -165,8 +165,8 @@
165 165 .empty-state
166 166
167 167 CONTROL MODIFIERS
168 - Sizes: .btn-sm
169 - Intents: .btn-primary / -secondary / -danger
168 + Sizes: .button--sm
169 + Intents: .button--primary / --secondary / --danger
170 170 Shapes: .form-select--compact / --ghost, .form-input--ghost
171 171
172 172 UI MODE STRATEGY (do not casually merge)
@@ -409,7 +409,7 @@
409 409 bottom tab bar, where a long-press otherwise highlights the label and
410 410 you have to dodge it). Content text: inputs, textareas, contenteditable,
411 411 and anything explicitly marked .selectable, stays selectable. */
412 - .btn,
412 + .button,
413 413 .tab,
414 414 .tab-label,
415 415 .tab-navigation,
@@ -641,7 +641,7 @@
641 641 }
642 642
643 643 /* 9. Buttons */
644 - .btn {
644 + .button {
645 645 display: inline-flex;
646 646 align-items: center;
647 647 justify-content: center;
@@ -658,65 +658,65 @@
658 658 box-shadow: var(--bevel-raised);
659 659 }
660 660
661 - .btn:hover {
661 + .button:hover {
662 662 background: var(--surface-overlay);
663 663 }
664 664
665 665 /* Pressed inverts the bevel and drops the fill a step, which is the whole
666 666 idiom: no offset, no translate, the button reads as pushed into the page. */
667 - .btn:active {
667 + .button:active {
668 668 background: var(--surface-sunken);
669 669 box-shadow: var(--bevel-inset);
670 670 }
671 671
672 672 /* Disabled keeps its bevel. The object is still there, its label is just
673 673 unavailable, which is what greying the content says. */
674 - .btn:disabled {
674 + .button:disabled {
675 675 color: var(--content-muted);
676 676 border-color: var(--content-muted);
677 677 cursor: not-allowed;
678 678 }
679 679
680 - .btn:disabled:hover {
680 + .button:disabled:hover {
681 681 background: var(--surface-raised);
682 682 }
683 683
684 - .btn:disabled:active {
684 + .button:disabled:active {
685 685 box-shadow: var(--bevel-raised);
686 686 }
687 687
688 - .btn-primary {
688 + .button--primary {
689 689 background-color: var(--action);
690 690 color: var(--content-on-action);
691 691 }
692 692
693 - .btn-primary:hover {
693 + .button--primary:hover {
694 694 background-color: color-mix(in srgb, var(--action) 85%, black);
695 695 }
696 696
697 - .btn-primary:active {
697 + .button--primary:active {
698 698 background-color: color-mix(in srgb, var(--action) 70%, black);
699 699 }
700 700
701 - .btn-secondary {
701 + .button--secondary {
702 702 background-color: var(--surface-overlay);
703 703 color: var(--content);
704 704 }
705 705
706 - .btn-danger {
706 + .button--danger {
707 707 background-color: var(--danger);
708 708 color: var(--content-on-action);
709 709 }
710 710
711 - .btn-danger:hover {
711 + .button--danger:hover {
712 712 background-color: color-mix(in srgb, var(--danger) 85%, black);
713 713 }
714 714
715 - .btn-danger:active {
715 + .button--danger:active {
716 716 background-color: color-mix(in srgb, var(--danger) 70%, black);
717 717 }
718 718
719 - .btn-sm {
719 + .button--sm {
720 720 padding: var(--gap-bound) var(--gap-group);
721 721 font-size: var(--font-size-md);
722 722 }
@@ -2363,7 +2363,7 @@
2363 2363 .bulk-modal-prompt--wide {
2364 2364 margin-bottom: var(--gap-section);
2365 2365 }
2366 - /* Marker class kept for .ui-mode-mobile padding override only. Base styling: .btn.btn-sm + .w-full.text-left. */
2366 + /* Marker class kept for .ui-mode-mobile padding override only. Base styling: .button.button--sm + .w-full.text-left. */
2367 2367 .bulk-modal-scroll {
2368 2368 max-height: 300px;
2369 2369 overflow-y: auto;
@@ -3055,7 +3055,7 @@
3055 3055 display: flex;
3056 3056 gap: var(--gap-peer);
3057 3057 }
3058 - .account-row-quick .btn {
3058 + .account-row-quick .button {
3059 3059 flex: 1;
3060 3060 }
3061 3061 .account-list {
@@ -3072,7 +3072,7 @@
3072 3072 flex-wrap: wrap;
3073 3073 gap: var(--gap-peer);
3074 3074 }
3075 - .oauth-buttons .btn {
3075 + .oauth-buttons .button {
3076 3076 flex: 1;
3077 3077 min-width: 120px;
3078 3078 }
@@ -3253,7 +3253,7 @@
3253 3253 cursor: pointer;
3254 3254 }
3255 3255
3256 - .btn-link {
3256 + .button--link {
3257 3257 background: none;
3258 3258 border: none;
3259 3259 box-shadow: none;
@@ -3264,7 +3264,7 @@
3264 3264 padding: var(--gap-peer);
3265 3265 }
3266 3266
3267 - .btn-link:hover {
3267 + .button--link:hover {
3268 3268 box-shadow: none;
3269 3269 color: var(--content);
3270 3270 }
@@ -3276,7 +3276,7 @@
3276 3276 font-size: var(--font-size-sm);
3277 3277 margin-top: var(--gap-section);
3278 3278 }
3279 - .form-alt-path .btn-link { padding: 0; font-size: inherit; }
3279 + .form-alt-path .button--link { padding: 0; font-size: inherit; }
3280 3280
3281 3281 /* 24. Responsive - Large Screens & Tablet */
3282 3282
@@ -3448,14 +3448,14 @@
3448 3448 font-size: var(--font-size-base);
3449 3449 }
3450 3450
3451 - .pagination-controls .btn:disabled {
3451 + .pagination-controls .button:disabled {
3452 3452 opacity: 0.5;
3453 3453 cursor: not-allowed;
3454 3454 }
3455 3455
3456 3456 /* 28. Focus & Keyboard Accessibility */
3457 3457 .tab:focus-visible,
3458 - .btn:focus-visible,
3458 + .button:focus-visible,
3459 3459 .form-input:focus-visible,
3460 3460 .form-select:focus-visible,
3461 3461 .form-textarea:focus-visible,
@@ -3925,17 +3925,17 @@
3925 3925 }
3926 3926
3927 3927 /* Button loading state */
3928 - .btn-loading {
3928 + .button--loading {
3929 3929 position: relative;
3930 3930 pointer-events: none;
3931 3931 opacity: 0.8;
3932 3932 }
3933 3933
3934 - .btn-loading .btn-text {
3934 + .button--loading .button--text {
3935 3935 visibility: hidden;
3936 3936 }
3937 3937
3938 - .btn-loading::after {
3938 + .button--loading::after {
3939 3939 content: '';
3940 3940 position: absolute;
3941 3941 left: 50%;
@@ -4548,7 +4548,7 @@
4548 4548 }
4549 4549
4550 4550 /* 41. Settings */
4551 - /* Marker class on the header `?` button. Extends .btn with mono font and
4551 + /* Marker class on the header `?` button. Extends .button with mono font and
4552 4552 a fixed min-width so the single-character glyph stays centered. Mobile
4553 4553 touch passes hide it (see §59 + body.is-touch rule below). */
4554 4554 .shortcut-hint-btn {
@@ -4899,7 +4899,7 @@
4899 4899 margin-right: var(--gap-bound);
4900 4900 }
4901 4901
4902 - /* Kebab menu button, extends .btn-icon with hover-reveal + bigger font. */
4902 + /* Kebab menu button, extends .button--icon with hover-reveal + bigger font. */
4903 4903 .kebab-btn {
4904 4904 font-size: var(--font-size-xl);
4905 4905 padding: var(--step-tight) var(--step-snug);
@@ -4979,13 +4979,13 @@
4979 4979 font-family: var(--font-heading);
4980 4980 }
4981 4981
4982 - .bulk-actions-bar .btn {
4982 + .bulk-actions-bar .button {
4983 4983 background: var(--surface-raised);
4984 4984 border: var(--border-width-sm) solid var(--border);
4985 4985 color: var(--content);
4986 4986 }
4987 4987
4988 - .bulk-actions-bar .btn:hover {
4988 + .bulk-actions-bar .button:hover {
4989 4989 background: var(--surface-overlay);
4990 4990 }
4991 4991
@@ -5021,7 +5021,7 @@
5021 5021 gap: var(--gap-peer);
5022 5022 }
5023 5023
5024 - /* Selected state for quick-pick time slots. Base styling comes from .btn.btn-sm.btn-secondary. */
5024 + /* Selected state for quick-pick time slots. Base styling comes from .button.button--sm.button--secondary. */
5025 5025 .time-block-quick-btn.selected {
5026 5026 background: var(--action);
5027 5027 color: var(--content-on-action);
@@ -5236,7 +5236,7 @@
5236 5236 overflow: hidden;
5237 5237 }
5238 5238
5239 - .btn-icon {
5239 + .button--icon {
5240 5240 background: none;
5241 5241 border: none;
5242 5242 box-shadow: none;
@@ -5247,7 +5247,7 @@
5247 5247 line-height: 1;
5248 5248 }
5249 5249
5250 - .btn-icon:hover {
5250 + .button--icon:hover {
5251 5251 color: var(--content);
5252 5252 }
5253 5253
@@ -5485,13 +5485,13 @@
5485 5485 .tabs,
5486 5486 .filter-bar,
5487 5487 .pagination,
5488 - .btn,
5488 + .button,
5489 5489 .modal-overlay,
5490 5490 .toast,
5491 5491 .context-menu,
5492 5492 .review-actions-grid,
5493 - .focus-section .btn,
5494 - .focus-slot .btn,
5493 + .focus-section .button,
5494 + .focus-slot .button,
5495 5495 .focus-suggestion,
5496 5496 .tab-badge,
5497 5497 .tab-status-dot,
@@ -6417,7 +6417,7 @@
6417 6417 outline-offset: 2px;
6418 6418 }
6419 6419
6420 - /* Suggested task buttons carry no press hack of their own: .btn:active
6420 + /* Suggested task buttons carry no press hack of their own: .button:active
6421 6421 inverts its bevel, which is the pressed state for every button. */
6422 6422
6423 6423 /* §52 vacated 2026-05-24, weekly-review print styles consolidated into §48. */
@@ -6677,7 +6677,7 @@
6677 6677 text-decoration: line-through;
6678 6678 }
6679 6679
6680 - /* Extends .btn-icon with bigger font, fixed width, and parent-driven color overrides. */
6680 + /* Extends .button--icon with bigger font, fixed width, and parent-driven color overrides. */
6681 6681 .month-goal-status-btn {
6682 6682 font-size: var(--font-size-lg);
6683 6683 padding: 0;
@@ -6694,7 +6694,7 @@
6694 6694 font-size: var(--font-size-base);
6695 6695 }
6696 6696
6697 - /* Extends .btn-icon with hover-reveal opacity and tertiary color. */
6697 + /* Extends .button--icon with hover-reveal opacity and tertiary color. */
6698 6698 .month-goal-delete-btn {
6699 6699 color: var(--content-muted);
6700 6700 padding: 0 var(--step-tight);
@@ -7029,7 +7029,7 @@
7029 7029 color: var(--danger);
7030 7030 }
7031 7031
7032 - button.milestone-reorder-btn.btn {
7032 + button.milestone-reorder-btn.button {
7033 7033 font-size: var(--font-size-xxs);
7034 7034 padding: var(--step-hair) var(--step-snug);
7035 7035 line-height: 1;
@@ -7357,7 +7357,7 @@
7357 7357 }
7358 7358
7359 7359 /* Tasks page-header: Quick Add + New Task are hidden on mobile (see
7360 - .mobile-hide / .btn-primary rules), so only the view-toggle remains
7360 + .mobile-hide / .button--primary rules), so only the view-toggle remains
7361 7361 and takes the full row. */
7362 7362 .ui-mode-mobile #tasks-view .page-header > .row-flex {
7363 7363 grid-template-columns: 1fr;
@@ -7403,7 +7403,7 @@
7403 7403 }
7404 7404 /* Restore per-button borders/radii, the desktop segmented-strip rule
7405 7405 (no right border, square corners) doesn't apply here on mobile. */
7406 - .ui-mode-mobile #day-plan-view .day-plan-nav .btn {
7406 + .ui-mode-mobile #day-plan-view .day-plan-nav .button {
7407 7407 flex: 0 0 auto;
7408 7408 border-radius: var(--radius-sm);
7409 7409 border-right-width: var(--border-width);
@@ -7433,8 +7433,8 @@
7433 7433 /* Inside the new grid cells, undo the segmented-button styling (no
7434 7434 right border, square corners) inherited from the desktop page-header
7435 7435 rule, grid already gives equal sizing. */
7436 - .ui-mode-mobile #tasks-view .page-header > .row-flex .btn,
7437 - .ui-mode-mobile #contacts-view .page-header > .row-flex .btn {
7436 + .ui-mode-mobile #tasks-view .page-header > .row-flex .button,
7437 + .ui-mode-mobile #contacts-view .page-header > .row-flex .button {
7438 7438 border-radius: var(--radius-sm);
7439 7439 border-right-width: var(--border-width);
7440 7440 }
@@ -7457,7 +7457,7 @@
7457 7457 flex-wrap: wrap;
7458 7458 }
7459 7459
7460 - .ui-mode-mobile .page-header .btn-primary {
7460 + .ui-mode-mobile .page-header .button--primary {
7461 7461 display: none;
7462 7462 }
7463 7463
@@ -7474,10 +7474,10 @@
7474 7474 gap: 0 !important;
7475 7475 flex-wrap: wrap;
7476 7476 }
7477 - .ui-mode-mobile .page-header > div .btn,
7478 - .ui-mode-mobile #emails-view .page-header > div .btn,
7479 - .ui-mode-mobile #contacts-view .page-header > div .btn,
7480 - .ui-mode-mobile .bulk-actions-bar .btn {
7477 + .ui-mode-mobile .page-header > div .button,
7478 + .ui-mode-mobile #emails-view .page-header > div .button,
7479 + .ui-mode-mobile #contacts-view .page-header > div .button,
7480 + .ui-mode-mobile .bulk-actions-bar .button {
7481 7481 flex: 1 1 0;
7482 7482 min-width: 0;
7483 7483 padding: var(--gap-bound) var(--gap-peer);
@@ -7486,23 +7486,23 @@
7486 7486 border-right-width: 0;
7487 7487 white-space: nowrap;
7488 7488 }
7489 - .ui-mode-mobile .page-header > div .btn:first-child,
7490 - .ui-mode-mobile #emails-view .page-header > div .btn:first-child,
7491 - .ui-mode-mobile #contacts-view .page-header > div .btn:first-child,
7492 - .ui-mode-mobile .bulk-actions-bar .btn:first-of-type {
7489 + .ui-mode-mobile .page-header > div .button:first-child,
7490 + .ui-mode-mobile #emails-view .page-header > div .button:first-child,
7491 + .ui-mode-mobile #contacts-view .page-header > div .button:first-child,
7492 + .ui-mode-mobile .bulk-actions-bar .button:first-of-type {
7493 7493 border-top-left-radius: var(--radius-sm);
7494 7494 border-bottom-left-radius: var(--radius-sm);
7495 7495 }
7496 - /* Right-cap the visually-last button. `.btn-primary` (Compose) is hidden
7496 + /* Right-cap the visually-last button. `.button--primary` (Compose) is hidden
7497 7497 on mobile via display:none but stays in the DOM, so `:last-child` would
7498 7498 pick the hidden one. Cover both: actual last child, or the button
7499 7499 immediately before a hidden primary. */
7500 - .ui-mode-mobile .page-header > div .btn:last-child,
7501 - .ui-mode-mobile .page-header > div .btn:has(+ .btn-primary),
7502 - .ui-mode-mobile #emails-view .page-header > div .btn:last-child,
7503 - .ui-mode-mobile #emails-view .page-header > div .btn:has(+ .btn-primary),
7504 - .ui-mode-mobile #contacts-view .page-header > div .btn:last-child,
7505 - .ui-mode-mobile #contacts-view .page-header > div .btn:has(+ .btn-primary) {
7500 + .ui-mode-mobile .page-header > div .button:last-child,
7501 + .ui-mode-mobile .page-header > div .button:has(+ .button--primary),
7502 + .ui-mode-mobile #emails-view .page-header > div .button:last-child,
7503 + .ui-mode-mobile #emails-view .page-header > div .button:has(+ .button--primary),
7504 + .ui-mode-mobile #contacts-view .page-header > div .button:last-child,
7505 + .ui-mode-mobile #contacts-view .page-header > div .button:has(+ .button--primary) {
7506 7506 border-top-right-radius: var(--radius-sm);
7507 7507 border-bottom-right-radius: var(--radius-sm);
7508 7508 border-right-width: var(--border-width);
@@ -7512,11 +7512,11 @@
7512 7512 .ui-mode-mobile .bulk-actions-bar {
7513 7513 gap: 0;
7514 7514 }
7515 - .ui-mode-mobile .bulk-actions-bar .btn:not(.bulk-select-all) + .bulk-select-all {
7515 + .ui-mode-mobile .bulk-actions-bar .button:not(.bulk-select-all) + .bulk-select-all {
7516 7516 border-right-width: var(--border-width);
7517 7517 border-radius: var(--radius-sm);
7518 7518 }
7519 - .ui-mode-mobile .bulk-actions-bar .btn:not(.bulk-select-all):nth-last-of-type(2) {
7519 + .ui-mode-mobile .bulk-actions-bar .button:not(.bulk-select-all):nth-last-of-type(2) {
7520 7520 border-top-right-radius: var(--radius-sm);
7521 7521 border-bottom-right-radius: var(--radius-sm);
7522 7522 border-right-width: var(--border-width);
@@ -7906,7 +7906,7 @@
7906 7906 box-shadow: 0 -4px 12px rgba(0,0,0,0.15);
7907 7907 }
7908 7908
7909 - .ui-mode-mobile .pagination-controls .btn {
7909 + .ui-mode-mobile .pagination-controls .button {
7910 7910 font-size: var(--font-size-sm);
7911 7911 }
7912 7912
@@ -7935,15 +7935,15 @@
7935 7935 box-shadow: var(--bevel-raised);
7936 7936 }
7937 7937
7938 - .btn:hover {
7938 + .button:hover {
7939 7939 background: var(--surface-raised);
7940 7940 }
7941 7941
7942 - .btn-primary:hover {
7942 + .button--primary:hover {
7943 7943 background-color: var(--action);
7944 7944 }
7945 7945
7946 - .btn-danger:hover {
7946 + .button--danger:hover {
7947 7947 background-color: var(--danger);
7948 7948 }
7949 7949
@@ -8395,7 +8395,7 @@
8395 8395 margin-top: var(--gap-bound);
8396 8396 }
8397 8397
8398 - .unscheduled-task-actions .btn {
8398 + .unscheduled-task-actions .button {
8399 8399 font-size: var(--font-size-xs);
8400 8400 padding: var(--step-hair) var(--step-snug);
8401 8401 min-height: auto;
@@ -341,7 +341,7 @@
341 341 <p class="about-copyright">&copy; 2026 Make Creative, LLC</p>
342 342 </div>
343 343 <div class="form-actions">
344 - <button type="button" class="btn btn-secondary" data-act="ui.closeModal">Close</button>
344 + <button type="button" class="button button--secondary" data-act="ui.closeModal">Close</button>
345 345 </div>
346 346 `;
347 347 GoingsOn.ui.openModal('About', content);
@@ -368,9 +368,9 @@
368 368 <div class="welcome-section">
369 369 <h3 class="welcome-subhead">Get Started</h3>
370 370 <div class="stack stack-peer">
371 - <button class="btn btn-secondary text-left" data-act="ui.markSeenThen" data-a1="go-welcomed" data-a2="keyboard.openQuickAdd">${step1}</button>
372 - <button class="btn btn-secondary text-left" data-act="ui.markSeenThen" data-a1="go-welcomed" data-a2="navigation.switchView" data-a3="day-plan">${step2}</button>
373 - <button class="btn btn-secondary text-left" data-act="ui.markSeenThen" data-a1="go-welcomed" data-a2="emails.openAccountsModal"><strong>3.</strong> Add an email account</button>
371 + <button class="button button--secondary text-left" data-act="ui.markSeenThen" data-a1="go-welcomed" data-a2="keyboard.openQuickAdd">${step1}</button>
372 + <button class="button button--secondary text-left" data-act="ui.markSeenThen" data-a1="go-welcomed" data-a2="navigation.switchView" data-a3="day-plan">${step2}</button>
373 + <button class="button button--secondary text-left" data-act="ui.markSeenThen" data-a1="go-welcomed" data-a2="emails.openAccountsModal"><strong>3.</strong> Add an email account</button>
374 374 </div>
375 375 </div>
376 376 <div class="welcome-section">
@@ -384,7 +384,7 @@
384 384 ${shortcutsHint}
385 385 </div>
386 386 <div class="form-actions">
387 - <button class="btn btn-primary" data-act="ui.markSeenThen" data-a1="go-welcomed">Get Started</button>
387 + <button class="button button--primary" data-act="ui.markSeenThen" data-a1="go-welcomed">Get Started</button>
388 388 </div>
389 389 `;
390 390 GoingsOn.ui.openModal('Welcome to GoingsOn', content);
@@ -67,12 +67,12 @@
67 67 </div>
68 68 <div class="row-flex row-flex-peer">
69 69 ${a.hasLocalBlob ? `
70 - <button class="btn btn-sm btn-secondary" data-act="attachments.open" data-a1="${escAttr(a.id)}" title="Open">Open</button>
71 - <button class="btn btn-sm btn-secondary" data-act="attachments.saveAs" data-a1="${escAttr(a.id)}" data-a2="${escAttr(a.filename)}" title="Save As">Save</button>
70 + <button class="button button--sm button--secondary" data-act="attachments.open" data-a1="${escAttr(a.id)}" title="Open">Open</button>
71 + <button class="button button--sm button--secondary" data-act="attachments.saveAs" data-a1="${escAttr(a.id)}" data-a2="${escAttr(a.filename)}" title="Save As">Save</button>
72 72 ` : `
73 73 <span class="text-sm text-muted">Sync needed</span>
74 74 `}
75 - <button class="btn btn-sm btn-secondary text-accent-red"
75 + <button class="button button--sm button--secondary text-accent-red"
76 76 data-act="attachments.remove" data-a1="${escAttr(a.id)}" data-a2="${escAttr(tid)}" data-a3="${escAttr(pid)}" title="Delete">×</button>
77 77 </div>
78 78 </div>
@@ -83,7 +83,7 @@
83 83 <div>
84 84 ${listHtml}
85 85 <div class="attachment-attach-row">
86 - <button class="btn btn-primary" data-act="attachments.pickAndAttach" data-a1="${escAttr(tid)}" data-a2="${escAttr(pid)}">Attach File</button>
86 + <button class="button button--primary" data-act="attachments.pickAndAttach" data-a1="${escAttr(tid)}" data-a2="${escAttr(pid)}">Attach File</button>
87 87 </div>
88 88 </div>
89 89 `;
@@ -198,9 +198,9 @@
198 198
199 199 const projects = GoingsOn.projects?.getCache?.() || [];
200 200 let optionsHtml = `<p class="bulk-modal-prompt bulk-modal-prompt--wide">Set project for ${selectedTaskIds.size} tasks:</p>`;
201 - optionsHtml += `<button class="btn btn-sm text-left w-full bulk-modal-option-btn" data-act="bulk._applyProject" data-args='[null]'>No Project</button>`;
201 + optionsHtml += `<button class="button button--sm text-left w-full bulk-modal-option-btn" data-act="bulk._applyProject" data-args='[null]'>No Project</button>`;
202 202 for (const p of projects) {
203 - optionsHtml += `<button class="btn btn-sm text-left w-full bulk-modal-option-btn" data-act="bulk._applyProject" data-a1="${escAttr(p.id)}">${GoingsOn.utils.escapeHtml(p.name)}</button>`;
203 + optionsHtml += `<button class="button button--sm text-left w-full bulk-modal-option-btn" data-act="bulk._applyProject" data-a1="${escAttr(p.id)}">${GoingsOn.utils.escapeHtml(p.name)}</button>`;
204 204 }
205 205 GoingsOn.ui.openModal('Set Project', `<div class="bulk-modal-scroll">${optionsHtml}</div>`);
206 206 }
@@ -212,9 +212,9 @@
212 212 const content = `
213 213 <p class="bulk-modal-prompt bulk-modal-prompt--wide">Set priority for ${selectedTaskIds.size} tasks:</p>
214 214 <div class="row-flex row-flex-peer">
215 - <button class="btn btn-sm" data-act="bulk._applyPriority" data-a1="High">High</button>
216 - <button class="btn btn-sm" data-act="bulk._applyPriority" data-a1="Medium">Medium</button>
217 - <button class="btn btn-sm" data-act="bulk._applyPriority" data-a1="Low">Low</button>
215 + <button class="button button--sm" data-act="bulk._applyPriority" data-a1="High">High</button>
216 + <button class="button button--sm" data-act="bulk._applyPriority" data-a1="Medium">Medium</button>
217 + <button class="button button--sm" data-act="bulk._applyPriority" data-a1="Low">Low</button>
218 218 </div>
219 219 `;
220 220 GoingsOn.ui.openModal('Set Priority', content);
@@ -201,7 +201,7 @@
201 201
202 202 toast.innerHTML = `
203 203 <span class="undo-message">${esc(message)}</span>
204 - <button class="btn btn-sm btn-primary" data-act="ui.executeUndo" data-a1="${escAttr(undoId)}">Undo</button>
204 + <button class="button button--sm button--primary" data-act="ui.executeUndo" data-a1="${escAttr(undoId)}">Undo</button>
205 205 <span class="undo-countdown"></span>
206 206 `;
207 207
@@ -359,14 +359,14 @@
359 359 danger = false
360 360 } = options;
361 361
362 - const confirmBtnClass = danger ? 'btn btn-danger' : 'btn btn-primary';
362 + const confirmBtnClass = danger ? 'button button--danger' : 'button button--primary';
363 363
364 364 const content = `
365 365 <div class="confirm-message-wrap">
366 366 <p class="confirm-message">${esc(message)}</p>
367 367 </div>
368 368 <div class="form-actions">
369 - <button type="button" class="btn btn-secondary" id="confirm-dialog-cancel">${esc(cancelText)}</button>
369 + <button type="button" class="button button--secondary" id="confirm-dialog-cancel">${esc(cancelText)}</button>
370 370 <button type="button" class="${confirmBtnClass}" id="confirm-dialog-confirm">${esc(confirmText)}</button>
371 371 </div>
372 372 `;
@@ -442,8 +442,8 @@
442 442 <div id="${errorId}" class="form-error"></div>
443 443 </div>
444 444 <div class="form-actions">
445 - <button type="button" class="btn btn-secondary" id="prompt-dialog-cancel">${esc(cancelText)}</button>
446 - <button type="button" class="btn btn-primary" id="prompt-dialog-confirm">${esc(confirmText)}</button>
445 + <button type="button" class="button button--secondary" id="prompt-dialog-cancel">${esc(cancelText)}</button>
446 + <button type="button" class="button button--primary" id="prompt-dialog-confirm">${esc(confirmText)}</button>
447 447 </div>
448 448 `;
449 449
@@ -607,23 +607,23 @@
607 607 if (loading) {
608 608 // Wrap existing children in a span so CSS can hide text during loading
609 609 const wrapper = document.createElement('span');
610 - wrapper.className = 'btn-text';
610 + wrapper.className = 'button--text';
611 611 while (button.firstChild) {
612 612 wrapper.appendChild(button.firstChild);
613 613 }
614 614 button.appendChild(wrapper);
615 - button.classList.add('btn-loading');
615 + button.classList.add('button--loading');
616 616 button.disabled = true;
617 617 } else {
618 618 // Unwrap: move children out of the span wrapper
619 - const wrapper = button.querySelector('.btn-text');
619 + const wrapper = button.querySelector('.button--text');
620 620 if (wrapper) {
621 621 while (wrapper.firstChild) {
622 622 button.insertBefore(wrapper.firstChild, wrapper);
623 623 }
624 624 wrapper.remove();
625 625 }
626 - button.classList.remove('btn-loading');
626 + button.classList.remove('button--loading');
627 627 button.disabled = false;
628 628 }
629 629 }
@@ -137,7 +137,7 @@
137 137 function renderEmptyState(message, buttonLabel, onClickAct, iconKey) {
138 138 let html = `<div class="empty-state">${emptyStateIcon(iconKey)}<p class="empty-state-text">${GoingsOn.utils.escapeHtml(message)}</p>`;
139 139 if (buttonLabel && onClickAct) {
140 - html += `<button class="btn btn-primary empty-state-action" data-act="${GoingsOn.utils.escapeAttrValue(onClickAct)}">${GoingsOn.utils.escapeHtml(buttonLabel)}</button>`;
140 + html += `<button class="button button--primary empty-state-action" data-act="${GoingsOn.utils.escapeAttrValue(onClickAct)}">${GoingsOn.utils.escapeHtml(buttonLabel)}</button>`;
141 141 }
142 142 html += `</div>`;
143 143 return html;
@@ -211,7 +211,7 @@
211 211 </div>
212 212 <div class="header-row header-row--tight">
213 213 <span class="header-label"></span>
214 - <button type="button" id="toggle-cc" class="btn-link">${toggleLabel}</button>
214 + <button type="button" id="toggle-cc" class="button--link">${toggleLabel}</button>
215 215 </div>
216 216 <div class="header-row">
217 217 <label class="header-label" for="subject">Subject:</label>
@@ -81,12 +81,12 @@
81 81 // Actions bar
82 82 if (contact.isImplicit) {
83 83 actionsEl.innerHTML = `
84 - <button class="btn btn-primary" data-act="contactDashboard.promote" data-a1="${escAttr(contact.id)}">Save as Contact</button>
84 + <button class="button button--primary" data-act="contactDashboard.promote" data-a1="${escAttr(contact.id)}">Save as Contact</button>
85 85 `;
86 86 } else {
87 87 actionsEl.innerHTML = `
88 - <button class="btn btn-secondary" data-act="contacts.openEdit" data-a1="${escAttr(contact.id)}">Edit</button>
89 - <button class="btn btn-secondary text-accent-red" data-act="contacts.delete" data-a1="${escAttr(contact.id)}">Delete</button>
88 + <button class="button button--secondary" data-act="contacts.openEdit" data-a1="${escAttr(contact.id)}">Edit</button>
89 + <button class="button button--secondary text-accent-red" data-act="contacts.delete" data-a1="${escAttr(contact.id)}">Delete</button>
90 90 `;
91 91 }
92 92
@@ -137,7 +137,7 @@
137 137 const items = timelineItems.map(renderTimelineItem).join('');
138 138 // Rust caps the initial feed; offer to load the rest without a second round of client math.
139 139 const showAll = totalActivity > timelineItems.length
140 - ? `<button class="btn btn-link" data-act="contactDashboard.showAllActivity">Show all ${totalActivity} interactions</button>`
140 + ? `<button class="button button--link" data-act="contactDashboard.showAllActivity">Show all ${totalActivity} interactions</button>`
141 141 : '';
142 142 timelineHtml = `<div class="stack stack-peer" id="contact-timeline">${items}</div>${showAll}`;
143 143 }
@@ -52,7 +52,7 @@
52 52 ${nickname}
53 53 ${company}
54 54 </div>
55 - <button class="btn btn-sm btn-secondary" data-act="contacts.openEdit" data-a1="${escAttr(c.id)}" title="Edit">...</button>
55 + <button class="button button--sm button--secondary" data-act="contacts.openEdit" data-a1="${escAttr(c.id)}" title="Edit">...</button>
56 56 </div>
57 57 ${emailLine ? `<p class="card-description">${emailLine}</p>` : ''}
58 58 ${tagPills ? `<div class="card-meta">${tagPills}</div>` : ''}
@@ -86,7 +86,7 @@
86 86 const emailRows = (contact.emails || []).map(e => `
87 87 <div class="sub-item">
88 88 <span>${esc(e.address)} ${e.label ? `<small>(${esc(e.label)})</small>` : ''} ${e.isPrimary ? '<strong>Primary</strong>' : ''}</span>
89 - <button class="btn btn-sm btn-danger" data-act="contacts.removeEmail" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(e.id)}" title="Remove">x</button>
89 + <button class="button button--sm button--danger" data-act="contacts.removeEmail" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(e.id)}" title="Remove">x</button>
90 90 </div>
91 91 `).join('');
92 92
@@ -94,7 +94,7 @@
94 94 const phoneRows = (contact.phones || []).map(p => `
95 95 <div class="sub-item">
96 96 <span>${esc(p.number)} ${p.label ? `<small>(${esc(p.label)})</small>` : ''} ${p.isPrimary ? '<strong>Primary</strong>' : ''}</span>
97 - <button class="btn btn-sm btn-danger" data-act="contacts.removePhone" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(p.id)}" title="Remove">x</button>
97 + <button class="button button--sm button--danger" data-act="contacts.removePhone" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(p.id)}" title="Remove">x</button>
98 98 </div>
99 99 `).join('');
100 100
@@ -102,7 +102,7 @@
102 102 const socialRows = (contact.socialHandles || []).map(s => `
103 103 <div class="sub-item">
104 104 <span><strong>${esc(s.platform)}:</strong> ${s.url ? `<a href="${escAttrVal(safeUrl(s.url))}" target="_blank">${esc(s.handle)}</a>` : esc(s.handle)}</span>
105 - <button class="btn btn-sm btn-danger" data-act="contacts.removeSocialHandle" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(s.id)}" title="Remove">x</button>
105 + <button class="button button--sm button--danger" data-act="contacts.removeSocialHandle" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(s.id)}" title="Remove">x</button>
106 106 </div>
107 107 `).join('');
108 108
@@ -110,7 +110,7 @@
110 110 const customFieldRows = (contact.customFields || []).map(f => `
111 111 <div class="sub-item">
112 112 <span><strong>${esc(f.label)}:</strong> ${f.url ? `<a href="${escAttrVal(safeUrl(f.url))}" target="_blank">${esc(f.value)}</a>` : esc(f.value)}</span>
113 - <button class="btn btn-sm btn-danger" data-act="contacts.removeCustomField" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(f.id)}" title="Remove">x</button>
113 + <button class="button button--sm button--danger" data-act="contacts.removeCustomField" data-a1="${escAttr(contact.id)}" data-a2="${escAttr(f.id)}" title="Remove">x</button>
114 114 </div>
115 115 `).join('');
116 116
@@ -131,7 +131,7 @@
131 131 <div class="sub-collection">
132 132 <div class="sub-collection-header">
133 133 <h4>Email Addresses</h4>
134 - <button class="btn btn-sm btn-primary" data-act="contacts.openAddEmail" data-a1="${escAttr(contact.id)}">+ Add</button>
134 + <button class="button button--sm button--primary" data-act="contacts.openAddEmail" data-a1="${escAttr(contact.id)}">+ Add</button>
135 135 </div>
136 136 ${emailRows || '<div class="sub-empty">No email addresses</div>'}
137 137 </div>
@@ -139,7 +139,7 @@
139 139 <div class="sub-collection">
140 140 <div class="sub-collection-header">
141 141 <h4>Phone Numbers</h4>
142 - <button class="btn btn-sm btn-primary" data-act="contacts.openAddPhone" data-a1="${escAttr(contact.id)}">+ Add</button>
142 + <button class="button button--sm button--primary" data-act="contacts.openAddPhone" data-a1="${escAttr(contact.id)}">+ Add</button>
143 143 </div>
144 144 ${phoneRows || '<div class="sub-empty">No phone numbers</div>'}
145 145 </div>
@@ -147,7 +147,7 @@
147 147 <div class="sub-collection">
148 148 <div class="sub-collection-header">
149 149 <h4>Social Handles</h4>
150 - <button class="btn btn-sm btn-primary" data-act="contacts.openAddSocial" data-a1="${escAttr(contact.id)}">+ Add</button>
150 + <button class="button button--sm button--primary" data-act="contacts.openAddSocial" data-a1="${escAttr(contact.id)}">+ Add</button>
151 151 </div>
152 152 ${socialRows || '<div class="sub-empty">No social handles</div>'}
153 153 </div>
@@ -155,13 +155,13 @@
155 155 <div class="sub-collection">
156 156 <div class="sub-collection-header">
157 157 <h4>Custom Fields</h4>
158 - <button class="btn btn-sm btn-primary" data-act="contacts.openAddCustomField" data-a1="${escAttr(contact.id)}">+ Add</button>
158 + <button class="button button--sm button--primary" data-act="contacts.openAddCustomField" data-a1="${escAttr(contact.id)}">+ Add</button>
159 159 </div>
160 160 ${customFieldRows || '<div class="sub-empty">No custom fields</div>'}
161 161 </div>
162 162
163 163 <div class="form-actions form-actions--spaced">
164 - <button class="btn btn-secondary" data-act="contacts.openEdit" data-a1="${escAttr(contact.id)}">Edit Contact</button>
164 + <button class="button button--secondary" data-act="contacts.openEdit" data-a1="${escAttr(contact.id)}">Edit Contact</button>
165 165 </div>
166 166 </div>
167 167 `;
@@ -301,8 +301,8 @@
301 301 <form id="${escAttr(config.formId)}">
302 302 ${fieldHtml}
303 303 <div class="form-actions">
304 - <button type="button" class="btn btn-secondary" data-act="ui.closeModal">Cancel</button>
305 - <button type="button" class="btn btn-primary" data-act="contacts.${submitFn}" data-a1="${escAttr(contactId)}"${isEdit ? ` data-a2="${escAttr(editingId)}"` : ''}>${esc(submitText)}</button>
304 + <button type="button" class="button button--secondary" data-act="ui.closeModal">Cancel</button>
305 + <button type="button" class="button button--primary" data-act="contacts.${submitFn}" data-a1="${escAttr(contactId)}"${isEdit ? ` data-a2="${escAttr(editingId)}"` : ''}>${esc(submitText)}</button>
306 306 </div>
307 307 </form>
308 308 `;
@@ -669,8 +669,8 @@
669 669 // `GoingsOn.state.contacts` rather than smuggled through HTML attrs.
670 670 const rowActions = (kind, rowId) => `
671 671 <span class="sub-item-actions">
672 - <button type="button" class="btn btn-sm btn-secondary" data-act="contacts.openEdit${kind}" data-a1="${escAttr(id)}" data-a2="${escAttr(rowId)}" title="Edit">Edit</button>
673 - <button type="button" class="btn btn-sm btn-danger" data-act="contacts.remove${kind === 'Social' ? 'SocialHandle' : kind}" data-a1="${escAttr(id)}" data-a2="${escAttr(rowId)}" title="Remove">x</button>
672 + <button type="button" class="button button--sm button--secondary" data-act="contacts.openEdit${kind}" data-a1="${escAttr(id)}" data-a2="${escAttr(rowId)}" title="Edit">Edit</button>
673 + <button type="button" class="button button--sm button--danger" data-act="contacts.remove${kind === 'Social' ? 'SocialHandle' : kind}" data-a1="${escAttr(id)}" data-a2="${escAttr(rowId)}" title="Remove">x</button>
674 674 </span>
675 675 `;
676 676
@@ -702,37 +702,37 @@
702 702 <div class="edit-sub-section">
703 703 <div class="edit-sub-header">
704 704 <strong>Emails</strong>
705 - <button type="button" class="btn btn-sm btn-primary" data-act="contacts.openAddEmail" data-a1="${escAttr(id)}">+ Add</button>
705 + <button type="button" class="button button--sm button--primary" data-act="contacts.openAddEmail" data-a1="${escAttr(id)}">+ Add</button>
706 706 </div>
707 707 ${emailSummary}
708 708 </div>
709 709 <div class="edit-sub-section">
710 710 <div class="edit-sub-header">
711 711 <strong>Phones</strong>
712 - <button type="button" class="btn btn-sm btn-primary" data-act="contacts.openAddPhone" data-a1="${escAttr(id)}">+ Add</button>
712 + <button type="button" class="button button--sm button--primary" data-act="contacts.openAddPhone" data-a1="${escAttr(id)}">+ Add</button>
713 713 </div>
714 714 ${phoneSummary}
715 715 </div>
716 716 <div class="edit-sub-section">
717 717 <div class="edit-sub-header">
718 718 <strong>Social</strong>
719 - <button type="button" class="btn btn-sm btn-primary" data-act="contacts.openAddSocial" data-a1="${escAttr(id)}">+ Add</button>
719 + <button type="button" class="button button--sm button--primary" data-act="contacts.openAddSocial" data-a1="${escAttr(id)}">+ Add</button>
720 720 </div>
721 721 ${socialSummary}
722 722 </div>
723 723 <div class="edit-sub-section">
724 724 <div class="edit-sub-header">
725 725 <strong>Custom Fields</strong>
726 - <button type="button" class="btn btn-sm btn-primary" data-act="contacts.openAddCustomField" data-a1="${escAttr(id)}">+ Add</button>
726 + <button type="button" class="button button--sm button--primary" data-act="contacts.openAddCustomField" data-a1="${escAttr(id)}">+ Add</button>
727 727 </div>
728 728 ${customFieldSummary}
729 729 </div>
730 730 <div style="margin-top: var(--gap-peer);">
731 - <button type="button" class="btn btn-sm btn-secondary" data-act="contacts.open" data-a1="${escAttr(id)}">View Full Detail</button>
731 + <button type="button" class="button button--sm button--secondary" data-act="contacts.open" data-a1="${escAttr(id)}">View Full Detail</button>
732 732 </div>
733 733 </div>
734 734 <div style="margin-top: var(--gap-section);">
735 - <button type="button" class="btn btn-danger" data-act="contacts.deleteContact" data-a1="${escAttr(id)}">Delete Contact</button>
735 + <button type="button" class="button button--danger" data-act="contacts.deleteContact" data-a1="${escAttr(id)}">Delete Contact</button>
736 736 </div>
737 737 `,
738 738 });
@@ -179,8 +179,8 @@
179 179 </div>
180 180
181 181 <div class="form-actions">
182 - <button type="button" class="btn btn-secondary" data-act="ui.closeModal">Cancel</button>
183 - <button type="button" class="btn btn-primary" data-act="dayPlan.submitPaintedEvent">Create</button>
182 + <button type="button" class="button button--secondary" data-act="ui.closeModal">Cancel</button>
183 + <button type="button" class="button button--primary" data-act="dayPlan.submitPaintedEvent">Create</button>
184 184 </div>
185 185 </form>
186 186 `;
@@ -244,8 +244,8 @@
244 244 ${task.projectName ? esc(task.projectName) + ' - ' : ''}${task.priority}
245 245 </div>
246 246 <div class="unscheduled-task-actions" data-act="ui.noop">
247 - <button class="btn btn-sm btn-ghost" data-act="timeTracking.startTimer" data-a1="${escAttr(task.id)}" title="Track Time">Track</button>
248 - <button class="btn btn-sm btn-ghost" data-act="focusTimer.start" data-a1="${escAttr(task.id)}" title="Focus Mode">Focus</button>
247 + <button class="button button--sm button--ghost" data-act="timeTracking.startTimer" data-a1="${escAttr(task.id)}" title="Track Time">Track</button>
248 + <button class="button button--sm button--ghost" data-act="focusTimer.start" data-a1="${escAttr(task.id)}" title="Focus Mode">Focus</button>
249 249 </div>
250 250 </div>
251 251 `;
@@ -33,7 +33,7 @@
33 33 }
34 34
35 35 const timeSlotsHtml = timeSlots.slice(0, 12).map(slot => `
36 - <button class="btn btn-sm btn-secondary time-block-quick-btn" data-act="dayPlan.selectTimeSlot" data-a1="@el" data-a2="${escAttr(slot.time.toISOString())}">
36 + <button class="button button--sm button--secondary time-block-quick-btn" data-act="dayPlan.selectTimeSlot" data-a1="@el" data-a2="${escAttr(slot.time.toISOString())}">
37 37 ${slot.label}
38 38 </button>
39 39 `).join('');
@@ -70,8 +70,8 @@
70 70 <div id="schedule-conflict-warning"></div>
71 71
72 72 <div class="form-actions">
73 - <button type="button" class="btn btn-secondary" data-act="ui.closeModal">Cancel</button>
74 - <button type="button" class="btn btn-primary" data-act="dayPlan.scheduleTaskFromModal" data-a1="${escAttr(id)}">Schedule Task</button>
73 + <button type="button" class="button button--secondary" data-act="ui.closeModal">Cancel</button>
74 + <button type="button" class="button button--primary" data-act="dayPlan.scheduleTaskFromModal" data-a1="${escAttr(id)}">Schedule Task</button>
75 75 </div>
76 76 </div>
77 77 `;
@@ -244,14 +244,14 @@
244 244 bar.classList.remove('hidden');
245 245 if (state === 'current') {
246 246 bar.innerHTML = `
247 - <button class="btn btn-primary finish-review-btn" id="day-finish-review-btn" data-act="dayPlanSchedule.openFinishReviewModal">
247 + <button class="button button--primary finish-review-btn" id="day-finish-review-btn" data-act="dayPlanSchedule.openFinishReviewModal">
248 248 Finish &amp; Review
249 249 </button>
250 250 `;
251 251 } else {
252 252 const label = isReviewed ? 'View Past Review' : 'Review Past Day';
253 253 bar.innerHTML = `
254 - <button class="btn btn-secondary finish-review-btn" id="day-finish-review-btn" data-act="dayPlanSchedule.openFinishReviewModal">
254 + <button class="button button--secondary finish-review-btn" id="day-finish-review-btn" data-act="dayPlanSchedule.openFinishReviewModal">
255 255 ${label}
256 256 </button>
257 257 `;
@@ -311,7 +311,7 @@
311 311 ${reflectionHtml}
312 312 <div class="review-actions-grid">
313 313 <p class="review-action-hint">${esc(saveHint)}</p>
314 - <button type="button" class="btn btn-primary" data-act="dayPlan.saveDailyReview" title="${escAttr(saveHint)}">
314 + <button type="button" class="button button--primary" data-act="dayPlan.saveDailyReview" title="${escAttr(saveHint)}">
315 315 ${isReviewed ? 'Update Review' : 'Save Review'}
316 316 </button>
317 317 </div>