Background
Follow-up from a review comment on #101 (gemini-code-assist, medium): #101 (closing #78) migrated the typography tokens to Tailwind v4's --text-* namespace (Approach A — real text-h1, text-body, … utilities), but kept the layout --frame-* tokens as raw vars consumed via arbitrary-value classes (Approach B — px-[var(--frame-gutter)], max-w-[var(--frame-max)], …), matching the existing scroll-mt-[var(--nav-h)] precedent. This was a deliberate split (see #78's "Approach (open question)" section). This issue tracks the remaining "Approach A for layout" option, should we want it.
Proposal
Promote the layout tokens in app/globals.css's @theme inline block to Tailwind v4 namespaces so standard utilities auto-generate (no bracket-soup):
--frame-gutter: clamp(1.5rem, 4vw, 4rem) → --spacing-frame-gutter ⇒ px-frame-gutter
--frame-pad-y: clamp(5rem, 9vw, 7rem) → --spacing-frame-pad-y ⇒ py-frame-pad-y
--frame-max: 1280px → --container-frame ⇒ max-w-frame (also yields a @frame container-query variant — harmless)
--frame-min-h-cap: 54rem → fold the min() into the token: --spacing-frame-min-h: min(100svh, 54rem) ⇒ min-h-frame-min-h (alternatively keep --frame-min-h-cap as a raw var and leave min-h-[min(100svh,var(--frame-min-h-cap))] as-is — it's irreducibly an arbitrary value otherwise)
Sites to update
components/ui/Frame.tsx — px-frame-gutter py-frame-pad-y min-h-frame-min-h on the <section>, max-w-frame on the inner <div>
components/site/Footer.tsx — px-frame-gutter, max-w-frame
components/site/Chrome.tsx — px-frame-gutter, max-w-frame
app/globals.css — the lone CSS ref right: var(--frame-gutter) (mobile-menu close button) → var(--spacing-frame-gutter); update the --frame-* mentions in the :root --nav-h comment and the @theme inline comments
Trade-off
Renames the public CSS-var API (--frame-* → --spacing-frame-* / --container-frame). No external consumers were found when #78 was scoped (docs/, content/blog/, all .css/.ts(x) — app/globals.css is the website's only stylesheet), so this is low-risk; bundle as one PR (a partial migration reintroduces the inconsistency #78 fixed).
Verification
Same triple as #78: pnpm lint && pnpm exec tsc --noEmit && pnpm test && pnpm build; pnpm dev smoke (frame gutter / max-width rail / min-height unchanged across §01–§05, /blog, a post); confirm out/_next/static/chunks/*.css is roughly flat in size.
Links
Background
Follow-up from a review comment on #101 (
gemini-code-assist, medium): #101 (closing #78) migrated the typography tokens to Tailwind v4's--text-*namespace (Approach A — realtext-h1,text-body, … utilities), but kept the layout--frame-*tokens as raw vars consumed via arbitrary-value classes (Approach B —px-[var(--frame-gutter)],max-w-[var(--frame-max)], …), matching the existingscroll-mt-[var(--nav-h)]precedent. This was a deliberate split (see #78's "Approach (open question)" section). This issue tracks the remaining "Approach A for layout" option, should we want it.Proposal
Promote the layout tokens in
app/globals.css's@theme inlineblock to Tailwind v4 namespaces so standard utilities auto-generate (no bracket-soup):--frame-gutter: clamp(1.5rem, 4vw, 4rem)→--spacing-frame-gutter⇒px-frame-gutter--frame-pad-y: clamp(5rem, 9vw, 7rem)→--spacing-frame-pad-y⇒py-frame-pad-y--frame-max: 1280px→--container-frame⇒max-w-frame(also yields a@framecontainer-query variant — harmless)--frame-min-h-cap: 54rem→ fold themin()into the token:--spacing-frame-min-h: min(100svh, 54rem)⇒min-h-frame-min-h(alternatively keep--frame-min-h-capas a raw var and leavemin-h-[min(100svh,var(--frame-min-h-cap))]as-is — it's irreducibly an arbitrary value otherwise)Sites to update
components/ui/Frame.tsx—px-frame-gutter py-frame-pad-y min-h-frame-min-hon the<section>,max-w-frameon the inner<div>components/site/Footer.tsx—px-frame-gutter,max-w-framecomponents/site/Chrome.tsx—px-frame-gutter,max-w-frameapp/globals.css— the lone CSS refright: var(--frame-gutter)(mobile-menu close button) →var(--spacing-frame-gutter); update the--frame-*mentions in the:root--nav-hcomment and the@theme inlinecommentsTrade-off
Renames the public CSS-var API (
--frame-*→--spacing-frame-*/--container-frame). No external consumers were found when #78 was scoped (docs/,content/blog/, all.css/.ts(x)—app/globals.cssis the website's only stylesheet), so this is low-risk; bundle as one PR (a partial migration reintroduces the inconsistency #78 fixed).Verification
Same triple as #78:
pnpm lint && pnpm exec tsc --noEmit && pnpm test && pnpm build;pnpm devsmoke (frame gutter / max-width rail / min-height unchanged across §01–§05,/blog, a post); confirmout/_next/static/chunks/*.cssis roughly flat in size.Links