/* ==========================================================================
   isaacang.bio — ball-and-stick network portfolio
   Fixed-width desktop composition (network block is 760px, coordinates in
   index.html and the SVG edge layer share one coordinate space).
   ========================================================================== */

:root{
  --bg:      #0B0E17;
  --fg:      #E8E6E1;
  --mut:     #5A6070;
  --faint:   rgba(255,255,255,.35);

  /* three category hues */
  --research: #4ECDC4;
  --project:  #E8A838;
  --industry: #7E8AA8;

  --net-w: 760px;
  --sans:  'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --disp:  'Space Grotesk', var(--sans);
  --mono:  'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

*,*::before,*::after{ margin:0; padding:0; box-sizing:border-box; }

html{ scroll-behavior:smooth; }
body{
  background:var(--bg); color:var(--fg);
  font-family:var(--sans); font-weight:300;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
a{ color:inherit; text-decoration:none; }

.wrap{ max-width:880px; margin:0 auto; }

/* ---------- nav (wordmark + socials only) ---------- */
.nav{
  position:sticky; top:0; z-index:40;
  display:flex; align-items:center; gap:16px;
  padding:14px 28px;
  background:rgba(11,14,23,.92);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  border-bottom:.5px solid rgba(78,205,196,.12);
}
.nav-name{
  font-family:var(--disp); font-weight:600; font-size:14px;
  color:var(--research); letter-spacing:.3px;
}
.nav-ic{ display:flex; gap:13px; }
.nav-ic a{ color:var(--mut); display:flex; transition:color .2s, transform .2s; }
.nav-ic a:hover{ color:var(--fg); transform:translateY(-1px); }
.nav-ic svg{ width:16px; height:16px; }

/* ---------- hero ---------- */
.hero{ text-align:center; padding:40px 28px 4px; }
.pfp{
  width:88px; height:88px; border-radius:50%; margin:0 auto 16px;
  overflow:hidden; background:#1A1F2E;
  border:1.5px solid var(--research);
  box-shadow:0 0 22px -4px rgba(78,205,196,.45);
}
.pfp img{ width:100%; height:100%; object-fit:cover; display:block; }
.eyebrow{
  font-family:var(--mono); font-size:9.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--research); margin-bottom:10px;
}
.hero h1{
  font-family:var(--disp); font-weight:500; font-size:25px;
  letter-spacing:-.3px; margin-bottom:12px;
}
.typeline{ font-size:15px; color:#8A8E9A; margin-bottom:11px; min-height:1.6em; }
.type{ color:var(--fg); font-weight:500; }
.caret{
  display:inline-block; width:1.5px; height:1em; vertical-align:-.14em;
  background:var(--research); margin-left:1px; animation:blink 1.05s step-end infinite;
}
@keyframes blink{ 50%{ opacity:0 } }
.lede{
  font-size:12.5px; color:#767C8B; max-width:440px; margin:0 auto; line-height:1.7;
}

/* ---------- network ---------- */
.net{
  position:relative; width:var(--net-w); height:640px;
  margin:26px auto 0;
}
.edges{ position:absolute; inset:0; width:var(--net-w); height:640px; overflow:visible; }
.edges line{ stroke-linecap:round; }

/* base bonds */
.bond{ stroke-width:3; transition:opacity .5s ease; }
/* travelling pulse copies */
.pulse{
  stroke-width:3; stroke-linecap:round;
  stroke-dasharray:20 150;
  stroke-dashoffset:var(--flow0, 0px);
  opacity:calc(var(--pulse, 0) * .85);
}
.pulse.lag { stroke-dashoffset:var(--flow1, 0px); }
.pulse.lag2{ stroke-dashoffset:var(--flow2, 0px); }

/* node cards, positioned in the same coordinate space as the SVG */
.nd{
  position:absolute; width:220px;
  display:flex; flex-direction:column; align-items:center;
}
.sp{
  position:relative; width:68px; height:68px; border-radius:50%;
  transition:transform .3s cubic-bezier(.2,.7,.3,1), box-shadow .3s ease, filter .3s ease;
}
/* lighting: highlight upper-left, rim falloff — sits over solid fills and textures alike */
.sp::before{
  content:""; position:absolute; inset:0; border-radius:50%; pointer-events:none;
  background:
    radial-gradient(circle at 30% 24%, rgba(255,255,255,.34), rgba(255,255,255,0) 42%),
    radial-gradient(circle at 50% 50%, rgba(0,0,0,0) 52%, rgba(0,0,0,.72) 100%);
}
.nd.c-research{ --hue:var(--research); }
.nd.c-project { --hue:var(--project);  }
.nd.c-industry{ --hue:var(--industry); }

.sp-research{ background:radial-gradient(circle at 30% 25%,#8FEDE3,#2A9A90 42%,#0E4A44 78%,#071E1C 100%); }
.sp-project { background:radial-gradient(circle at 30% 25%,#F6D18A,#C08A20 42%,#5A3C08 78%,#2A1B04 100%); }
.sp-industry{ background:radial-gradient(circle at 30% 25%,#C2CADE,#6C7794 42%,#333A4D 78%,#171B26 100%); }
/* textured spheres: the plot is scaled DOWN so the whole figure sits inside
   the sphere face, over a dark research-tinted ball */
.sp-tex{
  background-image:var(--tex),
    radial-gradient(circle at 30% 25%, #4E7C74, #29504A 42%, #122623 78%, #071310 100%);
  background-repeat:no-repeat, no-repeat;
  background-position:center, center;
  background-size:31% auto, cover;
}
.sp-umap { --tex:url('../img/tex-umap.png'); }
.sp-phase{ --tex:url('../img/tex-phase.png'); background-size:32% auto, cover; }

/* category ring — carries the hue even on textured spheres */
.sp{ box-shadow:0 0 0 1.5px color-mix(in srgb, var(--hue, var(--research)) 52%, transparent); }

/* domain badge — centred inside sphere */
.ico{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:32px; height:32px;
  border-radius:50%; background:transparent; display:flex;
  align-items:center; justify-content:center;
  border:none; z-index:2;
}
.ico{ color:var(--hue, var(--research)); }
.ico svg{ width:22px; height:22px; }

/* external-link affordance, linked nodes only */
.out{
  position:absolute; top:-2px; right:-2px; width:18px; height:18px;
  border-radius:50%; background:var(--bg);
  border:1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  color:var(--hue); display:flex; align-items:center; justify-content:center;
  opacity:0; transform:scale(.7); transition:opacity .22s ease, transform .22s ease; z-index:2;
}
.out svg{ width:10px; height:10px; }

/* label block — opaque so bonds break at the label, ball-and-stick convention */
.hit{
  display:flex; flex-direction:column; align-items:center;
  text-decoration:none; color:inherit;
}
.lbl{
  position:relative; z-index:1; padding:3px 7px 4px;
  background:var(--bg); border-radius:5px; text-align:center; max-width:206px;
}
.lbl-top{ margin-top:9px; }
.lbl-bot{ margin-top:1px; display:inline-flex; align-items:center; gap:6px; max-width:216px; }

/* expand toggle */
.exp{
  flex:none; width:15px; height:15px; border-radius:50%;
  border:1px solid color-mix(in srgb, var(--hue) 38%, transparent);
  background:transparent; color:var(--hue);
  font-family:var(--mono); font-size:11px; line-height:1;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer; padding:0;
  transition:background .18s ease, border-color .18s ease, transform .18s ease;
}
.exp:hover{ background:color-mix(in srgb, var(--hue) 14%, transparent);
            border-color:var(--hue); transform:scale(1.12); }
.exp:focus-visible{ outline:2px solid var(--hue); outline-offset:2px; }

/* detail popover */
.nd.open{ z-index:30; }
.det{
  position:absolute; top:100%; left:50%; transform:translateX(-50%);
  width:256px; margin-top:7px; padding:10px 13px 9px;
  background:var(--bg); border-radius:7px;
  border:1px solid color-mix(in srgb, var(--hue) 30%, transparent);
  box-shadow:0 16px 34px -18px #000, 0 0 26px -18px var(--hue);
  text-align:left; z-index:30;
  animation:pop .18s cubic-bezier(.2,.7,.3,1);
}
@keyframes pop{ from{ opacity:0; transform:translateX(-50%) translateY(-5px) } }
.det-when{
  font-family:var(--mono); font-size:8.5px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--hue); margin-bottom:7px;
}
.det ul{ margin:0; padding-left:14px; }
.det li{ font-size:9.5px; line-height:1.55; color:#9AA0AE; margin-bottom:5px; }
.det li:last-child{ margin-bottom:0; }
.det li::marker{ color:var(--hue); }
.det em{ color:#B6BCC8; }
.nt{
  font-family:var(--disp); font-size:11.5px; font-weight:500; line-height:1.3;
  color:var(--fg); transition:color .2s ease;
}
.nr{ font-family:var(--mono); font-size:9px; color:var(--mut); margin-top:2px; line-height:1.35; }
.nw{ font-size:9px; color:var(--faint); line-height:1.35; margin-top:3px; }

/* linked vs terminal */
.nd.linked{ cursor:pointer; }
.nd.linked:hover .sp{ transform:translateY(-4px); }
.nd.linked:hover .out{ opacity:1; transform:scale(1); }
.nd.linked:hover .nt{ color:#fff; }
.nd.linked:focus-visible{ outline:none; }
.nd.linked:focus-visible .sp{ box-shadow:0 0 0 2px var(--hue), 0 0 18px -2px var(--hue); }
.nd:hover .sp{ filter:brightness(1.22); }
.nd.terminal{ cursor:default; }

/* ---------- side projects ---------- */
.side{ padding:6px 28px 16px; }
.side-wrap{
  position:relative; display:flex; gap:16px; justify-content:center;
  align-items:center; width:fit-content; max-width:560px; margin:0 auto; padding:16px 0;
}
.side-nd{
  position:relative; transform:translateY(var(--y, 0));
  display:flex; align-items:center; gap:6px; padding:4px 11px;
  border:.5px solid rgba(232,168,56,.22); border-radius:14px;
  background:rgba(232,168,56,.04); transition:border-color .2s ease;
}
.side-nd:hover{ border-color:rgba(232,168,56,.45); }
.side-dot{
  width:9px; height:9px; border-radius:50%;
  background:radial-gradient(circle at 32% 28%,#F6D18A,#B07E1E 55%,#3C2A08 100%);
}
.side-lb{ font-family:var(--mono); font-size:9px; color:var(--project); }


/* ---------- skills / courses strands ---------- */
.strand{ padding:8px 60px 18px; }
.ll{ font-family:var(--mono); font-size:11px; color:var(--mut); letter-spacing:1px; padding:8px 0 0; }
.strand-row{
  position:relative; display:flex; gap:5px; flex-wrap:wrap;
  justify-content:center; align-items:center;
  width:fit-content; max-width:744px; margin:0 auto; padding:14px 0;
}
.wave{
  position:absolute; left:0; top:50%; transform:translateY(-50%);
  width:100%; height:42px; pointer-events:none;
}
.st{
  position:relative; font-family:var(--mono); font-size:9px; padding:4px 8px;
  border:.5px solid; transform:translateY(var(--y, 0));
  transition:border-color .2s, background .2s;
}
.st.sk{ border-color:rgba(78,205,196,.3);  color:var(--research); background:rgba(78,205,196,.06); }
.st.sk:hover{ border-color:var(--research); background:rgba(78,205,196,.12); }
.st.cr{ border-color:rgba(232,168,56,.25); color:var(--project);  background:rgba(232,168,56,.04); }
.st.cr:hover{ border-color:var(--project); background:rgba(232,168,56,.1); }


/* ---------- footer ---------- */
.ft{
  text-align:center; padding:18px 28px 26px;
  border-top:.5px solid rgba(78,205,196,.06);
  font-family:var(--mono); font-size:11px; color:var(--mut); letter-spacing:.5px;
}

/* ---------- reveal ---------- */
.rv{ opacity:0; transform:translateY(12px); transition:opacity .55s ease, transform .55s cubic-bezier(.2,.7,.3,1); }
.rv.in{ opacity:1; transform:none; }
.edges .grp{ opacity:0; transition:opacity .7s ease; }
.edges .grp.in{ opacity:1; }

/* breathing animation for mental health app sphere */
@keyframes breathe{
  0%,100%{ transform:scale(1); }
  50%{ transform:scale(1.12); }
}
.sp-breathe{ animation:breathe 4s ease-in-out infinite; }

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  .rv{ opacity:1; transform:none; transition:none; }
  .edges .grp{ opacity:1; transition:none; }
  .cursor{ animation:none; }
  .pulse{ display:none; }
  .sp-breathe{ animation:none; }
}
