Files
portfolio-next/mockups/personal-r2-d.html
T
Lucas WintherandClaude Opus 5.5 843b6d32bc chore: bootstrap agent-ready docs, rules and design-phase artefacts
Add AGENTS.md as the single source of truth (with CLAUDE.md and GEMINI.md
as pointers), permissions for Claude Code, Codex and Gemini, the docs tree
(architecture, decisions, TODO, permissions, specs, plans), PRODUCT.md and
DESIGN.md, plus the design-phase record: the inspiration log, all mockup
rounds with briefs and screenshots, and the owner's work history.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 06:47:38 +01:00

534 lines
46 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lucas Winther · off the clock</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..700;1,9..144,300..600&family=Caveat:wght@500;600&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root {
--bg: #2a1a1f; --bg2: #321f26; --panel: #38242b; --panel2: #432c34; --ink: #f1e6d6; --ink2: #e3d4c1; --mute: #b8a592; --dim: #8a7568;
--line: rgba(241,230,214,.12); --line2: rgba(241,230,214,.24);
--amber: #e8b04a; --rose: #c9706b; --cream: #f1e6d6; --plum: #2a1a1f;
--serif: "Fraunces", Georgia, serif; --hand: "Caveat", cursive; --mono: "Geist Mono", ui-monospace, monospace;
--ease: cubic-bezier(.2,.8,.2,1); --edge: 42px;
}
* { box-sizing: border-box; }
html { scroll-padding-top: 72px; }
html, body { margin: 0; }
body { background: var(--bg); color: var(--ink); font-family: var(--serif); font-size: 16px; line-height: 1.55; font-weight: 350; -webkit-font-smoothing: antialiased; }
body::before { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: .16;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 .9 0 0 0 0 .8 0 0 0 .55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"); }
body::after { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0; background: radial-gradient(900px 500px at 75% -10%, rgba(232,176,74,.08), transparent 70%), radial-gradient(700px 500px at 0% 60%, rgba(201,112,107,.06), transparent 70%); }
a { color: inherit; }
button { font: inherit; color: inherit; }
::selection { background: var(--amber); color: var(--plum); }
:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.ph { text-decoration: underline dotted rgba(241,230,214,.35); text-underline-offset: 3px; text-decoration-thickness: 1px; cursor: help; }
.mono { font-family: var(--mono); }
.mk { position: fixed; bottom: 14px; right: 14px; z-index: 80; width: 310px; background: #f4ece0; color: #2a1a1f; font: 12px/1.45 var(--mono); padding: 10px 28px 10px 12px; border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,.35); }
.mk b { display: block; font-family: var(--serif); font-size: 14px; margin-bottom: 3px; }
.mk button { position: absolute; top: 4px; right: 6px; background: none; border: 0; font-size: 16px; cursor: pointer; color: #2a1a1f; }
.edge { position: fixed; top: 0; left: 0; bottom: 0; width: var(--edge); z-index: 60; background: #131210; color: #ede7dd; border-right: 1px solid #2a2724; display: flex; align-items: center; justify-content: center; writing-mode: vertical-rl; font: 500 12px var(--mono); letter-spacing: .12em; text-transform: uppercase; text-decoration: none; transition: width .2s var(--ease); }
.edge span { transform: rotate(180deg); }
.edge:hover { width: 54px; }
.page { position: relative; z-index: 1; margin-left: var(--edge); }
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 40px; }
.bar { position: sticky; top: 0; z-index: 50; background: rgba(42,26,31,.82); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid var(--line); }
.bar .in { max-width: 1240px; margin: 0 auto; padding: 0 40px; height: 56px; display: flex; align-items: center; gap: 26px; }
.crumb { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
.crumb a.back { font: 12px var(--mono); color: var(--mute); text-decoration: none; border: 1px solid var(--line2); border-radius: 6px; padding: 3px 8px; transition: color .15s, border-color .15s; }
.crumb a.back:hover { color: var(--ink); border-color: var(--mute); }
.crumb b { font-weight: 500; font-size: 15px; }
.crumb span { font-style: italic; color: var(--mute); }
.nav { display: flex; gap: 2px; }
.nav a { text-decoration: none; color: var(--ink2); font-size: 15px; padding: 5px 10px; border-radius: 6px; transition: background .15s; }
.nav a:hover { background: rgba(241,230,214,.07); }
.upd { margin-left: auto; font: 12px var(--mono); color: var(--mute); display: flex; align-items: center; gap: 8px; }
.upd i { width: 7px; height: 7px; border-radius: 50%; background: var(--amber); }
/* intro */
.intro { display: grid; grid-template-columns: 1fr 280px; gap: 60px; padding: 46px 0 30px; align-items: center; }
.hi { font: 600 30px/1 var(--hand); color: var(--amber); transform: rotate(-2deg); transform-origin: left; display: inline-block; }
.intro h1 { margin: 10px 0 0; font-weight: 300; font-size: 50px; line-height: 1.08; letter-spacing: -.02em; font-variation-settings: "opsz" 90; max-width: 17em; }
.intro h1 em { font-style: italic; color: var(--amber); }
.intro h1 .r { font-style: italic; color: var(--rose); }
.intro p { margin: 16px 0 0; font-size: 18px; color: var(--ink2); max-width: 36em; }
.intro .meta { margin-top: 18px; font: 12px var(--mono); color: var(--mute); display: flex; gap: 18px; flex-wrap: wrap; }
.me { position: relative; justify-self: end; }
.me .card { width: 240px; background: #f4ece0; padding: 10px 10px 8px; transform: rotate(2.5deg); box-shadow: 0 2px 0 rgba(0,0,0,.25), 0 24px 40px -20px rgba(0,0,0,.7); transition: transform .3s var(--ease); }
.me .card:hover { transform: rotate(.5deg) translateY(-4px); }
.me svg { display: block; width: 100%; }
.me .cap { font: 600 21px/1 var(--hand); color: #2a1a1f; text-align: center; margin: 6px 0 2px; }
.me .tape { position: absolute; width: 80px; height: 22px; background: rgba(232,176,74,.7); top: -10px; left: 80px; transform: rotate(-4deg); }
/* section heads */
.sh { display: flex; align-items: baseline; gap: 14px; margin: 0 0 14px; }
.sh h2 { margin: 0; font: 600 30px/1 var(--hand); color: var(--amber); transform: rotate(-1.5deg); transform-origin: left; }
.sh .n { font: 12px var(--mono); color: var(--mute); }
.sh .r { margin-left: auto; font: 12px var(--mono); color: var(--mute); }
.sh .r a { color: var(--ink2); text-decoration: none; border-bottom: 1px solid var(--rose); }
.sh .r a:hover { color: var(--amber); }
section { padding: 26px 0; }
/* currently */
.now { display: grid; grid-template-columns: repeat(4, 1fr) 1.35fr; background: var(--panel); border: 1px solid var(--line); border-radius: 16px; overflow: hidden; box-shadow: 0 30px 60px -40px rgba(0,0,0,.8); }
.slot { padding: 18px 18px 16px; border-right: 1px solid var(--line); position: relative; transition: background .2s; min-width: 0; }
.slot:hover { background: rgba(241,230,214,.03); }
.slot:last-child { border-right: 0; background: linear-gradient(160deg, rgba(232,176,74,.12), rgba(201,112,107,.06) 70%); }
.slot .lbl { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .09em; color: var(--mute); display: flex; justify-content: space-between; gap: 6px; }
.slot .lbl a { color: var(--dim); text-decoration: none; text-transform: none; letter-spacing: 0; transition: color .15s; }
.slot .lbl a:hover { color: var(--amber); }
.cov { height: 112px; margin: 12px 0 12px; display: flex; align-items: flex-end; gap: 12px; }
.cov .art { height: 112px; border-radius: 3px; box-shadow: 0 10px 20px -10px rgba(0,0,0,.8); flex: none; transition: transform .25s var(--ease); }
.slot:hover .cov .art { transform: translateY(-3px) rotate(-1.5deg); }
.cov .art.book { width: 75px; } .cov .art.sq { width: 112px; } .cov .art.wide { width: 100%; height: 100px; }
.slot .ti { font-size: 18px; font-weight: 450; line-height: 1.15; }
.slot .su { font-size: 14px; color: var(--mute); font-style: italic; margin-top: 2px; }
.slot .prog { height: 3px; border-radius: 2px; background: rgba(241,230,214,.12); margin-top: 10px; overflow: hidden; }
.slot .prog i { display: block; height: 100%; background: var(--amber); }
.slot .pm { font: 11px var(--mono); color: var(--dim); margin-top: 5px; display: flex; justify-content: space-between; }
.slot .note { font: 500 20px/1.1 var(--hand); color: var(--rose); margin-top: 10px; max-height: 0; opacity: 0; overflow: hidden; transition: max-height .25s var(--ease), opacity .2s; }
.slot:hover .note, .slot:focus-within .note { max-height: 60px; opacity: 1; }
.now-foot { display: flex; justify-content: space-between; font: 11.5px var(--mono); color: var(--dim); padding: 10px 4px 0; }
/* looping player */
.loopbox { display: flex; gap: 14px; align-items: center; margin: 12px 0 10px; }
.disc { width: 112px; height: 112px; border-radius: 50%; flex: none; position: relative; background: radial-gradient(circle, #f1e6d6 0 5%, var(--amber) 5.5% 26%, #1b1013 26.5% 28%, #221418 28.5% 100%); box-shadow: 0 10px 22px -10px rgba(0,0,0,.9); }
.disc::after { content: ""; position: absolute; inset: 8px; border-radius: 50%; background: repeating-radial-gradient(circle, transparent 0 3px, rgba(255,255,255,.045) 3px 4px); }
.disc::before { content: ""; position: absolute; left: 50%; top: 50%; width: 46%; height: 2px; background: linear-gradient(90deg, transparent, rgba(255,255,255,.18)); transform-origin: left; transform: rotate(-30deg); z-index: 1; }
.loopbox.on .disc { animation: spin 3.6s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.eq { display: flex; gap: 3px; align-items: flex-end; height: 26px; margin-bottom: 6px; }
.eq i { width: 4px; background: var(--amber); border-radius: 1px; height: 6px; opacity: .55; transition: height .2s; }
.loopbox.on .eq i { animation: eq 0.9s ease-in-out infinite alternate; opacity: 1; }
.loopbox.on .eq i:nth-child(2) { animation-delay: -.3s; } .loopbox.on .eq i:nth-child(3) { animation-delay: -.6s; } .loopbox.on .eq i:nth-child(4) { animation-delay: -.15s; } .loopbox.on .eq i:nth-child(5) { animation-delay: -.45s; }
@keyframes eq { from { height: 4px; } to { height: 24px; } }
.ctl { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.pp { width: 40px; height: 40px; border-radius: 50%; border: 0; background: var(--amber); color: var(--plum); display: grid; place-items: center; cursor: pointer; flex: none; transition: transform .15s, background .15s; }
.pp:hover { transform: scale(1.06); background: #f2c063; }
.pp svg { width: 14px; height: 14px; }
.seek { flex: 1; position: relative; height: 18px; cursor: pointer; }
.seek::before { content: ""; position: absolute; left: 0; right: 0; top: 8px; height: 2px; border-radius: 2px; background: rgba(241,230,214,.18); }
.seek i { position: absolute; left: 0; top: 8px; height: 2px; border-radius: 2px; background: var(--amber); width: 0; }
.tm { font: 11px var(--mono); color: var(--mute); font-variant-numeric: tabular-nums; white-space: nowrap; }
.loopct { font: 11px var(--mono); color: var(--mute); margin-top: 8px; }
.loopct b { color: var(--amber); font-weight: 500; }
/* featured + shares */
.pair { display: grid; grid-template-columns: 1.25fr 1fr; gap: 48px; }
.feat { position: relative; }
.feat .kick, .share .kick { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .09em; color: var(--mute); display: flex; gap: 10px; }
.kick .t { color: var(--rose); }
.feat h3 { margin: 10px 0 12px; font-weight: 300; font-size: 44px; line-height: 1.04; letter-spacing: -.025em; font-variation-settings: "opsz" 144; }
.feat h3 i { color: var(--amber); }
.feat .stand { font-size: 19px; font-style: italic; color: var(--ink2); margin: 0 0 16px; line-height: 1.45; }
.feat .body { font-size: 16.5px; color: var(--ink2); max-width: 36em; }
.feat .body p { margin: 0 0 12px; }
.feat .body > p:first-child::first-letter { float: left; font: 500 62px/.8 var(--serif); color: var(--amber); margin: 6px 10px 0 0; }
.more { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s var(--ease); }
.more > div { overflow: hidden; }
.more.open { grid-template-rows: 1fr; }
.rd { background: none; border: 0; padding: 0; cursor: pointer; font: italic 17px var(--serif); color: var(--ink); display: inline-flex; gap: 8px; align-items: center; border-bottom: 1px solid var(--rose); }
.rd .arrow { transition: transform .2s; display: inline-block; }
.rd:hover { color: var(--amber); } .rd:hover .arrow { transform: translateX(4px); }
.margin-note { position: absolute; right: -6px; top: 4px; font: 500 21px/1.05 var(--hand); color: var(--rose); transform: rotate(4deg); text-align: right; }
.feat .meta { font: 11.5px var(--mono); color: var(--dim); margin-top: 14px; display: flex; gap: 16px; }
.shares { display: flex; flex-direction: column; }
.share { display: grid; grid-template-columns: 124px 1fr; gap: 18px; padding: 16px 0; border-top: 1px solid var(--line); text-decoration: none; position: relative; }
.share:last-of-type { border-bottom: 1px solid var(--line); }
.share .thumb { height: 100px; position: relative; transition: transform .25s var(--ease); }
.share:hover .thumb { transform: translateY(-3px) rotate(-1.5deg); }
.share .thumb svg { width: 100%; height: 100%; display: block; }
.share h4 { margin: 6px 0 4px; font-weight: 450; font-size: 20px; line-height: 1.15; letter-spacing: -.01em; transition: color .15s; }
.share:hover h4 { color: var(--amber); }
.share p { margin: 0; font-size: 14.5px; color: var(--ink2); }
.share .when { position: absolute; right: 0; top: 16px; font: 11px var(--mono); color: var(--dim); }
/* doors */
.doors { display: grid; grid-template-columns: repeat(8, 1fr); gap: 14px; perspective: 900px; }
.door { all: unset; box-sizing: border-box; cursor: pointer; display: block; text-align: center; }
.frame { position: relative; height: 190px; border-radius: 70px 70px 4px 4px; background: #1d1115; overflow: hidden; box-shadow: inset 0 0 0 1px var(--line2); }
.inside { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; padding: 0 8px 16px 46%; background: radial-gradient(circle at 70% 70%, rgba(232,176,74,.35), transparent 70%); }
.inside .cnt { font: 500 42px/1 var(--serif); color: var(--amber); }
.inside .lt { font: 10px/1.3 var(--mono); text-align: center; color: var(--ink2); margin-top: 6px; }
.leaf { position: absolute; inset: 0; border-radius: 70px 70px 4px 4px; transform-origin: left center; transition: transform .3s var(--ease); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.25); backface-visibility: hidden; }
.leaf::before { content: ""; position: absolute; inset: 14px 14px 14px 14px; border-radius: 56px 56px 2px 2px; border: 1px solid rgba(0,0,0,.18); }
.leaf .knob { position: absolute; right: 14px; top: 56%; width: 8px; height: 8px; border-radius: 50%; background: rgba(0,0,0,.35); box-shadow: inset 0 1px 0 rgba(255,255,255,.3); }
.leaf svg { width: 30px; height: 30px; position: relative; }
.door:hover .leaf, .door:focus-visible .leaf, .door[aria-pressed="true"] .leaf { transform: rotateY(-62deg); }
.door:focus-visible { outline: none; } .door:focus-visible .frame { outline: 2px solid var(--amber); outline-offset: 3px; }
.door .nm { margin-top: 10px; font-size: 16px; }
.door .nm small { display: block; font: 10.5px var(--mono); color: var(--dim); margin-top: 1px; }
.door[aria-pressed="true"] .nm { color: var(--amber); }
.room { margin-top: 22px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; display: grid; grid-template-columns: 260px 1fr; min-height: 180px; }
.room .about { padding: 20px 22px; border-right: 1px solid var(--line); }
.room .about h4 { margin: 0; font-weight: 300; font-style: italic; font-size: 34px; line-height: 1; letter-spacing: -.02em; }
.room .about p { margin: 10px 0 14px; font-size: 14.5px; color: var(--ink2); }
.room .about a { font: 12px var(--mono); color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--rose); }
.room .about a:hover { color: var(--amber); }
.room ul { list-style: none; margin: 0; padding: 10px 22px; columns: 2; column-gap: 34px; }
.room li { break-inside: avoid; display: grid; grid-template-columns: 1fr auto; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--line); font-size: 15.5px; align-items: baseline; }
.room li small { display: block; font-style: italic; color: var(--mute); font-size: 13px; }
.room li .d { font: 11px var(--mono); color: var(--dim); white-space: nowrap; }
/* life */
.life { display: grid; grid-template-columns: 1fr 1.25fr; gap: 60px; }
.life h3 { margin: 6px 0 12px; font-weight: 300; font-size: 46px; line-height: 1.02; letter-spacing: -.025em; }
.life h3 i { color: var(--rose); }
.life .lede { font-size: 17px; color: var(--ink2); max-width: 30em; margin: 0; }
.mol { display: block; text-decoration: none; margin: 30px 10px 0 4px; background: #f4ece0; color: #2a1a1f; padding: 22px 24px 20px; position: relative; transform: rotate(-1.2deg); box-shadow: 0 2px 0 rgba(0,0,0,.25), 0 30px 50px -30px rgba(0,0,0,.8); transition: transform .3s var(--ease); max-width: 440px; }
.mol:hover { transform: rotate(0deg) translateY(-4px); }
.mol::before { content: ""; position: absolute; width: 90px; height: 22px; background: rgba(201,112,107,.55); top: -10px; left: 30px; transform: rotate(-5deg); }
.mol .k { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .09em; color: #84706a; }
.mol h4 { margin: 8px 0 8px; font-weight: 400; font-size: 30px; line-height: 1.05; letter-spacing: -.02em; }
.mol h4 i { color: #b45b56; }
.mol p { margin: 0; font-size: 15.5px; color: #4e3a3f; font-style: italic; }
.mol .go { margin-top: 14px; display: flex; justify-content: space-between; align-items: baseline; font: 12px var(--mono); color: #84706a; }
.mol .go b { font: italic 400 17px var(--serif); color: #2a1a1f; border-bottom: 1px solid #c9706b; }
.mol .scrib { position: absolute; right: -18px; top: -26px; font: 600 22px/1 var(--hand); color: var(--amber); transform: rotate(6deg); }
.tl { list-style: none; margin: 0; padding: 0; position: relative; }
.tl::before { content: ""; position: absolute; left: 87px; top: 12px; bottom: 12px; width: 0; border-left: 1.5px dashed rgba(201,112,107,.5); }
.tl li { position: relative; }
.tl button { all: unset; box-sizing: border-box; cursor: pointer; display: grid; grid-template-columns: 70px 1fr; gap: 0 36px; width: 100%; padding: 9px 0; }
.tl .y { font: italic 400 20px/1.2 var(--serif); color: var(--mute); text-align: right; transition: color .15s; }
.tl .tx { font-size: 17px; line-height: 1.35; position: relative; transition: color .15s; }
.tl .tx::before { content: ""; position: absolute; left: -24px; top: 7px; width: 10px; height: 10px; border-radius: 50%; background: var(--bg); border: 1.5px solid var(--rose); transition: background .15s, transform .15s; }
.tl button:hover .tx::before, .tl li.open .tx::before { background: var(--rose); transform: scale(1.15); }
.tl button:hover .y, .tl li.open .y { color: var(--amber); }
.tl .ex { grid-column: 2; display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s var(--ease); }
.tl .ex > div { overflow: hidden; font-size: 15px; color: var(--mute); font-style: italic; }
.tl li.open .ex { grid-template-rows: 1fr; }
.tl .ex p { margin: 6px 0 4px; }
.tl li.nowrow .y { color: var(--amber); }
.tl li.nowrow .tx::before { background: var(--amber); border-color: var(--amber); box-shadow: 0 0 0 4px rgba(232,176,74,.18); }
.tl-hint { font: 11.5px var(--mono); color: var(--dim); margin: 10px 0 0 106px; }
/* footer */
footer { margin-top: 30px; border-top: 1px solid var(--line); }
footer .wrap { display: grid; grid-template-columns: 1.2fr 1fr 1.4fr; gap: 40px; padding-top: 26px; padding-bottom: 34px; font-size: 14px; color: var(--ink2); }
footer h5 { margin: 0 0 6px; font: 600 23px var(--hand); color: var(--amber); }
footer a { color: var(--ink); text-decoration-color: var(--rose); text-underline-offset: 3px; }
footer .small { font: 11.5px/1.6 var(--mono); color: var(--mute); }
@media (max-width: 1100px) {
.now { grid-template-columns: repeat(2, 1fr); } .slot { border-bottom: 1px solid var(--line); } .slot:last-child { grid-column: 1 / -1; }
.doors { grid-template-columns: repeat(4, 1fr); }
.pair, .life { grid-template-columns: 1fr; gap: 30px; }
}
@media (max-width: 760px) {
:root { --edge: 26px; } .edge { font-size: 10px; }
.wrap, .bar .in { padding-left: 16px; padding-right: 16px; }
.nav, .upd span { display: none; }
.intro { grid-template-columns: 1fr; gap: 26px; } .intro h1 { font-size: 34px; } .me { justify-self: start; }
.now { grid-template-columns: 1fr; }
.doors { grid-template-columns: repeat(2, 1fr); }
.room { grid-template-columns: 1fr; } .room .about { border-right: 0; border-bottom: 1px solid var(--line); } .room ul { columns: 1; }
.feat h3 { font-size: 32px; } .margin-note { display: none; }
.share { grid-template-columns: 90px 1fr; } .share .when { position: static; }
.tl button { grid-template-columns: 50px 1fr; gap: 0 30px; } .tl::before { left: 64px; } .tl-hint { margin-left: 0; }
footer .wrap { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="mk" id="mk" role="note"><button onclick="document.getElementById('mk').remove()" aria-label="Dismiss note">×</button><b>personal-r2-d · A personal homepage</b>What "come in" opens: a warm "about me, right now" page. A short hello, a "currently" strip fed by Trakt and Hardcover (and a song on loop), one featured essay, the latest three shares, then eight doors into collections by interest, and a gentle life thread. A modern now-page plus a personal index; maggieappleton.com's sorting by type, the gate's plum warmth.</div>
<a class="edge" href="tech-r3-c.html" title="cross over to the work side"><span>← work</span></a>
<div class="page">
<header class="bar">
<div class="in">
<div class="crumb"><a class="back" href="nav-d.html" title="back to the start page">← gate</a><b>Lucas Winther</b><span>/ off the clock</span></div>
<nav class="nav" aria-label="sections"><a href="#now">Now</a><a href="#shares">Shares</a><a href="#interests">Interests</a><a href="#life">Life</a></nav>
<div class="upd"><i></i><span>updated 2 Nov 2026</span></div>
</div>
</header>
<main class="wrap">
<!-- intro -->
<section class="intro">
<div>
<span class="hi">hi, I'm Lucas</span>
<h1>I write software for a living. The rest of the time I'm <em>reading comics</em>, crying at them, and playing <span class="r">the same song</span> forty times in a row.</h1>
<p>This is my corner for the things I love and the things I think about. Something new lands here once or twice a month, whenever it's worth it.</p>
<div class="meta"><span>Denmark</span><span>bsky: stereotypicalcat</span><span>says hi back: lucas@lucaswinther.info</span></div>
</div>
<div class="me">
<span class="tape"></span>
<div class="card">
<svg viewBox="0 0 220 200" aria-label="drawing placeholder: a doodle self-portrait">
<rect width="220" height="200" fill="#efe3d1"/>
<circle cx="170" cy="48" r="20" fill="#e8b04a" opacity=".6"/>
<path d="M60 200 C 64 150, 156 150, 160 200" fill="#c9706b" stroke="#2a1a1f" stroke-width="2.4"/>
<path d="M98 140 v14 h24 v-14" fill="#f4dcc4" stroke="#2a1a1f" stroke-width="2.2"/>
<ellipse cx="110" cy="100" rx="40" ry="46" fill="#f4dcc4" stroke="#2a1a1f" stroke-width="2.4"/>
<path d="M70 92 C 66 50, 150 44, 152 92 C 140 70, 120 64, 104 66 C 92 72, 80 78, 70 92Z" fill="#4a2f2a" stroke="#2a1a1f" stroke-width="2.2"/>
<path d="M62 100 C 58 52, 162 52, 158 100" fill="none" stroke="#2a1a1f" stroke-width="4"/>
<rect x="54" y="92" width="16" height="26" rx="6" fill="#2a1a1f"/><rect x="150" y="92" width="16" height="26" rx="6" fill="#2a1a1f"/>
<circle cx="96" cy="102" r="9" fill="none" stroke="#2a1a1f" stroke-width="2"/><circle cx="124" cy="102" r="9" fill="none" stroke="#2a1a1f" stroke-width="2"/><path d="M105 102 h10" stroke="#2a1a1f" stroke-width="2"/>
<circle cx="97" cy="103" r="2" fill="#2a1a1f"/><circle cx="125" cy="103" r="2" fill="#2a1a1f"/>
<path d="M100 124 q10 8 20 0" fill="none" stroke="#2a1a1f" stroke-width="2.2" stroke-linecap="round"/>
<path d="M28 40 q6 -10 12 0 q6 10 12 0" fill="none" stroke="#c9706b" stroke-width="2" stroke-linecap="round"/>
<path d="M176 140 l6 -14 l3 12 l8 -6" fill="none" stroke="#2a1a1f" stroke-width="1.6" stroke-linecap="round"/>
</svg>
<div class="cap">me, by me (generously)</div>
</div>
</div>
</section>
<!-- currently -->
<section id="now">
<div class="sh"><h2>currently</h2><span class="n">synced from Trakt and Hardcover · 3 h ago</span><span class="r">hover for a note</span></div>
<div class="now">
<div class="slot" tabindex="0">
<div class="lbl">Playing <span>by hand</span></div>
<div class="cov"><div class="art sq" style="background:radial-gradient(circle at 50% 62%,#e8b04a 0 16%,rgba(232,176,74,.25) 30%,transparent 50%),linear-gradient(#3b2638,#1c1320)"></div></div>
<div class="ti ph" title="placeholder">Hades II</div>
<div class="su">Switch 2 · 41 hours in</div>
<div class="note">one more run. always one more run.</div>
</div>
<div class="slot" tabindex="0">
<div class="lbl">Reading <a href="#" title="placeholder link">hardcover ↗</a></div>
<div class="cov"><div class="art book" style="background:radial-gradient(circle at 50% 34%,#f1e6d6 0 12%,transparent 13%),repeating-linear-gradient(0deg,rgba(255,255,255,.06) 0 2px,transparent 2px 8px),linear-gradient(#456273,#20313b)"></div></div>
<div class="ti ph" title="placeholder">Piranesi</div>
<div class="su">Susanna Clarke</div>
<div class="prog"><i style="width:56%"></i></div>
<div class="pm"><span>p. 152 / 272</span><span>56%</span></div>
<div class="note">reading it slowly on purpose</div>
</div>
<div class="slot" tabindex="0">
<div class="lbl">Watching <a href="#" title="placeholder link">trakt ↗</a></div>
<div class="cov"><div class="art book" style="background:linear-gradient(165deg,#88a596 0 42%,#ece4d0 42% 56%,#6c6990 56%)"></div></div>
<div class="ti ph" title="placeholder">Frieren: Beyond Journey's End</div>
<div class="su">S2 · E6 · two days ago</div>
<div class="prog"><i style="width:43%"></i></div>
<div class="pm"><span>6 / 14 eps</span><span>★★★★★</span></div>
<div class="note">no spoilers but ep 5 😭</div>
</div>
<div class="slot" tabindex="0">
<div class="lbl">Listening <span>album</span></div>
<div class="cov"><div class="art sq" style="background:radial-gradient(circle at 50% 58%,#e8b04a 0 22%,transparent 22.5%) top/100% 100% no-repeat,linear-gradient(#c9706b 0 58%,#2a1a1f 58%)"></div></div>
<div class="ti ph" title="placeholder">Bright Future</div>
<div class="su ph" title="placeholder">Adrianne Lenker</div>
<div class="note">best with headphones, on a bike</div>
</div>
<div class="slot" id="looping">
<div class="lbl">Looping <span>song of the moment</span></div>
<div class="loopbox" id="loopbox">
<div class="disc" aria-hidden="true"></div>
<div style="min-width:0">
<div class="eq" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i></div>
<div class="ti ph" title="placeholder: song">Sadness as a Gift</div>
<div class="su ph" title="placeholder: artist">Adrianne Lenker</div>
</div>
</div>
<div class="ctl">
<button class="pp" id="pp" aria-label="Play"><svg viewBox="0 0 16 16" id="ppi"><path d="M4 2 L14 8 L4 14Z" fill="currentColor"/></svg></button>
<div class="seek" id="seek" aria-label="position"><i id="sfill"></i></div>
<span class="tm" id="tm">0:00 / 4:12</span>
</div>
<div class="loopct" id="loopct">played <b id="plays">38</b>× this week · press play, it won't start by itself</div>
</div>
</div>
<div class="now-foot"><span>Trakt and Hardcover data shown as if pulled from their APIs (placeholders)</span><span>the song and game are typed in by me</span></div>
</section>
<!-- featured + shares -->
<section id="shares">
<div class="pair">
<article class="feat">
<div class="sh"><h2>lately I've been thinking</h2></div>
<div class="kick"><span class="t">writing</span><span>essay · 7 min · 19 Oct</span></div>
<h3 class="ph" title="placeholder">What a webcomic taught me about <i>saying goodbye</i></h3>
<p class="stand">I cried so much at a chapter of Now Recharging that I had to put my phone down. This is me trying to work out why death in stories hits me so hard.</p>
<div class="body">
<p>Death has always been something that hits me hard, in stories more than anywhere. I used to think that was a bit embarrassing. Now I think stories are the one place where you get to rehearse a goodbye gently, with a page you can close and come back to.</p>
<div class="more" id="fmore"><div>
<p>The chapter doesn't do anything dramatic. Two characters sit on a roof. One of them knows. The other one figures it out a panel too late, like you do. That's it, and it wrecked me.</p>
<p>I think the reason is scale. The news gives you thousands of people at once, and my brain files it under weather. A story gives you one person, for long enough to know how they take their coffee. Then it asks you to let them go.</p>
<p>So I've stopped apologising for crying at comics. If fiction is where I practise caring, the practice counts. 🌧️</p>
</div></div>
</div>
<button class="rd" data-more="fmore">read the whole thing <span class="arrow">→</span></button>
<div class="meta"><span>also in: comics, life</span><span>2 older essays</span></div>
<div class="margin-note">this one<br>was hard to write</div>
</article>
<div>
<div class="sh"><h2>latest shares</h2><span class="r"><a href="#interests">all 21, by interest ↓</a></span></div>
<div class="shares">
<a class="share" href="#">
<div class="thumb">
<svg viewBox="0 0 124 100"><rect x="10" y="4" width="100" height="92" fill="#f4ece0" transform="rotate(-3 60 50)"/><g transform="rotate(-3 60 50)"><path d="M60 26 c-2 -8 2 -12 8 -12" stroke="#2a1a1f" stroke-width="2" fill="none"/><path d="M60 30 C 38 24, 20 38, 22 60 C 24 82, 46 90, 60 86 C 74 90, 98 82, 98 60 C 100 38, 82 24, 60 30Z" fill="#e8b04a" stroke="#2a1a1f" stroke-width="2"/><path d="M40 50 l9 -7 l5 9z M66 52 l5 -9 l9 7z" fill="#2a1a1f"/><path d="M38 64 q22 18 44 0 l-6 1 l-4 5 l-5 -4 l-5 5 l-5 -5 l-5 4 l-4 -5z" fill="#2a1a1f"/></g><rect x="40" y="0" width="40" height="11" fill="rgba(232,176,74,.7)" transform="rotate(-6 60 6)"/></svg>
</div>
<div><div class="kick"><span class="t">made by me</span><span>drawing</span></div><h4>The pumpkin 🎃</h4><p>Carved my first pumpkin in years, then drew it. The drawing is better than the pumpkin.</p></div>
<span class="when">2 Nov</span>
</a>
<a class="share" href="#">
<div class="thumb">
<svg viewBox="0 0 124 100"><rect x="2" y="6" width="120" height="88" fill="#fbf6ee"/><rect x="7" y="11" width="66" height="40" fill="#f3c9a0" stroke="#2a1a1f" stroke-width="1.6"/><circle cx="52" cy="28" r="7" fill="#e8b04a"/><path d="M7 51 V38 h10 v-6 h8 v19z M50 51 v-10 h12 v-4 h11 v14z" fill="#2a1a1f"/><circle cx="32" cy="38" r="3" fill="#2a1a1f"/><circle cx="40" cy="39" r="2.6" fill="#2a1a1f"/><rect x="77" y="11" width="40" height="40" fill="#fffaf3" stroke="#2a1a1f" stroke-width="1.6"/><path d="M82 31 Q97 18 112 31 Q97 42 82 31Z" fill="none" stroke="#2a1a1f" stroke-width="1.5"/><circle cx="97" cy="30" r="5" fill="#2a1a1f"/><path d="M104 38 q2 5 0 8 q-2 -3 0 -8z" fill="#c9706b"/><rect x="7" y="55" width="110" height="34" fill="#f4e6d2" stroke="#2a1a1f" stroke-width="1.6"/><path d="M44 72 h36 M44 77 h36 M47 77 v8 M77 77 v8" stroke="#2a1a1f" stroke-width="1.6"/><path d="M60 70 q4 0 6 3 q-1 6 1 10 l-3 1 q-2 -4 -2 -9z" fill="#c9706b"/></svg>
</div>
<div><div class="kick"><span class="t">comics</span><span>a few pages</span></div><h4>Now Recharging, chapter <span class="ph" title="placeholder">12</span></h4><p>“i cried so much in this chapter – death has always been something that hits me emotionally hard”</p></div>
<span class="when">14 Oct</span>
</a>
<a class="share" href="#">
<div class="thumb">
<svg viewBox="0 0 124 100"><rect x="2" y="8" width="120" height="84" rx="3" fill="#1f2a3d"/><circle cx="34" cy="38" r="14" fill="#e8b04a"/><circle cx="92" cy="30" r="9" fill="#cfd6e6"/><circle cx="96" cy="27" r="8" fill="#1f2a3d"/><path d="M2 70 Q32 54 62 68 T122 64 V92 H2Z" fill="#2c3d55"/><path d="M2 80 Q40 70 70 80 T122 78 V92 H2Z" fill="#14202f"/><path d="M58 70 l6 -12 l6 12z" fill="#14202f"/><rect x="6" y="12" width="48" height="11" rx="2" fill="#c9706b"/><text x="30" y="20.5" text-anchor="middle" font-family="Geist Mono, monospace" font-size="6.5" fill="#2a1a1f">BACKED 2020</text></svg>
</div>
<div><div class="kick"><span class="t">games</span><span>kickstarter</span></div><h4 class="ph" title="placeholder">Sea of Stars, five years after I backed it</h4><p>Pledged in 2020, forgot, and finally started it. Turns out past me had good taste.</p></div>
<span class="when">20 Oct</span>
</a>
</div>
</div>
</div>
</section>
<!-- doors -->
<section id="interests">
<div class="sh"><h2>wander by interest</h2><span class="n" id="doorsn"></span><span class="r">hover a door to peek in, click to keep it open</span></div>
<div class="doors" id="doors"></div>
<div class="room" id="room"></div>
</section>
<!-- life -->
<section id="life">
<div class="life">
<div>
<div class="sh"><h2>life, so far</h2></div>
<h3>A short life story, <i>told gently</i></h3>
<p class="lede">Not a CV. Just the bits that made me who I am, the way I'd tell them to a friend over a long dinner. Click a year if you want the longer version.</p>
<a class="mol" href="#">
<span class="scrib">took me a year</span>
<div class="k">essay · 12 min · the big one</div>
<h4 class="ph" title="placeholder">What I think the point of it all <i>might be</i></h4>
<p>Mostly: be kind to the few people near you, make small things, and like what you like out loud. The rest I'm still working out, and I've made peace with that.</p>
<div class="go"><span>written slowly, spring 2026</span><b>read it, slowly →</b></div>
</a>
</div>
<div>
<ol class="tl" id="tl">
<li><button><span class="y ph" title="placeholder">1998</span><span class="tx">Born in Denmark. Apparently I didn't sleep through a night for a year.</span><span class="ex"><div><p>My parents say I was a curious baby. I think they mean loud.</p></div></span></button></li>
<li><button><span class="y ph" title="placeholder">2006</span><span class="tx">Anders And &amp; Co. every Wednesday. The start of a lifelong comics habit.</span><span class="ex"><div><p>I read them until the spines fell off. Some of them are still in a box at my parents'.</p></div></span></button></li>
<li><button><span class="y ph" title="placeholder">2012</span><span class="tx">A second-hand guitar and three chords for a whole year.</span><span class="ex"><div><p>Still mostly three chords, to be honest. Just better ones.</p></div></span></button></li>
<li><button><span class="y">2016</span><span class="tx">Made a VR game for my high-school exam, and found out I love building things people can step into.</span><span class="ex"><div><p>It was called Censor Simulator. It was janky. Watching my classmates put on the headset and laugh is still one of my favourite memories.</p></div></span></button></li>
<li><button><span class="y">2019</span><span class="tx">Started computer science at Aarhus University.</span><span class="ex"><div><p>Moved out, learned to cook three dishes, and met most of the people I'd call my close friends today.</p></div></span></button></li>
<li><button><span class="y ph" title="placeholder">2022</span><span class="tx">Started a small band with friends. We're not good. It's the best night of the week.</span><span class="ex"><div><p>We film our gigs on a phone from the third row. On purpose.</p></div></span></button></li>
<li><button><span class="y ph" title="placeholder">2024</span><span class="tx ph" title="placeholder">A year worth a line here, in your own words.</span><span class="ex"><div><p class="ph" title="placeholder">A few sentences on what that year meant. Placeholder: written by Lucas, not guessed.</p></div></span></button></li>
<li><button><span class="y">2025</span><span class="tx">Started at Aarhus University's IT research team. Grown-up job, same curiosity.</span><span class="ex"><div><p>The work side of this site has the details. This side is for everything else.</p></div></span></button></li>
<li class="nowrow"><button><span class="y">now</span><span class="tx">Comics, a song on loop, a pumpkin, and this little corner of the internet.</span><span class="ex"><div><p>Thanks for reading this far. Say hi on Bluesky if you like.</p></div></span></button></li>
</ol>
<div class="tl-hint">click a year for a little more</div>
</div>
</div>
</section>
</main>
<footer>
<div class="wrap">
<div><h5>elsewhere</h5><a href="https://bsky.app/profile/stereotypicalcat.bsky.social">Bluesky</a> · <a href="#" class="ph" title="placeholder link">Trakt</a> · <a href="#" class="ph" title="placeholder link">Hardcover</a><br><a href="mailto:lucas@lucaswinther.info">lucas@lucaswinther.info</a><br><a href="tech-r3-c.html">the work side →</a> · <a href="nav-d.html">← the gate</a></div>
<div><h5>about this page</h5>A "now" page that's always current, plus doors to everything older. Shares are filed by interest the moment they're posted, so nothing scrolls away.</div>
<div class="small">Placeholders (dotted underline): game, album, song, book and show data (as if from Trakt/Hardcover), essay titles, Sea of Stars, most life years and events, door contents, all drawings and cover art. Real: Now Recharging, Junkwraith, Cupid 13 and the Bluesky quotes, the villainess trope, the pumpkin, Censor Simulator (2016), Aarhus University (2019, 2025).</div>
</div>
</footer>
</div>
<script>
// ---------- read more ----------
document.querySelectorAll('.rd[data-more]').forEach(function (b) {
var html = b.innerHTML;
b.addEventListener('click', function () {
var open = document.getElementById(b.dataset.more).classList.toggle('open');
b.innerHTML = open ? 'fold it back <span class="arrow">↑</span>' : html;
});
});
// ---------- timeline ----------
document.querySelectorAll('#tl li').forEach(function (li) {
li.querySelector('button').addEventListener('click', function () { li.classList.toggle('open'); });
});
// ---------- looping player (mock) ----------
(function () {
var L = 252, pos = 0, on = false, t = null, plays = 38;
var box = document.getElementById('loopbox'), pp = document.getElementById('pp'), ppi = document.getElementById('ppi');
var fill = document.getElementById('sfill'), tm = document.getElementById('tm'), seek = document.getElementById('seek'), pl = document.getElementById('plays');
var fmt = function (s) { return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); };
function ui() { fill.style.width = (pos / L * 100) + '%'; tm.textContent = fmt(pos) + ' / ' + fmt(L); pl.textContent = plays; }
function set(v) {
on = v; clearInterval(t); box.classList.toggle('on', on);
pp.setAttribute('aria-label', on ? 'Pause' : 'Play');
ppi.innerHTML = on ? '<rect x="3" y="2" width="3.5" height="12" fill="currentColor"/><rect x="9.5" y="2" width="3.5" height="12" fill="currentColor"/>' : '<path d="M4 2 L14 8 L4 14Z" fill="currentColor"/>';
if (on) t = setInterval(function () { pos++; if (pos >= L) { pos = 0; plays++; } ui(); }, 1000);
ui();
}
pp.addEventListener('click', function () { set(!on); });
seek.addEventListener('click', function (e) { var r = seek.getBoundingClientRect(); pos = Math.floor((e.clientX - r.left) / r.width * L); ui(); });
ui();
})();
// ---------- doors by interest ----------
(function () {
var ICON = {
comics: '<path d="M3 3h24v24H3z M3 15h14 M17 3v24" />',
games: '<rect x="2" y="9" width="26" height="13" rx="6.5"/><path d="M9 12.5v6M6 15.5h6"/><circle cx="20" cy="14" r="1"/><circle cx="23" cy="17" r="1"/>',
music: '<circle cx="15" cy="15" r="12"/><circle cx="15" cy="15" r="3"/>',
film: '<rect x="3" y="7" width="24" height="17"/><path d="M3 12h24M9 7v5M15 7v5M21 7v5"/>',
books: '<path d="M3 6c4-2 8-2 12 2 4-4 8-4 12-2v18c-4-2-8-2-12 2-4-4-8-4-12-2z M15 8v18"/>',
made: '<path d="M20 4l6 6-15 15H5v-6z M17 7l6 6"/>',
writing: '<path d="M4 7h22M4 12h22M4 17h16M4 22h10"/>',
life: '<path d="M15 26S4 19.5 4 11a5.5 5.5 0 0 1 11-2 5.5 5.5 0 0 1 11 2c0 8.5-11 15-11 15z"/>'
};
var D = [
{ k: 'comics', n: 'Comics', c: '#c9706b', about: 'Webcomics, manga one-shots and the odd trope I can\'t quit. Usually a few pages and a line about what got me.', items: [
['Now Recharging, chapter 12', 'i cried so much in this chapter', '14 Oct'], ['Reborn as the villainess (again)', 'everyone around her is possessive and I love it', '28 Oct'],
['Cupid 13', 'a MangaPlus one-shot about a forsaken sniper who regains faith', 'Mar'], ['Junkwraith', 'a coming-of-age story with a unique world', 'Jan'], ['Three panels I keep thinking about', 'a small collection', 'Dec 25', 1]] },
{ k: 'games', n: 'Games', c: '#8b6aa0', about: 'Games I love and why, plus Kickstarters I backed and actually played.', items: [
['Sea of Stars, five years after I backed it', 'past me had good taste', '20 Oct', 1], ['Hades II', 'one more run', 'Sep', 1], ['Outer Wilds, at last', 'no spoilers, just go', 'Jun', 1], ['Balatro ate my holidays', 'a poker game, somehow', 'Jan', 1]] },
{ k: 'music', n: 'Music', c: '#e8b04a', about: 'Songs I want to share right now, and our band\'s handcam recordings, one topic among many.', items: [
['Sadness as a Gift, on loop', 'cold bike rides in October', 'Oct', 1], ['Our band through a rehearsal door', 'handcam, two songs', 'Apr', 1], ['Nakamarra', 'on repeat all January', 'Jan', 1], ['Are You Looking Up', 'windows down', 'Jul', 1]] },
{ k: 'film', n: 'Film & TV', c: '#7f9a8c', about: 'What I\'m watching, pulled from Trakt, plus a few longer thoughts when something stays with me.', items: [
['Perfect Days made me tidy my flat', 'a slow film about small routines', 'Jul', 1], ['Frieren, all of it, again', 'the best show about time passing', 'Feb', 1], ['My Trakt top 10', 'pulled in, updates itself', 'live', 1]] },
{ k: 'books', n: 'Books', c: '#5a7a8c', about: 'Reading from Hardcover, and the occasional note on a book that rearranged something.', items: [
['Piranesi, read slowly', 'a house with endless halls', 'now', 1], ['Tomorrow, and Tomorrow, and Tomorrow', 'a novel about making games with friends', 'Aug', 1]] },
{ k: 'made', n: 'Made by me', c: '#d99a6c', about: 'My own small drawings, and art I commissioned from people far better at it.', items: [
['The pumpkin', 'carved it, then drew it', '2 Nov'], ['Sketchbook: ferry seats', 'twelve drawings of people asleep', 'Jul', 1], ['The band, drawn as cats', 'a commission I look at daily', 'Mar', 1]] },
{ k: 'writing', n: 'Writing', c: '#b8a592', about: 'Short essays on things I care about. Occasional, never rushed.', items: [
['What a webcomic taught me about saying goodbye', '7 min', '19 Oct', 1], ['Liking things without irony', '5 min', 'Aug', 1], ['Why this page isn\'t a feed', '3 min', 'Dec 25', 1]] },
{ k: 'life', n: 'Life', c: '#a85d63', about: 'The longer, quieter pieces: my life so far, and what I think it\'s all for.', items: [
['What I think the point of it all might be', '12 min · the big one', 'spring', 1], ['A short life story', 'the timeline, below', 'always', 1], ['My first winter swim (never again)', 'a dare, a fjord, a scream', 'Feb', 1]] }
];
var doors = document.getElementById('doors'), room = document.getElementById('room'), pinned = 'comics';
var total = D.reduce(function (s, d) { return s + d.items.length; }, 0);
document.getElementById('doorsn').textContent = '8 interests · ' + total + ' things so far';
D.forEach(function (d) {
var b = document.createElement('button');
b.className = 'door'; b.dataset.k = d.k; b.setAttribute('aria-pressed', d.k === pinned);
b.innerHTML = '<div class="frame"><div class="inside"><span class="cnt">' + d.items.length + '</span><span class="lt">latest:<br>' + d.items[0][2] + '</span></div>' +
'<div class="leaf" style="background:linear-gradient(160deg,' + d.c + ',color-mix(in srgb,' + d.c + ' 70%,#2a1a1f))"><svg viewBox="0 0 30 30" fill="none" stroke="#2a1a1f" stroke-width="1.6" stroke-linejoin="round">' + ICON[d.k] + '</svg><span class="knob"></span></div></div>' +
'<div class="nm">' + d.n + '<small>' + d.items.length + ' things</small></div>';
b.addEventListener('mouseenter', function () { show(d.k); });
b.addEventListener('focus', function () { show(d.k); });
b.addEventListener('mouseleave', function () { show(pinned); });
b.addEventListener('click', function () { pinned = d.k; doors.querySelectorAll('.door').forEach(function (x) { x.setAttribute('aria-pressed', x.dataset.k === pinned); }); show(pinned); });
doors.appendChild(b);
});
function show(k) {
var d = D.filter(function (x) { return x.k === k; })[0];
room.innerHTML = '<div class="about"><h4 style="color:' + d.c + '">' + d.n + '</h4><p>' + d.about + '</p><a href="#">open the whole ' + d.n.toLowerCase() + ' shelf →</a></div>' +
'<ul>' + d.items.map(function (i) { return '<li><span><span' + (i[3] ? ' class="ph" title="placeholder"' : '') + '>' + i[0] + '</span><small>' + i[1] + '</small></span><span class="d">' + i[2] + '</span></li>'; }).join('') + '</ul>';
}
show(pinned);
})();
</script>
</body>
</html>