Per-theme component shape tokens; Sport + Salon polish

Previously every theme had the same hairline-square component voice.
Now each theme picks its own radius / border weight / shadow profile,
chosen to match the theme's brief — editorial / brutalist / technical
themes stay square (the rule is the design); soft / modern themes get
measured radius (Pastel 12px is the most rounded — it's the post-Linear
theme); brutalist themes get heavier 2px borders.

Added four tokens to :root defaults: --radius-card, --radius-pill,
--radius-input, --rule-card, --shadow-card. Per-theme overrides at
the bottom of tokens.css give each theme its own shape voice without
touching colour or typography. Discipline maintained: nothing rounded
"for fun" — every choice maps to the theme's voice.

Token application in components.css: .code blocks pick up
--radius-input + --shadow-card, .tell cards pick up --rule-card +
--radius-card + --shadow-card, .btn picks up --radius-pill,
.banner__random picks up --radius-pill, .hero__mock keeps a
floor of 8px (browser-frame mockups always look slightly rounded).

Sport section title fix: the bold italic uppercase + tight tracking
+ weight 700 produced cramped, almost-touching letterforms. Loosened
tracking (-0.04em → -0.005em) just for section titles, bumped
line-height to 1.12, added 0.15em padding-inline-end for italic-slant
overhang, increased max-width to 26ch, and added word-spacing slack.
Sport's .spec__name and .tell__name also get tracking 0 so the
gallery cards read cleanly.

Salon section heads: tightened the eyebrow→title gap, gave the title
a comfortable 32ch measure, and made the fleuron ❦ divider read as
intentional spacing (margin-block-start, lower opacity, accent colour)
rather than a stray glyph.

Newsprint prose blocks (lede, captions, step subs, foot credits/tagline)
get text-align: justify + hyphens: auto. Long-form newspaper rhythm
without disturbing headlines.

Brutal + Manifesto get 1.5px borders on .code and .install__body,
plus border-color: var(--color-ink) on the install body — the heavier
ink lines suit the brutalist voice. Manifesto inherits from .code's
--rule-card token (set to 2px on Brutal/Manifesto in tokens.css).

Verified across Sport, Salon, Pastel, Quiet, Brutal, Newsprint,
Studio, and Garden — each theme now has a distinct component
shape voice in addition to its colour + typography voice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Youssef
2026-04-30 10:26:22 +01:00
co-authored by Claude Opus 4.7
parent b5b21ceebf
commit d990a2bfaf
2 changed files with 133 additions and 3 deletions
+97 -3
View File
@@ -159,6 +159,7 @@
padding: 0;
background: transparent;
border: 1px solid var(--color-rule);
border-radius: var(--radius-pill, 0);
color: var(--color-muted);
cursor: pointer;
transition: color var(--dur-micro) var(--ease-out),
@@ -260,7 +261,7 @@
color: var(--color-ink);
background: transparent;
border: var(--rule-fine) solid var(--color-ink);
border-radius: 0;
border-radius: var(--radius-pill, 0);
min-height: 44px;
/* explicit properties — never `transition: all` */
transition: transform 100ms var(--ease-out),
@@ -309,6 +310,7 @@
color: var(--color-ink);
background: var(--color-paper-2);
border: var(--rule-hair) solid var(--color-rule);
border-radius: var(--radius-input, 0);
padding: var(--space-md) var(--space-lg);
overflow-x: auto;
white-space: nowrap;
@@ -317,6 +319,7 @@
align-items: center;
gap: var(--space-md);
position: relative;
box-shadow: var(--shadow-card, none);
}
.code .prompt { color: var(--color-muted); user-select: none; }
@@ -335,6 +338,7 @@
color: var(--color-muted);
background: var(--color-paper);
border: var(--rule-hair) solid var(--color-rule);
border-radius: var(--radius-input, 0);
padding: 0.35rem 0.65rem;
cursor: pointer;
opacity: 0;
@@ -524,9 +528,12 @@
flex: 0 0 18rem;
display: grid;
grid-template-rows: 13rem auto;
border: var(--rule-hair) solid var(--color-rule);
border: var(--rule-card, 1px) solid var(--color-rule);
border-radius: var(--radius-card, 0);
scroll-snap-align: start;
background: var(--color-paper);
overflow: hidden;
box-shadow: var(--shadow-card, none);
}
.tell__viz {
@@ -1240,7 +1247,7 @@
max-width: none;
aspect-ratio: 16 / 10;
margin: 0;
border-radius: 14px;
border-radius: max(var(--radius-card, 0), 8px); /* always slightly rounded — it's a browser-frame mockup */
overflow: hidden;
box-shadow: 0 30px 60px -28px oklch(20% 0.02 260 / 0.28),
0 1px 2px oklch(20% 0.02 260 / 0.06);
@@ -1630,3 +1637,90 @@
/* Quiet's hero never shows the clipped mockup — even if forced. */
[data-theme="quiet"] .hero--clipped .hero__mock { display: none; }
[data-theme="quiet"] .hero--clipped { grid-template-columns: 1fr; }
/* ───────────── SPORT — section title fix ─────────────
The italic display + tight tracking + uppercase + weight 700
produced cramped, almost-touching letterforms. Loosen the
tracking just for section titles, give a tiny pad for the
italic slant overhang, and bump line-height for breathing room. */
[data-theme="sport"] .section__title {
letter-spacing: -0.005em; /* loosened from -0.04em */
line-height: 1.12;
padding-inline-end: 0.15em; /* slack for italic slant overhang */
max-width: 26ch;
word-spacing: 0.04em;
}
[data-theme="sport"] .spec__name,
[data-theme="sport"] .tell__name {
letter-spacing: 0;
line-height: 1.05;
}
/* ───────────── SALON — true-centred section heads + fleuron ─────────────
Salon's existing grid override (in sections.css) was fine but the
eyebrow + title weren't perfectly stacked. Tighten the gap between
them, give the title a comfortable measure, and make the fleuron
read as a divider rather than a stray glyph. */
[data-theme="salon"] .section__head {
gap: var(--space-sm);
padding-block-end: var(--space-2xl);
}
[data-theme="salon"] .section-label {
display: inline-flex;
justify-content: center;
margin-inline: auto;
}
[data-theme="salon"] .section__title {
max-width: 32ch;
margin-inline: auto;
font-style: italic;
}
[data-theme="salon"] .section__head::after {
content: "❦";
display: block;
text-align: center;
color: var(--color-accent);
font-size: 1.1rem;
margin-block-start: var(--space-lg);
font-family: var(--font-serif);
line-height: 1;
opacity: 0.65;
}
/* ───────────── NEWSPRINT — justified prose blocks ─────────────
Print discipline. Long-form copy gets justified + hyphenated where
the column is wide enough to render evenly. Headlines stay
left-aligned (only the prose justifies). */
[data-theme="newsprint"] .opening__sub,
[data-theme="newsprint"] .vs__caption,
[data-theme="newsprint"] .step__sub,
[data-theme="newsprint"] .foot__credits,
[data-theme="newsprint"] .foot__tagline {
text-align: justify;
hyphens: auto;
}
/* ───────────── BRUTAL / MANIFESTO — heavier card borders ─────────────
--rule-card is set to 2px on these themes (in tokens.css). The .tell
cards already use --rule-card. For other elements that have hairline
borders by default, give Brutal/Manifesto a touch more weight so the
theme's voice carries through. */
[data-theme="brutal"] .code,
[data-theme="manifesto"] .code,
[data-theme="brutal"] .install__body,
[data-theme="manifesto"] .install__body {
border-width: 1.5px;
}
[data-theme="brutal"] .install__body,
[data-theme="manifesto"] .install__body {
border-color: var(--color-ink);
}
+36
View File
@@ -79,6 +79,18 @@
--rule-hair: 0.5px;
--rule-fine: 1px;
/* Component shape square by default; per-theme overrides below.
The radius / border-weight choice is part of each theme's voice:
editorial themes stay square (Specimen, Newsprint, Salon, Linen),
technical themes stay square (Almanac, Midnight, Terminal),
brutalist themes get heavier borders (Brutal, Manifesto),
soft themes get rounded corners (Pastel, Garden, Studio, Quiet). */
--radius-card: 0; /* .code, .tell cards, .install__body */
--radius-pill: 0; /* CTAs, dot indicators, badges */
--radius-input: 0; /* form fields, single-line code blocks */
--rule-card: 1px; /* card border thickness */
--shadow-card: none; /* card depth — most themes have no shadow */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-in: cubic-bezier(0.7, 0, 0.84, 0);
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
@@ -798,3 +810,27 @@
--measure: 60ch;
}
/*
PER-THEME COMPONENT SHAPE radius, border weight, shadow.
Defaults (in :root above): square edges, 1 px border, no shadow.
These overrides give each theme its own component voice without
touching colour or typography.
The discipline: editorial / brutalist / technical themes stay
square (the rule is the design); soft / modern themes get
measured radius (Pastel 12 px is the most rounded it's the
post-Linear theme); brutalist / declarative themes get heavier
borders. Nothing is rounded "for fun".
*/
[data-theme="brutal"] { --rule-card: 2px; }
[data-theme="manifesto"] { --rule-card: 2px; }
[data-theme="sport"] { --rule-card: 1.5px; }
[data-theme="garden"] { --radius-card: 6px; --radius-pill: 4px; }
[data-theme="studio"] { --radius-card: 6px; --radius-pill: 4px; --shadow-card: 0 1px 2px oklch(20% 0.012 100 / 0.04); }
[data-theme="pastel"] { --radius-card: 12px; --radius-pill: 999px; --radius-input: 8px;
--shadow-card: 0 8px 24px -10px oklch(50% 0.13 282 / 0.14); }
[data-theme="riso"] { --radius-card: 2px; --radius-pill: 2px; }
[data-theme="quiet"] { --radius-card: 4px; --radius-pill: 4px; --shadow-card: 0 1px 2px oklch(20% 0.005 240 / 0.05); }