/* Fonts are served from this site, so a visit makes no request to anyone else. */
@font-face {
  font-family: 'IM Fell English';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/im-fell-english-400-italic.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IM Fell English';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/im-fell-english-400-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IM Fell English SC';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/im-fell-english-sc-400-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/jetbrains-mono-400-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* A growth sim draws hyphae into a density canvas; live tips, guttation droplets and the letters' mask ride along as extra
   layers. One WebGL pass lights it all (thin-film iridescence, glow, pulses, droplets, dissolves). */
:root {
  --soil: #050507;
  --bone: #efe6d6;
  --bone-dim: #a59f9a;
  --spore: #8fe3d4;
  --ember: #ff9b4a;
  --rule: rgba(239, 230, 214, .18);
  --f-text: "IM Fell English", Georgia, serif;
  --f-sc: "IM Fell English SC", Georgia, serif;
  --f-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
  color-scheme: dark;
}
html, body { height: 100%; overflow: hidden; margin: 0; }
html { background: #050507; height: 100dvh; } body { min-height: 100dvh; overscroll-behavior: none; }
[hidden] { display: none !important; }
body { background: var(--soil); color: var(--bone); font-family: var(--f-text); -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none; }
#gl, #fallback { position: fixed; inset: 0; width: 100%; height: 100%; display: block; z-index: 0; touch-action: none; }
.view { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
.view a, .view button { pointer-events: auto; }
.mono { font-family: var(--f-mono); font-size: 11px; letter-spacing: .14em; text-transform: uppercase; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.top { position: absolute; top: 0; left: 0; right: 0; display: flex; justify-content: space-between; align-items: center; gap: 8px 20px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) max(16px, env(safe-area-inset-right, 0px)) 0 max(16px, env(safe-area-inset-left, 0px)); color: var(--bone-dim); }
.sub { position: absolute; left: 0; right: 0; margin: 0; padding: 0 16px; text-align: center; font-family: var(--f-text); font-style: italic; font-size: 20px; letter-spacing: .01em; color: #c9c1b6;
  text-shadow: 0 0 12px var(--soil), 0 0 4px var(--soil), 0 0 2px var(--soil); opacity: 0; transition: opacity 2s; }
@media (max-width: 640px) { .sub { font-size: 16.5px; } }
.pin { position: absolute; transform: translate(-50%, -50%); background: none; border: 0; color: var(--bone); cursor: pointer; padding: 8px 10px; text-decoration: none; white-space: nowrap; text-align: center;
  font-family: var(--f-sc); font-size: 20px; letter-spacing: .06em; opacity: .82; transition: opacity 1.6s, color 1.6s, text-shadow 1.6s, top .8s cubic-bezier(.2,.7,.2,1), left .8s cubic-bezier(.2,.7,.2,1);
  text-shadow: 0 0 8px var(--soil), 0 0 3px var(--soil); display: grid; gap: 2px; }
/* the labels are readable from the first frame; growth decorates them instead of gating them */
.dormant [data-clear] { opacity: 0; pointer-events: none !important; }
[data-clear] { transition: opacity 1.4s; }
/* every label sits in a faint veil, just enough to read; the mycelium still shows through */
.pin { isolation: isolate; }
.pin::before { content: ""; position: absolute; inset: -24px -40px; z-index: -1; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, rgba(5,5,7,.34), rgba(5,5,7,.27) 25%, rgba(5,5,7,.17) 48%, rgba(5,5,7,.08) 70%, rgba(5,5,7,.025) 87%, transparent); transition: background 1.6s; }
.pin.lit::before, .pin.on::before, .pin:hover::before { background: radial-gradient(closest-side, color-mix(in srgb, var(--hue) 5%, rgba(5,5,7,.4)), rgba(5,5,7,.32) 25%, rgba(5,5,7,.2) 48%, rgba(5,5,7,.09) 70%, rgba(5,5,7,.03) 87%, transparent); }
.pin.lit { text-shadow: 0 0 18px rgba(239, 230, 214, .22), 0 0 4px var(--soil), 0 0 2px var(--soil), 0 1px 1px var(--soil); }
.pin small { font-family: var(--f-text); font-style: italic; font-size: 14.5px; letter-spacing: .01em; color: #c9c1b6; }
.pin.lit { opacity: 1; }
/* projects without a public link yet sit a step back, still readable */
/* projects without a public link yet sit dimmer, and brighten a little when lit or pointed at */
.pin.soon { opacity: .46; }
.pin.soon.lit, .pin.soon:hover, .pin.soon:focus-visible { opacity: .74; }
.pin.on, .pin:hover, .pin:focus-visible { opacity: 1; color: var(--hue, var(--spore)); text-shadow: 0 0 14px var(--hue), 0 0 4px var(--soil), 0 0 2px var(--soil); }
/* top corners: contact on the left, two quiet glyphs on the right (sound, regrow) */
.top .mail a { font-size: 10.5px; letter-spacing: .14em; text-transform: none; color: var(--bone-dim); text-decoration: none; opacity: .75; transition: opacity .4s; }
.top .mail a:hover, .top .mail a:focus-visible { opacity: 1; color: var(--bone); }
.top .ctl { display: flex; gap: 2px; margin: -8px -10px 0 0; }
.top .glyph { font: inherit; background: none; border: 0; padding: 0; width: 40px; height: 40px; display: grid; place-items: center; border-radius: 50%; color: var(--bone); opacity: .38; cursor: pointer;
  transition: opacity .5s, transform .9s cubic-bezier(.2,.7,.2,1); filter: drop-shadow(0 0 4px rgba(5,5,7,.9)); }
.top .glyph:hover, .top .glyph:focus-visible { opacity: .85; }
.top .glyph:active { opacity: 1; }
.top .regrow:hover, .top .regrow:focus-visible { transform: rotate(-200deg); }
.glyph .x, .glyph.off .wv { display: none; } .glyph.off .x { display: inline; }
@keyframes nudge { 0% { transform: rotate(0); opacity: .38; } 50% { opacity: .8; } 100% { transform: rotate(-360deg); opacity: .38; } }
.top .regrow.nudge { animation: nudge 1.8s cubic-bezier(.3,.6,.2,1) 1; }
.dormant .top .regrow { opacity: 0; }
.pin:focus-visible, .top .glyph:focus-visible, .top .mail a:focus-visible, .read .go:focus-visible { outline: 1px dashed var(--ember); outline-offset: 2px; }
/* without JavaScript (and for search engines) the list in the HTML is the page */
html:not(.js) #splash, html:not(.js) .top .ctl { display: none; }
html:not(.js) h1.sr { position: absolute; top: calc(20px + env(safe-area-inset-top, 0px)); left: 0; right: 0; width: auto; height: auto; clip: auto; margin: 0; text-align: center;
  font-family: var(--f-sc); font-weight: 400; font-size: 30px; letter-spacing: .04em; color: var(--bone); }
html:not(.js) .index { padding-top: calc(110px + env(safe-area-inset-top, 0px)); }
html:not(.js) .sub { top: calc(62px + env(safe-area-inset-top, 0px)); opacity: 1; }
html:not(.js) .top { top: auto; bottom: 0; padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); justify-content: center; }
.index { position: relative; z-index: 3; pointer-events: auto; max-width: 640px; height: 100%; box-sizing: border-box; overflow-y: auto; margin: 0 auto;
  padding: calc(64px + env(safe-area-inset-top, 0px)) max(20px, env(safe-area-inset-right, 0px)) 48px max(20px, env(safe-area-inset-left, 0px)); -webkit-user-select: text; user-select: text; }
.index ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 20px; }
.index a, .index .nm { font-family: var(--f-sc); font-size: 24px; letter-spacing: .05em; color: var(--bone); text-decoration: none; }
.index .tag { font-style: italic; color: var(--bone-dim); }
.beta, .index .beta { font-family: var(--f-mono); font-style: normal; font-size: .62em; letter-spacing: .14em; text-transform: uppercase; vertical-align: .18em; margin-left: .45em; padding: .18em .5em .1em; border: 1px solid currentColor; border-radius: 999px; opacity: .72; white-space: nowrap; text-shadow: none; }
/* On the plate the Beta mark hangs off the name, outside the label's box, so the name stays centred on its node. */
.pin .bn { position: relative; }
.pin .beta { position: absolute; left: 100%; top: .3em; font-size: 8.5px; margin-left: .7em; padding: .3em .6em .25em; }
/* short phones fold name and tag onto one line, so there the mark sits in the line instead of hanging over the tag */
.m-a:not(.t-4) .pins .pin .beta { position: static; margin-left: .5em; vertical-align: .3em; }
.index p { margin: 4px 0 0; color: var(--bone-dim); line-height: 1.45; }
.index .kin-link a { font-family: var(--f-text); font-style: italic; color: #f3dcc0; }

@keyframes sheen { to { background-position: -220% 0; } }
@media (max-width: 640px) { .pin { font-size: 17.5px; padding: 6px 6px; gap: 1px; } .pin small { font-size: 13.5px; } }
/* Cursor: a glowing spore instead of the arrow (fine pointers only). Every press, mouse or touch, sends out cascading rings. */
.orb, .ring { position: fixed; left: 0; top: 0; pointer-events: none; z-index: 80; border-radius: 50%; }
.orb { width: 14px; height: 14px; margin: -7px 0 0 -7px; opacity: 0; transition: opacity .4s, width .35s, height .35s, margin .35s;
  background: radial-gradient(circle, #fff 0 18%, rgba(185, 243, 232, .9) 34%, rgba(217, 184, 255, .35) 58%, transparent 72%);
  box-shadow: 0 0 14px 4px rgba(185, 243, 232, .35), 0 0 34px 10px rgba(217, 184, 255, .16); mix-blend-mode: screen; }
.orb::before { content: ""; position: absolute; inset: -6px; border-radius: 50%; opacity: .7;
  background: conic-gradient(from 0deg, #8fe3d4, #d9b8ff, #ffd9a8, #ff9bd0, #b9f3e8, #8fe3d4);
  -webkit-mask: radial-gradient(circle, transparent 0 56%, #000 60% 64%, transparent 70%); mask: radial-gradient(circle, transparent 0 56%, #000 60% 64%, transparent 70%);
  animation: spin 6s linear infinite; }
.orb.on { opacity: 1; }
.orb.hot { width: 26px; height: 26px; margin: -13px 0 0 -13px; }
.orb.down { width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; }
/* each ring is laid out at its full final size and shrunk at the start, so it is drawn sharp at every size (scaling a small ring up pixelates it) */
.ring { width: var(--d, 90px); height: var(--d, 90px); margin: calc(var(--d, 90px) / -2) 0 0 calc(var(--d, 90px) / -2); box-sizing: border-box; border: 1.25px solid rgba(239, 230, 214, .8); mix-blend-mode: screen;
  box-shadow: 0 0 10px rgba(185, 243, 232, .45), inset 0 0 8px rgba(217, 184, 255, .3); transform: scale(.05); opacity: 0; animation: ripple 1.3s cubic-bezier(.15, .7, .3, 1) forwards; }
.ring:nth-of-type(3n+1) { border-color: rgba(143, 227, 212, .85); } .ring:nth-of-type(3n+2) { border-color: rgba(217, 184, 255, .85); } .ring:nth-of-type(3n) { border-color: rgba(255, 217, 168, .85); }
@keyframes ripple { 0% { transform: scale(.05); opacity: 0; } 12% { opacity: 1; } 100% { transform: scale(1); opacity: 0; } }
@media (hover: hover) and (pointer: fine) { html.orbed, html.orbed * { cursor: none !important; } }
@media (prefers-reduced-motion: reduce) { .orb::before { animation: none; } .ring { animation-duration: .6s; } }
@keyframes spin { to { transform: rotate(1turn); } }
.embed .top > span:first-child { visibility: hidden; }
/* Previews: no box. The summary is written straight onto the plate under a soft cloud of dark, word by word,
   each word bleeding in like ink. Desktop: beside the project you hover. Phone: in the open water at the bottom. */
#splash { position: fixed; inset: 0; z-index: 200; background: #050507; transition: opacity 1.4s ease, filter 1.4s ease; }
#splash canvas { width: 100%; height: 100%; display: block; }
#splash.out { opacity: 0; filter: blur(8px) brightness(1.6); pointer-events: none; }
#fx { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; mix-blend-mode: screen; }
/* Kindred: other people's work. Its own warm, single-colour colony (never the iridescent threads), italic names, an arrow on each. */
#kin { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; mix-blend-mode: screen; }
.pin.door, .pin.kin { --hue: #ffcf96; font-family: var(--f-text); font-style: italic; letter-spacing: .01em; color: #f3dcc0; }
.pin.door { font-size: 21px; opacity: 0; transition: opacity 1.2s, color 1.6s, text-shadow 1.6s; }
.pin.door.lit { opacity: .85; text-shadow: 0 0 18px rgba(255, 190, 120, .35), 0 0 3px var(--soil); }
.pin.door small, .pin.kin small { font-family: var(--f-mono); font-style: normal; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: rgba(255, 207, 150, .75); }
.pin.door::before { inset: -22px -34px; background: radial-gradient(closest-side, rgba(5,5,7,.34), rgba(5,5,7,.18) 55%, transparent) !important; }
.pin.kin { font-size: 18px; opacity: 0; transition: opacity 1.4s, color 1.2s, text-shadow 1.2s, top .8s cubic-bezier(.2,.7,.2,1), left .8s cubic-bezier(.2,.7,.2,1); }
.pin.kin.in { opacity: .85; }
.pin.kin::after { content: "\2197\FE0E"; position: absolute; right: -4px; top: 3px; font-size: 11px; font-style: normal; color: #ffcf96; opacity: .7; }
/* the projects step fully out while Kindred is open (a blurred ghost layer caused rendering seams through the names on iOS) */
.kin-open .pins .pin:not(.door):not(.kin) { opacity: 0 !important; visibility: hidden; pointer-events: none; transition: opacity .8s, visibility 0s .8s; }
@media (max-width: 640px) { .pin.door { font-size: 18px; } .pin.kin { font-size: 15.5px; } }
.read { position: absolute; width: min(340px, calc(100% - 32px)); text-align: center; pointer-events: none; opacity: 0; transition: opacity .5s; z-index: 2; }
.read::before { content: ""; position: absolute; inset: -40px -50px; z-index: -1; background: radial-gradient(closest-side, rgba(5,5,7,.62), rgba(5,5,7,.36) 55%, transparent); }
.read .l, .read .soon { text-shadow: 0 0 6px var(--soil), 0 0 2px var(--soil); }
/* the name is gradient-clipped text, so a text-shadow would show through its clear fill and turn it grey; use a drop shadow instead */
.read .n { filter: drop-shadow(0 0 5px rgba(5,5,7,.85)) drop-shadow(0 0 12px color-mix(in srgb, var(--hue) 35%, transparent)); }
.read.on { opacity: 1; }
.read.inl.on { pointer-events: auto; -webkit-user-select: text; user-select: text; }
/* phones: a centred list; small caps tag under each name (.t-4), or beside it on short screens (.t-1) */
.m-a .pins .pin:not(.door) { display: block; font-size: 17px; padding: 5px 8px; }
.m-a .pins .pin:not(.door) small { display: inline; margin-left: .55em; font-size: 13.5px; }
.t-4 .pins .pin:not(.door) { display: flex; flex-direction: column; align-items: center; gap: calc(3px * var(--ls, 1)); line-height: 1.05; font-size: calc(16.5px * var(--ls, 1)); padding: 3px 10px; }
.t-4 .pins .pin:not(.door) small { display: block; margin: 0; font-family: var(--f-mono); font-style: normal; font-size: max(11px, calc(10.5px * var(--ls, 1))); letter-spacing: .16em; text-transform: uppercase; color: rgba(239, 230, 214, .78); }
/* phones: no repeated name or tag, a light veil only, and the other labels (and Kindred) step back while one is open */
.read.inl .k, .read.inl .n { display: none; }
.read.inl::before { inset: -26px -16px; background: radial-gradient(closest-side, rgba(5,5,7,.36), rgba(5,5,7,.18) 60%, transparent); }
body.reading-in .pin:not(.on) { opacity: 0 !important; pointer-events: none; transition: opacity .6s; }
#kin { transition: opacity .8s; } body.reading-in #kin { opacity: .18; }
.reading .pin:not(.on) { opacity: .1; }
.read .n, .read .k, .read .l { text-align: inherit; }
.read .k { font-family: var(--f-text); font-style: italic; font-size: 14px; color: var(--hue); text-shadow: 0 0 12px var(--hue); }
.read .n { font-family: var(--f-sc); font-size: 34px; line-height: 1.05; margin: 2px 0 8px; color: var(--bone);
  background: linear-gradient(100deg, var(--bone) 30%, var(--hue) 55%, #d9b8ff 75%, var(--bone)); background-size: 220% 100%; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; animation: sheen 6s linear infinite; }
.read .l { font-family: var(--f-text); font-size: 18.5px; line-height: 1.4; color: var(--bone); text-wrap: pretty; }
.read .l b { font-weight: 400; font-style: italic; color: var(--hue); }
.read .go { display: inline-block; background: none; border: 0; border-bottom: 1px solid currentColor; cursor: pointer; margin-top: 12px; font-family: var(--f-text); font-style: italic; font-size: 15px; color: var(--hue); text-decoration: none; pointer-events: auto; padding: 6px 4px; border-bottom: 1px solid currentColor; }
.read .soon { display: block; margin-top: 12px; font-family: var(--f-sc); font-size: 15px; letter-spacing: .08em; color: var(--hue); text-shadow: 0 0 14px var(--hue); }
.read .w { display: inline-block; opacity: 0; filter: blur(7px); transform: translateY(3px); animation: bleed .9s cubic-bezier(.2,.7,.2,1) forwards; animation-delay: calc(var(--i) * 28ms); }
@keyframes bleed { to { opacity: 1; filter: blur(0); transform: none; } }
@keyframes sheen { to { background-position: -220% 0; } }
.whisper { position: absolute; padding: 18px 34px; background: radial-gradient(closest-side, rgba(5,5,7,.82), rgba(5,5,7,.45) 60%, transparent); transform: translate(-50%, -50%); font-family: var(--f-sc); font-size: 18px; letter-spacing: .1em; color: var(--hue); text-shadow: 0 0 16px var(--hue), 0 0 4px var(--soil);
  white-space: nowrap; pointer-events: none; animation: rise 2.6s ease-out forwards; z-index: 3; }
@keyframes rise { 0% { opacity: 0; transform: translate(-50%, -30%); filter: blur(6px); } 18% { opacity: 1; filter: blur(0); } 70% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, -160%); filter: blur(4px); } }
.pin.gone { animation: spore-out 1.4s ease-out; }
@keyframes spore-out { 0% { filter: none; } 30% { filter: blur(4px); opacity: .1; letter-spacing: .5em; } 100% { filter: none; } }
/* Akasha on hover: its line re-types itself the way dictation lands, with a little live waveform */
.pin .wave { display: inline-flex; gap: 2px; align-items: center; height: 10px; margin-left: 6px; vertical-align: middle; }
.pin .wave i { width: 2px; height: 100%; background: var(--hue); border-radius: 1px; animation: talk .7s ease-in-out infinite alternate; }
.pin .wave i:nth-child(2) { animation-delay: -.2s; } .pin .wave i:nth-child(3) { animation-delay: -.45s; } .pin .wave i:nth-child(4) { animation-delay: -.1s; } .pin .wave i:nth-child(5) { animation-delay: -.6s; }
@keyframes talk { from { transform: scaleY(.2); } to { transform: scaleY(1); } }
.pin .caret { display: inline-block; width: 1px; height: 1em; background: var(--hue); margin-left: 1px; vertical-align: -2px; animation: blink .8s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
@media (max-width: 640px) { .read .n { font-size: 30px; } .read .l { font-size: 17px; } }
@media (prefers-reduced-motion: reduce) { .read .w { animation-duration: .01s; } .read .n { animation: none; } }
/* less motion: no ripples, no spore-out, no live waveform; whispers simply appear */
@media (prefers-reduced-motion: reduce) { .ring { display: none; } .pin.gone { animation: none; } .whisper { animation: none; opacity: 1; } .pin .wave i, .pin .caret { animation: none; } .top .glyph, .top .regrow.nudge { transition: none; animation: none; } .pin, .pin::before { transition: none; } }
