/* ── Home page — animations & layout (on the shared site.css tokens) ── */
@keyframes blinkCursor{0%,49%{opacity:1;}50%,100%{opacity:0;}}
@keyframes floatOrb{0%,100%{transform:translateY(0px);}50%{transform:translateY(-20px);}}
@keyframes zoomReveal{from{opacity:0;transform:scale(.9);}to{opacity:1;transform:scale(1);}}
@keyframes revealLeft{from{opacity:0;transform:translateX(-40px);}to{opacity:1;transform:translateX(0);}}
@keyframes revealTile{from{opacity:0;transform:translateY(26px) scale(.92);}to{opacity:1;transform:translateY(0) scale(1);}}
@keyframes nowPulse{0%,100%{opacity:1;transform:scale(1);}50%{opacity:.35;transform:scale(.7);}}
@keyframes gridDrift{from{background-position:0 0;}to{background-position:26px 26px;}}
/* Slow ambient rotation for the Projects card's gradient border */
@keyframes borderSpin{to{--edge:360deg;}}
@keyframes iconBreathe{0%,100%{transform:translateY(0);box-shadow:0 0 0 0 rgba(59,111,214,0);}50%{transform:translateY(-3px);box-shadow:0 8px 22px -6px rgba(59,111,214,.4);}}
@property --edge{syntax:'<angle>';initial-value:0deg;inherits:false;}

/* Scroll-linked expand: content starts slightly small + faded and grows to
   full size as it scrolls up into view — a gentle pull that rewards scrolling.
   Scale/opacity are tied to scroll position, not a timed tween. */
@keyframes scrollExpand{from{opacity:.35;transform:scale(.9);}to{opacity:1;transform:scale(1);}}
.scroll-scale{animation:scrollExpand linear both;animation-timeline:view();animation-range:entry 8% cover 42%;transform-origin:center top;}
@media(prefers-reduced-motion:reduce){.scroll-scale{animation:none;}}

/* Hero — a full-bleed stage: effect layers (dots, glow, orbs) span and clip
   at the section edge, while the content sits in .hero-inner capped at the
   measure. */
.hero{
  position:relative;overflow:hidden;
  padding:var(--s-10) var(--section-x) var(--s-9);
}
.hero-inner{
  position:relative;max-width:1200px;margin:0 auto;
  display:grid;grid-template-columns:1.05fr .95fr;gap:var(--s-8);align-items:center;
}
.hero-dots,.hero-grid,.hero-orbs,.hero-spot{
  position:absolute;inset:0;pointer-events:none;
}
.hero-dots{background-image:radial-gradient(light-dark(#d6d4ce,#242a33) 1px,transparent 1px);background-size:26px 26px;-webkit-mask-image:linear-gradient(180deg,transparent,#000 12%,#000 88%,transparent);mask-image:linear-gradient(180deg,transparent,#000 12%,#000 88%,transparent);opacity:.4;animation:gridDrift 20s linear infinite;}
.hero-grid{background-image:radial-gradient(var(--accent) 1.5px,transparent 1.5px);background-size:26px 26px;opacity:0;transition:opacity .5s ease;-webkit-mask-image:radial-gradient(300px circle at 50% 50%,#000 0%,#000 10%,transparent 70%);mask-image:radial-gradient(300px circle at 50% 50%,#000 0%,#000 10%,transparent 70%);}
/* Orbs trail the cursor: JS retargets the transform on every mousemove and
   this long eased transition turns those snaps into a soft lagging drift. */
.hero-orbs{transition:transform 1.2s cubic-bezier(.22,1,.36,1);}
.orb{position:absolute;border-radius:50%;background:var(--accent);}
/* Orbs bleed off the hero's own corners (.hero clips), so any cut edge sits
   at the page border where it reads as a natural vignette. */
.orb.a{top:-80px;left:-60px;width:340px;height:340px;opacity:.22;filter:blur(56px);animation:floatOrb 11s ease-in-out infinite;}
.orb.b{bottom:-100px;right:-70px;width:400px;height:400px;opacity:.17;filter:blur(64px);animation:floatOrb 14s ease-in-out infinite 1.6s;}
/* Glows read dimmer against the dark background — lift them there. */
[data-theme="dark"] .orb.a{opacity:.17;}
[data-theme="dark"] .orb.b{opacity:.13;}
.hero-text{position:relative;}
.hero .eyebrow{animation:heroIn .6s ease both;}
.name{font:800 var(--t-display)/1.0 Manrope,sans-serif;margin:var(--s-5) 0 0;letter-spacing:-.035em;text-wrap:balance;}
.name > span{display:block;}
.subtitle{font:400 var(--t-lg)/1.5 Manrope,sans-serif;color:var(--ink-2);max-width:42ch;margin:var(--s-5) 0 0;animation:heroIn .6s ease .4s both;}
.nowline{display:flex;align-items:center;gap:var(--s-2);margin-top:var(--s-5);animation:heroIn .6s ease .46s both;}
.nowdot{width:8px;height:8px;border-radius:50%;background:#34c759;flex:none;animation:nowPulse 2.4s ease-in-out infinite;}
.now-text{font:500 var(--t-xs)/1 'IBM Plex Mono',monospace;color:var(--ink-2);}
.herobtns{display:flex;gap:var(--s-3);margin-top:var(--s-7);animation:heroIn .6s ease .5s both;}
.btn-primary,.btn-ghost{text-decoration:none;font:600 var(--t-sm)/1 Manrope,sans-serif;padding:var(--s-4) var(--s-6);border-radius:100px;display:inline-block;transition:background .25s,color .25s,transform .25s,box-shadow .25s;}
.btn-primary{color:#fff;background:var(--accent);}
.btn-primary:hover{background:var(--accent-strong);box-shadow:0 10px 24px rgba(59,111,214,.35);transform:translateY(-2px);}
.btn-primary:active{transform:scale(.97);}
.btn-ghost{color:var(--accent);background:var(--accent-soft);}
.btn-ghost:hover{box-shadow:0 10px 24px rgba(59,111,214,.16);transform:translateY(-2px);}
.btn-ghost:active{transform:scale(.97);}

/* Scroll cue — quiet invitation at the base of the hero; fades away the
   moment scrolling starts (html.scrolled, set in theme.js). */
@keyframes cueBob{0%,100%{transform:translateY(0);opacity:.45;}50%{transform:translateY(6px);opacity:1;}}
.scroll-cue{
  position:absolute;left:50%;bottom:6px;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:var(--s-1);
  text-decoration:none;color:var(--ink-3);
  font:600 10px Manrope,sans-serif;letter-spacing:.24em;text-transform:uppercase;
  animation:heroIn .6s ease 1.1s both;transition:opacity .4s ease,color .25s ease;
}
.scroll-cue:hover{color:var(--accent);}
.scroll-cue svg{animation:cueBob 1.8s ease-in-out infinite;}
html.scrolled .scroll-cue{opacity:0;pointer-events:none;}

.term-wrap{position:relative;animation:heroIn .8s ease .3s both;}
.term{transform:perspective(1100px);transform-style:preserve-3d;transition:transform .5s cubic-bezier(.16,1,.3,1);background:#1d1d1f;border-radius:var(--radius);box-shadow:0 24px 60px rgba(0,0,0,.28);overflow:hidden;}
.term-bar{height:38px;display:flex;align-items:center;gap:var(--s-2);padding:0 var(--s-4);background:#2c2c2e;}
.term-dot{width:11px;height:11px;border-radius:50%;}
.term-title{font:500 var(--t-2xs)/1 'IBM Plex Mono',monospace;color:#8e8e93;margin-left:var(--s-2);}
.term-body{padding:var(--s-5);height:400px;overflow-y:auto;}
.term-body pre{margin:0;white-space:pre-wrap;font:var(--t-xs)/1.75 'IBM Plex Mono',monospace;color:#e8e8ed;}
.term-cursor{animation:blinkCursor 1s steps(1) infinite;color:#8db2f5;}
.board{margin:var(--s-4) 0 0;font:var(--t-sm)/1.6 'IBM Plex Mono',monospace;color:#9bb4e0;letter-spacing:4px;}
.board-move{font:var(--t-2xs)/1 'IBM Plex Mono',monospace;color:#8e8e93;margin-top:var(--s-3);}
.board-soon{font:var(--t-2xs)/1.7 'IBM Plex Mono',monospace;color:#5b5b60;margin-top:var(--s-4);}

/* Section label = shared eyebrow token */
.sec-label{font:600 var(--t-xs)/1 Manrope,sans-serif;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);}
.reveal-up{animation:revealUp linear both;animation-timeline:view();animation-range:cover 0% cover 32%;}
.reveal-left{animation:revealLeft linear both;animation-timeline:view();animation-range:cover 0% cover 32%;}

/* About — sidebar label + content, aligned baselines */
.about-row{display:grid;grid-template-columns:120px 1fr;gap:var(--s-8);max-width:var(--measure);margin:0 auto;}
.about-lead{font:500 var(--t-h3)/1.45 Manrope,sans-serif;letter-spacing:-.01em;color:var(--ink);margin:0 0 var(--s-6);text-wrap:balance;}
.about-path{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2);margin:0 0 var(--s-7);font:500 var(--t-xs)/1.6 'IBM Plex Mono',monospace;color:var(--ink-2);}
.about-path .sep{font:600 var(--t-xs) Manrope,sans-serif;color:var(--ink-3);}
.about-path .now{color:var(--accent);font-weight:700;}
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-6);border-top:1px solid var(--hair);padding-top:var(--s-6);}
.stat-k{font:600 var(--t-2xs)/1 Manrope,sans-serif;color:var(--ink-3);text-transform:uppercase;letter-spacing:.08em;}
.stat-v{font:600 var(--t-body)/1 Manrope,sans-serif;margin-top:var(--s-2);color:var(--ink);}

/* Focus & stack */
.stack-head{text-align:center;margin-bottom:var(--s-7);}
.stack-grid{display:grid;grid-template-columns:1fr 1.35fr;gap:var(--s-4);}
.card{border:1px solid var(--hair);border-radius:var(--radius);background:var(--surface);}
.domains{padding:var(--s-3) var(--s-5);display:flex;flex-direction:column;justify-content:center;}
/* Domain rows: slide in from the left, staggered top-to-bottom */
.domain{display:flex;align-items:center;gap:var(--s-4);padding:var(--s-4) var(--s-3);border-radius:var(--radius-sm);margin:0 calc(var(--s-3) * -1);color:var(--accent);
  transition:background .25s ease,transform .3s cubic-bezier(.34,1.56,.64,1),color .25s ease;
  animation:revealLeft .55s cubic-bezier(.22,1,.36,1) both;animation-timeline:view();animation-range:cover 2% cover 26%;animation-delay:calc(var(--i) * .06s);}
.domain:hover{background:var(--hair-2);transform:translateX(6px);}
.domain span{font:600 var(--t-sm) Manrope,sans-serif;color:var(--ink);transition:color .25s ease;}
.domain:hover span{color:var(--accent);}
.domain svg{stroke:currentColor;transition:transform .3s cubic-bezier(.34,1.56,.64,1);}
.domain:hover svg{transform:scale(1.12) rotate(-4deg);}
.langs{padding:var(--s-5);display:flex;flex-direction:column;justify-content:center;}
.langgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-2);}
/* Language tiles: pop in staggered; hover lifts with a glow in the lang's own colour */
.lang{position:relative;display:flex;flex-direction:column;align-items:center;gap:var(--s-2);padding:var(--s-4) var(--s-1);border-radius:var(--radius-sm);
  transition:transform .3s cubic-bezier(.34,1.56,.64,1),background .25s ease;
  animation:revealTile .5s cubic-bezier(.22,1,.36,1) both;animation-timeline:view();animation-range:cover 2% cover 30%;animation-delay:calc(var(--i) * .05s);}
.lang:hover{transform:translateY(-6px) scale(1.08);background:var(--hair-2);}
.lang-badge{width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;font:700 var(--t-2xs) 'IBM Plex Mono',monospace;
  transition:box-shadow .3s ease,transform .3s cubic-bezier(.34,1.56,.64,1);}
.lang:hover .lang-badge{box-shadow:0 8px 22px -4px color-mix(in srgb,var(--c) 70%,transparent);transform:rotate(-6deg);}
.lang span{font:600 var(--t-2xs) Manrope,sans-serif;color:var(--ink-2);transition:color .25s ease;}
.lang:hover span{color:var(--ink);}

/* Projects */
.proj-head{text-align:center;max-width:var(--measure);margin:0 auto var(--s-8);}
/* Card sits over a slowly-rotating conic gradient that shows as a live accent
   edge — signals "content is coming" rather than reading as an inert stub. */
.proj-card{position:relative;max-width:600px;margin:0 auto;text-align:center;border-radius:var(--radius);padding:var(--s-9) var(--s-8);background:var(--surface);
  transform-origin:top center;animation:zoomReveal linear both;animation-timeline:view();animation-range:entry 10% cover 45%;}
.proj-card::before{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;
  background:conic-gradient(from var(--edge),var(--hair) 0deg,var(--hair) 300deg,var(--accent) 340deg,var(--hair) 360deg);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;
  animation:borderSpin 7s linear infinite;pointer-events:none;}
.proj-icon{width:56px;height:56px;border-radius:14px;background:var(--hair-2);display:flex;align-items:center;justify-content:center;margin:0 auto var(--s-5);
  animation:iconBreathe 4s ease-in-out infinite;}
.proj-icon svg{transition:transform .4s cubic-bezier(.34,1.56,.64,1);}
.proj-card:hover .proj-icon svg{transform:scale(1.1);}
.proj-title{font:700 var(--t-h3)/1.2 Manrope,sans-serif;letter-spacing:-.02em;margin-bottom:var(--s-3);color:var(--ink);}
.proj-desc{font:400 var(--t-body)/1.6 Manrope,sans-serif;color:var(--ink-2);max-width:44ch;margin:0 auto var(--s-6);}
.proj-btn{text-decoration:none;display:inline-flex;align-items:center;gap:var(--s-2);font:600 var(--t-sm)/1 Manrope,sans-serif;color:#fff;background:var(--accent);padding:var(--s-3) var(--s-5);border-radius:100px;transition:background .25s,box-shadow .25s,transform .25s;}
.proj-btn:hover{background:var(--accent-strong);box-shadow:0 10px 24px rgba(59,111,214,.3);transform:translateY(-2px);}

/* Recent writeups */
.wu-top{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:var(--s-6);}
.wu-all{text-decoration:none;font:600 var(--t-sm)/1 Manrope,sans-serif;color:var(--accent);transition:color .2s;}
.wu-all:hover{color:var(--ink);}
.wgrid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4);}
.wcard{text-decoration:none;color:inherit;display:block;padding:var(--s-5);border:1px solid var(--hair);border-radius:var(--radius);background:var(--surface);
  transition:transform .45s cubic-bezier(.34,1.56,.64,1),box-shadow .35s ease,border-color .35s ease;
  animation:revealTile .55s cubic-bezier(.22,1,.36,1) both;animation-timeline:view();animation-range:cover 2% cover 34%;animation-delay:calc(var(--i,0) * .08s);}
.wcard:hover{border-color:var(--tc,var(--accent));transform:translateY(-4px);box-shadow:0 14px 32px rgba(0,0,0,.1);}
.wcard-meta{display:flex;align-items:center;gap:var(--s-3);margin-bottom:var(--s-4);}
.wcard-tag{font:600 var(--t-2xs) 'IBM Plex Mono',monospace;padding:var(--s-1) var(--s-3);border-radius:6px;}
.wcard-date{font:var(--t-2xs) 'IBM Plex Mono',monospace;color:var(--ink-3);}
.wcard-title{min-height:2.6em;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;font:700 var(--t-lg)/1.3 Manrope,sans-serif;letter-spacing:-.01em;color:var(--ink);}
.wcard-foot{display:flex;align-items:center;justify-content:space-between;margin-top:var(--s-5);padding-top:var(--s-4);border-top:1px solid var(--hair);}
.wcard-ctf{font:var(--t-2xs) 'IBM Plex Mono',monospace;color:var(--ink-3);}
.wcard-arrow{color:var(--ink-3);font:var(--t-sm) Manrope,sans-serif;display:inline-block;transition:transform .3s cubic-bezier(.34,1.56,.64,1),color .3s ease;}
.wcard:hover .wcard-arrow{transform:translateX(5px);color:var(--accent);}

.center920{max-width:var(--measure);margin:0 auto;}
.txt-center{text-align:center;}

/* letterized spans (cursor repel) */
.ltr{display:inline-block;transition:transform .2s cubic-bezier(.34,1.56,.64,1),color .2s ease;cursor:default;}
.ltr-word{display:inline-block;white-space:nowrap;}

@media(max-width:900px){
  .stack-grid{grid-template-columns:1fr;}
  .wgrid{grid-template-columns:1fr;}
}
@media(max-width:820px){
  .hero{padding:var(--s-8) var(--section-x) var(--s-8);}
  .hero-inner{grid-template-columns:1fr;gap:var(--s-7);}
  .name{font-size:56px;letter-spacing:-.03em;}
  .about-row{grid-template-columns:1fr;gap:var(--s-4);}
  .stats{gap:var(--s-4);}
}
@media(max-width:520px){
  .nav-links a[data-nav]{display:none;}
  .herobtns{flex-direction:column;align-items:stretch;}
  .herobtns a{text-align:center;}
  .name{font-size:44px;}
}
