fix Harmonize dark-theme action colours and focus behavior

Dark mode used paper-raised as foreground text on oxblood and brass surfaces, but paper-raised is deliberately dark there: primary controls fell to 3.80:1 and hovered primary controls to 2.26:1. Add explicit on-primary and on-brass tokens, separate the darker oxblood hover surface from the accessible oxblood-dark foreground, and use a link-hover token. Every audited normal-text pair now exceeds 4.5:1 in both themes; dark primary is 4.88:1 and primary hover 6.46:1. Replace light-only hover, disabled, warning, and marker literals with theme tokens. Keyboard focus now includes buttons and textareas. Stop accordion containers clipping the 2px focus outline, and remove the toast reduced-motion override that reintroduced a transition after the global motion suppression rule.

Commit
ef8232a28e2404334158e86f9e8bef15eaea61e6
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
lib/web/assets/hito.css
index d9408e78..149d4b25 100644..100644
@@ -4,14 +4,20 @@
4 4 color-scheme: light;
5 5 --paper: #f7f2e8;
6 6 --paper-raised: #fffdf8;
7 Added: --on-primary: #fffdf8;
8 Added: --on-brass: #fffdf8;
7 9 --ink: #1a1a16;
8 10 --muted-ink: #5b584f;
9 11 --rule: #b9b1a2;
10 12 --rule-strong: #756f63;
11 13 --oxblood: #8c201b;
12 14 --oxblood-dark: #65130f;
15 Added: --oxblood-hover: #65130f;
16 Added: --link-hover: #8c201b;
13 17 --brass: #7b5714;
14 18 --brass-wash: #f4e7c5;
19 Added: --hover-surface: #ece4d5;
20 Added: --disabled-surface: #ded8cc;
15 21 --evergreen: #1f5b45;
16 22 --evergreen-wash: #dcebe2;
17 23 --focus: #65130f;
@@ -31,14 +37,20 @@
31 37 color-scheme: dark;
32 38 --paper: #171614;
33 39 --paper-raised: #24211d;
40 Added: --on-primary: #f3eee3;
41 Added: --on-brass: #171614;
34 42 --ink: #f3eee3;
35 43 --muted-ink: #c2b9aa;
36 44 --rule: #655e54;
37 45 --rule-strong: #918778;
38 Removed: --oxblood: #c65a50;
46 Added: --oxblood: #ae453e;
39 47 --oxblood-dark: #f08073;
48 Added: --oxblood-hover: #96332f;
49 Added: --link-hover: #d4a94f;
40 50 --brass: #d4a94f;
41 51 --brass-wash: #40351f;
52 Added: --hover-surface: #40351f;
53 Added: --disabled-surface: #4a443c;
42 54 --evergreen: #74c49a;
43 55 --evergreen-wash: #244334;
44 56 --focus: #f08073;
@@ -74,12 +86,15 @@
74 86 text-underline-offset: 0.16em;
75 87 }
76 88
77 Removed: a:hover { color: var(--oxblood); }
89 Added: a:hover { color: var(--link-hover); }
78 90
79 91 a:focus-visible,
92 Added: button:focus-visible,
80 93 input:focus-visible,
81 94 select:focus-visible,
82 Removed: summary:focus-visible {
95 Added: textarea:focus-visible,
96 Added: summary:focus-visible,
97 Added: [tabindex]:focus-visible {
83 98 outline: 2px solid var(--focus);
84 99 outline-offset: 2px;
85 100 }
@@ -145,10 +160,10 @@
145 160 }
146 161 .profile:hover {
147 162 color: var(--oxblood-dark);
148 Removed: background: #ece4d5;
163 Added: background: var(--hover-surface);
149 164 }
150 165 .profile[aria-current] {
151 Removed: color: var(--paper-raised);
166 Added: color: var(--on-primary);
152 167 background: var(--oxblood);
153 168 border-color: var(--oxblood-dark);
154 169 }
@@ -180,7 +195,7 @@
180 195 }
181 196
182 197 .primary-nav > a:hover {
183 Removed: background: #ece4d5;
198 Added: background: var(--hover-surface);
184 199 color: var(--oxblood-dark);
185 200 }
186 201
@@ -188,7 +203,7 @@
188 203 .page-routine .primary-nav > a[href="/routine"],
189 204 .page-workout .primary-nav > a[href="/workout"],
190 205 .page-logbook .primary-nav > a[href="/logbook"] {
191 Removed: color: var(--paper-raised);
206 Added: color: var(--on-primary);
192 207 background: var(--oxblood);
193 208 }
194 209
@@ -273,10 +288,10 @@
273 288 }
274 289 .profile-menu-item:hover {
275 290 color: var(--oxblood-dark);
276 Removed: background: #ece4d5;
291 Added: background: var(--hover-surface);
277 292 }
278 293 .profile-menu-item[aria-current] {
279 Removed: color: var(--paper-raised);
294 Added: color: var(--on-primary);
280 295 background: var(--oxblood);
281 296 }
282 297 .profile-menu .logout {
@@ -287,7 +302,7 @@
287 302 .page-routine .bottom-nav > a[href="/routine"],
288 303 .page-workout .bottom-nav > a[href="/workout"],
289 304 .page-logbook .bottom-nav > a[href="/logbook"] {
290 Removed: color: var(--paper-raised);
305 Added: color: var(--on-primary);
291 306 background: var(--oxblood);
292 307 }
293 308
@@ -430,7 +445,7 @@
430 445 margin-top: 1rem;
431 446 border: 2px solid var(--oxblood-dark);
432 447 border-radius: var(--radius);
433 Removed: color: var(--paper-raised);
448 Added: color: var(--on-primary);
434 449 background: var(--oxblood);
435 450 cursor: pointer;
436 451 font: 700 var(--font-size-small)/1 var(--sans);
@@ -440,13 +455,13 @@
440 455 }
441 456
442 457 input[type="submit"]:hover {
443 Removed: background: var(--oxblood-dark);
458 Added: background: var(--oxblood-hover);
444 459 transform: translateY(-2px);
445 460 }
446 461 input[type="submit"]:disabled {
447 462 border-color: var(--rule-strong);
448 463 color: var(--muted-ink);
449 Removed: background: #ded8cc;
464 Added: background: var(--disabled-surface);
450 465 cursor: not-allowed;
451 466 }
452 467
@@ -459,7 +474,7 @@
459 474 border-color: var(--brass);
460 475 }
461 476 input[type="submit"].secondary:hover {
462 Removed: color: var(--paper-raised);
477 Added: color: var(--on-brass);
463 478 background: var(--brass);
464 479 }
465 480
@@ -485,7 +500,7 @@
485 500 padding: 0 1rem;
486 501 border: 2px solid var(--oxblood-dark);
487 502 border-radius: var(--radius);
488 Removed: color: var(--paper-raised);
503 Added: color: var(--on-primary);
489 504 background: var(--oxblood);
490 505 font: 700 var(--font-size-small)/1 var(--sans);
491 506 letter-spacing: 0.055em;
@@ -494,8 +509,8 @@
494 509 transition: background-color 150ms ease, transform 150ms ease;
495 510 }
496 511 a.button:hover {
497 Removed: color: var(--paper-raised);
498 Removed: background: var(--oxblood-dark);
512 Added: color: var(--on-primary);
513 Added: background: var(--oxblood-hover);
499 514 transform: translateY(-2px);
500 515 }
501 516 a.button.secondary {
@@ -504,7 +519,7 @@
504 519 border-color: var(--brass);
505 520 }
506 521 a.button.secondary:hover {
507 Removed: color: var(--paper-raised);
522 Added: color: var(--on-brass);
508 523 background: var(--brass);
509 524 }
510 525 a.button.outline {
@@ -513,7 +528,7 @@
513 528 border-color: var(--oxblood);
514 529 }
515 530 a.button.outline:hover {
516 Removed: color: var(--paper-raised);
531 Added: color: var(--on-primary);
517 532 background: var(--oxblood);
518 533 }
519 534
@@ -669,16 +684,16 @@
669 684 font-weight: 700;
670 685 text-decoration: none;
671 686 }
672 Removed: .logbook-row-menu-drawer a:hover { background: #ece4d5; }
687 Added: .logbook-row-menu-drawer a:hover { background: var(--hover-surface); }
673 688 .logbook-row-menu-drawer a.danger { color: var(--oxblood-dark); }
674 689 .logbook-row-menu-drawer a.danger:hover {
675 Removed: color: var(--paper-raised);
690 Added: color: var(--on-primary);
676 691 background: var(--oxblood);
677 692 }
678 693
679 694 .confirm-dialog button.danger {
680 Removed: border-color: var(--oxblood-dark);
681 Removed: background: var(--oxblood-dark);
695 Added: border-color: var(--oxblood-hover);
696 Added: background: var(--oxblood-hover);
682 697 }
683 698 .confirm-dialog button.danger:hover { background: var(--oxblood); }
684 699 .confirm-dialog .delete-record-form { flex: 1 1 10rem; margin: 0; }
@@ -872,7 +887,7 @@
872 887 text-decoration: none;
873 888 }
874 889 .in-progress-card:hover {
875 Removed: background: #ece4d5;
890 Added: background: var(--hover-surface);
876 891 }
877 892 .in-progress-card h1 { margin: 0.35rem 0; }
878 893 .in-progress-card p { margin: 0; }
@@ -890,7 +905,7 @@
890 905 border: 1px solid var(--rule);
891 906 border-radius: var(--radius);
892 907 background: var(--paper-raised);
893 Removed: overflow: hidden;
908 Added: overflow: visible;
894 909 }
895 910 .slot-accordion > summary {
896 911 display: flex;
@@ -1013,7 +1028,7 @@
1013 1028 min-height: 3rem;
1014 1029 border: 2px solid var(--oxblood-dark);
1015 1030 border-radius: var(--radius);
1016 Removed: color: var(--paper-raised);
1031 Added: color: var(--on-primary);
1017 1032 background: var(--oxblood);
1018 1033 cursor: pointer;
1019 1034 font: 700 var(--font-size-small)/1 var(--sans);
@@ -1022,7 +1037,7 @@
1022 1037 transition: background-color 150ms ease, transform 150ms ease;
1023 1038 }
1024 1039 .confirm-dialog button:hover {
1025 Removed: background: var(--oxblood-dark);
1040 Added: background: var(--oxblood-hover);
1026 1041 transform: translateY(-2px);
1027 1042 }
1028 1043 .confirm-dialog button.secondary {
@@ -1031,7 +1046,7 @@
1031 1046 border-color: var(--brass);
1032 1047 }
1033 1048 .confirm-dialog button.secondary:hover {
1034 Removed: color: var(--paper-raised);
1049 Added: color: var(--on-brass);
1035 1050 background: var(--brass);
1036 1051 }
1037 1052
@@ -1078,7 +1093,7 @@
1078 1093 min-height: 3rem;
1079 1094 border: 2px solid var(--oxblood-dark);
1080 1095 border-radius: var(--radius);
1081 Removed: color: var(--paper-raised);
1096 Added: color: var(--on-primary);
1082 1097 background: var(--oxblood);
1083 1098 cursor: pointer;
1084 1099 font: 700 var(--font-size-small)/1 var(--sans);
@@ -1086,7 +1101,7 @@
1086 1101 text-transform: uppercase;
1087 1102 }
1088 1103 .feedback-actions button:hover {
1089 Removed: background: var(--oxblood-dark);
1104 Added: background: var(--oxblood-hover);
1090 1105 }
1091 1106
1092 1107 /* The subjective feedback section on the Logbook. A bordered block separating
@@ -1106,7 +1121,7 @@
1106 1121 border: 1px solid var(--brass);
1107 1122 border-radius: var(--radius);
1108 1123 background: var(--brass-wash);
1109 Removed: color: #47350f;
1124 Added: color: var(--ink);
1110 1125 font-weight: 600;
1111 1126 list-style: none;
1112 1127 }
@@ -1114,6 +1129,7 @@
1114 1129 display: none;
1115 1130 }
1116 1131 .feedback-toggle:hover {
1132 Added: color: var(--on-brass);
1117 1133 background: var(--brass);
1118 1134 }
1119 1135 .feedback-disclosure[open] .feedback-toggle {
@@ -1139,7 +1155,7 @@
1139 1155 margin: 1rem 0;
1140 1156 border: 1px solid var(--brass);
1141 1157 border-left: 5px solid var(--brass);
1142 Removed: color: #47350f;
1158 Added: color: var(--ink);
1143 1159 background: var(--brass-wash);
1144 1160 padding: 0.9rem 1rem;
1145 1161 }
@@ -1231,7 +1247,7 @@
1231 1247 padding: 0;
1232 1248 color: var(--ink);
1233 1249 }
1234 Removed: li::marker { color: #000; }
1250 Added: li::marker { color: var(--ink); }
1235 1251 li ul {
1236 1252 margin: 0.55rem 0 0;
1237 1253 list-style: disc;
@@ -1250,7 +1266,7 @@
1250 1266 border: 1px solid var(--rule);
1251 1267 border-radius: var(--radius);
1252 1268 background: var(--paper-raised);
1253 Removed: overflow: hidden;
1269 Added: overflow: visible;
1254 1270 }
1255 1271 .routine-accordion > summary {
1256 1272 padding: 0.8rem 1rem;
@@ -1311,7 +1327,11 @@
1311 1327 }
1312 1328
1313 1329 @media (prefers-reduced-motion: reduce) {
1314 Removed: *, *::before, *::after { scroll-behavior: auto !important; transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
1330 Added: *, *::before, *::after {
1331 Added: scroll-behavior: auto !important;
1332 Added: transition: none !important;
1333 Added: animation: none !important;
1334 Added: }
1315 1335 }
1316 1336
1317 1337 /* Keyboard users bypass persistent navigation before it becomes visible. */
@@ -1367,7 +1387,7 @@
1367 1387 }
1368 1388 .bottom-nav > a:hover {
1369 1389 color: var(--oxblood-dark);
1370 Removed: background: #ece4d5;
1390 Added: background: var(--hover-surface);
1371 1391 }
1372 1392 .app-shell { padding: 0 0.75rem calc(6.75rem + env(safe-area-inset-bottom)); }
1373 1393
@@ -1401,7 +1421,7 @@
1401 1421 }
1402 1422 .feedback-tab:hover,
1403 1423 .feedback-tab[aria-current] {
1404 Removed: color: var(--paper-raised);
1424 Added: color: var(--on-primary);
1405 1425 background: var(--oxblood);
1406 1426 border-color: var(--oxblood-dark);
1407 1427 }
@@ -1494,10 +1514,6 @@
1494 1514 cursor: pointer;
1495 1515 }
1496 1516 .toast-dismiss:hover { background: rgba(26, 26, 22, 0.08); }
1497 Removed: @media (prefers-reduced-motion: reduce) {
1498 Removed: .toast { animation: none; transition: opacity 320ms ease; }
1499 Removed: .toast[data-hito-toast-done] { transform: translate(-50%, 0); }
1500 Removed: }
1501 1517
1502 1518 /* Subjective feedback uses one inline three-choice group per signal. The radio
1503 1519 input keeps native keyboard and form behavior; its adjacent span is the
@@ -1545,7 +1561,7 @@
1545 1561 }
1546 1562 .feedback-choice input:checked + span {
1547 1563 border-color: var(--oxblood-dark);
1548 Removed: color: var(--paper-raised);
1564 Added: color: var(--on-primary);
1549 1565 background: var(--oxblood);
1550 1566 }
1551 1567