/* ---------- Design tokens ---------- */
/* Default = light. Dark applies via explicit [data-theme="dark"] (manual toggle)
   or via the system-preference media query when no manual choice has been made. */
:root {
  --bg: #fbfbfe;
  --bg-alt: #f0f2fc;
  --surface: #ffffff;
  --text: #1b1c1f;
  --text-muted: #5f6368;
  --border: #e3e6f3;

  --gemini-blue: #4c8df6;
  --gemini-purple: #a76dee;
  --gemini-pink: #f96a91;
  --gemini-gradient: linear-gradient(120deg, var(--gemini-blue) 0%, var(--gemini-purple) 55%, var(--gemini-pink) 100%);
  --gemini-gradient-soft: linear-gradient(120deg, rgba(76, 141, 246, 0.14) 0%, rgba(167, 109, 238, 0.14) 55%, rgba(249, 106, 145, 0.14) 100%);

  --shadow-sm: 0 1px 2px rgba(20, 20, 30, 0.06), 0 1px 3px rgba(20, 20, 30, 0.08);
  --shadow-md: 0 6px 16px rgba(20, 20, 30, 0.08), 0 2px 6px rgba(20, 20, 30, 0.06);
  --shadow-lg: 0 20px 48px rgba(20, 20, 30, 0.16), 0 6px 16px rgba(20, 20, 30, 0.08);

  --radius-lg: 20px;
  --radius-md: 14px;
  --radius-sm: 10px;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --font-fancy: "Playfair Display", Georgia, "Times New Roman", serif;
  --content-width: 1180px;

  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #131316;
  --bg-alt: #1a1b1f;
  --surface: #1e1f24;
  --text: #f1f2f4;
  --text-muted: #9a9da3;
  --border: #2c2e35;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 6px 16px rgba(0, 0, 0, 0.35);
  --shadow-lg: 0 20px 48px rgba(0, 0, 0, 0.5);

  color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #131316;
    --bg-alt: #1a1b1f;
    --surface: #1e1f24;
    --text: #f1f2f4;
    --text-muted: #9a9da3;
    --border: #2c2e35;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 6px 16px rgba(0, 0, 0, 0.35);
    --shadow-lg: 0 20px 48px rgba(0, 0, 0, 0.5);

    color-scheme: dark;
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--font);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.25s ease, color 0.25s ease;
}

a {
  color: inherit;
}

/* The hidden attribute must win over any display set by a class on the same
   element (e.g. .pub-list-view { display: flex }) — without this, toggling
   `hidden` silently does nothing once a class-based display rule exists. */
[hidden] {
  display: none !important;
}

h1, h2, h3, p, ol, ul {
  margin: 0;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: background-color 0.25s ease, border-color 0.25s ease;
}

/* ---------- Topbar ---------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.topbar-inner {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0.9rem 2rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

.wordmark-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  min-width: 0;
  text-decoration: none;
}

.wordmark {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: transparent;
  background-image: var(--gemini-gradient);
  -webkit-background-clip: text;
  background-clip: text;
}

.gradient-text {
  font-weight: 600;
  color: transparent;
  background-image: var(--gemini-gradient);
  -webkit-background-clip: text;
  background-clip: text;
}

/* ---------- Nav dropdown ---------- */
.nav-menu {
  position: relative;
  flex: 0 0 auto;
}

.nav-menu-dropdown {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  min-width: 190px;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.4rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 30;
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}

.nav-menu-dropdown.open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.nav-menu-dropdown a {
  display: block;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  transition: background 0.15s ease;
}

.nav-menu-dropdown a:hover {
  background: var(--bg-alt);
}

.tagline {
  font-size: 0.78rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.icon-links {
  display: flex;
  gap: 0.6rem;
  flex: 0 0 auto;
}

.icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--border);
  color: var(--text-muted);
  background: var(--surface);
  background-clip: padding-box;
  background-origin: padding-box;
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.icon-btn svg {
  width: 18px;
  height: 18px;
  flex: none;
}

.icon-btn:hover,
.icon-btn:focus-visible {
  color: #fff;
  border-color: transparent;
  background: var(--gemini-gradient);
  background-clip: padding-box;
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

/* ---------- Theme switch ---------- */
.theme-switch {
  flex: none;
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
}

.theme-switch-track {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 56px;
  height: 30px;
  padding: 0 7px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  transition: background-color 0.3s ease, border-color 0.3s ease;
}

.track-icon {
  width: 14px;
  height: 14px;
  color: var(--text-muted);
  position: relative;
  z-index: 1;
  transition: color 0.3s ease;
}

.theme-switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--gemini-gradient);
  box-shadow: var(--shadow-sm);
  transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}

.theme-switch.is-dark .theme-switch-thumb {
  transform: translateX(26px);
}

.theme-switch:hover .theme-switch-thumb {
  box-shadow: var(--shadow-md);
}

/* ---------- Layout ---------- */
main {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 3rem 2rem 5rem;
  display: flex;
  flex-direction: column;
  gap: 4.5rem;
}

.section-heading {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 0.4rem;
}

.section-subheading {
  color: var(--text-muted);
  font-size: 0.98rem;
}

/* ---------- Hero ---------- */
.hero {
  display: flex;
  align-items: center;
  gap: 3rem;
}

.photo-wrap {
  position: relative;
  flex: 0 0 240px;
  width: 240px;
  height: 240px;
}

.photo-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, var(--gemini-blue), var(--gemini-purple), var(--gemini-pink), var(--gemini-blue));
  filter: blur(20px);
  opacity: 0.5;
  z-index: 0;
  transition: opacity 0.4s ease;
}

.photo-wrap:hover::before {
  opacity: 0.95;
  animation: portrait-spin 3.5s linear infinite;
}

@keyframes portrait-spin {
  to {
    transform: rotate(360deg);
  }
}

.photo {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: var(--shadow-md);
  transition: box-shadow 0.4s ease, transform 0.4s ease;
}

.photo-wrap:hover .photo {
  transform: scale(1.02);
  box-shadow: var(--shadow-lg);
}

.bio {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 1.1rem;
  line-height: 1.7;
  color: var(--text);
}

.bio.panel {
  padding: 1.5rem 1.75rem;
}

.bio p {
  margin: 0 0 1.1rem;
}

.bio p:last-child {
  margin-bottom: 0;
}

.bio a,
.news-text a {
  font-weight: 600;
  text-decoration: none;
  background-image: var(--gemini-gradient);
  background-size: 100% 2px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  padding-bottom: 1px;
}

/* ---------- News timeline ---------- */
.news-section .section-heading {
  margin-bottom: 1.5rem;
}

.news-timeline {
  list-style: none;
  padding: 0;
  margin: 0;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  /* This list is empty until a fetch resolves, then gets populated in one
     shot — defensively opt out of the browser's scroll anchoring so a large,
     late DOM insertion here can never fight the hash-scroll correction in
     site/index.html (see the comment there for the fuller story). */
  overflow-anchor: none;
}

/* Positioned to pass through the center of the dot column below — keep the
   left offset in sync with .news-date width + .news-item gap + half the dot. */
.news-timeline::before {
  content: "";
  position: absolute;
  left: calc(4.5rem + 0.85rem + 7px);
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--gemini-gradient);
  opacity: 0.35;
}

.news-item {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.news-item.in-view {
  opacity: 1;
  transform: translateY(0);
}

.news-date {
  flex: 0 0 4.5rem;
  text-align: right;
  font-size: 0.8rem;
  font-weight: 700;
  color: transparent;
  background-image: var(--gemini-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  white-space: nowrap;
}

.news-dot {
  flex: 0 0 auto;
  position: relative;
  z-index: 1;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--gemini-gradient);
  box-shadow: 0 0 0 4px var(--bg-alt);
}

.news-card {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.85rem 1.1rem;
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  transition: box-shadow 0.2s ease;
}

.news-item:hover .news-card {
  box-shadow: var(--shadow-md);
}

.news-text {
  color: var(--text);
  font-size: 1rem;
  line-height: 1.5;
}

/* ---------- Publications header ---------- */
.publications-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: 1.75rem;
}

.publications-header .section-heading,
.publications-header .section-subheading {
  margin-bottom: 0.4rem;
}

.view-toggle {
  display: flex;
  flex: 0 0 auto;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}

.view-toggle-btn {
  position: relative;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font);
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.2s ease, background 0.2s ease;
}

.view-toggle-btn.active {
  color: #fff;
  background: var(--gemini-gradient);
  box-shadow: var(--shadow-sm);
}

.view-toggle-beta-badge {
  position: absolute;
  top: -7px;
  right: -8px;
  font-family: var(--font);
  font-size: 0.55rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: #fff;
  background: var(--gemini-gradient);
  padding: 1px 5px;
  border-radius: 999px;
  line-height: 1.35;
  box-shadow: var(--shadow-sm);
}

/* ---------- Publications graph ---------- */
.graph-container {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background:
    radial-gradient(circle at 15% 20%, rgba(76, 141, 246, 0.08), transparent 45%),
    radial-gradient(circle at 85% 80%, rgba(249, 106, 145, 0.08), transparent 45%),
    var(--bg-alt);
  overflow: hidden;
}

/* Whenever the real graph is swapped out for .graph-size-notice (too narrow
   a browser window, or an actual mobile device — see view-toggle.js), the
   4:3 aspect-ratio meant for the card simulation would leave a tall mostly-
   empty box under a short message. This applies at any width, since the
   notice can show on both a full mobile viewport and a merely-shrunk
   desktop window. */
.graph-container.size-notice-active {
  aspect-ratio: auto;
  height: auto;
  min-height: 280px;
}

#graph-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  /* Bubbles opt back in individually (see .tag-bubble) — the empty canvas
     must stay click/hover-through, or moving across it would keep a hover
     "alive" in dead space that isn't actually part of any bubble. */
  pointer-events: none;
}

.tag-bubble {
  pointer-events: fill;
  fill-opacity: 0.16;
  stroke-width: 1.5;
  stroke-opacity: 0.55;
  /* Translucent blobs read as naturally overlapping ink/light rather than
     stacked flat shapes when they cross — the two blend modes below are
     each tuned for their theme's background lightness. */
  mix-blend-mode: multiply;
}

:root[data-theme="dark"] .tag-bubble {
  mix-blend-mode: screen;
  fill-opacity: 0.14;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .tag-bubble {
    mix-blend-mode: screen;
    fill-opacity: 0.14;
  }
}

.graph-nodes {
  position: absolute;
  inset: 0;
}

/* The floating-card force simulation assumes room to spread cards out and
   fine pointer hover — neither holds up on a phone, so mobile gets this
   static message instead of the real graph (see view-toggle.js). */
.graph-size-notice {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 2rem 1.5rem;
  text-align: center;
}

.graph-size-notice-icon {
  width: 34px;
  height: 34px;
  color: var(--gemini-purple);
}

.graph-size-notice-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
}

.graph-size-notice-text {
  font-size: 0.9rem;
  color: var(--text-muted);
  max-width: 320px;
  line-height: 1.5;
}

.graph-size-notice-btn {
  margin-top: 0.4rem;
  border: none;
  border-radius: 999px;
  padding: 0.5rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: #fff;
  background: var(--gemini-gradient);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
}

.graph-node-card {
  position: absolute;
  top: 0;
  left: 0;
  /* Square — so the card's own box can double as its collision "bounding
     box" in graph.js, instead of needing a separate circle/rect distinction. */
  width: 112px;
  height: 112px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  padding: 0.35rem;
  gap: 0.25rem;
  cursor: pointer;
  overflow: hidden;
  transform-origin: center;
  will-change: transform;
  z-index: 1;
  /* transform itself is driven by graph.js every simulation tick, at up to
     60fps — transitioning it here would fight/lag the physics, so only the
     discrete state changes (dim, elevate) get a transition. */
  transition: opacity 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

.graph-node-card img {
  width: 100%;
  height: 52px;
  object-fit: contain;
  border-radius: 6px;
  background: var(--bg-alt);
  pointer-events: none;
}

.graph-node-thumb-empty {
  width: 100%;
  height: 52px;
  border-radius: 6px;
  background: var(--bg-alt);
}

.graph-node-title {
  font-size: 0.4rem;
  line-height: 1.15;
  color: var(--text-muted);
  /* No line-clamp/ellipsis here — titles run long (over 100 characters is
     common), and the point is to show the whole thing rather than cut it
     off. The font is sized small enough that even the longest title in the
     data wraps to fit within the card's fixed height; overflow:hidden on
     the card itself (not this element) is just a backstop. */
  overflow-wrap: break-word;
}

.graph-node-card.neighbor {
  z-index: 2;
  border-color: transparent;
  box-shadow: var(--shadow-md);
}

.graph-node-card.active {
  z-index: 3;
  border-color: transparent;
  box-shadow: var(--shadow-lg);
}

.graph-node-card.dimmed {
  opacity: 0.32;
}

/* ---------- Publications list view ---------- */
.pub-list-view {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.pub-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.pub-search,
.pub-select {
  font-family: var(--font);
  font-size: 0.9rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.85rem;
}

.pub-search {
  flex: 1 1 240px;
  min-width: 0;
}

.pub-search:focus,
.pub-select:focus {
  outline: 2px solid var(--gemini-purple);
  outline-offset: 1px;
}

.pub-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.9rem;
  color: var(--text-muted);
  padding: 0.55rem 0.2rem;
  cursor: pointer;
  user-select: none;
}

.pub-checkbox input {
  width: 16px;
  height: 16px;
  accent-color: var(--gemini-purple);
  cursor: pointer;
}

.pub-count {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.pub-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
  /* Same reasoning as .news-timeline above — this fills in async and is
     much larger. */
  overflow-anchor: none;
}

.pub-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.pub-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.pub-card img {
  width: 100%;
  height: 140px;
  object-fit: contain;
  background: var(--bg-alt);
}

.pub-card-body {
  padding: 1rem 1.1rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  flex: 1;
}

.pub-card h3 {
  font-size: 0.95rem;
  line-height: 1.35;
  font-weight: 700;
  color: var(--text);
}

.pub-card .pub-authors {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.pub-card .pub-venue {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
}

.author-highlight {
  font-weight: 700;
  color: transparent;
  background-image: var(--gemini-gradient);
  -webkit-background-clip: text;
  background-clip: text;
}

.award-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  width: fit-content;
  padding: 0.2rem 0.6rem;
  margin-bottom: 0.4rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(135deg, #f7c948, #e8940c);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.award-badge:hover,
.award-badge:focus-visible {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.award-badge svg {
  width: 13px;
  height: 13px;
}

.pub-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.3rem;
}

.pub-tag {
  position: relative;
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: var(--bg-alt);
  color: var(--text-muted);
  border: 1px solid var(--border);
  text-decoration: none;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
}

/* The gradient fill is a separate layer that fades in via opacity rather
   than being swapped in through the `background` shorthand — animating
   from a flat background-color to a gradient background-image isn't a
   well-defined CSS transition, and browsers can leave it partially/
   incorrectly painted (only part of the pill filled) mid-hover. Opacity
   is a real interpolatable property, so this always renders cleanly. */
.pub-tag::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--gemini-gradient);
  opacity: 0;
  transition: opacity 0.2s ease;
}

.pub-tag:hover,
.pub-tag:focus-visible {
  color: #fff;
  border-color: transparent;
  transform: translateY(-1px);
}

.pub-tag:hover::before,
.pub-tag:focus-visible::before {
  opacity: 1;
}

.pub-card .pub-link {
  margin-top: auto;
  padding-top: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: transparent;
  background-image: var(--gemini-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  text-decoration: none;
}

/* ---------- Publication detail page ---------- */
.pub-page-main {
  max-width: 820px;
  margin: 0 auto;
  padding: 2.5rem 2rem 5rem;
  display: flex;
  flex-direction: column;
  gap: 2rem;
}

.pub-back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  width: fit-content;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-muted);
  text-decoration: none;
  transition: color 0.2s ease;
}

.pub-back-link:hover {
  color: var(--text);
}

.pub-back-link svg {
  width: 16px;
  height: 16px;
}

.pub-page-header {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.pub-page-title {
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1.32;
  letter-spacing: -0.01em;
}

.pub-page-authors {
  font-size: 1.02rem;
  color: var(--text-muted);
}

.pub-page-venue {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-muted);
}

.pub-page-header .award-badge {
  font-size: 0.78rem;
  padding: 0.3rem 0.7rem;
}

.pub-page-header .award-badge svg {
  width: 15px;
  height: 15px;
}

.pub-video {
  position: relative;
  width: 100%;
  padding-top: 56.25%;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  background: var(--bg-alt);
}

.pub-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.pub-thumbnail {
  display: block;
  width: 100%;
  max-height: 460px;
  object-fit: contain;
  background: var(--bg-alt);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.pub-abstract-panel {
  padding: 1.5rem 1.75rem;
}

.pub-abstract-panel h2,
.pub-bibtex-panel h2 {
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 0.75rem;
}

.pub-abstract-text {
  font-size: 1.02rem;
  line-height: 1.75;
  color: var(--text);
}

.pub-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
}

.pub-doi-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.65rem 1.15rem;
  border-radius: 999px;
  background: var(--gemini-gradient);
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.pub-doi-btn:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.pub-doi-btn svg {
  width: 16px;
  height: 16px;
}

.pub-bibtex-panel {
  padding: 1.5rem 1.75rem;
}

.pub-bibtex-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}

.pub-bibtex-header h2 {
  margin-bottom: 0;
}

.pub-copy-btn {
  flex: 0 0 auto;
  font-family: var(--font);
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.4rem 0.8rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.pub-copy-btn:hover {
  color: var(--text);
  border-color: var(--gemini-purple);
}

.pub-bibtex-panel pre {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-word;
}

/* ---------- More About Me ---------- */
.fun-fact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
}

.fun-fact-card {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  padding: 1.5rem;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.fun-fact-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.fun-fact-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.fun-fact-icon {
  flex: none;
  width: 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--gemini-gradient-soft);
}

.fun-fact-icon svg {
  width: 24px;
  height: 24px;
}

.fun-fact-header h3 {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
}

.fun-fact-badge {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  background: var(--gemini-gradient);
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
}

.fun-fact-card p {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text-muted);
}

/* ---------- Responsive ---------- */
@media (max-width: 780px) {
  .pub-page-main {
    padding: 1.75rem 1.25rem 3.5rem;
  }

  .pub-page-title {
    font-size: 1.5rem;
  }
  .topbar-inner {
    padding: 0.8rem 1.25rem;
  }

  .tagline {
    display: none;
  }

  main {
    padding: 2rem 1.25rem 4rem;
    gap: 3rem;
  }

  .hero {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 1.5rem;
  }

  .bio {
    text-align: left;
  }

  .photo-wrap {
    flex: 0 0 180px;
    width: 180px;
    height: 180px;
  }

  .publications-header {
    flex-direction: column;
  }
}
