@@ -0,0 +1,343 @@
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< title > __TITLE__< / 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:opsz,wght@9..144,500;9..144,600&family=Inter:wght@400;500&display=swap" rel = "stylesheet" >
< style >
: root {
/* ===== THE DETERMINER =====
--font-floor is the comfortable-readable body atom. Everything derives UP from it.
floor 15px = comfortable-readable minimum (physiological)
ceiling 21px = anti-absurd on huge screens (convention)
viewport term = growth rate (convention) — ~16-17px around a 1440px viewport
--measure 62ch = optimal line length (physiological ~60ch) */
--font-floor : clamp ( 15 px , 0.9 rem + 0.35 vw , 21 px ) ;
--measure : 62 ch ;
/* derived UP from the determiner (ratios, not magic numbers) */
--f-body : var ( - - font - floor ) ;
--f-head : calc ( var ( - - font - floor ) * 1.7 ) ;
--f-eye : calc ( var ( - - font - floor ) * 0.72 ) ;
--card-min : 22 rem ; /* ~ a readable measure at floor size; derived target */
--bg : #ffffff ; --ink : #2b2b3a ; --muted : #6b6b7b ; --line : #e3e3ec ;
--bar-h : 52 px ; --radius : 20 px ; --gap : 14 px ; --fade : .28 s ;
}
* { box-sizing : border-box ; }
html , body { margin : 0 ; height : 100 % ; background : var ( - - bg ) ; color : var ( - - ink ) ;
font-family : "Inter" , system-ui , sans-serif ; font-size : var ( - - f - body ) ;
-webkit- font-smoothing : antialiased ; }
# bar { position : sticky ; top : 0 ; height : var ( - - bar - h ) ; display : flex ; align-items : center ; gap : 8 px ;
padding : 0 16 px ; background : rgba ( 255 , 255 , 255 , .85 ) ; backdrop-filter : blur ( 8 px ) ;
border-bottom : 1 px solid var ( - - line ) ; z-index : 100 ; }
. navtag { font : 500 15 px / 1 "Inter" , sans-serif ; color : var ( - - muted ) ; background : none ;
border : 1 px solid var ( - - line ) ; border-radius : 999 px ; padding : 8 px 16 px ; cursor : pointer ;
transition : color .2 s , border-color .2 s , background .2 s ; }
. navtag : hover { color : var ( - - ink ) ; border-color : var ( - - ink ) ; }
. navtag . active { color : var ( - - bg ) ; background : var ( - - ink ) ; border-color : var ( - - ink ) ; }
/* ===== n× n GRID: wraps, mobile-safe, no media query =====
minmax(min(--card-min,100%),1fr): as many columns as fit at >=card-min,
but never wider than the container (so phones become one full-width column). */
# grid { display : grid ; gap : var ( - - gap ) ; padding : var ( - - gap ) ;
grid-template-columns : repeat ( auto - fill , minmax ( min ( var ( - - card - min ) , 100 % ) , 1 fr ) ) ;
align-content : start ; }
. card { position : relative ; border : 1 px solid var ( - - line ) ; border-radius : var ( - - radius ) ;
padding : 26 px 24 px ; min-height : 24 vh ; background : var ( - - bg ) ; cursor : pointer ; overflow : hidden ;
display : flex ; flex-direction : column ; justify-content : flex-start ;
box-shadow : 0 1 px 2 px rgba ( 43 , 43 , 58 , .04 ) ;
transition : box-shadow .2 s ease , transform .12 s ease ; } /* opacity owned by WAAPI, not CSS */
. card : hover { box-shadow : 0 6 px 22 px rgba ( 43 , 43 , 58 , .08 ) ; }
. card : active { transform : scale ( .995 ) ; }
. card { --accent : var ( - - ink ) ; }
. card :: before { content : "" ; position : absolute ; left : 0 ; top : 0 ; bottom : 0 ; width : 4 px ; background : var ( - - accent ) ; }
. card h2 { margin : 0 0 6 px ; font-family : "Fraunces" , Georgia , serif ; font-weight : 600 ;
font-size : var ( - - f - head ) ; line-height : 1.05 ; letter-spacing : -.01 em ; color : var ( - - ink ) ; overflow-wrap : anywhere ; }
. card . k { display : block ; font-size : var ( - - f - eye ) ; letter-spacing : .14 em ; text-transform : uppercase ;
color : var ( - - accent ) ; font-weight : 500 ; }
. card p { margin : 10 px 0 0 ; color : var ( - - muted ) ; font-size : var ( - - f - body ) ; line-height : 1.5 ; max-width : var ( - - measure ) ; }
. card pre { margin : 12 px 0 0 ; padding : 12 px 14 px ; background : #f5f5f9 ; border : 1 px solid var ( - - line ) ;
border-radius : 10 px ; overflow : auto ; font : 0.85 em / 1.5 ui-monospace , "SF Mono" , Menlo , monospace ; color : var ( - - ink ) ; }
. card blockquote { margin : 12 px 0 0 ; padding : 2 px 0 2 px 14 px ; border-left : 3 px solid var ( - - accent ) ;
color : var ( - - ink ) ; font-style : italic ; font-size : var ( - - f - body ) ; }
. card . invite { margin : 14 px 0 0 ; align-self : flex-start ; padding : 7 px 14 px ; border-radius : 999 px ;
border : 1 px solid var ( - - accent ) ; color : var ( - - accent ) ; font-size : 0.9 em ; font-weight : 500 ; }
. card . tags { margin-top : auto ; padding-top : 16 px ; display : flex ; flex-wrap : wrap ; gap : 6 px ; }
. card . tag { font : 500 0.72 rem / 1 "Inter" , sans-serif ; color : var ( - - muted ) ; cursor : pointer ;
border : 1 px solid var ( - - line ) ; border-radius : 999 px ; padding : 4 px 10 px ; transition : color .2 s , border-color .2 s ; }
. card . tag : hover { color : var ( - - ink ) ; border-color : var ( - - ink ) ; }
/* tags view = ONE virtual card holding a weighted cloud (normalized band sizing).
tag look (Fraunces + accent) carried from the old tag render for consistency. */
. card . cloud { cursor : default ; display : block ; }
. card . cloud . cloudtag { display : inline-block ; margin : 0 .55 em .35 em 0 ; line-height : 1.1 ;
font-family : "Fraunces" , Georgia , serif ; color : var ( - - accent ) ; cursor : pointer ;
transition : opacity .2 s ; }
. card . cloud . cloudtag : hover { opacity : .55 ; }
. placeholder { visibility : hidden ; }
/* the ?card render: one card, inset by the same --gap gutter as the grid,
fills the remaining width, content-height, scrolls past the viewport.
ONLY functional overrides here — corners/border/shadow/padding inherit from .card. */
. card . solo { position : fixed ; z-index : 50 ;
top : calc ( var ( - - bar - h ) + var ( - - gap ) ) ; left : var ( - - gap ) ; right : var ( - - gap ) ; width : auto ;
height : auto ; min-height : 0 ; max-height : calc ( 100 vh - var ( - - bar - h ) - 2 * var ( - - gap ) ) ;
overflow : auto ; }
@ media ( prefers-reduced-motion : reduce ) { . navtag { transition : none ; } }
< / style >
< / head >
< body >
< nav id = "bar" > < / nav >
< main id = "grid" > < / main >
< script >
/*__DATA__*/ /* worker injects window.__CARDS__ [{slug,md}] + window.__TAGS__ [str] */
/* ---------- parser ---------- */
function parse ( md ) {
const idm = md . match ( /<!--\s*id:\s*([0-9a-f-]{36})\s*-->/i ) ; // minted by gen.mjs
const id = idm ? idm [ 1 ] . toLowerCase ( ) : "" ;
md = md . replace ( /<!--\s*id:\s*[0-9a-f-]{36}\s*-->/i , "" ) ; // strip so it never renders
const fm = md . match ( /^---\n([\s\S]*?)\n---\n?/ ) ;
const front = fm ? fm [ 1 ] : "" ;
const body = fm ? md . slice ( fm [ 0 ] . length ) : md ;
const tags = ( front . match ( /tags:\s*\[([^\]]*)\]/ ) ? . [ 1 ] || "" )
. split ( "," ) . map ( s => s . trim ( ) ) . filter ( Boolean ) ;
const L = body . split ( "\n" ) ; const blocks = [ ] ;
for ( let i = 0 ; i < L . length ; i ++ ) {
const l = L [ i ] ; if ( ! l . trim ( ) ) continue ;
if ( /^\^\s+/ . test ( l ) ) { blocks . push ( { type : "eyebrow" , text : l . replace ( /^\^\s+/ , "" ) . trim ( ) } ) ; continue ; }
if ( /^#\s+/ . test ( l ) ) { blocks . push ( { type : "heading" , text : l . replace ( /^#\s+/ , "" ) . trim ( ) } ) ; continue ; }
if ( /^```/ . test ( l ) ) { const b = [ ] ; i ++ ; while ( i < L . length && ! /^```/ . test ( L [ i ] ) ) { b . push ( L [ i ] ) ; i ++ ; }
blocks . push ( { type : "code" , text : b . join ( "\n" ) } ) ; continue ; }
if ( /^>\s?/ . test ( l ) ) { const b = [ l . replace ( /^>\s?/ , "" ) ] ;
while ( i + 1 < L . length && /^>\s?/ . test ( L [ i + 1 ] ) ) { i ++ ; b . push ( L [ i ] . replace ( /^>\s?/ , "" ) ) ; }
blocks . push ( { type : "quote" , text : b . join ( " " ) } ) ; continue ; }
if ( /^=>\s+/ . test ( l ) ) { blocks . push ( { type : "invite" , text : l . replace ( /^=>\s+/ , "" ) . trim ( ) } ) ; continue ; }
const b = [ l . trim ( ) ] ;
while ( i + 1 < L . length && L [ i + 1 ] . trim ( ) && ! /^(\^|#|```|>|=>)/ . test ( L [ i + 1 ] ) ) { i ++ ; b . push ( L [ i ] . trim ( ) ) ; }
blocks . push ( { type : "prose" , text : b . join ( " " ) } ) ;
}
const pick = t => blocks . find ( b => b . type === t ) ? . text || "" ;
return { id , tags , eyebrow : pick ( "eyebrow" ) , heading : pick ( "heading" ) , blocks } ;
}
const hue = t => { let h = 0 ; for ( const c of t ) h = ( h * 31 + c . charCodeAt ( 0 ) ) >>> 0 ; return h % 360 ; } ;
const accentOf = tag => ` hsl( ${ hue ( tag ) } 52% 42%) ` ;
function renderBlock ( b ) {
let el ;
if ( b . type === "prose" ) { el = document . createElement ( "p" ) ; }
else if ( b . type === "code" ) { el = document . createElement ( "pre" ) ; const c = document . createElement ( "code" ) ;
c . textContent = b . text ; el . append ( c ) ; return el ; }
else if ( b . type === "quote" ) { el = document . createElement ( "blockquote" ) ; }
else if ( b . type === "invite" ) { el = document . createElement ( "div" ) ; el . className = "invite" ; }
else { el = document . createElement ( "div" ) ; }
el . textContent = b . text ;
return el ;
}
function renderCard ( c ) {
const primary = c . tags [ 0 ] || "" ;
const el = document . createElement ( "article" ) ;
el . className = "card" ; el . dataset . k = primary ; el . dataset . slug = c . slug || "" ; el . dataset . id = c . id || "" ;
el . style . setProperty ( "--accent" , accentOf ( primary ) ) ;
const eb = document . createElement ( "span" ) ; eb . className = "k" ; eb . textContent = c . eyebrow ;
const h = document . createElement ( "h2" ) ; h . textContent = c . heading ;
el . append ( eb , h ) ;
for ( const b of c . blocks ) {
if ( b . type === "eyebrow" || b . type === "heading" ) continue ;
el . append ( renderBlock ( b ) ) ;
}
if ( c . tags . length ) {
const row = document . createElement ( "div" ) ; row . className = "tags" ;
for ( const t of c . tags ) {
const s = document . createElement ( "span" ) ; s . className = "tag" ; s . textContent = t ;
s . addEventListener ( "click" , e => { e . stopPropagation ( ) ; setState ( { view : 'surface' , tag : t , card : null } ) ; } ) ;
row . append ( s ) ;
}
el . append ( row ) ;
}
return el ;
}
/* the tags view: one virtual card holding a weighted cloud.
weight = card-count per tag (free from ALL). normalized band → size, derived on --font-floor. */
function renderTagCloud ( ) {
const count = new Map ( ) ;
for ( const e of ALL ) for ( const t of e . tags ) count . set ( t , ( count . get ( t ) || 0 ) + 1 ) ;
const counts = TAGS . map ( t => count . get ( t ) || 0 ) ;
const lo = Math . min ( ... counts ) , hi = Math . max ( ... counts ) ;
const MIN = 1.0 , MAX = 2.2 ; // font-floor multiples: least→most frequent
const mul = c => hi === lo ? ( MIN + MAX ) / 2 : MIN + ( MAX - MIN ) * ( c - lo ) / ( hi - lo ) ;
const el = document . createElement ( "article" ) ;
el . className = "card cloud" ; el . dataset . slug = "cloud:tags" ; // non-navigable (see click guard)
for ( const t of TAGS ) {
const s = document . createElement ( "span" ) ;
s . className = "cloudtag" ; s . textContent = t ;
s . style . fontSize = ` calc(var(--font-floor) * ${ mul ( count . get ( t ) || 0 ) . toFixed ( 3 ) } ) ` ;
s . style . setProperty ( "--accent" , accentOf ( t ) ) ;
s . addEventListener ( "click" , e => { e . stopPropagation ( ) ; setState ( { view : 'surface' , tag : t , card : null } ) ; } ) ;
el . append ( s ) ;
}
return el ;
}
/* ---------- source boundary: bundled CARDS + TAGS (injected) ---------- */
const RAW = ( window . _ _CARDS _ _ || [ ] ) ;
const TAGS = ( window . _ _TAGS _ _ || [ ] ) ;
const RAWMAP = new Map ( RAW . map ( c => [ c . slug , c . md ] ) ) ;
const BYID = new Map ( RAW . map ( c => [ c . id , c ] ) ) ; // id → raw card (identity lookup for ?card=)
const CACHE = new Map ( ) ;
function cardFor ( slug ) {
if ( CACHE . has ( slug ) ) return CACHE . get ( slug ) ;
const c = parse ( RAWMAP . get ( slug ) ) ; c . slug = slug ; CACHE . set ( slug , c ) ; return c ;
}
const ALL = RAW . map ( c => ( { slug : c . slug , id : c . id , tags : parse ( c . md ) . tags } ) ) ; // index, file-order (name-sorted)
const grid = document . getElementById ( "grid" ) ;
const bar = document . getElementById ( "bar" ) ;
/* ---------- toolbar: Cards + Tags (intrinsic views) ---------- */
const NAV = [
{ label : "Cards" , act : ( ) => setState ( { view : 'cards' , tag : null , card : null } ) } ,
{ label : "Tags" , act : ( ) => setState ( { view : 'tags' , tag : null , card : null } ) } ,
] ;
const navEls = NAV . map ( n => { const b = document . createElement ( "button" ) ; b . className = "navtag" ;
b . textContent = n . label ; b . addEventListener ( "click" , n . act ) ; bar . append ( b ) ; return b ; } ) ;
/* ================= THE AXIOM =================
ONE state. setState → 'state' event → render(S). Activators only setState.
URL is a peer expression of state (push only) and a peer activator (popstate). */
let S = { view : 'cards' , tag : null , card : null } ; // one query, always. no 'open'. 'card' holds a v7 id (identity); name gives order
/* state <-> URL (push only; NEVER replaceState — browser history is the user's) */
/* URL is query-shaped: every state IS a query, flat, no hierarchy.
all cards → ?cards ( bare / normalizes here on boot — educational: home is a query too )
tags → ?tags
surface → ?tag=NAME
card → ?card=ID
No 'open': a single card is just ?card=ID. Back button walks the query path. */
function stateToURL ( S ) {
if ( S . view === 'tags' ) return '?tags' ;
if ( S . view === 'surface' && S . tag ) return '?tag=' + encodeURIComponent ( S . tag ) ;
if ( S . view === 'card' && S . card ) return '?card=' + encodeURIComponent ( S . card ) ;
return '?cards' ; // canonical all-cards ( / normalizes here on boot )
}
function urlToState ( ) {
const p = new URLSearchParams ( location . search ) ;
if ( p . has ( 'tags' ) ) return { view : 'tags' , tag : null , card : null } ;
if ( p . has ( 'tag' ) ) return { view : 'surface' , tag : p . get ( 'tag' ) , card : null } ;
if ( p . has ( 'card' ) ) return { view : 'card' , tag : null , card : p . get ( 'card' ) } ;
return { view : 'cards' , tag : null , card : null } ; // ?cards or bare / → all cards
}
const bus = new EventTarget ( ) ;
let queue = Promise . resolve ( ) ;
function setState ( patch ) {
S = { ... S , ... patch } ;
history . pushState ( S , '' , stateToURL ( S ) ) ; // PUSH only — appends, never replaces
queue = queue . then ( ( ) => render ( S ) ) ;
}
/* ===== TRANSITIONS: Web Animations API. Completion = Animation.finished
(promise-based, event-driven, guaranteed to SETTLE — resolves on real
completion, rejects on cancel). No transitionend (conditional-firing),
no timers (trust assumptions). A transition is a named render; swap the
keyframes and nothing else changes. t=0 / reduced-motion = instant. ===== */
const DUR = 750 ; // one duration source (ms) — app-wide floor
const reduce = matchMedia ( '(prefers-reduced-motion:reduce)' ) . matches ;
// run an animation, resolve when it FINISHES; a cancelled anim (element
// pulled mid-flight) rejects → we swallow it and treat as done. Never hangs.
const play = ( el , frames , opts = { } ) => {
if ( reduce || ! el . animate ) return Promise . resolve ( ) ; // instant path
const a = el . animate ( frames , { duration : DUR , easing : 'ease' , fill : 'both' , ... opts } ) ;
return a . finished . then ( ( ) => a . cancel ( ) , ( ) => { } ) ; // commit then clear; ignore cancel-reject
} ;
const fadeOut = els => Promise . all ( els . map ( el =>
play ( el , [ { opacity : 1 } , { opacity : 0 } ] ) ) ) ; // each card fades; all .finished
const fadeIn = els => Promise . all ( els . map ( el =>
play ( el , [ { opacity : 0 } , { opacity : 1 } ] ) ) ) ;
/* the group for a state = a query result */
function groupFor ( S ) {
if ( S . view === 'cards' ) return ALL . map ( e => e . slug ) . map ( cardFor ) . map ( renderCard ) ;
if ( S . view === 'tags' ) return [ renderTagCloud ( ) ] ;
if ( S . view === 'card' ) { const c = BYID . get ( S . card ) ; return c ? [ cardFor ( c . slug ) ] . map ( renderCard ) : [ ] ; }
// surface: cards carrying the tag
return ALL . filter ( e => e . tags . includes ( S . tag ) ) . map ( e => e . slug ) . map ( cardFor ) . map ( renderCard ) ;
}
/* grow: animate the BOX geometry from slot rect (first) to full rect (last).
geometry-space, not transform — content reflows to fill at normal size, never scales.
first keyframe = slot with fill:'both', so the full-size state never paints (no flash).
.solo rests at full w/h, so the cancel-on-finished holds the end with no jump. */
function grow ( el , first ) {
el . classList . add ( 'solo' ) ;
const last = el . getBoundingClientRect ( ) ; // full rect (from .solo)
const box = r => ( { top : r . top + 'px' , left : r . left + 'px' , width : r . width + 'px' , height : r . height + 'px' } ) ;
return play ( el , [ box ( first ) , box ( last ) ] ) ;
}
async function swap ( S ) {
const cur = [ ... grid . querySelectorAll ( '.card' ) ] ;
const target = ( S . view === 'card' ) ? cur . find ( c => c . dataset . id === S . card ) : null ;
if ( target ) { // a visible card was clicked → grow sequence
const first = target . getBoundingClientRect ( ) ; // slot rect, up front
const others = cur . filter ( c => c !== target ) ;
await fadeOut ( others ) ; // PHASE 1: the way clears — .finished = broadcast "cleared"
others . forEach ( c => c . remove ( ) ) ;
navEls . forEach ( n => n . classList . remove ( 'active' ) ) ;
await grow ( target , first ) ; // PHASE 2: target heard "cleared", grows — .finished = broadcast "filled"
return ;
}
// generic transition: old fades out → new group → new fades in
await fadeOut ( cur ) ;
const els = groupFor ( S ) ;
grid . replaceChildren ( ... els ) ;
navEls [ 0 ] . classList . toggle ( 'active' , S . view === 'cards' ) ;
navEls [ 1 ] . classList . toggle ( 'active' , S . view === 'tags' ) ;
if ( S . view === 'card' ) els . forEach ( el => el . classList . add ( 'solo' ) ) ; // direct ?card= (no source card): appear solo, no grow
await fadeIn ( els ) ;
}
/* ---------- the ONE response: DOM := f(state) ---------- */
function key ( S ) { return S . view + '|' + ( S . tag || '' ) + '|' + ( S . card || '' ) ; } // what defines "which group"
async function render ( S ) {
if ( key ( S ) !== grid . dataset . key ) {
grid . dataset . key = key ( S ) ;
await swap ( S ) ;
}
}
/* ---------- activators ---------- */
grid . addEventListener ( 'click' , e => {
const card = e . target . closest ( '.card' ) ; if ( ! card || card . classList . contains ( 'cloud' ) ) return ;
setState ( { view : 'card' , card : card . dataset . id , tag : null } ) ; // click a card = navigate to ?card=<id>
} ) ;
window . addEventListener ( 'popstate' , ( ) => { // back/forward = peer activator (no push)
S = urlToState ( ) ; queue = queue . then ( ( ) => render ( S ) ) ;
} ) ;
function boot ( ) {
S = urlToState ( ) ;
history . replaceState ( S , '' , stateToURL ( S ) ) ; // seed initial entry only (the one allowed replace: first load has no prior)
queue = queue . then ( ( ) => render ( S ) ) ;
}
boot ( ) ;
< / script >
< / body >
< / html >