/*
 * Custom styles layered on top of Tailwind's utility classes.
 *
 * NOTE: This is a plain CSS file served directly to the browser, so it uses
 * vanilla CSS rather than Tailwind's @apply / theme() directives (those only
 * work when Tailwind processes the file at build time). The Tailwind utility
 * classes in index.html still work via the Play CDN.
 */

:root {
  /* Accent blue, anchored on the #008cff (HSL 207°, 100%, 50%) used in the
   * MILLIVID animation. Darker shades keep full saturation so they stay the
   * same vivid hue rather than looking greyed-out. */
  --brand-500: #008cff;
  --brand-600: #0079e6; /* hover: a touch darker, still vivid */
  --brand-700: #0062cc;
}

/* Balanced wrapping for headings / short blocks. */
.text-balance {
  text-wrap: balance;
}

/* Smoothly animate in-page anchor jumps. */
html {
  scroll-behavior: smooth;
}

/* Inline body-text links (e.g. the in-page jumps in the Method intro).
 * Keeps the surrounding text color; the underline is the only affordance. */
.text-link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: text-decoration-color 150ms ease;
}
.text-link:hover {
  text-decoration-color: var(--brand-500);
}

/* ---- Reusable component classes ---- */

/* Section headings with an accent underline. */
.section-heading {
  font-size: 1.5rem;
  line-height: 2rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  color: #0f172a;
  position: relative;
  padding-bottom: 0.5rem;
}
.section-heading::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 2.5rem;
  height: 3px;
  border-radius: 9999px;
  background-color: var(--brand-500);
}

/* Author name links. */
.author-link {
  font-weight: 500;
  color: var(--brand-500);
  transition: color 150ms ease;
}
.author-link:hover {
  color: var(--brand-600);
  text-decoration: underline;
}

/* Primary resource buttons (Paper, Code, etc.). */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: 9999px;
  background-color: #0f172a;
  padding: 0.625rem 1.25rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: #ffffff;
  box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  transition: transform 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
}
.btn:hover {
  transform: translateY(-2px);
  background-color: #334155;
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}
.btn.btn-disabled {
  background-color: #cbd5e1;
  color: #f1f5f9;
  cursor: not-allowed;
  box-shadow: none;
  pointer-events: none;
}

/* Small secondary button (e.g. Copy BibTeX). */
.btn-sm {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  border-radius: 0.375rem;
  border: 1px solid #e2e8f0;
  background-color: #ffffff;
  padding: 0.375rem 0.75rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: #475569;
  cursor: pointer;
  transition: border-color 150ms ease, background-color 150ms ease;
}
.btn-sm:hover {
  border-color: #cbd5e1;
  background-color: #f8fafc;
}
.btn-sm.copied {
  border-color: #bbf7d0;
  background-color: #f0fdf4;
  color: #15803d;
}

/* ---- "MILLIVID" scrolling decoration (inlined from anim.html) ----
 * Variables live on the container (not :root) so they stay scoped; the
 * script reads them from this element. No page background / full-height
 * rules, so the figure sits directly on the page as a decoration. */
.millivid-anim {
  --cell: 12px;
  --rows: 5;
  --grid-line: #000000; /* 0.5px separators between cells */
  --cell-bg: #ffffff;
  --text-blue: #008cff; /* sampled from image */
  --vid-color: #ffa602; /* sampled from image */
  --box-outline: #000000;
  --axis: #000000;
  --label: #000000;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Manrope", system-ui, sans-serif;
}

/* Figure: 44 + 400 + 56 = 500 wide, 8 + 64 + 40 = 112 tall */
.millivid-anim .figure {
  position: relative;
  display: inline-block;
  padding: 8px 56px 40px 44px; /* top right bottom left */
}

.millivid-anim .box {
  border: 2px solid var(--box-outline);
  background: var(--cell-bg);
  line-height: 0;
  overflow: hidden;
}

.millivid-anim canvas {
  display: block;
}

.millivid-anim .axes {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}

.millivid-anim .axis-title {
  position: absolute;
  color: var(--label);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.2px;
  white-space: nowrap;
}
.millivid-anim .axis-title.frame {
  left: 44px; /* left-aligned with the x-axis start */
  top: 79px;
}
.millivid-anim .axis-title.detail {
  left: 18px; /* left of the y-axis */
  top: 72px; /* bottom-aligned with the y-axis start */
  transform-origin: top left;
  transform: rotate(-90deg);
}

.millivid-anim .row-label {
  position: absolute;
  left: 448px; /* just right of the grid */
  color: var(--label);
  font-size: 12px; /* ~ same as a grid cell */
  font-weight: 500;
  transform: translateY(-50%);
  white-space: nowrap;
}

/* ---- Coarse-to-fine rollout animation ----
 * A filmstrip of the frames in strategies/millivid.json scrolling leftward.
 * Variables live on the container so script.js can read them (same pattern as
 * .millivid-anim). Colours/grid intentionally match the MILLIVID decoration. */
.rollout-anim {
  --cell: 20px; /* 39 cols * 20px = 780px, fits the prose column */
  --rows: 3;
  --grid-line: #000000;
  --cell-bg: #ffffff; /* not-yet-generated (future) frames */
  --fixed-color: #585858; /* fixed / already-generated frames */
  --ctx-color: #008cff; /* value 1 (context) */
  --gen-color: #ffa602; /* value 2 (denoised) */
  --box-outline: #000000;
  --axis: #000000;
  --label: #000000;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: inherit; /* match the document font (Inter) */
}

/* Heading above each animation. The figure is 884px wide with a 44px left pad,
 * so this matches that geometry to left-align the heading with the box edge. */
.rollout-anim .rollout-anim-title {
  width: 884px;
  max-width: 100%;
  padding-left: 44px;
  margin-bottom: 0.35rem;
  text-align: left;
}

/* Figure box: 44 + 784 + 56 = 884 wide, 8 + 64 + 40 = 112 tall. The canvas is
 * 780 x 60 (39 cols x 3 rows at --cell 20px) plus the 2px box border. */
.rollout-anim .figure {
  position: relative;
  display: inline-block;
  padding: 8px 56px 40px 44px; /* top right bottom left */
}
.rollout-anim .rollout-box {
  border: 2px solid var(--box-outline);
  background: var(--cell-bg);
  line-height: 0;
  overflow: hidden;
}
.rollout-anim canvas {
  display: block;
}
.rollout-anim .axes {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}
.rollout-anim .axis-title {
  position: absolute;
  color: var(--label);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.2px;
  white-space: nowrap;
}
.rollout-anim .axis-title.frame {
  left: 44px; /* left-aligned with the x-axis start */
  top: 79px;
}
.rollout-anim .axis-title.detail {
  left: 18px; /* left of the y-axis */
  top: 72px; /* bottom-aligned with the y-axis start */
  transform-origin: top left;
  transform: rotate(-90deg);
}
.rollout-anim .row-label {
  position: absolute;
  left: 832px; /* just right of the box (box right edge = 828) */
  color: var(--label);
  font-size: 13px;
  font-weight: 500;
  transform: translateY(-50%);
  white-space: nowrap;
}

/* Legend: 4 swatch + label pairs side by side, centred, no surrounding border.
 * Each swatch is a single cell 20% smaller than an animation cell. */
.rollout-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem 1.5rem;
  margin-top: -0.75rem; /* sit a little closer under the animation */
}
.rollout-legend-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 1rem;
  color: #334155;
}
.rollout-swatch {
  flex: none;
  width: calc(var(--cell) * 0.8);
  height: calc(var(--cell) * 0.8);
  border: 1px solid var(--grid-line);
}

/* ---- Interactive adaptive-autoencoder figure ---- */
.ae-col-label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #64748b;
  text-align: center;
}

/* Shared look for the clickable scene thumbnails and level buttons. */
.ae-thumb,
.ae-level {
  border: 2px solid #e2e8f0;
  border-radius: 0.5rem;
  background: #ffffff;
  cursor: pointer;
  transition:
    border-color 150ms ease,
    box-shadow 150ms ease,
    background-color 150ms ease;
}

/* Hover affordance: border picks up the brand blue. */
.ae-thumb:hover,
.ae-level:hover {
  border-color: var(--brand-500);
}

/* Selected state: brand border plus a soft ring to distinguish from hover. */
.ae-thumb.is-selected,
.ae-level.is-selected {
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgba(0, 140, 255, 0.18);
}

.ae-thumb {
  padding: 0;
  line-height: 0;
  overflow: hidden;
}
.ae-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ae-level {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.125rem;
  padding: 0.5rem 0.75rem;
  text-align: center;
}
.ae-level-name {
  font-size: 0.9rem;
  font-weight: 600;
  color: #0f172a;
}
.ae-level-tokens {
  font-size: 0.7rem;
  color: #64748b;
}
.ae-level.is-selected .ae-level-name {
  color: var(--brand-700);
}

/* The adaptive/cascaded dropdown inside the figure caption. */
.ae-select {
  font: inherit;
  font-weight: 600;
  color: var(--brand-600);
  border: 1px solid #cbd5e1;
  border-radius: 0.375rem;
  padding: 0.1rem 1.6rem 0.1rem 0.5rem;
  background-color: #ffffff;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  /* Custom down-chevron in the brand blue. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230079e6' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.5rem center;
  background-size: 0.7rem;
  transition:
    border-color 150ms ease,
    box-shadow 150ms ease;
}
.ae-select:hover {
  border-color: var(--brand-500);
}
.ae-select:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgba(0, 140, 255, 0.18);
}

/* The two large Ground Truth / Reconstruction images. */
.ae-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 2px solid #e2e8f0;
  border-radius: 0.75rem;
  background: #f1f5f9;
}

/* ---- Results video widget ----
 * One video at a time, chosen from a dropdown. Each video tiles four 256px-wide
 * columns separated by three 8px margins (4*256 + 3*8 = 1048 units). The video
 * fills the page's centre column, and the headings grid uses the same 256fr/8fr
 * track pattern so each heading stays centred over its column at any scale. */
.results-widget {
  min-width: 560px; /* scroll rather than squish the headings on small screens */
}
.results-headings {
  display: grid;
  grid-template-columns: 256fr 8fr 256fr 8fr 256fr 8fr 256fr;
  align-items: end;
  margin-bottom: 0.5rem;
}
.results-video {
  display: block;
  width: 100%;
  height: auto;
  /* Reserve the exact slot so switching videos doesn't reflow the page. Every
   * video is 256*4 + 8*3 = 1048 wide by 256 tall. */
  aspect-ratio: 1048 / 256;
}

/* ---- Quality vs. Consistency line charts ----
 * Two SVG line charts (Consistency / Quality) side by side, built in script.js
 * from plots/quality_consistency.js. Titles use the document font (Inter). */
.qc-panels {
  display: flex;
  flex-wrap: wrap;
  /* Wide column gap so the right panel's left-bleeding y-axis labels sit clear
   * of the left panel; row gap leaves room for the bottom x-axis labels. */
  gap: 1.75rem 5rem;
  justify-content: center;
}
.qc-panel {
  flex: 1 1 320px;
  min-width: 280px;
}
.qc-title {
  text-align: center;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.01em;
  color: #0f172a;
  margin-bottom: 0.25rem;
}
/* The plot box aligns flush with the panel (= column); the axis tick labels
 * bleed outside the box via overflow: visible. */
.qc-plot {
  position: relative;
}
.qc-plot svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
/* Black left (y) / bottom (x) axes as a bordered overlay matching the plot box.
 * A CSS border stays crisp at any zoom and doesn't clip like the SVG edge did. */
.qc-plot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-left: 2px solid #000000;
  border-bottom: 2px solid #000000;
  pointer-events: none;
}

/* Legend below the charts, styled like the animation legends (16px swatch with
 * a 1px black border). Colours match the plotted lines. */
.qc-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem 1.5rem;
  margin-top: 2.5rem;
}
.qc-legend-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 1rem;
  color: #334155;
}
.qc-swatch {
  flex: none;
  width: 16px;
  height: 16px;
  border: 1px solid #000000;
}

/* ---- Adaptive autoencoder method-pipeline diagram ----
 * A left-to-right pipeline (Input -> Image Pyramid -> Hierarchical Tokens ->
 * Single Level's Tokens -> Reconstructed Pyramid) with labelled operation
 * arrows between stages. Recreated in the site's style: brand-blue tokens,
 * Inter labels, rounded cards. Token grids are built in script.js. */
.ae-pipe {
  display: flex;
  align-items: stretch; /* every column is as tall as the tallest stage */
  justify-content: center;
  gap: 0.5rem;
  min-width: 720px; /* horizontal scroll on small screens */
  padding: 0.25rem 0;
}

/* A pipeline stage (Input, Image Pyramid, ...) and an operation connector
 * both lead with a fixed-height head so their bodies start on the same line. */
/* The title + content of each stage are centred together as one group, so the
 * title sits directly above its column's content rather than at the very top. */
.ae-pipe-stage,
.ae-pipe-conn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.ae-pipe-head {
  width: 7rem;
  /* Fixed two-line-tall slot so one- and two-line titles push their content
   * down by the same amount, keeping the pyramids aligned across columns. The
   * title is bottom-aligned so it still sits right above its content. */
  min-height: 1.85rem;
  /* Gap below the title, matching the .ae-col-label mb-3 in the figure above. */
  margin-bottom: 0.75rem;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
/* Titles inherit .ae-col-label's size (matching the figure above); only the
 * line-height is tightened so multi-line titles wrap snugly. */
.ae-pipe-head .ae-col-label {
  line-height: 1.2;
}
/* Connectors have no title; drop the empty head so the arrow stays centred. */
.ae-pipe-conn .ae-pipe-head {
  display: none;
}

/* The stage body holds the pyramid (or single image), centred horizontally. */
.ae-pipe-body {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* The connector body is wider than its card so the arrow line (behind the
 * card) shows on both sides; the arrow sits on the shared centre line. */
.ae-pipe-conn .ae-pipe-body {
  position: relative;
  width: 3.5rem;
}

/* Stacked image / token pyramid: levels shrink downward, centre-aligned. */
.ae-pyramid {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

/* Image pyramid levels. */
.ae-pyr-img {
  display: block;
  border-radius: 4px;
  border: 1px solid #000000;
  object-fit: cover;
}

/* Token grids and individual tokens. */
.ae-tok-grid {
  display: grid;
  gap: 2px;
}
.ae-tok {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  border: 1px solid #000000;
  background: var(--brand-500);
}
.ae-tok.is-empty {
  border-color: #cbd5e1;
  background: #ffffff;
}

/* Operation connector: a right-pointing arrow that runs the full width of the
 * connector, passing behind a labelled card with vertical (rotated) text. */
.ae-arrow {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1.25px;
  transform: translateY(-50%);
  background: #94a3b8;
}
.ae-arrow::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 5px solid #94a3b8;
}
.ae-op-box {
  position: relative; /* sits above the arrow line */
  z-index: 1;
  border: 1px solid #e2e8f0;
  background: #f8fafc;
  border-radius: 0.375rem;
  padding: 0.5rem 0.3rem;
}
.ae-op-label {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: #475569;
  white-space: nowrap;
}
