:root {
  --accent: #1f6f78;
  --accent-dark: #164f56;
  --ink: #1b1f23;
  --ink-soft: #4a5257;
  --bg: #ffffff;
  --bg-alt: #f5f7f7;
  --border: #e3e8e8;
  --card-bg: #ffffff;
  --max-width: 1100px;
  --max-width-narrow: 780px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: "Noto Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: var(--ink);
  background: var(--bg);
  line-height: 1.65;
  font-size: 17px;
}

h1, h2, h3 {
  font-family: "Source Serif 4", Georgia, serif;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink);
}

h2 {
  font-size: 1.75rem;
  margin: 0 0 1.25rem;
  padding-bottom: .6rem;
  display: inline-block;
  position: relative;
}
h2::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 0;
  background: var(--accent);
  transition: width .7s cubic-bezier(.22,.9,.3,1);
}
h2.in-view::after,
h2:not(.reveal)::after { width: 100%; }

h3 {
  font-size: 1.2rem;
  margin: 1.5rem 0 .6rem;
}

p { margin: 0 0 1rem; color: var(--ink-soft); }

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

sup { font-size: .68em; }

code, .bibtex-block {
  font-family: "Noto Sans Mono", "SF Mono", Consolas, monospace;
}

/* ---------- top nav ---------- */
.topnav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--border);
}
.topnav-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: .75rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .5rem;
}
.brand { font-weight: 600; font-size: .95rem; color: var(--ink); }
.topnav-links { display: flex; gap: 1.25rem; flex-wrap: wrap; }
.topnav-links a {
  color: var(--ink-soft);
  font-size: .92rem;
  font-weight: 500;
}
.topnav-links a:hover { color: var(--accent-dark); text-decoration: none; }
.topnav-links a {
  position: relative;
  padding-bottom: 2px;
}
.topnav-links a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: -2px;
  height: 2px;
  background: var(--accent);
  transition: right .25s ease;
}
.topnav-links a:hover::after,
.topnav-links a.active::after { right: 0; }
.topnav-links a.active { color: var(--accent-dark); }

/* ---------- hero ---------- */
.hero {
  background: linear-gradient(180deg, #fbfdfd 0%, #eef4f4 100%);
  padding: 3.5rem 1.5rem 0;
  text-align: center;
}
.hero-inner { max-width: 880px; margin: 0 auto; }
.hero h1 {
  font-size: 2.1rem;
  margin: 0 0 1.4rem;
}
.authors {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .4rem 1rem;
  font-size: 1.05rem;
  margin-bottom: .5rem;
}
.affiliations {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .3rem 1.5rem;
  color: var(--ink-soft);
  font-size: .92rem;
  margin-bottom: .4rem;
}
.venue {
  font-weight: 600;
  color: var(--accent-dark);
  margin-bottom: 1.6rem;
  letter-spacing: .02em;
}

.cta-row {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: .75rem;
  margin-bottom: 2.5rem;
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .55rem 1.1rem;
  border-radius: 999px;
  border: 1.5px solid var(--accent);
  color: var(--accent-dark);
  font-weight: 600;
  font-size: .92rem;
  background: #fff;
  transition: background .15s, color .15s;
}
.btn:hover { background: var(--accent); color: #fff; text-decoration: none; }
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-dark); }
.icon { font-size: 1em; }

.hero-video-wrap {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 1.5rem 3rem;
}
.hero-video {
  width: 100%;
  max-height: 340px;
  object-fit: cover;
  border-radius: 10px;
  display: block;
  box-shadow: 0 10px 30px rgba(0,0,0,.12);
  background: #000;
}
.hero-video-caption {
  text-align: center;
  font-size: .88rem;
  color: var(--ink-soft);
  margin-top: .6rem;
}

/* ---------- sections ---------- */
.section { padding: 3.5rem 1.5rem; }
.section.alt { background: var(--bg-alt); }
.section-inner { max-width: var(--max-width); margin: 0 auto; }
.section-inner.narrow { max-width: var(--max-width-narrow); }
.section-note { font-size: .92rem; color: var(--ink-soft); margin-top: -.5rem; }
.caveat {
  font-size: .9rem;
  background: #fff7ea;
  border-left: 3px solid #d9a441;
  padding: .75rem 1rem;
  border-radius: 4px;
  color: #5c4a1f;
}

.two-col {
  display: grid;
  grid-template-columns: 1.1fr .9fr;
  gap: 2.5rem;
  align-items: center;
}
.two-col.reverse { grid-template-columns: .9fr 1.1fr; }
.two-col figure, .two-col video { margin: 0; width: 100%; }
.two-col img { width: 100%; border-radius: 8px; border: 1px solid var(--border); }

@media (max-width: 820px) {
  .two-col, .two-col.reverse { grid-template-columns: 1fr; }
}

figure { margin: 1.5rem 0; }
figure img { width: 100%; display: block; border-radius: 8px; border: 1px solid var(--border); }
figcaption {
  font-size: .88rem;
  color: var(--ink-soft);
  margin-top: .6rem;
  line-height: 1.5;
}
.full-bleed-figure { margin: 2rem 0; }

.contrib-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
  margin-top: 2rem;
}
.contrib-card {
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem 1.4rem;
}
.contrib-card h3 { margin-top: 0; color: var(--accent-dark); }
.contrib-card p { margin-bottom: 0; font-size: .95rem; }

@media (max-width: 820px) {
  .contrib-grid { grid-template-columns: 1fr; }
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin: 1.5rem 0 1.75rem;
}
.stat-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.4rem 1rem;
  text-align: center;
}
.stat-value {
  font-family: "Source Serif 4", serif;
  font-size: 2rem;
  font-weight: 700;
  color: var(--accent-dark);
}
.stat-label {
  font-size: .82rem;
  color: var(--ink-soft);
  margin-top: .35rem;
}

@media (max-width: 820px) {
  .stat-row { grid-template-columns: repeat(2, 1fr); }
}

.video-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin: 1.25rem 0 2rem;
}
.video-grid figure { margin: 0; }
.video-grid video {
  width: 100%;
  background: #000;
  border-radius: 6px;
  border: 1px solid var(--border);
  display: block;
}
.video-grid figcaption { text-align: center; font-weight: 600; color: var(--ink); }

@media (max-width: 820px) {
  .video-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .video-grid { grid-template-columns: 1fr; }
}

.eval-demo-video {
  width: 100%;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: #000;
  display: block;
}

.expand-block {
  margin-top: 1.5rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem 1.25rem;
  background: var(--bg-alt);
}
.expand-block summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--accent-dark);
}
.expand-block figure { margin-top: 1.25rem; }

.limitations-list { padding-left: 1.2rem; }
.limitations-list li { margin-bottom: .7rem; color: var(--ink-soft); }

.bibtex-block {
  background: #1e2528;
  color: #d9e4e4;
  padding: 1.25rem 1.5rem;
  border-radius: 8px;
  overflow-x: auto;
  font-size: .85rem;
  line-height: 1.6;
}

.site-footer {
  padding: 2.5rem 1.5rem 3rem;
  text-align: center;
  border-top: 1px solid var(--border);
}
.site-footer p { margin: .2rem 0; font-size: .88rem; }
.footer-note { color: #b05a2a; font-weight: 600; }

/* ======================================================
   Motion layer: scroll reveal, counters, hover polish
   ====================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* The scroll-reveal fade (.reveal/.in-view, driven by IntersectionObserver
     in script.js) was removed after it caused real, hard-to-diagnose
     visibility bugs for a purely decorative effect: a CSS specificity
     mistake made content permanently invisible in every real browser for
     a period, independent of any testing-tool artifacts. The .reveal/
     in-view classes are still present in the HTML as inert hooks but no
     longer do anything; everything renders at normal opacity by default.
     The h2 underline-draw-in (near the top of this file) already handles
     its own .in-view styling outside this media query and was never a
     visibility risk, since text itself was never hidden by it. */

  .hero h1, .hero .authors, .hero .affiliations, .hero .venue, .hero .cta-row {
    opacity: 0;
    transform: translateY(10px);
    animation: heroIn .45s cubic-bezier(.22,.9,.3,1) forwards;
  }
  .hero .authors      { animation-delay: .05s; }
  .hero .affiliations { animation-delay: .09s; }
  .hero .venue         { animation-delay: .13s; }
  .hero .cta-row        { animation-delay: .17s; }
  @keyframes heroIn {
    to { opacity: 1; transform: translateY(0); }
  }
  .hero-video { animation: kenBurns 18s ease-in-out infinite alternate; }
  @keyframes kenBurns {
    from { transform: scale(1); }
    to   { transform: scale(1.06); }
  }
}

.btn-disabled {
  opacity: .55;
  cursor: default;
  border-style: dashed;
}
.btn-disabled:hover { background: #fff; color: var(--accent-dark); }

.btn, .contrib-card, .stat-card, .video-grid figure video, .expand-block summary {
  transition: transform .25s ease, box-shadow .25s ease, background .2s ease, border-color .2s ease;
}
.btn:hover:not(.btn-disabled) { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(31,111,120,.22); }
.contrib-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 26px rgba(20,40,42,.1);
  border-color: var(--accent);
}
.stat-card { cursor: default; }
.stat-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 26px rgba(20,40,42,.12);
}
.video-grid figure { overflow: hidden; border-radius: 6px; }
.video-grid figure video { transform: scale(1); }
.video-grid figure:hover video { transform: scale(1.06); }

/* nav shadow once page has scrolled */
.topnav.scrolled { box-shadow: 0 2px 14px rgba(20,40,42,.08); }

/* ======================================================
   Methodology diagram stepper
   ====================================================== */
.stepper {
  margin: 2rem 0;
}
.stepper-frame {
  position: relative;
  width: 100%;
  /* padding-top intrinsic-ratio fallback (1080/1882) for browsers without
     aspect-ratio support; aspect-ratio below overrides it where supported.
     Without one of these, the two position:absolute image layers inside
     contribute no height at all and the whole frame collapses to 0px. */
  padding-top: 57.3858%;
  aspect-ratio: 1882 / 1080;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: #fff;
}
@supports (aspect-ratio: 1 / 1) {
  .stepper-frame { padding-top: 0; }
}
.stepper-frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.stepper-frame .layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.stepper-frame .layer-bg img {
  filter: grayscale(1) brightness(1.2) contrast(.9);
  opacity: .32;
}
.stepper-frame .layer-fg {
  /* Default: plain left-to-right reveal. The stepper JS overrides this with
     a polygon() clip when the figure has a separate band (e.g. an Inference
     row below the main diagram) that shouldn't appear until its own stage. */
  clip-path: var(--clip, inset(0 var(--hide, 0%) 0 0));
  transition: clip-path .85s cubic-bezier(.65,0,.35,1);
}
.stepper-frame .sweep-edge {
  position: absolute;
  top: 0;
  /* Confined to the band the sweep is actually revealing (the top diagram),
     not the full frame height, so it doesn't run down through a lower band
     (e.g. Inference) that this stage hasn't revealed yet. On the final
     stage (full reveal, no meaningful x-position) it fades out instead. */
  height: var(--band, 100%);
  opacity: var(--edge-opacity, 1);
  left: var(--edge, 0%);
  width: 3px;
  background: linear-gradient(180deg, transparent, var(--accent), transparent);
  box-shadow: 0 0 14px 2px rgba(31,111,120,.55);
  transition: left .85s cubic-bezier(.65,0,.35,1), height .85s cubic-bezier(.65,0,.35,1), opacity .5s ease;
}

.stepper-controls {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-top: 1.25rem;
  flex-wrap: wrap;
}
.stepper-dots {
  display: flex;
  gap: .5rem;
  flex: 1;
  min-width: 220px;
}
.stepper-dot {
  flex: 1;
  text-align: left;
  border: 1px solid var(--border);
  background: var(--bg-alt);
  border-radius: 8px;
  padding: .6rem .75rem;
  cursor: pointer;
  font-family: inherit;
  font-size: .82rem;
  color: var(--ink-soft);
  transition: border-color .2s ease, background .2s ease, color .2s ease;
}
.stepper-dot b {
  display: block;
  font-size: .78rem;
  color: var(--ink);
  margin-bottom: .15rem;
}
.stepper-dot.active {
  border-color: var(--accent);
  background: #eaf4f4;
  color: var(--accent-dark);
}
.stepper-dot.active b { color: var(--accent-dark); }

.stepper-nav-btn {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
  background: #fff;
  color: var(--accent-dark);
  font-size: 1rem;
  cursor: pointer;
  flex-shrink: 0;
  transition: background .2s ease, color .2s ease;
}
.stepper-nav-btn:hover { background: var(--accent); color: #fff; }

.stepper-caption {
  margin-top: 1rem;
  padding: .9rem 1.1rem;
  background: var(--bg-alt);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  font-size: .92rem;
  color: var(--ink);
  min-height: 2.6em;
}

@media (max-width: 700px) {
  .stepper-dots { flex-direction: column; }
}

/* staggered reveal for grid children */
@media (prefers-reduced-motion: no-preference) {
  .stat-row .reveal:nth-child(1) { transition-delay: 0s; }
  .stat-row .reveal:nth-child(2) { transition-delay: .08s; }
  .stat-row .reveal:nth-child(3) { transition-delay: .16s; }
  .stat-row .reveal:nth-child(4) { transition-delay: .24s; }
  .contrib-grid .reveal:nth-child(1) { transition-delay: 0s; }
  .contrib-grid .reveal:nth-child(2) { transition-delay: .1s; }
  .contrib-grid .reveal:nth-child(3) { transition-delay: .2s; }
  .video-grid .reveal:nth-child(1) { transition-delay: 0s; }
  .video-grid .reveal:nth-child(2) { transition-delay: .08s; }
  .video-grid .reveal:nth-child(3) { transition-delay: .16s; }
  .video-grid .reveal:nth-child(4) { transition-delay: .24s; }
}
