afe36fd347
Claude Design export for SD-0001 (login + create-storefront surfaces): wf-*/hf-* screens, design-system bundle, offline preview. First artifact in the ui/designs/ collection (ecomm#8). Also ignore .DS_Store. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
88 lines
5.4 KiB
React
88 lines
5.4 KiB
React
// hf-intro.jsx — Hi-fi cover: the design language Direction A locks in.
|
|
const { HFScreen: IScreen, HFWordmark: IWordmark, HF_H: I, HF_DSC: IDS } = window;
|
|
const { Eyebrow: IEyebrow, Soul: ISoul, Tag: ITag } = IDS;
|
|
|
|
function HFCover() {
|
|
const langs = [
|
|
['Ground', 'Midnight sky with a barely-there starfield; a gold horizon glow warms the bottom of entry screens.'],
|
|
['Depth', 'Carried by layered surfaces and hairlines — not drop shadows. Only the auth card earns real elevation.'],
|
|
['Type', 'Space Grotesk for structure, Inter for body — calm and precise, never hypey. Sentence case throughout; uppercase only for small eyebrows.'],
|
|
['Action', 'One gold CTA per screen. Lilac for links and nodes. Hover lifts 1px; focus is a gold ring.'],
|
|
['Attention', 'Gold, always — the palette carries no red. Honest failure, never a faked success.'],
|
|
['Emptiness', 'A finished state with its own composition — no zeroed tiles, no locked-feature teasers.'],
|
|
];
|
|
return (
|
|
<IScreen horizon style={{ padding: '44px 46px' }}>
|
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
<IWordmark size={28} sub />
|
|
<ITag variant="live">SD-0001 · Hi-fi · Direction A</ITag>
|
|
</div>
|
|
<div style={{ marginTop: 30 }}>
|
|
<IEyebrow style={{ margin: '0 0 14px' }}>Quiet centered — the full design</IEyebrow>
|
|
<h1 style={{ fontFamily: I.disp, fontWeight: 700, letterSpacing: '-0.02em', fontSize: 40, lineHeight: 1.03, color: I.star, margin: '0 0 12px' }}>
|
|
The language, before<br />the hundred screens
|
|
</h1>
|
|
<p style={{ fontFamily: I.body, fontSize: 15.5, lineHeight: 1.6, color: I.soft, maxWidth: 620, margin: 0, textWrap: 'pretty' }}>
|
|
Every surface below is the same six decisions, applied. Get these right and the next ninety-six
|
|
screens inherit a calm, honest house style for free.
|
|
</p>
|
|
</div>
|
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginTop: 30 }}>
|
|
{langs.map(([k, v]) => (
|
|
<div key={k} style={{ display: 'flex', gap: 13, padding: '15px 17px', borderRadius: 12, background: I.raised, border: `1px solid ${I.hairCard}` }}>
|
|
<span style={{ flex: '0 0 auto', width: 7, height: 7, borderRadius: 4, background: I.gold, marginTop: 6 }} />
|
|
<div>
|
|
<div style={{ fontFamily: I.disp, fontWeight: 500, fontSize: 14.5, color: I.star, marginBottom: 3 }}>{k}</div>
|
|
<div style={{ fontFamily: I.body, fontSize: 13, lineHeight: 1.5, color: I.mute }}>{v}</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</IScreen>
|
|
);
|
|
}
|
|
|
|
// Entry routing — the shared spine, hi-fi
|
|
function HFRouting() {
|
|
const lanes = [
|
|
{ sess: 'No session', store: '—', arrow: 'Landing', puc: 'PUC-1', tone: 'mute' },
|
|
{ sess: 'Valid session', store: 'No storefront', arrow: 'Create storefront', puc: 'PUC-5', tone: 'gold' },
|
|
{ sess: 'Valid session', store: 'Has storefront', arrow: 'Admin shell', puc: 'PUC-6', tone: 'lilac' },
|
|
];
|
|
return (
|
|
<IScreen style={{ padding: '44px 40px' }}>
|
|
<IEyebrow style={{ margin: '0 0 14px' }}>The shared spine</IEyebrow>
|
|
<h1 style={{ fontFamily: I.disp, fontWeight: 700, letterSpacing: '-0.015em', fontSize: 28, lineHeight: 1.08, color: I.star, margin: '0 0 10px' }}>Entry routing</h1>
|
|
<p style={{ fontFamily: I.body, fontSize: 14, lineHeight: 1.55, color: I.soft, margin: '0 0 8px' }}>
|
|
One server answer — <code style={{ fontFamily: 'ui-monospace,monospace', fontSize: 12.5, color: I.lilac, background: 'var(--wv-lilac-08)', padding: '1px 6px', borderRadius: 5 }}>GET /api/auth/me</code> — decides where every arrival lands.
|
|
</p>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 13, marginTop: 26 }}>
|
|
{lanes.map((l, i) => {
|
|
const c = l.tone === 'gold' ? I.gold : l.tone === 'lilac' ? I.lilac : I.mute;
|
|
return (
|
|
<div key={i} className="row-lift" style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '17px 19px', borderRadius: 12, background: I.raised, border: `1px solid ${I.hairCard}` }}>
|
|
<div style={{ display: 'flex', gap: 8, flex: '0 0 auto' }}>
|
|
<Cond>{l.sess}</Cond><Cond>{l.store}</Cond>
|
|
</div>
|
|
<span aria-hidden="true" style={{ color: c, fontSize: 18, flex: '0 0 auto' }}>→</span>
|
|
<div style={{ flex: 1, display: 'flex', alignItems: 'baseline', gap: 10, justifyContent: 'flex-end' }}>
|
|
<span style={{ fontFamily: I.disp, fontWeight: 700, fontSize: 17, color: c, letterSpacing: '-0.01em' }}>{l.arrow}</span>
|
|
<span style={{ fontFamily: I.body, fontSize: 11.5, color: I.mute }}>{l.puc}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
<p style={{ fontFamily: I.body, fontSize: 13, lineHeight: 1.55, color: I.mute, margin: '24px 0 0', display: 'flex', gap: 9 }}>
|
|
<span aria-hidden="true" style={{ color: I.lilac }}>◇</span>
|
|
Exhaustive by design — no state lands nowhere. A merchant without a storefront is guided to create one, never stranded.
|
|
</p>
|
|
</IScreen>
|
|
);
|
|
}
|
|
function Cond({ children }) {
|
|
return <span style={{ fontFamily: I.body, fontSize: 13, color: I.soft, padding: '6px 12px', borderRadius: 999, background: 'rgba(237,234,255,.05)', border: `1px solid ${I.hair}`, whiteSpace: 'nowrap' }}>{children}</span>;
|
|
}
|
|
|
|
Object.assign(window, { HFCover, HFRouting });
|