From adf0da6fd480db09ec0898c70adb07ce7edbcb42 Mon Sep 17 00:00:00 2001 From: Youssef Date: Wed, 6 May 2026 14:06:15 +0100 Subject: [PATCH] =?UTF-8?q?Polish=20=E2=80=94=20drop=20Bricolage,=20vertic?= =?UTF-8?q?al=20section=20heads,=20edge-bleed=20examples,=20GitHub=20star?= =?UTF-8?q?=20button?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six items in one pass: · **Bricolage Grotesque removed** entirely. Distinctive italic-a forms (curl ear) read as "weird" at section-title scale across several themes. Replaced per-theme with cleaner alternatives: Sport → Inter Tight (italic). Riso → Space Grotesk. Almanac → IBM Plex Sans. Plume → Geist. Manifesto's display fallback chain swapped Bricolage out for Space Grotesk. Google Fonts stylesheet URL updated — Bricolage dropped, Space Grotesk and Anton (italic axis) added. · **Section heads restructured.** Was: 10rem | 1fr two-column with the section label ("04 / ANTI-PATTERNS") on the left and the title on the right. Problem: at narrow widths (and on themes that override to 6rem | 1fr like Sport), the label was forced to wrap mid-word ("ANTI-/PATTERNS") and the title felt squeezed. Now: single-column. Label stacks ABOVE the title with a small gap. Label gets `white-space: nowrap` so it never breaks. Title font-size grows from `clamp(2rem, 3vw + 1rem, 3rem)` to `clamp(2rem, 4vw + 0.5rem, 3.5rem)` since it has full row width. Sport's per-theme override (was 6rem | 1fr) now also 1fr. · **Foundations card strokes — fixed.** The gap-as-border pattern (gap: 0.5px, parent bg showing through) sub-pixel-rounded inconsistently — col 2/3 boundaries dropped on some themes. Replaced with explicit 1px right + bottom borders on each card, plus left + top on the parent. Every divider now renders crisp at every theme + viewport. Atelier/Salon use a dashed bottom rule instead, no vertical dividers (matches their borderless card aesthetic). · **Worked examples — full bleed to viewport edges.** The rail had `margin-inline: calc(-1 * var(--page-gutter))` which only escaped the page gutter, not the page max-width. On wide desktops the rail still capped at 76rem. Now uses `width: 100vw; margin-inline: calc(50% - 50vw)` so cards extend flush to the viewport edges no matter how wide the screen. Internal scroll-padding still snaps the first/last card cleanly. · **Study brief pill** — "Paste a design you admire." → "/hallmark study this landing page". Reads as the actual command the user would type, matches the Build row's brief style. · **GitHub star button** added to the nav. Sits beside Install, styled as an inverse pill (ink fill, accent star, paper text). Live star count fetched from the GitHub API on first paint, cached in localStorage for 1h to avoid rate-limit. Falls back to "★" if the request fails. Counts ≥1000 render as "1.2k" etc. Co-Authored-By: Claude Opus 4.7 (1M context) --- site/css/components.css | 57 ++++++++++++++++++++++++++++++++++++ site/css/sections.css | 65 +++++++++++++++++++++++++---------------- site/css/tokens.css | 18 ++++++------ site/index.html | 13 +++++++-- site/js/main.js | 40 +++++++++++++++++++++++++ 5 files changed, 156 insertions(+), 37 deletions(-) diff --git a/site/css/components.css b/site/css/components.css index ee190cb..bf8b5a1 100644 --- a/site/css/components.css +++ b/site/css/components.css @@ -104,6 +104,63 @@ .banner__install { display: none; } } +/* GitHub star button — sits next to Install in the banner, shows + the live star count fetched from the GitHub API on load (cached + in localStorage for 1 hour to avoid rate-limit). Click → repo. */ +.banner__star { + display: inline-flex; + align-items: center; + gap: 0.35rem; + margin-inline-start: var(--space-2xs); + padding: 0.18rem 0.65rem; + font-family: var(--font-label); + font-weight: 500; + font-size: 0.6875rem; + letter-spacing: 0.06em; + color: var(--color-ink); + text-decoration: none; + background: var(--color-ink); + color: var(--color-paper); + border: 1px solid var(--color-ink); + border-radius: var(--radius-pill, 999px); + transition: background-color var(--dur-micro) var(--ease-out), + color var(--dur-micro) var(--ease-out), + border-color var(--dur-micro) var(--ease-out); +} + +.banner__star-icon { + flex-shrink: 0; + display: block; + color: var(--color-accent); +} + +.banner__star-count { + font-feature-settings: "tnum" 1; + letter-spacing: 0.04em; +} + +.banner__star:hover { + background: var(--color-accent); + border-color: var(--color-accent); + color: var(--color-paper); +} + +.banner__star:hover .banner__star-icon { + color: var(--color-paper); +} + +.banner__star:focus-visible { + outline: 2px solid var(--color-focus); + outline-offset: 2px; +} + +@media (max-width: 36rem) { + .banner__star { + padding: 0.18rem 0.5rem; + gap: 0.3rem; + } +} + /* Genre label — small text after the theme name in the banner. */ .banner__theme { display: inline; diff --git a/site/css/sections.css b/site/css/sections.css index bfa4ef5..1c6b6dc 100644 --- a/site/css/sections.css +++ b/site/css/sections.css @@ -23,32 +23,39 @@ position: relative; /* anchors absolute children (hidden radios) */ } +/* Section head — single-column always. Section label stacks ABOVE + the title, separated by a small gap. No more 10rem fixed sidebar + that forced the section label ("ANTI-PATTERNS") to wrap on + themes that needed wider title columns. Section titles can grow + bigger now since they have full width. */ .section__head { display: grid; - grid-template-columns: 10rem 1fr; - gap: var(--space-xl); - align-items: baseline; + grid-template-columns: 1fr; + gap: var(--space-sm); padding-bottom: var(--section-head-gap); border-bottom: var(--rule-hair) solid var(--color-rule-2); } +/* Section label — small mono uppercase coordinate above the title. + Hard rule: never wrap. White-space: nowrap forces single-line at + every viewport. The label is short ("05 / Foundations") so this + is safe. */ +.section-label, +.section__head .section-label { + white-space: nowrap; +} + .section__title { font-family: var(--font-display); font-weight: var(--display-weight, 400); font-style: var(--display-style, normal); - font-size: var(--text-2xl); - line-height: var(--lh-snug); + font-size: clamp(2rem, 4vw + 0.5rem, 3.5rem); + line-height: var(--lh-tight); letter-spacing: var(--tracking-display); - max-width: 24ch; + max-width: 28ch; color: var(--color-ink); font-optical-sizing: auto; -} - -@media (max-width: 48rem) { - .section__head { - grid-template-columns: 1fr; - gap: var(--space-md); - } + margin: 0; } /* Narrow viewports — let headings wrap freely + cap display sizes so @@ -191,12 +198,13 @@ overflow-x: auto; overflow-y: visible; scroll-snap-type: x mandatory; - /* Escape the page gutter so tiles can extend past the container edge */ - margin-inline: calc(-1 * var(--page-gutter)); + /* Full-bleed: escape both the page max-width AND the page gutter so + the rail spans the full viewport regardless of how wide the + screen is. Cards extend right up to the viewport's edge. */ + width: 100vw; + margin-inline: calc(50% - 50vw); padding-inline: var(--page-gutter); padding-block: var(--space-md) var(--space-lg); - /* Symmetric scroll-padding so the first AND last card snap clean to the - gutter — without inline-end the last card always reads as clipped. */ scroll-padding-inline: var(--page-gutter); scrollbar-color: var(--color-rule-2) transparent; } @@ -1452,10 +1460,9 @@ html[data-theme="almanac"] body { } [data-theme="sport"] .opening__sub { font-weight: 500; } [data-theme="sport"] .section__head { - grid-template-columns: 6rem 1fr; + grid-template-columns: 1fr; border-bottom: 2px solid var(--color-rule-2); padding-bottom: var(--space-md); - align-items: end; } [data-theme="sport"] .section__title { font-style: italic; @@ -1678,15 +1685,21 @@ html[data-theme="almanac"] body { font-style: normal; } +/* Foundations cards — explicit per-card right + bottom borders so + every column gap renders crisp at every theme + viewport. The + prior gap-as-border pattern (gap: 0.5px, parent bg showing + through) sub-pixel-rounded inconsistently — col 2/3 gaps + sometimes vanished. The new approach uses real 1px borders on + each card, parent gives top + left, cards give right + bottom. + Result: every divider renders. */ .found-cards { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: var(--rule-hair); - background: var(--color-rule); - border: var(--rule-hair) solid var(--color-rule); + border-block-start: 1px solid var(--color-rule); + border-inline-start: 1px solid var(--color-rule); } .found-card { @@ -1696,6 +1709,8 @@ html[data-theme="almanac"] body { gap: var(--space-sm); align-content: start; min-height: 12rem; + border-block-end: 1px solid var(--color-rule); + border-inline-end: 1px solid var(--color-rule); } .found-card__icon { @@ -1747,16 +1762,16 @@ html[data-theme="almanac"] body { [data-theme="atelier"] .found-card, [data-theme="salon"] .found-card { background: transparent; + border-inline-end: 0; + border-block-end: var(--rule-hair) dashed var(--color-rule); } [data-theme="atelier"] .found-cards, [data-theme="salon"] .found-cards { background: transparent; border: 0; - gap: var(--space-md); border-block-start: var(--rule-hair) solid var(--color-rule); - border-block-end: var(--rule-hair) solid var(--color-rule); - padding-block: var(--space-lg); + padding-block-start: var(--space-md); } @media (max-width: 60rem) { diff --git a/site/css/tokens.css b/site/css/tokens.css index 0ad4a44..a85ffd7 100644 --- a/site/css/tokens.css +++ b/site/css/tokens.css @@ -404,9 +404,9 @@ --color-accent-ink: oklch(58% 0.24 28); --color-focus: #E51A1A; - --font-display: "Anton", "Bebas Neue", "Bricolage Grotesque", "Space Grotesk", sans-serif; + --font-display: "Anton", "Bebas Neue", "Space Grotesk", sans-serif; --font-body: "IBM Plex Sans", "Public Sans", "The Future", ui-sans-serif, sans-serif; - --font-serif: "Anton", "Bricolage Grotesque", sans-serif; + --font-serif: "Anton", "Space Grotesk", sans-serif; --font-label: "JetBrains Mono", ui-monospace, monospace; --font-mono: "JetBrains Mono", ui-monospace, monospace; @@ -550,7 +550,7 @@ --color-accent-ink: oklch(40% 0.13 250); --color-focus: oklch(38% 0.135 250); - --font-display: "Bricolage Grotesque", "IBM Plex Sans", ui-sans-serif, sans-serif; + --font-display: "IBM Plex Sans", "Hanken Grotesk", ui-sans-serif, sans-serif; --font-body: "IBM Plex Sans", "The Future", ui-sans-serif, sans-serif; --font-serif: "Newsreader", ui-serif, Georgia, serif; --font-label: "IBM Plex Mono", ui-monospace, monospace; @@ -606,9 +606,9 @@ --color-accent-ink: oklch(54% 0.20 35); --color-focus: oklch(58% 0.190 35); - --font-display: "Bricolage Grotesque", "Space Grotesk", ui-sans-serif, sans-serif; + --font-display: "Inter Tight", "Space Grotesk", ui-sans-serif, sans-serif; --font-body: "Plus Jakarta Sans", "Hanken Grotesk", "The Future", ui-sans-serif, sans-serif; - --font-serif: "Bricolage Grotesque", ui-sans-serif, sans-serif; + --font-serif: "Inter Tight", ui-sans-serif, sans-serif; --font-label: "JetBrains Mono", ui-monospace, monospace; --font-mono: "JetBrains Mono", ui-monospace, monospace; @@ -729,7 +729,7 @@ } /* ────────────────────────────────────────────────────────────── - RISO — risograph print · Bricolage display, off-register + RISO — risograph print · Space Grotesk display, off-register Inspiration: Are.na, e-flux, Frieze, indie magazine sites. Warm peach paper, riso cyan + yellow as accents, slight CMYK misregistration on display via text-shadow. @@ -750,10 +750,10 @@ --color-accent-ink: oklch(58% 0.170 220); --color-focus: oklch(58% 0.170 220); - --font-display: "Bricolage Grotesque", "Inter Tight", system-ui, sans-serif; + --font-display: "Space Grotesk", "Inter Tight", system-ui, sans-serif; --font-body: "Newsreader", "Tiempos", ui-serif, Georgia, serif; --font-serif: "Newsreader", ui-serif, Georgia, serif; - --font-label: "Bricolage Grotesque", ui-monospace, monospace; + --font-label: "Space Grotesk", ui-monospace, monospace; --font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace; --display-weight: 800; @@ -1064,7 +1064,7 @@ --color-accent-ink: oklch(96% 0.020 70); --color-focus: oklch(68% 0.130 18); - --font-display: "Bricolage Grotesque", "Geist", ui-sans-serif, system-ui, sans-serif; + --font-display: "Geist", "Inter Tight", ui-sans-serif, system-ui, sans-serif; --font-body: "Geist", "Inter", ui-sans-serif, system-ui, sans-serif; --font-serif: "Newsreader", ui-serif, Georgia, serif; --font-label: "Geist Mono", ui-monospace, monospace; diff --git a/site/index.html b/site/index.html index ef63d91..d4ee403 100644 --- a/site/index.html +++ b/site/index.html @@ -20,11 +20,11 @@ - + + href="https://fonts.googleapis.com/css2?family=Anton&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;1,9..144,400;1,9..144,500&family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500&family=Inter:wght@400;500;600;700&family=Inter+Tight:ital,wght@0,500;0,600;0,700;0,800;1,500;1,600;1,700&family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;1,6..72,400;1,6..72,500&family=Playfair+Display:ital,wght@1,400;1,500;1,600&family=Space+Grotesk:wght@400;500;600;700&display=swap" /> @@ -53,6 +53,13 @@ + +