/* ==========================================================================
   calcia showcase
   Everything is scoped under .calcia-showcase so a section can be lifted into
   a host page without its own styles leaking, or being overwritten.
   Dark only, deliberately: the subject is fluorescence on black.
   ========================================================================== */

/* Page-level reset. The rest of this file is scoped to .calcia-showcase so it
   can be lifted into a host page; THIS block is the one part that is not, and
   it is the one to drop when embedding. Without it the browser's default 8px
   body margin shows as a white frame around the page, because the dark
   background lives on .calcia-showcase rather than on the document. */
html, body {
  margin: 0;
  padding: 0;
  background: #05070c;
}
html { color-scheme: dark; }   /* dark scrollbars, form controls, overscroll */
body { min-height: 100%; }

.calcia-showcase {
  --bg:        #05070c;
  --bg-2:      #080b13;
  --ink:       #e8eefb;
  --ink-dim:   #93a2bd;
  --ink-faint: #5b6a86;
  --line:      #17203a;
  --cyan:      #4fd8e8;
  --violet:    #9a7cff;
  --mint:      #4fe3a6;
  --amber:     #ffb454;

  --w: 1380px;
  --pad: clamp(20px, 5vw, 64px);

  background: var(--bg);
  color: var(--ink);
  font-family: "Inter", "SF Pro Text", -apple-system, BlinkMacSystemFont,
               "Segoe UI", "PingFang SC", "Hiragino Sans GB",
               "Microsoft YaHei", system-ui, sans-serif;
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
  min-height: 100vh;
}

.calcia-showcase * { box-sizing: border-box; }
.calcia-showcase h1,
.calcia-showcase h2,
.calcia-showcase h3 { margin: 0; font-weight: 600; letter-spacing: -0.022em; }
.calcia-showcase p { margin: 0; }
.calcia-showcase code {
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace;
  font-size: 0.88em; color: var(--cyan);
}

/* language ---------------------------------------------------------------- */
body[data-lang="en"] .calcia-showcase .zh,
body[data-lang="zh"] .calcia-showcase .en { display: none; }
body[data-lang="zh"] .calcia-showcase { letter-spacing: 0; }

.langbar {
  position: fixed; top: 16px; right: 16px; z-index: 40;
  display: flex; gap: 2px; padding: 3px;
  background: rgba(8, 11, 19, 0.72); border: 1px solid var(--line);
  border-radius: 999px; backdrop-filter: blur(12px);
}
.lang-btn {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  color: var(--ink-faint); font: inherit; font-size: 12px; font-weight: 600;
  letter-spacing: 0.04em; padding: 5px 13px; border-radius: 999px;
  transition: color .18s, background .18s;
}
.lang-btn:hover { color: var(--ink); }
.lang-btn.is-on { color: #071018; background: var(--ink); }

/* hero -------------------------------------------------------------------- */
.hero { position: relative; min-height: min(94vh, 880px); overflow: hidden; }
.hero-media { position: absolute; inset: 0; }
.hero-media canvas,
.hero-media .hero-fallback {
  width: 100%; height: 100%; display: block; background: #04060a;
  touch-action: pan-y; cursor: grab;
}
.hero-media .hero-fallback { object-fit: cover; cursor: default; }
.hero-media canvas.is-drag { cursor: grabbing; }
.hero-scrim {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(90deg, rgba(5,7,12,.97) 0%, rgba(5,7,12,.88) 30%, rgba(5,7,12,.42) 52%, rgba(5,7,12,0) 72%),
    linear-gradient(0deg, rgba(5,7,12,.96) 0%, rgba(5,7,12,0) 42%);
}
.hero-copy {
  position: relative; z-index: 2;
  max-width: var(--w); margin: 0 auto;
  /* The bottom padding RESERVES the space the pinned track + stats occupy.
     Without it the hero is a fixed height with absolutely positioned furniture
     at its foot, and any copy that grows -- a longer caption, a second control
     row, a language with taller lines -- silently lands on top of it. With the
     reserve the hero simply grows instead. */
  padding: clamp(56px, 12vh, 140px) var(--pad) 158px;
}
.eyebrow {
  font-size: 12.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--cyan); margin-bottom: 22px !important;
}
.hero h1 {
  font-size: clamp(29px, 7.6vw, 76px); line-height: 1.04;
  max-width: 18ch; margin-bottom: 26px;
}
.lede {
  font-size: clamp(16px, 1.35vw, 19px); color: var(--ink-dim);
  max-width: 47ch;
}
.hero-caption {
  margin-top: clamp(28px, 6vh, 64px);
  /* A FIXED slot, tall enough for the longest caption in either language.
     If this box grows when the caption changes, the hero grows with it, the
     canvas changes size, and the renderer reallocates its framebuffers -- a
     visible hitch on every stage change, plus the scene visibly rescaling. */
  min-height: 136px; max-width: 42ch;
  font-size: 15px; color: var(--ink);
  border-left: 2px solid var(--cyan); padding-left: 16px;
  opacity: 0; transform: translateY(6px);
  transition: opacity .45s ease, transform .45s ease;
}
.hero-caption.is-on { opacity: 1; transform: none; }
.hero-caption b {
  display: block; font-size: 11.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--cyan); font-weight: 600;
  margin-bottom: 3px;
}

/* hero controls: the one thing a rendered film cannot offer -- you can stop it
   anywhere and the geometry is still there to be looked at. */
.hero-ctrl {
  display: flex; align-items: center; flex-wrap: wrap; gap: 14px;
  margin-top: clamp(20px, 4vh, 34px); max-width: 42ch;
}
.hbtn {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid var(--line); background: rgba(8,11,19,.7);
  color: var(--ink); cursor: pointer; display: flex;
  align-items: center; justify-content: center; padding: 0;
  transition: border-color .18s, background .18s;
}
.hbtn:hover { border-color: var(--cyan); background: rgba(79,216,232,.10); }
.ico-pause, .ico-play { display: block; }
.ico-pause {
  width: 10px; height: 12px;
  border-left: 3px solid currentColor; border-right: 3px solid currentColor;
}
.ico-play {
  width: 0; height: 0; margin-left: 3px;
  border-top: 6px solid transparent; border-bottom: 6px solid transparent;
  border-left: 10px solid currentColor;
}
#hero-scrub { flex: 1 1 auto; max-width: 210px; }
.hero-hint {
  font-size: 11.5px; letter-spacing: .11em; text-transform: uppercase;
  color: var(--ink-faint); white-space: nowrap;
}

.hero-track {
  position: absolute; left: 0; right: 0; bottom: 96px; z-index: 3;
  height: 2px; display: flex; gap: 3px;
  max-width: var(--w); margin: 0 auto; padding: 0 var(--pad);
}
.hero-track i {
  flex: var(--f, 1); background: #1c2740; border-radius: 2px;
  position: relative; overflow: hidden;
}
.hero-track i::after {
  content: ""; position: absolute; inset: 0;
  background: var(--cyan); transform-origin: left;
  transform: scaleX(var(--p, 0));
}

.hero-stats {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  max-width: var(--w); margin: 0 auto; padding: 22px var(--pad) 30px;
  display: flex; flex-wrap: wrap; gap: clamp(20px, 4vw, 54px);
  border-top: 1px solid var(--line);
}
.hero-stats div { display: flex; flex-direction: column; gap: 1px; }
.hero-stats b {
  font-size: clamp(20px, 2.4vw, 27px); font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.hero-stats span {
  font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint);
}

/* bands ------------------------------------------------------------------- */
.band {
  max-width: var(--w); margin: 0 auto;
  padding: clamp(72px, 12vh, 132px) var(--pad);
  border-top: 1px solid var(--line);
}
.band:first-of-type { border-top: 0; }
.band-quiet { color: var(--ink-dim); }
.band-head { max-width: 62ch; margin-bottom: clamp(30px, 5vh, 52px); }

/* A centred column with one centred image in it wastes most of a wide screen
   and makes every section read the same. `split` puts the prose in a narrow
   rail that stays with you while the media scrolls, and gives the media the
   rest of the width; `bleed` lets one section escape the column entirely, so
   the page has a rhythm instead of one ribbon down the middle. */
.band.split {
  display: grid;
  grid-template-columns: minmax(260px, 0.95fr) minmax(0, 1.75fr);
  gap: clamp(28px, 4vw, 68px);
  align-items: start;
}
.band.split > .band-head,
.band.split > .split-rail { margin-bottom: 0; }
.band.split > .band-head,
.band.split > .split-rail > .band-head { max-width: 46ch; }
.split-rail {
  position: sticky; top: 44px;
  display: flex; flex-direction: column; gap: clamp(24px, 3vh, 38px);
}
.band.split > .band-head { position: sticky; top: 44px; }

.band.bleed > *:not(.band-head) {
  width: 100vw; margin-left: calc(50% - 50vw);
}
.band.bleed .series video {
  border-radius: 0; border-left: 0; border-right: 0;
  /* Stretched to the viewport this grid is ~1900 px tall. Cropping it is the
     better read anyway: a wall of volumes running past the frame says "there
     are more of these" more plainly than a complete, shrunken contact sheet. */
  max-height: 68vh; object-fit: cover;
}
.band-head h2 {
  font-size: clamp(27px, 3.6vw, 43px); line-height: 1.12; margin-bottom: 16px;
}
.band-head p { color: var(--ink-dim); }

/* compare ----------------------------------------------------------------- */
.compare {
  position: relative; aspect-ratio: 1 / 1;
  max-width: min(100%, 820px); margin: 0;
  border: 1px solid var(--line); border-radius: 18px; overflow: hidden;
  background: #000; touch-action: pan-y; user-select: none;
}
.cmp-video { position: absolute; inset: 0; width: 100%; height: 100%;
             object-fit: cover; display: block; }
.cmp-clip {
  position: absolute; inset: 0;
  clip-path: inset(0 0 0 var(--split, 50%));
}
.cmp-handle {
  position: absolute; top: 0; bottom: 0; left: var(--split, 50%);
  width: 2px; background: rgba(232,238,251,.85); cursor: ew-resize; z-index: 3;
  box-shadow: 0 0 18px rgba(79,216,232,.55);
}
.cmp-handle span {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 40px; height: 40px; border-radius: 50%;
  background: rgba(5,7,12,.72); border: 1.5px solid rgba(232,238,251,.85);
  backdrop-filter: blur(6px);
}
.cmp-handle span::before, .cmp-handle span::after {
  content: ""; position: absolute; top: 50%; width: 0; height: 0;
  border: 5px solid transparent;
}
.cmp-handle span::before { left: 6px;  transform: translateY(-50%);
  border-right-color: rgba(232,238,251,.9); }
.cmp-handle span::after  { right: 6px; transform: translateY(-50%);
  border-left-color: rgba(232,238,251,.9); }
.cmp-label {
  position: absolute; bottom: 14px; z-index: 3; font-size: 11.5px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink);
  background: rgba(5,7,12,.6); padding: 5px 11px; border-radius: 999px;
  backdrop-filter: blur(8px); pointer-events: none;
}
.cmp-label-l { left: 14px; }
.cmp-label-r { right: 14px; }

/* ground truth ------------------------------------------------------------ */
.gt-stage {
  position: relative; aspect-ratio: 1 / 1; max-width: min(100%, 820px);
  border: 1px solid var(--line); border-radius: 18px; overflow: hidden;
  background: #000;
}
.gt-video, .gt-overlay {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
}
.gt-overlay { pointer-events: auto; cursor: crosshair; }
.gt-side { display: flex; flex-direction: column; gap: 20px; }
.ctrl { display: flex; flex-direction: column; gap: 10px; }
.ctrl-label {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint);
}
.ctrl-label b {
  color: var(--cyan); font-size: 15px; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.ctrl.checkbox { flex-direction: row; align-items: center; gap: 10px;
                 font-size: 14px; color: var(--ink-dim); cursor: pointer; }
input[type="range"] {
  appearance: none; width: 100%; height: 2px; background: var(--line);
  border-radius: 2px; outline: none; cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
  appearance: none; width: 16px; height: 16px; border-radius: 50%;
  background: var(--cyan); border: 3px solid var(--bg);
  box-shadow: 0 0 0 1px var(--cyan);
}
input[type="range"]::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%; border: 3px solid var(--bg);
  background: var(--cyan); box-shadow: 0 0 0 1px var(--cyan);
}
.gt-readout {
  display: grid; grid-template-columns: auto 1fr; gap: 4px 14px;
  font-size: 14px; color: var(--ink-dim);
  border-top: 1px solid var(--line); padding-top: 18px;
}
.gt-readout b { color: var(--ink); font-variant-numeric: tabular-nums;
                font-weight: 600; }
.fineprint { font-size: 13px; line-height: 1.55; color: var(--ink-faint); }

/* traces ------------------------------------------------------------------ */
.traces-wrap {
  position: relative; border: 1px solid var(--line); border-radius: 18px;
  background: var(--bg-2); overflow: hidden;
}
.traces-wrap canvas { display: block; width: 100%; }
#traces-play { position: absolute; inset: 0; pointer-events: none; }

/* pipeline ---------------------------------------------------------------- */
.pipeline { list-style: none; margin: 0; padding: 0;
            display: grid; gap: 1px; background: transparent;
            grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
            border: 1px solid var(--line); border-radius: 18px; overflow: hidden; }
.pipeline li { background: var(--bg); outline: 1px solid var(--line);
               padding: clamp(24px, 3.4vw, 38px); }
.pipeline .step {
  font-size: 11.5px; letter-spacing: .16em; color: var(--cyan);
  font-variant-numeric: tabular-nums;
}
.pipeline h3 { font-size: 21px; margin: 8px 0 10px; }
.pipeline p { color: var(--ink-dim); max-width: 62ch; }
.psf { margin: 20px 0 0; }
.psf img { width: 100%; max-width: 560px; border-radius: 12px; display: block; }
.noise-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
              margin-top: 20px; max-width: 620px; }
.noise-pair figure { margin: 0; }
.noise-pair video { width: 100%; display: block; border-radius: 12px;
                    background: #000; border: 1px solid var(--line); }
.noise-pair figcaption {
  margin-top: 8px; font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-faint);
}

/* series ------------------------------------------------------------------ */
.series { margin: 0; }
.series video {
  width: 100%; display: block; border-radius: 18px; background: #000;
  border: 1px solid var(--line);
}

/* perf table -------------------------------------------------------------- */
.perf { width: 100%; border-collapse: collapse; font-size: 15px; }
.perf th, .perf td { text-align: left; padding: 14px 16px 14px 0;
                     border-bottom: 1px solid var(--line); vertical-align: top; }
.perf th { font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase;
           color: var(--ink-faint); font-weight: 600; }
.perf td:first-child { color: var(--ink); width: 34%; }
.perf td { color: var(--ink-dim); }

/* footer ------------------------------------------------------------------ */
.foot {
  max-width: var(--w); margin: 0 auto;
  padding: 40px var(--pad) 84px; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 10px;
}
.foot p { font-size: 13.5px; color: var(--ink-faint); }

.offline-note {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  z-index: 50; max-width: min(620px, 92vw);
  background: #12080a; border: 1px solid #3a1a1f; color: #f0c9ce;
  padding: 13px 18px; border-radius: 12px; font-size: 13.5px; line-height: 1.5;
}

/* responsive -------------------------------------------------------------- */
@media (max-width: 900px) {
  .band.split { grid-template-columns: 1fr; gap: clamp(26px, 5vh, 40px); }
  .band.split > .band-head, .split-rail { position: static; }
  .compare, .gt-stage { margin-inline: auto; }
  .band.bleed > *:not(.band-head) { width: auto; margin-left: 0; }
  .band.bleed .series video { border-radius: 18px; border: 1px solid var(--line); }
}

@media (max-width: 860px) {
  .calcia-showcase { font-size: 16px; }
  .noise-pair { grid-template-columns: 1fr; }
  .hero-track { bottom: 132px; }
  .hero-stats { gap: 18px 30px; }
  .hero-scrim {
    background:
      linear-gradient(0deg, rgba(5,7,12,.97) 0%, rgba(5,7,12,.55) 45%, rgba(5,7,12,.25) 100%);
  }
}

@media (max-width: 620px) {
  .hero-stats { gap: 14px 24px; }
  .hero-stats b { font-size: 19px; }
  .hero-copy { padding-bottom: 186px; }   /* the strip wraps to two rows here */
  .hero-caption { min-height: 158px; }    /* narrower box, more lines */
  /* 'drag the scene to orbit' is nowrap; beside the button and slider it does
     not fit a phone, and it is decoration. */
  .hero-hint { display: none; }
  #hero-scrub { max-width: none; }
  .langbar { top: 10px; right: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .calcia-showcase * { animation: none !important; transition: none !important; }
}
