/* ==========================================================================
   Tao Lab — HKUST(GZ)
   Single-page static site. No build step, no framework.

   Light editorial / journal styling: paper ground, ink text, one accent.
   Colour is deliberately scarce — the micrographs and the neuron line art
   are meant to be the only saturated things on the page.

   Sections: tokens · base · nav · hero · about · research · pubs · team
             gallery · join · footer · lightbox · motion · responsive
   ========================================================================== */

/* ---------- tokens ---------- */
:root {
  /* paper */
  --paper:       #fbfaf7;   /* page */
  --paper-2:     #f4f2ec;   /* alternating band */
  --paper-3:     #fffefc;   /* cards, raised surfaces */

  /* ink */
  --ink:         #16191f;   /* headings, primary text */
  --ink-2:       #3f4753;   /* body copy */
  --ink-3:       #737b86;   /* meta, captions, labels */

  /* hairlines — an editorial page is held together by rules, not borders */
  --rule:        #e4dfd5;
  --rule-2:      #cec8bb;

  /* the single accent */
  --accent:      #1d4e89;
  --accent-dark: #143a68;
  --accent-tint: #ecf1f7;
  --accent-line: #b6c8de;

  --font:        "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-serif:  "Source Serif 4", Georgia, "Times New Roman", serif;

  --wrap:        1180px;
  --pad:         clamp(1.25rem, 4vw, 3rem);

  /* The mark's size and the lockup gap are tokens because the brand's hanging
     indent is derived from their sum — a hard-coded -39.6px would drift the
     moment either one changed. */
  --brand-mark:  30px;
  --brand-gap:   .6rem;
  --r:           3px;       /* crisp corners; pills read as product UI, not print */

  --t-fast:      .18s cubic-bezier(.4, 0, .2, 1);
  --t:           .32s cubic-bezier(.4, 0, .2, 1);
  --t-slow:      .7s cubic-bezier(.22, 1, .36, 1);

  --nav-h:       72px;
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--nav-h);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-2);
  font-family: var(--font);
  font-size: clamp(.975rem, .35vw + .9rem, 1.0625rem);
  line-height: 1.72;
  font-weight: 400;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }

a { color: var(--accent); text-decoration: none; transition: color var(--t-fast); }
a:hover { color: var(--accent-dark); }

h1, h2, h3 {
  font-family: var(--font-serif);
  color: var(--ink);
  font-weight: 600;
  line-height: 1.18;
  letter-spacing: -.008em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0 0 1.05em; }
p:last-child { margin-bottom: 0; }

strong, b { color: var(--ink); font-weight: 600; }

::selection { background: #d7e3f1; color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  top: -100px; left: 1rem;
  z-index: 200;
  padding: .7rem 1.1rem;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  border-radius: 0 0 var(--r) var(--r);
  transition: top var(--t-fast);
}
.skip-link:focus { top: 0; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
}

/* scroll progress */
.scroll-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 120;
  pointer-events: none;
}
.scroll-progress span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent);
  transition: width .1s linear;
}

/* ---------- shared bits ---------- */
/* Letterspaced small caps rather than a monospace HUD label. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: .6rem;
  margin: 0 0 1.1rem;
  font-size: .705rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.eyebrow .num {
  color: var(--accent);
  padding-right: .6rem;
  border-right: 1px solid var(--rule-2);
  font-variant-numeric: tabular-nums;
}
.eyebrow--hero { color: var(--ink-3); letter-spacing: .16em; }

.sec-title {
  font-size: clamp(1.9rem, 3.5vw, 3rem);
  font-weight: 600;
}
.sec-sub {
  max-width: 60ch;
  margin: 1.1rem 0 0;
  color: var(--ink-2);
  font-size: 1.03rem;
}
.sec-note {
  display: block;
  margin-top: .55rem;
  font-size: .84rem;
  color: var(--ink-3);
}
.sec-note code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .92em;
  padding: .1em .4em;
  border-radius: 2px;
  background: var(--paper-2);
  border: 1px solid var(--rule);
}

.sec-head { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.sec-head--center { text-align: center; }
.sec-head--center .eyebrow { justify-content: center; }
.sec-head--center .sec-sub { margin-inline: auto; }

.section { padding: clamp(4.25rem, 8vw, 7.5rem) 0; position: relative; }
.section--alt {
  background: var(--paper-2);
  border-block: 1px solid var(--rule);
}

/* buttons — rectangular and quiet */
.btn {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .78rem 1.35rem;
  border-radius: var(--r);
  font-family: var(--font);
  font-size: .9rem;
  font-weight: 550;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
  white-space: nowrap;
}
.btn svg { width: 15px; height: 15px; transition: transform var(--t-fast); }
.btn:hover svg { transform: translateX(3px); }

.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-dark); color: #fff; }

.btn--ghost {
  background: transparent;
  border-color: var(--rule-2);
  color: var(--ink);
}
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-tint); }

/* neuron brand mark */
.brand__mark { width: var(--brand-mark); height: var(--brand-mark); flex: none; }
.bm-soma      { fill: var(--accent-tint); stroke: var(--accent); stroke-width: 1.6; }
.bm-dend path { fill: none; stroke: var(--ink-3); stroke-width: 1.4; stroke-linecap: round; }
.bm-axon      { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-linecap: round; }

/* ==========================================================================
   NAV
   ========================================================================== */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--nav-h);
  background: rgba(251, 250, 247, .82);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t), background var(--t);
}
.nav.is-stuck { background: rgba(251, 250, 247, .94); border-bottom-color: var(--rule); }
.nav__inner {
  height: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.brand { display: inline-flex; align-items: center; gap: var(--brand-gap); color: var(--ink); }

/* Hang the neuron mark out into the page gutter so TAO — not the mark — starts
   on the content edge, putting the wordmark on the same vertical line as the
   hero headline and every section heading below it. The mark is aria-hidden
   decoration, so treating it like hanging punctuation is fair.

   Only where a gutter exists to hang into. Once the viewport nears --wrap the
   centred column runs out of margin and --pad becomes the page's whole safe
   edge; hanging into that walks the mark to the window edge — 7.6px clear at
   1180px, 0.4px at 1000px, off-screen below 880px. 1240px is where the mark
   still clears the window by 38px. Narrower than that the lockup stays
   mark-aligned; keeping the mark at every width and aligning TAO at every width
   are mutually exclusive here, and the mark is the identity. */
@media (min-width: 1240px) {
  .brand__mark { margin-left: calc(-1 * (var(--brand-mark) + var(--brand-gap))); }
}
.brand:hover { color: var(--accent); }
.brand__text {
  font-family: var(--font-serif);
  font-size: 1.12rem;
  font-weight: 700;
  letter-spacing: .04em;
}
.brand__thin { font-weight: 400; color: var(--ink-3); margin-left: .2em; }

/* Distinguishes this Tao Lab from the ones at other universities. The size is in
   `em` so it tracks the wordmark; the sans face at meta weight makes it read as a
   qualifier rather than part of the name — TAOLAB still carries the lockup.
   Like .brand__thin, it keeps its grey on :hover instead of taking the accent.

   The gap is in `rem`, deliberately. An `em` margin here would resolve against the
   .58em font-size set just below — not the wordmark — and come out at half the
   intended width. It also wants to be wider than the .2em holding TAO and LAB
   together: this is a separate unit, not the third syllable of the name. */
.brand__org {
  margin-left: .75rem;
  font-family: var(--font);
  font-size: .58em;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--ink-3);
  white-space: nowrap;
}

.nav__links { display: flex; align-items: center; gap: .2rem; }
.nav__links > a {
  position: relative;
  padding: .5rem .75rem;
  color: var(--ink-2);
  font-size: .885rem;
  font-weight: 450;
  transition: color var(--t-fast);
}
.nav__links > a:hover { color: var(--ink); }
.nav__links > a.is-active { color: var(--ink); }
.nav__links > a.is-active::after {
  content: "";
  position: absolute;
  left: .75rem; right: .75rem; bottom: .25rem;
  height: 1.5px;
  background: var(--accent);
}
.nav__cta {
  margin-left: .6rem;
  padding: .48rem 1.05rem !important;
  border: 1px solid var(--rule-2);
  border-radius: var(--r);
  color: var(--ink) !important;
}
.nav__cta:hover { border-color: var(--accent); color: var(--accent) !important; background: var(--accent-tint); }
.nav__cta.is-active::after { display: none; }

.nav__toggle {
  display: none;
  width: 40px; height: 40px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--rule-2);
  border-radius: var(--r);
  cursor: pointer;
  position: relative;
}
.nav__toggle span {
  position: absolute;
  left: 11px;
  width: 18px; height: 1.5px;
  background: var(--ink);
  transition: transform var(--t-fast), opacity var(--t-fast);
}
.nav__toggle span:nth-child(1) { top: 13px; }
.nav__toggle span:nth-child(2) { top: 19px; }
.nav__toggle span:nth-child(3) { top: 25px; }
.nav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ==========================================================================
   HERO
   ========================================================================== */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: min(94svh, 860px);
  padding: calc(var(--nav-h) + 3.5rem) var(--pad) 5rem;
}

.hero__content {
  position: relative;      /* containing block for the neuron figure */
  width: 100%;
  /* Not var(--wrap). Every other section uses .wrap, where --wrap is the
     border-box width and --pad is inside it, so the text measure is
     --wrap - 2 * --pad. Here the padding sits on .hero, one level up, so
     matching that measure means subtracting it here instead — otherwise the
     hero runs 2 * --pad wider than the rest of the page and its headline
     hangs --pad to the left of every heading below it (48px at 1600px). */
  max-width: calc(var(--wrap) - var(--pad) * 2);
  margin-inline: auto;
}

.hero__title {
  font-size: clamp(2.2rem, 5.4vw, 4.15rem);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -.018em;
  max-width: 16ch;
  margin-bottom: 1.5rem;
}
/* accent italic instead of a gradient fill */
.hero__title em {
  font-style: italic;
  font-weight: 600;
  color: var(--accent);
}

.hero__lede {
  max-width: 48ch;
  font-size: clamp(1rem, .45vw + .93rem, 1.13rem);
  color: var(--ink-2);
  line-height: 1.68;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-top: 2.1rem;
}

/* ---- the PVD neuron figure ----
   Sits in the clear right-hand column on wide screens; drops into the flow
   below the buttons once the text needs the full measure.

   The arbor is drawn with the animal's anterior-posterior axis vertical. Laid
   out horizontally it is a 2.6:1 band, which cannot fill a column this tall —
   turning it upright matches the figure's proportions to the column's. */
.hero__figure {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 32%;
  max-width: 385px;
  margin: 0;
}
.pvd { width: 100%; height: auto; overflow: visible; }

/* Every path carries pathLength="1", so one dash pair draws any stroke over
   exactly its own duration — no per-branch-order length arithmetic, and a
   branch that gets re-shaped later cannot fall out of sync with its dasharray. */
.pvd path {
  fill: none;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: pvdDraw .55s ease-out forwards;
}
@keyframes pvdDraw { to { stroke-dashoffset: 0; } }

/* Branch orders, thickest to finest — the same hierarchy a camera lucida
   drawing would show. */
.pvd-o1 path { stroke: var(--accent); stroke-width: 3.2; opacity: .85; animation-duration: 1.5s; }
.pvd-ax path { stroke: var(--accent); stroke-width: 2.6; opacity: .5;  animation-duration: 1.8s; animation-delay: .55s; }
.pvd-o2 path { stroke: var(--ink-3);  stroke-width: 2.4; opacity: .85; animation-duration: .6s; }
.pvd-o3 path { stroke: var(--ink-3);  stroke-width: 2;   opacity: .8;  animation-duration: .7s; }
.pvd-o4 path { stroke: var(--ink-3);  stroke-width: 1.8; opacity: .62; animation-duration: .5s; }

.pvd-soma { fill: var(--accent-tint); stroke: var(--accent); stroke-width: 2.6; }
.pvd-nuc  { fill: var(--accent); opacity: .7; }

.hero__figcaption {
  margin-top: 1.1rem;
  padding-top: .7rem;
  border-top: 1px solid var(--rule);
  font-size: .745rem;
  line-height: 1.5;
  color: var(--ink-3);
}
.hero__figcaption b {
  color: var(--ink-2);
  font-weight: 600;
}
.hero__figcaption span { display: block; margin-top: .15rem; }

/* Three fixed columns rather than a wrapping flex row: at 560px the third
   figure dropped to its own line and the labels broke mid-phrase. */
.hero__facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem 1.75rem;
  list-style: none;
  margin: 3.25rem 0 0;
  padding: 1.5rem 0 0;
  border-top: 1px solid var(--rule);
  max-width: 660px;
}
.hero__facts li { display: flex; flex-direction: column; gap: .3rem; }
.hero__facts b {
  font-family: var(--font-serif);
  font-size: clamp(1.4rem, 2.2vw, 1.85rem);
  font-weight: 600;
  color: var(--accent);
  letter-spacing: -.01em;
}
.hero__facts span {
  font-size: .82rem;
  line-height: 1.45;
  color: var(--ink-3);
}

.hero__scroll {
  position: absolute;
  right: var(--pad); bottom: 1.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .55rem;
  color: var(--ink-3);
}
.hero__scroll:hover { color: var(--accent); }
.hero__scroll-line { width: 1px; height: 38px; background: var(--rule-2); }
.hero__scroll-text {
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
}

/* ==========================================================================
   ABOUT / PI
   ========================================================================== */
.pi {
  display: grid;
  grid-template-columns: minmax(240px, 320px) 1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

.pi__media { position: sticky; top: calc(var(--nav-h) + 2rem); }

.portrait {
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 5;
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--rule);
  background: var(--paper-2);
}
.portrait > img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 2;
}
.portrait__ph { position: absolute; inset: 0; display: grid; place-items: center; }
.portrait__neuron { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .5; }
.pn-dend path {
  fill: none; stroke: var(--ink-3); stroke-width: 1.6; stroke-linecap: round;
  stroke-dasharray: 220; stroke-dashoffset: 220;
  animation: pvdDraw 2.6s ease-out forwards;
}
.pn-dend path:nth-child(2) { animation-delay: .14s; }
.pn-dend path:nth-child(3) { animation-delay: .28s; }
.pn-dend path:nth-child(4) { animation-delay: .42s; }
.pn-dend path:nth-child(5) { animation-delay: .56s; }
.pn-dend path:nth-child(6) { animation-delay: .7s; }
.pn-axon {
  fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-linecap: round; opacity: .7;
  stroke-dasharray: 200; stroke-dashoffset: 200;
  animation: pvdDraw 2.6s .25s ease-out forwards;
}
.pn-soma    { fill: var(--paper); stroke: var(--accent); stroke-width: 1.8; }
.pn-nucleus { fill: var(--accent); opacity: .28; }
.portrait__initials {
  position: relative;
  font-family: var(--font-serif);
  font-size: 3rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--accent);
}

.pi__contact {
  list-style: none;
  margin: 1.35rem 0 0;
  padding: 0;
  display: grid;
  gap: .65rem;
}
.pi__contact li {
  display: flex;
  align-items: center;
  gap: .65rem;
  font-size: .875rem;
  color: var(--ink-2);
}
.pi__contact svg { width: 15px; height: 15px; flex: none; color: var(--ink-3); }
.pi__contact a { color: var(--ink-2); border-bottom: 1px solid var(--accent-line); }
.pi__contact a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* grid gap rather than sibling margins — component rules like `.timeline
   { margin: 0 }` have equal specificity and would win the margin fight. */
.pi__body {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  align-content: start;
}
.lead-para {
  font-family: var(--font-serif);
  font-size: clamp(1.15rem, .7vw + 1.02rem, 1.45rem);
  line-height: 1.5;
  color: var(--ink);
  font-weight: 400;
}
.lead-para strong { font-weight: 600; }

/* timeline */
.timeline {
  list-style: none;
  margin: 0;
  padding: 0 0 0 1.5rem;
  border-left: 1px solid var(--rule);
  display: grid;
  gap: 1.5rem;
}
.timeline li { position: relative; }
.timeline li::before {
  content: "";
  position: absolute;
  left: calc(-1.5rem - 4.5px);
  top: .6rem;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--paper);
  border: 1.5px solid var(--accent-line);
}
.timeline li:first-child::before { background: var(--accent); border-color: var(--accent); }
.timeline__year {
  display: inline-block;
  margin-bottom: .15rem;
  font-size: .665rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.timeline h3 { font-size: 1.075rem; font-weight: 600; }
.timeline p { margin: .2rem 0 0; font-size: .885rem; color: var(--ink-3); }

/* stats */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 1px;
  margin: 0;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--rule);
}
.stats > div { padding: 1.3rem 1.15rem; background: var(--paper-3); }
.stats dt {
  font-family: var(--font-serif);
  font-size: 2.1rem;
  font-weight: 600;
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.stats dd {
  margin: .45rem 0 0;
  font-size: .775rem;
  line-height: 1.35;
  color: var(--ink-3);
}

/* ==========================================================================
   RESEARCH
   ========================================================================== */
/* 2x2 for the four pillars — auto-fit gave 3 columns and left an orphan. */
.pillars {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
}

.pillar {
  position: relative;
  padding: 1.9rem 1.75rem 1.7rem;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper-3);
  transition: border-color var(--t), box-shadow var(--t);
}
.pillar:hover { border-color: var(--rule-2); box-shadow: 0 6px 24px -14px rgba(22, 25, 31, .22); }
.pillar__idx {
  position: absolute;
  top: 1.6rem; right: 1.6rem;
  font-family: var(--font-serif);
  font-size: .85rem;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.pillar__icon {
  width: 44px; height: 44px;
  margin-bottom: 1.2rem;
  display: grid;
  place-items: center;
  border-radius: var(--r);
  background: var(--accent-tint);
  color: var(--accent);
}
.pillar__icon svg { width: 26px; height: 26px; }
.pillar h3 { font-size: 1.28rem; margin-bottom: .7rem; }
.pillar p { font-size: .92rem; color: var(--ink-2); line-height: 1.68; }

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem .4rem;
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
}
.tags li {
  padding: .2rem .6rem;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  font-size: .705rem;
  letter-spacing: .03em;
  color: var(--ink-3);
  background: var(--paper-2);
}

/* methods */
.methods {
  margin-top: 2.75rem;
  padding-top: 2rem;
  border-top: 1px solid var(--rule-2);
}
.methods__title {
  font-family: var(--font);
  font-size: .705rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.5rem;
}
.methods__title .num { color: var(--accent); margin-right: .5rem; }
/* Three columns, not auto-fit: there are six methods, and auto-fit gave four
   columns at full width, so the second row sat half-empty. */
.methods__list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.35rem 1.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.methods__list li { position: relative; padding-left: .95rem; }
.methods__list li::before {
  content: "";
  position: absolute;
  left: 0; top: .6rem;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
}
.methods__list b {
  display: block;
  font-family: var(--font-serif);
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}
.methods__list span {
  display: block;
  margin-top: .1rem;
  font-size: .815rem;
  line-height: 1.5;
  color: var(--ink-3);
}

/* ==========================================================================
   PUBLICATIONS
   ========================================================================== */
.pubfilter {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin-bottom: 1.75rem;
}
.chip {
  padding: .42rem .9rem;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: transparent;
  color: var(--ink-2);
  font-family: var(--font);
  font-size: .825rem;
  font-weight: 450;
  cursor: pointer;
  transition: color var(--t-fast), border-color var(--t-fast), background var(--t-fast);
}
.chip:hover { color: var(--ink); border-color: var(--rule-2); }
.chip.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pubs { list-style: none; margin: 0; padding: 0; }
.pub {
  display: grid;
  grid-template-columns: 58px 1fr 32px;
  gap: 1.35rem;
  align-items: start;
  padding: 1.45rem .35rem;
  border-top: 1px solid var(--rule);
  transition: background var(--t-fast);
}
.pub:last-of-type { border-bottom: 1px solid var(--rule); }
.pub:hover { background: var(--paper-2); }
.pub[hidden] { display: none; }

.pub__year {
  font-size: .82rem;
  font-weight: 600;
  color: var(--accent);
  padding-top: .2rem;
  font-variant-numeric: tabular-nums;
}
.pub__title {
  font-size: 1.08rem;
  font-weight: 600;
  line-height: 1.4;
  margin-bottom: .4rem;
}
.pub__authors { margin: 0; font-size: .85rem; color: var(--ink-3); }
.pub__authors b { color: var(--ink); font-weight: 600; }
.pub__venue { margin: .28rem 0 0; font-size: .85rem; color: var(--ink-2); }
.pub__venue i { font-family: var(--font-serif); font-size: 1.03em; }
.pub__badge {
  display: inline-block;
  margin-left: .4rem;
  padding: .05rem .4rem;
  border: 1px solid var(--accent-line);
  border-radius: 2px;
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--accent);
}
.pub__link {
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  color: var(--ink-3);
  transition: color var(--t-fast), border-color var(--t-fast), background var(--t-fast);
}
.pub__link svg { width: 13px; height: 13px; }
.pub__link:hover { color: var(--accent); border-color: var(--accent-line); background: var(--accent-tint); }
.pubs__empty { margin-top: 2rem; color: var(--ink-3); text-align: center; }

/* ==========================================================================
   TEAM
   ========================================================================== */
/* A fixed column count, not auto-fill. The PI and "You?" cards span more than one
   cell, so the roster only tiles cleanly at column counts the spans were chosen
   for — auto-fill picks its own count from the available width and lands on ones
   that leave a hole mid-grid. Each breakpoint below is sized so the cells divide
   exactly:

     5 cols — PI 2 + 5 members + join 3 = 10  (2 rows)
     3 cols — PI 2 + 5 members + join 2 =  9  (3 rows)
     2 cols — PI 2 + 5 members + join 1 =  8  (4 rows)

   Adding or removing a member breaks that arithmetic. The join card's span is the
   thing to adjust: it holds no content a different width would crowd. */
.team {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  grid-auto-flow: dense;
  gap: 1.1rem;
}

.member {
  position: relative;
  padding: 1.75rem 1.35rem 1.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper-3);
  text-align: center;
  transition: border-color var(--t), box-shadow var(--t);
}
.member:hover { border-color: var(--rule-2); box-shadow: 0 6px 24px -14px rgba(22, 25, 31, .22); }
.member--pi { grid-column: span 2; background: var(--accent-tint); border-color: var(--accent-line); }
.member h3 { font-size: 1.075rem; margin-bottom: .3rem; }
.member__role {
  margin: 0;
  font-size: .665rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
}
.member__note { margin: .6rem 0 0; font-size: .79rem; color: var(--ink-3); line-height: 1.5; }
.member__mail {
  display: inline-block;
  margin-top: .65rem;
  font-size: .79rem;
  color: var(--ink-2);
  border-bottom: 1px solid var(--accent-line);
}
.member__mail:hover { color: var(--accent); }

.avatar {
  position: relative;
  width: 78px; height: 78px;
  margin: 0 auto 1.1rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 1px solid var(--rule-2);
  background: var(--paper-2);
}
.avatar--lg { width: 96px; height: 96px; }
.avatar > img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 2;
}
.avatar::after {
  content: attr(data-initials);
  font-family: var(--font-serif);
  font-size: 1.4rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--accent);
}
.avatar--lg::after { font-size: 1.7rem; }

.member--open {
  display: block;
  grid-column: span 3;
  border-style: dashed;
  border-color: var(--rule-2);
  background: transparent;
  color: var(--ink);
}
.member--open:hover { border-color: var(--accent); background: var(--accent-tint); color: var(--ink); }
.avatar--open { background: transparent; border-style: dashed; color: var(--accent); }
.avatar--open::after { content: none; }
.avatar--open svg { width: 24px; height: 24px; }
.member__cta { display: inline-block; margin-top: .8rem; font-size: .79rem; color: var(--accent); }

/* ---- alumni ----
   Deliberately quieter than the roster: a ruled label instead of a heading, a
   smaller avatar, and the role in grey rather than the accent. Past members are
   listed, not featured, so the current group stays the thing you read first. */
.alumni { margin-top: clamp(2.75rem, 5vw, 4rem); }

.alumni__title {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  margin: 0 0 1.4rem;
  font-family: var(--font);
  font-size: .665rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
/* the rule runs from the label to the edge of the measure */
.alumni__title::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

/* Wider min than the roster: these cards lay the name beside the avatar rather
   than under it, so they need room for a name on one line. */
.alumni__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.alum {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .9rem 1.1rem;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper-3);
  transition: border-color var(--t);
}
.alum:hover { border-color: var(--rule-2); }
.alum .avatar { flex: none; margin: 0; }
.alum__text { min-width: 0; }
.alum h4 {
  margin: 0 0 .15rem;
  font-family: var(--font-serif);
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.3;
}
.alum__role {
  margin: 0;
  font-size: .665rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.avatar--sm { width: 54px; height: 54px; }
.avatar--sm::after { font-size: 1rem; }

/* ==========================================================================
   GALLERY
   Figure panels with the caption below the image, the way a paper sets them —
   9 photos on a 3-column grid, so it tiles exactly with no span arithmetic.
   ========================================================================== */
.gallery {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2rem 1.6rem;
}
.shot { margin: 0; cursor: zoom-in; }
.shot > img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper-2);
  transition: border-color var(--t), box-shadow var(--t);
}
.shot:hover > img { border-color: var(--rule-2); box-shadow: 0 8px 28px -16px rgba(22, 25, 31, .35); }
.shot figcaption {
  margin-top: .8rem;
  padding-top: .6rem;
  border-top: 1px solid var(--rule);
  font-size: .765rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
  transition: color var(--t-fast);
}
.shot:hover figcaption { color: var(--accent); }

/* ==========================================================================
   JOIN / CONTACT
   ========================================================================== */
.section--join { background: var(--paper-2); border-top: 1px solid var(--rule); }
.join {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
.join__pitch .sec-title { margin-bottom: 1.25rem; }
.join__list {
  list-style: none;
  margin: 1.5rem 0 1.9rem;
  padding: 0;
  display: grid;
  gap: .65rem;
}
.join__list li {
  position: relative;
  padding-left: 1.45rem;
  font-size: .925rem;
  color: var(--ink-2);
}
.join__list li::before {
  content: "";
  position: absolute;
  left: 0; top: .52rem;
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
}
.join__hint { margin-top: 1rem; font-size: .815rem; color: var(--ink-3); }

.contact-card {
  padding: 1.9rem 1.75rem;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper-3);
}
.contact-card__title {
  font-family: var(--font);
  font-size: .705rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.4rem;
}
.contact-card__list { margin: 0; display: grid; gap: 1.1rem; }
.contact-card__list dt {
  font-size: .655rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: .25rem;
}
.contact-card__list dd { margin: 0; font-size: .885rem; color: var(--ink-2); line-height: 1.6; }
.contact-card__list dd a { color: var(--ink); border-bottom: 1px solid var(--accent-line); }
.contact-card__list dd a:hover { color: var(--accent); }
.contact-card__links {
  display: flex;
  flex-wrap: wrap;
  gap: .45rem;
  margin-top: 1.7rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
}
.contact-card__links a {
  padding: .34rem .75rem;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  font-size: .765rem;
  color: var(--ink-2);
  transition: color var(--t-fast), border-color var(--t-fast), background var(--t-fast);
}
.contact-card__links a:hover { color: var(--accent); border-color: var(--accent-line); background: var(--accent-tint); }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.footer {
  border-top: 1px solid var(--rule);
  padding: 2.75rem 0 2.25rem;
  background: var(--paper);
}
.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.75rem;
}
.footer__brand { display: flex; align-items: center; gap: .8rem; }
.footer__name {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
}
.footer__meta { margin: .1rem 0 0; font-size: .775rem; color: var(--ink-3); }
.footer__nav { display: flex; flex-wrap: wrap; gap: 1.25rem; }
.footer__nav a { font-size: .84rem; color: var(--ink-2); }
.footer__nav a:hover { color: var(--accent); }
.footer__copy { margin: 0; font-size: .775rem; color: var(--ink-3); width: 100%; }

/* ==========================================================================
   LIGHTBOX
   Dark neutral scrim — photographs need it, and it stays out of the accent.
   ========================================================================== */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 5vw, 4rem);
  background: rgba(22, 25, 31, .95);
  opacity: 0;
  transition: opacity var(--t);
}
/* An author `display` beats the UA stylesheet's `[hidden] { display: none }`, so
   without this the closed lightbox still covers the viewport at z-index 200 —
   invisible at opacity 0, but swallowing every click on the page. */
.lightbox[hidden] { display: none; }
.lightbox.is-open { opacity: 1; }
.lightbox__figure { margin: 0; max-width: min(1100px, 100%); text-align: center; }
.lightbox__figure img {
  max-width: 100%;
  max-height: 78vh;
  width: auto;
  border-radius: var(--r);
  transform: scale(.98);
  transition: transform var(--t);
}
.lightbox.is-open .lightbox__figure img { transform: scale(1); }
.lightbox__figure figcaption {
  margin-top: 1.2rem;
  font-size: .9rem;
  color: #cfd3d9;
  max-width: 62ch;
  margin-inline: auto;
}
.lightbox__close,
.lightbox__nav {
  position: absolute;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: 50%;
  background: rgba(255, 255, 255, .06);
  color: #fff;
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
  line-height: 1;
}
.lightbox__close:hover,
.lightbox__nav:hover { background: rgba(255, 255, 255, .16); border-color: #fff; }
.lightbox__close {
  top: 1.5rem; right: 1.5rem;
  width: 44px; height: 44px;
  font-size: 1.6rem;
  padding-bottom: 3px;
}
.lightbox__nav {
  top: 50%;
  width: 46px; height: 46px;
  margin-top: -23px;
  font-size: 1.75rem;
  padding-bottom: 4px;
}
.lightbox__nav--prev { left: 1.25rem; }
.lightbox__nav--next { right: 1.25rem; }
body.no-scroll { overflow: hidden; }

/* ==========================================================================
   REVEAL / MOTION
   Short travel and a quick curve — an editorial page should settle, not swoop.
   ========================================================================== */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--t-slow), transform var(--t-slow);
}
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    /* delays too: the neuron draw-in is staged up to ~2.7s, and leaving those
       in place would hold the arbor invisible for that long. */
    animation-delay: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 1080px) {
  /* The neuron no longer fits beside the text — drop it into the flow. It stays
     narrow: the arbor is taller than it is wide, so a full-width figure here
     would run to well over a screen height. */
  .hero { min-height: 0; }
  .hero__figure {
    position: static;
    transform: none;
    width: 100%;
    max-width: 290px;
    margin: 3rem 0 0;
  }
  .hero__title, .hero__lede { max-width: 34ch; }
  .hero__facts { max-width: none; }
  .hero__scroll { display: none; }

  /* 5 columns would put member cards under ~185px here, which wraps the longer
     names. Three columns still tiles — see the table above the .team rule. */
  .team { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .member--open { grid-column: span 2; }
}

@media (max-width: 1000px) {
  .pi { grid-template-columns: 1fr; }
  .pi__media {
    position: static;
    display: grid;
    grid-template-columns: minmax(0, 230px) 1fr;
    gap: 1.75rem;
    align-items: center;
  }
  .pi__contact { margin-top: 0; }
  .join { grid-template-columns: 1fr; }
}

@media (max-width: 900px) {
  .pillars { grid-template-columns: 1fr; }
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .methods__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .nav__links {
    position: fixed;
    inset: var(--nav-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: .75rem var(--pad) 1.5rem;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    transform: translateY(-10px);
    opacity: 0;
    visibility: hidden;
    transition: transform var(--t), opacity var(--t), visibility var(--t);
  }
  .nav__links.is-open { transform: none; opacity: 1; visibility: visible; }
  .nav__links > a {
    padding: .85rem .25rem;
    border-bottom: 1px solid var(--rule);
    font-size: 1rem;
  }
  .nav__links > a.is-active::after { left: .25rem; right: auto; width: 18px; bottom: .5rem; }
  .nav__cta {
    margin: .9rem 0 0;
    text-align: center;
    padding: .75rem 1.05rem !important;
  }
  .nav__toggle { display: block; }
  .nav.is-open { background: var(--paper); }

  .pi__media { grid-template-columns: 1fr; }
  .portrait { max-width: 290px; }
}

@media (max-width: 620px) {
  :root { --nav-h: 64px; }
  .hero { padding-top: calc(var(--nav-h) + 2.5rem); padding-bottom: 3.5rem; }
  .hero__title, .hero__lede { max-width: none; }
  /* one column: three figures side by side leaves ~6ch per label */
  .hero__facts { grid-template-columns: 1fr; gap: 1.1rem; }

  .methods__list { grid-template-columns: 1fr; }
  .pillar { padding: 1.6rem 1.3rem; }

  .pub { grid-template-columns: 1fr auto; gap: .45rem 1rem; padding: 1.3rem .25rem; }
  .pub__year { grid-row: 1; grid-column: 1; font-size: .76rem; padding-top: 0; }
  .pub__main { grid-row: 2; grid-column: 1 / -1; }
  .pub__link { grid-row: 1; grid-column: 2; width: 30px; height: 30px; }

  /* join drops to a single cell so it pairs with the odd member out instead of
     being pushed to a row of its own, leaving a gap beside them */
  .team { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .member--pi { grid-column: span 2; }
  .member--open { grid-column: span 1; }

  .gallery { gap: 1.5rem 1rem; }

  .lightbox__nav { width: 40px; height: 40px; margin-top: -20px; }
  .lightbox__nav--prev { left: .5rem; }
  .lightbox__nav--next { right: .5rem; }
  .lightbox__close { top: .85rem; right: .85rem; }

  .footer__inner { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 420px) {
  .gallery { grid-template-columns: minmax(0, 1fr); }
  .team { grid-template-columns: minmax(0, 1fr); }
  .member--pi, .member--open { grid-column: span 1; }
}

/* print — the page is already light, so this is mostly about stripping chrome */
@media print {
  .nav, .hero__scroll, .scroll-progress, .lightbox, .pubfilter { display: none !important; }
  body { background: #fff; }
  .section, .section--alt, .section--join { padding: 1.25rem 0; background: #fff; border: 0; }
  .reveal { opacity: 1 !important; transform: none !important; }
  .pvd path, .pn-dend path, .pn-axon { stroke-dashoffset: 0 !important; animation: none !important; }
  .pub { break-inside: avoid; }
}
