:root {
  --ink: #0b0d12;
  --paper: #f5f3ef;
  --accent: #6ee7ff;
  --muted: #8b93a7;
  --line: #262b36;
  font-family: "Inter", "Helvetica Neue", system-ui, -apple-system, sans-serif;
}

* { box-sizing: border-box; }

body { margin: 0; background: var(--ink); color: var(--paper); }

/* One centered column instead of content anchored to the left edge of a
   wide window — reads oddly once the video stopped filling the page. */
header, main { max-width: 1100px; margin-left: auto; margin-right: auto; }

header { padding: 1.2rem 1.5rem 0.4rem; }
h1 { margin: 0 0 0.2rem; font-size: 1.3rem; }
.hint { margin: 0; color: var(--muted); font-size: 0.9rem; }

.upload-bar { display: flex; align-items: center; gap: 0.7rem; margin-top: 0.8rem; }
.upload-bar .preview-status { margin-top: 0; flex: 1; min-width: 200px; }
.upload-bar .bar {
  height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.12);
  margin-top: 4px; overflow: hidden;
}
.upload-bar .bar > div { height: 100%; background: #f2ff00; transition: width 0.15s ease; }

main { display: flex; gap: 1.5rem; padding: 1rem 1.5rem 2rem; flex-wrap: wrap; align-items: flex-start; justify-content: center; }

/* Same cap as #previewVideo/#finalVideo (640px) — picking cameras and
   reviewing the result should be directly comparable sizes, not one much
   bigger than the other. */
.stage { flex: 0 1 640px; min-width: 360px; }

.video-wrap { position: relative; width: 100%; max-width: 640px; margin: 0 auto; aspect-ratio: 16/9; background: #000; }
.video-wrap video { width: 100%; height: 100%; display: block; }

/* Skeleton placeholder filling the same reserved box the video occupies, so
   clearing footage doesn't collapse or reflow the layout around it. */
.video-empty {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 1.5rem; color: var(--muted); font-size: 0.9rem;
  background: repeating-linear-gradient(135deg, #14171f, #14171f 10px, #191c25 10px, #191c25 20px);
}

/* Same striped placeholder, but pulsing — this one means "actively working",
   not "empty", so it needs to read as busy rather than static. Sized like
   #previewVideo/#finalVideo so nothing shifts once the real player replaces it. */
.video-skeleton {
  width: 100%; max-width: 640px; aspect-ratio: 16/9; margin: 1rem auto 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 0.9rem;
  background: repeating-linear-gradient(135deg, #14171f, #14171f 10px, #191c25 10px, #191c25 20px);
  animation: skeleton-pulse 1.4s ease-in-out infinite;
}
@keyframes skeleton-pulse {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

.overlay {
  position: absolute; inset: 0;
  display: grid;
  pointer-events: none;
}
.overlay .cell {
  border: 1px solid rgba(255, 255, 255, 0.12);
  cursor: pointer;
  pointer-events: auto;
  transition: background 0.1s ease;
}
.overlay .cell:hover { background: rgba(110, 231, 255, 0.22); }

/* No text label here — `matrix` already burns the camera number into the
   video itself (drawtext, for when the grid is watched standalone outside
   this editor). Drawing our own number on top of that in the overlay
   doubled it up, slightly offset, into a ghosted-looking duplicate. */

/* Which camera the EDL currently has live at the playhead, and — mid-pan —
   which one it's sweeping toward. Everything else dims down so the pick
   actually pops instead of just being one highlighted cell among 25. */
.overlay .cell.dim { background: rgba(0, 0, 0, 0.42); }
.overlay .cell.active {
  outline: 4px solid #f2ff00;
  outline-offset: -4px;
  background: rgba(242, 255, 0, 0.1);
  box-shadow: 0 0 14px rgba(242, 255, 0, 0.5);
}
.overlay .cell.target {
  outline: 4px dashed #f2ff00;
  outline-offset: -4px;
}

/* A camera some earlier entry already used, before the current one — dimmed
   like anything unused right now, but a thin border marks it as "already
   shown", not "never picked". */
.overlay .cell.used { outline: 1px solid rgba(242, 255, 0, 0.45); outline-offset: -1px; }

.transport { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.5rem; font-size: 0.85rem; }
.transport #seek { flex: 1; }
.transport #time { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.transport-hint { color: #ffb454; white-space: nowrap; }

.controls { display: flex; align-items: center; gap: 0.8rem; margin-top: 0.7rem; font-size: 0.9rem; }

/* Full width below the stage, not a side column — a proportional timeline
   needs room to actually show duration, not be squeezed into 360px. */
.edl { flex: 1 1 100%; }
.edl h2 { font-size: 1rem; margin: 0 0 0.4rem; }

.timeline-scale {
  display: flex; justify-content: space-between;
  font-size: 0.78rem; color: var(--muted); font-variant-numeric: tabular-nums;
  margin-bottom: 3px;
}

.uniform-pan-row {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: 0.82rem; color: var(--muted); margin-bottom: 6px;
}
.uniform-pan-row input[type="range"] { width: 8em; accent-color: #f2ff00; }
.uniform-pan-row #uniformPanValue { color: #f2ff00; font-variant-numeric: tabular-nums; }

/* One control per transition between camera picks, positioned at the exact
   time it happens (same left% math as the timeline blocks below it), so
   "set this cut to a pan" reads as an action on that specific transition —
   not a mode you had to remember to flip before clicking the next camera. */
.timeline-transitions { position: relative; height: 24px; }
.transition { position: absolute; top: 0; transform: translateX(-50%); display: flex; align-items: center; gap: 2px; }
.transition-btn {
  background: #12151c; color: var(--muted); border: 1px solid var(--line);
  border-radius: 10px; padding: 1px 7px; font-size: 0.68rem; line-height: 1.4;
  cursor: pointer; white-space: nowrap;
}
.transition-btn:hover { border-color: var(--accent); }
.transition-btn.pan { color: #f2ff00; border-color: #f2ff00; background: rgba(242, 255, 0, 0.12); }
.transition-duration { width: 4.5em; height: 12px; accent-color: #f2ff00; cursor: pointer; }
.transition-duration-value {
  font-size: 0.68rem; color: #f2ff00; font-variant-numeric: tabular-nums; min-width: 2.4em;
}

.timeline {
  position: relative; height: 64px;
  background: #12151c; border: 1px solid var(--line); border-radius: 6px;
  overflow: hidden;
}
.timeline-empty {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 0.85rem; pointer-events: none;
}

/* One block per EDL segment — a hold (fixed camera) or a pan (sweep between
   two). Position/width are percentages of the container, so they're always
   proportional to the video's real duration regardless of pixel width. */
.seg {
  position: absolute; top: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center;
  border-right: 1px solid rgba(0, 0, 0, 0.5);
  font-size: 0.8rem; font-weight: 700; color: #fff;
  cursor: pointer; overflow: hidden; white-space: nowrap;
}
.seg.hold { background: linear-gradient(180deg, #2b3142, #1d222d); }
.seg.hold:hover { background: linear-gradient(180deg, #363d53, #262c3a); }
.seg.pan {
  font-size: 0.7rem;
  background: repeating-linear-gradient(135deg, #3a3f1f, #3a3f1f 7px, #4a5024 7px, #4a5024 14px);
}
.seg.active {
  outline: 3px solid #f2ff00; outline-offset: -3px;
  background: rgba(242, 255, 0, 0.16);
  z-index: 2;
}
.seg-del {
  position: absolute; top: 2px; right: 2px;
  background: rgba(0, 0, 0, 0.55); color: #ff9b9b; border: none; border-radius: 3px;
  font-size: 0.68rem; line-height: 1; padding: 1px 4px; cursor: pointer;
}

.playhead {
  position: absolute; top: 0; bottom: 0; left: 0; width: 2px;
  background: #fff; box-shadow: 0 0 5px rgba(255, 255, 255, 0.9);
  pointer-events: none; z-index: 3;
}

button {
  background: #12151c; color: var(--paper); border: 1px solid var(--line);
  border-radius: 6px; padding: 6px 12px; cursor: pointer; font-size: 0.85rem;
}
button:hover { border-color: var(--accent); }
button:disabled { opacity: 0.5; cursor: default; }
button.danger { color: #ff9b9b; }

.actions { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.8rem; }

/* Tracks whether the preview below actually reflects the table above —
   editing the list after a render leaves the old preview showing with no
   other hint that it's now stale. */
.preview-status {
  margin-top: 0.6rem; padding: 5px 9px; border-radius: 5px;
  font-size: 0.82rem; display: inline-flex; align-items: center; gap: 0.4em;
}
.status--none { color: var(--muted); }
.status--rendering { color: #f2ff00; }
.status--ready { color: #7CFF9B; background: rgba(124, 255, 155, 0.1); }
.status--stale { color: #ffb454; background: rgba(255, 180, 84, 0.1); }
.status--error { color: #ff9b9b; background: rgba(255, 155, 155, 0.1); }

/* The timeline section is full-width (it needs the room), but a rendered
   result stretched to that same full width was comically large — cap it
   like any other video player instead of matching the timeline's width.
   Capping the width without centering just left it stranded on the left
   edge of that full-width section, so margin: auto to actually center it. */
#previewVideo, #finalVideo { width: 100%; max-width: 640px; margin: 1rem auto 0; background: #000; display: block; }

#renderFinalBtn { border-color: #7CFF9B; color: #7CFF9B; }
#renderFinalBtn:hover { background: rgba(124, 255, 155, 0.1); }

.download-link {
  display: inline-flex; align-items: center; gap: 0.4em;
  margin-top: 0.6rem; padding: 7px 14px; border-radius: 6px;
  background: #7CFF9B; color: #06210f; font-weight: 700; font-size: 0.9rem;
  text-decoration: none;
}
.download-link:hover { background: #97ffb0; }
