/* Base layout and shared components. Panel-specific styles live in css/. */

:root {
  --background: #1e1f24;
  --surface: #26272e;
  --surface-raised: #2f3038;
  --border: #3c3d47;
  --text: #e8e8ec;
  --text-dim: #9a9ba6;
  --accent: #4f9cf9;
  --warning: #e2a636;
  --error: #e05656;
  /* Scrubber track: the indexed (seekable) range against the rest of a clip
     whose index is still being built. */
  --scrubber-indexed: #6b6d7a;
  --scrubber-unindexed: #34353d;
  --toolbar-height: 44px;
}

* { box-sizing: border-box; }

html {
  background: var(--background);
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--background);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
  overscroll-behavior: none;
}

/* ---------- Toolbar ---------- */

#toolbar {
  height: var(--toolbar-height);
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 12px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  user-select: none;
}

#application-title {
  flex: 0 0 auto;
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
}

/* Everything that can be clipped/scrolled when the window is too narrow —
   the title before it and the hovered-pixel readout after it are outside
   this region so they never scroll out of view. */
#toolbar-scroll-region {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 16px;
  overflow-x: auto;
  scrollbar-width: thin;
}
#toolbar-scroll-region::-webkit-scrollbar { height: 6px; }
#toolbar-scroll-region::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
}

.toolbar-group {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

button {
  background: var(--surface-raised);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 5px 10px;
  font-size: 13px;
  cursor: pointer;
}

button:hover:not(:disabled) { border-color: var(--accent); }
button:disabled { opacity: 0.45; cursor: default; }
/* Suppress the outline left behind after a mouse click (it stays until focus
   moves elsewhere, e.g. a tool button clicked then swapped via hotkey), while
   keeping it for keyboard navigation (:focus-visible, e.g. tabbing through). */
button:focus:not(:focus-visible) { outline: none; }

#hovered-pixel-label {
  flex: 0 0 auto;
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ---------- Settings modal ---------- */

.settings-dialog {
  min-width: 280px;
  padding: 16px;
  background: var(--surface-raised);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
}

.settings-dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
}

.settings-dialog h2 {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

.settings-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: 13px;
}

.settings-row select {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 3px 6px;
  font-size: 12px;
}

.coordinate-select-wrapper {
  position: relative;
  display: inline-block;
}

.coordinate-select-lock-overlay {
  display: none;
  position: absolute;
  inset: 0;
  cursor: not-allowed;
}

.settings-dialog-close {
  display: block;
  margin-left: auto;
}

/* ---------- Second-video prompt ---------- */

.second-video-question {
  margin: 0 0 12px;
  font-size: 13px;
}

.second-video-choices {
  display: flex;
  gap: 10px;
  margin-bottom: 14px;
}

/* Two side-by-side toggle buttons; the highlighted one gets an accent outline. */
.second-video-choice {
  flex: 1 1 0;
  padding: 12px 10px;
  font-size: 16px;
  font-weight: 600;
}

.second-video-choice.selected {
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

.second-video-save {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  font-size: 12px;
  color: var(--text-dim);
}

.second-video-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* ---------- First screenful: tool rail + canvas + transport + tabs ---------- */

#viewport-section {
  height: calc(100vh - var(--toolbar-height));
  display: flex;
  min-height: 0;
}

#canvas-column {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

/* ---------- Tool rail (Illustrator-style icon column) ---------- */

#tool-rail {
  flex: 0 0 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  user-select: none;
  /* When the viewport is too short to show every button, the rail scrolls on
     its own (buttons keep their size rather than squashing). When everything
     fits, the rail is not scrollable and the wheel falls through to the page. */
  overflow-y: auto;
  scrollbar-width: thin;
}
#tool-rail::-webkit-scrollbar { width: 6px; }
#tool-rail::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
}

.rail-button {
  position: relative;   /* anchors the corner hotkey label */
  flex-shrink: 0;       /* never squash to fit a short viewport — scroll instead */
  width: 32px;
  height: 32px;
  padding: 0;
  font-size: 15px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* This glyph renders small at the base size; enlarge it to fill the button. */
#tool-rail button[data-tool="point"],
#frame-agnostic-toggle {
  font-size: 21px;
}

/* ● sits visibly below true center in its own line box at this font size (a
   font-metrics quirk of that particular glyph, not a layout bug); nudge the
   flex-centered content up so it reads as centered in the button. */
#tool-rail button[data-tool="point"] { padding-bottom: 2px; }

/* Single-key hotkey, tucked into the button's bottom-right corner. Inherits the
   button color (white when active, dim otherwise) and stays out of pointer flow. */
.rail-button[data-hotkey]::after {
  content: attr(data-hotkey);
  position: absolute;
  right: 2px;
  bottom: 1px;
  font-size: 8px;
  line-height: 1;
  opacity: 0.55;
  pointer-events: none;
}

.rail-button.active-tool {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Clicking (or hotkey-pressing) the already-active tool no longer falls back
   to pan; it just blinks the background briefly, halfway from the active
   blue to the inactive grey, as a small acknowledgment of the press. */
.rail-button.active-tool.tool-blink {
  background: color-mix(in srgb, var(--accent) 50%, var(--surface-raised) 50%);
}

/* The annotation-mode toggle sits above the tools; the active mode is filled
   like an active tool but stays visually a mode, not the currently held tool. */
.rail-button.mode-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Pinned to the very bottom of the rail (the page-scroll toggle). */
.rail-button-bottom {
  margin-top: auto;
}

/* Looks like button:disabled, but stays a real (non-disabled) button so click
   and contextmenu still fire — used for tools that need a matching layer
   before they can be used, or that have no implementation yet. */
.rail-button-unavailable {
  opacity: 0.45;
}

/* The scroll toggle's arrow: large, thick-stroked, and flipped to point up
   once the page has scrolled away from the top. */
#scroll-toggle-button .scroll-arrow {
  display: block;
  transition: transform 0.15s ease;
}
#scroll-toggle-button.pointing-up .scroll-arrow {
  transform: rotate(180deg);
}

.rail-divider {
  flex-shrink: 0;   /* keep its height when the rail scrolls */
  width: 24px;
  border-top: 1px solid var(--border);
  margin: 4px 0;
}

/* ---------- Layer tab bar (bottom of the canvas area) ---------- */

#layer-tabs-container {
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  background: var(--surface);
  border-top: 1px solid var(--border);
  user-select: none;
  min-height: 34px;
}

.layer-tabs-scroll-button {
  flex: 0 0 auto;
  border: none;
  border-radius: 0;
  background: var(--surface);
  color: var(--text-dim);
  padding: 0 8px;
}

/* Shown only when there is something to scroll to in that direction (the
   hidden attribute is managed by layer-tabs.js). */
.layer-tabs-scroll-button[hidden] { display: none; }

.layer-tabs-strip {
  flex: 1 1 auto;
  display: flex;
  overflow-x: auto;
  scrollbar-width: none;   /* the ◀ ▶ buttons are the scroll affordance */
}
.layer-tabs-strip::-webkit-scrollbar { display: none; }

.layer-tab {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  border-right: 1px solid var(--border);
  cursor: pointer;
  white-space: nowrap;
  color: var(--text-dim);
  max-width: 200px;
  touch-action: none;   /* tabs are dragged sideways to re-order layers */
}

/* While dragged, the tab glides with the pointer via a translateX transform
   set by layer-tabs.js; raise it above its neighbors and lift it visually. */
.layer-tab.dragging {
  opacity: 0.85;
  cursor: grabbing;
  position: relative;
  z-index: 5;
  background: var(--surface-raised);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

.layer-tab.active {
  background: var(--surface-raised);
  color: var(--text);
  box-shadow: inset 0 2px 0 var(--accent);
}

.layer-tab .layer-tab-name {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The clock marking the primary video's tab when several videos are open. */
.layer-tab .layer-tab-primary-clock {
  display: flex;
  align-items: center;
  color: var(--accent);
}

.layer-tab .layer-tab-primary-clock svg { display: block; }

.layer-tab .layer-tab-eye {
  border: none;
  background: none;
  padding: 0;
  display: flex;
  align-items: center;
  color: inherit;
  cursor: pointer;
  opacity: 0.9;
}

.layer-tab .layer-tab-eye svg { display: block; }

.layer-tab .layer-tab-eye.layer-hidden { opacity: 0.35; }

.layer-tab input.layer-tab-rename {
  width: 90px;
  font-size: 13px;
}

.layer-tab-add {
  flex: 0 0 auto;
  border: none;
  border-radius: 0;
  background: var(--surface);
  color: var(--text-dim);
  padding: 0 12px;
}

/* Deletes the layer selected in the tab bar; sits just right of the ＋. */
.layer-tab-delete-current {
  flex: 0 0 auto;
  border: none;
  border-radius: 0;
  background: var(--surface);
  color: var(--text-dim);
  padding: 0 12px;
}

.layer-tab-delete-current:hover:not(:disabled) {
  color: var(--error);
  border-color: transparent;
}

.layer-tab-add-menu {
  /* position, left, bottom are set inline (see layer-tabs.js) — fixed
     viewport coordinates so the menu is never clipped by the tab strip's
     overflow, regardless of which parent the ＋ button currently rides in. */
  z-index: 30;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

.layer-tab-add-menu button { border: none; text-align: left; }

.layer-tab-add-menu-separator {
  height: 1px;
  margin: 3px 2px;
  background: var(--border);
}

/* ---------- Plugin settings (inside the layer detail panel) ---------- */

.plugin-settings {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

.plugin-settings h3 {
  margin: 0 0 4px;
  font-size: 13px;
  color: var(--accent);
}

.plugin-settings-explanation,
.plugin-settings-status {
  color: var(--text-dim);
  font-size: 12px;
  margin: 4px 0;
}

/* ---------- Below the fold: details sections ---------- */

#details-section {
  display: grid;
  grid-template-columns: minmax(280px, 380px) 1fr;
  gap: 12px;
  padding: 12px;
  align-items: start;
}

#layer-detail-container { grid-column: 1; }
#class-manager-container { grid-column: 1; }
#annotations-table-container { grid-column: 2; grid-row: 1 / span 2; }

@media (max-width: 900px) {
  #details-section { grid-template-columns: 1fr; }
  #annotations-table-container { grid-column: 1; grid-row: auto; }
}

/* ---------- Layer detail panel ---------- */

.layer-detail-type {
  color: var(--text-dim);
  font-size: 13px;
  margin: 0 0 10px;
}

.layer-detail-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.layer-detail-row label { display: flex; align-items: center; gap: 6px; }
.layer-detail-transform-field input { width: 76px; }
.layer-detail-opacity input[type="range"] { width: 120px; }

.layer-detail-facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 3px 12px;
  margin: 8px 0 0;
  font-size: 13px;
}

.layer-detail-facts dt { color: var(--text-dim); }
.layer-detail-facts dd { margin: 0; font-variant-numeric: tabular-nums; }

.layer-detail-empty, .layer-detail-count { color: var(--text-dim); font-size: 13px; }

.panel {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px;
}

.panel h2 {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

/* ---------- Stage ---------- */

#stage-section {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

#stage-container {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  background: #101014;
}

#stage-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;   /* the viewer owns all pointer gestures */
}

#drop-hint {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  text-align: center;
  pointer-events: none;
}

#drop-hint.hidden { display: none; }
.drop-hint-details { font-size: 12px; max-width: 380px; }

/* Indexing progress, bottom-left of the stage. Stays up while a clip plays
   whose index is still growing underneath it. */
#indexing-status {
  position: absolute;
  left: 10px;
  bottom: 10px;
  padding: 4px 10px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

#indexing-status[hidden] { display: none; }

#stage-container.drag-over::after {
  content: "";
  position: absolute;
  inset: 6px;
  border: 2px dashed var(--accent);
  border-radius: 10px;
  pointer-events: none;
}

/* ---------- Transport bar (populated by js/ui/transport.js) ---------- */

#transport-container {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--surface);
  border-top: 1px solid var(--border);
  user-select: none;
}

/* Fixed square box, regardless of which icon it holds, so the play/pause
   button never resizes when its icon changes (it used to, because ▶ and ⏸
   are different widths as text glyphs). */
#transport-container .transport-play,
#transport-container .transport-step-backward,
#transport-container .transport-step-forward {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 32px;
  height: 32px;
  padding: 0;
}

#transport-container .transport-icon {
  width: 18px;
  height: 18px;
  display: block;
}

/* Both icons are always in the DOM (see js/ui/transport.js); only one is
   shown at a time, so swapping between them never changes the button's box. */
#transport-container .transport-icon-pause {
  display: none;
}

#transport-container .transport-play.is-playing .transport-icon-play {
  display: none;
}

#transport-container .transport-play.is-playing .transport-icon-pause {
  display: block;
}

/* The scrubber's track is painted in two greys, the way a video player shows
   buffering: solid for the range whose frames are indexed and therefore
   seekable, dim for the remainder of a clip still being indexed. The fraction
   is set by js/ui/transport.js; a complete index leaves it at 100%, which is
   the ordinary single-tone track. Both vendor track/thumb pairs have to be
   written out — a shared selector list would be dropped whole by any browser
   that does not recognize one of its parts. */
#transport-container .transport-scrubber {
  --indexed-fraction: 100%;
  --scrubber-track: linear-gradient(to right,
    var(--scrubber-indexed) 0 var(--indexed-fraction),
    var(--scrubber-unindexed) var(--indexed-fraction) 100%);
  flex: 1 1 auto;
  min-width: 60px;
  appearance: none;
  -webkit-appearance: none;
  height: 16px;
  background: transparent;
}

#transport-container .transport-scrubber::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: var(--scrubber-track);
}

#transport-container .transport-scrubber::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--scrubber-track);
}

#transport-container .transport-scrubber::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  margin-top: -4px;   /* centre the thumb on the 6px track */
  border-radius: 50%;
  border: none;
  background: var(--text);
}

#transport-container .transport-scrubber::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: none;
  background: var(--text);
}

#transport-container .transport-scrubber:disabled::-webkit-slider-thumb { background: var(--text-dim); }
#transport-container .transport-scrubber:disabled::-moz-range-thumb { background: var(--text-dim); }

#transport-container .transport-readout {
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* Its width is set by js/ui/transport.js to reserve space for the current
   time's minute digits to grow into; the dot stays centered as that space
   shrinks. */
#transport-container .transport-time-gap {
  display: inline-flex;
  justify-content: center;
}

/* While the index grows, the totals in the readout are a floor and a claim
   rather than facts, so they are dimmed; they come up to full weight when the
   pass has read the whole clip. A truncated index is not tentative — it is
   final and short — so it takes the warning color instead. */
#transport-container .transport-readout.index-growing {
  color: color-mix(in srgb, var(--text-dim) 65%, transparent);
}

#transport-container .transport-readout.index-truncated {
  color: var(--warning);
}

.index-waiting {
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
  font-style: italic;
}

.index-waiting[hidden] { display: none; }

#transport-container .transport-frame-input {
  background: var(--surface-raised);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px 4px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.exactness-warning {
  background: color-mix(in srgb, var(--warning) 25%, transparent);
  color: var(--warning);
  border: 1px solid var(--warning);
  border-radius: 6px;
  padding: 2px 8px;
  font-size: 12px;
  white-space: nowrap;
}

/* ---------- Offscreen video host ---------- */

#video-host {
  position: fixed;
  left: -100000px;
  top: 0;
}

#video-host canvas, #video-host video {
  display: block;
}

/* ---------- Toasts (styled further by the toasts module if needed) ---------- */

#toast-container {
  position: fixed;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 100;
  pointer-events: none;
}

/* ---------- Shared form controls ---------- */

input[type="text"], input[type="number"], select {
  background: var(--surface-raised);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 6px;
  font-size: 13px;
}

input[type="range"] { accent-color: var(--accent); }
input[type="color"] { border: none; background: none; padding: 0; width: 24px; height: 24px; }
