Skip to main content

max / goingson

Take the raised surface from layout.css instead of hand-rolling it Thirteen rules still paired background: var(--surface-raised) with box-shadow: var(--bevel-raised) on their own selector, which is exactly what the generated .raised is. Twelve now take the class, alongside the component class as the rest of the app already does. Two dead hex fallbacks go with them: each sat directly above a color-mix line that overrode it, so neither had painted anything in a long time. Two matches are left deliberately. .kanban-card:hover re-asserts raised inside the coarse-pointer query to cancel the generated .card hover, so the duplication is the point. .month-day-detail matches nothing at all, which is a dead-code question rather than a design-system one and is filed as its own finding.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-10 13:46 UTC
Signed with PGP, not checked
Commit: 5e16cc1c59a0ee217f558c37b80ccfa8ba3e8f48
Parent: 8aaf747
9 files changed, +26 insertions, -50 deletions
@@ -138,7 +138,7 @@
138 138 <option value="due">Sort: Due Date</option>
139 139 </select>
140 140 </div>
141 - <div class="filter-bar" id="task-filter-bar" role="search" aria-label="Task filters">
141 + <div class="raised filter-bar" id="task-filter-bar" role="search" aria-label="Task filters">
142 142 <select id="filter-status" class="filter-select" data-change="tasks.applyFilters">
143 143 <option value="">All Status</option>
144 144 <option value="pending" selected>Pending</option>
@@ -171,7 +171,7 @@
171 171 <button class="button button--link" data-act="tasks.clearFilters">Clear filters</button>
172 172 </div>
173 173 </div>
174 - <div class="task-table" id="task-table" role="grid" aria-label="Tasks list">
174 + <div class="raised task-table" id="task-table" role="grid" aria-label="Tasks list">
175 175 <div class="task-header-row" role="row">
176 176 <div class="task-cell col-description sortable" data-sort="description" data-act="tasks.sort" data-a1="description" role="columnheader" tabindex="0">
177 177 Description <span class="sort-arrow"></span>
@@ -366,7 +366,7 @@
366 366 <span id="day-review-status-badge" class="review-status hidden"></span>
367 367 </div>
368 368 <div class="day-plan-content">
369 - <div class="day-plan-main" id="day-plan-container">
369 + <div class="raised day-plan-main" id="day-plan-container">
370 370 <p class="timeline-hint">Click and drag across time slots to schedule blocks</p>
371 371 <!-- All-day items sit above the scrolling column, not in it. -->
372 372 <div class="timeline-all-day hidden" id="timeline-all-day"></div>
@@ -378,7 +378,7 @@
378 378 </div>
379 379 </div>
380 380 </div>
381 - <div class="day-plan-sidebar">
381 + <div class="raised day-plan-sidebar">
382 382 <div id="time-summary-container"></div>
383 383 <button class="day-plan-sidebar-toggle" data-act="dayPlan.toggleSidebar">
384 384 <span>Tasks to Schedule</span>
@@ -449,7 +449,7 @@
449 449 <h2 class="page-title">Events</h2>
450 450 <button class="button button--primary" data-act="events.openNew" title="New event (n)">+ New Event <kbd class="kbd-hint">n</kbd></button>
451 451 </div>
452 - <div class="filter-bar" id="events-filter-bar">
452 + <div class="raised filter-bar" id="events-filter-bar">
453 453 <label class="filter-checkbox" title="Include events hidden until a later date">
454 454 <input type="checkbox" id="filter-events-snoozed" data-change="events.onFilterChange">
455 455 Show Snoozed
@@ -467,7 +467,7 @@
467 467 <span class="past-events-label">Recurring</span>
468 468 <span class="past-events-count" id="recurring-events-count">0</span>
469 469 </summary>
470 - <div class="event-table-virtual" id="recurring-event-table">
470 + <div class="raised event-table-virtual" id="recurring-event-table">
471 471 <div class="event-header-row event-header-recurring" role="row">
472 472 <div class="event-cell col-pattern" role="columnheader">Pattern</div>
473 473 <div class="event-cell col-time" role="columnheader">Time</div>
@@ -479,7 +479,7 @@
479 479 </div>
480 480 </details>
481 481 <h3 class="events-section-heading hidden" id="future-events-heading">Upcoming</h3>
482 - <div class="event-table-virtual" id="event-table" role="grid" aria-label="Upcoming events">
482 + <div class="raised event-table-virtual" id="event-table" role="grid" aria-label="Upcoming events">
483 483 <div class="event-header-row event-header-upcoming" role="row">
484 484 <div class="event-cell col-select" role="columnheader"><span class="sr-only">Select</span></div>
485 485 <div class="event-cell col-date" role="columnheader">Date</div>
@@ -501,7 +501,7 @@
501 501 <span class="past-events-label">Past Events</span>
502 502 <span class="past-events-count" id="past-events-count">0</span>
503 503 </summary>
504 - <div class="event-table-virtual event-table-past" id="past-event-table">
504 + <div class="raised event-table-virtual event-table-past" id="past-event-table">
505 505 <div class="event-header-row" role="row">
506 506 <div class="event-cell" role="columnheader">Date</div>
507 507 <div class="event-cell" role="columnheader">Time</div>
@@ -1059,16 +1059,16 @@
1059 1059 vertical-align: middle;
1060 1060 }
1061 1061
1062 - /* 13. Data Table */
1062 + /* 13. Data Table
1063 + The fill and the bevel come from `.raised` in layout.css; the markup carries
1064 + the class. What stays here is the box model. */
1063 1065 .data-table {
1064 1066 width: 100%;
1065 1067 border-collapse: separate;
1066 1068 border-spacing: 0;
1067 - background-color: var(--surface-raised);
1068 1069 border: var(--border-width) solid var(--border);
1069 1070 border-radius: var(--radius-md);
1070 1071 overflow: hidden;
1071 - box-shadow: var(--bevel-raised);
1072 1072 }
1073 1073
1074 1074 .data-table th,
@@ -1102,7 +1102,6 @@
1102 1102 /* 14. Task Table & Rows */
1103 1103 .task-table {
1104 1104 width: 100%;
1105 - background: var(--surface-raised);
1106 1105 border: var(--border-width) solid var(--border);
1107 1106 border-radius: var(--radius-lg);
1108 1107 overflow: hidden;
@@ -1110,7 +1109,6 @@
1110 1109 flex-direction: column;
1111 1110 flex: 1;
1112 1111 min-height: 0;
1113 - box-shadow: var(--bevel-raised);
1114 1112 }
1115 1113
1116 1114 /* Task Grid Column Widths
@@ -1225,13 +1223,11 @@
1225 1223
1226 1224 .priority-high {
1227 1225 color: var(--danger);
1228 - background: #fde8ea;
1229 1226 background: color-mix(in srgb, var(--danger) 15%, var(--surface-raised));
1230 1227 }
1231 1228
1232 1229 .priority-medium {
1233 1230 color: var(--warning);
1234 - background: #fef8e6;
1235 1231 background: color-mix(in srgb, var(--warning) 15%, var(--surface-raised));
1236 1232 }
1237 1233
@@ -1323,7 +1319,6 @@
1323 1319 /* Event Table - CSS Grid based for virtual scrolling */
1324 1320 .event-table-virtual {
1325 1321 width: 100%;
1326 - background: var(--surface-raised);
1327 1322 border: var(--border-width) solid var(--border);
1328 1323 border-radius: var(--radius-lg);
1329 1324 overflow: hidden;
@@ -1331,7 +1326,6 @@
1331 1326 flex-direction: column;
1332 1327 flex: 1;
1333 1328 min-height: 0;
1334 - box-shadow: var(--bevel-raised);
1335 1329 }
1336 1330
1337 1331 /* Event Grid Column Widths
@@ -1873,8 +1867,6 @@
1873 1867 font-size: var(--font-size-md);
1874 1868 border: var(--border-width) solid var(--border);
1875 1869 border-radius: var(--radius-sm);
1876 - background: var(--surface-raised);
1877 - box-shadow: var(--bevel-raised);
1878 1870 cursor: pointer;
1879 1871 }
1880 1872
@@ -3380,10 +3372,8 @@
3380 3372 gap: var(--gap-peer);
3381 3373 margin-bottom: var(--gap-section);
3382 3374 padding: var(--gap-group);
3383 - background-color: var(--surface-raised);
3384 3375 border: var(--border-width) solid var(--border);
3385 3376 border-radius: var(--radius-md);
3386 - box-shadow: var(--bevel-raised);
3387 3377 }
3388 3378
3389 3379 .filter-select {
@@ -4323,11 +4313,9 @@
4323 4313 min-height: 0;
4324 4314 display: flex;
4325 4315 flex-direction: column;
4326 - background: var(--surface-raised);
4327 4316 border: var(--border-width) solid var(--border);
4328 4317 border-radius: var(--radius-md);
4329 4318 overflow: hidden;
4330 - box-shadow: var(--bevel-raised);
4331 4319 }
4332 4320
4333 4321 .day-plan-sidebar {
@@ -4335,11 +4323,9 @@
4335 4323 flex-shrink: 0;
4336 4324 display: flex;
4337 4325 flex-direction: column;
4338 - background: var(--surface-raised);
4339 4326 border: var(--border-width) solid var(--border);
4340 4327 border-radius: var(--radius-md);
4341 4328 overflow: hidden;
4342 - box-shadow: var(--bevel-raised);
4343 4329 }
4344 4330
4345 4331 /* Sidebar width by how much room there is. Here rather than in §24 for the
@@ -6926,12 +6912,10 @@
6926 6912 }
6927 6913
6928 6914 .milestone-card {
6929 - background: var(--surface-raised);
6930 6915 border: var(--border-width) solid var(--border);
6931 6916 border-radius: var(--radius-md);
6932 6917 padding: var(--gap-group);
6933 6918 margin-bottom: var(--gap-peer);
6934 - box-shadow: var(--bevel-raised);
6935 6919 }
6936 6920
6937 6921 .milestone-card:hover {
@@ -8815,9 +8799,7 @@
8815 8799 .task-overview-section {
8816 8800 margin-bottom: var(--gap-section);
8817 8801 padding: var(--gap-group);
8818 - background: var(--surface-raised);
8819 8802 border: var(--border-width) solid var(--border);
8820 - box-shadow: var(--bevel-raised);
8821 8803 }
8822 8804
8823 8805 .task-overview-section-title {
@@ -9040,8 +9022,6 @@
9040 9022 .cal-month-grid {
9041 9023 border: var(--border-width) solid var(--border);
9042 9024 overflow: hidden;
9043 - background: var(--surface-raised);
9044 - box-shadow: var(--bevel-raised);
9045 9025 }
9046 9026
9047 9027 .cal-month-header,
@@ -9200,8 +9180,6 @@
9200 9180 .cal-week-grid {
9201 9181 border: var(--border-width) solid var(--border);
9202 9182 overflow: hidden;
9203 - background: var(--surface-raised);
9204 - box-shadow: var(--bevel-raised);
9205 9183 }
9206 9184
9207 9185 .cal-week-header {
@@ -9686,8 +9664,6 @@
9686 9664 padding: var(--gap-peer) var(--gap-group);
9687 9665 border: var(--border-width-sm) solid var(--border);
9688 9666 border-radius: var(--radius-md);
9689 - background: var(--surface-raised);
9690 - box-shadow: var(--bevel-raised);
9691 9667 }
9692 9668
9693 9669 /* Settled problems stay visible but recede: they are history, not queue. */
@@ -147,7 +147,7 @@
147 147 const today = toDateKey(new Date());
148 148 const dayHeaders = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
149 149
150 - let html = '<div class="cal-month-grid">';
150 + let html = '<div class="raised cal-month-grid">';
151 151 html += '<div class="cal-month-header">';
152 152 for (const d of dayHeaders) {
153 153 html += `<div class="cal-month-day-header">${d}</div>`;
@@ -290,7 +290,7 @@
290 290 const totalSlots = (HOURS_END - HOURS_START) * 4;
291 291 const gridHeight = totalSlots * SLOT_HEIGHT;
292 292
293 - let html = '<div class="cal-week-grid">';
293 + let html = '<div class="raised cal-week-grid">';
294 294
295 295 // Header row
296 296 html += '<div class="cal-week-header"><div class="cal-week-time-gutter"></div>';
@@ -64,7 +64,7 @@
64 64 const html = `
65 65 <p class="import-summary"><strong>${preview.length}</strong> contact${preview.length !== 1 ? 's' : ''} found</p>
66 66 <div class="import-preview-table-wrapper">
67 - <table class="data-table import-preview-table">
67 + <table class="raised data-table import-preview-table">
68 68 <thead>
69 69 <tr><th>Name</th><th>Company</th><th>Emails</th><th>Phones</th><th>Status</th></tr>
70 70 </thead>
@@ -189,7 +189,7 @@
189 189 const html = `
190 190 <p class="import-summary"><strong>${preview.length}</strong> event${preview.length !== 1 ? 's' : ''} found</p>
191 191 <div class="import-preview-table-wrapper">
192 - <table class="data-table import-preview-table">
192 + <table class="raised data-table import-preview-table">
193 193 <thead>
194 194 <tr><th>Title</th><th>Start</th><th>Location</th><th>Recurrence</th></tr>
195 195 </thead>
@@ -143,7 +143,7 @@
143 143 <strong>${items.length}</strong> ${esc(entityType)}${items.length !== 1 ? 's' : ''} found
144 144 </p>
145 145 <div class="import-preview-table-wrapper">
146 - <table class="data-table import-preview-table">
146 + <table class="raised data-table import-preview-table">
147 147 <thead>
148 148 <tr>${columns.map(c => `<th>${esc(c.label)}</th>`).join('')}</tr>
149 149 </thead>
@@ -110,7 +110,7 @@
110 110 // The score leads the row: it is the reason this problem is where it is
111 111 // in the list, so it should be readable before the title.
112 112 return `
113 - <div class="problem-row${settled ? ' problem-row--settled' : ''}" data-problem-id="${escAttr(p.id)}">
113 + <div class="raised problem-row${settled ? ' problem-row--settled' : ''}" data-problem-id="${escAttr(p.id)}">
114 114 <div class="problem-score">
115 115 <span class="badge badge--filled" data-color="${bandColor(p.band)}" title="painhours: pain ${p.pain} x scale ${p.scale}, aged ${esc(p.age)}">${p.painhours}</span>
116 116 </div>
@@ -184,7 +184,7 @@
184 184 </div>
185 185 <div class="milestones-list">
186 186 ${openMilestones.map((m, idx) => `
187 - <div class="milestone-card">
187 + <div class="raised milestone-card">
188 188 <div class="milestone-info">
189 189 <span class="milestone-name">${esc(m.name)}</span>
190 190 ${m.targetDate ? `<span class="milestone-date">${esc(m.targetDate)}</span>` : ''}
@@ -214,7 +214,7 @@
214 214 </button>
215 215 <div class="milestones-completed-list" style="display: ${showCompletedMilestones ? 'block' : 'none'};">
216 216 ${completedMilestones.map(m => `
217 - <div class="milestone-card completed milestone-card-summary">
217 + <div class="raised milestone-card completed milestone-card-summary">
218 218 <div class="milestone-info">
219 219 <span class="milestone-name">${esc(m.name)}</span>
220 220 <span class="milestone-complete-badge">Complete</span>
@@ -44,7 +44,7 @@
44 44
45 45 const weekdayCheckboxes = WEEKDAY_LABELS.map((label, i) => {
46 46 const checked = weekdays.includes(i) ? 'checked' : '';
47 - return `<label class="recurrence-weekday-label"><input type="checkbox" name="${prefix}-weekday-${i}" value="${i}" ${checked}><span>${label}</span></label>`;
47 + return `<label class="raised recurrence-weekday-label"><input type="checkbox" name="${prefix}-weekday-${i}" value="${i}" ${checked}><span>${label}</span></label>`;
48 48 }).join('');
49 49
50 50 const monthlyDom = monthlySpec?.type === 'dayOfMonth' ? monthlySpec.day : '';
@@ -200,7 +200,7 @@
200 200 function renderDependencies(t) {
201 201 const blocking = currentDeps.blockedBy.filter(b => !b.satisfied);
202 202
203 - let html = '<div class="task-overview-section">';
203 + let html = '<div class="raised task-overview-section">';
204 204 html += '<h3 class="task-overview-section-title">Dependencies';
205 205 if (t.inCycle) {
206 206 html += ' <span class="badge badge--danger">In a cycle</span>';
@@ -338,7 +338,7 @@
338 338
339 339 function renderHabitSection(data) {
340 340 const s = data.streak;
341 - let html = '<div class="task-overview-section">';
341 + let html = '<div class="raised task-overview-section">';
342 342 html += '<h3 class="task-overview-section-title">Completion History</h3>';
343 343
344 344 // Streak stats
@@ -471,7 +471,7 @@
471 471 // Metadata
472 472
473 473 function renderMetadata(t) {
474 - let html = '<div class="task-overview-section">';
474 + let html = '<div class="raised task-overview-section">';
475 475 html += '<div class="stack stack-peer">';
476 476
477 477 const STATUS_COLOR = { completed: 'green', started: 'blue', pending: 'muted' };
@@ -512,7 +512,7 @@
512 512 const completed = t.subtasks.filter(s => s.isCompleted).length;
513 513 const total = t.subtasks.length;
514 514
515 - let html = '<div class="task-overview-section">';
515 + let html = '<div class="raised task-overview-section">';
516 516 html += `<h3 class="task-overview-section-title">Subtasks <span class="task-overview-count">${completed}/${total}</span></h3>`;
517 517
518 518 if (total > 0) {
@@ -569,7 +569,7 @@
569 569 // Time Tracking
570 570
571 571 function renderTimeTracking(t, sessions) {
572 - let html = '<div class="task-overview-section">';
572 + let html = '<div class="raised task-overview-section">';
573 573 const est = t.estimatedMinutes ? `${t.estimatedMinutes}m est` : '';
574 574 const actual = `${t.actualMinutes}m tracked`;
575 575 const label = est ? `${actual} / ${est}` : actual;
@@ -600,7 +600,7 @@
600 600 // Annotations
601 601
602 602 function renderAnnotations(t) {
603 - let html = '<div class="task-overview-section">';
603 + let html = '<div class="raised task-overview-section">';
604 604 html += `<h3 class="task-overview-section-title">Notes <span class="task-overview-count">${t.annotations.length}</span></h3>`;
605 605
606 606 if (t.annotations.length > 0) {