/* ==========================================================================
   Forge shared stylesheet -- the single source of truth for how every tool
   in the hub looks.
   ==========================================================================

   Served by each app's own backend at /shared/forge.css (each web_app.py
   mounts this directory), so a change here reaches all three tools at once.
   Before this existed the palette was copy-pasted into every frontend and had
   already drifted apart between them.

   An app supplies only its own identity and its genuinely unique widgets, by
   linking this file and then declaring its accent in a small style block of
   its own. See README.md section 3 for the frontend contract.

   Keep --accent / --accent-2 / --on-accent as the ONLY tokens an app
   overrides. The neutrals and semantic colours are what make the three tools
   read as one product inside the hub window.

   NOTE: CSS comments do NOT nest. An inner "*\/" closes the whole block early
   and the parser then swallows whatever follows -- which is exactly how this
   file once ate its own :root and rendered every page black-on-white.
   ========================================================================== */

:root {
  /* Neutrals -- identical in every tool, do not override per app. */
  --bg: #0f1115;
  --panel: #171a21;
  --panel-2: #1e222b;
  --border: #2a2f3a;
  --text: #e7e9ee;
  --muted: #8b93a3;
  /* Raised panels, quiet text and hairlines. The hub sends these per theme
     with the rest (forge_themes.SURFACE_TOKENS), held readable against the
     theme's text; an app that keeps its own dark ones breaks light themes. */
  --surface: #13161c;
  --raise: #191d25;
  --raise-2: #20252f;
  --faint: #6c7484;
  --hair: rgba(255, 255, 255, 0.07);
  --hair-2: rgba(255, 255, 255, 0.11);

  /* Semantic -- identical in every tool. */
  --good: #59d499;
  --warn: #f2a154;
  --bad: #f2637d;
  --on-bad: #1a0d12; /* text on a --bad fill (a count badge) */

  /* Identity -- the one pair an app overrides. Defaults to the hub's blue. */
  --accent: #6ea8fe;
  --accent-2: #4f8cf7;

  /* Text that sits ON an --accent-2 fill. Apps with a light accent should
     override this too so primary buttons keep their contrast. */
  --on-accent: #0b1220;

  /* THE white-on-white fix.

     WebKitGTK draws native controls -- <select> popups, number spinners,
     checkboxes, <audio> players, scrollbars -- with the GTK theme, not with
     page CSS. Under a light GTK theme that means a white popup, while the
     near-white `color` this page sets on <select> is inherited by its
     <option>s: white text on white, which made most of MediaForge's dropdowns
     unreadable (it has 30 selects across its tabs).

     `color-scheme: dark` tells the engine to render those native widgets with
     their dark variants instead. The explicit option/optgroup rules below are
     belt-and-braces for builds that ignore it. */
  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.45 -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* --------------------------------------------------------------------------
   Form controls
   -------------------------------------------------------------------------- */
button { font: inherit; cursor: pointer; }

input, select, textarea {
  font: inherit;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 9px;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }
textarea { width: 100%; resize: vertical; }

/* Paired with color-scheme: dark above -- see the note in :root. */
option, optgroup {
  background: var(--panel-2);
  color: var(--text);
}

/* Checkboxes sit inline inside labels all over both apps and must not stretch
   to the field width. Every call site used to repeat style="width:auto". */
input[type="checkbox"], input[type="radio"] { width: auto; accent-color: var(--accent); }
input[type="color"] { padding: 2px; height: 34px; }

label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px; }

.field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.row { display: flex; gap: 14px; flex-wrap: wrap; }
.row > .field { flex: 1; min-width: 160px; }

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.btn {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 7px;
  padding: 8px 14px;
}
.btn:hover { border-color: var(--accent); }
.btn-primary { background: var(--accent-2); border-color: var(--accent-2); color: var(--on-accent); font-weight: 600; }
.btn-danger { background: transparent; border-color: var(--bad); color: var(--bad); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn:disabled:hover { border-color: var(--border); }

/* --------------------------------------------------------------------------
   Layout: header / tabs / panels
   -------------------------------------------------------------------------- */
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  margin-bottom: 16px;
}
.muted { color: var(--muted); }
.hidden { display: none !important; }

#app { display: flex; flex-direction: column; height: 100vh; }

header {
  display: flex; align-items: center; gap: 16px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
  flex: none;
}
header .brand { font-weight: 700; }
header .brand span { color: var(--accent); }
header .spacer { flex: 1; }

nav {
  display: flex; gap: 2px;
  padding: 8px 18px 0;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
  flex: none; flex-wrap: wrap;
}
nav .tab { padding: 9px 14px; border-radius: 8px 8px 0 0; color: var(--muted); cursor: pointer; font-size: 13px; }
nav .tab:hover { color: var(--text); }
nav .tab.active {
  color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-bottom-color: var(--bg);
  margin-bottom: -1px;
}

main { flex: 1; overflow-y: auto; padding: 22px; }
.panel { display: none; max-width: 960px; margin: 0 auto; }
.panel.active { display: block; }
.placeholder { text-align: center; padding: 60px 20px; color: var(--muted); }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--border); }
th { color: var(--muted); font-weight: 600; }

/* --------------------------------------------------------------------------
   Job output: log boxes, progress, toasts
   -------------------------------------------------------------------------- */

/* Both apps had this same block of monospace-log styling pasted inline onto
   half a dozen divs each. It is one class now; height comes from a modifier
   or an inline height on the element. */
.logbox {
  background: #0b0d11;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  font: 12px/1.5 ui-monospace, monospace;
  white-space: pre-wrap;
  overflow-y: auto;
  height: 220px;
}
.logbox.tall { height: 320px; }
.logbox.short { height: 180px; }

.progress-bar { height: 6px; background: var(--panel-2); border-radius: 3px; overflow: hidden; margin: 8px 0 4px; }
.progress-bar > div { height: 100%; background: var(--accent-2); width: 0%; transition: width .2s; }

.toast {
  position: fixed; bottom: 18px; right: 18px;
  padding: 10px 16px; border-radius: 8px;
  background: var(--panel-2); border: 1px solid var(--border);
  font-size: 13px; max-width: 420px; z-index: 50;
}
/* Standalone (outside Forge) the floating Full screen / Close app pair sits in
   this corner (shared/forge_chrome.js marks the page), so toasts go above it. */
.forge-floating-chrome .toast { bottom: 52px; }
/* toast(msg, kind): apps say the same thing several ways, all styled here */
.toast.ok, .toast.good { border-color: var(--good); color: var(--good); }
.toast.err, .toast.error, .toast.bad { border-color: var(--bad); color: var(--bad); }

/* --------------------------------------------------------------------------
   Simple / Advanced mode
   --------------------------------------------------------------------------
   Anything marked .adv is hidden until advanced mode is on. ForgeMode in
   forge.js owns the body class and persists the choice to the app's settings
   endpoint as advanced_mode. */
body:not(.advanced) .adv { display: none !important; }

.mode-switch {
  display: flex; align-items: center; gap: 2px;
  font-size: 12px; padding: 3px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--panel-2);
}
.mode-switch button {
  background: none; border: none; color: var(--muted); font: inherit;
  padding: 4px 12px; border-radius: 999px;
}
.mode-switch button.on { background: var(--accent-2); color: var(--on-accent); font-weight: 600; }

/* --------------------------------------------------------------------------
   Clear ("x") buttons
   --------------------------------------------------------------------------
   Any element marked data-clearable gets one of these in its corner, injected
   by initClearButtons() in forge.js. Adding one to a new output box is just
   the attribute -- no markup and no wiring. */
.clearable-wrap { position: relative; }
.clear-x {
  position: absolute; top: 6px; right: 8px; z-index: 2;
  background: var(--panel-2); border: 1px solid var(--border);
  color: var(--muted); border-radius: 6px;
  line-height: 1; padding: 3px 8px; font-size: 14px;
  opacity: 0; transition: opacity .15s;
}
.clearable-wrap:hover .clear-x, .clear-x:focus { opacity: 1; }
.clear-x:hover { color: var(--text); border-color: var(--bad); }

/* --------------------------------------------------------------------------
   Thumbnails
   -------------------------------------------------------------------------- */

/* Media file thumbnails in list views (fileThumb() in forge.js). */
.file-thumb {
  width: 84px; height: 48px; flex: none;
  object-fit: cover; border-radius: 4px;
  border: 1px solid var(--border); background: var(--panel-2);
}
td .file-thumb { width: 72px; height: 41px; }
/* Hatched placeholder while loading, and permanently for files nothing can
   render a frame from. */
.file-thumb.blank {
  background: repeating-linear-gradient(45deg,
    var(--panel-2), var(--panel-2) 6px, var(--panel) 6px, var(--panel) 12px);
}

/* Portrait cover art (book covers). */
.cover-thumb {
  width: 44px; height: 66px; flex: none;
  object-fit: cover; border-radius: 4px;
  border: 1px solid var(--border); background: var(--panel-2);
}
.cover-fallback {
  width: 44px; height: 66px; flex: none;
  border-radius: 4px; border: 1px solid var(--border);
  background: linear-gradient(160deg, var(--panel-2), #10131a);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 700; color: var(--accent);
}

/* A heading row with a dismiss button on the right. */
.section-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.section-head h3 { margin: 0; flex: 1; font-size: 15px; }

/* A slider and its number box (ForgeSliders in forge.js). */
.forge-pair { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.forge-pair input[type=range] { flex: 1; min-width: 60px; }
.forge-pair-num { width: 72px; flex: none; }
.forge-pair-range { min-width: 60px; margin-right: 6px; vertical-align: middle; }
.forge-pair-hidden { display: none !important; }

/* --------------------------------------------------------------------------
   Reduced motion
   --------------------------------------------------------------------------
   When the desktop asks for less motion, every app's transitions and CSS
   animations finish at once. Durations go to almost zero rather than "none"
   so transitionend and animationend still fire for scripts that wait on them. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
