From ba0d4c397ea2ea9015f0e0e42330def3b93d06af Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:24 +0800 Subject: [PATCH 01/18] fix: keep the hidden back-to-top button out of the tab order The hidden back-to-top button was only transparent, so Tab still stopped on it and its focus outline was invisible. Co-Authored-By: Claude --- website/static/style.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/static/style.css b/website/static/style.css index 59ffb190..3ea73f16 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1269,14 +1269,18 @@ th[data-sort].sort-asc::after { letter-spacing: 0.03em; cursor: pointer; opacity: 0; + /* Keeps the hidden button out of the tab order; stays visible for the whole fade */ + visibility: hidden; pointer-events: none; transition: opacity 180ms ease, + visibility 180ms ease, color 180ms ease; } .back-to-top.visible { opacity: 1; + visibility: visible; pointer-events: auto; } From ac8cffc779dfeec7692eee8c37c88c95ee4b161d Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:43 +0800 Subject: [PATCH 02/18] style: enlarge category link tap targets on phones On phones the hero's category links were about 17px tall and 4.5px apart, below the 24px minimum touch target. Co-Authored-By: Claude --- website/static/style.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/website/static/style.css b/website/static/style.css index 3ea73f16..612957b5 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1857,6 +1857,16 @@ th[data-sort].sort-asc::after { column-gap: 0.75rem; } + /* Meets the 24px minimum touch target */ + .hero-category-links li { + padding-bottom: 0; + } + + .hero-category-link { + display: inline-block; + padding-block: 0.35rem; + } + .search { min-height: 3.5rem; border-radius: 1.25rem; From 242af0e11e003ef31b3c4110b1f500a850db13d2 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:43 +0800 Subject: [PATCH 03/18] style: extend topbar link tap targets to 44px Topbar links were about 37px tall, short of a 44px touch target. Co-Authored-By: Claude --- website/static/style.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/website/static/style.css b/website/static/style.css index 612957b5..3923677a 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -233,6 +233,7 @@ kbd { } .hero-topbar-link { + position: relative; padding: 0.45rem 0.8rem; border: 1px solid var(--hero-line); border-radius: 999px; @@ -247,6 +248,13 @@ kbd { transform 180ms ease; } +/* Grows the tap target to 44px without changing the pill */ +.hero-topbar-link::after { + content: ""; + position: absolute; + inset: -0.25rem 0; +} + .hero-topbar-link-strong, .hero-topbar-link:hover { border-color: oklch(100% 0 0 / 0.28); From d829a262a39ef553e18fea2af047b78e831f8906 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:43 +0800 Subject: [PATCH 04/18] style: center tag tap targets without overlapping neighbours Each tag's tap area overlapped the next tag's and, with both insets plus min-height set, grew downward only, sitting off-center. Co-Authored-By: Claude --- website/static/style.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 3923677a..02ea3e79 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1246,12 +1246,12 @@ th[data-sort].sort-asc::after { margin-left: 0.2rem; } +/* A 44px-tall target centered on the pill, kept clear of the neighbouring tags */ .tag::after { content: ""; position: absolute; - inset: -0.5rem -0.25rem; - min-height: 44px; - min-width: 44px; + inset-block: calc((100% - 44px) / 2); + inset-inline: -0.1rem; } .tag:hover { From b46518c497d53eddb809ca74f654b48edfd57179 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:43 +0800 Subject: [PATCH 05/18] style: show a single focus ring on the search field Text inputs match :focus-visible on click, so the search field showed the accent outline on top of its own tinted focus border. Co-Authored-By: Claude --- website/static/style.css | 1 - 1 file changed, 1 deletion(-) diff --git a/website/static/style.css b/website/static/style.css index 02ea3e79..6a4ce29d 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -459,7 +459,6 @@ kbd { .hero-topbar-link:focus-visible, .hero-category-link:focus-visible, .hero-category-meta:focus-visible, -.search:focus-visible, .tag:focus-visible, .jump-link:focus-visible, .back-to-top:focus-visible, From e1d4806abb64c11cbe8e7c6298624791645be84c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:57 +0800 Subject: [PATCH 06/18] fix: hide decorative arrows and the search icon from screen readers Arrow glyphs on rows, jump links, sort headers, and the category toggle, plus the search icon, were exposed to assistive tech, adding noise to every row and link name. Co-Authored-By: Claude --- website/static/style.css | 14 +++++++------- website/templates/category.html | 3 ++- website/templates/index.html | 3 ++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 6a4ce29d..3d15ff9a 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -378,11 +378,11 @@ kbd { } .hero-category-meta h2::after { - content: " ↓"; + content: " ↓" / ""; } .hero-category-details[open] .hero-category-meta h2::after { - content: " ↑"; + content: " ↑" / ""; } .hero-category-links { @@ -594,7 +594,7 @@ kbd { /* The arrow marks an in-page jump; inline-block keeps it out of the underline */ .jump-link::after { - content: "\2193"; + content: "\2193" / ""; display: inline-block; margin-left: 0.3rem; color: var(--hero-kicker); @@ -1022,13 +1022,13 @@ th[data-sort]:hover { } th[data-sort]::after { - content: " \2193"; + content: " \2193" / ""; opacity: 0; transition: opacity 180ms ease; } th[data-sort="name"]::after { - content: " \2191"; + content: " \2191" / ""; } th[data-sort]:hover::after, @@ -1038,11 +1038,11 @@ th[data-sort].sort-desc::after { } th[data-sort].sort-desc::after { - content: " \2193"; + content: " \2193" / ""; } th[data-sort].sort-asc::after { - content: " \2191"; + content: " \2191" / ""; } .col-stars { diff --git a/website/templates/category.html b/website/templates/category.html index d901c06f..4399505c 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -155,7 +155,7 @@ {% endif %} - → + {% if entry.description %} @@ -234,6 +234,7 @@
→ + {% if entry.description %} From 23b40a8476c9f323f3bc80ea2dbdfe8cfe0f488a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:57 +0800 Subject: [PATCH 07/18] style: balance section heading line breaks Section headings could wrap with a single word on the last line. Co-Authored-By: Claude --- website/static/style.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/static/style.css b/website/static/style.css index 3d15ff9a..b0c8877f 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -617,6 +617,7 @@ kbd { font-weight: 600; line-height: 0.94; letter-spacing: -0.03em; + text-wrap: balance; } .guide-body { @@ -747,6 +748,7 @@ kbd { font-weight: 600; line-height: 0.94; letter-spacing: -0.03em; + text-wrap: balance; } .results-section { From 407a8e48bcf67825de3f680e17850192030767e3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:57 +0800 Subject: [PATCH 08/18] style: avoid orphan words in short paragraphs Sponsor, sponsorship, call-to-action, and table-note paragraphs could end on a lone word, unlike their peers. Co-Authored-By: Claude --- website/static/style.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/website/static/style.css b/website/static/style.css index b0c8877f..996ea369 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -728,6 +728,7 @@ kbd { color: var(--ink-soft); font-size: var(--text-lg); line-height: 1.55; + text-wrap: pretty; } .sponsor-desc a { @@ -768,12 +769,14 @@ kbd { align-self: start; color: var(--ink-soft); font-size: var(--text-base); + text-wrap: pretty; } .results-note { color: var(--ink-soft); font-size: var(--text-sm); justify-self: end; + text-wrap: pretty; } /* Single-project pages drop the order note, so keep the note in the last column */ @@ -1399,6 +1402,7 @@ th[data-sort].sort-asc::after { color: var(--ink-muted); font-size: var(--text-sm); line-height: 1.55; + text-wrap: pretty; } .sponsorship-body { @@ -1473,6 +1477,7 @@ th[data-sort].sort-asc::after { color: var(--ink-soft); font-size: var(--text-base); line-height: 1.65; + text-wrap: pretty; } .tier-list { @@ -1548,6 +1553,7 @@ th[data-sort].sort-asc::after { color: var(--ink-soft); font-size: var(--text-base); line-height: 1.6; + text-wrap: pretty; } .tier-includes li::before { @@ -1612,6 +1618,7 @@ th[data-sort].sort-asc::after { .past-sponsor-desc { color: var(--ink-soft); font-size: var(--text-lg); + text-wrap: pretty; } .sponsorship-cta-row { @@ -1649,6 +1656,7 @@ th[data-sort].sort-asc::after { .final-cta p { color: var(--ink-soft); font-size: var(--text-lg); + text-wrap: pretty; } .final-cta .hero-action-primary { From 6147fa1c8077689ceca78c0fe39a8f2b1a57be9d Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:55:57 +0800 Subject: [PATCH 09/18] style: drop the row expand animation On the home page, opening a row showed the description instantly while the details below it slid in, so one open state moved in two ways. Co-Authored-By: Claude --- website/static/style.css | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 996ea369..b9bd3e62 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1185,7 +1185,6 @@ th[data-sort].sort-asc::after { overflow-wrap: break-word; word-break: break-word; contain: layout style paint; - animation: expand-in 220ms cubic-bezier(0.22, 1, 0.36, 1); } .expand-also-see a, @@ -1737,17 +1736,6 @@ th[data-sort].sort-asc::after { border: 0; } -@keyframes expand-in { - from { - opacity: 0; - transform: translateY(-0.4rem); - } - to { - opacity: 1; - transform: translateY(0); - } -} - @media (max-width: 960px) { .hero-grid, .results-intro, @@ -1961,8 +1949,6 @@ th[data-sort].sort-asc::after { } *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } From 74f217ed76174264fd63d71ed18b535c197d5f19 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:56:05 +0800 Subject: [PATCH 10/18] style: scale buttons down on press The 1px press nudge was barely visible on pill buttons. Co-Authored-By: Claude --- website/static/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/static/style.css b/website/static/style.css index b9bd3e62..7f0dc157 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -264,7 +264,7 @@ kbd { .hero-topbar-link:active, .hero-action:active, .tag:active { - transform: translateY(1px); + transform: scale(0.96); } .hero-grid { From 0551570da82427a980415fed0e7b6fa4717118b8 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:56:05 +0800 Subject: [PATCH 11/18] style: shorten row and tag hover transitions Hover fades of 180ms on a long table left trailing highlights when sweeping the pointer across rows. Co-Authored-By: Claude --- website/static/style.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 7f0dc157..09d2822c 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -889,7 +889,7 @@ kbd { vertical-align: middle; border-bottom: 1px solid var(--line); transition: - background-color 180ms ease, + background-color 150ms ease-out, border-color 180ms ease; } @@ -1122,7 +1122,7 @@ th[data-sort].sort-asc::after { text-wrap: pretty; overflow-wrap: break-word; transition: - background-color 180ms ease, + background-color 150ms ease-out, border-color 180ms ease; } @@ -1239,9 +1239,9 @@ th[data-sort].sort-asc::after { letter-spacing: 0.02em; cursor: pointer; transition: - color 180ms ease, - background-color 180ms ease, - border-color 180ms ease, + color 150ms ease-out, + background-color 150ms ease-out, + border-color 150ms ease-out, transform 180ms ease; } From fdd49249d1569d4c89b3dd392505d4e19c0dc480 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 21:58:48 +0800 Subject: [PATCH 12/18] style: switch row borders instantly when a row opens Table cells faded their border color over 180ms, so opening a row left the old divider visible between the row and its newly shown content before it faded out. Co-Authored-By: Claude --- website/static/style.css | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 09d2822c..c8d2a40d 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -888,9 +888,7 @@ kbd { padding-bottom: 1rem; vertical-align: middle; border-bottom: 1px solid var(--line); - transition: - background-color 150ms ease-out, - border-color 180ms ease; + transition: background-color 150ms ease-out; } .table tbody tr[hidden] { @@ -1121,9 +1119,7 @@ th[data-sort].sort-asc::after { line-height: 1.6; text-wrap: pretty; overflow-wrap: break-word; - transition: - background-color 150ms ease-out, - border-color 180ms ease; + transition: background-color 150ms ease-out; } .row:not(.open) + .desc-row td { From 761745ad8ceaa9f5d8a930041c3327cbc01f9d0c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 22:01:30 +0800 Subject: [PATCH 13/18] refactor: drop the press transform from tags Tags are inline links, which CSS transforms do not apply to, so the tag press rule and its transform transition never had any effect. Co-Authored-By: Claude --- website/static/style.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index c8d2a40d..d6db5b1b 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -262,8 +262,7 @@ kbd { } .hero-topbar-link:active, -.hero-action:active, -.tag:active { +.hero-action:active { transform: scale(0.96); } @@ -1237,8 +1236,7 @@ th[data-sort].sort-asc::after { transition: color 150ms ease-out, background-color 150ms ease-out, - border-color 150ms ease-out, - transform 180ms ease; + border-color 150ms ease-out; } .tag + .tag { From 179d4552597904e10956f5cdc7aa3bddfa33a9f7 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 22:03:27 +0800 Subject: [PATCH 14/18] fix: stop clipping focus rings on links in an opened row Paint containment on the opened row's details clipped anything drawn outside its box, cutting off the focus outline of links at its edges. Co-Authored-By: Claude --- website/static/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/static/style.css b/website/static/style.css index d6db5b1b..8a8fc670 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1179,7 +1179,7 @@ th[data-sort].sort-asc::after { text-wrap: pretty; overflow-wrap: break-word; word-break: break-word; - contain: layout style paint; + contain: layout style; } .expand-also-see a, From 3fc97705e7bd72cdd00d5bdcb331dbbb056aa478 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 22:04:51 +0800 Subject: [PATCH 15/18] fix: draw a focused tag's ring above the next tag The focus ring reaches farther than the gap between tags, and the next tag painted over its right side. Co-Authored-By: Claude --- website/static/style.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/website/static/style.css b/website/static/style.css index 8a8fc670..fb064adf 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1243,6 +1243,11 @@ th[data-sort].sort-asc::after { margin-left: 0.2rem; } +/* The focus ring reaches past the gap, so lift it above the next tag */ +.tag:focus-visible { + z-index: 1; +} + /* A 44px-tall target centered on the pill, kept clear of the neighbouring tags */ .tag::after { content: ""; From 67673a386d796937e463d1e0d9885fafef645dfa Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 22:25:19 +0800 Subject: [PATCH 16/18] fix: drop default outline and opaque-ify search focus ring Removing .search from the :focus-visible list left the focused search field with Chromium's default blue outline, and its translucent focus border measured 1.65:1 against the page, below WCAG 1.4.11's 3:1. Co-Authored-By: Claude --- website/static/style.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/static/style.css b/website/static/style.css index fb064adf..656110d2 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -47,7 +47,7 @@ --search-inset: oklch(100% 0 0 / 0.75); --search-shadow: oklch(18% 0.03 45 / 0.24); - --search-focus-ring: oklch(61% 0.14 48 / 0.45); + --search-focus-ring: oklch(61% 0.14 48); --search-focus-shadow: oklch(34% 0.08 42 / 0.28); --tag-hover-border: oklch(71% 0.09 62 / 0.45); @@ -826,6 +826,7 @@ kbd { } .search:focus { + outline: none; border-color: var(--search-focus-ring); box-shadow: inset 0 1px 0 var(--search-inset), From 58a0349dfe6940280c657b523aeaacbc613167b2 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 22:26:40 +0800 Subject: [PATCH 17/18] Revert "style: avoid orphan words in short paragraphs" This reverts commit 407a8e48bcf67825de3f680e17850192030767e3. --- website/static/style.css | 8 -------- 1 file changed, 8 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 656110d2..45498f93 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -727,7 +727,6 @@ kbd { color: var(--ink-soft); font-size: var(--text-lg); line-height: 1.55; - text-wrap: pretty; } .sponsor-desc a { @@ -768,14 +767,12 @@ kbd { align-self: start; color: var(--ink-soft); font-size: var(--text-base); - text-wrap: pretty; } .results-note { color: var(--ink-soft); font-size: var(--text-sm); justify-self: end; - text-wrap: pretty; } /* Single-project pages drop the order note, so keep the note in the last column */ @@ -1401,7 +1398,6 @@ th[data-sort].sort-asc::after { color: var(--ink-muted); font-size: var(--text-sm); line-height: 1.55; - text-wrap: pretty; } .sponsorship-body { @@ -1476,7 +1472,6 @@ th[data-sort].sort-asc::after { color: var(--ink-soft); font-size: var(--text-base); line-height: 1.65; - text-wrap: pretty; } .tier-list { @@ -1552,7 +1547,6 @@ th[data-sort].sort-asc::after { color: var(--ink-soft); font-size: var(--text-base); line-height: 1.6; - text-wrap: pretty; } .tier-includes li::before { @@ -1617,7 +1611,6 @@ th[data-sort].sort-asc::after { .past-sponsor-desc { color: var(--ink-soft); font-size: var(--text-lg); - text-wrap: pretty; } .sponsorship-cta-row { @@ -1655,7 +1648,6 @@ th[data-sort].sort-asc::after { .final-cta p { color: var(--ink-soft); font-size: var(--text-lg); - text-wrap: pretty; } .final-cta .hero-action-primary { From 31994bb73f2ea88e5c07e94ef2965bac1cb434ff Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 25 Oct 2026 22:26:40 +0800 Subject: [PATCH 18/18] Revert "style: balance section heading line breaks" This reverts commit 23b40a8476c9f323f3bc80ea2dbdfe8cfe0f488a. --- website/static/style.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 45498f93..d14e65f4 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -616,7 +616,6 @@ kbd { font-weight: 600; line-height: 0.94; letter-spacing: -0.03em; - text-wrap: balance; } .guide-body { @@ -747,7 +746,6 @@ kbd { font-weight: 600; line-height: 0.94; letter-spacing: -0.03em; - text-wrap: balance; } .results-section {