From a1f29c58f79c59139dd43cdfa638c0debaa01dea Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 08:25:01 +0800 Subject: [PATCH 01/12] fix: use lining figures for tier prices Sponsorship tier prices rendered in Cormorant Garamond's default old-style figures, so zeros sat at x-height and the 5 dropped below the baseline, making "$500" hard to read. Co-Authored-By: Claude --- DESIGN.md | 1 + website/static/style.css | 1 + 2 files changed, 2 insertions(+) diff --git a/DESIGN.md b/DESIGN.md index 8cad2e73..eaa53b20 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -116,6 +116,7 @@ Hard-won sizing rules (do not relax): - **When in doubt, pick one step larger** than what generic scale references suggest (`--text-base` over `--text-sm`, 1.75rem over 1.5rem for a heading). The maintainer has corrected sizes upward 11+ times across 8 sessions. Footer, meta rows, expand content, labels, and headings all trend too small by default. **Never reduce an existing size unprompted.** - Adjacent heading levels differ by at least 0.25rem of rendered size. - Row numbers in the table: left-align, no leading zeros. Zero-padding was tried and rejected. +- **Cormorant Garamond numerals use lining figures** (`font-variant-numeric: lining-nums`). Its default old-style figures shrink zeros to x-height and drop 3/4/5/7/9 below the baseline, so a price like `$500` reads as `$5oo`. - **Never `text-transform`.** Write the casing in the markup. ## Layout diff --git a/website/static/style.css b/website/static/style.css index 4e0ea619..2a61b6cb 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1434,6 +1434,7 @@ th[data-sort].sort-asc::after { font-weight: 600; line-height: 0.9; letter-spacing: -0.025em; + font-variant-numeric: lining-nums; color: var(--ink); } From ede39d7ad1d21ffb2383e04b9272830f72b86931 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 08:32:27 +0800 Subject: [PATCH 02/12] style: round ad-hoc font sizes into scale tokens Roughly 20 ad-hoc font-size values rendered near-duplicate sizes 1-2px apart, reading as noise rather than hierarchy, and .hero-category-link rendered below the documented 12px floor. Co-Authored-By: Claude --- DESIGN.md | 20 +++++++++++------ website/static/style.css | 46 +++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index eaa53b20..3185cd7e 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -101,16 +101,22 @@ Pairing (do not swap): Scale: -| Role | Token | Size | Family | Weight | Notes | -| ---------------- | ----------------- | ----------------------------- | ------------------ | --------- | ---------------------------------------------- | -| Hero headline | (literal `clamp`) | `clamp(4.5rem, 11vw, 8.5rem)` | Cormorant Garamond | 600 | Magazine-cover scale, single use on the hero | -| Body large | `--text-lg` | `1.125rem` | Manrope | 400 | Content-heavy passages | -| Body | `--text-base` | `1rem` (16px) | Manrope | 400 | Body floor | -| Meta / secondary | `--text-sm` | `0.95rem` | Manrope | 400 / 600 | Meta rows, secondary copy | -| Caption / pill | `--text-xs` | `0.8rem` (12.8px) | Manrope | 600 / 700 | Smallest token, pills, badges, tags, footnotes | +| Role | Token | Size | Family | Weight | Notes | +| ---------------- | ----------------- | -------------------------------- | ------------------ | --------- | ----------------------------------------------- | +| Hero headline | (literal `clamp`) | `clamp(4.5rem, 11vw, 8.5rem)` | Cormorant Garamond | 600 | Magazine-cover scale, single use on the hero | +| Page title | `--display-lg` | `clamp(3.6rem, 9vw, 7rem)` | Cormorant Garamond | 600 | Category and sponsorship `h1` | +| Section heading | `--display-md` | `clamp(2.25rem, 4.2vw, 3.3rem)` | Cormorant Garamond | 600 | Guide, results, CTA `h2`, sponsor name | +| Display small | `--display-sm` | `clamp(1.75rem, 2.8vw, 2.25rem)` | Cormorant Garamond | 600 | Group-row `h2`, sponsorship lede, past sponsors | +| Lede | `--text-2xl` | `1.5rem` | Manrope | 400 | First paragraph of a category intro | +| Subtitle | `--text-xl` | `1.25rem` | Manrope | 400 | Hero and category subtitles, category intro | +| Body large | `--text-lg` | `1.125rem` | Manrope | 400 | Content-heavy passages, project names, search | +| Body | `--text-base` | `1rem` (16px) | Manrope | 400 | Body floor | +| Meta / secondary | `--text-sm` | `0.95rem` | Manrope | 400 / 600 | Meta rows, secondary copy | +| Caption / pill | `--text-xs` | `0.8rem` (12.8px) | Manrope | 600 / 700 | Smallest token, pills, badges, tags, footnotes | Hard-won sizing rules (do not relax): +- **Every `font-size` uses a scale token.** The literal exceptions are the hero headline, `.tier-amount`, the sort `.arrow` glyph, and `em` sizes on inline code and `kbd`. Body tokens are fixed `rem`; only display tokens are fluid, because `vw` in body text does not grow with browser zoom. Round a new size up to the next token instead of adding an in-between step: sizes 1 to 2px apart read as noise, not hierarchy. - **Body type floor is 16px.** Do not go smaller. - **Absolute minimum font size is 12px (`0.75rem`) for ANY text**, including pills, badges, tags, captions, footnotes. Anything smaller hits Chrome's default minimum-font-size floor and renders inconsistently across browsers and user accessibility settings. - **When in doubt, pick one step larger** than what generic scale references suggest (`--text-base` over `--text-sm`, 1.75rem over 1.5rem for a heading). The maintainer has corrected sizes upward 11+ times across 8 sessions. Footer, meta rows, expand content, labels, and headings all trend too small by default. **Never reduce an existing size unprompted.** diff --git a/website/static/style.css b/website/static/style.css index 2a61b6cb..94a67f3d 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -61,6 +61,12 @@ --text-sm: 0.95rem; --text-base: 1rem; --text-lg: 1.125rem; + --text-xl: 1.25rem; + --text-2xl: 1.5rem; + + --display-sm: clamp(1.75rem, 2.8vw, 2.25rem); + --display-md: clamp(2.25rem, 4.2vw, 3.3rem); + --display-lg: clamp(3.6rem, 9vw, 7rem); --footer-bg: oklch(16% 0.025 35); --footer-text: oklch(72% 0.02 75); @@ -306,7 +312,7 @@ kbd { .hero-sub { margin-top: 2rem; color: var(--hero-muted); - font-size: clamp(1rem, 2vw, 1.18rem); + font-size: var(--text-xl); text-wrap: pretty; } @@ -372,7 +378,7 @@ kbd { .hero-category-link { color: var(--hero-muted); - font-size: 0.72rem; + font-size: var(--text-xs); font-weight: 700; line-height: 1.35; text-decoration: underline; @@ -463,7 +469,7 @@ kbd { .category-hero h1 { font-family: var(--font-display); - font-size: clamp(3.6rem, 9vw, 7rem); + font-size: var(--display-lg); line-height: 0.9; font-weight: 600; text-wrap: balance; @@ -472,7 +478,7 @@ kbd { .category-breadcrumb { margin: 0 0 1rem; color: var(--hero-muted); - font-size: clamp(1rem, 1.5vw, 1.1rem); + font-size: var(--text-lg); } .category-breadcrumb a { @@ -489,7 +495,7 @@ kbd { .category-subtitle { margin-top: 1.1rem; color: var(--hero-muted); - font-size: clamp(1rem, 1.8vw, 1.18rem); + font-size: var(--text-xl); text-wrap: pretty; } @@ -515,13 +521,13 @@ kbd { display: grid; gap: 0.9rem; color: var(--hero-muted); - font-size: clamp(1.05rem, 1.8vw, 1.2rem); + font-size: var(--text-xl); text-wrap: pretty; } .category-intro > p:first-child { color: var(--hero-text); - font-size: clamp(1.2rem, 2.2vw, 1.45rem); + font-size: var(--text-2xl); line-height: 1.45; } @@ -574,7 +580,7 @@ kbd { .guide-section h2 { font-family: var(--font-display); - font-size: clamp(2.2rem, 4vw, 3.3rem); + font-size: var(--display-md); font-weight: 600; line-height: 0.94; letter-spacing: -0.03em; @@ -667,7 +673,7 @@ kbd { .sponsor-name { font-family: var(--font-display); - font-size: clamp(2.25rem, 4.2vw, 3.25rem); + font-size: var(--display-md); font-weight: 600; line-height: 0.95; letter-spacing: -0.025em; @@ -675,7 +681,7 @@ kbd { .sponsor-desc { color: var(--ink-soft); - font-size: clamp(1rem, 1.5vw, 1.1rem); + font-size: var(--text-lg); line-height: 1.55; } @@ -693,7 +699,7 @@ kbd { .results-intro h2, .final-cta h2 { font-family: var(--font-display); - font-size: clamp(2.2rem, 4vw, 3.3rem); + font-size: var(--display-md); font-weight: 600; line-height: 0.94; letter-spacing: -0.03em; @@ -750,7 +756,7 @@ kbd { border-radius: 999px; background: linear-gradient(180deg, oklch(100% 0 0 / 0.82), var(--bg-paper)); color: var(--ink); - font-size: clamp(1rem, 1.4vw, 1.06rem); + font-size: var(--text-lg); box-shadow: inset 0 1px 0 var(--search-inset), 0 1.4rem 2.6rem -2.1rem var(--search-shadow); @@ -854,7 +860,7 @@ kbd { align-items: baseline; gap: 0.75rem; font-family: var(--font-display); - font-size: clamp(1.7rem, 2.8vw, 2.2rem); + font-size: var(--display-sm); font-weight: 600; line-height: 1; scroll-margin-top: 4.5rem; @@ -927,7 +933,7 @@ kbd { .col-name > a { color: var(--ink); - font-size: clamp(1rem, 1.5vw, 1.08rem); + font-size: var(--text-lg); font-weight: 700; overflow-wrap: break-word; word-break: break-word; @@ -1265,7 +1271,7 @@ th[data-sort].sort-asc::after { } .sponsorship-hero-copy h1 { - font-size: clamp(3.4rem, 8.5vw, 6.5rem); + font-size: var(--display-lg); } .sponsorship-proof { @@ -1362,7 +1368,7 @@ th[data-sort].sort-asc::after { .sponsorship-lede { font-family: var(--font-display); - font-size: clamp(1.55rem, 2.6vw, 2rem); + font-size: var(--display-sm); line-height: 1.25; color: var(--ink); letter-spacing: -0.01em; @@ -1518,7 +1524,7 @@ th[data-sort].sort-asc::after { .past-sponsors a { font-family: var(--font-display); - font-size: clamp(1.6rem, 2.8vw, 2.1rem); + font-size: var(--display-sm); font-weight: 600; line-height: 1; letter-spacing: -0.02em; @@ -1564,7 +1570,7 @@ th[data-sort].sort-asc::after { .final-cta p { color: var(--ink-soft); - font-size: clamp(1rem, 1.6vw, 1.08rem); + font-size: var(--text-lg); } .final-cta .hero-action-primary { @@ -1785,10 +1791,6 @@ th[data-sort].sort-asc::after { column-gap: 0.75rem; } - .hero-category-link { - font-size: 0.68rem; - } - .search { min-height: 3.5rem; border-radius: 1.25rem; From b3b3bc202fab93e9ddba7363e934f9052b68517a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 08:36:45 +0800 Subject: [PATCH 03/12] style: raise tier eyebrow and fact labels to text-sm On the sponsorship page the tier names and fact labels rendered smaller than the "/ month" cadence beneath them, inverting the hierarchy. Co-Authored-By: Claude --- website/static/style.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 94a67f3d..f8249f9a 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1391,9 +1391,9 @@ th[data-sort].sort-asc::after { } .sponsorship-facts dt { - font-size: var(--text-xs); + font-size: var(--text-sm); font-weight: 800; - letter-spacing: 0.05em; + letter-spacing: 0.04em; color: var(--ink); } @@ -1421,9 +1421,9 @@ th[data-sort].sort-asc::after { } .tier-eyebrow { - font-size: var(--text-xs); + font-size: var(--text-sm); font-weight: 800; - letter-spacing: 0.05em; + letter-spacing: 0.04em; color: var(--ink); } From 537aff4a466b5822dbe632db23fbd64e63ea562f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 08:40:55 +0800 Subject: [PATCH 04/12] style: set sponsorship ledes in Manrope and stack past sponsor names above descriptions The sponsorship ledes were set in Cormorant Garamond, whose short x-height and thin strokes read poorly across a paragraph, and past sponsor names shared a baseline with Manrope descriptions, where the mismatched x-heights clash. Co-Authored-By: Claude --- DESIGN.md | 26 ++++++++++++++------------ website/static/style.css | 16 +++++++--------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 3185cd7e..1eb296f1 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -99,20 +99,22 @@ Pairing (do not swap): - **Display**: `Cormorant Garamond` (serif, 600 only). - **Body**: `Manrope` (sans, 400 / 600 / 700 / 800). +Cormorant Garamond sets headings and standalone names only, never running sentences, and never on the same line as Manrope. Its short x-height and thin strokes tire the eye across a paragraph, and next to Manrope on one baseline the two x-heights clash. Ledes and other multi-line copy use Manrope (`--text-2xl`); a display name with a description stacks the name above it, as in the sponsor band. + Scale: -| Role | Token | Size | Family | Weight | Notes | -| ---------------- | ----------------- | -------------------------------- | ------------------ | --------- | ----------------------------------------------- | -| Hero headline | (literal `clamp`) | `clamp(4.5rem, 11vw, 8.5rem)` | Cormorant Garamond | 600 | Magazine-cover scale, single use on the hero | -| Page title | `--display-lg` | `clamp(3.6rem, 9vw, 7rem)` | Cormorant Garamond | 600 | Category and sponsorship `h1` | -| Section heading | `--display-md` | `clamp(2.25rem, 4.2vw, 3.3rem)` | Cormorant Garamond | 600 | Guide, results, CTA `h2`, sponsor name | -| Display small | `--display-sm` | `clamp(1.75rem, 2.8vw, 2.25rem)` | Cormorant Garamond | 600 | Group-row `h2`, sponsorship lede, past sponsors | -| Lede | `--text-2xl` | `1.5rem` | Manrope | 400 | First paragraph of a category intro | -| Subtitle | `--text-xl` | `1.25rem` | Manrope | 400 | Hero and category subtitles, category intro | -| Body large | `--text-lg` | `1.125rem` | Manrope | 400 | Content-heavy passages, project names, search | -| Body | `--text-base` | `1rem` (16px) | Manrope | 400 | Body floor | -| Meta / secondary | `--text-sm` | `0.95rem` | Manrope | 400 / 600 | Meta rows, secondary copy | -| Caption / pill | `--text-xs` | `0.8rem` (12.8px) | Manrope | 600 / 700 | Smallest token, pills, badges, tags, footnotes | +| Role | Token | Size | Family | Weight | Notes | +| ---------------- | ----------------- | -------------------------------- | ------------------ | --------- | ------------------------------------------------- | +| Hero headline | (literal `clamp`) | `clamp(4.5rem, 11vw, 8.5rem)` | Cormorant Garamond | 600 | Magazine-cover scale, single use on the hero | +| Page title | `--display-lg` | `clamp(3.6rem, 9vw, 7rem)` | Cormorant Garamond | 600 | Category and sponsorship `h1` | +| Section heading | `--display-md` | `clamp(2.25rem, 4.2vw, 3.3rem)` | Cormorant Garamond | 600 | Guide, results, CTA `h2`, sponsor name | +| Display small | `--display-sm` | `clamp(1.75rem, 2.8vw, 2.25rem)` | Cormorant Garamond | 600 | Group-row `h2`, past sponsor names | +| Lede | `--text-2xl` | `1.5rem` | Manrope | 400 | Category intro first paragraph, sponsorship ledes | +| Subtitle | `--text-xl` | `1.25rem` | Manrope | 400 | Hero and category subtitles, category intro | +| Body large | `--text-lg` | `1.125rem` | Manrope | 400 | Content-heavy passages, project names, search | +| Body | `--text-base` | `1rem` (16px) | Manrope | 400 | Body floor | +| Meta / secondary | `--text-sm` | `0.95rem` | Manrope | 400 / 600 | Meta rows, secondary copy | +| Caption / pill | `--text-xs` | `0.8rem` (12.8px) | Manrope | 600 / 700 | Smallest token, pills, badges, tags, footnotes | Hard-won sizing rules (do not relax): diff --git a/website/static/style.css b/website/static/style.css index f8249f9a..bdc3b7f1 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1367,11 +1367,9 @@ th[data-sort].sort-asc::after { } .sponsorship-lede { - font-family: var(--font-display); - font-size: var(--display-sm); - line-height: 1.25; + font-size: var(--text-2xl); + line-height: 1.45; color: var(--ink); - letter-spacing: -0.01em; text-wrap: pretty; } @@ -1516,9 +1514,9 @@ th[data-sort].sort-asc::after { .past-sponsors li { display: flex; - flex-wrap: wrap; - align-items: baseline; - gap: 0.65rem; + flex-direction: column; + align-items: start; + gap: 0.35rem; padding-block: 0.4rem; } @@ -1537,8 +1535,8 @@ th[data-sort].sort-asc::after { } .past-sponsor-desc { - color: var(--ink-muted); - font-size: var(--text-base); + color: var(--ink-soft); + font-size: var(--text-lg); } .sponsorship-cta-row { From af4f4f8d2f8873b73f55386d42f1146536cca3d3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 08:45:47 +0800 Subject: [PATCH 05/12] fix: scale category subtitle margin with the hero heading The subtitle's fixed top margin did not grow with the fluid h1, so heading descenders crowded the subtitle on category and sponsorship heroes. 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 bdc3b7f1..3c3bd9c8 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -493,7 +493,8 @@ kbd { } .category-subtitle { - margin-top: 1.1rem; + /* Cormorant descenders hang ~0.28em below the h1's 0.9 line box, so the gap scales with the h1. */ + margin-top: max(1.1rem, var(--display-lg) * 0.3); color: var(--hero-muted); font-size: var(--text-xl); text-wrap: pretty; From 94126bc6bca912f3c6c1f6037e4ec8a709dbcce1 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 08:58:41 +0800 Subject: [PATCH 06/12] style: tighten sponsorship hero kicker spacing The sponsorship hero kicker sat farther above the heading than the heading sat above its subtitle, so the label read as detached from the heading it labels. 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 3c3bd9c8..e42dd156 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1271,6 +1271,10 @@ th[data-sort].sort-asc::after { gap: clamp(2rem, 5vw, 3.5rem); } +.sponsorship-hero-copy .hero-kicker { + margin-bottom: 0.5rem; +} + .sponsorship-hero-copy h1 { font-size: var(--display-lg); } From f45997e386d58252dc2b79ea42dffd70dedf92b4 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 15:33:30 +0800 Subject: [PATCH 07/12] fix: draw one focus outline on a focused table row Keyboard focus on a table row drew one box per cell, because the focused row fell back to the browser's default outline and each cell also got an inset accent stripe on its left edge. Co-Authored-By: Claude --- website/static/style.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/website/static/style.css b/website/static/style.css index e42dd156..4c15ac61 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -903,9 +903,13 @@ kbd { background: var(--row-hover); } +.row:focus-visible { + outline: 2px solid var(--accent); + outline-offset: -2px; +} + .row:focus-visible td { background: var(--row-focus); - box-shadow: inset 3px 0 0 var(--accent); } .row:has(+ .desc-row:not([hidden])) td { From 5f2bff284504936980ef41b343e92e27cb143b83 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 15:37:12 +0800 Subject: [PATCH 08/12] fix: show Downloads instead of Stars on narrow screens Below 960px the table hid the PyPI Downloads column but kept the default downloads sort, so the visible Stars column looked unsorted and the active sort header was not shown or tappable. Co-Authored-By: Claude --- website/static/style.css | 10 +++++----- website/templates/category.html | 6 +++--- website/templates/index.html | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 4c15ac61..bc78a581 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1174,7 +1174,7 @@ th[data-sort].sort-asc::after { } .expand-commit, -.expand-downloads { +.expand-stars { display: none; } @@ -1732,12 +1732,12 @@ th[data-sort].sort-asc::after { } .col-commit, - .col-downloads { + .col-stars { display: none; } .expand-commit, - .expand-downloads { + .expand-stars { display: inline; } @@ -1847,8 +1847,8 @@ th[data-sort].sort-asc::after { padding-right: 0.8rem; } - .col-stars { - width: 5.4rem; + .col-downloads { + width: 7.5rem; } .col-arrow { diff --git a/website/templates/category.html b/website/templates/category.html index 6b867269..e27e5f90 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -197,10 +197,10 @@ >{% endif %} {% if entry.downloads is not none %}{% endif %} {% if entry.stars is not none %}/{{ - "{:,}".format(entry.downloads) }} downloads/month{% endif %} diff --git a/website/templates/index.html b/website/templates/index.html index 4b024c3c..156d5aae 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -257,10 +257,10 @@ >{% endif %} {% if entry.downloads is not none %}{% endif %} {% if entry.stars is not none %}/{{ - "{:,}".format(entry.downloads) }} downloads/month{% endif %} From 9b43e6e3377151152671b063a76a701381302c00 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 15:48:59 +0800 Subject: [PATCH 09/12] fix: collapse home hero category list into a disclosure on phones On phones the hero's 74-link category grid was 1,236px tall and pushed the project table down to 2,583px, over three screens. Co-Authored-By: Claude --- website/static/style.css | 27 ++++++++++++++++++++++++--- website/templates/index.html | 32 ++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index bc78a581..d612f1c7 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -353,12 +353,24 @@ kbd { } .hero-category-nav { + padding-top: 1.35rem; + border-top: 1px solid var(--hero-line); +} + +.hero-category-details { display: grid; grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 3rem); align-items: start; - padding-top: 1.35rem; - border-top: 1px solid var(--hero-line); +} + +.hero-category-meta { + display: block; + cursor: pointer; +} + +.hero-category-meta::-webkit-details-marker { + display: none; } .hero-category-meta h2 { @@ -368,6 +380,14 @@ kbd { letter-spacing: 0.04em; } +.hero-category-meta h2::after { + content: " ↓"; +} + +.hero-category-details[open] .hero-category-meta h2::after { + content: " ↑"; +} + .hero-category-links { list-style: none; display: grid; @@ -438,6 +458,7 @@ kbd { .hero-brand-mini:focus-visible, .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, @@ -1718,7 +1739,7 @@ th[data-sort].sort-asc::after { gap: 0.35rem; } - .hero-category-nav { + .hero-category-details { grid-template-columns: 1fr; gap: 0.95rem; } diff --git a/website/templates/index.html b/website/templates/index.html index 156d5aae..6020f35b 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -53,18 +53,26 @@ From 2c0145fbbca11623e56766b06e2ec0e8b9a00b3c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 15:51:43 +0800 Subject: [PATCH 10/12] style: wrap tier billing line under price and keep amounts with units The longer billing lines added with the annual prices broke across two or three lines beside the price and split amounts from their units. Co-Authored-By: Claude --- website/static/style.css | 3 ++- website/templates/sponsorship.html | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index d612f1c7..88d3a736 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1457,8 +1457,9 @@ th[data-sort].sort-asc::after { .tier-price { display: flex; + flex-wrap: wrap; align-items: baseline; - gap: 0.55rem; + gap: 0.35rem 0.55rem; margin-bottom: 0.25rem; } diff --git a/website/templates/sponsorship.html b/website/templates/sponsorship.html index 46d546d8..c250a8f3 100644 --- a/website/templates/sponsorship.html +++ b/website/templates/sponsorship.html @@ -116,7 +116,7 @@

Headline Sponsor

$500 - / month or $4,500 / year + / month or $4,500 / year

Logo pinned at the top of the README. Logo on the website. @@ -139,7 +139,7 @@

Featured Sponsor

$200 - / month or $1,800 / year + / month or $1,800 / year

Small logo and text link pinned at the top of the README. Logo and @@ -166,7 +166,7 @@

Indie Dev Sponsor

$99 - / month, $249 / quarter, or $891 / year + / month, $249 / quarter, or $891 / year

Lower-cost text link for eligible indie developers and solo From 766bff0c08383d9b00aa39f92dc6519d17e7dd9e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 16:22:57 +0800 Subject: [PATCH 11/12] style: set sponsor band apart from the search section and mark names as outbound links The sponsor band's background faded from --bg-paper-strong to --bg-paper, ending lighter than the page below it, with only a faint bottom border, so the band blended into the search section and read as its intro rather than a sponsor placement; the sponsor name also gave no cue that it links out. Co-Authored-By: Claude --- DESIGN.md | 7 ++++--- website/static/style.css | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 1eb296f1..2ac85446 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -62,7 +62,8 @@ Surfaces: - `--bg-page`. Cream/ivory canvas, the body floor. The body uses a vertical gradient from `--bg-page-top` through `--bg-page` (at 24rem) to `--bg-page-end`, with a soft radial highlight in the top-left corner. - `--bg-paper`. Warm white for the content shell. -- `--bg-paper-strong`. Tinted paper for sponsor band, CTA backgrounds, static decoration. +- `--bg-paper-strong`. Tinted paper for CTA backgrounds and static decoration. +- `--sponsor-bg`. Deeper warm tint for the sponsor band only, so it reads as its own block between the hero and the table. - `--hero-bg-start` → `--hero-bg-mid` → `--hero-bg-end`. Dark earthy hero gradient. - `--footer-bg`. Dark warm charcoal footer, part of the same system. @@ -145,7 +146,7 @@ Hard-won sizing rules (do not relax): Depth comes from **tonal layers**, not heavy shadows. -- The page is a quiet warm canvas (`--bg-page`). The content shell is slightly brighter paper (`--bg-paper`). The sponsor band, CTA backgrounds, and inline decorative blocks step up to `--bg-paper-strong`. +- The page is a quiet warm canvas (`--bg-page`). The content shell is slightly brighter paper (`--bg-paper`). CTA backgrounds and inline decorative blocks step up to `--bg-paper-strong`; the sponsor band steps further, to `--sponsor-bg`. - The hero and the category guide band are the only places with real atmosphere: warm gradients on a dark earthy ground (`--hero-bg-start` → `--hero-bg-mid` → `--hero-bg-end`). Only the hero adds the subtle grid and slow sheen. The sheen and any other motion respect `prefers-reduced-motion`. - The footer is a single tonal block in `--footer-bg`, no internal gradients. - Two depth treatments are allowed and only these two. The search input combines a 1px inset highlight (`--search-inset`) with a soft warm drop shadow (`--search-shadow`, intensified by `--search-focus-shadow` on focus). The primary CTA button (`.hero-action-primary`) carries a warm drop shadow for press affordance. Both shadows are soft, warm-tinted, and tied to interactive elements. No new drop shadows on cards, panels, rows, or static decoration. @@ -171,7 +172,7 @@ The component vocabulary is small and table-led. Source of truth: `website/stati - **Hero**. Magazine-cover headline, dark earthy ground, kicker and proof microcopy, primary CTA button using `--hero-btn-start` / `--hero-btn-end`. Subtle grid plus slow sheen. Respects `prefers-reduced-motion`. - **Jump links**. One per use case in a category hero, plus one for the guide. Underlined like the intro's links, with a trailing ↓. Never tag-styled: tags filter the table or open another page, jump links only scroll. - **Guide band**. Everything in a category intro after its "How to choose" list. It sits below the table on the hero's dark gradient, with its H2 above the text. -- **Sponsor band**. Sits below the hero on the home page and category pages, on `--bg-paper-strong`. Editorial layout, not a logo wall. Sponsor links share the global accent treatment. +- **Sponsor band**. Sits below the hero on the home page and category pages, on `--sponsor-bg` with a `--line-strong` bottom border. Editorial layout, not a logo wall. Sponsor links share the global accent treatment; each sponsor name ends in a small ↗ in `--accent-deep` to mark it as an outbound link. - **CTA**. Warm `--cta-bg`, full-bleed within shell. The button itself uses accent tokens. - **Footer**. Dark warm charcoal, part of the same system. Footer links share the global hover and focus treatment. - **Search**. Pill input with `--search-inset` interior and `--search-focus-ring` focus ring. Focus shadow uses `--search-focus-shadow`. diff --git a/website/static/style.css b/website/static/style.css index 88d3a736..65a10921 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -56,6 +56,7 @@ --tag-active-end: oklch(74% 0.11 58); --cta-bg: oklch(94% 0.025 72); + --sponsor-bg: oklch(91% 0.04 68); --text-xs: 0.8rem; --text-sm: 0.95rem; @@ -625,9 +626,8 @@ kbd { .sponsor-band { padding-block: clamp(2.5rem, 5.5vw, 4rem); - background: - linear-gradient(180deg, var(--bg-paper-strong), var(--bg-paper)); - border-bottom: 1px solid var(--line); + background: var(--sponsor-bg); + border-bottom: 1px solid var(--line-strong); } .sponsor-shell { @@ -701,6 +701,16 @@ kbd { letter-spacing: -0.025em; } +.sponsor-name::after { + content: "\2197" / ""; + margin-left: 0.25em; + font-family: var(--font-body); + font-size: 0.45em; + /* Centers the arrow on the name's cap height */ + vertical-align: 0.33em; + color: var(--accent-deep); +} + .sponsor-desc { color: var(--ink-soft); font-size: var(--text-lg); From 85912280e2f8a1de6d9742ce20fb5bf6f98ef1ba Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Wed, 21 Oct 2026 16:26:27 +0800 Subject: [PATCH 12/12] style: enlarge back-to-top tap target to 37x36px The table header's back-to-top button had a 37x20px tap target, below the WCAG 2.2 minimum of 24x24px. Co-Authored-By: Claude --- website/static/style.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/static/style.css b/website/static/style.css index 65a10921..110b995f 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1251,6 +1251,9 @@ th[data-sort].sort-asc::after { } .back-to-top { + /* Grows the tap target past 24px without changing the header row height */ + padding-block: 0.5rem; + margin-block: -0.5rem; border: 0; background: none; color: var(--accent-deep);