jb-website/docs/design-system/Posted Graphic.html
2026-06-01 19:35:56 +10:00

202 lines
7.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Posted Graphic — Josh Bairstow</title>
<link rel="stylesheet" href="colors_and_type.css">
<style>
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
background: #16130F;
font-family: var(--font-body);
display: flex; flex-direction: column;
align-items: center; justify-content: center;
min-height: 100vh; gap: 20px; padding: 24px;
}
/* ---- toolbar (outside the scaled canvas) ---- */
.toolbar {
display: flex; gap: 10px; align-items: center;
font-family: var(--font-mono); font-size: 11px; color: #9C8B72;
}
.toolbar .grp { display: flex; gap: 6px; align-items: center; }
.toolbar button {
font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em;
text-transform: uppercase; cursor: pointer; color: #C9B89E;
background: transparent; border: 1px solid rgba(201,184,153,0.25);
border-radius: 3px; padding: 5px 10px;
transition: all var(--dur-base) var(--ease-out);
}
.toolbar button:hover { border-color: rgba(201,184,153,0.6); }
.toolbar button.on { background: rgba(201,184,153,0.14); border-color: rgba(201,184,153,0.6); color: #EFE7DA; }
.toolbar .lbl { opacity: 0.6; letter-spacing: 0.16em; text-transform: uppercase; }
/* ---- scaled stage ---- */
.viewport { display: flex; align-items: center; justify-content: center; }
.canvas {
width: 1080px; height: 1350px;
transform-origin: center center;
position: relative; overflow: hidden;
background: var(--ground);
box-shadow: 0 40px 100px rgba(0,0,0,0.55);
}
.canvas.dark { background: var(--ground-dark); }
/* page-wide grain greeble */
.canvas::before {
content: ""; position: absolute; inset: 0;
background-image: url(assets/texture-grain.svg);
background-size: 300px; opacity: 0.05; pointer-events: none; z-index: 5;
}
.canvas.dark::before { opacity: 0.07; mix-blend-mode: screen; }
/* sprinkled accents — simple crisp marks, loose placement */
.pgMark { position: absolute; pointer-events: none; z-index: 1;
filter: invert(54%) sepia(16%) saturate(340%) brightness(90%); opacity: 0.18; }
.canvas:not(.dark) .pgMark { filter: invert(36%) sepia(18%) saturate(280%) brightness(78%); opacity: 0.13; }
.pgMark.k1 { width: 150px; top: 250px; left: 60px; transform: rotate(-3deg); }
.pgMark.k2 { width: 70px; top: 980px; right: 70px; transform: rotate(4deg); }
.pgMark.k3 { width: 64px; top: 150px; right: 150px; }
.pad { position: absolute; inset: 76px 76px 72px; display: flex; flex-direction: column; z-index: 2; }
/* header row */
.head { display: flex; align-items: baseline; justify-content: space-between; }
.cat {
font-family: var(--font-body); font-weight: 500; font-size: 22px;
letter-spacing: 0.26em; text-transform: uppercase; color: var(--fg-3);
}
.canvas.dark .cat { color: var(--fg-on-dark-2); }
.handle {
font-family: var(--font-mono); font-size: 19px; color: var(--fg-3);
letter-spacing: 0.02em;
}
.canvas.dark .handle { color: var(--fg-on-dark-3); }
/* image cut-out */
.frameWrap { margin-top: 44px; position: relative; }
.frame {
position: relative; width: 100%; height: 620px;
border-radius: 8px 120px 8px 8px;
background: radial-gradient(120% 100% at 70% 14%, #C9B299 0%, #8A6A47 32%, #4A3826 64%, #1E1A16 96%);
overflow: hidden;
}
image-slot { position: absolute; inset: 0; width: 100%; height: 100%;
--is-bg: transparent; background: transparent; }
.frame .wm {
position: absolute; right: 30px; bottom: 26px; width: 150px;
opacity: 0.1; filter: invert(1); z-index: 4; pointer-events: none;
}
/* title block */
.body { margin-top: auto; }
.title {
font-family: var(--font-display); font-weight: 500;
font-size: 72px; line-height: 1.0; letter-spacing: -0.02em;
color: var(--fg-1); margin: 0; text-wrap: balance;
}
.canvas.dark .title { color: var(--fg-on-dark-1); }
.title em { font-style: italic; font-weight: 400; }
.dek {
font-family: var(--font-body); font-weight: 300; font-size: 25px;
line-height: 1.5; color: var(--fg-2); margin: 22px 0 0; max-width: 80%;
}
.canvas.dark .dek { color: var(--fg-on-dark-2); }
/* footer */
.foot {
margin-top: 40px; padding-top: 26px; border-top: 1px solid var(--hairline);
display: flex; align-items: flex-end; justify-content: space-between;
}
.canvas.dark .foot { border-color: var(--hairline-on-dark); }
.foot .sig { width: 90px; opacity: 0.28;
filter: invert(36%) sepia(18%) saturate(280%) brightness(78%); }
.canvas.dark .foot .sig { filter: invert(54%) sepia(16%) saturate(340%) brightness(90%); }
.foot .date {
font-family: var(--font-body); font-size: 21px; color: var(--fg-3);
font-feature-settings: "onum" 1; letter-spacing: 0.02em;
}
.canvas.dark .foot .date { color: var(--fg-on-dark-3); }
</style>
</head>
<body>
<div class="toolbar">
<span class="lbl">Theme</span>
<div class="grp">
<button id="t-light">Bone</button>
<button id="t-dark" class="on">Ink</button>
</div>
<span class="lbl" style="margin-left:14px">Watermark</span>
<div class="grp">
<button class="mk on" data-src="assets/mark-rings.svg">Orbit</button>
<button class="mk" data-src="assets/mark-rings-drift.svg">Drift</button>
<button class="mk" data-src="assets/mark-rings-cascade.svg">Cascade</button>
<button class="mk" data-src="assets/accent-concentric.svg">Concentric</button>
</div>
</div>
<div class="viewport">
<div class="canvas dark" id="canvas">
<img class="pgMark k1" src="assets/accent-ringdots.svg" alt="">
<img class="pgMark k2" src="assets/accent-pipes.svg" alt="">
<img class="pgMark k3" src="assets/accent-dots.svg" alt="">
<div class="pad">
<div class="head">
<span class="cat">Art</span>
<span class="handle">joshbairstow.com</span>
</div>
<div class="frameWrap">
<div class="frame">
<image-slot id="post-image" fit="cover"
placeholder="Drop a photo — warm, directional light"></image-slot>
<img class="wm" id="wm" src="assets/mark-rings.svg" alt="">
</div>
</div>
<div class="body">
<h1 class="title">Warm light,<br><em>cold water</em></h1>
<p class="dek">Notes on chiaroscuro, the ocean off Manly, and learning to see in value.</p>
<div class="foot">
<img class="sig" src="assets/accent-ringdots.svg" alt="">
<span class="date">March 2026</span>
</div>
</div>
</div>
</div>
</div>
<script src="templates/image-slot.js"></script>
<script>
// ---- fit-to-viewport scaling (canvas fixed at 1080x1350) ----
const canvas = document.getElementById('canvas');
const vp = document.querySelector('.viewport');
function fit() {
const availW = window.innerWidth - 48;
const availH = window.innerHeight - 120;
const s = Math.min(availW / 1080, availH / 1350);
canvas.style.transform = `scale(${s})`;
vp.style.width = (1080 * s) + 'px';
vp.style.height = (1350 * s) + 'px';
}
window.addEventListener('resize', fit); fit();
// ---- theme toggle ----
const tl = document.getElementById('t-light'), td = document.getElementById('t-dark');
tl.onclick = () => { canvas.classList.remove('dark'); tl.classList.add('on'); td.classList.remove('on'); };
td.onclick = () => { canvas.classList.add('dark'); td.classList.add('on'); tl.classList.remove('on'); };
// ---- watermark switch ----
const wm = document.getElementById('wm');
document.querySelectorAll('.mk').forEach(b => {
b.onclick = () => {
document.querySelectorAll('.mk').forEach(x => x.classList.remove('on'));
b.classList.add('on');
wm.src = b.dataset.src;
};
});
</script>
</body>
</html>