jb-website/docs/design-system/ui_kits/home/index.html
2026-06-01 19:35:56 +10:00

230 lines
8.7 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Josh Bairstow</title>
<link rel="stylesheet" href="../../colors_and_type.css">
<style>
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
font-family: var(--font-body);
background-color: var(--ground-dark);
color: var(--fg-1);
min-height: 100vh;
}
body.dark { background-color: var(--ground-dark); }
body:not(.dark) { background-color: var(--ground); }
/* page-wide grain greeble — static, barely-there (§5) */
body::before {
content: "";
position: fixed; inset: 0;
background-image: url(../../assets/texture-grain.svg);
background-size: 240px;
opacity: 0.045;
pointer-events: none;
z-index: 0;
}
body.dark::before { opacity: 0.06; mix-blend-mode: screen; }
/* sprinkled accents — simple crisp marks (rings, dots, pipes) placed with
loose, non-rigid positioning across the page. Quiet but present. */
.mark {
position: fixed; pointer-events: none; z-index: 0;
filter: invert(52%) sepia(16%) saturate(340%) brightness(88%);
opacity: 0.16;
}
body:not(.dark) .mark { filter: invert(34%) sepia(18%) saturate(280%) brightness(76%); opacity: 0.11; }
.mark.m1 { width: 84px; top: 15%; left: 3%; transform: rotate(-5deg); }
.mark.m2 { width: 28px; top: 72%; left: 6.5%; transform: rotate(8deg); }
.mark.m3 { width: 50px; top: 28%; right: 3.5%; }
.mark.m4 { width: 40px; bottom: 8%; right: 8%; }
.mark.m5 { width: 66px; bottom: 18%; left: 45%; transform: rotate(-3deg); }
#root { position: relative; z-index: 1; }
.stage {
max-width: 1180px;
margin: 0 auto;
padding: clamp(28px, 5vh, 56px) clamp(24px, 5vw, 64px) clamp(32px, 5vh, 56px);
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* header */
.topbar {
display: flex; align-items: center; justify-content: space-between;
padding-bottom: 18px;
border-bottom: 1px solid var(--hairline);
}
.dark .topbar { border-color: var(--hairline-on-dark); }
.topmeta { display: flex; align-items: center; gap: 22px; }
.coord {
font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
color: var(--fg-3); font-feature-settings: "onum" 1;
}
.toggle {
font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
text-transform: uppercase; cursor: pointer;
background: transparent; color: var(--fg-2);
border: 1px solid var(--hairline-strong);
border-radius: var(--radius-xs); padding: 6px 11px;
transition: border-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.toggle:hover { border-color: var(--fg-1); color: var(--fg-1); }
.dark .toggle { color: var(--fg-on-dark-2); border-color: var(--hairline-on-dark); }
.dark .toggle:hover { color: var(--fg-on-dark-1); border-color: var(--fg-on-dark-1); }
/* hero composition grid */
.hero {
display: grid;
grid-template-columns: 1.15fr 0.85fr;
gap: clamp(32px, 6vw, 80px);
align-items: stretch;
padding: clamp(36px, 7vh, 84px) 0 clamp(28px, 5vh, 56px);
flex: 1;
}
.heroLeft { display: flex; flex-direction: column; }
.eyebrow {
font-family: var(--font-body); font-weight: 500; font-size: 11px;
letter-spacing: 0.24em; text-transform: uppercase; color: var(--fg-3);
margin: 0 0 clamp(20px, 4vh, 34px);
}
.dark .eyebrow { color: var(--fg-on-dark-2); }
.statement {
font-family: var(--font-display); font-weight: 500;
font-size: clamp(40px, 6.4vw, 92px); line-height: 0.96;
letter-spacing: -0.02em; margin: 0; color: var(--fg-1);
text-wrap: balance;
}
.dark .statement { color: var(--fg-on-dark-1); }
.statement em { font-style: italic; font-weight: 400; }
.statement .accent { color: var(--accent-deep); }
.leadline {
font-family: var(--font-body); font-weight: 300;
font-size: clamp(15px, 1.5vw, 18px); line-height: 1.6;
color: var(--fg-2); max-width: 42ch;
margin: clamp(22px, 4vh, 34px) 0 0;
}
.dark .leadline { color: var(--fg-on-dark-2); }
.heroLeftFoot { margin-top: auto; padding-top: clamp(28px, 5vh, 48px); }
.heroRight { display: flex; align-items: stretch; }
.heroRight > * { width: 100%; align-self: center; }
/* lower band: index + signature */
.lower {
display: grid;
grid-template-columns: 1.15fr 0.85fr;
gap: clamp(32px, 6vw, 80px) clamp(32px, 6vw, 80px);
align-items: end;
padding-top: clamp(22px, 3.5vh, 36px);
border-top: 1px solid var(--hairline);
}
.dark .lower { border-top-color: var(--hairline-on-dark); }
.lowerInk {
grid-column: 1 / -1; width: 50px; opacity: 0.22;
margin: 0 0 clamp(6px, 1.4vh, 12px);
filter: invert(52%) sepia(16%) saturate(340%) brightness(88%);
}
body:not(.dark) .lowerInk { filter: invert(34%) sepia(18%) saturate(280%) brightness(76%); }
.indexHead {
font-family: var(--font-body); font-weight: 500; font-size: 11px;
letter-spacing: 0.24em; text-transform: uppercase; color: var(--fg-3);
margin: 0 0 6px;
}
.dark .indexHead { color: var(--fg-on-dark-2); }
.sigBlock { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
.sigBlock img { width: 74px; opacity: 0.24;
filter: invert(52%) sepia(16%) saturate(340%) brightness(88%); }
body:not(.dark) .sigBlock img { filter: invert(34%) sepia(18%) saturate(280%) brightness(76%); }
.copyline {
font-family: var(--font-body); font-size: 12px; color: var(--fg-3);
font-feature-settings: "onum" 1; text-align: right;
}
.dark .copyline { color: var(--fg-on-dark-3); }
@media (max-width: 820px) {
.hero, .lower { grid-template-columns: 1fr; }
.heroRight { max-width: 420px; }
.sigBlock { align-items: flex-start; }
.copyline { text-align: left; }
}
</style>
</head>
<body class="dark">
<img class="mark m1" src="../../assets/accent-ringdots.svg" alt="">
<img class="mark m2" src="../../assets/accent-pipes.svg" alt="">
<img class="mark m3" src="../../assets/accent-dots.svg" alt="">
<img class="mark m4" src="../../assets/accent-concentric.svg" alt="">
<img class="mark m5" src="../../assets/accent-ringdots.svg" alt="">
<div id="root"></div>
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
<script type="text/babel" src="Wordmark.jsx"></script>
<script type="text/babel" src="HeroZone.jsx"></script>
<script type="text/babel" src="LatestLine.jsx"></script>
<script type="text/babel" src="SubdomainIndex.jsx"></script>
<script type="text/babel">
function App() {
const [dark, setDark] = React.useState(true);
React.useEffect(() => {
document.body.classList.toggle('dark', dark);
}, [dark]);
return (
<div className="stage">
<header className="topbar">
<Wordmark size="header" onDark={dark} />
<div className="topmeta">
<span className="coord">33.7969° S · Sydney</span>
<button className="toggle" onClick={() => setDark(d => !d)}>
{dark ? 'Light' : 'Dark'}
</button>
</div>
</header>
<section className="hero">
<div className="heroLeft">
<p className="eyebrow">Engineer · Sydney</p>
<h2 className="statement">
I make small,<br /><em>careful</em> things<span className="accent">.</span>
</h2>
<p className="leadline">
Software, tools, and the occasional mark in ink. A quiet corner of the
internet mostly writing, sometimes shipping.
</p>
<div className="heroLeftFoot">
<LatestLine onDark={dark} />
</div>
</div>
<div className="heroRight">
<HeroZone />
</div>
</section>
<section className="lower">
<img className="lowerInk" src="../../assets/accent-dots.svg" alt="" />
<div>
<p className="indexHead">Index</p>
<SubdomainIndex onDark={dark} />
</div>
<div className="sigBlock">
<img src="../../assets/accent-ringdots.svg" alt="" />
<span className="copyline">© Josh Bairstow Sydney</span>
</div>
</section>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>