/* ilans.net/cv - generated by ~/cv-drafts/cv-build/build.py, edit there.
   Tokens are the site's own (same values as writing/writing.css). */

:root{
  --bg:#0b0b0d; --bg-elev:#121215; --bg-card:#131318; --bg-card-hi:#17171d;
  --ink:#ededea; --ink-muted:#a0a0a8; --ink-dim:#80808a; --ink-strong:#fff;
  --accent:#8a7bff; --accent-ink:#b9afff; --ok:#4ade80; --warn:#fbbf24;
  --line:#1f1f24; --line-strong:#2e2e35; --radius:14px;
  --serif:'Instrument Serif',Georgia,'Times New Roman',serif;
  --sans:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,'SF Mono',monospace;
  --ease:cubic-bezier(.16,1,.3,1);
  --nav-bg:rgba(11,11,13,.72);
  --sel-bg:rgba(138,123,255,.28); --sel-ink:#fff;
  --ambient:radial-gradient(60% 55% at 50% 0%, rgba(138,123,255,.10), rgba(138,123,255,0) 70%);
  --accent-wash:rgba(138,123,255,.08); --accent-line:rgba(138,123,255,.32);
  --btn-ink:#0b0b0d;
}
html[data-theme="light"]{
  --bg:#faf9f7; --bg-elev:#f1f0ed; --bg-card:#f4f3f0; --bg-card-hi:#efeeea;
  --ink:#17171c; --ink-muted:#54545e; --ink-dim:#7c7c86; --ink-strong:#000;
  --accent:#5b4de0; --accent-ink:#4d3ed1; --ok:#15803d; --warn:#b45309;
  --line:#e7e5e0; --line-strong:#d6d4cd;
  --nav-bg:rgba(250,249,247,.82);
  --sel-bg:rgba(91,77,224,.18); --sel-ink:#17171c;
  --ambient:radial-gradient(60% 55% at 50% 0%, rgba(91,77,224,.07), rgba(91,77,224,0) 70%);
  --accent-wash:rgba(91,77,224,.07); --accent-line:rgba(91,77,224,.28);
  --btn-ink:#faf9f7;
}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%; scroll-behavior:smooth}
body{
  background:var(--bg); color:var(--ink);
  font-family:var(--sans); font-size:16px; line-height:1.6;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
::selection{background:var(--sel-bg); color:var(--sel-ink)}
a{color:var(--accent-ink); text-decoration:none}
a:hover{text-decoration:underline; text-underline-offset:3px}
:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:4px}
body::before{content:""; position:fixed; inset:-30vh 0 auto 0; height:80vh; z-index:0; pointer-events:none; background:var(--ambient)}
body > *{position:relative; z-index:1}

.wrap{max-width:920px; margin:0 auto; padding-inline:clamp(16px,4vw,32px)}

/* ---------- nav (same pattern as /writing) */
nav.top{position:sticky; top:0; z-index:10; background:var(--nav-bg); backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); border-bottom:1px solid var(--line)}
nav.top .wrap{display:flex; align-items:center; justify-content:space-between; height:60px}
.logo{font-family:var(--mono); font-size:13px; font-weight:600; letter-spacing:.12em; color:var(--ink)}
.logo span{color:var(--accent)}
.logo:hover{text-decoration:none}
.nav-right{display:flex; align-items:center; gap:18px}
.back{display:inline-flex; align-items:center; gap:6px; font-size:14px; color:var(--ink-muted)}
.theme-toggle{display:grid; place-items:center; width:34px; height:34px; border-radius:50%; border:1px solid var(--line-strong); background:transparent; color:var(--ink-muted); cursor:pointer}
.theme-toggle svg{width:16px; height:16px}
.theme-toggle .icon-moon{display:none}
html[data-theme="light"] .theme-toggle .icon-sun{display:none}
html[data-theme="light"] .theme-toggle .icon-moon{display:block}

/* ---------- hero */
header.hero{padding-block:clamp(48px,9vw,96px) 32px}
.role{font-family:var(--mono); font-size:13px; letter-spacing:.14em; text-transform:uppercase; color:var(--accent-ink)}
h1{font-family:var(--serif); font-weight:400; font-size:clamp(48px,9vw,88px); line-height:1; letter-spacing:-.01em; color:var(--ink-strong); margin-top:14px}
.summary{max-width:640px; margin-top:22px; font-size:clamp(17px,2.2vw,19px); color:var(--ink-muted)}
.actions{display:flex; flex-wrap:wrap; gap:10px; margin-top:28px}
.btn{display:inline-flex; align-items:center; gap:8px; height:44px; padding-inline:18px; border-radius:999px; font-size:15px; font-weight:600; border:1px solid var(--line-strong); color:var(--ink); background:var(--bg-card)}
.btn:hover{text-decoration:none; border-color:var(--accent-line)}
/* same gradient as the hand-drawn squiggle under "creative production" on the ilans.net hero */
.btn.primary{background:linear-gradient(90deg,#8a7bff 0%,#c4b9ff 50%,#8a7bff 100%); background-size:200% 100%;
  background-position:0% 0; border-color:transparent; color:#0b0b0d; transition:background-position .6s var(--ease)}
.btn.primary:hover{background-position:100% 0}
.btn .pulse{width:8px; height:8px; border-radius:50%; background:currentColor; animation:pulse 2s ease-in-out infinite}
@keyframes pulse{50%{opacity:.35}}
.contact{display:flex; flex-wrap:wrap; gap:6px 18px; margin-top:22px; font-size:14px; color:var(--ink-dim)}
.contact a{color:var(--ink-muted)}
.variants{margin-top:10px; font-size:13px; color:var(--ink-dim)}

/* ---------- portrait, placement "hero" */
header.hero.with-art{display:grid; grid-template-columns:1fr auto; gap:clamp(24px,5vw,56px); align-items:center}
.portrait{width:clamp(180px,24vw,260px)}
.portrait img{display:block; width:100%; height:auto}
@media (max-width:760px){
  header.hero.with-art{grid-template-columns:1fr}
  .portrait{order:-1; width:104px}
}

/* ---------- portrait, placement "behind-apps" */
section.has-art{position:relative; isolation:isolate}
section.has-art .app a{background:color-mix(in srgb, var(--bg-card) 70%, transparent)}
.turntable{position:absolute; left:50%; top:52%; z-index:-1; pointer-events:none;
  width:min(720px, calc(100vw - 32px)); transform:translate(-50%,-50%); opacity:.22}
.turntable img{position:absolute; top:0; display:block; height:auto; max-width:none}
.turntable.grainy{filter:url(#tt-grain)}
.grain-defs{position:absolute; width:0; height:0; overflow:hidden}
@media (max-width:520px){ .turntable{display:none} }

/* ---------- stats */
.stats{display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin-top:8px}
/* each stat is a cube (cv.js rolls it): .face is the card, a second face waits on the bottom */
.stat{perspective:900px; --half:40px}
.stat .cube{position:relative; height:100%; transform-style:preserve-3d; transform:translateZ(calc(-1 * var(--half)))}
.stat .cube.rolling{transform:translateZ(calc(-1 * var(--half))) rotateX(90deg); transition:transform .75s cubic-bezier(.65,0,.25,1.2)}
.stat .face{height:100%; padding:18px; border:1px solid var(--line); border-radius:var(--radius); background:var(--bg-card);
  transform:translateZ(var(--half)); backface-visibility:hidden}
.stat .face.next{position:absolute; inset:0; transform:rotateX(-90deg) translateZ(var(--half))}
.stat b [data-up]{display:inline; margin:0; font:inherit; color:inherit}
.stat[data-faces] .face span{white-space:nowrap}
.stat b{display:block; font-size:clamp(19px,2.5vw,25px); line-height:1.15; font-weight:650; letter-spacing:-.02em; color:var(--ink-strong); white-space:nowrap}
.stat span{display:block; margin-top:6px; font-size:13px; color:var(--ink-dim)}

/* ---------- quote */
.quote{margin-top:40px; padding:4px 0 4px 22px; border-left:2px solid var(--accent)}
.quote blockquote{font-family:var(--serif); font-style:italic; font-size:clamp(22px,3vw,28px); line-height:1.3; color:var(--ink-strong)}
.quote figcaption{margin-top:12px; font-size:14px; color:var(--ink-dim)}
.quote figcaption b{color:var(--ink); font-weight:600}

/* ---------- sections */
section{padding-block:56px 8px}
h2{font-family:var(--mono); font-size:12px; font-weight:600; letter-spacing:.16em; text-transform:uppercase; color:var(--ink-dim); padding-bottom:12px; border-bottom:1px solid var(--line); margin-bottom:20px; display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap}
h2 .live-sum{letter-spacing:.04em; text-transform:none; color:var(--ink-muted)}
.note{font-size:14px; color:var(--ink-dim); margin:-8px 0 18px}

/* ---------- live apps */
.apps{display:grid; grid-template-columns:repeat(3,1fr); gap:10px; list-style:none}
.app a{display:block; height:100%; padding:16px; border:1px solid var(--line); border-radius:var(--radius); background:var(--bg-card); color:var(--ink); transition:border-color .2s var(--ease), background .2s var(--ease)}
.app a:hover{text-decoration:none; border-color:var(--accent-line); background:var(--bg-card-hi)}
.app .head{display:flex; align-items:center; gap:9px; font-weight:600; font-size:15px}
.app p{margin-top:6px; font-size:14px; line-height:1.5; color:var(--ink-muted)}
.app .host{display:block; margin-top:10px; font-family:var(--mono); font-size:12px; color:var(--ink-dim); overflow-wrap:anywhere}
.dot{flex:none; width:9px; height:9px; border-radius:50%; background:var(--line-strong); box-shadow:0 0 0 3px transparent; transition:background .3s, box-shadow .3s}
.app[data-status="checking"] .dot{animation:pulse 1.2s ease-in-out infinite}
.app[data-status="live"] .dot{background:var(--ok); box-shadow:0 0 0 3px color-mix(in srgb, var(--ok) 20%, transparent)}
.app[data-status="unreachable"] .dot{background:var(--warn)}
.more-apps{margin-top:14px; font-size:14px; color:var(--ink-dim)}

/* ---------- experience */
.job{padding-block:18px; border-bottom:1px solid var(--line)}
.job:first-of-type{padding-top:4px}
.job .top{display:flex; justify-content:space-between; align-items:baseline; gap:16px; flex-wrap:wrap}
.job h3{font-size:17px; font-weight:600; color:var(--ink-strong)}
.job .dates{font-family:var(--mono); font-size:13px; color:var(--ink-dim); white-space:nowrap}
.job .sub{margin-top:4px; font-size:15px; color:var(--ink-muted)}
.job ul{margin-top:10px; padding-left:18px; color:var(--ink-muted); font-size:15px}
.job li{margin-top:6px}
.job li::marker{color:var(--accent)}
.job b{color:var(--ink)}

/* ---------- worked with */
.logos{display:flex; flex-wrap:wrap; gap:12px 34px; align-items:center}
.logos .mark{font-family:var(--serif); font-size:clamp(22px,3vw,28px); color:var(--ink-dim); white-space:nowrap; transition:color .2s}
.logos .mark:hover{color:var(--ink)}
.logo-mask{display:inline-block; max-width:100%; background:var(--ink-dim);
  -webkit-mask:var(--src) center/contain no-repeat; mask:var(--src) center/contain no-repeat;
  transition:background .2s}
.logo-mask:hover{background:var(--ink)}
.logo-item{display:inline-flex; align-items:center; gap:9px}
.logo-name{font-weight:650; font-size:19px; letter-spacing:-.01em; color:var(--ink-dim)}

/* ---------- skills */
dl.skills{display:grid; grid-template-columns:140px 1fr; gap:14px 20px; font-size:15px}
dl.skills dt{font-family:var(--mono); font-size:13px; color:var(--ink-dim); padding-top:2px}
dl.skills dd{color:var(--ink-muted)}

footer{padding-block:56px 48px; margin-top:40px; border-top:1px solid var(--line); font-size:13px; color:var(--ink-dim)}

/* ---------- small screens */
@media (max-width:760px){
  .stats{grid-template-columns:repeat(2,1fr)}
  .apps{grid-template-columns:1fr 1fr}
}
@media (max-width:520px){
  .apps{grid-template-columns:1fr}
  dl.skills{grid-template-columns:1fr; gap:4px}
  dl.skills dd{margin-bottom:12px}
  .back .label{display:none}
}
@media (prefers-reduced-motion:reduce){
  *{animation:none !important; transition:none !important}
}
@media print{
  nav.top, .actions, body::before{display:none}
}

/* ---------- screen-reader only */
.sr-only{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0}

/* ---------- prepared-for banner (per-company link) */
.prepared{display:inline-flex; align-items:center; gap:8px; margin-top:14px; padding:6px 12px; border-radius:999px;
  border:1px solid var(--accent-line); background:var(--accent-wash); font-size:13px; color:var(--ink)}
.prepared b{font-weight:650}

/* ---------- shipping pulse: stat tile + 30-day columns (dataviz: single series, accent = last 7 days) */
section.pulse{padding-block:36px 0}
section.pulse .as-of{letter-spacing:.04em; text-transform:none; color:var(--ink-dim)}
.pulse-row{display:flex; align-items:flex-end; gap:28px; flex-wrap:wrap}
.pulse-fig b{display:block; font-size:clamp(34px,5vw,46px); line-height:1; font-weight:650; letter-spacing:-.02em; color:var(--ink-strong)}
.pulse-fig span{display:block; margin-top:6px; font-size:14px; color:var(--ink-muted)}
.pulse-fig .sub{font-size:13px; color:var(--ink-dim)}
.pulse-bars{--bar-old:#5f55ad; --bar-now:#8a7bff;
  flex:1 1 320px; min-width:0; height:72px; display:flex; align-items:flex-end; gap:2px; border-bottom:1px solid var(--line)}
html[data-theme="light"] .pulse-bars{--bar-old:#8378dc; --bar-now:#4d3ed1}
.pulse-bars .col{position:relative; flex:1 1 0; max-width:24px; height:100%; display:flex; align-items:flex-end; cursor:default}
.pulse-bars .col i{display:block; width:100%; border-radius:4px 4px 0 0; background:var(--bar-old)}
.pulse-bars .col.now i{background:var(--bar-now)}
.pulse-bars .col:hover i{filter:brightness(1.2)}
.pulse-bars .col::after{content:attr(data-tip); position:absolute; bottom:calc(100% + 8px); left:50%; transform:translateX(-50%);
  white-space:nowrap; padding:5px 9px; border-radius:6px; background:var(--bg-card-hi); border:1px solid var(--line-strong);
  font-size:12px; color:var(--ink); opacity:0; pointer-events:none; transition:opacity .15s; z-index:2}
.pulse-bars .col:hover::after, .pulse-bars .col:focus-visible::after{opacity:1}
.pulse-bars .col:nth-child(-n+6)::after{left:0; transform:none}
.pulse-bars .col:nth-last-child(-n+6)::after{left:auto; right:0; transform:none}

/* ---------- ask his AI */
.ask textarea{width:100%; min-height:96px; resize:vertical; padding:14px 16px; border-radius:var(--radius);
  border:1px solid var(--line-strong); background:var(--bg-card); color:var(--ink); font:inherit; font-size:15px; line-height:1.5}
.ask textarea:focus{outline:none; border-color:var(--accent-line); box-shadow:0 0 0 3px var(--accent-wash)}
.ask-row{display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:10px}
.ask-note{font-size:13px; color:var(--ink-dim); flex:1 1 280px}
.ask .btn[disabled]{opacity:.6; cursor:progress}
.ask-thread{margin-top:18px; display:grid; gap:12px}
.ask-q{justify-self:end; max-width:85%; padding:10px 14px; border-radius:14px 14px 4px 14px; background:var(--accent-wash);
  border:1px solid var(--accent-line); font-size:14px; color:var(--ink); white-space:pre-wrap; overflow-wrap:anywhere;
  max-height:9.5em; overflow:auto}
.ask-a{padding:14px 16px; border-radius:14px 14px 14px 4px; background:var(--bg-card); border:1px solid var(--line);
  font-size:15px; line-height:1.6; color:var(--ink); white-space:pre-wrap; overflow-wrap:anywhere}
.ask-a.thinking{color:var(--ink-dim)}
.ask-a .tools{display:flex; gap:10px; flex-wrap:wrap; margin-top:12px; white-space:normal}
.ask-a .tools button{height:34px; padding-inline:14px; border-radius:999px; border:1px solid var(--line-strong);
  background:transparent; color:var(--ink); font:inherit; font-size:13px; cursor:pointer}
.ask-a .tools button:hover{border-color:var(--accent-line)}
.lead{display:grid; gap:8px; margin-top:12px; white-space:normal}
.lead input, .lead textarea{padding:9px 12px; border-radius:10px; border:1px solid var(--line-strong); background:var(--bg); color:var(--ink); font:inherit; font-size:14px}
.lead .ok{color:var(--ok)}

/* app hover loops (record_clips.py): a floating preview above the card, desktop pointers only */
.app{position:relative}
.app .peek{position:absolute; left:0; right:0; bottom:calc(100% + 10px); aspect-ratio:16/10; z-index:5;
  border:1px solid var(--line-strong); border-radius:var(--radius); overflow:hidden; background:var(--bg-card-hi);
  box-shadow:0 22px 48px -14px rgba(0,0,0,.55); pointer-events:none; will-change:transform, opacity;
  --peek-y:16px; opacity:0; transform:translateY(var(--peek-y)) scale(.92); transform-origin:50% 100%;
  /* leaving: quick, under a short signal-loss burst (cv.js) */
  transition:opacity .2s ease-in, transform .25s ease-in}
.app.peeking .peek{opacity:1; transform:none;
  /* arriving: slow ease-out rise from the card edge while the signal locks on */
  transition:opacity .38s cubic-bezier(.16,1,.3,1), transform .55s cubic-bezier(.16,1,.3,1)}
.peek-defs{position:absolute; width:0; height:0}
.app .peek video{display:block; width:100%; height:100%; object-fit:cover; object-position:top}
.apps .app:nth-child(-n+3) .peek{bottom:auto; top:calc(100% + 10px); transform-origin:50% 0; --peek-y:-16px}
