/* ============================================================
   people.css
   Page-specific styles for /people/ index and /people/{slug}/
   detail pages.

   REQUIRES theme.css to be loaded FIRST (for tokens, reset,
   .container, .rv, .site-nav, .site-footer, .back-strip,
   .sidebar-section helpers).
   ============================================================ */

/* Hero rules are shared — see theme.css for .hero / .hero h1 / .hero::before.
   Only page-specific extras kept here. */
.hero h1 { max-width: 700px; }

/* ── Category sections (people index) ────────────────────── */
/* Section spacing is controlled below by `.people-section { margin-bottom }`
   alone — the .people-content column above provides the column's top/bottom
   gutter, so individual sections don't need their own top padding. The hidden
   class is toggled by the role filter to remove non-matching sections. */
.people-section.hidden { display: none; }
/* Section heading ("Current Team", "Alumni", …). Rendered as a full
   heading rather than a tiny eyebrow label — big display type, dark
   ink, tabular underline — so the page has clear structural anchors
   when scrolling through hundreds of people. The `/ Filter` suffix
   the JS appends (e.g. "Current Team / Students") stays in the same
   weight since it's part of the heading phrase.
   On mobile the size drops so it doesn't eat the viewport. */
.section-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 44px;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--color-neutral-100);
  margin-bottom: 28px;
  text-transform: none;
}
@media (max-width: 767px) {
  .section-label { font-size: 32px; }
}

/* Card-level hidden state used by the role filter. */
.person-card.hidden { display: none; }

/* ── Layout: sticky lab timeline (left) + people sections (right) ─
   Mirrors the pattern used by /press/, /projects/, /publications/.
   The year-nav exists as a placeholder for a future "lab timeline"
   feature; it has no scroll-spy or filtering behaviour wired up yet,
   it just highlights the current year. Keeping the structural parity
   now so the feature can be activated later without having to rejig
   the whole index markup. */
.people-layout {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 0;
  min-height: 60vh;
}
@media (max-width: 991px) { .people-layout { grid-template-columns: 1fr; } }

/* ── Year nav ────────────────────────────────────────────── */
.year-nav {
  position: sticky;
  top: 92px;
  height: calc(100vh - 92px);
  padding: 40px 0 40px 40px;
  overflow-y: auto;
  border-right: 1px solid var(--color-neutral-30);
  scrollbar-width: none;               /* Firefox */
}
.year-nav::-webkit-scrollbar { display: none; } /* Chrome / Safari / Edge */
.year-nav a {
  display: flex;
  align-items: baseline;
  font-family: var(--font-display); font-weight: 500; font-size: 15px;
  color: var(--color-neutral-60);
  padding: 8px 20px 8px 0;
  transition: color .25s, border-color .25s;
  border-right: 2px solid transparent;
  margin-right: -1px;
  /* cursor:default because no click handler is wired up — revisit
     when the lab-timeline feature lights up. */
  cursor: default;
  pointer-events: none;
}
.year-nav a.active {
  color: var(--color-accent);
  font-weight: 700;
  border-right-color: var(--color-accent);
}
@media (max-width: 991px) {
  .year-nav {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    top: auto;
    height: auto;
    padding: 10px 20px;
    border-right: none;
    border-top: 1px solid var(--color-neutral-30);
    display: flex; gap: 6px;
    overflow-x: auto;
    z-index: 30;
    background: rgba(255,255,255,.94);
    backdrop-filter: blur(14px);
  }
  .people-content { padding-bottom: 100px; }
  .year-nav a {
    white-space: nowrap;
    padding: 6px 14px;
    border-right: none;
    border-bottom: 2px solid transparent;
    font-size: 13px;
    flex-shrink: 0;
  }
  .year-nav a.active { border-bottom-color: var(--color-accent); border-right-color: transparent; }
}

/* ── People content column ───────────────────────────────── */
/* Right padding matches the .container gutter (40px) so the
   rightmost column doesn't touch the viewport edge on desktop.
   48px on the left gives the content some breathing room from
   the year-nav's border. */
.people-content { padding: 40px 40px 80px 48px; }
@media (max-width: 991px) { .people-content { padding: 32px 20px 60px; } }

.people-section { margin-bottom: 72px; }
.people-section:last-child { margin-bottom: 20px; }

/* ── People grid (index) ─────────────────────────────────── */
/* Column count scales with viewport width rather than snapping to
   fixed breakpoints. On a MacBook (~1440px content area) this still
   yields 4 columns; on a 4K/ultrawide display it yields 6+, keeping
   the card photo size sensible instead of stretching to huge squares. */
.people-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 28px; }
@media (max-width: 767px)  { .people-grid { gap: 16px; } }

.person-card { display: block; transition: transform .4s ease; }
.person-card-photo {
  aspect-ratio: 1 / 1.1;
  overflow: hidden;
  background: var(--color-neutral-40);
  margin-bottom: 16px;
  position: relative;
  border-radius: var(--radius-lg);
}
.person-card-photo img {
  width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(100%);
  transition: filter .5s ease, transform .6s cubic-bezier(.16,1,.3,1);
}
.person-card:hover .person-card-photo img { filter: grayscale(0%); transform: scale(1.04); }
.person-card-photo::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(14,15,17,.2), transparent 50%);
  opacity: 0; transition: opacity .4s;
}
.person-card:hover .person-card-photo::after { opacity: 1; }
.person-card h4 {
  font-family: var(--font-display); font-weight: 700;
  font-size: 18px; line-height: 24px;
  color: var(--color-neutral-100);
  margin-bottom: 2px; transition: color .3s;
}
.person-card:hover h4 { color: var(--color-accent); }
.person-card .person-role {
  font-size: 15px; line-height: 22px; color: var(--color-neutral-70);
}

/* ── Profile hero (detail) ───────────────────────────────── */
.profile-hero { padding: 132px 0 60px; }
.profile-hero-grid {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 60px;
  align-items: start;
}
.profile-photo {
  aspect-ratio: 1 / 1.1;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-40);
  position: relative;
}
.profile-photo img { width: 100%; height: 100%; object-fit: cover; }
.profile-photo::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(221deg, rgba(0,215,238,.1) 0%, rgba(97,0,255,.06) 100%);
  pointer-events: none;
}
.profile-info h1 {
  font-family: var(--font-display); font-weight: 700;
  font-size: 44px; line-height: 46px;
  color: var(--color-neutral-100);
  margin-bottom: 8px;
}
.profile-role {
  font-family: var(--font-display); font-weight: 500;
  font-size: 21px; color: var(--color-neutral-70);
  margin-bottom: 24px;
}
.profile-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-text); font-weight: 600; font-size: 16px;
  color: var(--color-accent); transition: opacity .3s;
}
.profile-link:hover { opacity: .7; }
@media (max-width: 991px) {
  .profile-hero-grid { grid-template-columns: 1fr; gap: 32px; }
  .profile-photo { max-width: 300px; }
  .profile-info h1 { font-size: 36px; line-height: 42px; }
}
/* On true mobile widths, let the photo expand to the full container
   width (the .container already provides 20px left/right gutters, so
   the photo ends up flush with the text margins on either side). The
   max-width cap from the tablet rule would otherwise leave a big empty
   strip to the right of the photo on phones. */
@media (max-width: 767px) {
  .profile-photo { max-width: none; }
}

/* ── Profile social row ───────────────────────────────────
   Four icon slots rendered in a fixed order above the text
   links: LinkedIn, GitHub, Google Scholar, Personal Website.
   Filled slots are interactive <a> tags in the active color;
   empty slots are non-interactive <span class="is-empty">
   placeholders, greyscale and softened so the row's visual
   rhythm stays consistent across all profiles. */
.profile-socials {
  display: flex;
  gap: 10px;
  margin-bottom: 18px;
}
.profile-social {
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-neutral-30);
  border-radius: var(--radius-sm);
  color: var(--color-neutral-80);
  transition: all .25s;
}
.profile-social:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
/* Empty slot: a desaturated placeholder. Non-interactive (no hover
   color shift, default cursor) so users immediately understand the
   icon means "this slot exists but isn't filled in" rather than
   "click here". The dashed border subtly reinforces the placeholder
   meaning. */
.profile-social.is-empty {
  color: var(--color-neutral-40);
  border-style: dashed;
  border-color: var(--color-neutral-30);
  background: transparent;
  cursor: default;
  opacity: .65;
}
.profile-social.is-empty:hover {
  /* Override the default :hover rule so empty slots stay quiet */
  background: transparent;
  border-color: var(--color-neutral-30);
  color: var(--color-neutral-40);
}

/* ── Career timeline ───────────────────────────────────────
   3-node horizontal graph rendered next to the hero photo.
   Layout is a 3-column grid (Then / Now / Next), each column
   containing a header label, a dot, and the org/role/duration
   text. A SINGLE continuous line runs across the whole track
   behind the dots — implemented as a ::before pseudo on the
   .tl-track that stretches from the first dot's center to the
   last dot's center. The dots sit ON TOP of this line so the
   visual is one unbroken horizontal rule punctuated by three
   circles.

   The "Then / Now / Next" headers refer to AHL chronology, NOT
   to today's calendar:
     Then = before AHL  |  Now = at AHL  |  Next = after AHL
   The .is-current dot highlight indicates where the person is
   today. For current members that's "Now"; for alumni it's "Next". */
.profile-timeline {
  margin-top: 32px;
}
.tl-track {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0;
  position: relative;
  padding-top: 36px;       /* space for the column header above each dot */
}
/* Continuous line behind all three dots. Sits at the dot center
   (padding-top + half the dot size). Stretches from the center of
   column 1 to the center of column 3 — i.e. from 1/6 to 5/6 of the
   track width — so the line starts and ends UNDER the outer dots
   instead of running off either edge. */
.tl-track::before {
  content: "";
  position: absolute;
  left: 16.66%;
  right: 16.66%;
  top: calc(36px + 6px);   /* header space + (dot height / 2) */
  height: 2px;
  background: var(--color-neutral-30);
  z-index: 0;
}
/* 2-node variant (current members: Then → Now at AHL; alumni: AHL → Now).
   Two columns instead of three, and the connector line now spans from the
   center of column 1 (25%) to the center of column 2 (75%). */
.tl-track.is-2col {
  grid-template-columns: 1fr 1fr;
}
.tl-track.is-2col::before {
  left: 25%;
  right: 25%;
}
.tl-node {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  min-width: 0;
  position: relative;
  z-index: 1;              /* above the connector line */
}
.tl-col-header {
  position: absolute;
  top: -32px;              /* sits in the padding-top area above the dot */
  left: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--color-neutral-60);
}
.tl-node.is-current .tl-col-header { color: var(--color-accent); }
.tl-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--color-neutral-60);
  flex-shrink: 0;
  /* White inset shadow gives the dot a "punch through" effect — visually
     breaks the line behind it even though the line is one continuous element. */
  box-shadow: 0 0 0 4px #fff;
}
.tl-node.is-current .tl-dot {
  border-color: var(--color-accent);
  background: var(--color-accent);
  box-shadow: 0 0 0 4px #fff, 0 0 0 8px rgba(97,0,255,.15);
}
.tl-node.is-empty .tl-dot {
  border-style: dashed;
  border-color: var(--color-neutral-40);
  background: transparent;
}
.tl-label {
  font-family: var(--font-text);
  font-size: 12px;
  line-height: 1.4;
  color: var(--color-neutral-80);
}
.tl-org {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: .2px;
  color: var(--color-neutral-100);
  margin-bottom: 2px;
}
.tl-node.is-current .tl-org { color: var(--color-accent); }
.tl-role {
  font-size: 12px;
  color: var(--color-neutral-80);
  margin-bottom: 2px;
}
.tl-duration {
  font-size: 11px;
  color: var(--color-neutral-60);
  font-variant-numeric: tabular-nums;
}
.tl-node.is-empty .tl-label {
  color: var(--color-neutral-40);
  font-size: 11px;
}

/* Mobile: stack the 3 columns vertically. The continuous line becomes a
   vertical spine on the left, dots sit on it, content flows to the right. */
@media (max-width: 567px) {
  .tl-track {
    grid-template-columns: 1fr;
    gap: 24px;
    padding-top: 0;
    padding-left: 32px;
  }
  .tl-track::before {
    left: 6px;
    right: auto;
    top: 7px;
    bottom: 7px;
    width: 2px;
    height: auto;
  }
  .tl-col-header {
    position: static;
    margin-bottom: 6px;
  }
  .tl-node .tl-dot {
    position: absolute;
    left: -32px;
    top: 24px;
  }
}

/* ── Profile body (detail) ───────────────────────────────── */
.profile-body { padding: 60px 0 80px; }
.profile-body-grid {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 60px;
  align-items: start;
}
@media (max-width: 991px) { .profile-body-grid { grid-template-columns: 1fr; gap: 40px; } }

.profile-content { max-width: 780px; }
.profile-content p {
  font-size: 21px; line-height: 35px;
  color: var(--color-neutral-100);
  margin-bottom: 20px;
}
.profile-content p:last-child { margin-bottom: 0; }
@media (max-width: 991px) { .profile-content p { font-size: 19px; line-height: 28px; } }

/* ── Intro grid (bio left, featured project right) ─────────
   Uses the same 3-column template as .profile-projects-grid
   below (3 equal columns, 20px gap). The bio spans columns 1–2,
   the featured card sits in column 3. This guarantees the
   featured card is the EXACT same width as each card in the
   projects grid — any other approach (e.g. "2fr 1fr" with one
   gap vs. two gaps) leaves a few pixels of drift because the
   subtracted gap width differs.
   Collapses to stacked on tablet/mobile so the featured project
   falls in right after the bio, before the rest of the projects. */
.profile-intro-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  align-items: start;
}
.profile-intro-grid .profile-content {
  grid-column: 1 / span 2;
  max-width: none;   /* let the 2-column span define width */
}
.profile-intro-grid .profile-featured {
  grid-column: 3 / span 1;
}
@media (max-width: 991px) {
  .profile-intro-grid { grid-template-columns: 1fr; gap: 40px; }
  .profile-intro-grid .profile-content,
  .profile-intro-grid .profile-featured { grid-column: auto; }
}

/* The featured-project sidebar itself — just holds a label and
   one .profile-project-card. The card's aspect-ratio handles the
   height, so this wrapper doesn't need explicit sizing. */
.profile-featured {
  min-width: 0;   /* prevent grid blow-out on narrow viewports */
}
.profile-featured .sidebar-section-title { margin-bottom: 16px; }


/* ── Projects grid in profile ──────────────────────────────
   Image fills the entire card; title overlays at the bottom
   with a frosted-glass background (backdrop-filter blur).
   This is the modern poster-card pattern. The whole card has
   rounded corners and clips its overflow so the overlay
   inherits the rounded bottom edge. */
.profile-projects-grid {
  display: grid;
  /* Adaptive columns: roughly 260px min per card. Person pages sit in
     a narrower content column than the projects index, so the min here
     is tighter — we still want 3 cols on a standard laptop but more on
     a 4K display without the cards becoming oversized image blocks. */
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 20px;
  margin-top: 40px;
}
.profile-project-card {
  display: block;
  position: relative;
  aspect-ratio: 16 / 11;       /* slightly taller than the old 16/10 to give the title room */
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-neutral-40);
  border: 1px solid var(--color-neutral-30);
  transition: transform .4s, box-shadow .4s, border-color .4s;
}
.profile-project-card:hover {
  box-shadow: 0 12px 40px rgba(14,15,17,.18);
  border-color: transparent;
}
/* Image fills the whole card, edge to edge */
.profile-project-card-thumb {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.profile-project-card-thumb img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .6s cubic-bezier(.16,1,.3,1);
}
.profile-project-card:hover .profile-project-card-thumb img { transform: scale(1.06); }

/* Title bar sits absolutely at the bottom, full width, with a frosted
   glass background. The blur picks up whatever's behind it (the project
   image), producing the modern glass-morphism effect. The body is a
   flex row: title left, principle icon tags right — mirroring the card
   pattern used on the projects-index page so a project looks the same
   wherever it appears. */
.profile-project-card-body {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 10px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  background: rgba(14,15,17,.45);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border-top: 1px solid rgba(255,255,255,.12);
  transition: background .3s;
}
.profile-project-card:hover .profile-project-card-body {
  background: rgba(97,0,255,.55);   /* shifts toward accent on hover */
}
.profile-project-card h5 {
  margin: 0;
  font-family: var(--font-display); font-weight: 700;
  font-size: 16px; line-height: 1.25;
  color: #fff;
  flex: 1;
  min-width: 0;                /* allow flex shrinking so ellipsis can fire */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Principle tag icons (profile project card) ──────────
   Right side of the title bar. Same hover-swap pattern as
   the projects-index cards: two stacked <img>s cross-fade
   between default and highlight variants. The icons sit on
   the dark glass title bar, so use a subtle opacity boost
   on the default variant to keep them readable. */
.profile-project-card-tags {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.profile-project-card-tag {
  position: relative;
  display: block;
  width: 22px;
  height: 22px;
  line-height: 0;
}
.profile-project-card-tag img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: opacity .25s ease;
}
.profile-project-card-tag-hover { opacity: 0; }
.profile-project-card-tag:hover .profile-project-card-tag-default { opacity: 0; }
.profile-project-card-tag:hover .profile-project-card-tag-hover   { opacity: 1; }

/* (No breakpoint overrides for .profile-projects-grid — auto-fill + the
   260px min handles the full range from mobile up to 4K on its own.) */

/* ── Orphan project (no thumbnail in projects.json) ───────
   Renders the project card with a colored placeholder block
   instead of an image. The title overlay still works on top. */
.profile-project-card.is-orphan { opacity: .85; }
.profile-project-card-placeholder {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--color-neutral-30), var(--color-neutral-40));
  font-family: var(--font-display); font-weight: 700;
  font-size: 72px;
  color: rgba(255,255,255,.85);
}

/* ── Publications list ────────────────────────────────────
   Used on the person profile page below the projects grid.
   Each publication renders as: title (link if local), full
   citation in muted text, and a row of small DOI/PDF buttons.
   Numbered list to give each entry a clear order. */
.profile-pub-list {
  list-style: none;
  counter-reset: pub;
  padding: 0;
  margin: 0;
}
.profile-pub-item {
  counter-increment: pub;
  position: relative;
  padding: 24px 0 24px 56px;
  border-bottom: 1px solid var(--color-neutral-30);
}
.profile-pub-item:first-child { border-top: 1px solid var(--color-neutral-30); }
.profile-pub-item::before {
  content: counter(pub, decimal-leading-zero);
  position: absolute;
  left: 0; top: 28px;
  font-family: var(--font-display); font-weight: 800;
  font-size: 12px; letter-spacing: 1.5px;
  color: var(--color-neutral-60);
}

.profile-pub-title {
  display: block;
  font-family: var(--font-display); font-weight: 700;
  font-size: 18px; line-height: 26px;
  color: var(--color-neutral-100);
  margin-bottom: 8px;
  transition: color .25s;
}
a.profile-pub-title:hover { color: var(--color-accent); }

.profile-pub-citation {
  font-family: var(--font-text);
  font-size: 14px; line-height: 22px;
  color: var(--color-neutral-70);
  margin-bottom: 12px;
}

.profile-pub-links {
  display: flex; gap: 8px; flex-wrap: wrap;
}
.profile-pub-link {
  font-family: var(--font-display); font-weight: 600;
  font-size: 11px; letter-spacing: .8px;
  color: var(--color-accent);
  padding: 5px 12px;
  border: 1px solid var(--color-neutral-30);
  border-radius: var(--radius-sm);
  transition: all .25s;
}
.profile-pub-link:hover {
  background: var(--color-accent);
  color: #fff;
  border-color: var(--color-accent);
}

@media (max-width: 567px) {
  .profile-pub-item { padding-left: 0; padding-top: 32px; }
  .profile-pub-item::before { top: 8px; }
  .profile-pub-title { font-size: 17px; line-height: 24px; }
}

/* ── Expertise bar ───────────────────────────────────────
   Segmented horizontal bar visualizing the mix of assistive
   augmentation principles across a person's projects. Each
   segment stacks the principle name + count on two lines
   inside the bar itself — no separate legend needed. Segment
   width uses flex-grow with the count as the growth factor,
   so proportions are exact without JS. Narrow segments clip
   their labels gracefully; the title attribute still shows
   the full label on hover. */
.profile-expertise {
  margin-top: 48px;
  margin-bottom: 12px;
}
.profile-expertise .sidebar-section-title { margin-bottom: 16px; }
.expertise-bar {
  display: flex;
  width: 100%;
  height: 100px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--color-neutral-20);
  gap: 2px;
}
.expertise-segment {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  padding: 10px 8px;
  overflow: hidden;
  cursor: default;
  transition: filter .2s;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}
.expertise-segment:hover { filter: brightness(1.08); }
.expertise-segment-icon {
  width: 32px;
  height: 32px;
  object-fit: contain;
  display: block;
  flex-shrink: 0;
  /* Source icons are dark-on-transparent; invert so they read as
     white on the colored segment. Slight opacity softens them so
     they don't dominate over the numeric data. */
  filter: brightness(0) invert(1);
  opacity: .95;
}
.expertise-segment-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
  max-width: 100%;
}
.expertise-segment-count {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  line-height: 1;
  opacity: .92;
}

@media (max-width: 567px) {
  .expertise-bar { height: 84px; }
  .expertise-segment { gap: 3px; padding: 8px 6px; }
  .expertise-segment-icon { width: 24px; height: 24px; }
  .expertise-segment-name { font-size: 11px; }
  .expertise-segment-count { font-size: 12px; }
}