/* turnertomlinson.com · shared styles.
   Deliberately single-theme dark: the ink needs a near-black page. Palette tokens are written
   onto :root by gate.js from src/data/look.json (and the hidden tuner), so the fallbacks
   below only matter if JS is off. */
@font-face{font-family:"JBM";src:url(/fonts/jbm-400.woff2) format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:"JBM";src:url(/fonts/jbm-700.woff2) format("woff2");font-weight:700;font-display:swap}
@font-face{font-family:"Inter Tight";src:url(/fonts/inter-tight-800.woff2) format("woff2");font-weight:800;font-display:swap}
@font-face{font-family:"Instrument Serif";src:url(/fonts/instr-400.woff2) format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:"Instrument Serif";src:url(/fonts/instr-400i.woff2) format("woff2");font-weight:400;font-style:italic;font-display:swap}

:root{
  --bg:#050505; --ink:#e9f3f1; --ink-rgb:233 243 241;
  --a:#33e6c8; --b:#2f7bff; --c:#9ff3ff; --a-rgb:51 230 200; --b-rgb:47 123 255; --c-rgb:159 243 255;
  --glow:.8; --e:0;
  --muted:rgb(var(--ink-rgb) / .74); --faint:rgb(var(--ink-rgb) / .62);
  --a-text:color-mix(in srgb, var(--a) 72%, #fff); /* accent for small text: lifted so it holds 4.5:1 */ --line:rgb(var(--ink-rgb) / .14);
  --panel:rgb(0 0 0 / .42);
  --serif:"Instrument Serif","Iowan Old Style",Georgia,serif;
  --mono:"JBM",ui-monospace,"SF Mono",Menlo,monospace;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
  color-scheme:dark;
}
*{box-sizing:border-box}
html{background:var(--bg);-webkit-text-size-adjust:100%}
html.leaving body{visibility:hidden}
body{margin:0;background:transparent;color:var(--ink);font:400 16.5px/1.62 var(--sans);-webkit-font-smoothing:antialiased;overflow-x:hidden;-webkit-tap-highlight-color:transparent}
a{color:inherit}
:focus-visible{outline:2px solid var(--a);outline-offset:3px;border-radius:4px}
.sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.wrap{max-width:1080px;margin:0 auto;padding:0 18px}

/* ---------- the smoke layer: behind everything, never takes input ---------- */
#smoke{position:fixed;inset:0;width:100%;height:100%;z-index:-1;display:block;pointer-events:none}
/* still smoke: reduced motion, no WebGL, or smoke dialled to zero */
html.still #smoke{display:none}
html.still body::before{content:"";position:fixed;inset:-10%;z-index:-1;pointer-events:none;
  background:
    radial-gradient(42% 34% at 22% 30%, rgb(var(--a-rgb) / .20), transparent 70%),
    radial-gradient(38% 30% at 78% 58%, rgb(var(--b-rgb) / .18), transparent 70%),
    radial-gradient(30% 26% at 40% 86%, rgb(var(--c-rgb) / .10), transparent 70%);
  filter:blur(18px)}
html.still.smoke-off body::before{display:none}

/* ---------- text over smoke ----------
   Headings are slightly transparent and screen-blended, so the smoke behind them lights the
   letters up. Body copy carries a dark halo so it reads with or without smoke. */
.glow{color:rgb(var(--ink-rgb) / .92);mix-blend-mode:screen;
  text-shadow:
    0 0 calc(2px + 5px*var(--glow)) rgb(var(--c-rgb) / calc(.22*var(--glow))),
    0 0 calc(6px + 26px*var(--glow)) rgb(var(--a-rgb) / calc(.16*var(--glow) + .5*var(--glow)*var(--e))),
    0 0 calc(18px + 50px*var(--glow)) rgb(var(--b-rgb) / calc(.10*var(--glow) + .32*var(--glow)*var(--e)))}
.glow em,.glow i{color:var(--a)}
.copy{text-shadow:0 0 1px rgb(0 0 0 / .9),0 0 10px rgb(0 0 0 / .8),0 0 26px rgb(0 0 0 / .55)}
.label{font:400 11px/1 var(--mono);letter-spacing:.22em;text-transform:uppercase;color:var(--a-text);margin:0 0 14px;text-shadow:0 0 12px rgb(0 0 0 / .8)}

/* ---------- fixed chrome (unused on the live site: there is no visible Tune button) ---------- */
.chrome{position:fixed;z-index:40;bottom:calc(10px + env(safe-area-inset-bottom));display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 15px;
  font:400 12.5px/1 var(--mono);letter-spacing:.04em;color:var(--ink);text-decoration:none;cursor:pointer;
  border:1px solid rgb(var(--a-rgb) / .35);border-radius:999px;background:rgb(0 0 0 / .62);
  -webkit-backdrop-filter:blur(10px) saturate(1.3);backdrop-filter:blur(10px) saturate(1.3);box-shadow:0 6px 22px rgb(0 0 0 / .5)}
.fin{left:max(10px,env(safe-area-inset-left))}
.tune-btn{right:max(10px,env(safe-area-inset-right))}
.tune-btn .dot{width:8px;height:8px;border-radius:50%;background:linear-gradient(135deg,var(--a),var(--b));box-shadow:0 0 10px var(--a)}
.tune-btn[aria-expanded="true"]{border-color:var(--a);color:var(--a)}

/* ---------- egg landing note ---------- */
.eggnote{position:fixed;z-index:45;top:calc(10px + env(safe-area-inset-top));left:50%;transform:translateX(-50%);width:min(440px,calc(100vw - 24px));
  margin:0;display:flex;align-items:center;gap:10px;padding:8px 6px 8px 14px;border:1px solid rgb(var(--a-rgb) / .4);border-radius:12px;
  background:rgb(0 0 0 / .78);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);font:400 12.5px/1.4 var(--mono);color:var(--ink)}
.eggnote[hidden]{display:none}
.eggnote button{margin-left:auto;flex:0 0 44px;height:44px;border:0;background:none;color:var(--muted);font-size:18px;cursor:pointer}

/* ---------- hero: the signal portrait. Not pinned, not scroll-driven: the intro is timed ---------- */
.hero{position:relative}
.pin{position:relative;display:flex;align-items:flex-start;padding-top:calc(22px + env(safe-area-inset-top))}
.pin .wrap{width:100%;display:grid;gap:14px}
.screen{position:relative;margin:0;background:var(--bg);overflow:hidden;touch-action:manipulation;-webkit-tap-highlight-color:transparent;
  box-shadow:0 0 0 1px rgb(var(--ink-rgb) / .08),0 24px 60px rgb(0 0 0 / .6)}
.screen img,.screen canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
.screen img{object-fit:cover}
.screen canvas{opacity:0;transition:opacity .35s}
html.js .screen img{opacity:0}
html.gl .screen.ready canvas{opacity:1}
html.nogl .screen img,.screen.lost img{opacity:1}
.screen .tag{position:absolute;left:0;top:0;z-index:2;font:400 9.5px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;background:rgb(0 0 0 / .78);color:var(--muted);padding:5px 7px;pointer-events:none}
.screen .tag.r{left:auto;right:0}
.screen .state{color:var(--a-text)}
html.nogl .screen .tag{display:none}
.portrait{width:min(100%,calc(100svh - 300px));min-width:min(100%,260px);aspect-ratio:1;justify-self:start}
.who h1{font:400 clamp(44px,12.5vw,104px)/.9 var(--serif);letter-spacing:-.02em;margin:0}
.who .role{font:400 12px/1 var(--mono);letter-spacing:.22em;text-transform:uppercase;color:var(--muted);margin:12px 0 0}
.ticker{font:400 12.5px/1.5 var(--mono);color:var(--muted);min-height:3em;margin:0;max-width:46ch}
.ticker b{color:var(--ink);font-weight:400}
.cap{font:400 11px/1.5 var(--mono);color:var(--muted);margin:4px 0 0}
@media (min-width:860px){
  .pin{align-items:center;padding-top:0}
  .pin .wrap{grid-template-columns:auto 1fr;align-items:center;gap:22px 52px}
  .portrait{width:min(560px,calc(100svh - 120px));grid-row:1/3}
  .who{align-self:end}
  .intro-cap{align-self:start}
}

/* ---------- sections ---------- */
.sec{padding:96px 0 40px;scroll-margin-top:30px}
h2{font:400 clamp(40px,10vw,72px)/1 var(--serif);margin:0 0 30px;letter-spacing:-.01em}
.tagline{font:400 clamp(32px,8.4vw,64px)/1.06 var(--serif);margin:0;max-width:18ch;text-wrap:balance}

/* Drowning Lessons splash (off by default; Tune toggles it) */
.dl{display:none}
html.show-dl .dl{display:block}
.dl-stage{position:relative;padding:34px 20px 40px;margin:0 -2px 56px;border-radius:18px;overflow:hidden;border:1px solid rgb(var(--a-rgb) / .22);
  background:radial-gradient(120% 80% at 50% 30%, rgb(var(--a-rgb) / .10), rgb(0 0 0 / .55) 70%);user-select:none;-webkit-user-select:none}
.dl-stage .water{position:absolute;inset:0;width:100%;height:100%;z-index:3;pointer-events:none;display:block}
.dl-kicker{font:400 11px/1.5 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--a-text);margin:0 0 14px;position:relative}
.dl-title{font:400 clamp(54px,15vw,112px)/.88 var(--serif);margin:0 0 20px;position:relative;color:var(--ink);
  text-shadow:0 0 18px rgb(var(--a-rgb) / .7),0 0 46px rgb(var(--a-rgb) / .4)}
.dl-title i{font-style:italic}
.dl-log{font:400 clamp(21px,5.4vw,30px)/1.32 var(--serif);margin:0;max-width:30ch;position:relative;text-wrap:pretty}
.dl-hint{position:relative;z-index:4;margin:20px 0 0;font:400 12px/1.4 var(--mono);letter-spacing:.08em;color:var(--muted)}
.dl-hint .dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--a);box-shadow:0 0 10px var(--a);margin-right:8px;vertical-align:1px;animation:pulse 2.2s ease-in-out infinite}
.dl.drowned .dl-hint{color:var(--b)}
@keyframes pulse{0%,100%{opacity:.35;transform:scale(.8)}50%{opacity:1;transform:scale(1.15)}}

/* books */
.books{list-style:none;margin:0;padding:0;display:grid;gap:40px}
.book{display:grid;grid-template-columns:minmax(0,44%) 1fr;gap:18px;align-items:start}
.book .screen{width:100%;max-width:220px}
.book h3{font:400 27px/1.04 var(--serif);margin:0 0 6px}
.meta{font:400 11px/1.45 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 10px}
.award{font:400 10.5px/1.45 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--a-text);margin:0 0 10px}
.book p.blurb{margin:0 0 14px;font-size:14.5px;line-height:1.55;color:rgb(var(--ink-rgb) / .86)}
.btn{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 16px;border:1px solid rgb(var(--a-rgb) / .45);border-radius:999px;text-decoration:none;
  font:400 13px/1 var(--mono);color:var(--ink);background:rgb(0 0 0 / .55);transition:border-color .25s,color .25s,box-shadow .25s}
.btn:hover{border-color:var(--a);color:var(--a);box-shadow:0 0 0 3px rgb(var(--a-rgb) / .15)}
.authorlink{margin:44px 0 0}
@media (min-width:860px){
  .books{grid-template-columns:repeat(4,1fr);gap:30px}
  .book{grid-template-columns:1fr;grid-template-rows:340px auto;gap:16px}
  .book .screen,.book .mystery{align-self:end}
}

/* the mystery book: a strobing cover with a question mark */
.mystery{position:relative;display:block;width:100%;max-width:220px;aspect-ratio:2/3;overflow:hidden;text-decoration:none;color:#fff;isolation:isolate;
  border-radius:2px 5px 5px 2px;box-shadow:0 0 0 1px rgb(var(--ink-rgb) / .14),0 24px 60px rgb(0 0 0 / .6)}
.mystery .mx-bg{position:absolute;inset:-40%;background:conic-gradient(from 0deg,var(--a),var(--b),var(--c),#ff3b6b,var(--a));animation:mxspin 6s linear infinite;filter:saturate(1.2)}
.mystery .mx-scan{position:absolute;inset:0;background:repeating-linear-gradient(0deg,rgb(0 0 0 / .32) 0 2px,transparent 2px 5px);mix-blend-mode:multiply}
.mystery .mx-strobe{position:absolute;inset:0;background:#000;animation:mxstrobe 1.9s steps(1) infinite}
.mystery .mx-q{position:absolute;inset:0;display:grid;place-items:center;font:400 clamp(110px,30vw,170px)/1 var(--serif);font-style:italic;color:#fff;
  text-shadow:0 0 30px rgb(255 255 255 / .6),4px 0 0 rgb(var(--b-rgb) / .8),-4px 0 0 rgb(var(--a-rgb) / .8);animation:mxjit 1.9s steps(1) infinite}
.mystery .mx-t{position:absolute;left:9%;right:9%;bottom:8%;font:800 clamp(13px,3.6vw,17px)/1.02 "Inter Tight",var(--sans);letter-spacing:-.01em;text-transform:uppercase;text-shadow:0 1px 8px rgb(0 0 0 / .6)}
.mystery .mx-au{position:absolute;left:9%;top:7%;font:400 9px/1 var(--mono);letter-spacing:.3em;text-transform:uppercase;opacity:.9}
.mystery .mx-sheen{position:absolute;inset:0;background:linear-gradient(115deg,transparent 30%,rgb(255 255 255 / .38) 46%,transparent 60%);background-size:250% 100%;animation:mxsheen 3.4s ease-in-out infinite;mix-blend-mode:soft-light}
@keyframes mxspin{to{transform:rotate(360deg)}}
@keyframes mxstrobe{0%{opacity:0}46%{opacity:.85}49%{opacity:0}71%{opacity:.6}73%{opacity:0}}
@keyframes mxjit{0%{transform:none}46%{transform:translate(3px,-2px) skewX(-6deg)}49%{transform:none}71%{transform:translate(-4px,1px)}73%{transform:none}}
@keyframes mxsheen{0%{background-position:120% 0}60%,100%{background-position:-60% 0}}
.vm-only{display:none!important}
html.show-vm .vm-only{display:revert!important}
html.show-vm .sidequest.vm-only{display:inline-block!important}
.sidequest{display:inline-block;font:400 10px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:#000;background:var(--a);padding:5px 8px;border-radius:999px;margin:0 0 10px}

/* about */
.bio{font:400 17px/1.75 var(--sans);margin:0 0 36px;max-width:62ch}
.bio em{color:var(--a-text)}
.links{list-style:none;margin:0;padding:0;max-width:640px;border-top:1px solid var(--line)}
.links li{border-bottom:1px solid var(--line)}
.links a{display:flex;align-items:center;gap:14px;min-height:60px;padding:10px 2px;text-decoration:none}
.links .t{font:400 24px/1.1 var(--serif)}
.links .d{display:block;font:400 12.5px/1.4 var(--mono);color:var(--muted);margin-top:3px}
.links .arr{margin-left:auto;color:var(--a);transition:transform .2s}
.links a:hover .arr{transform:translate(3px,-3px)}

.foot{padding:80px 0 120px}
.foot p{margin:0 0 6px;font:400 12px/1.6 var(--mono);color:var(--faint)}
.foot .end{font:400 clamp(24px,6vw,40px)/1.1 var(--serif);color:var(--ink);margin-bottom:14px}
.foot a{color:var(--muted)}

/* ---------- Tune: a bottom sheet that never covers more than ~half the phone ---------- */
.tune{position:fixed;z-index:60;left:0;right:0;bottom:0;max-height:52vh;max-height:52svh;display:flex;flex-direction:column;
  background:rgb(6 8 10 / .94);-webkit-backdrop-filter:blur(14px) saturate(1.2);backdrop-filter:blur(14px) saturate(1.2);
  border-top:1px solid rgb(var(--a-rgb) / .35);border-radius:16px 16px 0 0;box-shadow:0 -14px 40px rgb(0 0 0 / .55);
  font:400 12.5px/1.35 var(--mono);color:var(--ink);transform:translateY(105%);transition:transform .28s cubic-bezier(.2,.8,.2,1);visibility:hidden}
.tune.open{transform:none;visibility:visible}
@media (min-width:760px){.tune{left:auto;right:14px;bottom:66px;width:390px;max-height:min(78vh,720px);border-radius:16px;border:1px solid rgb(var(--a-rgb) / .35)}}
.tune-hd{display:flex;align-items:center;gap:6px;padding:6px 6px 6px 14px;border-bottom:1px solid var(--line);flex:0 0 auto}
.tune-hd b{font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:11.5px}
.tune-hd span{color:var(--muted);font-size:11px}
.tune-hd .sp{flex:1}
.tune button{font:inherit;color:inherit;cursor:pointer}
.tbtn{min-height:40px;padding:0 11px;border:1px solid var(--line);border-radius:999px;background:rgb(255 255 255 / .04)}
.tbtn:hover{border-color:var(--a)}
.tclose{width:44px;height:44px;border:0;background:none;font-size:20px!important;color:var(--muted)}
.tune-body{overflow:auto;padding:6px 14px calc(16px + env(safe-area-inset-bottom));-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.tgrp{margin:12px 0 2px;font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--a)}
.trow{display:grid;grid-template-columns:1fr auto;align-items:center;gap:2px 10px;padding:7px 0;border-bottom:1px solid rgb(var(--ink-rgb) / .06)}
.trow label{color:rgb(var(--ink-rgb) / .9)}
.trow output{color:var(--muted);font-variant-numeric:tabular-nums;min-width:4ch;text-align:right}
.trow input[type=range]{grid-column:1/-1;width:100%;height:32px;margin:0;accent-color:var(--a)}
.trow small{grid-column:1/-1;color:var(--faint);font-size:10.5px}
.tchk{display:flex;align-items:center;gap:10px;min-height:44px;cursor:pointer;border-bottom:1px solid rgb(var(--ink-rgb) / .06)}
.tchk input{width:20px;height:20px;accent-color:var(--a);margin:0}
.tseg{display:flex;border:1px solid var(--line);border-radius:999px;overflow:hidden;margin:6px 0 8px}
.tseg button{flex:1;min-height:40px;border:0;background:none;color:var(--muted)}
.tseg button[aria-pressed="true"]{background:var(--a);color:#000}
.presets{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin:8px 0 6px}
.presets button{min-height:44px;border:1px solid var(--line);border-radius:10px;background:none;display:flex;flex-direction:column;align-items:stretch;gap:5px;padding:6px;font-size:10.5px;color:var(--muted)}
.presets button i{display:block;height:10px;border-radius:6px}
.presets button[aria-pressed="true"]{border-color:var(--a);color:var(--ink)}
.colors{display:flex;gap:10px;align-items:center;padding:4px 0 8px;flex-wrap:wrap}
.colors label{display:flex;align-items:center;gap:6px;color:var(--muted)}
.colors input{width:44px;height:32px;border:1px solid var(--line);border-radius:8px;background:none;padding:0}
.tnote{color:var(--faint);font-size:10.5px;margin:10px 0 0}
.tcopy{width:100%;min-height:90px;margin-top:8px;font:11px/1.4 var(--mono);color:var(--ink);background:#000;border:1px solid var(--line);border-radius:8px}
.ttoast{min-height:1.4em;color:var(--a);font-size:11px;margin:6px 0 0}

/* ---------- reduced motion (system, or the Tune preview) ---------- */
html.rm .mystery .mx-bg,html.rm .mystery .mx-strobe,html.rm .mystery .mx-q,html.rm .mystery .mx-sheen,html.rm .dl-hint .dot{animation:none}
html.rm .mystery .mx-strobe{opacity:0}
html.rm .tune{transition:none}
@media (prefers-reduced-motion:reduce){
  .mystery .mx-bg,.mystery .mx-strobe,.mystery .mx-q,.mystery .mx-sheen,.dl-hint .dot{animation:none}
  .mystery .mx-strobe{opacity:0}
  .tune{transition:none}
}

/* small type over bright smoke keeps a dark halo too */
.who .role,.cap,.meta,.award,.links .d,.foot p,.fine,.dl-hint{text-shadow:0 0 1px rgb(0 0 0 / .9),0 0 8px rgb(0 0 0 / .85),0 0 18px rgb(0 0 0 / .6)}

/* no WebGL: the portrait is just the photo */
html.nogl .intro-cap{display:none}
