/* ================================================================
   STYLES.CSS

   Stylesheet for the MGB Lab website. This is a single continuous
   scroll page, so the file is ordered to match the page from top
   to bottom: variables and resets first, then the navbar, shared
   layout pieces, the home page, people cards, publications and
   news, the blog, forms and popups, search, the footer, and a
   few small utilities at the end.

   Sections in this file, in order:
     1. Design tokens (colours, spacing, fonts, light/dark theme)
     2. Base reset and global element styles
     3. Navbar (top bar, logo, links, icon buttons, mobile menu)
     4. Shared layout pieces (page sections, chips, badges, buttons)
     5. Home page hero (heading, photo slideshow)
     6. Profile cards (People page)
     7. Academic cards (Research, Projects, News)
     8. Publications and news list rows
     9. Blog (card list and full post view)
    10. Forms and the Join Us popup
    11. Command palette search popup
    12. Footer
    13. Tooltips and page routing
   ================================================================ */

/* ----------------------------------------------------------------
   1. DESIGN TOKENS
   All colours, spacing, and font choices live here as CSS
   variables, so the rest of the file never hardcodes a colour.
   The .dark class on <body> overrides the theme variables for
   dark mode; everything else stays the same.
   ---------------------------------------------------------------- */
:root {
  --accent: #0f766e;
  --accent-hover: #0d5f59;
  --accent-light: rgba(15, 118, 110, 0.08);
  --emerald: #059669;
  --blue: #2563eb;
  --amber: #d97706;
  --danger: #dc2626;

  --bg: #ffffff;
  --bg-alt: #f2f2f2;
  --bg-card: #ffffff;
  --fg: #1a1a1a;
  --muted: #5c5c5c;
  --faint: #8a8a8a;
  --border: #e2e2e2;
  --divider: rgba(15, 118, 110, 0.28);
  --v-sep-color: rgba(15, 118, 110, 0.05);
  --v-sep-glow: rgba(15, 118, 110, 0.24);

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);

  --container-max: 1040px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-full: 9999px;

  --serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --sans: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', 'Fira Code', monospace;

  --t-fast: 150ms ease;
  --t-base: 220ms ease;
}

@media (min-width: 1400px) {
  :root { --container-max: 1180px; }
}
@media (min-width: 1600px) {
  :root { --container-max: 1300px; }
}

.dark {
  --accent: #3dbaa8;
  --accent-hover: #5dd4c2;
  --accent-light: rgba(61, 186, 168, 0.1);
  --danger: #f87171;

  --bg: #1c1b18;
  --bg-alt: #242320;
  --bg-card: #262520;
  --fg: #e8e4dc;
  --muted: #b5b0a5;
  --faint: #7d796f;
  --border: #3a382f;
  --divider: rgba(61, 186, 168, 0.3);
  --v-sep-color: rgba(61, 186, 168, 0.07);
  --v-sep-glow: rgba(61, 186, 168, 0.32);

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4);
}

/* Old variable names kept as aliases, in case older markup still uses them */
:root { --cyan: var(--accent); --glass-bg: var(--bg-card); --glass-border: var(--border); --card-shadow: var(--shadow-md); }

/* ----------------------------------------------------------------
   2. BASE RESET AND GLOBAL ELEMENT STYLES
   Browser default spacing removed, then the basic look of the
   page (body font, headings, links, scrollbar, text selection).
   ---------------------------------------------------------------- */
* { box-sizing: border-box; margin: 0; padding: 0; }

/* overflow-x lives on body, not html — avoids an implicit overflow-y:auto
   some browsers apply to an element with overflow-x set but overflow-y
   left unset. */
html { scroll-behavior: smooth; }

body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.7;
  color: var(--fg);
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.3s ease, color 0.3s ease;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  overflow-x: hidden;
}
.site-main { flex: 1 0 auto; }
footer { flex-shrink: 0; }

h1, h2, h3, h4 { font-family: var(--serif); font-weight: 700; letter-spacing: -0.01em; line-height: 1.25; color: var(--fg); }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }

::selection { background: var(--accent); color: #fff; }
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--bg-alt); }
::-webkit-scrollbar-thumb { background: var(--accent); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent-hover); }

/* ----------------------------------------------------------------
   3. NAVBAR
   A floating pill fixed to the top of every page (position:fixed): logo,
   page links, and search/theme/join buttons, all grouped together and
   centred. Below 900px width the page links and join button are
   replaced by a hamburger button that opens the mobile menu.
   ---------------------------------------------------------------- */
#navbar {
  position: fixed;
  top: 12px;
  left: 0;
  right: 0;
  margin: 0 auto;
  width: fit-content;
  max-width: calc(100% - 24px);
  z-index: 100;
  background: transparent;
  border: 0.5px solid rgba(15, 118, 110, 0.45);
  border-radius: 10px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.10);
  height: 42px;
  transform: translateZ(0);
  will-change: transform;
  transition: box-shadow var(--t-base), border-color var(--t-base), height var(--t-base);
}
/* The frost lives on this pseudo, not on #navbar itself. backdrop-filter
   directly on a position:fixed element is a known mobile-browser
   compositing bug — Safari/Chrome mobile can stop repainting a fixed +
   backdrop-filter element during scroll, making it appear to not be fixed
   at all. translateZ(0) + will-change force a dedicated GPU layer for the
   pseudo so it keeps repainting correctly while scrolling. */
#navbar::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: -1;
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  transform: translateZ(0);
  will-change: transform;
  contain: paint;
}
.dark #navbar { border-color: rgba(61, 186, 168, 0.45); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4); }
.dark #navbar::before { background: rgba(28, 27, 24, 0.55); }
#navbar.scrolled { box-shadow: 0 8px 30px rgba(0, 0, 0, 0.18); }
.dark #navbar.scrolled { box-shadow: 0 8px 30px rgba(0, 0, 0, 0.55); }
/* 42px by default (there's no separate desktop size — this applies
   everywhere above 900px too), 44px below 900px — mobile is very
   slightly taller here, not shorter. */
@media (max-width: 900px) { #navbar { height: 44px; } }

.nav-inner {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 6px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
}
@media (min-width: 640px) { .nav-inner { padding: 0 8px; gap: 24px; } }
@media (max-width: 399px) { .nav-inner { padding: 0 4px; gap: 10px; } }
.logo { display: flex; align-items: center; height: 100%; flex-shrink: 0; min-width: 0; text-decoration: none; }
.logo-lockup { height: 100%; width: auto; max-width: 100%; display: block; }
.logo-text { font-family: var(--serif); font-weight: 700; font-size: 13px; letter-spacing: 0; }
.word-microbial { color: var(--emerald); }
.word-genomics { color: var(--amber); }
.word-amp { color: var(--muted); }
.word-bio { color: var(--blue); }

.nav-links {
  display: flex;
  gap: 6px;
  font-family: var(--sans);
}
.nav-links a {
  color: var(--fg);
  text-transform: uppercase;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 5px 8px;
  border-radius: var(--radius-sm);
  position: relative;
  transition: color var(--t-fast), background-color var(--t-fast);
}
.nav-links a::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 2px;
  width: 0;
  height: 2px;
  background: var(--accent);
  transform: translateX(-50%);
  transition: width var(--t-fast);
}
.nav-links a:hover, .nav-links a.active { color: var(--accent); background: var(--accent-light); }
.nav-links a:hover::after, .nav-links a.active::after { width: 75%; }

.nav-utils {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 4px;
}
@media (min-width: 900px) { .nav-utils { gap: 2px; padding: 3px; } }
.nav-icon-btn {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-full);
  border: 1px solid transparent;
  transition: all var(--t-fast);
  display: flex;
  align-items: center;
  justify-content: center;
}
.nav-icon-btn:hover { color: var(--accent); border-color: var(--border); background: var(--accent-light); }
.nav-icon-btn i { font-size: 13px; }
@media (min-width: 900px) {
  .nav-icon-btn { width: 26px; height: 26px; }
  .nav-icon-btn i { font-size: 11px; }
}
#hamburger {
  display: none;
  background: var(--accent);
  border: none;
  border-radius: var(--radius-full);
  color: #fff;
  cursor: pointer;
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  transition: background var(--t-fast);
}
#hamburger:hover { background: var(--accent-hover); }

.join-btn {
  padding: 7px 16px;
  border-radius: var(--radius-full);
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  border: none;
  cursor: pointer;
  font-family: var(--sans);
  transition: background var(--t-fast);
}
.join-btn:hover { background: var(--accent-hover); color: #fff; }
@media (min-width: 900px) { .join-btn { padding: 5px 12px; font-size: 11px; } }

/* Mobile menu: a small side panel that drops down from the navbar,
   used instead of the page links and join button under 900px width. */
#mobile-menu {
  display: none;
  position: fixed;
  top: 56px;
  left: 50%;
  bottom: auto;
  width: 220px;
  max-width: 80vw;
  background: transparent;
  z-index: 99;
  flex-direction: column;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.68);
  border-radius: 14px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  transform-origin: top center;
  transform: translateX(-50%) translateY(-10px);
  will-change: transform;
  opacity: 0;
  visibility: hidden;
  transition: transform var(--t-base), opacity var(--t-base), visibility 0s linear var(--t-base);
}
/* Same reasoning as #navbar::before — frost lives on a pseudo, not on the
   fixed element itself, with a forced GPU layer so it keeps repainting
   correctly on mobile while the menu is open and the page scrolls. */
#mobile-menu::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: -1;
  background: rgba(255, 255, 255, 0.68);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  transform: translateZ(0);
  will-change: transform;
  contain: paint;
}
.dark #mobile-menu { border-color: rgba(28, 27, 24, 0.68); }
.dark #mobile-menu::before { background: rgba(28, 27, 24, 0.68); }
@media (max-width: 900px) { #mobile-menu { display: flex; } }
#mobile-menu.open {
  transform: translateX(-50%) translateY(0);
  opacity: 1;
  visibility: visible;
  transition: transform var(--t-base), opacity var(--t-base);
}
#mobile-menu a, #mobile-menu button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--fg);
  padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
}
#mobile-menu a:last-child, #mobile-menu button:last-child { border-bottom: none; }
#mobile-menu a:hover, #mobile-menu button:hover { background: var(--accent-light); color: var(--accent); }

@media (max-width: 900px) {
  .nav-links { display: none; }
  #hamburger { display: flex; }
  .nav-utils { border: none; padding: 0; }
}
@media (max-width: 480px) {
  .join-btn { display: none; }
  .nav-utils { gap: 2px; }
}

/* ----------------------------------------------------------------
   4. SHARED LAYOUT PIECES
   Building blocks reused across every page: the max-width wrapper
   each section sits in, the thin animated line down each side of
   the page on wide screens, section titles and labels, chips,
   badges, buttons, and small helpers like scroll-reveal.
   ---------------------------------------------------------------- */
.page-section { max-width: var(--container-max); margin: 0 auto; padding: 36px 24px; scroll-margin-top: 76px; }

/* Vertical separator lines down the left and right edge of each
   section, visible on screens 1200px and wider. Purely decorative. */
@keyframes flowVerticalLine {
  0% { background-position: 0 0; }
  100% { background-position: 0 200%; }
}
@media (min-width: 1200px) {
  .page-section, .footer-inner, .home-banner { position: relative; }
  .page-section::before, .page-section::after, .footer-inner::before, .footer-inner::after, .home-banner::before, .home-banner::after {
    content: '';
    position: absolute;
    top: 1.5rem;
    bottom: 1.5rem;
    width: 1px;
    z-index: 1;
    pointer-events: none;
    background-size: 100% 200%;
    animation: flowVerticalLine 24s linear infinite;
  }
  .footer-inner::before, .footer-inner::after { top: 0.5rem; bottom: 0.5rem; }
  .page-section::before, .footer-inner::before, .home-banner::before {
    left: -0.5px;
    background: linear-gradient(to bottom, var(--v-sep-color) 0%, var(--v-sep-glow) 50%, var(--v-sep-color) 100%);
  }
  .page-section::after, .footer-inner::after, .home-banner::after {
    right: -0.5px;
    background: linear-gradient(to bottom, var(--v-sep-color) 0%, var(--v-sep-glow) 50%, var(--v-sep-color) 100%);
  }
}
.section-label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
  display: block;
  margin-bottom: 8px;
}
.section-title { font-size: clamp(24px, 3vw, 32px); margin-bottom: 8px; color: var(--accent); }
.section-desc { color: var(--muted); font-size: 15px; line-height: 1.7; max-width: 640px; margin-bottom: 20px; }

.chip {
  display: inline-flex;
  align-items: center;
  padding: 3px 12px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  border-radius: var(--radius-full);
  background: var(--accent-light);
  color: var(--accent);
  border: 1px solid var(--accent);
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.chip.chip-muted { background: var(--bg-alt); color: var(--muted); border-color: var(--border); }
.chip-container { display: flex; flex-wrap: wrap; gap: 6px; }

/* Tags with a matching entry in MGB_GLOSSARY (see markGlossaryChips() in
   scripts.js) get a dotted underline and a pointer cursor to signal they're
   clickable, opening the definition popover below. */
.chip-glossary { cursor: pointer; text-decoration: underline dotted; text-underline-offset: 2px; }
.chip-glossary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The tag-definition popover, appended once to <body> and positioned in JS
   next to whichever chip was clicked. */
.glossary-popover {
  display: none;
  position: fixed;
  z-index: 10000;
  max-width: 280px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 12px 14px;
  font-family: var(--sans);
}
.glossary-popover.open { display: block; }
.glossary-popover strong { display: block; margin-bottom: 4px; font-size: 13px; color: var(--accent); }
.glossary-popover p { margin: 0; font-size: 13px; line-height: 1.55; color: var(--fg); }

.badge {
  display: inline-block;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  padding: 2px 10px;
  border-radius: var(--radius-full);
  background: var(--accent-light);
  color: var(--accent);
  border: 1px solid var(--accent);
}
.badge.badge-fg { background: var(--bg-alt); color: var(--fg); border-color: var(--border); }

.btn-primary, .btn-outline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 18px;
  border-radius: var(--radius-full);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: all var(--t-fast);
  border: 1px solid transparent;
}
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-hover); color: #fff; }
.btn-outline { background: transparent; color: var(--fg); border-color: var(--border); }
.btn-outline:hover { border-color: var(--accent); color: var(--accent); }

.text-link {
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.text-link:hover { color: var(--accent-hover); }

[data-reveal] { opacity: 0; transform: translateY(12px); transition: opacity 0.5s ease, transform 0.5s ease; }
[data-reveal].revealed { opacity: 1; transform: none; }

.line-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.line-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* ----------------------------------------------------------------
   5. HOME PAGE HERO
   The top section of the home page: the photo slideshow, the main
   heading, the short description, and the topic chips underneath.
   ---------------------------------------------------------------- */
.home-banner {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 33px 24px 32px;
}
/* The navbar is position:fixed, so it reserves no space in the document
   flow — this top padding is set to roughly (navbar's top offset + half its
   own height), so the hero photo begins right at the navbar's vertical
   midpoint: the top half of the bar sits over blank page, the bottom half
   overlaps the photo. */
/* The research pillar boxes sit in a .page-section right after the hero.
   Its own top padding would double up with the hero's bottom padding
   above, so pull it in tight here. */
.home-banner + .page-section { padding-top: 4px; }
.home-banner h1 { font-size: clamp(28px, 4vw, 40px); margin-bottom: 12px; max-width: none; text-align: center; }
.hero-line-problem { color: var(--amber); }
.hero-line-dash { color: var(--faint); }
.hero-line-solution { color: var(--emerald); }
.home-banner .section-desc { font-size: 16px; margin-bottom: 16px; max-width: 800px; margin-left: auto; margin-right: auto; text-align: center; }
.home-slideshow, .group-photo { height: 300px; }
@media (min-width: 640px) { .home-slideshow, .group-photo { height: 380px; } }
@media (min-width: 900px) { .home-slideshow, .group-photo { height: 460px; } }
@media (min-width: 1400px) { .home-slideshow, .group-photo { height: 500px; } }
@media (min-width: 1600px) { .home-slideshow, .group-photo { height: 540px; } }
.group-photo { height: 360px; }
@media (min-width: 640px) { .group-photo { height: 460px; } }
@media (min-width: 900px) { .group-photo { height: 560px; } }
@media (min-width: 1400px) { .group-photo { height: 620px; } }
@media (min-width: 1600px) { .group-photo { height: 680px; } }
.home-banner .chip-container { margin-bottom: 16px; justify-content: center; }
.home-banner .chip-container .chip:hover { background: var(--accent); color: #fff; }

.photo-frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--bg);
}
.photo-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px dashed var(--border);
  color: var(--faint);
  text-align: center;
}
.photo-placeholder i { font-size: 28px; opacity: 0.6; }
.photo-placeholder span { font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.photo-frame > img.fill-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.photo-frame img.slide-fade, .photo-frame video.slide-fade, .photo-frame div.slide-fade {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1.2s ease;
}
.photo-frame img.slide-fade.active, .photo-frame video.slide-fade.active, .photo-frame div.slide-fade.active { opacity: 1; }
.photo-frame img.slide-fade, .photo-frame video.slide-fade, .photo-frame div.slide-fade { touch-action: pan-y; user-select: none; -webkit-user-drag: none; }
.slide-combo { display: flex; }
.slide-combo img, .slide-combo video { width: 50%; height: 100%; object-fit: cover; display: block; }
.slide-dots { position: absolute; left: 0; right: 0; bottom: 14px; z-index: 2; display: flex; justify-content: center; gap: 10px; }
.slide-dot {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, 0.6);
  cursor: pointer;
  padding: 0;
  background: rgba(255, 255, 255, 0.2);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  transition: border-color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
}
.slide-dot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.slide-dot.active { border-color: var(--accent); transform: scale(1.18); box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.5), 0 2px 6px rgba(0, 0, 0, 0.3); }
@media (max-width: 399px) {
  .slide-dot { width: 26px; height: 26px; }
}

/* ----------------------------------------------------------------
   6. PROFILE CARDS (People page)
   One card per person, grouped by category (Group Leader,
   Postdoctoral Researchers, PhD Students, and so on). Each
   category gets its own accent colour, used for the hover border,
   the name, chips, and the heading pill above the group.
   ---------------------------------------------------------------- */
.profile-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 20px;
  transition: box-shadow var(--t-base), border-color var(--t-base), transform var(--t-base);
}
/* One accent colour per category, used by the hover rules below via var(--cat-accent) */
.cat-postdocs { --cat-accent: #2563eb; }
.cat-phd { --cat-accent: #7c3aed; }
.cat-masters { --cat-accent: #d97706; }
.cat-bachelors { --cat-accent: #db2777; }
.cat-others { --cat-accent: #475569; }
.cat-alumni { --cat-accent: #78716c; }
.profile-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--cat-accent, var(--accent));
  transform: translateY(-3px);
}
.profile-card:hover .profile-name { color: var(--cat-accent, var(--accent)); }
.profile-card:hover .profile-chips .chip {
  background: var(--cat-accent, var(--accent));
  color: #fff;
  border-color: var(--cat-accent, var(--accent));
}
.profile-card:hover .profile-photo, .profile-card:hover .profile-initials {
  box-shadow: 0 0 0 1px var(--cat-accent, var(--accent));
}
.profile-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}
/* Alumni cards intentionally carry no bio/tags, so drop the header's
   trailing margin when it's the only thing in the card (no dangling gap
   between it and the card's own bottom padding). */
.profile-card > .profile-header:last-child { margin-bottom: 0; }
.profile-header-left {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.profile-photo {
  width: 68px;
  height: 68px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  border: 2px solid var(--bg);
  box-shadow: 0 0 0 1px var(--border);
  transition: border-color var(--t-base), box-shadow var(--t-base);
}
.profile-initials {
  width: 68px;
  height: 68px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-weight: 700;
  border: 2px solid var(--bg);
  box-shadow: 0 0 0 1px var(--border);
  transition: border-color var(--t-base), box-shadow var(--t-base);
  font-size: 22px;
  color: #fff;
  flex-shrink: 0;
}
.profile-name { font-family: var(--serif); font-size: 16px; font-weight: 700; margin-bottom: 2px; text-align: left; }
.profile-title { font-size: 11px; color: var(--muted); text-align: left; }
/* Bio text is always justified, even on the centred Group Leader card,
   so name and title can be centred while the paragraph itself stays readable. */
.profile-bio { font-size: 13px; color: var(--muted); text-align: justify; margin-bottom: 10px; }
/* Alumni cards only ever show a photo, name, role, and LinkedIn link (no
   bio/tags by design), so they run noticeably smaller than the other
   category cards instead of reserving the same padding/avatar size for
   content that's never there. */
.profile-card.cat-alumni { padding: 14px 16px; }
.profile-card.cat-alumni .profile-photo,
.profile-card.cat-alumni .profile-initials { width: 48px; height: 48px; font-size: 16px; }
.profile-card.cat-faculty .profile-name,
.profile-card.cat-faculty .profile-title { text-align: center; }
.profile-card.cat-faculty .profile-chips { justify-content: center; }
.profile-bio-full { display: none; }
.profile-bio-full.open { display: block; }
.profile-bio-short.hidden { display: none; }
.profile-bio-toggle { font-size: 12px; float: right; margin-left: 8px; background: none; border: none; padding: 0; cursor: pointer; font-family: var(--sans); white-space: nowrap; }
.profile-card-toggleable { cursor: pointer; }
.profile-chips { display: flex; flex-wrap: wrap; gap: 5px; justify-content: flex-start; margin-bottom: 12px; }
.profile-links {
  display: flex;
  flex-shrink: 0;
  gap: 2px;
}
.profile-links .icon-link { width: 34px; height: 34px; font-size: 14px; }
.profile-links .icon-link .fa-envelope { color: #2563eb; }
.profile-links .icon-link .fa-orcid { color: #a6ce39; }
.profile-links .icon-link .fa-globe { color: #059669; }
.profile-links .icon-link .fa-linkedin { color: #0a66c2; }
.profile-links .icon-link:hover { background: var(--accent-light); }
.icon-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-full);
  color: var(--muted);
  font-size: 13px;
  transition: all var(--t-fast);
}
.icon-link:hover { color: var(--accent); background: var(--accent-light); }
.icon-link-dummy { opacity: 0.35; cursor: default; }
.icon-link-dummy:hover { background: none; }
.icon-link-dummy i { color: var(--faint) !important; }

/* Category groups and the grid of cards inside each one. A group with
   only one person (the Group Leader, or a category pruned down to one
   real person) gets the people-grid-solo layout instead of a full grid. */
.people-section { margin-bottom: 32px; }
.people-section > .section-label, .alumni-toggle .section-label {
  text-align: center;
  display: block;
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
  padding: 4px 14px;
  border-radius: var(--radius-full);
  transition: background var(--t-fast), color var(--t-fast);
}
.people-section:has(.profile-card:hover) .section-label {
  background: var(--cat-accent, var(--accent));
  color: #fff;
}
.alumni-toggle {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px 0;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.alumni-toggle-icon { position: absolute; right: 0; }
.alumni-toggle-icon { color: var(--muted); font-size: 12px; transition: transform var(--t-base); }
.alumni-toggle[aria-expanded="true"] .alumni-toggle-icon { transform: rotate(180deg); }
.people-grid.alumni-grid { display: none; }
.people-grid.alumni-grid.open { display: grid; }
.people-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}
@media (min-width: 700px) {
  .people-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 761px) {
  .people-grid { grid-template-columns: repeat(3, 1fr); }
  .people-grid.people-grid-duo { grid-template-columns: repeat(2, 1fr); }
  .people-grid.people-grid-solo { grid-template-columns: 1fr; max-width: 520px; }
  .people-section.cat-faculty .people-grid.people-grid-solo { margin: 0 auto; }
}

/* ----------------------------------------------------------------
   7. ACADEMIC CARDS (Research, Projects, News)
   The shared card style used for research pillar cards and project
   cards, plus the two-column layout that puts the news ticker next
   to the projects list.
   ---------------------------------------------------------------- */
.card-academic {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--t-base), border-color var(--t-base);
}
.card-academic:hover { box-shadow: var(--shadow-md); border-color: var(--accent); }
.card-academic:hover .chip-container .chip { background: var(--accent); color: #fff; border-color: var(--accent); }
.card-academic h3 { font-size: 16px; margin-bottom: 6px; }
.card-academic p { font-size: 13.5px; color: var(--muted); margin-bottom: 10px; }
/* Tool cards are whole-card links (to each tool's GitHub repo), unlike the
   plain divs the other card-academic renderers use. */
.tool-card { display: block; color: inherit; text-decoration: none; }
.tool-card:hover h3 { color: var(--accent); }
/* Finished projects hover in red instead of the usual accent teal, so a
   glance at the hover colour tells active and wrapped-up projects apart. */
.card-project-finished:hover { border-color: var(--danger); box-shadow: var(--shadow-md); }
.card-project-finished:hover .chip-container .chip { background: var(--danger); color: #fff; border-color: var(--danger); }

.research-pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px;
}
/* Projects grid: a fixed 2-column grid, filled in normal reading order
   (left to right, top to bottom) — since renderProjects always sorts
   Active projects before Finished ones, that reading order is also what
   keeps every Active project ahead of every Finished one on screen. */
.project-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
}
@media (max-width: 639px) {
  .project-grid { grid-template-columns: 1fr; }
}
/* Projects on the left, news on the right, side by side from 900px up */
.projects-news-grid { display: grid; grid-template-columns: 1fr; gap: 40px; align-items: start; }
@media (min-width: 900px) {
  .projects-news-grid { grid-template-columns: 1.6fr 1fr; }
  .news-col { border-left: 1px solid var(--border); padding-left: 32px; }
}

/* News ticker: a fixed-height box that auto-scrolls through the news
   cards (driven from JS, see initNewsAutoScroll in scripts.js) and loops
   back to the top. The native scrollbar is hidden so it still looks like
   a ticker, but a visitor's own wheel/touch scroll pauses the auto-scroll
   for a few seconds so they can read at their own pace. The mask fades
   the top and bottom edges so items don't appear to cut off abruptly. */
.news-ticker {
  position: relative;
  max-height: 400px;
  overflow-y: auto;
  overflow-x: hidden;
  border-radius: var(--radius-lg);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
  scrollbar-width: none;
}
.news-ticker::-webkit-scrollbar { display: none; }

/* ----------------------------------------------------------------
   8. PUBLICATIONS AND NEWS LIST ROWS
   Publications render as compact list rows; news renders as its
   own boxy card style further down. Shared hover styling for both.
   ---------------------------------------------------------------- */
.pub-entry, .news-entry {
  padding: 16px 12px;
  margin: 0 -12px;
  border: 1px solid transparent;
  border-bottom-color: var(--border);
  border-radius: var(--radius-md);
  position: relative;
  transition: border-color var(--t-base);
}
.pub-entry:last-child { border-bottom-color: transparent; }
.pub-entry:hover, .news-entry:hover {
  border-color: var(--accent);
}
.pub-entry:hover .pub-title, .news-entry:hover .news-title { color: var(--accent); }
.pub-entry:hover .chip-container .chip { background: var(--accent); color: #fff; border-color: var(--accent); }
.pub-title, .news-title { font-size: 15.5px; font-weight: 600; color: var(--fg); line-height: 1.4; }
.pub-authors { font-size: 13px; color: var(--muted); font-style: italic; margin-top: 2px; }
.news-date { font-size: 12px; color: var(--faint); }
.pub-meta, .news-meta { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; flex-wrap: wrap; }
.pub-doi { font-family: var(--mono); }
.pub-doi:hover { background: var(--accent-light); color: var(--accent); border-color: var(--accent); }

/* Publications list scrolls inside a fixed-height panel; the round
   button below it jumps forward one screen at a time, and loops back
   to the top once the list is scrolled to the bottom. */
.pub-panel { position: relative; }
.pub-panel .scrollable-list {
  max-height: 620px;
  overflow-y: auto;
  overflow-x: hidden;
  scroll-behavior: smooth;
  padding-bottom: 8px;
}
.scroll-more-btn {
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: var(--accent);
  color: #fff;
  border-radius: 50%;
  cursor: pointer;
  border: none;
  box-shadow: var(--shadow-md);
  transition: transform var(--t-fast), background var(--t-fast);
  z-index: 5;
}
.scroll-more-btn:hover { background: var(--accent-hover); transform: translateX(-50%) translateY(3px) scale(1.08); }

.news-entry {
  margin: 0 0 14px 0;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: flex-start;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}
.news-entry:hover { border-color: var(--accent); box-shadow: var(--shadow-md); }
.news-avatar { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.news-body { min-width: 0; flex: 1; }
.news-desc { color: var(--muted); font-size: 13.5px; margin-top: 4px; }

/* ----------------------------------------------------------------
   9. BLOG
   The blog list (small preview cards) and the full blog post view,
   which is reached by clicking a card and replaces the page content.
   ---------------------------------------------------------------- */
.blog-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; align-items: start; }
.blog-card {
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  color: var(--fg);
  border: 1px solid var(--border);
  background: var(--bg-card);
  cursor: pointer;
  transition: border-color var(--t-base);
}
.blog-card:hover { border-color: var(--accent); }
.blog-cover { height: 140px; background: var(--bg-alt); overflow: hidden; }
.blog-cover img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s; }
.blog-card:hover .blog-cover img { transform: scale(1.04); }
.blog-body { padding: 16px 18px; flex: 1; display: flex; flex-direction: column; }
.blog-body > .text-link { margin-top: auto; }
.blog-meta-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.blog-date { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--accent); }
.blog-title { display: block; font-family: var(--serif); font-size: 17px; font-weight: 700; line-height: 1.3; margin-bottom: 6px; color: inherit; text-decoration: none; }
.blog-card:hover .blog-title { color: var(--accent); }
.blog-desc { color: var(--muted); font-size: 13px; margin-bottom: 12px; }
.blog-author-link { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; color: var(--muted); flex-shrink: 0; }
.blog-author-link:hover { color: var(--accent); }
.blog-author-link .fa-linkedin { font-size: 13px; color: #0a66c2; }

.blog-post-topbar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px; margin-bottom: 24px; }
.blog-post-topbar > :first-child { justify-self: start; }
.blog-post-topbar > :last-child { justify-self: end; }
@media (max-width: 640px) {
  .blog-post-topbar { grid-template-columns: 1fr; justify-items: center; text-align: center; gap: 10px; }
  .blog-post-topbar > :first-child, .blog-post-topbar > :last-child { justify-self: center; }
}
.blog-post-cover { width: 100%; max-height: 320px; object-fit: cover; border-radius: var(--radius-lg); margin-bottom: 28px; }
.blog-post-header { text-align: center; max-width: 720px; margin: 0 auto 28px; }
.blog-post-title { font-size: clamp(26px, 4vw, 38px); margin-bottom: 12px; }
.blog-post-body { max-width: 680px; margin: 0 auto; font-size: 16px; line-height: 1.8; text-align: justify; }
.blog-post-body h2 { font-size: 22px; margin-top: 32px; margin-bottom: 10px; }
.blog-post-body h3 { font-size: 18px; margin-top: 24px; margin-bottom: 8px; }
.blog-post-body p { color: var(--muted); margin-bottom: 16px; }
.blog-post-body ul { color: var(--muted); padding-left: 22px; margin-bottom: 16px; }
.blog-post-body li { margin-bottom: 6px; }
.blog-post-body strong { color: var(--fg); }
.blog-post-body code { font-family: var(--mono); background: var(--accent-light); padding: 2px 6px; border-radius: 4px; color: var(--accent); font-size: 0.88em; }

/* ----------------------------------------------------------------
   10. FORMS AND THE JOIN US POPUP
   Shared input styling used by the Join Us form, plus the popup
   (overlay and centred box) that the form sits inside. The popup
   opens when the "Join Us" button in the navbar or mobile menu
   is clicked.
   ---------------------------------------------------------------- */
.form-label { display: block; font-family: var(--mono); font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin-bottom: 6px; }
.form-input, .form-select, .form-textarea {
  width: 100%;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 11px 14px;
  color: var(--fg);
  font-family: var(--sans);
  font-size: 15px;
  transition: border-color var(--t-fast);
}
.form-input:focus, .form-select:focus, .form-textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-light); }
.form-select { appearance: none; }

.join-overlay {
  position: fixed; inset: 0; z-index: 9998;
  display: flex; align-items: flex-start; justify-content: center;
  padding: clamp(24px, 6vh, 70px) 16px;
  overflow-y: auto;
  opacity: 0; pointer-events: none;
  transition: opacity 0.18s ease;
  background: rgba(28, 27, 24, 0.55);
}
.join-overlay.join-open { opacity: 1; pointer-events: auto; }
.join-modal {
  position: relative;
  width: min(560px, 100%);
  background: var(--bg-card);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  padding: 32px;
  transform: translateY(-12px) scale(0.98);
  transition: transform 0.2s ease, opacity 0.18s ease;
  opacity: 0;
}
.join-overlay.join-open .join-modal { transform: translateY(0) scale(1); opacity: 1; }
.join-modal-close {
  position: absolute;
  top: 14px; right: 14px;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  background: none;
  border: none;
  border-radius: var(--radius-full);
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.join-modal-close:hover { background: var(--bg-alt); color: var(--fg); }
@media (max-width: 600px) { .join-modal { padding: 24px 20px; } }

/* ----------------------------------------------------------------
   11. COMMAND PALETTE SEARCH
   The search popup opened with the search icon or Ctrl/Cmd+K.
   Same overlay and centred box pattern as the Join Us popup above.
   ---------------------------------------------------------------- */
.srch-overlay {
  position: fixed; inset: 0; z-index: 9998;
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: clamp(48px, 8vh, 90px);
  opacity: 0; pointer-events: none;
  transition: opacity 0.18s ease;
  background: rgba(28, 27, 24, 0.55);
}
.srch-overlay.srch-open { opacity: 1; pointer-events: auto; }
.srch-box {
  width: min(600px, 92vw);
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), 0 0 0 1px var(--border);
  overflow: hidden;
  display: flex; flex-direction: column;
  max-height: 70vh;
  transform: translateY(-12px) scale(0.98);
  transition: transform 0.2s ease, opacity 0.18s ease;
  opacity: 0;
}
.srch-overlay.srch-open .srch-box { transform: translateY(0) scale(1); opacity: 1; }
.srch-header { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.srch-icon-lbl { color: var(--muted); font-size: 15px; }
.srch-input { flex: 1; border: none; background: transparent; font-size: 15px; color: var(--fg); outline: none; font-family: var(--sans); }
.srch-input::placeholder { color: var(--faint); }
.srch-kbd { display: flex; gap: 4px; }
.srch-key { background: var(--bg-alt); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 2px 6px; font-size: 10px; color: var(--muted); font-family: var(--mono); }
.srch-body { overflow-y: auto; flex: 1; }
.srch-section-hd {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 18px 4px;
  font-family: var(--mono); font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--faint); position: sticky; top: 0; background: var(--bg-card);
}
.srch-badge { background: var(--accent); color: #fff; border-radius: var(--radius-full); padding: 1px 7px; font-size: 10px; font-weight: 700; min-width: 18px; text-align: center; }
.srch-item { display: flex; align-items: center; gap: 12px; padding: 9px 18px; cursor: pointer; border-left: 2px solid transparent; }
.srch-item:hover, .srch-item.srch-active { background: var(--accent-light); border-left-color: var(--accent); }
.srch-item-icon { width: 30px; height: 30px; border-radius: var(--radius-md); background: var(--bg-alt); display: flex; align-items: center; justify-content: center; font-size: 12px; color: var(--accent); flex-shrink: 0; }
.srch-item-body { flex: 1; min-width: 0; }
.srch-item-title { font-size: 13.5px; font-weight: 600; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.srch-item-title mark, .srch-item-excerpt mark { background: var(--accent-light); color: var(--accent); border-radius: 2px; font-style: normal; }
.srch-item-excerpt { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.srch-item-cat { font-size: 9px; font-weight: 700; color: var(--accent); background: var(--accent-light); border-radius: var(--radius-full); padding: 2px 8px; flex-shrink: 0; }
.srch-pills { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 18px; border-bottom: 1px solid var(--border); }
.srch-pill { background: var(--bg-alt); border: 1px solid var(--border); border-radius: var(--radius-full); padding: 3px 11px; font-size: 11px; font-weight: 600; color: var(--fg); cursor: pointer; }
.srch-pill:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.srch-footer { display: flex; gap: 14px; padding: 8px 18px; border-top: 1px solid var(--border); flex-wrap: wrap; }
.srch-hint { display: flex; align-items: center; gap: 5px; font-size: 10px; color: var(--faint); }
.srch-empty { text-align: center; padding: 28px 20px; color: var(--faint); font-size: 13px; }
.srch-empty i { font-size: 1.6rem; margin-bottom: 8px; display: block; }
.srch-flash { outline: 2px solid var(--accent) !important; outline-offset: 4px !important; }

@media (max-width: 600px) {
  .srch-overlay { padding-top: calc(56px + env(safe-area-inset-top)); }
  .srch-box { width: calc(100vw - 24px); max-height: calc(100vh - 24px - env(safe-area-inset-top)); }
}

/* ----------------------------------------------------------------
   12. FOOTER
   The bar at the bottom of every page: logo, GitHub link, and the
   copyright line. The back-to-top button further down is fixed to
   the screen, not part of the footer itself, but lives in this
   section because it is closely related.
   ---------------------------------------------------------------- */
footer { border-top: 1px solid var(--border); background: var(--bg-alt); margin-top: 32px; padding: 8px 0; }
footer .logo-lockup { height: 24px; }
@media (min-width: 640px) { footer .logo-lockup { height: 30px; } }
.footer-inner { max-width: var(--container-max); margin: 0 auto; padding: 0 24px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 16px 32px; }
.footer-brand { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.footer-inner p { font-size: 11px; color: var(--faint); text-transform: uppercase; letter-spacing: 0.04em; }
@media (max-width: 700px) {
  .footer-inner { flex-direction: column; text-align: center; gap: 20px; }
  .footer-brand { justify-content: center; }
}

/* Back to top button: a circular ring that fills in as the page scrolls */
/* #scroll-to-top (id selector) guards position:fixed against the [data-tip] attribute rule below, which shares .back-to-top's specificity and would otherwise win by source order */
#scroll-to-top { position: fixed; }
.back-to-top {
  position: fixed;
  bottom: 24px;
  right: 24px;
  width: 48px;
  height: 48px;
  background: var(--bg-card);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 15px;
  box-shadow: var(--shadow-md);
  cursor: pointer;
  z-index: 90;
  opacity: 0;
  transform: translateY(20px);
  pointer-events: none;
  transition: opacity var(--t-base), transform var(--t-base), border-color var(--t-fast), color var(--t-fast);
}
.back-to-top.visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
.back-to-top:hover { border-color: var(--accent); color: var(--accent); }
.progress-ring {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
  pointer-events: none;
}
.progress-ring__background { stroke: transparent; }
.progress-ring__circle { stroke: var(--accent); transition: stroke-dashoffset 0.1s linear; stroke-linecap: round; }

/* ----------------------------------------------------------------
   13. TOOLTIPS AND PAGE ROUTING
   Small text labels that appear on hover for any element with a
   data-tip attribute, plus the rules that show only one page
   section at a time.
   ---------------------------------------------------------------- */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute; bottom: 100%; left: 50%;
  transform: translateY(-6px) translateX(-50%);
  background: var(--fg); color: var(--bg);
  padding: 5px 10px; border-radius: var(--radius-sm);
  font-size: 11px; font-weight: 600; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity var(--t-fast);
  z-index: 2147483647;
}
[data-tip]:hover::after { opacity: 1; }
[data-tip].tip-visible::after { opacity: 1; }
@media (hover: none) {
  /* Touch devices: only show via the long-press JS below, never on a plain tap */
  [data-tip]:hover::after { opacity: 0; }
}
.nav-utils [data-tip]::after {
  bottom: auto; left: auto; top: 50%; right: 100%;
  transform: translateY(-50%) translateX(-8px);
}

/* Page router: only one page-view section is visible at a time */
.page-view { display: block; scroll-margin-top: 76px; }
.page-view + .page-view:not(#page-blog-post) > .page-section:first-child { border-top: 2px solid var(--divider); }
#page-blog-post { display: none; }
#page-blog-post.active { display: block; }
/* Opening a single blog post (e.g. from a shared link) hides every other
   section, so the post reads as its own page instead of sitting buried
   partway down the full scroll. */
body.viewing-blog-post .page-view:not(#page-blog-post) { display: none; }
/* handleRouting() scrolls straight to the very top of the document for this
   page, so — unlike every other section, which relies on scroll-margin-top
   because it's scrolled INTO view — this needs its own explicit top
   padding to clear the fixed navbar, or its content (the "Back to Blog"
   row) renders underneath the bar. */
#page-blog-post > .page-section { padding-top: 72px; }
