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>
762 lines
66 KiB
HTML
762 lines
66 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Off the clock · Nº 04 · Autumn 2026 · Lucas Winther</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 {
|
||
--paper: #f1e6d6; --paper2: #e9dcc7; --card: #f7efe3; --ink: #2a1a1f; --ink2: #4e3a3f; --mute: #84706a; --dim: #ab9a8f;
|
||
--line: rgba(42,26,31,.16); --line2: rgba(42,26,31,.32);
|
||
--amber: #e8b04a; --rose: #c9706b; --plum: #2a1a1f; --plum2: #3a252b; --cream: #f1e6d6;
|
||
--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: 76px; }
|
||
html, body { margin: 0; }
|
||
body { background: var(--paper); color: var(--ink); font-family: var(--serif); font-size: 16px; line-height: 1.55; font-optical-sizing: auto; -webkit-font-smoothing: antialiased; }
|
||
body::before { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: .5; mix-blend-mode: multiply;
|
||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .55 0 0 0 0 .42 0 0 0 0 .36 0 0 0 .22 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"); }
|
||
a { color: inherit; }
|
||
button { font: inherit; color: inherit; }
|
||
::selection { background: var(--amber); color: var(--ink); }
|
||
:focus-visible { outline: 2px solid var(--rose); outline-offset: 2px; }
|
||
.ph { text-decoration: underline dotted rgba(42,26,31,.38); text-underline-offset: 3px; text-decoration-thickness: 1px; cursor: help; }
|
||
.mono { font-family: var(--mono); }
|
||
.hand { font-family: var(--hand); }
|
||
|
||
/* mockup note */
|
||
.mk { position: fixed; bottom: 14px; right: 14px; z-index: 80; width: 310px; background: #fffaf2; color: #2a1a1f; font: 12px/1.45 var(--mono); padding: 10px 28px 10px 12px; border-radius: 8px; box-shadow: 0 6px 24px rgba(42,26,31,.18); border: 1px solid var(--line); }
|
||
.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; }
|
||
|
||
/* work edge, mirrors tech-r3-c's right-side "off the clock" */
|
||
.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; transform: none; 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: 1260px; margin: 0 auto; padding: 0 40px; }
|
||
|
||
/* top bar */
|
||
.bar { position: sticky; top: 0; z-index: 50; background: rgba(241,230,214,.88); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
|
||
.bar .in { max-width: 1260px; 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(--ink); }
|
||
.crumb b { font-weight: 600; 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(42,26,31,.06); }
|
||
.fill { margin-left: auto; display: flex; align-items: center; gap: 10px; font: 12px var(--mono); color: var(--mute); }
|
||
.fill .dots { display: flex; gap: 3px; }
|
||
.fill .dots i { width: 8px; height: 11px; border-radius: 1.5px; border: 1px solid var(--ink2); }
|
||
.fill .dots i.on { background: var(--ink); }
|
||
|
||
/* masthead */
|
||
.mast { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 30px; padding: 30px 0 14px; border-bottom: 2px solid var(--ink); position: relative; }
|
||
.mast h1 { margin: 0; font-weight: 300; font-style: italic; font-size: 92px; line-height: .9; letter-spacing: -.035em; font-variation-settings: "opsz" 144; }
|
||
.mast h1 em { font-style: normal; font-weight: 600; color: var(--rose); }
|
||
.mast .sub { font: 12px var(--mono); color: var(--mute); margin-top: 12px; letter-spacing: .02em; }
|
||
.issue-no { text-align: right; display: grid; grid-template-columns: auto auto; align-items: end; gap: 0 16px; }
|
||
.issue-no .n { font-weight: 600; font-size: 84px; line-height: .8; letter-spacing: -.05em; font-variation-settings: "opsz" 144; grid-row: span 3; }
|
||
.issue-no .n small { font-size: 26px; font-weight: 400; vertical-align: top; letter-spacing: 0; margin-right: 2px; }
|
||
.issue-no .s { font-style: italic; font-size: 22px; line-height: 1.1; text-align: left; }
|
||
.issue-no .d { font: 11.5px var(--mono); color: var(--mute); text-align: left; }
|
||
.scribble { position: absolute; right: 290px; top: 34px; font-family: var(--hand); font-size: 22px; color: var(--rose); transform: rotate(-4deg); line-height: 1; }
|
||
.scribble svg { display: block; margin: 2px 0 0 60px; }
|
||
.coverline { display: flex; justify-content: space-between; gap: 30px; align-items: baseline; padding: 10px 0; border-bottom: 1px solid var(--line2); font-size: 18px; font-style: italic; color: var(--ink2); }
|
||
.coverline .r { font: 11.5px var(--mono); font-style: normal; color: var(--mute); white-space: nowrap; }
|
||
|
||
/* issue grid */
|
||
.issue { display: grid; grid-template-columns: repeat(12, 1fr); gap: 0 30px; }
|
||
.pg { position: relative; padding: 24px 0 26px; border-bottom: 1px solid var(--line2); min-width: 0; }
|
||
.pgno { position: absolute; top: 24px; right: 0; font: italic 400 14px var(--serif); color: var(--mute); }
|
||
.kick { font: 11px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute); display: flex; gap: 10px; align-items: center; }
|
||
.kick .t { color: var(--rose); }
|
||
.kick .new { background: var(--amber); color: var(--ink); border-radius: 3px; padding: 0 5px; letter-spacing: .04em; }
|
||
.pg h2 { font-weight: 500; font-size: 30px; line-height: 1.05; letter-spacing: -.02em; margin: 8px 0 10px; font-variation-settings: "opsz" 72; }
|
||
.pg h2 i { font-weight: 300; }
|
||
.pg p { margin: 0 0 10px; }
|
||
.vr { border-left: 1px solid var(--line2); padding-left: 30px; margin-left: -1px; }
|
||
.s3 { grid-column: span 3; } .s4 { grid-column: span 4; } .s5 { grid-column: span 5; } .s6 { grid-column: span 6; } .s7 { grid-column: span 7; } .s12 { grid-column: 1 / -1; }
|
||
|
||
/* contents */
|
||
.toc ol { list-style: none; margin: 12px 0 0; padding: 0; counter-reset: none; }
|
||
.toc li a { display: grid; grid-template-columns: 30px 1fr; gap: 0 6px; padding: 7px 0; border-top: 1px solid var(--line); text-decoration: none; transition: background .15s, padding .15s; }
|
||
.toc li:last-child a { border-bottom: 1px solid var(--line); }
|
||
.toc li a:hover { background: rgba(232,176,74,.16); padding-left: 6px; }
|
||
.toc .p { font: italic 500 17px/1.2 var(--serif); color: var(--rose); }
|
||
.toc .tt { font-size: 15px; line-height: 1.25; }
|
||
.toc .m { grid-column: 2; font: 10.5px var(--mono); color: var(--mute); letter-spacing: .03em; margin-top: 2px; }
|
||
.toc .m b { font-weight: 500; color: var(--ink); background: var(--amber); padding: 0 4px; border-radius: 2px; }
|
||
.toc li.empty a { color: var(--dim); cursor: default; }
|
||
.toc li.empty a:hover { background: none; padding-left: 0; }
|
||
.toc li.empty .p { color: var(--dim); }
|
||
.letter { margin-top: 18px; font-size: 14.5px; font-style: italic; color: var(--ink2); line-height: 1.5; }
|
||
.letter .sig { font: 600 24px var(--hand); font-style: normal; color: var(--ink); display: block; margin-top: 2px; transform: rotate(-2deg); }
|
||
|
||
/* comic spread */
|
||
.comic-wrap { display: grid; grid-template-columns: 1fr; gap: 14px; }
|
||
.quote { font: italic 300 25px/1.22 var(--serif); letter-spacing: -.01em; margin: 0; color: var(--ink); }
|
||
.quote::before { content: "“"; color: var(--rose); font-weight: 600; margin-right: 2px; }
|
||
.quote::after { content: "”"; color: var(--rose); font-weight: 600; }
|
||
.quote-src { font: 11px var(--mono); color: var(--mute); margin-top: 4px; }
|
||
.comicpage { background: #fbf6ee; padding: 10px; border: 1px solid var(--line); box-shadow: 0 1px 0 rgba(42,26,31,.08), 0 14px 30px -18px rgba(42,26,31,.35); display: grid; gap: 8px; grid-template-columns: 1.15fr 1fr 1fr; grid-template-rows: 150px 118px; grid-template-areas: "a a b" "c d d"; position: relative; transition: box-shadow .25s; }
|
||
.panel { all: unset; box-sizing: border-box; position: relative; border: 2px solid var(--ink); background: #fffaf3; overflow: hidden; cursor: zoom-in; transition: transform .25s var(--ease), opacity .25s, filter .25s; }
|
||
.panel svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
|
||
.panel:hover { transform: translateY(-2px); }
|
||
.panel:focus-visible { outline: 3px solid var(--rose); outline-offset: 2px; }
|
||
.panel.a { grid-area: a; } .panel.b { grid-area: b; } .panel.c { grid-area: c; } .panel.d { grid-area: d; }
|
||
.comicpage.zoom .panel:not(.on) { opacity: .28; filter: grayscale(.6); }
|
||
.comicpage.zoom .panel.on { cursor: zoom-out; transform: scale(1.08); z-index: 2; box-shadow: 0 18px 36px -12px rgba(42,26,31,.55); }
|
||
.panel-cap { min-height: 46px; font-size: 14.5px; color: var(--ink2); display: flex; gap: 12px; align-items: flex-start; }
|
||
.panel-cap .hn { font: 600 22px/1 var(--hand); color: var(--rose); flex: none; transform: rotate(-3deg); margin-top: 2px; }
|
||
.comic-meta { display: flex; justify-content: space-between; gap: 16px; font: 11.5px var(--mono); color: var(--mute); flex-wrap: wrap; }
|
||
.ext { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--rose); }
|
||
.ext:hover { color: var(--rose); }
|
||
|
||
/* currently sidebar */
|
||
.cur { background: var(--plum); color: var(--cream); border-radius: 4px; padding: 18px 18px 14px; position: relative; overflow: hidden; margin-top: 22px; }
|
||
.cur::before { content: ""; position: absolute; inset: 0; opacity: .16; pointer-events: none; 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>"); }
|
||
.cur > * { position: relative; }
|
||
.cur h3 { margin: 0; font: 600 26px/1 var(--hand); color: var(--amber); transform: rotate(-2deg); transform-origin: left; }
|
||
.cur .synced { font: 10.5px var(--mono); color: #b8a592; margin: 4px 0 6px; }
|
||
.cur-item { padding: 11px 0; border-top: 1px solid rgba(241,230,214,.14); display: grid; grid-template-columns: 38px 1fr; gap: 0 12px; }
|
||
.cur-item .art { width: 38px; height: 54px; border-radius: 2px; box-shadow: 0 2px 6px rgba(0,0,0,.35); }
|
||
.cur-item .lbl { font: 10.5px var(--mono); color: #b8a592; text-transform: uppercase; letter-spacing: .08em; display: flex; justify-content: space-between; }
|
||
.cur-item .lbl a { color: #b8a592; text-decoration: none; text-transform: none; letter-spacing: 0; }
|
||
.cur-item .lbl a:hover { color: var(--amber); }
|
||
.cur-item .ti { font-size: 15.5px; line-height: 1.2; margin-top: 2px; }
|
||
.cur-item .su { font-size: 13px; color: #d9c8b3; font-style: italic; }
|
||
.prog { height: 3px; background: rgba(241,230,214,.16); border-radius: 2px; margin-top: 6px; overflow: hidden; }
|
||
.prog i { display: block; height: 100%; background: var(--amber); }
|
||
.rated { list-style: none; margin: 4px 0 0; padding: 0; font-size: 13.5px; }
|
||
.rated li { display: flex; justify-content: space-between; gap: 8px; padding: 3px 0; color: #e8dccb; }
|
||
.rated .st { color: var(--amber); font-size: 11px; letter-spacing: 1px; white-space: nowrap; }
|
||
.cur .out { display: flex; gap: 6px; margin-top: 10px; }
|
||
.cur .out a { font: 11px var(--mono); color: var(--cream); text-decoration: none; border: 1px solid rgba(241,230,214,.25); border-radius: 5px; padding: 2px 8px; transition: border-color .15s, background .15s; }
|
||
.cur .out a:hover { border-color: var(--amber); background: rgba(232,176,74,.12); }
|
||
|
||
/* song of the season */
|
||
.song { display: grid; grid-template-columns: 200px 1fr; gap: 0 22px; }
|
||
.sleeve { width: 168px; height: 168px; position: relative; box-shadow: 0 14px 28px -14px rgba(42,26,31,.55); }
|
||
.sleeve svg { width: 100%; height: 100%; display: block; }
|
||
.vinyl { position: absolute; top: 8px; left: 12px; width: 152px; height: 152px; border-radius: 50%; background: radial-gradient(circle, var(--amber) 0 13%, #1b1013 13.5% 15%, #2a1a1f 15.5% 100%); z-index: -1; transition: left .3s var(--ease); box-shadow: inset 0 0 0 1px #000; }
|
||
.vinyl::after { content: ""; position: absolute; inset: 10px; border-radius: 50%; background: repeating-radial-gradient(circle, transparent 0 3px, rgba(255,255,255,.05) 3px 4px); }
|
||
.song.playing .vinyl, .sleeve-box:hover .vinyl { left: 40px; }
|
||
.sleeve-box { position: relative; z-index: 0; width: 168px; }
|
||
.song .title { font-weight: 500; font-size: 28px; line-height: 1.05; letter-spacing: -.02em; margin: 8px 0 0; }
|
||
.song .artist { font-style: italic; color: var(--ink2); font-size: 17px; }
|
||
.song .why { font-size: 15px; margin: 10px 0 0; color: var(--ink2); }
|
||
.deck { grid-column: 1 / -1; margin-top: 18px; display: grid; grid-template-columns: auto 1fr auto auto; gap: 14px; align-items: center; }
|
||
.pp { width: 46px; height: 46px; border-radius: 50%; border: 0; background: var(--ink); color: var(--cream); cursor: pointer; display: grid; place-items: center; transition: background .15s, transform .15s; }
|
||
.pp:hover { background: var(--rose); transform: scale(1.05); }
|
||
.pp svg { width: 16px; height: 16px; }
|
||
.bar2 { position: relative; height: 22px; cursor: pointer; }
|
||
.bar2::before { content: ""; position: absolute; left: 0; right: 0; top: 10px; height: 2px; background: var(--line2); border-radius: 2px; }
|
||
.bar2 i { position: absolute; left: 0; top: 10px; height: 2px; background: var(--rose); width: 0; border-radius: 2px; }
|
||
.bar2 b { position: absolute; top: 6px; width: 10px; height: 10px; margin-left: -5px; border-radius: 50%; background: var(--rose); left: 0; transform: scale(0); transition: transform .15s; }
|
||
.bar2:hover b, .song.playing .bar2 b { transform: scale(1); }
|
||
.time { font: 12px var(--mono); color: var(--mute); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
||
.loop { font: 11px var(--mono); border: 1px solid var(--line2); background: none; border-radius: 99px; padding: 3px 9px; cursor: pointer; color: var(--mute); transition: all .15s; }
|
||
.loop[aria-pressed="true"] { background: var(--amber); border-color: var(--amber); color: var(--ink); }
|
||
.deck-note { grid-column: 1 / -1; font: 11px var(--mono); color: var(--mute); margin-top: -4px; }
|
||
.bside { grid-column: 1 / -1; margin-top: 16px; border-top: 1px solid var(--line); }
|
||
.bside .h { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .08em; color: var(--mute); padding: 8px 0 2px; }
|
||
.bside button { all: unset; box-sizing: border-box; cursor: pointer; display: grid; grid-template-columns: 22px 1fr auto; gap: 8px; width: 100%; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 14.5px; align-items: baseline; transition: color .15s; }
|
||
.bside button:hover { color: var(--rose); }
|
||
.bside button .k { font: 11px var(--mono); color: var(--dim); }
|
||
.bside button .d { font: 11px var(--mono); color: var(--mute); }
|
||
.bside button[aria-current="true"] { color: var(--rose); }
|
||
.bside button[aria-current="true"] .k { color: var(--rose); }
|
||
|
||
/* game */
|
||
.shot { height: 150px; border-radius: 3px; overflow: hidden; position: relative; margin: 4px 0 12px; box-shadow: 0 12px 24px -16px rgba(42,26,31,.6); }
|
||
.shot svg { width: 100%; height: 100%; display: block; transition: transform .35s var(--ease); }
|
||
.shot:hover svg { transform: scale(1.03); }
|
||
.shot .tag { position: absolute; left: 8px; bottom: 8px; font: 10px var(--mono); color: var(--cream); background: rgba(42,26,31,.7); padding: 2px 6px; border-radius: 3px; }
|
||
.facts { display: flex; flex-wrap: wrap; gap: 4px 14px; font: 11.5px var(--mono); color: var(--mute); margin: 2px 0 10px; }
|
||
.facts b { color: var(--ink); font-weight: 500; }
|
||
.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; font: 12px var(--mono); color: var(--rose); cursor: pointer; border-bottom: 1px dotted var(--rose); }
|
||
.rd:hover { color: var(--ink); border-color: var(--ink); }
|
||
|
||
/* drawing */
|
||
.sheet { background: #fffaf2; padding: 14px 14px 8px; margin: 14px 6px 0; transform: rotate(-2.2deg); box-shadow: 0 2px 0 rgba(42,26,31,.06), 0 16px 26px -18px rgba(42,26,31,.6); position: relative; transition: transform .3s var(--ease); }
|
||
.sheet:hover { transform: rotate(-.4deg) translateY(-3px); }
|
||
.sheet::before, .sheet::after { content: ""; position: absolute; width: 70px; height: 20px; background: rgba(232,176,74,.55); top: -9px; }
|
||
.sheet::before { left: 18px; transform: rotate(-6deg); }
|
||
.sheet::after { right: 18px; transform: rotate(5deg); }
|
||
.sheet svg { width: 100%; display: block; }
|
||
.sheet .cap { font: 600 22px/1.1 var(--hand); text-align: center; margin: 4px 0 2px; }
|
||
.drawn-note { font-size: 14px; color: var(--ink2); margin-top: 16px; }
|
||
|
||
/* essay */
|
||
.essay .stand { font-size: 19px; line-height: 1.4; font-style: italic; color: var(--ink2); margin: 0 0 14px; }
|
||
.cols { columns: 2; column-gap: 30px; column-rule: 1px solid var(--line); font-size: 15.5px; }
|
||
.cols p { margin: 0 0 10px; }
|
||
.cols > p:first-child::first-letter { float: left; font: 600 58px/.82 var(--serif); margin: 6px 8px 0 0; color: var(--rose); }
|
||
.essay .foot { display: flex; justify-content: space-between; font: 11.5px var(--mono); color: var(--mute); margin-top: 8px; }
|
||
|
||
/* trope */
|
||
.bingo { display: grid; grid-template-columns: repeat(3, 1fr); border-top: 1px solid var(--ink); border-left: 1px solid var(--ink); margin: 12px 0 12px; }
|
||
.bingo button { all: unset; box-sizing: border-box; border-right: 1px solid var(--ink); border-bottom: 1px solid var(--ink); padding: 9px 9px; font-size: 13px; line-height: 1.2; min-height: 64px; cursor: pointer; position: relative; transition: background .15s; }
|
||
.bingo button:hover { background: rgba(201,112,107,.1); }
|
||
.bingo button[aria-pressed="true"]::after { content: ""; position: absolute; inset: 6px; border: 2.5px solid var(--rose); border-radius: 50%; transform: rotate(-8deg); opacity: .85; }
|
||
.bingo button.free { font-family: var(--hand); font-size: 20px; text-align: center; display: grid; place-items: center; background: rgba(232,176,74,.25); }
|
||
.recs { list-style: none; padding: 0; margin: 0; font-size: 14.5px; }
|
||
.recs li { padding: 5px 0; border-top: 1px solid var(--line); display: flex; justify-content: space-between; gap: 10px; }
|
||
.recs li span { font: 11px var(--mono); color: var(--mute); white-space: nowrap; }
|
||
|
||
/* blank pages */
|
||
.blank { margin: 18px 0 4px; border: 1.5px dashed var(--line2); border-radius: 4px; padding: 16px 20px; display: flex; gap: 24px; align-items: center; color: var(--mute); }
|
||
.blank .pp2 { font: italic 500 30px/1 var(--serif); color: var(--dim); white-space: nowrap; }
|
||
.blank p { margin: 0; font-size: 15px; }
|
||
.blank .hand { font-size: 22px; color: var(--rose); margin-left: auto; white-space: nowrap; transform: rotate(-2deg); }
|
||
|
||
/* section heads */
|
||
.sec { padding: 46px 0 0; }
|
||
.sh { display: flex; align-items: baseline; gap: 16px; border-bottom: 2px solid var(--ink); padding-bottom: 8px; }
|
||
.sh h2 { margin: 0; font-weight: 300; font-style: italic; font-size: 44px; letter-spacing: -.03em; line-height: 1; }
|
||
.sh .n { font: 12px var(--mono); color: var(--mute); }
|
||
.sh .r { margin-left: auto; font: 12px var(--mono); color: var(--mute); }
|
||
|
||
/* back issues */
|
||
.shelf { display: grid; grid-template-columns: 70px 1fr; gap: 20px; padding: 22px 0 0; }
|
||
.yr { font: italic 500 28px var(--serif); color: var(--mute); padding-top: 4px; }
|
||
.covers { display: grid; grid-template-columns: repeat(5, 1fr); gap: 22px; }
|
||
.cover { all: unset; box-sizing: border-box; cursor: pointer; display: block; }
|
||
.cover .fr { aspect-ratio: 3 / 4; position: relative; overflow: hidden; border-radius: 2px; box-shadow: 0 1px 0 rgba(42,26,31,.1), 0 10px 22px -14px rgba(42,26,31,.55); transition: transform .25s var(--ease), box-shadow .25s; }
|
||
.cover .fr svg { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||
.cover:hover .fr, .cover:focus-visible .fr { transform: translateY(-6px) rotate(-1deg); box-shadow: 0 1px 0 rgba(42,26,31,.1), 0 22px 30px -16px rgba(42,26,31,.6); }
|
||
.cover[aria-expanded="true"] .fr { transform: translateY(-6px); box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--ink), 0 22px 30px -16px rgba(42,26,31,.6); }
|
||
.cover .cap { display: flex; justify-content: space-between; margin-top: 10px; font-size: 15px; }
|
||
.cover .cap span { font: 11px var(--mono); color: var(--mute); }
|
||
.cover.ghost .fr { border: 1.5px dashed var(--line2); box-shadow: none; background: transparent; display: grid; place-items: center; text-align: center; font-family: var(--hand); font-size: 22px; color: var(--mute); padding: 20px; }
|
||
.cover.ghost { cursor: default; }
|
||
.cover.ghost:hover .fr { transform: none; box-shadow: none; }
|
||
.drawer { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s var(--ease); margin-left: 90px; }
|
||
.drawer > div { overflow: hidden; }
|
||
.drawer.open { grid-template-rows: 1fr; }
|
||
.drawer-in { margin-top: 22px; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--line2); padding: 14px 0 16px; display: grid; grid-template-columns: 240px 1fr; gap: 30px; }
|
||
.drawer-in h3 { margin: 0; font-weight: 500; font-size: 26px; line-height: 1.05; letter-spacing: -.02em; }
|
||
.drawer-in h3 i { font-weight: 300; }
|
||
.drawer-in .lead { font-size: 14.5px; color: var(--ink2); font-style: italic; margin: 8px 0 10px; }
|
||
.dlist { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 30px; }
|
||
.dlist li { break-inside: avoid; display: grid; grid-template-columns: 30px 1fr auto; gap: 6px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 15px; align-items: baseline; }
|
||
.dlist .p { font: italic 500 15px var(--serif); color: var(--rose); }
|
||
.tagx { font: 10.5px var(--mono); color: var(--mute); white-space: nowrap; }
|
||
|
||
/* index */
|
||
.idx-top { display: flex; gap: 18px; align-items: center; padding: 18px 0 14px; flex-wrap: wrap; }
|
||
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
|
||
.chip { border: 1px solid var(--line2); background: none; border-radius: 99px; padding: 4px 12px 4px 10px; font-size: 15px; cursor: pointer; display: inline-flex; gap: 7px; align-items: baseline; transition: background .15s, border-color .15s, color .15s; }
|
||
.chip sup { font: 10.5px var(--mono); color: var(--mute); top: 0; }
|
||
.chip:hover { border-color: var(--ink); }
|
||
.chip[aria-pressed="true"] { background: var(--ink); color: var(--cream); border-color: var(--ink); }
|
||
.chip[aria-pressed="true"] sup { color: var(--amber); }
|
||
.find { margin-left: auto; display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--line2); padding: 2px 0; }
|
||
.find input { border: 0; background: none; font: 15px var(--serif); font-style: italic; color: var(--ink); width: 200px; outline: none; }
|
||
.find input::placeholder { color: var(--dim); }
|
||
.find kbd { font: 10px var(--mono); border: 1px solid var(--line2); border-radius: 3px; padding: 0 4px; color: var(--mute); }
|
||
.idx { display: grid; grid-template-columns: 1fr 1fr; gap: 0 40px; }
|
||
.group { break-inside: avoid; margin-bottom: 18px; }
|
||
.group h4 { margin: 0; display: flex; align-items: baseline; gap: 10px; font-weight: 500; font-size: 20px; border-bottom: 1px solid var(--ink); padding: 6px 0 5px; }
|
||
.group h4 span { font: 11px var(--mono); color: var(--mute); }
|
||
.group h4 .glyph { width: 16px; height: 16px; align-self: center; }
|
||
.row { display: grid; grid-template-columns: 1fr auto auto; gap: 14px; padding: 7px 0; border-bottom: 1px solid var(--line); text-decoration: none; align-items: baseline; transition: background .15s, padding .15s; position: relative; }
|
||
.row:hover { background: rgba(232,176,74,.14); padding-left: 6px; padding-right: 6px; }
|
||
.row .t { font-size: 15.5px; line-height: 1.25; }
|
||
.row .t small { display: block; font-size: 13px; color: var(--mute); font-style: italic; margin-top: 1px; max-height: 0; overflow: hidden; transition: max-height .2s; }
|
||
.row:hover .t small, .row:focus-visible .t small { max-height: 40px; }
|
||
.row .iss { font: 11px var(--mono); color: var(--mute); white-space: nowrap; }
|
||
.row .iss b { color: var(--ink); font-weight: 500; }
|
||
.row .dt { font: 11px var(--mono); color: var(--dim); white-space: nowrap; width: 54px; text-align: right; }
|
||
.row.cur-iss .iss b { background: var(--amber); padding: 0 4px; border-radius: 2px; }
|
||
.idx-empty { grid-column: 1 / -1; font-style: italic; color: var(--mute); padding: 20px 0; }
|
||
.idx-note { font: 11.5px var(--mono); color: var(--mute); padding: 6px 0 0; }
|
||
|
||
/* colophon */
|
||
.colo { margin-top: 56px; background: var(--plum); color: var(--cream); position: relative; }
|
||
.colo::before { content: ""; position: absolute; inset: 0; opacity: .14; pointer-events: none; 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>"); }
|
||
.colo .wrap { display: grid; grid-template-columns: 1.4fr 1fr 1.3fr; gap: 40px; padding-top: 30px; padding-bottom: 34px; position: relative; font-size: 14px; color: #e3d4c1; }
|
||
.colo h5 { margin: 0 0 6px; font: 600 24px var(--hand); color: var(--amber); }
|
||
.colo a { color: var(--cream); text-decoration-color: var(--rose); text-underline-offset: 3px; }
|
||
.colo .ph { text-decoration-color: rgba(241,230,214,.4); }
|
||
.colo .small { font: 11.5px/1.6 var(--mono); color: #b8a592; }
|
||
|
||
@media (max-width: 1100px) {
|
||
.s3, .s4, .s5, .s6, .s7 { grid-column: span 6; }
|
||
.vr { border-left: 0; padding-left: 0; }
|
||
.covers { grid-template-columns: repeat(3, 1fr); }
|
||
.scribble { display: none; }
|
||
}
|
||
@media (max-width: 760px) {
|
||
:root { --edge: 26px; }
|
||
.edge { font-size: 10px; }
|
||
.wrap, .bar .in { padding-left: 16px; padding-right: 16px; }
|
||
.bar .in { gap: 10px; } .nav, .fill { display: none; }
|
||
.mast { grid-template-columns: 1fr; } .mast h1 { font-size: 58px; } .issue-no { text-align: left; justify-content: start; } .issue-no .n { font-size: 60px; }
|
||
.coverline { flex-direction: column; gap: 4px; }
|
||
.s3, .s4, .s5, .s6, .s7 { grid-column: 1 / -1; }
|
||
.comicpage { grid-template-rows: 110px 90px; }
|
||
.song { grid-template-columns: 1fr; } .song .sleeve-box { margin-bottom: 12px; }
|
||
.cols { columns: 1; }
|
||
.shelf { grid-template-columns: 1fr; } .covers { grid-template-columns: repeat(2, 1fr); } .drawer { margin-left: 0; }
|
||
.drawer-in { grid-template-columns: 1fr; } .dlist { columns: 1; }
|
||
.idx { grid-template-columns: 1fr; } .find { margin-left: 0; }
|
||
.colo .wrap { grid-template-columns: 1fr; }
|
||
.blank { flex-wrap: wrap; } .blank .hand { margin-left: 0; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="mk" id="mk" role="note"><button onclick="document.getElementById('mk').remove()" aria-label="Dismiss note">×</button><b>personal-r2-c · The zine, grown up</b>What "come in" opens: the current seasonal issue is the front page and fills up as the season goes (1–3 things a month fills an issue naturally). Past issues sit below as covers, and an index by interest cuts across every issue. Evolves P5, with marcschuster.com's editorial calm and beige.zone's archival index.</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="#issue">This issue</a><a href="#back">Back issues</a><a href="#index">By interest</a></nav>
|
||
<div class="fill" title="pages filled in this issue"><span>Nº 04 · 7 of ~9 pages</span><span class="dots" aria-hidden="true"><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i></i><i></i></span></div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="wrap">
|
||
<section class="mast" id="issue">
|
||
<div>
|
||
<h1>Off the clock<em>.</em></h1>
|
||
<div class="sub">a seasonal zine of things I love and things I think · by Lucas Winther</div>
|
||
</div>
|
||
<div class="issue-no">
|
||
<div class="n"><small>Nº</small>04</div>
|
||
<div class="s">Autumn 2026</div>
|
||
<div class="d">Sep · Oct · Nov</div>
|
||
<div class="d">closes 30 Nov</div>
|
||
</div>
|
||
<div class="scribble" aria-hidden="true">still filling up!
|
||
<svg width="60" height="28" viewBox="0 0 60 28" fill="none"><path d="M2 4 C 20 4, 40 8, 54 22" stroke="#c9706b" stroke-width="2" stroke-linecap="round"/><path d="M46 22 L55 23 L53 14" stroke="#c9706b" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
</div>
|
||
</section>
|
||
<div class="coverline"><span>This season: a webcomic that wrecked me, a song for cold bike rides, a pumpkin, and why I keep falling for villainesses.</span><span class="r">last page added 2 Nov</span></div>
|
||
|
||
<div class="issue">
|
||
<!-- contents -->
|
||
<aside class="pg s3 toc" aria-label="Contents">
|
||
<div class="kick">In this issue</div>
|
||
<ol>
|
||
<li><a href="#p2"><span class="p">2</span><span class="tt">Now Recharging made me cry, a lot</span><span class="m">comics · 14 Sep</span></a></li>
|
||
<li><a href="#p4"><span class="p">4</span><span class="tt">Song of the season</span><span class="m">music · 21 Sep</span></a></li>
|
||
<li><a href="#p5"><span class="p">5</span><span class="tt ph" title="placeholder">Hades II and the comfort of trying again</span><span class="m">games · 6 Oct</span></a></li>
|
||
<li><a href="#p6"><span class="p">6</span><span class="tt">The pumpkin</span><span class="m">made by me · <b>new</b> 2 Nov</span></a></li>
|
||
<li><a href="#p7"><span class="p">7</span><span class="tt ph" title="placeholder">Why I cry at fiction and not at the news</span><span class="m">writing · 19 Oct</span></a></li>
|
||
<li><a href="#p8"><span class="p">8</span><span class="tt">Reborn as the villainess (again)</span><span class="m">comics · <b>new</b> 28 Oct</span></a></li>
|
||
<li><a href="#cur"><span class="p">✦</span><span class="tt">Currently: watching, reading</span><span class="m">pulled from Trakt + Hardcover</span></a></li>
|
||
<li class="empty"><a href="#p9" tabindex="-1"><span class="p">9</span><span class="tt">still blank</span><span class="m">before 30 Nov</span></a></li>
|
||
</ol>
|
||
<div class="letter">Autumn turned into a comics season. I read more than I played, cried at one chapter more than I'd like to admit, and carved a pumpkin for the first time in years.<span class="sig">— Lucas</span></div>
|
||
</aside>
|
||
|
||
<!-- comic spread -->
|
||
<article class="pg s6 vr" id="p2">
|
||
<span class="pgno">pp. 2–3</span>
|
||
<div class="kick"><span class="t">comics</span><span>webcomic · ongoing</span></div>
|
||
<h2>Now Recharging made me <i>cry, a lot</i></h2>
|
||
<div class="comic-wrap">
|
||
<div>
|
||
<p class="quote">i cried so much in this chapter – death has always been something that hits me emotionally hard</p>
|
||
<div class="quote-src">me, on Bluesky · 14 Sep</div>
|
||
</div>
|
||
<div class="comicpage" id="comic">
|
||
<button class="panel a" data-cap="The quiet before. Two of them on a roof, the city humming underneath, and you just know." aria-label="Panel 1, enlarge">
|
||
<svg viewBox="0 0 400 150" preserveAspectRatio="xMidYMid slice"><defs><pattern id="dt1" width="7" height="7" patternUnits="userSpaceOnUse"><circle cx="3.5" cy="3.5" r="1.5" fill="#c9706b" opacity=".5"/></pattern><linearGradient id="sk1" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#f3c9a0"/><stop offset="1" stop-color="#fffaf3"/></linearGradient></defs><rect width="400" height="150" fill="url(#sk1)"/><rect width="400" height="90" fill="url(#dt1)"/><circle cx="300" cy="70" r="26" fill="#e8b04a" opacity=".85"/><g fill="#2a1a1f"><rect x="0" y="92" width="38" height="58"/><rect x="42" y="78" width="26" height="72"/><rect x="72" y="100" width="40" height="50"/><rect x="250" y="84" width="30" height="66"/><rect x="284" y="98" width="46" height="52"/><rect x="334" y="74" width="24" height="76"/><rect x="362" y="96" width="38" height="54"/></g><rect x="110" y="112" width="150" height="38" fill="#2a1a1f"/><g fill="#fffaf3"><rect x="50" y="88" width="4" height="5"/><rect x="58" y="100" width="4" height="5"/><rect x="342" y="86" width="4" height="5"/><rect x="342" y="100" width="4" height="5"/></g><g fill="#2a1a1f"><circle cx="160" cy="90" r="8"/><path d="M150 112 q10 -20 20 0z"/><circle cx="196" cy="92" r="7"/><path d="M187 112 q9 -18 18 0z"/></g><path d="M176 104 q4 -6 10 -2" stroke="#2a1a1f" stroke-width="1.5" fill="none"/></svg>
|
||
</button>
|
||
<button class="panel b" data-cap="This face. No words in the panel, and none needed." aria-label="Panel 2, enlarge">
|
||
<svg viewBox="0 0 200 150" preserveAspectRatio="xMidYMid slice"><rect width="200" height="150" fill="#fffaf3"/><g stroke="#2a1a1f" stroke-width="1" opacity=".35"> <path d="M0 10 L200 140"/><path d="M0 30 L200 160"/><path d="M0 -10 L200 120"/><path d="M0 50 L200 180"/></g><path d="M30 78 Q100 26 170 78 Q100 120 30 78Z" fill="#fffaf3" stroke="#2a1a1f" stroke-width="3"/><circle cx="100" cy="76" r="22" fill="#2a1a1f"/><circle cx="108" cy="68" r="6" fill="#fffaf3"/><path d="M40 60 Q100 20 162 58" stroke="#2a1a1f" stroke-width="3" fill="none"/><path d="M128 104 q6 14 0 22 q-6 -8 0 -22z" fill="#c9706b" stroke="#2a1a1f" stroke-width="1.5"/></svg>
|
||
</button>
|
||
<button class="panel c" data-cap="The line that did it. (Paraphrased; read it yourself.)" aria-label="Panel 3, enlarge">
|
||
<svg viewBox="0 0 200 118" preserveAspectRatio="xMidYMid slice"><defs><pattern id="dt2" width="6" height="6" patternUnits="userSpaceOnUse"><circle cx="3" cy="3" r="1.2" fill="#2a1a1f" opacity=".25"/></pattern></defs><rect width="200" height="118" fill="url(#dt2)"/><path d="M18 14 H182 Q192 14 192 24 V70 Q192 80 182 80 H70 L52 100 L56 80 H18 Q8 80 8 70 V24 Q8 14 18 14Z" fill="#fffaf3" stroke="#2a1a1f" stroke-width="2.5"/><text x="100" y="44" text-anchor="middle" font-family="Caveat, cursive" font-size="21" fill="#2a1a1f">you can rest now.</text><text x="100" y="66" text-anchor="middle" font-family="Caveat, cursive" font-size="17" fill="#2a1a1f">i've got it from here.</text></svg>
|
||
</button>
|
||
<button class="panel d" data-cap="The empty bench. The scarf. I had to put my phone down for a minute here." aria-label="Panel 4, enlarge">
|
||
<svg viewBox="0 0 400 118" preserveAspectRatio="xMidYMid slice"><rect width="400" height="118" fill="#f4e6d2"/><rect y="88" width="400" height="30" fill="#e9d6bd"/><g stroke="#2a1a1f" stroke-width="3" stroke-linecap="round"><path d="M150 72 H260"/><path d="M150 82 H260"/><path d="M158 82 V100"/><path d="M252 82 V100"/><path d="M150 62 H260"/></g><path d="M196 62 q12 -2 20 6 q-4 18 4 30 l-8 2 q-8 -12 -6 -28 q-6 -6 -10 -10z" fill="#c9706b" stroke="#2a1a1f" stroke-width="1.5"/><g fill="#e8b04a" stroke="#2a1a1f" stroke-width="1"><path d="M80 30 q8 -6 12 2 q-6 6 -12 -2z"/><path d="M320 20 q8 -6 12 2 q-6 6 -12 -2z"/><path d="M290 60 q8 -6 12 2 q-6 6 -12 -2z"/><path d="M110 70 q8 -6 12 2 q-6 6 -12 -2z"/></g></svg>
|
||
</button>
|
||
</div>
|
||
<div class="panel-cap" id="pcap"><span class="hn">tap a panel</span><span>Drawn stand-ins for a few pages from the chapter. Click one to look closer, click again to step back.</span></div>
|
||
<div class="comic-meta"><span>panels: placeholders, not the real art</span><a class="ext" href="https://nowrecharging.com" target="_blank" rel="noopener">read it at nowrecharging.com ↗</a></div>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- currently -->
|
||
<aside class="pg s3 vr" id="cur" aria-label="Currently">
|
||
<div class="kick">Sidebar</div>
|
||
<div class="cur">
|
||
<h3>currently</h3>
|
||
<div class="synced">pulled from Trakt + Hardcover · 3 h ago</div>
|
||
<div class="cur-item">
|
||
<div class="art" style="background:linear-gradient(160deg,#7f9a8c 0 45%,#e9e2cf 45% 60%,#6d6a8f 60%)"></div>
|
||
<div><div class="lbl">Watching <a href="#" title="placeholder link">trakt ↗</a></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>
|
||
</div>
|
||
<div class="cur-item">
|
||
<div class="art" style="background:radial-gradient(circle at 50% 38%,#f1e6d6 0 16%,transparent 17%),linear-gradient(#3e5a6b,#21323c)"></div>
|
||
<div><div class="lbl">Reading <a href="#" title="placeholder link">hardcover ↗</a></div><div class="ti ph" title="placeholder">Piranesi</div><div class="su">Susanna Clarke · p. 152 of 272</div><div class="prog"><i style="width:56%"></i></div></div>
|
||
</div>
|
||
<div class="cur-item" style="grid-template-columns:1fr">
|
||
<div><div class="lbl">Recently rated <span>trakt</span></div>
|
||
<ul class="rated">
|
||
<li><span class="ph" title="placeholder">Perfect Days</span><span class="st">★★★★★</span></li>
|
||
<li><span class="ph" title="placeholder">The Wild Robot</span><span class="st">★★★★☆</span></li>
|
||
<li><span class="ph" title="placeholder">Arcane, S2</span><span class="st">★★★★☆</span></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="cur-item" style="grid-template-columns:1fr">
|
||
<div><div class="lbl">Finished this season <span>hardcover</span></div>
|
||
<ul class="rated">
|
||
<li><span class="ph" title="placeholder">Tomorrow, and Tomorrow…</span><span class="st">★★★★★</span></li>
|
||
<li><span class="ph" title="placeholder">The Hobbit (reread)</span><span class="st">★★★★☆</span></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="out"><a href="#" title="placeholder link">Trakt ↗</a><a href="#" title="placeholder link">Hardcover ↗</a></div>
|
||
</div>
|
||
<p style="font-size:13.5px;color:var(--mute);font-style:italic;margin:12px 0 0">Not logged twice: this box refreshes from the APIs, and freezes when the issue closes.</p>
|
||
</aside>
|
||
|
||
<!-- song -->
|
||
<article class="pg s5" id="p4">
|
||
<span class="pgno">p. 4</span>
|
||
<div class="kick"><span class="t">music</span><span>song of the season</span></div>
|
||
<div class="song" id="song">
|
||
<div class="sleeve-box"><div class="vinyl"></div><div class="sleeve">
|
||
<svg viewBox="0 0 168 168"><rect width="168" height="168" fill="#c9706b"/><rect y="104" width="168" height="64" fill="#2a1a1f"/><circle cx="84" cy="104" r="40" fill="#e8b04a"/><rect y="104" width="168" height="64" fill="#2a1a1f"/><g stroke="#c9706b" stroke-width="3"><path d="M20 120 H148"/><path d="M36 134 H132"/><path d="M54 148 H114"/></g><text x="12" y="24" font-family="Fraunces, serif" font-style="italic" font-size="14" fill="#2a1a1f">sadness as a gift</text></svg>
|
||
</div></div>
|
||
<div>
|
||
<div class="title ph" title="placeholder: song">Sadness as a Gift</div>
|
||
<div class="artist ph" title="placeholder: artist">Adrianne Lenker</div>
|
||
<p class="why">This was on repeat on every cold bike ride in October. It sounds like the end of something, but in a kind way 🍂</p>
|
||
</div>
|
||
<div class="deck">
|
||
<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="bar2" id="seek" role="slider" aria-label="position" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" tabindex="0"><i id="sfill"></i><b id="sknob"></b></div>
|
||
<span class="time" id="time">0:00 / 4:12</span>
|
||
<button class="loop" id="loop" aria-pressed="false" title="loop this song">loop</button>
|
||
<div class="deck-note" id="dnote">press play · nothing starts on its own · mock player, no audio</div>
|
||
</div>
|
||
<div class="bside" id="bside">
|
||
<div class="h">also this season</div>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- game -->
|
||
<article class="pg s4 vr" id="p5">
|
||
<span class="pgno">p. 5</span>
|
||
<div class="kick"><span class="t">games</span><span>write-up</span></div>
|
||
<h2 class="ph" title="placeholder">Hades II and the comfort of <i>trying again</i></h2>
|
||
<div class="shot">
|
||
<svg viewBox="0 0 360 150" preserveAspectRatio="xMidYMid slice"><defs><radialGradient id="gl" cx=".5" cy=".55" r=".5"><stop offset="0" stop-color="#e8b04a" stop-opacity=".9"/><stop offset="1" stop-color="#e8b04a" stop-opacity="0"/></radialGradient></defs><rect width="360" height="150" fill="#2b1d2e"/><rect y="110" width="360" height="40" fill="#1c1320"/><circle cx="180" cy="86" r="70" fill="url(#gl)"/><g fill="#1c1320"><rect x="40" y="20" width="26" height="100"/><rect x="34" y="16" width="38" height="8"/><rect x="294" y="20" width="26" height="100"/><rect x="288" y="16" width="38" height="8"/></g><path d="M66 30 Q180 -20 294 30" stroke="#1c1320" stroke-width="10" fill="none"/><path d="M172 112 l8 -34 l8 34z" fill="#1c1320"/><circle cx="180" cy="72" r="7" fill="#1c1320"/><path d="M186 82 l26 -24" stroke="#f1e6d6" stroke-width="2"/><g fill="#e8b04a"><circle cx="120" cy="60" r="1.6"/><circle cx="240" cy="50" r="1.6"/><circle cx="210" cy="96" r="1.2"/><circle cx="150" cy="40" r="1.2"/></g></svg>
|
||
<span class="tag">screenshot placeholder</span>
|
||
</div>
|
||
<div class="facts"><span><b>41 h</b> played</span><span>Switch 2</span><span class="ph" title="placeholder">★★★★½</span></div>
|
||
<p>Every run ends, and that's the point. I've been having a heavy autumn, and there's something gentle about a game that says <i>go again, you'll be a bit stronger</i>.</p>
|
||
<div class="more" id="gmore"><div><p>The witch-y moveset took me a while. Now I can't go back. The music is doing half the work, honestly. Best moment so far: finally beating the second boss on the bus home and nearly shouting.</p></div></div>
|
||
<button class="rd" data-more="gmore">read the rest</button>
|
||
</article>
|
||
|
||
<!-- drawing -->
|
||
<article class="pg s3 vr" id="p6">
|
||
<span class="pgno">p. 6</span>
|
||
<div class="kick"><span class="t">made by me</span><span class="new">new</span></div>
|
||
<div class="sheet">
|
||
<svg viewBox="0 0 200 170" aria-label="drawing placeholder: a carved pumpkin">
|
||
<path d="M100 30 c-4 -14 4 -22 14 -22" stroke="#2a1a1f" stroke-width="3" fill="none" stroke-linecap="round"/>
|
||
<path d="M100 36 C 60 26, 20 50, 24 96 C 28 140, 70 158, 100 152 C 130 158, 174 140, 176 96 C 180 50, 140 26, 100 36Z" fill="#e8b04a" stroke="#2a1a1f" stroke-width="2.6" stroke-linejoin="round"/>
|
||
<path d="M100 36 C 82 50, 80 140, 100 152 M100 36 C 118 50, 122 140, 100 152" stroke="#2a1a1f" stroke-width="1.6" fill="none" opacity=".6"/>
|
||
<path d="M58 44 C 44 70, 46 130, 70 150 M142 44 C 156 70, 154 130, 130 150" stroke="#2a1a1f" stroke-width="1.4" fill="none" opacity=".45"/>
|
||
<path d="M58 80 l16 -12 l8 16z M118 84 l8 -16 l16 12z" fill="#2a1a1f"/>
|
||
<path d="M94 96 l6 -10 l6 10z" fill="#2a1a1f"/>
|
||
<path d="M56 108 q44 34 88 0 l-10 2 l-6 8 l-8 -6 l-8 8 l-8 -8 l-8 6 l-6 -8 l-10 -2z" fill="#2a1a1f"/>
|
||
<path d="M140 18 q8 4 4 12" stroke="#c9706b" stroke-width="2" fill="none" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="cap">carved it, then drew it 🎃</div>
|
||
</div>
|
||
<p class="drawn-note">My first pumpkin in years. The drawing is honestly better than the pumpkin. Pen and one marker, ten minutes.</p>
|
||
<div class="facts"><span>drawing placeholder</span><span>31 Oct</span></div>
|
||
</article>
|
||
|
||
<!-- essay -->
|
||
<article class="pg s7 essay" id="p7">
|
||
<span class="pgno">p. 7</span>
|
||
<div class="kick"><span class="t">writing</span><span>essay · 6 min</span></div>
|
||
<h2 class="ph" title="placeholder">Why I cry at fiction <i>and not at the news</i></h2>
|
||
<p class="stand">A comic chapter about a goodbye got me more than a month of headlines. I think that's not coldness. I think it's scale.</p>
|
||
<div class="cols">
|
||
<p>When a story lets you sit with one person for long enough, their loss becomes something you can hold. The news hands you thousands at once, and my brain just files it under weather. I don't love that about myself, but I understand it better now.</p>
|
||
<p>Death has always hit me hard in stories. Maybe because stories are the only place where you get to rehearse it gently, with a page you can close.</p>
|
||
<div class="more" id="emore"><div><p>So I've stopped feeling guilty about crying at a webcomic. If fiction is where I practice caring, then the practice counts. The trick is to carry a little of it back out with me, into the real week.</p><p>Anyway. Read Now Recharging. Bring tissues.</p></div></div>
|
||
</div>
|
||
<div class="foot"><button class="rd" data-more="emore">keep reading</button><span>19 Oct · writing, life</span></div>
|
||
</article>
|
||
|
||
<!-- trope -->
|
||
<article class="pg s5 vr" id="p8">
|
||
<span class="pgno">p. 8</span>
|
||
<div class="kick"><span class="t">comics</span><span>a trope I can't quit</span><span class="new">new</span></div>
|
||
<h2>Reborn as the villainess, <i>surrounded by lovely psychopaths</i></h2>
|
||
<p style="font-size:15px;color:var(--ink2)">She wakes up as the doomed villain, decides to just be nice, and everyone around her gets weirdly, possessively obsessed. I know. I love it anyway.</p>
|
||
<div class="bingo" id="bingo" aria-label="trope bingo, click to mark">
|
||
<button aria-pressed="true">wakes up in a novel she read</button>
|
||
<button aria-pressed="false">"I'll just avoid the prince"</button>
|
||
<button aria-pressed="true">the duke is a menace</button>
|
||
<button aria-pressed="false">tea party ambush</button>
|
||
<button class="free" aria-pressed="true">free square: she's too kind</button>
|
||
<button aria-pressed="false">the maid knows everything</button>
|
||
<button aria-pressed="true">brother has a knife collection</button>
|
||
<button aria-pressed="false">deathflag dodged in ch. 3</button>
|
||
<button aria-pressed="false">everyone's possessive</button>
|
||
</div>
|
||
<ul class="recs">
|
||
<li><span class="ph" title="placeholder" style="font:inherit;color:inherit">The Villainess Lives Twice</span><span>manhwa · ongoing</span></li>
|
||
<li><span class="ph" title="placeholder" style="font:inherit;color:inherit">Death Is the Only Ending for the Villainess</span><span>manhwa</span></li>
|
||
</ul>
|
||
</article>
|
||
|
||
<div class="s12" id="p9">
|
||
<div class="blank"><span class="pp2">p. 9</span><p>This page is still blank. Something will land here before the issue closes on 30 November, then Nº 05 opens for winter.</p><span class="hand">maybe a Kickstarter game?</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- back issues -->
|
||
<section class="sec" id="back">
|
||
<div class="sh"><h2>Back issues</h2><span class="n">3 printed · one per season since winter</span><span class="r">click a cover for its contents</span></div>
|
||
<div class="shelf">
|
||
<div class="yr">2026</div>
|
||
<div class="covers" id="covers"></div>
|
||
</div>
|
||
<div class="drawer" id="drawer"><div><div class="drawer-in" id="drawer-in"></div></div></div>
|
||
<p class="idx-note" style="margin-left:90px">Each year gets its own row of four. After a few years this is still a short shelf, and the index below does the heavy lifting.</p>
|
||
</section>
|
||
|
||
<!-- index -->
|
||
<section class="sec" id="index">
|
||
<div class="sh"><h2>Index, by interest</h2><span class="n" id="idxn"></span><span class="r">every page from every issue</span></div>
|
||
<div class="idx-top">
|
||
<div class="chips" id="chips" role="group" aria-label="filter by interest"></div>
|
||
<label class="find"><input id="q" type="search" placeholder="find a title…" aria-label="find a title"><kbd>/</kbd></label>
|
||
</div>
|
||
<div class="idx" id="idx"></div>
|
||
</section>
|
||
</main>
|
||
|
||
<footer class="colo">
|
||
<div class="wrap">
|
||
<div><h5>colophon</h5>Written, drawn and put together by Lucas Winther. One issue per season, closed when the season ends and never rewritten. Shares land on a page as they happen, so the current issue is always the newest thing here.</div>
|
||
<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></div>
|
||
<div class="small">Placeholders (dotted underline): the game, song, essay titles, Trakt/Hardcover data, manhwa titles, back-issue contents, all panel and cover art (drawn stand-ins). Real: Now Recharging, Junkwraith, Cupid 13 and the quotes from Bluesky, the villainess trope, the Halloween pumpkin.</div>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<script>
|
||
// ---------- comic panels: click to look closer ----------
|
||
(function () {
|
||
var page = document.getElementById('comic'), cap = document.getElementById('pcap');
|
||
var def = cap.innerHTML;
|
||
page.querySelectorAll('.panel').forEach(function (p, i) {
|
||
p.addEventListener('click', function () {
|
||
var on = p.classList.contains('on');
|
||
page.querySelectorAll('.panel').forEach(function (x) { x.classList.remove('on'); });
|
||
if (on) { page.classList.remove('zoom'); cap.innerHTML = def; return; }
|
||
p.classList.add('on'); page.classList.add('zoom');
|
||
cap.innerHTML = '<span class="hn">panel ' + (i + 1) + '</span><span>' + p.dataset.cap + '</span>';
|
||
});
|
||
});
|
||
document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && page.classList.contains('zoom')) { page.querySelector('.panel.on').click(); } });
|
||
})();
|
||
|
||
// ---------- read more toggles ----------
|
||
document.querySelectorAll('.rd[data-more]').forEach(function (b) {
|
||
var label = b.textContent;
|
||
b.addEventListener('click', function () {
|
||
var m = document.getElementById(b.dataset.more), open = m.classList.toggle('open');
|
||
b.textContent = open ? 'fold it back' : label;
|
||
});
|
||
});
|
||
|
||
// ---------- bingo ----------
|
||
document.querySelectorAll('#bingo button').forEach(function (b) {
|
||
b.addEventListener('click', function () { b.setAttribute('aria-pressed', b.getAttribute('aria-pressed') === 'true' ? 'false' : 'true'); });
|
||
});
|
||
|
||
// ---------- mock player ----------
|
||
(function () {
|
||
var TRACKS = [
|
||
{ t: 'Sadness as a Gift', a: 'Adrianne Lenker', len: 252, main: true },
|
||
{ t: 'Ichiban', a: 'Hiatus Kaiyote', len: 214 },
|
||
{ t: 'Sunday Morning (handcam, rehearsal)', a: 'our band', len: 301, band: true }
|
||
];
|
||
var cur = 0, pos = 0, on = false, loop = false, timer = null;
|
||
var song = document.getElementById('song'), pp = document.getElementById('pp'), ppi = document.getElementById('ppi');
|
||
var fillEl = document.getElementById('sfill'), knob = document.getElementById('sknob'), time = document.getElementById('time'), note = document.getElementById('dnote');
|
||
var seek = document.getElementById('seek'), loopB = document.getElementById('loop'), bside = document.getElementById('bside');
|
||
var fmt = function (s) { return Math.floor(s / 60) + ':' + String(Math.floor(s % 60)).padStart(2, '0'); };
|
||
TRACKS.forEach(function (tr, i) {
|
||
var b = document.createElement('button');
|
||
b.innerHTML = '<span class="k">' + (i === 0 ? 'A' : 'B' + i) + '</span><span><span class="ph" title="placeholder">' + tr.t + '</span> <i style="color:var(--mute)">· ' + tr.a + '</i></span><span class="d">' + fmt(tr.len) + '</span>';
|
||
b.addEventListener('click', function () { if (cur === i) { set(!on); return; } cur = i; pos = 0; set(true); });
|
||
bside.appendChild(b);
|
||
});
|
||
function ui() {
|
||
var L = TRACKS[cur].len, pct = pos / L * 100;
|
||
fillEl.style.width = pct + '%'; knob.style.left = pct + '%'; seek.setAttribute('aria-valuenow', Math.round(pct));
|
||
time.textContent = fmt(pos) + ' / ' + fmt(L);
|
||
bside.querySelectorAll('button').forEach(function (b, i) { b.setAttribute('aria-current', i === cur ? 'true' : 'false'); });
|
||
note.textContent = on ? 'playing ' + TRACKS[cur].t + (loop ? ' · on loop' : '') : (pos > 0 ? 'paused' : 'press play · nothing starts on its own · mock player, no audio');
|
||
}
|
||
function set(v) {
|
||
on = v; clearInterval(timer); song.classList.toggle('playing', 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) timer = setInterval(function () {
|
||
pos++;
|
||
if (pos >= TRACKS[cur].len) { pos = 0; if (!loop) { if (cur < TRACKS.length - 1) cur++; else { set(false); } } }
|
||
ui();
|
||
}, 1000);
|
||
ui();
|
||
}
|
||
pp.addEventListener('click', function () { set(!on); });
|
||
loopB.addEventListener('click', function () { loop = !loop; loopB.setAttribute('aria-pressed', loop); ui(); });
|
||
seek.addEventListener('click', function (e) { var r = seek.getBoundingClientRect(); pos = Math.floor((e.clientX - r.left) / r.width * TRACKS[cur].len); ui(); });
|
||
seek.addEventListener('keydown', function (e) { if (e.key === 'ArrowRight') { pos = Math.min(TRACKS[cur].len - 1, pos + 5); ui(); } if (e.key === 'ArrowLeft') { pos = Math.max(0, pos - 5); ui(); } });
|
||
ui();
|
||
})();
|
||
|
||
// ---------- data: every page of every issue ----------
|
||
var INTERESTS = [
|
||
['comics', 'Comics'], ['games', 'Games'], ['music', 'Music'], ['film', 'Film & TV'], ['books', 'Books'], ['made', 'Made by me'], ['writing', 'Writing'], ['life', 'Life']
|
||
];
|
||
var ISSUES = [
|
||
{ no: '01', season: 'Winter', yr: '2026', months: 'Dec · Jan · Feb', title: 'Snowed in, <i>reading</i>', lead: 'The first one. Mostly about staying inside and finding a comic with a world I wanted to live in.', bg: '#2a1a1f', fg: '#f1e6d6', motif: 'snow' },
|
||
{ no: '02', season: 'Spring', yr: '2026', months: 'Mar · Apr · May', title: 'Faith, a sniper, <i>and cats</i>', lead: 'A one-shot that stuck with me, a commission I still look at daily, and the band filmed through a door.', bg: '#c9706b', fg: '#2a1a1f', motif: 'sprout' },
|
||
{ no: '03', season: 'Summer', yr: '2026', months: 'Jun · Jul · Aug', title: 'Long days, <i>slow films</i>', lead: 'Outer Wilds at last, a film about cleaning toilets that made me happier than most, and sketches from the ferry.', bg: '#e8b04a', fg: '#2a1a1f', motif: 'sun' },
|
||
{ no: '04', season: 'Autumn', yr: '2026', months: 'Sep · Oct · Nov', title: 'A comics season', lead: 'This one, still filling up.', bg: '#f7efe3', fg: '#2a1a1f', motif: 'leaf', current: true }
|
||
];
|
||
// [issue, page, interest(s), title, note, date, placeholder?]
|
||
var PAGES = [
|
||
['01', 2, ['comics'], 'Junkwraith', 'a new comic with an interesting art style… feels like a coming-of-age story with a unique world', '12 Jan', false],
|
||
['01', 4, ['music'], 'Song of the season: Nakamarra', 'Hiatus Kaiyote, on repeat all January', '20 Jan', true],
|
||
['01', 5, ['games'], 'Balatro, one more run', 'a poker game that ate my holidays', '2 Jan', true],
|
||
['01', 6, ['film'], 'Frieren, all of it, again', 'the best show about time passing', '8 Feb', true],
|
||
['01', 7, ['writing'], 'Why I\'m making a zine instead of a feed', 'four times a year, no infinite scroll', '1 Dec', true],
|
||
['01', 8, ['life'], 'My first winter swim (never again)', 'a dare, a fjord, a scream', '15 Feb', true],
|
||
['02', 2, ['comics'], 'Cupid 13', 'a MangaPlus one-shot about a forsaken sniper who regains faith', '9 Mar', false],
|
||
['02', 4, ['made'], 'The band, drawn as cats', 'a commission I look at every day', '30 Mar', true],
|
||
['02', 5, ['music'], 'Through the door: Sunday Morning', 'our band\'s handcam from rehearsal', '18 Apr', true],
|
||
['02', 6, ['games'], 'Backed on Kickstarter, finally playing: Sea of Stars', 'three years after pledging', '2 May', true],
|
||
['02', 7, ['books'], 'Piranesi, the first time', 'a house with endless halls and tides', '20 May', true],
|
||
['03', 2, ['games'], 'Outer Wilds, at last', 'no spoilers, just go', '14 Jun', true],
|
||
['03', 4, ['film'], 'Perfect Days made me tidy my flat', 'a slow film about small routines', '2 Jul', true],
|
||
['03', 5, ['music'], 'Song of the season: Are You Looking Up', 'Mk.gee, windows down', '10 Jul', true],
|
||
['03', 6, ['made'], 'Sketchbook: ferry seats', 'twelve drawings of people asleep', '28 Jul', true],
|
||
['03', 7, ['writing', 'life'], 'Liking things without irony', 'an essay about being openly into stuff', '19 Aug', true],
|
||
['04', 2, ['comics'], 'Now Recharging made me cry, a lot', 'i cried so much in this chapter', '14 Sep', false],
|
||
['04', 4, ['music'], 'Song of the season: Sadness as a Gift', 'cold bike rides in October', '21 Sep', true],
|
||
['04', 5, ['games'], 'Hades II and the comfort of trying again', 'every run ends, and that\'s the point', '6 Oct', true],
|
||
['04', 6, ['made'], 'The pumpkin', 'carved it, then drew it', '2 Nov', false],
|
||
['04', 7, ['writing', 'life'], 'Why I cry at fiction and not at the news', 'an essay about scale', '19 Oct', true],
|
||
['04', 8, ['comics'], 'Reborn as the villainess (again)', 'a trope I can\'t quit, with bingo', '28 Oct', false]
|
||
];
|
||
var GLYPH = {
|
||
comics: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><rect x="1.5" y="1.5" width="13" height="13"/><path d="M1.5 8H9M9 1.5v13"/></svg>',
|
||
games: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><rect x="1.5" y="4.5" width="13" height="7" rx="3.5"/><path d="M5 6.5v3M3.5 8h3"/><circle cx="11" cy="7.5" r=".6" fill="currentColor"/></svg>',
|
||
music: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><circle cx="8" cy="8" r="6.5"/><circle cx="8" cy="8" r="1.6"/></svg>',
|
||
film: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><rect x="1.5" y="3.5" width="13" height="9"/><path d="M1.5 6.5h13M5 3.5v3M9 3.5v3"/></svg>',
|
||
books: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><path d="M2 3c2-1 4-1 6 1 2-2 4-2 6-1v10c-2-1-4-1-6 1-2-2-4-2-6-1z"/><path d="M8 4v10"/></svg>',
|
||
made: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><path d="M11 2l3 3-8 8H3v-3z"/></svg>',
|
||
writing: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><path d="M2 4h12M2 7h12M2 10h8M2 13h5"/></svg>',
|
||
life: '<svg class="glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><path d="M8 14s-6-3.5-6-8a3 3 0 0 1 6-1 3 3 0 0 1 6 1c0 4.5-6 8-6 8z"/></svg>'
|
||
};
|
||
var MOTIF = {
|
||
snow: function (c) { var s = ''; [[30,40],[90,30],[150,60],[60,90],[120,110],[40,150],[160,140],[100,170],[20,200],[140,200]].forEach(function (p) { s += '<circle cx="' + p[0] + '" cy="' + p[1] + '" r="3" fill="' + c + '" opacity=".7"/>'; }); return s + '<path d="M0 200 Q50 186 100 198 T200 194 V214 Q100 206 0 214Z" fill="' + c + '" opacity=".9"/>'; },
|
||
sprout: function (c) { return '<path d="M100 240 V150" stroke="' + c + '" stroke-width="5"/><path d="M100 175 C100 140 70 125 45 128 C45 160 70 175 100 175Z" fill="' + c + '"/><path d="M100 160 C100 125 128 110 158 112 C158 145 130 160 100 160Z" fill="' + c + '" opacity=".75"/>'; },
|
||
sun: function (c) { var r = ''; for (var i = 0; i < 12; i++) { var a = i * Math.PI / 6; r += '<path d="M' + (100 + Math.cos(a) * 52) + ' ' + (150 + Math.sin(a) * 52) + ' L' + (100 + Math.cos(a) * 70) + ' ' + (150 + Math.sin(a) * 70) + '" stroke="' + c + '" stroke-width="4" stroke-linecap="round"/>'; } return '<circle cx="100" cy="150" r="40" fill="' + c + '"/>' + r; },
|
||
leaf: function (c) { return '<path d="M60 220 C 50 150, 110 100, 160 110 C 165 170, 120 225, 60 220Z" fill="#c9706b"/><path d="M60 220 C 90 180, 120 150, 150 120" stroke="' + c + '" stroke-width="2.5" fill="none"/>'; }
|
||
};
|
||
|
||
// ---------- back issues ----------
|
||
(function () {
|
||
var wrap = document.getElementById('covers'), drawer = document.getElementById('drawer'), din = document.getElementById('drawer-in');
|
||
var open = null;
|
||
ISSUES.forEach(function (x) {
|
||
var b = document.createElement('button');
|
||
b.className = 'cover'; b.setAttribute('aria-expanded', 'false');
|
||
b.innerHTML = '<div class="fr" style="background:' + x.bg + '"><svg viewBox="0 0 200 267" preserveAspectRatio="xMidYMid slice">' + MOTIF[x.motif](x.fg) +
|
||
'<text x="14" y="34" font-family="Fraunces, serif" font-style="italic" font-weight="300" font-size="21" fill="' + x.fg + '">Off the clock.</text>' +
|
||
'<text x="186" y="252" text-anchor="end" font-family="Fraunces, serif" font-weight="600" font-size="58" letter-spacing="-3" fill="' + x.fg + '">' + x.no + '</text>' +
|
||
'<text x="14" y="252" font-family="Geist Mono, monospace" font-size="10" fill="' + x.fg + '" opacity=".8">' + x.season.toUpperCase() + ' ' + x.yr + '</text></svg></div>' +
|
||
'<div class="cap"><span style="font:inherit;color:inherit">Nº ' + x.no + ' · ' + x.season + '</span><span>' + (x.current ? 'reading now' : PAGES.filter(function (p) { return p[0] === x.no; }).length + ' pages') + '</span></div>';
|
||
b.addEventListener('click', function () {
|
||
if (x.current) { document.getElementById('issue').scrollIntoView({ behavior: 'smooth' }); return; }
|
||
wrap.querySelectorAll('.cover').forEach(function (c) { c.setAttribute('aria-expanded', 'false'); });
|
||
if (open === x.no) { open = null; drawer.classList.remove('open'); return; }
|
||
open = x.no; b.setAttribute('aria-expanded', 'true');
|
||
var ps = PAGES.filter(function (p) { return p[0] === x.no; });
|
||
din.innerHTML = '<div><div class="kick">Nº ' + x.no + ' · ' + x.season + ' ' + x.yr + ' · ' + x.months + '</div><h3 style="margin-top:6px" class="ph" title="placeholder">' + x.title + '</h3><p class="lead">' + x.lead + '</p><a href="#" class="ext" onclick="return false">open the whole issue →</a></div>' +
|
||
'<ol class="dlist">' + ps.map(function (p) { return '<li><span class="p">' + p[1] + '</span><span' + (p[6] ? ' class="ph" title="placeholder"' : '') + '>' + p[3] + '</span><span class="tagx">' + p[2].join(', ') + '</span></li>'; }).join('') + '</ol>';
|
||
drawer.classList.add('open');
|
||
});
|
||
wrap.appendChild(b);
|
||
});
|
||
var g = document.createElement('div');
|
||
g.className = 'cover ghost';
|
||
g.innerHTML = '<div class="fr">Nº 05 · winter<br>opens 1 December</div><div class="cap"><span style="font:inherit;color:var(--mute)">next</span><span>0 pages</span></div>';
|
||
wrap.appendChild(g);
|
||
})();
|
||
|
||
// ---------- index by interest ----------
|
||
(function () {
|
||
var chips = document.getElementById('chips'), idx = document.getElementById('idx'), q = document.getElementById('q'), n = document.getElementById('idxn');
|
||
var sel = 'all';
|
||
n.textContent = PAGES.length + ' pages · ' + ISSUES.length + ' issues';
|
||
var count = function (k) { return PAGES.filter(function (p) { return p[2].indexOf(k) > -1; }).length; };
|
||
var html = '<button class="chip" data-k="all" aria-pressed="true">Everything <sup>' + PAGES.length + '</sup></button>';
|
||
INTERESTS.forEach(function (i) { html += '<button class="chip" data-k="' + i[0] + '" aria-pressed="false">' + i[1] + ' <sup>' + count(i[0]) + '</sup></button>'; });
|
||
chips.innerHTML = html;
|
||
chips.querySelectorAll('.chip').forEach(function (c) {
|
||
c.addEventListener('click', function () { sel = c.dataset.k; chips.querySelectorAll('.chip').forEach(function (x) { x.setAttribute('aria-pressed', x === c); }); render(); });
|
||
});
|
||
function row(p) {
|
||
return '<a class="row' + (p[0] === '04' ? ' cur-iss' : '') + '" href="#"><span class="t"><span' + (p[6] ? ' class="ph" title="placeholder"' : '') + '>' + p[3] + '</span><small>' + p[4] + '</small></span><span class="iss"><b>Nº ' + p[0] + '</b> · p. ' + p[1] + '</span><span class="dt">' + p[5] + '</span></a>';
|
||
}
|
||
function render() {
|
||
var term = q.value.trim().toLowerCase();
|
||
var list = PAGES.filter(function (p) { return !term || (p[3] + ' ' + p[4]).toLowerCase().indexOf(term) > -1; })
|
||
.slice().sort(function (a, b) { return b[0].localeCompare(a[0]) || b[1] - a[1]; });
|
||
var groups = sel === 'all' ? INTERESTS : INTERESTS.filter(function (i) { return i[0] === sel; });
|
||
var out = '';
|
||
groups.forEach(function (gi) {
|
||
var ps = list.filter(function (p) { return p[2][0] === gi[0] || (sel !== 'all' && p[2].indexOf(gi[0]) > -1); });
|
||
if (!ps.length) return;
|
||
out += '<div class="group"><h4>' + GLYPH[gi[0]] + gi[1] + ' <span>' + ps.length + '</span></h4>' + ps.map(row).join('') + '</div>';
|
||
});
|
||
idx.style.gridTemplateColumns = sel === 'all' ? '' : '1fr';
|
||
idx.innerHTML = out || '<p class="idx-empty">Nothing with that name yet. Maybe next season.</p>';
|
||
}
|
||
q.addEventListener('input', render);
|
||
document.addEventListener('keydown', function (e) { if (e.key === '/' && document.activeElement !== q) { e.preventDefault(); q.focus(); } });
|
||
render();
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|