/* ─────────────────────────────────────────────
   Kapil Soni · portfolio
   ───────────────────────────────────────────── */
:root{
  --bg:#06070a;
  --bg-2:#0b0d13;
  --ink:#eef1f7;
  --muted:#8a93a8;
  --line:rgba(255,255,255,.09);
  --cy:#5ee7ff;
  --vi:#a78bfa;
  --wa:#ffb96b;
  --max:1240px;
  --pad:clamp(1.25rem,5vw,4.5rem);
  --f-display:"Space Grotesk",system-ui,sans-serif;
  --f-body:"Inter",system-ui,sans-serif;
  --f-mono:"JetBrains Mono",ui-monospace,monospace;
  --ease:cubic-bezier(.22,1,.36,1);
}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;overflow-x:clip}   /* full-bleed section scrims use -50vw insets;
                                                          clip (not hidden) contains them without
                                                          creating a scroll container */
body{
  background:var(--bg);color:var(--ink);
  font-family:var(--f-body);font-size:clamp(15px,.55vw + 13px,17px);
  line-height:1.65;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{max-width:100%;display:block;height:auto}
a{color:inherit;text-decoration:none}
ul,ol{list-style:none}
::selection{background:var(--cy);color:#04121a}

/* ── webgl canvas ── */
#gl{position:fixed;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;opacity:0;transition:opacity 1.2s ease}
#gl.on{opacity:1}
main{position:relative;z-index:2}

/* film grain + vignette so the 3D never feels flat */
.grain{
  position:fixed;inset:-50%;z-index:1;pointer-events:none;opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grain 8s steps(6) infinite;
}
@keyframes grain{0%{transform:translate(0,0)}20%{transform:translate(-3%,4%)}40%{transform:translate(4%,-2%)}60%{transform:translate(-2%,-4%)}80%{transform:translate(3%,3%)}100%{transform:translate(0,0)}}


/* ── cursor ── */
.cursor{position:fixed;top:0;left:0;z-index:90;pointer-events:none;mix-blend-mode:difference}
.cursor__dot{position:fixed;width:5px;height:5px;border-radius:50%;background:#fff;transform:translate(-50%,-50%)}
.cursor__ring{position:fixed;width:34px;height:34px;border:1px solid rgba(255,255,255,.55);border-radius:50%;transform:translate(-50%,-50%);transition:width .3s var(--ease),height .3s var(--ease),border-color .3s}
.cursor.hot .cursor__ring{width:58px;height:58px;border-color:var(--cy)}
@media (hover:none),(max-width:820px){.cursor{display:none}}

/* ── scroll progress ── */
.progress{position:fixed;top:0;left:0;height:2px;width:0;z-index:80;background:linear-gradient(90deg,var(--cy),var(--vi),var(--wa))}

/* ── nav ── */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:70;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:1.1rem var(--pad);
  transition:background .4s,backdrop-filter .4s,padding .4s,border-color .4s;
  border-bottom:1px solid transparent;
}
.nav.stuck{background:rgba(6,7,10,.72);backdrop-filter:blur(14px);border-color:var(--line);padding-block:.8rem}
.nav__logo{display:grid;place-items:center;border:1px solid var(--line);border-radius:999px;padding:.5rem .85rem;color:var(--ink)}
.nav__logo svg{width:34px;height:auto;display:block}
.nav__logo:hover{border-color:var(--cy);color:var(--cy)}
.nav__links{display:flex;gap:1.8rem;font-size:.85rem;color:var(--muted)}
.nav__links a{position:relative;transition:color .3s}
.nav__links a::after{content:"";position:absolute;left:0;bottom:-4px;width:0;height:1px;background:var(--cy);transition:width .35s var(--ease)}
.nav__links a:hover,.nav__links a.active{color:var(--ink)}
.nav__links a:hover::after,.nav__links a.active::after{width:100%}
.nav__cta{font-size:.82rem;border:1px solid var(--line);border-radius:999px;padding:.5rem 1.05rem;transition:.3s}
.nav__cta:hover{background:var(--ink);color:var(--bg);border-color:var(--ink)}
.nav__burger{display:none;background:none;border:0;cursor:pointer;width:34px;height:34px;position:relative}
.nav__burger i{position:absolute;left:6px;right:6px;height:1.5px;background:var(--ink);transition:.35s var(--ease)}
.nav__burger i:first-child{top:13px}.nav__burger i:last-child{top:20px}
.nav__burger.open i:first-child{top:16px;transform:rotate(45deg)}
.nav__burger.open i:last-child{top:16px;transform:rotate(-45deg)}

.menu{
  position:fixed;inset:0;z-index:60;background:rgba(6,7,10,.97);backdrop-filter:blur(20px);
  display:flex;flex-direction:column;justify-content:center;gap:.4rem;padding:0 var(--pad);
  clip-path:inset(0 0 100% 0);transition:clip-path .7s var(--ease);
}
.menu.open{clip-path:inset(0 0 0 0)}
.menu a{font-family:var(--f-display);font-size:clamp(2rem,9vw,3.4rem);font-weight:500;display:flex;align-items:baseline;gap:1rem;padding:.25rem 0;transition:color .3s;color:var(--muted)}
.menu a:hover{color:var(--ink)}
.menu a span{font-family:var(--f-mono);font-size:.7rem;color:var(--cy)}

@media (max-width:900px){
  .nav__links,.nav__cta{display:none}
  .nav__burger{display:block}
}

/* ── layout ── */
.sec{max-width:var(--max);margin-inline:auto;padding:clamp(5rem,12vw,9rem) var(--pad)}
.sec__label{font-family:var(--f-mono);font-size:.72rem;letter-spacing:.22em;text-transform:uppercase;color:var(--cy);margin-bottom:1.6rem}
.sec__title{font-family:var(--f-display);font-weight:500;font-size:clamp(2rem,6vw,4rem);line-height:1.05;letter-spacing:-.02em;margin-bottom:3rem}

/* ── hero ── */
.hero{min-height:100svh;display:grid;place-items:center;position:relative;padding:6rem var(--pad) 4rem;isolation:isolate}
/* keeps the particle cloud from eating the copy */
.hero::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(100deg,var(--bg) 8%,rgba(6,7,10,.86) 34%,rgba(6,7,10,.28) 60%,transparent 78%)}
@media(max-width:900px){.hero::before{background:radial-gradient(120% 70% at 50% 45%,rgba(6,7,10,.86),rgba(6,7,10,.5) 70%,transparent)}}
.hero__inner{max-width:var(--max);width:100%;margin-inline:auto}
.hero__eyebrow{font-family:var(--f-mono);font-size:.74rem;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);margin-bottom:1.4rem}
.hero__eyebrow::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--cy);margin-right:.7rem;vertical-align:middle;animation:pulse 2.4s infinite}
@keyframes pulse{0%,100%{opacity:1;box-shadow:0 0 0 0 rgba(94,231,255,.55)}70%{opacity:.7;box-shadow:0 0 0 9px rgba(94,231,255,0)}}
.hero__title{font-family:var(--f-display);font-weight:700;letter-spacing:-.045em;line-height:.88;
  font-size:clamp(3.1rem,13.5vw,10.5rem);margin-bottom:clamp(1rem,2.2vw,1.9rem);padding-bottom:.06em}
.hero__title .char{display:inline-block;will-change:transform}
.hero__role{font-family:var(--f-mono);font-size:clamp(.85rem,2.2vw,1.15rem);color:var(--cy);letter-spacing:.06em;margin-bottom:1.6rem;min-height:1.6em}
.hero__blurb{max-width:56ch;color:var(--muted);font-size:clamp(.98rem,1.4vw,1.1rem)}
.hero__actions{display:flex;flex-wrap:wrap;gap:.9rem;margin-top:2.4rem}
.btn{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:.82rem 1.7rem;font-size:.9rem;transition:.35s var(--ease);backdrop-filter:blur(6px)}
.btn:hover{border-color:var(--ink);transform:translateY(-2px)}
.btn--primary{background:var(--ink);color:var(--bg);border-color:var(--ink);font-weight:500}
.btn--primary:hover{background:var(--cy);border-color:var(--cy);color:#04121a}
.hero__scroll{position:absolute;bottom:1.8rem;left:50%;transform:translateX(-50%);font-family:var(--f-mono);font-size:.66rem;letter-spacing:.28em;text-transform:uppercase;color:var(--muted);display:flex;flex-direction:column;align-items:center;gap:.6rem}
.hero__scroll i{width:1px;height:40px;background:linear-gradient(var(--cy),transparent);animation:drop 2s var(--ease) infinite}
@keyframes drop{0%{transform:scaleY(0);transform-origin:top}50%{transform:scaleY(1);transform-origin:top}51%{transform:scaleY(1);transform-origin:bottom}100%{transform:scaleY(0);transform-origin:bottom}}
.hero__side{position:absolute;right:var(--pad);bottom:2rem;display:flex;flex-direction:column;gap:1rem;font-family:var(--f-mono);font-size:.68rem;letter-spacing:.14em;color:var(--muted)}
.hero__side a:hover{color:var(--cy)}
@media(max-width:820px){.hero__side{display:none}}

/* ── marquee ── */
.marquee{overflow:hidden;border-block:1px solid var(--line);padding:1rem 0;background:rgba(11,13,19,.55);backdrop-filter:blur(6px)}
.marquee__track{display:flex;gap:2.2rem;width:max-content;animation:slide 38s linear infinite;font-family:var(--f-display);font-size:clamp(1.1rem,3vw,1.9rem);letter-spacing:-.01em;color:var(--muted)}
.marquee__track b{color:var(--cy);font-size:.55em;align-self:center}
@keyframes slide{to{transform:translateX(-50%)}}

/* ── about ── */
.about__grid{display:grid;gap:clamp(2rem,5vw,4rem)}
.about__lead{font-family:var(--f-display);font-size:clamp(1.5rem,4.2vw,2.9rem);line-height:1.18;letter-spacing:-.025em;max-width:22ch}
.about__lead .word{display:inline-block}
.about__body{display:grid;gap:1.15rem;max-width:62ch;color:var(--muted);margin-left:auto}
.about__body p{font-size:1.02rem}
.about__stats{display:grid;grid-template-columns:repeat(2,1fr);gap:1.5rem 1.2rem;margin-top:1.6rem;padding-top:1.8rem;border-top:1px solid var(--line)}
.about__stats b{display:block;font-family:var(--f-display);font-size:clamp(1.9rem,5vw,2.8rem);color:var(--ink);line-height:1;font-weight:500}
.about__stats span{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
@media(min-width:960px){.about__grid{grid-template-columns:1fr 1fr;align-items:start}}

/* ── timeline ── */
.timeline{position:relative;display:grid;gap:clamp(2.5rem,5vw,4rem)}
.timeline::before{content:"";position:absolute;left:0;top:.6rem;bottom:.6rem;width:1px;background:linear-gradient(var(--cy),var(--vi),transparent)}
.job{position:relative;padding-left:clamp(1.6rem,4vw,3rem);display:grid;gap:.4rem}
.job::before{content:"";position:absolute;left:-4px;top:.65rem;width:9px;height:9px;border-radius:50%;background:var(--bg);border:1.5px solid var(--cy);transition:.4s}
.job:hover::before{background:var(--cy);box-shadow:0 0 16px var(--cy)}
.job__when{font-family:var(--f-mono);font-size:.74rem;letter-spacing:.12em;color:var(--cy);text-transform:uppercase}
.job h3{font-family:var(--f-display);font-size:clamp(1.25rem,3vw,1.7rem);font-weight:500;letter-spacing:-.02em}
.job__org{color:var(--muted);font-size:.92rem;margin-bottom:.7rem}
.job ul{display:grid;gap:.5rem;max-width:70ch}
.job li{position:relative;padding-left:1.1rem;color:var(--muted);font-size:.97rem}
.job li::before{content:"\25B8";position:absolute;left:0;color:var(--vi);font-size:.75em;top:.32em}
@media(min-width:960px){.job{grid-template-columns:200px 1fr;gap:2rem}.job__when{padding-top:.35rem}}

/* ── tags ── */
.tags{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:1rem}
.tags span{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.05em;border:1px solid var(--line);border-radius:999px;padding:.24rem .65rem;color:var(--muted);transition:.3s}
.job:hover .tags span{border-color:rgba(94,231,255,.35);color:var(--ink)}

/* ── project cards ── */
.card__no{font-family:var(--f-mono);font-size:.7rem;color:var(--vi);letter-spacing:.2em}
.card__kind{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-bottom:.85rem}

/* ── stack ── */

/* ── hobbies ── */
.offline__lead{color:var(--muted);margin-top:-2rem;margin-bottom:2.6rem;font-size:1.05rem}
.hobbies{display:grid;gap:1.1rem;grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.hobby{border:1px solid var(--line);border-radius:18px;padding:1.7rem 1.5rem;background:linear-gradient(160deg,rgba(255,185,107,.06),rgba(255,255,255,.012));transition:border-color .4s,transform .4s;transform-style:preserve-3d}
.hobby:hover{border-color:rgba(255,185,107,.45)}
.hobby__ico{display:grid;place-items:center;width:40px;height:40px;border-radius:12px;border:1px solid var(--line);color:var(--wa);font-size:.95rem;margin-bottom:1.1rem}
.hobby h3{font-family:var(--f-display);font-size:1.28rem;font-weight:500;margin-bottom:.5rem}
.hobby p{color:var(--muted);font-size:.94rem;margin-bottom:1rem}
.hobby__link{font-family:var(--f-mono);font-size:.74rem;letter-spacing:.08em;color:var(--wa);transition:.3s}
.hobby__link:hover{letter-spacing:.14em}

/* ── contact ── */
.contact{text-align:center}
.contact__big{font-family:var(--f-display);font-weight:700;letter-spacing:-.04em;line-height:1;font-size:clamp(2.4rem,10vw,6.5rem);margin-bottom:1rem}
.contact__big .word{display:inline-block}
.contact__sub{color:var(--muted);max-width:52ch;margin:0 auto 2.6rem}
.contact__mail{display:inline-block;font-family:var(--f-display);font-size:clamp(1rem,3.4vw,1.9rem);border-bottom:1px solid var(--line);padding-bottom:.35rem;transition:.35s var(--ease)}
.contact__mail:hover{color:var(--cy);border-color:var(--cy);letter-spacing:.01em}
.contact__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:1.4rem;margin-top:4rem;text-align:left;border-top:1px solid var(--line);padding-top:2rem}
.contact__list span{display:block;font-family:var(--f-mono);font-size:.66rem;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);margin-bottom:.3rem}
.contact__list a:hover{color:var(--cy)}

/* ── footer ── */
.foot{max-width:var(--max);margin-inline:auto;padding:2rem var(--pad) 3rem;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;font-family:var(--f-mono);font-size:.72rem;letter-spacing:.08em;color:var(--muted)}
.foot a:hover{color:var(--cy)}

/* ── reveal defaults (JS overrides; keeps content visible without JS) ── */
.js [data-reveal],.js [data-split],.js [data-split-words]{opacity:0}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  .js [data-reveal],.js [data-split],.js [data-split-words]{opacity:1!important;transform:none!important}
  #gl{opacity:.5}
}

/* ── earlier work (compact list under the featured cards) ── */
.earlier__label{margin-top:3.4rem;color:var(--muted)}
.earlier{display:grid;gap:0;border-top:1px solid var(--line)}
.earlier li{display:grid;gap:.15rem .9rem;padding:1rem .2rem;border-bottom:1px solid var(--line);transition:padding-left .35s var(--ease),background .35s}
.earlier li:hover{padding-left:.9rem;background:rgba(255,255,255,.02)}
.earlier b{font-family:var(--f-display);font-weight:500;font-size:1.02rem}
.earlier span{color:var(--muted);font-size:.93rem}
.earlier i{font-family:var(--f-mono);font-style:normal;font-size:.68rem;letter-spacing:.06em;color:var(--cy);opacity:.8}
@media(min-width:900px){
  .earlier li{grid-template-columns:230px 1fr 250px;align-items:baseline}
  .earlier i{text-align:right}
}

/* ── how I work ── */
.steps{display:grid;gap:1.1rem;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));margin-bottom:clamp(4rem,9vw,7rem)}
.steps li{border-top:1px solid var(--line);padding-top:1.2rem}
.steps__no{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.2em;color:var(--cy)}
.steps h3{font-family:var(--f-display);font-size:1.28rem;font-weight:500;margin:.55rem 0 .5rem;letter-spacing:-.02em}
.steps p{color:var(--muted);font-size:.95rem}

.process__second{margin-bottom:1.2rem}
.process__lead{color:var(--muted);max-width:66ch;margin-bottom:2.4rem;font-size:1.02rem}
.offers{display:grid;gap:1.1rem;grid-template-columns:repeat(auto-fit,minmax(270px,1fr))}
.offer{position:relative;border:1px solid var(--line);border-radius:18px;padding:1.7rem 1.5rem;
  background:linear-gradient(160deg,rgba(167,139,250,.07),rgba(255,255,255,.012));
  backdrop-filter:blur(10px);transform-style:preserve-3d;transition:border-color .4s,box-shadow .4s}
.offer:hover{border-color:rgba(167,139,250,.5);box-shadow:0 24px 60px -32px rgba(167,139,250,.45)}
.offer__len{display:inline-block;font-family:var(--f-mono);font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--vi);border:1px solid rgba(167,139,250,.32);border-radius:999px;padding:.24rem .7rem;margin-bottom:1rem}
.offer h3{font-family:var(--f-display);font-size:1.3rem;font-weight:500;letter-spacing:-.02em;margin-bottom:.5rem}
.offer p{color:var(--muted);font-size:.94rem}
.process__foot{margin-top:2.2rem;color:var(--muted);font-size:.97rem;display:flex;flex-wrap:wrap;gap:.2rem .8rem;align-items:baseline}
.process__foot a{color:var(--cy);font-family:var(--f-mono);font-size:.82rem;letter-spacing:.04em;display:inline-block}
.process__foot a:hover{color:var(--ink)}

/* hero blurb emphasis */
.hero__blurb b{color:var(--ink);font-weight:500}
.job li b{color:var(--ink);font-weight:500}

/* ── references ── */
.refs__lead{color:var(--muted);margin-top:-2rem;margin-bottom:2.6rem;font-size:1.05rem}
.quotes{display:grid;gap:1.1rem;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr))}
.quote{position:relative;display:flex;flex-direction:column;justify-content:space-between;gap:1.4rem;
  border:1px solid var(--line);border-radius:18px;padding:1.8rem 1.6rem 1.5rem;
  background:linear-gradient(160deg,rgba(255,255,255,.045),rgba(255,255,255,.012));
  backdrop-filter:blur(10px);transform-style:preserve-3d;transition:border-color .4s,box-shadow .4s}
.quote::before{content:"\201C";position:absolute;top:.1rem;right:1.1rem;font-family:var(--f-display);
  font-size:5rem;line-height:1;color:var(--cy);opacity:.14;pointer-events:none}
.quote:hover{border-color:rgba(94,231,255,.38);box-shadow:0 24px 60px -32px rgba(94,231,255,.35)}
.quote blockquote{display:grid;gap:.8rem}
.quote blockquote p{color:var(--muted);font-size:.95rem}
.quote figcaption{display:flex;align-items:center;gap:.9rem;border-top:1px solid var(--line);padding-top:1.1rem}
.quote figcaption .avatar{width:52px;height:52px;flex:none;border-radius:50%;overflow:hidden;
  border:1px solid var(--line);display:block}
.quote figcaption .avatar img{width:100%;height:100%;object-fit:cover;display:block;
  filter:grayscale(1) contrast(1.05);transition:filter .45s}
.quote:hover figcaption .avatar img{filter:none}
/* Khushboo's photo is full-body, so an un-cropped 52px avatar shows a torso.
   Scale up and offset so her face lands in the middle of the circle.
   Specificity must match `.quote figcaption .avatar img` above, or width/height
   lose and only the negative margin lands, pushing the photo out of frame. */
.quote figcaption .avatar--tight img{width:290%;max-width:none;height:290%;
  margin-left:-98%;margin-top:-2%}
.quote figcaption span{display:grid;line-height:1.4}
.quote figcaption b{font-family:var(--f-display);font-weight:500;font-size:1rem;color:var(--ink)}
.quote figcaption span{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.08em;color:var(--muted)}

/* ── portrait ── */
.about__intro{display:grid;gap:2rem;align-content:start;justify-items:start}
.portrait{position:relative;display:grid;gap:.95rem;width:100%;max-width:340px;transform-style:preserve-3d}
.portrait__frame{position:relative;display:block;border-radius:24px;padding:1px;
  background:linear-gradient(150deg,rgba(94,231,255,.6),rgba(167,139,250,.4) 45%,rgba(255,255,255,.07) 80%)}
.portrait__frame::after{content:"";position:absolute;inset:-14%;z-index:-1;pointer-events:none;
  background:radial-gradient(closest-side,rgba(94,231,255,.2),transparent 72%);filter:blur(20px)}
.portrait img{display:block;width:100%;aspect-ratio:1;object-fit:cover;border-radius:23px;
  transition:filter .5s var(--ease)}
.portrait figcaption{display:flex;align-items:center;gap:.55rem;font-family:var(--f-mono);
  font-size:.7rem;letter-spacing:.13em;text-transform:uppercase;color:var(--muted)}
.portrait figcaption i{width:7px;height:7px;border-radius:50%;background:var(--cy);flex:none;
  animation:pulse 2.4s infinite}
@media (max-width:959px){.portrait{max-width:280px}}

/* ── failure floor ──────────────────────────────────────────────────
   The `js` class is set by main.js only after it confirms gsap loaded,
   so if the CDN is blocked or the script never runs, none of the
   hide-until-animated rules above apply and the page renders as plain
   HTML with nothing covering it. */

/* ── focus ──────────────────────────────────────────────────────────
   Nothing here had a focus style. Keyboard users could not see where
   they were anywhere on the page. */
:where(a, button, [tabindex]):focus-visible{
  outline:2px solid var(--cy);
  outline-offset:3px;
  border-radius:6px;
}
.nav__logo:focus-visible,.nav__cta:focus-visible,.btn:focus-visible,
.contact__mail:focus-visible{outline-offset:4px;border-radius:999px}
.offer:focus-within,.quote:focus-within{border-color:var(--cy)}

.skip{
  position:fixed;top:.6rem;left:.6rem;z-index:200;
  padding:.7rem 1.1rem;border-radius:10px;
  background:var(--ink);color:var(--bg);font-size:.85rem;font-weight:500;
  transform:translateY(-160%);transition:transform .25s var(--ease);
}
/* :focus, not :focus-visible — a skip link is only ever reached by keyboard,
   and it must appear for programmatic focus too (e.g. a screen reader jumping to it) */
.skip:focus{transform:translateY(0);outline:2px solid var(--cy);outline-offset:3px}

/* ── section ground ─────────────────────────────────────────────────
   Only .hero had a scrim; every other section rendered its copy
   directly over the particle cloud, which sits on the right — exactly
   where the body columns are. Each section now carries its own veil,
   masked at top and bottom so the cloud still breathes between them.
   The scene stays put and the content passes over it. */
.sec{position:relative;isolation:isolate}
.sec::before{
  content:"";position:absolute;inset:0 -50vw;z-index:-1;pointer-events:none;
  background:rgba(6,7,10,.74);
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 7%,#000 93%,transparent 100%);
  mask-image:linear-gradient(to bottom,transparent 0,#000 7%,#000 93%,transparent 100%);
}
/* the inverted section paints its own ground */
.sec--light::before{display:none}


/* ── the move ── */
.journey{border:1px solid var(--line);border-radius:18px;padding:1.6rem 1.5rem 1.2rem;
  background:linear-gradient(160deg,rgba(94,231,255,.05),rgba(255,255,255,.012));overflow:hidden}
.journey svg{width:100%;height:auto;display:block;overflow:visible}
.journey .j-city{font-family:var(--f-mono);font-size:15px;letter-spacing:.18em;fill:var(--ink)}
.journey .j-sub{font-family:var(--f-mono);font-size:11px;letter-spacing:.1em;fill:var(--muted)}
.journey .j-cap{font-family:var(--f-mono);font-size:11px;letter-spacing:.22em;fill:var(--muted)}
.journey .j-arc{fill:none;stroke:var(--cy);stroke-width:1.5;stroke-dasharray:7 7;opacity:.85}
.journey .j-dot{fill:var(--cy)}
.journey .j-dot--ghost{fill:var(--ink);opacity:.9}
@media (prefers-reduced-motion:no-preference){
  .journey .j-arc{stroke-dashoffset:0;animation:j-drift 3.2s linear infinite}
  @keyframes j-drift{to{stroke-dashoffset:-28}}
}
@media (max-width:620px){
  .journey .j-city{font-size:19px}
  .journey .j-sub,.journey .j-cap{font-size:14px}
}
.hobby__soon{font-family:var(--f-mono);font-size:.72rem;letter-spacing:.08em;color:var(--muted);opacity:.75}

/* ── the one inverted section ───────────────────────────────────────
   Nine sections shared one treatment: mono label, big left title, grey
   copy, same cloud behind. By the fourth the eye stops registering
   change. The engagements block flips to light, which is also where a
   buyer is deciding — so it gets the page's only bright ground.
   Everything below is a token override; the components are untouched. */
.sec--light{
  --ink:#0c1017;
  --muted:#4d5768;
  --line:rgba(10,14,22,.16);
  --cy:#0b6f83;          /* #5ee7ff is 1.5:1 on white; this is 5.6:1 */
  --vi:#6b4fd6;
  color:var(--ink);
}
.sec--light::before{
  display:block;background:#eef1f6;-webkit-mask-image:none;mask-image:none;
}
.sec--light .offer{
  background:linear-gradient(160deg,rgba(107,79,214,.07),rgba(12,16,23,.02));
  backdrop-filter:none;
}
.sec--light .offer:hover{border-color:rgba(107,79,214,.5);box-shadow:0 22px 50px -30px rgba(12,16,23,.45)}
.sec--light .offer__len{border-color:rgba(107,79,214,.32)}
.sec--light .steps li{border-top-color:var(--line)}
.sec--light .process__foot a{color:var(--cy)}
.sec--light .process__foot a:hover{color:var(--ink)}

.offer__meta{display:grid;gap:.35rem;margin:.9rem 0 1.1rem;padding:.85rem 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
/* one row carrying a sentence, not a number: stack it and read left to right */
.offer__meta > div{display:grid;gap:.3rem}
.offer__meta dt{font-family:var(--f-mono);font-size:.66rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted)}
.offer__meta dd{font-size:.9rem;color:var(--ink);line-height:1.5}
.process__foot b{color:var(--ink);font-weight:600}
.about__source{margin-top:1.1rem;font-family:var(--f-mono);font-size:.7rem;line-height:1.7;
  letter-spacing:.04em;color:var(--muted);opacity:.8}

/* ── project schematics (hoisted out of the inline SVGs so four copies
   of .p/.s/.q/text cannot leak into the rest of the document) ── */
.schem text{font-family:ui-monospace,"JetBrains Mono",SFMono-Regular,Menlo,monospace;
  font-size:8px;letter-spacing:.6px;text-transform:uppercase;text-anchor:middle}
.schem .cap{font-size:6.5px;letter-spacing:.5px}
.schem .nd{fill:none;stroke:currentColor;stroke:var(--ink,currentColor);stroke-width:1.1;opacity:.5}
.schem .bound{fill:none;stroke:#8a93a8;stroke:var(--muted,#8a93a8);stroke-width:1;stroke-dasharray:3 3;opacity:.45}
.schem .p{fill:none;stroke:#5ee7ff;stroke:var(--cy,#5ee7ff);stroke-width:1.3}
.schem .s{fill:none;stroke:#a78bfa;stroke:var(--vi,#a78bfa);stroke-width:1.3}
.schem .q{stroke-dasharray:4 3}
.schem .lb{fill:#8a93a8;fill:var(--muted,#8a93a8);stroke:none}
.schem .lk{fill:currentColor;stroke:none;opacity:.94}
.schem .dot{fill:#5ee7ff;fill:var(--cy,#5ee7ff);stroke:none}
.card__schem{margin:0 0 1.4rem;padding:0}
.card__schem svg{width:100%;height:auto;display:block;color:var(--ink)}


.stack__note{color:var(--muted);margin:-2rem 0 1.6rem;font-size:1rem}
/* ── hero: a third, quieter action for the contract path ── */
.btn--quiet{border-color:transparent;color:var(--muted);padding-inline:.9rem}
.btn--quiet:hover{color:var(--ink);border-color:var(--line)}

.projects__lead{color:var(--muted);margin:-2rem 0 2.6rem;max-width:70ch;font-size:1.02rem}
.projects__lead a{color:var(--cy);border-bottom:1px solid rgba(94,231,255,.35)}
.projects__lead a:hover{color:var(--ink);border-color:var(--ink)}
.process__lead a{color:var(--cy);border-bottom:1px solid rgba(11,111,131,.4)}
.sec--light .process__lead a{border-bottom-color:rgba(11,111,131,.45)}
.process__lead a:hover{color:var(--ink);border-color:var(--ink)}

/* ── stack ────────────────────────────────────────────────────────────
   Was two lists of the same technologies: a six-cell category grid and
   then a table repeating all of it. One list now, and the provenance
   column is the quiet part instead of the loudest thing on screen. */
.stack__note{color:var(--muted);margin:-2rem 0 2.4rem;max-width:62ch;font-size:1.02rem}
.stackline{display:grid;border-top:1px solid var(--line)}
.stackline__row{display:grid;gap:.45rem 3rem;padding:1.35rem 0;border-bottom:1px solid var(--line);
  transition:padding-left .35s var(--ease),background .35s}
.stackline__row:hover{padding-left:.9rem;background:rgba(255,255,255,.018)}
.stackline dt{font-family:var(--f-display);font-weight:500;font-size:1.02rem;color:var(--ink);
  letter-spacing:-.01em;line-height:1.35}
.stackline dt span{display:block;margin-top:.4rem;font-family:var(--f-mono);font-size:.64rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);opacity:.72}
.stackline dd{margin:0;color:var(--muted);font-size:.95rem;line-height:1.65}
@media(min-width:860px){
  .stackline__row{grid-template-columns:minmax(200px,270px) 1fr;align-items:baseline}
}

/* ── education rows (reuses .earlier; only the year column is narrower) ── */
.earlier.edu{margin-bottom:2.6rem}
@media(min-width:900px){ .earlier.edu li{grid-template-columns:270px 1fr 130px} }

/* ── the entry tier ─────────────────────────────────────────────────
   The three offers are a ladder, not a menu: you cannot buy the sprint
   without the audit's output. So the first is marked, not the middle,
   and the mark is a route instruction rather than a popularity claim.
   Border and a denser wash, per the guidelines: no drop shadow. */
.offer--entry{border-color:rgba(107,79,214,.5);
  background:linear-gradient(160deg,rgba(107,79,214,.14),rgba(12,16,23,.02))}
.offer--entry .offer__len{border-color:rgba(107,79,214,.5);color:var(--vi)}
.offer__len i{font-style:normal}
.offer__len i::before{content:" · ";opacity:.5}



/* ── project spec line (replaces the pill row) ── */
.card__spec{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.06em;color:var(--muted);
  margin-top:1.1rem;padding-top:.9rem;border-top:1px solid var(--line);opacity:.85}
.proj:hover .card__spec{color:var(--cy);opacity:1}

/* ── selected work ───────────────────────────────────────────────────
   Was a 2x2 of four identical cards: same badge, same five pills, same
   paragraph length, no hierarchy. Now one full-width row per project,
   alternating sides. Two reasons, in order of importance: the schematic
   is the actual evidence and it was cramped at 467px, and four rows that
   alternate cannot read as a template the way four equal boxes do. */
.projs{display:grid;gap:clamp(2.5rem,5vw,4.5rem)}
.proj{display:grid;gap:1.6rem 3.5rem;align-items:center;
  padding-bottom:clamp(2.5rem,5vw,4.5rem);border-bottom:1px solid var(--line)}
.proj:last-child{border-bottom:0;padding-bottom:0}
.proj .card__schem{margin:0}
.proj .card__schem svg{color:var(--ink)}
.proj__body{display:grid;gap:.15rem;align-content:center}
.proj .card__no{margin-bottom:.8rem}
.proj h3{font-family:var(--f-display);font-size:clamp(1.4rem,2.6vw,1.85rem);font-weight:500;
  letter-spacing:-.02em;margin-bottom:.25rem}
.proj .card__kind{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin-bottom:1rem}
.proj > .proj__body > p:not(.card__kind):not(.card__spec):not(.proj__call):not(.proj__cons){color:var(--muted);font-size:1rem;max-width:52ch}
.proj .card__spec{margin-top:1.3rem}

@media(min-width:900px){
  .proj{grid-template-columns:1.15fr .85fr}
  /* hierarchy from reading order, not from a claim about importance */
  .proj:first-child{grid-template-columns:1.32fr .68fr}
  /* the schematic keeps the wider column on both sides of the alternation */
  .proj:nth-child(even){grid-template-columns:.85fr 1.15fr}
  .proj:nth-child(even) .card__schem{order:2}
  .proj:nth-child(even) .proj__body{order:1}
}

/* ── diagram key: the notation carries meaning, so state it once ── */
.schem__key{display:flex;flex-wrap:wrap;gap:.55rem 1.6rem;margin:-1.4rem 0 3rem;
  font-family:var(--f-mono);font-size:.66rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.schem__key li{display:flex;align-items:center;gap:.5rem}
.schem__key svg{width:22px;height:8px;flex:none;overflow:visible}
.schem__key .p{fill:none;stroke:var(--cy);stroke-width:1.3}
.schem__key .s{fill:none;stroke:var(--vi);stroke-width:1.3}
.schem__key .q{stroke-dasharray:4 3}
.schem__key .bound{fill:none;stroke:var(--muted);stroke-width:1;stroke-dasharray:3 3}

/* ── the tradeoff line: the lead promises this, so it gets its own rule ── */
.proj__call{position:relative;margin-top:1.15rem;padding-left:1rem;max-width:52ch;
  font-size:.96rem;color:var(--muted)}
.proj__call::before{content:"";position:absolute;left:0;top:.45em;bottom:.45em;width:1px;
  background:linear-gradient(180deg,var(--cy),transparent)}
.proj__call b{color:var(--ink);font-weight:500}

/* ── design constraint, reads as a footnote to the spec ── */
.proj__cons{margin-top:.45rem;font-family:var(--f-mono);font-size:.66rem;letter-spacing:.06em;
  color:var(--muted);opacity:.72;max-width:52ch;line-height:1.5}

/* hover reports which diagram you are reading, rather than lighting a container edge */
.proj .schem .nd{transition:opacity .4s var(--ease)}
.proj:hover .schem .nd{opacity:.72}
