/* world.css: the grove's pages. Text sits in a reading column over the scene, no boxes; the leaf you are reading is lit and a thread
   of light runs from it to its node on the branch (assets/world.js). term3d's palette: ground, silver past, golden tip. */
:root{--veil:3,4,6;--font:'JetBrains Mono',ui-monospace,monospace;--ground:#030406;--silver:#cdd7ec;--dim:#7d8496;--faint:#3c4250;--gold:#ffb547;--ember:#ff8a3d;--white:#fff0dc;color-scheme:dark}
*{box-sizing:border-box}
/* day's paper from the first paint (x 10-31: 'black jitter on white theme'): these came only with the variant's json, after the page was up,
   so every page and every cross-fade between two began black. Same values as assets/variants/b-paper-ink.json */
html[data-theme=day]{--ground:#f1ede2;--silver:#23211d;--dim:#5d584c;--faint:#b8b09c;--gold:#a3300c;--ember:#c0451a;--white:#000;--veil:241,237,226;color-scheme:light}
html{background:var(--ground);-webkit-text-size-adjust:100%}
body{margin:0;background:var(--ground);color:var(--silver);font:300 14.5px/1.75 var(--font);overflow-x:hidden}
#w{position:fixed;inset:0;width:100%;height:100%;display:block;z-index:0;cursor:grab;touch-action:pan-y}
#w{opacity:0}#w.on{opacity:1;transition:opacity .25s}   /* a WebGL canvas is black until its first frame: it shows from then */
#w.drag{cursor:grabbing}
.veil{position:fixed;inset:0;z-index:1;pointer-events:none;background:linear-gradient(90deg,rgba(var(--veil),.95) 0,rgba(var(--veil),.86) calc(min(600px,calc(100vw - 32px)) + clamp(16px,7vw,120px) - 40px),rgba(var(--veil),0) calc(min(600px,calc(100vw - 32px)) + clamp(16px,7vw,120px) + 220px))}
#thread{position:fixed;inset:0;width:100%;height:100%;z-index:2;pointer-events:none;overflow:visible}
#thread path{fill:none;stroke:var(--gold);stroke-width:1;opacity:.85;filter:drop-shadow(0 0 3px rgba(255,181,71,.7))}
#thread circle{fill:var(--gold);filter:drop-shadow(0 0 4px var(--gold))}
#tags{position:fixed;inset:0;z-index:2;pointer-events:none}
.tag{position:absolute;left:0;top:0;font-size:11.5px;color:var(--dim);text-decoration:none;white-space:nowrap;pointer-events:auto;text-shadow:0 0 6px #000,0 0 2px #000;transition:opacity .3s,color .2s}
.tag::before{content:'';display:inline-block;width:5px;height:5px;border:1px solid currentColor;border-radius:50%;margin-right:7px;vertical-align:1px}
.tag:hover,.tag:focus-visible{color:var(--gold)}
.top{position:fixed;left:0;right:0;top:0;z-index:5;display:flex;justify-content:space-between;align-items:baseline;gap:16px;padding:16px clamp(16px,7vw,120px) 28px;font-size:12.5px;background:linear-gradient(var(--ground) 40%,transparent)}
.top a{color:var(--dim);text-decoration:none}
.top .me{color:var(--silver)}
.top nav{display:flex;gap:20px;flex-wrap:wrap;justify-content:flex-end}
.top a:hover,.top a[aria-current]{color:var(--gold)}
.skip{position:absolute;left:-999px;top:8px;z-index:9;background:var(--ground);color:var(--gold);padding:6px 10px}
.skip:focus{left:16px}
a{color:var(--gold);text-decoration-thickness:1px;text-underline-offset:3px}
a:focus-visible,kbd:focus-visible{outline:1px solid var(--gold);outline-offset:3px}

main{position:relative;z-index:3;width:min(600px,calc(100vw - 32px));margin-left:clamp(16px,7vw,120px);padding:18vh 0 26vh}
.path{font-size:12px;color:var(--dim);margin-bottom:5vh}
.path a{color:var(--dim);text-decoration:none}.path a:hover{color:var(--gold)}
h1{font-size:clamp(25px,3vw,34px);line-height:1.2;font-weight:700;color:var(--white);letter-spacing:-.015em;margin:0 0 .9em;text-wrap:balance}
h1 em{font-style:italic;font-weight:400}
h2{font-size:17px;line-height:1.4;font-weight:700;color:var(--white);margin:0 0 .9em}
h2 a,h3 a{color:inherit;text-decoration:none}
h3,h4{font-size:14.5px;line-height:1.45;font-weight:700;color:var(--white);margin:1.6em 0 .5em}
.leaf>h3:first-child,.leaf>div>h3:first-child,.leaf>h4:first-child,.leaf>div>h4:first-child{margin-top:0}
p,li{max-width:64ch}
p{margin:0 0 1.05em}
ul,ol{padding-left:1.3em;margin:0 0 1.1em}
li{margin:.3em 0}
li::marker{color:var(--faint)}
strong,b{font-weight:700;color:var(--white)}
code{font:inherit;color:var(--white)}
pre{white-space:pre-wrap;color:var(--white);border-left:1px solid var(--faint);padding-left:14px}
table{border-collapse:collapse;font-size:12.5px;margin:0 0 1.2em;display:block;overflow-x:auto}
td,th{border-bottom:1px solid var(--faint);padding:5px 12px 5px 0;text-align:left;vertical-align:top}
th{color:var(--white);font-weight:700}
img{max-width:100%;height:auto}
img[alt="Shreenivas Sangoram"]{width:112px;height:112px;object-fit:cover;filter:grayscale(1) contrast(1.05);opacity:.85;border-radius:50%;margin-bottom:1.2em}
small,.byline,time,.mono,.when,.org,.k,.meta,.tags,.what,.top .star{color:var(--dim);font-size:12px}
.tags span+span::before{content:'  '}
.tldr{border-left:1px solid var(--gold);padding:2px 0 2px 16px;margin:0 0 1.4em}
.tldr>span{display:block;color:var(--gold);font-size:12px;margin-bottom:4px}
.tldr p{color:var(--white);font-weight:400}
.what{font-style:italic;margin-top:1.2em}
.what a{color:var(--dim)}
.btn,.go{display:inline-block;margin:0 18px 8px 0}
.hire{border-top:1px solid var(--faint);margin-top:2em;padding-top:1.2em}
.stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 28px;margin:2em 0 0}
.stats b{display:block;font-size:22px;color:var(--white)}
.stats span{font-size:12px;color:var(--dim)}
.cta{margin:1.4em 0}
.foot .tags span,.proj .tags span{margin-right:12px}

/* a leaf: one node on the branch. The one you are reading is lit; the rest wait in the dark. */
.leaf{position:relative;min-height:62vh;padding:3vh 0 7vh;opacity:.34;transition:opacity .5s}
.leaf.on{opacity:1}
.leaf::before{content:'';position:absolute;left:-26px;top:calc(3vh + .62em);width:7px;height:7px;border:1px solid var(--faint);border-radius:50%;transition:border-color .4s,background .4s,box-shadow .4s}
.leaf.on::before{border-color:var(--gold);background:var(--gold);box-shadow:0 0 10px var(--gold)}
.leaf.hero,.leaf.pivot,.leaf.trunk{min-height:72vh}
.leaf.hero h1{font-size:clamp(28px,4vw,46px)}
.branches{list-style:none;padding:0;margin:4vh 0 0}
.branches .leaf{min-height:36vh;max-width:none}
.branches .leaf b{font-size:16px;line-height:1.45}
.branches .leaf a{text-decoration:none}
.branches .leaf a:hover b{color:var(--gold)}
.branches small{display:block;margin:.3em 0 .6em}
.twigs{list-style:none;padding:0;display:flex;flex-wrap:wrap;gap:4px 22px}
.twigs a{color:var(--silver);text-decoration:none;font-size:13px}
.twigs a:hover{color:var(--gold)}
.tree h2 a:hover{color:var(--gold)}

.turn{display:flex;justify-content:space-between;gap:20px;margin-top:6vh;padding-top:2vh;font-size:13px}
.turn a{color:var(--silver);text-decoration:none}
.turn a:hover{color:var(--gold)}
.foot{margin-top:8vh;font-size:12px;color:var(--dim)}
.foot a{color:var(--dim)}
kbd{font:inherit;font-size:11px;color:var(--silver);border:1px solid var(--faint);border-bottom-width:2px;border-radius:3px;padding:0 4px}

/* the position strip: every page in reading order, top to bottom; trees are the long ticks, you are the gold one */
.strip{position:fixed;right:14px;top:50%;transform:translateY(-50%);z-index:4;display:flex;flex-direction:column;align-items:flex-end;gap:0}
.strip a{position:relative;display:flex;align-items:center;justify-content:flex-end;width:26px;height:9px;text-decoration:none}
.strip i{display:block;width:8px;height:1px;background:var(--faint);transition:width .3s,background .3s}
.strip a.tree i,.strip a.grove i{width:16px;background:var(--dim)}
.strip a.on i{width:22px;background:var(--gold);box-shadow:0 0 6px var(--gold)}
.strip span{position:absolute;right:32px;white-space:nowrap;font-size:11px;color:var(--gold);opacity:0;pointer-events:none;transition:opacity .15s;text-shadow:0 0 6px #000}
.strip a:hover span,.strip a:focus-visible span{opacity:1}
.strip a:hover i{background:var(--silver)}
.keys{position:fixed;right:48px;bottom:12px;z-index:4;margin:0;font-size:11px;color:var(--dim);pointer-events:none;max-width:none}

}
@media (prefers-reduced-motion:reduce){.leaf,.leaf::before,.tag,.strip i{transition:none}}

/* pivot rings (lab winner, from a-pivots): leaf marks are term3d pivots, the strip is gold pivot ticks, the thread travels */
@keyframes tr{to{stroke-dashoffset:-40}
}
#thread path{stroke-width:1.5;stroke-dasharray:2 6;animation:tr 1.4s linear infinite;filter:drop-shadow(0 0 5px rgba(255,181,71,0.9)) drop-shadow(0 0 12px rgba(255,138,61,0.6))}
.leaf::before{width:11px;height:11px;left:-32px;border:1px solid var(--dim);background:transparent;border-radius:50%}
.leaf.on::before{border:1.5px solid var(--gold);background:radial-gradient(circle,var(--white) 0 2px,transparent 3px);box-shadow:0 0 14px var(--gold),0 0 0 4px rgba(255,181,71,0.12)}
.leaf{opacity:0.28}
.strip i{width:1px;height:7px;background:var(--faint)}
.strip a{height:12px}
.strip a.on i{width:1px;height:12px;background:var(--gold);box-shadow:0 0 8px var(--gold)}
.strip a.tree i,.strip a.grove i{width:1px;height:9px;background:var(--dim)}
@media (prefers-reduced-motion:reduce){#thread path{animation:none}}

/* round 2 (d-best): legible tags with gold rings, a lighter thread, a taller phone scene that fades into the text */
.leaf{opacity:.36}.leaf.on{opacity:1}
.tag{color:var(--silver);text-shadow:0 0 8px #000,0 0 3px #000,0 0 16px #000}
.tag::before{border-color:var(--gold);box-shadow:0 0 6px rgba(255,181,71,.5)}
#thread path{stroke-width:1.1;animation-duration:2.4s;filter:drop-shadow(0 0 4px rgba(255,181,71,.8))}

/* the theme switch in the header: day = ink on paper, night = the molten grove (world.js picks the variant) */
.top .theme-toggle{background:none;border:0;padding:0;font:inherit;color:var(--dim);cursor:pointer}
.top .theme-toggle:hover,.top .theme-toggle:focus-visible{color:var(--gold)}
/* zoom: three marks in the bar, no box; the number lights gold once it is not 100% (a click there puts it back) */
.top .zoom{display:inline-flex;align-items:baseline;gap:2px;margin-right:14px}
.top .zoom button{background:none;border:0;padding:0 4px;font:inherit;color:var(--dim);cursor:pointer;font-variant-numeric:tabular-nums}
.top .zoom button[data-z="0"]{min-width:4.5ch;font-size:var(--t-cap)}
.top .zoom button[data-z="0"].on{color:var(--gold)}
.top .zoom button:hover,.top .zoom button:focus-visible{color:var(--gold)}

/* the run-out: the next page's title, alone, as the last leaf; past it the page cuts to the next one (world.js), cross-faded */
@view-transition{navigation:auto}
::view-transition-old(root),::view-transition-new(root){animation-duration:.7s;animation-timing-function:ease-in-out}
.leaf.reel{min-height:118vh;padding-top:24vh}
/* page to page with no title said twice (x 10-31: 'why are we rendering next page heading the one extra time without text'): the run-out keeps
   its length, the cut still comes when it reaches the reading line, but its title shows only to the keyboard; the next page says it once */
.reel a{opacity:0}.reel a:focus-visible{opacity:1}
/* the words fade while the next page's are fetched and swapped in; the scene behind keeps moving */
main{transition:opacity .16s}body.swap main{opacity:0}main:focus{outline:0}
.reel a{display:block;text-decoration:none;color:var(--white)}
.reel small{display:block;color:var(--gold);margin-bottom:.6em}
.reel b{display:block;font-size:var(--t-title);line-height:1.2;letter-spacing:-.015em;text-wrap:balance}
.reel span{display:block;margin-top:1.2em;color:var(--dim);font-size:var(--t-cap)}
.reel a:hover b{color:var(--gold)}

/* type pass (x 10-31, after Apple's HIG typography: few text styles, no light weights, sizes that follow the reader's font size,
   text off a background made bolder with a halo, 44px touch targets): five sizes, in rem */
:root{--t-cap:.75rem;--t-small:.8125rem;--t-body:.9375rem;--t-head:1.125rem;--t-title:clamp(1.6rem,3vw,2.15rem)}
body{font:400 var(--t-body)/1.7 var(--font)}
h1{font-size:var(--t-title)}
h2,.branches .leaf b,.stats b{font-size:var(--t-head)}
h3,h4{font-size:var(--t-body)}
.top,.twigs a,.turn,table{font-size:var(--t-small)}
small,.byline,time,.mono,.when,.org,.k,.meta,.tags,.what,.top .star,.path,.foot,.tldr>span,.stats span,kbd,.keys,.strip span{font-size:var(--t-cap)}
#tags .tag{font-size:var(--t-small);font-weight:700;text-shadow:0 0 2px var(--ground),0 0 4px var(--ground),0 0 8px var(--ground),0 0 14px var(--ground)}
}

/* the thread, redrawn (x 10-31): a callout leader. Hairline in a dim-to-gold gradient, a tick at the words, a node and a ring at the
   object, and once drawn a spark that rides from the words to the object */
#thread path.base{stroke:url(#tg);stroke-width:1;stroke-dasharray:none;animation:none;opacity:1;filter:none}
#thread path.pulse{fill:none;stroke:var(--white);stroke-width:1.6;stroke-linecap:round;stroke-dasharray:.05 1.2;stroke-dashoffset:.05;opacity:0;filter:drop-shadow(0 0 4px var(--gold)) drop-shadow(0 0 10px var(--ember))}
#thread.lit path.pulse{opacity:1;animation:spark 2.6s cubic-bezier(.45,0,.25,1) infinite}
@keyframes spark{0%{stroke-dashoffset:.05}62%,100%{stroke-dashoffset:-1.05}}
#thread circle.tick{r:2px;fill:var(--dim);filter:none}
#thread circle.node{fill:var(--gold);filter:drop-shadow(0 0 5px var(--gold))}
#thread circle.ring{fill:none;stroke:var(--gold);stroke-width:1;filter:none;transform-box:fill-box;transform-origin:center;opacity:0}
#thread.lit circle.ring{animation:ring 2.6s ease-out infinite}
@keyframes ring{0%,55%{transform:scale(.35);opacity:0}62%{opacity:.9}100%{transform:scale(2.4);opacity:0}}
html[data-theme=day] #thread path.pulse{stroke:var(--gold);filter:none}
html[data-theme=day] #thread circle.node{filter:none}
@media (prefers-reduced-motion:reduce){#thread.lit path.pulse,#thread.lit circle.ring{animation:none;opacity:0}}

/* Apple's text (x 10-31: 'use the apple design skill for text'), from the HIG skill: Inter, the open twin of San Francisco, first (on Linux, Chrome swaps
   a local font in for the Apple names before Inter is reached); named styles (large title, title, headline, body, subhead, footnote,
   caption) told apart by weight as much as size; tight tracking on display sizes. JetBrains Mono stays for the instrument layer:
   breadcrumbs, metadata, keys, code */
:root{--sf:'Inter',-apple-system,BlinkMacSystemFont,'Helvetica Neue',sans-serif;--sfd:'Inter',-apple-system,BlinkMacSystemFont,'Helvetica Neue',sans-serif;
  --t-cap:.75rem;--t-small:.875rem;--t-body:1.0625rem;--t-head:1.375rem;--t-title:clamp(2rem,3.4vw,2.75rem)}
body{font:400 var(--t-body)/1.52 var(--sf);letter-spacing:-.011em;-webkit-font-smoothing:antialiased}
p,li{max-width:34em}
h1,h2,.reel b{font-family:var(--sfd);font-weight:700;letter-spacing:-.025em;line-height:1.08}
h1{font-size:var(--t-title)}
.leaf.hero h1{font-size:clamp(2.4rem,4.6vw,3.75rem);letter-spacing:-.032em;line-height:1.04}
h2{font-size:var(--t-head);letter-spacing:-.018em;line-height:1.18}
h3,h4,.branches .leaf b{font-family:var(--sf);font-size:var(--t-body);font-weight:600;letter-spacing:-.014em;line-height:1.3}
strong,b{font-weight:600}
.tldr p{font-size:1.1875rem;line-height:1.45;font-weight:500;letter-spacing:-.016em}
.top{font:500 var(--t-small)/1.3 var(--sf);letter-spacing:-.006em}
.top .me{font-weight:600}
.turn,.twigs a{font-family:var(--sf);font-size:var(--t-small);font-weight:500}
#tags .tag{font-family:var(--sf);font-size:var(--t-small);font-weight:600;letter-spacing:-.01em}
.reel b{font-size:var(--t-title)}
small,.byline,time,.mono,.when,.org,.k,.meta,.tags,.what,.path,.foot,.tldr>span,.stats span,.reel small,.reel span{font-family:var(--font);letter-spacing:0}
code,pre,kbd,.keys,table{font-family:var(--font);letter-spacing:0}
@media(max-width:760px){.leaf.hero h1{font-size:2.3rem}}
/* the indicator (x 10-31 sketch): this page's strip mark keeps its name lit, a hairline under it for how far down you are;
   the dial is the nav, top right: the four trees, each brightening as the ring brings it to the front */
.strip a.on span{opacity:.9}
.strip a.on span::after{content:"";position:absolute;left:0;right:0;bottom:-4px;height:1px;background:linear-gradient(90deg,var(--gold) calc(var(--p,0)*100%),var(--faint) calc(var(--p,0)*100%));opacity:.8}
.dial{display:flex;gap:18px;margin-right:6px;font-size:var(--t-cap);letter-spacing:.08em;text-transform:uppercase}
.dial a{color:var(--silver);text-decoration:none;transition:color .4s;position:relative}
.dial a.front{color:var(--gold)}
.dial a::after{content:"";position:absolute;left:0;right:0;bottom:-5px;height:1px;background:var(--gold);transform:scaleX(0);transition:transform .45s}
.dial a.front::after,.dial a:hover::after{transform:scaleX(1)}
.dial a:focus-visible{outline:1px solid var(--gold);outline-offset:4px}
.dial a.here::before{content:"";position:absolute;left:50%;top:-7px;width:3px;height:3px;margin-left:-1.5px;border-radius:50%;background:var(--gold);box-shadow:0 0 6px var(--gold)}
.dial a:hover{color:var(--white)}
/* the top band stays clear of the reading veil, so the centre piece shows there under the name */
.veil{-webkit-mask-image:linear-gradient(transparent 0,transparent 15vh,#000 26vh);mask-image:linear-gradient(transparent 0,transparent 15vh,#000 26vh)}
/* Home (x 10-31 sketch 2: 'text doesn't overlap visual objects'): a small text area bottom left, below the orb's light; what you have
   read leaves (it doesn't dim over the light), the scene keeps the bigger right side */
body[data-kind=grove] main{width:min(440px,34vw)}
body[data-kind=grove] .leaf.past{opacity:0}
body[data-kind=grove] .leaf.hero{min-height:88vh}
body[data-kind=grove] .veil{-webkit-mask-image:linear-gradient(transparent 0,transparent 50vh,#000 62vh);mask-image:linear-gradient(transparent 0,transparent 50vh,#000 62vh)}
/* Home: only the section being read shows (the orb becomes it; no other text on screen while it forms) */
body[data-kind=grove] .leaf:not(.on){opacity:0}
/* ---- design review pass (10-31, artifact-design + Apple HIG lenses, in x's taste): the text set for the scene ---- */
/* Home hero: a wider column so the headline sets in three lines and the whole hero fits above the reserved bottom band */
body[data-kind=grove] main{width:var(--home-col,min(560px,40vw));padding-bottom:0}
body[data-kind=grove] .leaf.hero h1{font-size:clamp(2.4rem,3.6vw,3.25rem);text-wrap:balance}
body[data-kind=grove] .leaf.hero{min-height:100vh}
/* the fixed stage (world.js stage()): each section a screen tall, its words pinned bottom left, swapping in place */
body[data-kind=grove] .leaf.tree{min-height:100vh;padding:0}
body[data-kind=grove] .leaf.tree::before{display:none}
body[data-kind=grove] .stage{position:fixed;left:clamp(16px,7vw,120px);width:var(--home-col,min(560px,40vw));padding-bottom:8px}
body[data-kind=grove] .leaf:not(.on) .stage{pointer-events:none}
body[data-kind=grove] .stage::before{content:'';position:absolute;left:-32px;top:.55em;width:11px;height:11px;border-radius:50%;border:1.5px solid var(--gold);background:radial-gradient(circle,var(--white) 0 2px,transparent 3px);box-shadow:0 0 14px var(--gold)}
body[data-kind=grove] .leaf.tree h2{font-size:clamp(2rem,3vw,2.75rem);font-weight:600;letter-spacing:-.025em;line-height:1.05;margin-bottom:.5em}
body[data-kind=grove] .twigs{flex-direction:column;flex-wrap:nowrap;gap:.35em 0}
body[data-kind=grove] .twigs a{font-size:15px;font-weight:400}
/* the numbers: one row of four instrument readings */
@media (min-width:761px){.stats{grid-template-columns:repeat(4,minmax(0,1fr));gap:10px 22px}}
.stats b{font-weight:600;font-variant-numeric:tabular-nums}
.stats span{line-height:1.35}
/* the eyebrow sits apart from the lede */
.leaf.hero .mono{display:block;margin:0 0 .6em;letter-spacing:.08em;text-transform:uppercase}
/* credits: last in their section, upright, quiet */
.what{font-style:normal;margin-top:1.4em;opacity:.8}
/* the short answer without the accent rail */
.tldr{border-left:0;padding:0}
/* two Inter weights (400, 600), plain mono; no light, no mono italic */
.twigs a,.turn{font-weight:400}
h1,h2,h3,.leaf.hero h1,.stats b{font-weight:600}
em,i{font-synthesis:none}
.what,.byline,.mono,time,.tags{font-style:normal}
/* text you've read stays legible on inner pages */
.leaf{opacity:.6}.leaf.on{opacity:1}
/* header: the theme switch set like the dial, on its baseline */
.top .theme-toggle{font-size:var(--t-cap);letter-spacing:.08em;text-transform:uppercase;color:var(--silver);margin-left:6px}
.dial a{opacity:1 !important}
/* the key hints: a first visit only, gold glyphs, no boxes; text keeps clear of the bottom band they use */
.keys{transition:opacity .8s}
.keys.gone{opacity:0}
.keys.explore{bottom:30px}   /* the exploring line sits above the key hints, never over them */
.keys kbd{border:0;background:none;box-shadow:none;padding:0 1px;color:var(--gold)}
.keys kbd{pointer-events:auto;cursor:pointer}   /* each glyph presses its key (world.js), so a touch screen has them too */
html[data-theme=day] .strip span{text-shadow:none}
.twigs li.more a{color:var(--gold)}
/* Home (x 10-31): the orb holds the top 30% of the left side; the text lives in the bottom 70% and the reading veil starts there */
body[data-kind=grove] main{padding-top:calc(30vh + 12px)}
body[data-kind=grove] .leaf.hero{min-height:70vh;padding-top:0}
body[data-kind=grove] .veil{-webkit-mask-image:linear-gradient(transparent 0,transparent 28vh,#000 34vh);mask-image:linear-gradient(transparent 0,transparent 28vh,#000 34vh)}
