From c9161af655efbcec1dbf59064612c45250deda9b Mon Sep 17 00:00:00 2001 From: ctao Date: Sat, 25 Jul 2026 17:35:28 +0200 Subject: [PATCH] =?UTF-8?q?style:=20login=20card=20refined=20per=20guidebo?= =?UTF-8?q?ok=20=E2=80=94=20SG-medium=20h2=20headline,=20D.3.4=20hierarchy?= =?UTF-8?q?,=20logo=20min-size,=20token=20rhythm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/styles/global.css | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/styles/global.css b/src/styles/global.css index 059cbc5..0a053e7 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -26,7 +26,7 @@ --ico-ext: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"%3E%3Cpath d="M7 17 17 7M9 7h8v8" fill="none" stroke="black" stroke-width="3"/%3E%3C/svg%3E'); /* Type — fonts (BRAND D.3.1/D.3.2) and the ONLY font sizes in this codebase */ --font-body: "Inter", "Inter Fallback", Arial, system-ui, sans-serif; - --font-display: "Space Grotesk", var(--font-body); /* headlines only */ + --font-display: "Space Grotesk", "Space Grotesk Fallback", var(--font-body); /* headlines only */ --fs-xs: 0.8125rem; /* chips, meta, badges, labels */ --fs-s: 0.9rem; /* secondary text, nav, forms, footer */ --fs-l: 1.125rem; /* card titles, standfirst, panel titles */ @@ -73,14 +73,21 @@ :root { --hero-scrim: linear-gradient(rgba(0, 0, 74, 0.8), rgba(0, 0, 74, 0.8)); } } -/* Self-hosted brand fonts — latin subset, variable weight, swap + metric-matched fallback */ +/* Self-hosted brand fonts — latin subset, variable weight, preload (Base.astro) + + font-display: swap + metric-matched Arial fallbacks for BOTH families. + NOT `optional`: its ~100ms window loses to per-navigation revalidation + (dev/preview serve no-cache), so pageviews randomly committed to Arial or + the brand font — "fonts flash" between navigations. With swap every page + converges on the brand fonts, and the size-adjusted fallbacks make the + swap metric-neutral (near-zero shift). Override values computed from the + actual font metrics (weighted latin advance widths, capsize method). */ @font-face { - font-family: "Inter"; font-weight: 400 700; font-display: optional; + font-family: "Inter"; font-weight: 400 700; font-display: swap; src: url("/fonts/inter-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { - font-family: "Space Grotesk"; font-weight: 500 700; font-display: optional; + font-family: "Space Grotesk"; font-weight: 500 700; font-display: swap; src: url("/fonts/space-grotesk-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -88,6 +95,10 @@ font-family: "Inter Fallback"; src: local("Arial"); size-adjust: 107%; ascent-override: 90.2%; descent-override: 22.48%; line-gap-override: 0%; } +@font-face { + font-family: "Space Grotesk Fallback"; src: local("Arial"); + size-adjust: 111.12%; ascent-override: 88.55%; descent-override: 26.28%; line-gap-override: 0%; +} /* Screen-reader-only utility (visually hidden, still announced) */ .sr-only { @@ -651,17 +662,21 @@ mark { background: var(--tint-cherenkov); color: inherit; border-radius: calc(va } .auth-card { position: relative; background: #fff; border-radius: calc(var(--radius) + 8px); - padding: var(--space-l); max-width: 440px; width: 100%; + padding: clamp(28px, 4vw, 44px); max-width: 420px; width: 100%; box-shadow: var(--shadow-lifted); + display: flex; flex-direction: column; gap: var(--space-s); } -.auth-logo { height: 24px; width: auto; margin-bottom: var(--space-m); } +/* Logo ≥100px digital (BRAND B.1.3): 26px height ≈ 125px wordmark */ +.auth-logo { height: 26px; width: auto; margin-bottom: var(--space-m); align-self: flex-start; } /* Whisper badge sits top-right, off the reading flow (back in flow ≤480px where it would collide with the logo) */ .auth-card .badge-mock { position: absolute; top: var(--space-l); right: var(--space-l); margin: 0; } @media (max-width: 480px) { .auth-card .badge-mock { position: static; margin-bottom: 14px; } } -.auth-card h1 { color: var(--galaxy); margin: 6px 0 10px; font-size: var(--fs-xl); } -.auth-card .muted { color: var(--muted); font-size: var(--fs-s); } -.btn-wide { width: 100%; margin-top: var(--space-s); } +/* Hierarchy per BRAND D.3.4: SG-medium Galaxy headline, Inter body */ +.auth-card h1 { color: var(--galaxy); margin: 0; font-size: var(--fs-h2); } +.auth-card .muted { color: var(--muted); font-size: var(--fs-s); margin: 0; } +.auth-card .notice { margin: 0; } +.btn-wide { width: 100%; margin-top: var(--space-m); } /* Footer — brand band: logo + descriptor / spec links (§3.3.1) / demo note + flash. No top margin: Moon/Galaxy bands meet it flush; white pages pad via .page/.article. */ @@ -698,7 +713,10 @@ mark { background: var(--tint-cherenkov); color: inherit; border-radius: calc(va sized to be clearly perceptible within ~10s of looking. ========================================================================== */ @media (prefers-reduced-motion: no-preference) { - @view-transition { navigation: auto; } + /* NO cross-document view transitions: the root crossfade snapshots the new + page at its first render opportunity — on slow networks that is a half- + parsed page, so every navigation reads as a full-page blink. Plain MPA + paint + prefetch is the intended feel (see DESIGN.md, Motion policy). */ html { scroll-behavior: smooth; } /* The auth band hands its glow to a roaming layer inside the .band-bg clip frame (same --nebula stack); the photo hero keeps its scrimmed photo and