/* ==========================================================================
   knight.css — /knight/ knight motion page (3D view with 3-tier quality)
   Layer 3: loads after tokens.css + frame.css. All values come from tokens.

   Obys contract: the page chrome is warm paper — solid --surface slabs with
   ink type, --border-color hairlines and one orange-red accent. The canvas
   inside .stage stays the dark media block (owned by knight.js, never
   restyled here). Floating chrome over the canvas: the small chips are solid
   --surface (accent-dim small text only clears 4.5:1 on white), the wide
   bottom bar is paper glass rgba(242, 240, 234, …) with alphas chosen so
   --text-dim keeps >= 4.5:1 on the darkest canvas. No amber, no dark panel
   residue.
   ========================================================================== */

[hidden] {
  display: none !important;
}

/* ---- Stage: full-bleed under the sticky header, fills the viewport ------- */
.stage {
  position: relative;
  height: calc(100vh - var(--header-height));
  height: calc(100dvh - var(--header-height));
  overflow: hidden;
  background: var(--bg);
  border-bottom: 1px solid var(--border-color);
}

.stage > canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ---- Loadbar: accent progress line across the stage top ------------------- */
.loadbar {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 30;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: width 0.3s var(--ease-out);
}

/* ---- Status chip (top center) + meta chip (top right) ----------------------
   Solid --surface slabs over the dark canvas media block. */
.stage-status {
  position: absolute;
  top: var(--space-4);
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  max-width: min(80%, 40rem);
  margin: 0;
  padding: var(--space-1) var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  font-size: var(--text-xs);
  line-height: var(--leading-mono);
  color: var(--text-dim);
  text-align: center;
}

.stage-status.is-ok {
  color: var(--accent-dim); /* 5.1:1 on --surface; --accent fails AA at xs */
  border-color: var(--accent-dim);
}

/* Error = the ink slab: loudest signal on paper (18.4:1). No token-less red:
   tokens.css defines no --danger, so error semantics ride on weight of ink. */
.stage-status.is-err {
  color: var(--text);
  border-color: var(--border-strong);
}

.stage-meta {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 20;
  max-width: min(46%, 22rem);
  margin: 0;
  padding: var(--space-1) var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  font-size: var(--text-xs);
  line-height: var(--leading-mono);
  color: var(--text-faint); /* 4.3:1 on --surface; non-essential metadata */
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: pre;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- WebGL unavailable panel ---------------------------------------------- */
.glfail {
  position: absolute;
  inset: 0;
  z-index: 40;
  display: grid;
  place-content: center;
  gap: var(--space-2);
  padding: var(--space-6);
  text-align: center;
}

.glfail-code {
  font-size: var(--text-md);
  color: var(--accent-dim); /* 4.4:1 on --bg; --accent is display-size only */
}

.glfail p:not(.glfail-code) {
  max-width: 34rem;
  color: var(--text-dim);
}

/* ---- Buttons (machine voice: mono labels per design contract) ------------- */
.kbtn {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--leading-mono);
  color: var(--text-dim);
  background: var(--surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-3);
  transition: color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              background var(--dur-base) var(--ease-out),
              scale var(--dur-fast) var(--ease-out);
}

.kbtn:hover {
  color: var(--text);
  border-color: var(--border-strong); /* Obys hover: stroke black, never grey */
}

.kbtn:active {
  scale: 0.96;
}

/* Active = the ink slab with the accent word: 5.5:1 and it reads as the
   ink/paper inversion used across the system. Declared after :hover so an
   active control keeps its state under the cursor. */
.kbtn.is-active {
  color: var(--accent);
  background: var(--text);
  border-color: var(--border-strong);
}

/* Armed HD button: small accent fill is the confirm signal (momentary). */
.kbtn.is-armed {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
}

.kbtn:disabled {
  opacity: 0.45;
  cursor: wait;
}

/* ---- Deck: quality switch + action list (left overlay panel) --------------- */
.deck {
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 20;
  width: 18rem;
  max-height: calc(100% - 9rem);
  overflow-y: auto;
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
}

.deck-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.deck-back {
  font-size: var(--text-xs);
}

.deck-close {
  display: none;
}

.deck-title {
  margin-block: var(--space-3) var(--space-1);
  font-size: var(--text-h1);
  line-height: var(--leading-tight);
  font-weight: 600;
}

.deck-note {
  font-size: var(--text-xs);
  line-height: var(--leading-mono);
  color: var(--text-dim);
}

.deck-label {
  margin-block: var(--space-4) var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--text-faint);
}

.qrow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.qnote {
  min-height: 1.6em;
  margin-block-start: var(--space-2);
  font-size: var(--text-xs);
  line-height: var(--leading-mono);
  color: var(--text-dim);
}

/* Action groups (h3 created by knight.js) */
#btns h3,
.cmu h3 {
  margin-block: var(--space-3) var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--text-faint);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

/* ---- CMU motion-capture browser (demo_web parity) ------------------------- */
.cmu-search {
  width: 100%;
  margin-block-start: var(--space-2);
  padding: var(--space-1) var(--space-2);
  background: var(--surface-2);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.cmu-search::placeholder {
  color: var(--text-faint);
}

.cmu-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-block-start: var(--space-2);
}

.cmu-grid {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: var(--space-1);
  max-height: 220px;
  overflow-y: auto;
  margin-block-start: var(--space-2);
}

/* ---- Camera presets (right rail) ------------------------------------------- */
.cambar {
  position: absolute;
  top: 25%;
  right: var(--space-4);
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* ---- Bottom playback bar ----------------------------------------------------
   Paper glass over the dark canvas: at 0.94 alpha the effective ground keeps
   --text-dim labels at ~4.6:1 on the darkest frame. */
.ctrl {
  position: absolute;
  left: var(--space-4);
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-2) var(--space-4);
  background: rgba(242, 240, 234, 0.94);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
}

.ctrl-field,
.ctrl-check {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-dim);
}

.ctrl-field input[type="range"] {
  width: 9rem;
  accent-color: var(--accent);
}

#scrub {
  width: min(21rem, 38vw);
}

#spdVal,
#tVal {
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.ctrl-check input {
  accent-color: var(--accent);
}

.deck-toggle {
  display: none;
}

/* ---- Mobile: deck becomes a bottom sheet; toggle lives in the ctrl bar ----- */
@media (max-width: 879px) {
  .deck-toggle,
  .deck-close {
    display: inline-block;
  }

  .deck {
    top: auto;
    left: var(--space-3);
    right: var(--space-3);
    bottom: 0;
    z-index: 25;
    width: auto;
    max-height: 62%;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: none;
    display: none;
  }

  .deck.is-open {
    display: block;
  }

  .cambar {
    top: 4.5rem;
    right: var(--space-3);
  }

  .stage-status {
    max-width: 62%;
  }

  .stage-meta {
    max-width: 55%;
  }

  .ctrl {
    left: var(--space-3);
    right: var(--space-3);
    bottom: var(--space-3);
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
  }

  .ctrl-field input[type="range"] {
    width: 6.5rem;
  }

  #scrub {
    width: min(11rem, 34vw);
  }
}

/* ---- Project hero: pinned Obys split screen (lid above the 3D stage) -------
   Scroll-driven strip while pinned (script adds the wrapper height). No-JS /
   reduced motion: nothing pins; the strip is a plain scrollable column. */

.phero-pin {
  height: calc(100vh - var(--header-height));
  height: calc(100svh - var(--header-height));
}

.phero {
  position: sticky;
  top: var(--header-height);
  display: flex;
  height: calc(100vh - var(--header-height));
  height: calc(100svh - var(--header-height));
  overflow: hidden;
  border-bottom: 1px solid var(--border-color);
}

.phero-half {
  position: relative;
  width: 50%;
}

/* Left: raised paper. max-width keeps ragged lines clear of the brackets. */
.phero-left {
  display: flex;
  align-items: center;
  background: var(--surface);
}

.phero-name {
  position: absolute;
  top: 50%;
  left: var(--space-4);
  transform: translateY(-50%);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  white-space: nowrap;
  color: var(--text);
}

.phero-info {
  display: grid;
  gap: var(--space-1);
  max-width: min(20rem, 24vw);
  margin-left: clamp(9rem, 17vw, 16rem);
}

.phero-cat {
  color: var(--text);
}

.phero-credits {
  color: var(--text-dim);
}

.phero-cta {
  justify-self: start;
  margin-top: var(--space-2);
}

/* Right: the ink slab carrying the media strip. */
.phero-right {
  background: var(--text);
}

.phero-media {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  scrollbar-width: none;
}

.phero-media::-webkit-scrollbar {
  display: none;
}

.phero-track {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: clamp(240px, 26vw, 420px);
  margin-inline: auto;
  padding-block: var(--space-8);
}

.phero-shot {
  display: block;
  transition: scale var(--dur-fast) var(--ease-out);
}

.phero-shot:active {
  scale: 0.96;
}

.phero-shot img {
  width: 100%;
  height: auto;
  outline: 1px solid rgba(255, 255, 255, 0.1); /* edge on the ink slab */
  transition: opacity var(--dur-base) var(--ease-out);
}

/* Three crops of the one artwork = three "frames". */
.phero-shot.is-a img,
.phero-shot.is-b img,
.phero-shot.is-c img {
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

.phero-shot.is-a img { object-position: 24% 50%; }
.phero-shot.is-b img { object-position: 50% 50%; }
.phero-shot.is-c img { object-position: 76% 50%; }

/* Dimming only while the JS driver runs (.is-pinned). */
.phero-pin.is-pinned .phero-media {
  overflow: hidden;
}

.phero-pin.is-pinned .phero-track {
  will-change: transform;
}

.phero-pin.is-pinned .phero-shot img {
  opacity: 0.45;
}

.phero-pin.is-pinned .phero-shot.is-current img,
.phero-pin.is-pinned .phero-shot:hover img,
.phero-pin.is-pinned .phero-shot:focus-visible img {
  opacity: 1;
}

/* Giant brackets on the seam: "(" ink on paper, ")" paper on ink. */
.phero-brackets {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-weight: 900;
  font-size: min(30vh, 16vw); /* ~30vh, text-safe cap */
  line-height: 0;
  pointer-events: none;
  user-select: none;
}

.phero-brackets span:first-child {
  color: var(--text);
}

.phero-brackets span:last-child {
  color: var(--bg);
}

.phero-back {
  position: absolute;
  left: var(--space-4);
  bottom: var(--space-4);
  font-size: var(--text-xs);
  color: var(--text-dim);
  text-decoration-color: currentColor;
}

.phero-back:hover {
  color: var(--accent-dim);
}

/* ---- Narrow viewports: hero stacks — copy on top, single image below ------- */
@media (max-width: 767px) {
  .phero {
    flex-direction: column;
    height: auto;
    min-height: calc(100vh - var(--header-height));
    min-height: calc(100svh - var(--header-height));
  }

  .phero-half {
    width: 100%;
  }

  .phero-left {
    display: block;
    padding: var(--space-8) var(--space-4) var(--space-6);
  }

  .phero-name {
    position: static;
    transform: none;
    margin-block-end: var(--space-3);
  }

  .phero-info {
    max-width: none;
    margin-left: 0;
  }

  .phero-right {
    flex: 1;
    min-height: 50vh;
    min-height: 50svh;
  }

  .phero-track {
    width: min(72vw, 300px);
    margin-block: auto;
  }

  .phero-shot:not(:first-child) {
    display: none; /* single-image fallback */
  }

  .phero-brackets {
    display: none;
  }

  .phero-back {
    color: rgba(242, 240, 234, 0.7); /* now sits on the ink half */
  }

  .phero-back:hover {
    color: var(--bg);
  }
}
