/* ==========================================================================
   THE DESIGN
   ==========================================================================

   One stylesheet for the whole application — the sign-in card, the console and
   every modal. No framework, no build step, no preprocessor: edit and reload.

   HOW IT IS PUT TOGETHER

     :root tokens        every colour, radius and shadow is a variable. Restyle
                         the entire app by changing the dozen values below and
                         nothing else. Never hard-code a colour further down.
     Auth pages          .auth-shell / .auth-card / .field / .btn-primary
     App shell           .app is a two-column grid: fixed .rail + .main
     Rail                .rail-scroll scrolls; .rail-pinned (meters) and
                         .rail-foot (queue + user) stay put
     Workspace           .workspace holds one .pane per engine; each .pane is a
                         three-column grid — .col-chats | .col-chat | .col-params
                         with .folded-left / .folded-right collapsing the sides
                         down to a .reopen handle
     Conversation        .msg / .msg-body / .job-card / .result tiles
     Composer            .composer-wrap is fixed to the bottom of column 2;
                         .dropzone covers it while a file is dragged over
     Parameters          .group / .pfield / .switch / .seed-row — the classes
                         app.js emits for each field type in app/models.php
     Libraries           .lib-grid / .lib-item, with hover video previews
     Modals              .modal-back > .modal, used by the queue and the picker
     Toasts              .toast-host, bottom-right, auto-dismissing
     Responsive          one breakpoint at 1100px (side columns become overlays)
                         and one at 720px (the rail becomes a drawer)

   THE TWO RULES THAT KEEP THE LAYOUT HONEST

     1. The rail and the top bar are fixed furniture; only the three columns
        scroll, and each scrolls on its own. Opening the parameter panel can
        therefore never move the conversation.
     2. Nothing inside a column sets a page-level height. Columns are grid
        children with min-height: 0 — that is what allows them to scroll
        internally instead of stretching the page.

   Class names are shared with assets/js/app.js and htdocs/dashboard.php.
   Renaming one here means renaming it in both of those.
   ========================================================================== */

:root {
  --bg:            #0b0d10;
  --bg-elev:       #12151a;
  --bg-elev-2:     #171b21;
  --bg-input:      #1b2027;
  --line:          #262c35;
  --line-soft:     #1e242c;
  --text:          #e8ecf1;
  --text-dim:      #97a2b1;
  --text-faint:    #64707f;
  --accent:        #6f8cff;
  --accent-2:      #a77bff;
  --accent-soft:   rgba(111,140,255,.14);
  --ok:            #3ecf8e;
  --warn:          #f2b544;
  --bad:           #ff6b6b;
  --radius:        14px;
  --radius-sm:     10px;
  --shadow:        0 18px 48px rgba(0,0,0,.5);
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 8px; border: 2px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: var(--line-strong); }

/* ==========================================================================
   Auth pages
   ========================================================================== */

.auth-body {
  display: grid;
  place-items: center;
  min-height: 100vh;
  background:
    radial-gradient(900px 600px at 15% -10%, color-mix(in srgb,var(--accent) 16%,transparent), transparent 60%),
    radial-gradient(800px 500px at 95% 110%, color-mix(in srgb,var(--accent2) 13%,transparent), transparent 60%),
    var(--bg);
  padding: 24px;
}

.auth-shell { width: 100%; max-width: 420px; }

.auth-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 34px 30px 26px;
  box-shadow: var(--shadow);
}

.auth-brand { display: flex; align-items: center; gap: 14px; margin-bottom: 26px; }

.auth-logo {
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 13px;
  background: var(--accent);
  color: var(--accentInk);
  box-shadow: 0 8px 22px color-mix(in srgb,var(--accent) 32%,transparent);
}
.auth-logo svg { width: 24px; height: 24px; }
.auth-logo-alt { background: linear-gradient(135deg, var(--warn), color-mix(in srgb,var(--warn) 55%,var(--bad))); box-shadow: 0 8px 22px color-mix(in srgb,var(--warn) 28%,transparent); }

.auth-brand h1 { margin: 0; font-size: 21px; font-weight: 650; letter-spacing: -.01em; }
.auth-brand p  { margin: 2px 0 0; font-size: 13px; color: var(--text-dim); }

.auth-form { display: flex; flex-direction: column; gap: 16px; }

.field { display: flex; flex-direction: column; gap: 7px; }
.field-label { font-size: 12.5px; font-weight: 550; color: var(--text-dim); letter-spacing: .02em; }

.field input,
.pw-wrap input {
  width: 100%;
  padding: 12px 14px;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.field input:focus, .pw-wrap input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  background: var(--surface2);
}
.field input:disabled { opacity: .5; cursor: not-allowed; }
.field input::placeholder { color: var(--text-faint); }

.pw-wrap { position: relative; display: block; }
.pw-wrap input { padding-right: 44px; }
.pw-toggle {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: none; border: none; border-radius: 8px;
  color: var(--text-faint); cursor: pointer;
}
.pw-toggle:hover { color: var(--text); background: color-mix(in srgb,var(--text) 5%,transparent); }
.pw-toggle.on { color: var(--accent); }
.pw-toggle svg { width: 17px; height: 17px; }

.btn-primary {
  margin-top: 4px;
  padding: 12px 16px;
  background: var(--accent);
  border: none; border-radius: 999px;
  color: var(--accentInk); font-weight: 600; font-size: 14.5px;
  box-shadow: 0 8px 24px -10px var(--glow), inset 0 -2px 0 rgba(0,0,0,.12);
  cursor: pointer;
  transition: filter .15s, transform .06s, opacity .15s;
}
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); }
.btn-primary:active:not(:disabled) { transform: translateY(1px); }
.btn-primary:disabled { opacity: .45; cursor: not-allowed; }
.btn-primary.as-link { display: block; text-align: center; text-decoration: none; }

.alert {
  padding: 11px 13px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  margin-bottom: 18px;
  border: 1px solid transparent;
}
.alert-error { background: color-mix(in srgb,var(--bad) 10%,transparent);  border-color: color-mix(in srgb,var(--bad) 30%,transparent);  color: var(--bad-text); }
.alert-info  { background: color-mix(in srgb,var(--accent) 10%,transparent);  border-color: color-mix(in srgb,var(--accent) 30%,transparent);  color: var(--accent-text); }
.alert-ok    { background: color-mix(in srgb,var(--ok) 10%,transparent);   border-color: color-mix(in srgb,var(--ok) 30%,transparent);   color: var(--ok-text); }

.lock-panel {
  display: flex; align-items: center; gap: 14px;
  padding: 14px;
  margin-bottom: 18px;
  background: color-mix(in srgb,var(--warn) 8%,transparent);
  border: 1px solid color-mix(in srgb,var(--warn) 28%,transparent);
  border-radius: var(--radius-sm);
}
.lock-ring {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: color-mix(in srgb,var(--warn) 16%,transparent);
  color: var(--warn);
}
.lock-ring svg { width: 19px; height: 19px; }
.lock-copy { display: flex; flex-direction: column; font-size: 13.5px; }
.lock-copy strong { color: var(--warn-text); font-weight: 600; }
.lock-copy span { color: var(--text-dim); }
.lock-copy b { color: var(--warn); font-variant-numeric: tabular-nums; }

.attempts-hint { margin: 0; text-align: center; font-size: 12.5px; color: var(--text-faint); }

.auth-foot {
  margin-top: 20px; padding-top: 16px;
  border-top: 1px solid var(--line-soft);
  font-size: 13px; color: var(--text-dim); text-align: center;
}

.auth-legal { margin: 18px 0 0; text-align: center; font-size: 12px; color: var(--text-faint); }

.status-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 10px; margin-bottom: 20px;
}
.status-grid > div {
  padding: 10px;
  background: var(--bg-input);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  display: flex; flex-direction: column; gap: 3px;
}
.status-key { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); }
.status-val { font-size: 13px; font-weight: 550; }
.status-val.good { color: var(--ok); }
.status-val.bad  { color: var(--bad); }

/* ==========================================================================
   App shell — fixed rail, fixed top bar, three-column workspace
   ========================================================================== */

.app { display: flex; height: 100vh; overflow: hidden; }

/* ---------------------------------------------------------------- left rail */
.rail {
  width: 250px; flex: none;
  display: flex; flex-direction: column;
  background: var(--bg-elev);
  border-right: 1px solid var(--line);
  /* Above .scrim (55) and above every mobile overlay and the status bar, so an
     open drawer is never dimmed or covered. See the note on .scrim. */
  z-index: 60;
}

.rail-head {
  display: flex; align-items: center; gap: 11px;
  padding: 15px 15px 13px;
  border-bottom: 1px solid var(--line-soft);
  flex: none;
}
.rail-logo {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center; border-radius: 10px;
  background: var(--accent);
  color: var(--accentInk);
}
.rail-logo svg { width: 18px; height: 18px; }
.rail-title { font-size: 15px; font-weight: 650; letter-spacing: -.01em; }
.rail-sub   { font-size: 11.5px; color: var(--text-faint); }

/* Only the engine and library lists scroll. */
.rail-scroll { flex: 1 1 auto; overflow-y: auto; min-height: 0; }

/* System meters stay put no matter how long the lists get. */
.rail-pinned { flex: none; border-top: 1px solid var(--line-soft); }

.rail-section {
  padding: 15px 14px 6px;
  font-size: 10.5px; font-weight: 650;
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-faint);
}

.tabs { display: flex; flex-direction: column; gap: 3px; padding: 0 9px; }

.tab {
  display: flex; align-items: center; gap: 11px;
  width: 100%; padding: 9px 10px;
  background: none; border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--text-dim); cursor: pointer; text-align: left;
  transition: background .14s, color .14s, border-color .14s;
}
.tab:hover { background: color-mix(in srgb,var(--text) 4%,transparent); color: var(--text); }
.tab.active { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 32%,transparent); color: var(--text); }

/* A FINISHED TAB READS AS FINISHED.
   Every tab is --text-dim by default, which is right for "not started" and
   wrong for everything else: a rail of uniformly dim labels reads as a rail of
   disabled buttons, whatever the dot beside it is doing. */
.tab.done { color: var(--text); }
.tab.done .tab-name { font-weight: 600; }
.tab.working { color: var(--text); }
.tab.working .tab-name { color: var(--warn); }
.tab-icon {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center; border-radius: 9px;
  background: var(--bg-elev-2); border: 1px solid var(--line); color: var(--text-dim);
}
.tab.active .tab-icon { background: color-mix(in srgb,var(--accent) 20%,transparent); border-color: color-mix(in srgb,var(--accent) 35%,transparent); color: var(--accent-text); }
.tab-icon svg { width: 15px; height: 15px; }
.tab-text { min-width: 0; display: flex; flex-direction: column; }
.tab-name { font-size: 13.5px; font-weight: 550; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tab-purpose { font-size: 11px; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tab-dot { width: 7px; height: 7px; border-radius: 50%; margin-left: auto; flex: none; background: var(--text-faint); }
.tab-dot.ready { background: var(--ok); box-shadow: 0 0 8px color-mix(in srgb,var(--ok) 60%,transparent); }
/* WORKING: GREEN AND GREY, ALTERNATING.
   Amber read as a warning — a rail of amber dots looks like a rail of
   problems, when all it means is "this one is being made right now". Blinking
   between the finished colour and the not-started colour says the true thing:
   it is on its way from one to the other. */
.tab-dot.downloading {
  background: var(--ok);
  animation: dotWorking 1.1s steps(1, end) infinite;
  box-shadow: 0 0 8px color-mix(in srgb,var(--ok) 50%,transparent);
}
@keyframes dotWorking {
  0%, 49%   { background: var(--ok);         box-shadow: 0 0 8px color-mix(in srgb,var(--ok) 50%,transparent); }
  50%, 100% { background: var(--text-faint); box-shadow: none; }
}
.tab-dot.error { background: var(--bad); }
.tab-badge {
  margin-left: auto; flex: none;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: grid; place-items: center;
  border-radius: 9px; background: var(--accent); color: var(--accentInk);
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .3; } }

/* ---- live system meters ---- */
.meters { padding: 4px 12px 12px; display: flex; flex-direction: column; gap: 10px; }
.meter-row { display: flex; flex-direction: column; gap: 5px; }
.meter-head { display: flex; align-items: baseline; gap: 8px; font-size: 11.5px; }
.meter-name { color: var(--text-dim); font-weight: 550; }
.meter-val  { margin-left: auto; color: var(--text); font-variant-numeric: tabular-nums; font-size: 11px; }
.meter-track { height: 5px; background: var(--surface3); border-radius: 3px; overflow: hidden; }
.meter-fill {
  display: block; height: 100%; width: 0;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width .45s ease;
}
.meter-fill.warm { background: linear-gradient(90deg, var(--warn), color-mix(in srgb,var(--warn) 55%,var(--bad))); }
.meter-fill.hot  { background: linear-gradient(90deg, var(--bad), color-mix(in srgb,var(--bad) 80%,var(--accent))); }
.meter-sub { font-size: 10.5px; color: var(--text-faint); }

/* ---- queue button ---- */
.queue-btn {
  display: flex; align-items: center; gap: 10px;
  width: 100%; margin: 0 0 10px;
  padding: 9px 11px;
  background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text-dim); cursor: pointer; text-align: left;
  transition: border-color .15s, color .15s, background .15s;
}
.queue-btn:hover { border-color: color-mix(in srgb,var(--accent) 45%,transparent); color: var(--text); background: var(--surface2); }
.queue-btn svg { width: 15px; height: 15px; flex: none; }
.queue-btn .qlabel { font-size: 12.5px; font-weight: 550; }
.queue-btn .qcount {
  margin-left: auto; padding: 1px 7px;
  border-radius: 9px; background: var(--line-strong);
  font-size: 11px; font-variant-numeric: tabular-nums;
}
.queue-btn.busy { border-color: color-mix(in srgb,var(--accent) 50%,transparent); }
.queue-btn.busy .qcount { background: var(--accent); color: var(--accentInk); }

.rail-foot { flex: none; padding: 10px 12px 12px; border-top: 1px solid var(--line-soft); }
.rail-user { display: flex; align-items: center; gap: 9px; }
.avatar {
  width: 28px; height: 28px; flex: none;
  display: grid; place-items: center; border-radius: 50%;
  background: linear-gradient(135deg, var(--line-strong), var(--surface3));
  border: 1px solid var(--line);
  font-size: 11.5px; font-weight: 650; color: var(--text-dim);
}
.rail-email { flex: 1; min-width: 0; font-size: 12px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.icon-btn {
  width: 28px; height: 28px; flex: none;
  display: grid; place-items: center;
  background: none; border: 1px solid transparent; border-radius: 8px;
  color: var(--text-faint); cursor: pointer;
}
.icon-btn:hover { background: color-mix(in srgb,var(--text) 5%,transparent); color: var(--text); border-color: var(--line); }
.icon-btn svg { width: 15px; height: 15px; }

/* ------------------------------------------------------------- main column */
.main { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.main-head {
  flex: none;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-elev);
  z-index: 30;
}
.hamburger { display: none; }
.head-title { display: flex; flex-direction: column; min-width: 0; }
.head-title h2 { margin: 0; font-size: 16px; font-weight: 620; letter-spacing: -.01em; }
.head-title p  { margin: 1px 0 0; font-size: 12.5px; color: var(--text-dim); }
.head-badges { margin-left: auto; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }

.badge {
  padding: 3.5px 9px; font-size: 11px; font-weight: 550;
  background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: 20px; color: var(--text-dim); white-space: nowrap;
}
.badge.ok   { background: color-mix(in srgb,var(--ok) 10%,transparent);  border-color: color-mix(in srgb,var(--ok) 30%,transparent);  color: var(--ok-text); }
.badge.warn { background: color-mix(in srgb,var(--warn) 10%,transparent);  border-color: color-mix(in srgb,var(--warn) 30%,transparent);  color: var(--warn-text); }
.badge.bad  { background: color-mix(in srgb,var(--bad) 10%,transparent); border-color: color-mix(in srgb,var(--bad) 30%,transparent); color: var(--bad-text); }
.badge.gpu  { background: color-mix(in srgb,var(--accent) 10%,transparent); border-color: color-mix(in srgb,var(--accent) 30%,transparent); color: var(--accent-text); }

/* ==========================================================================
   Workspace — column 1 (chats) | column 2 (conversation) | column 3 (params)
   ========================================================================== */

.workspace { flex: 1; display: flex; min-height: 0; }
.pane { display: none; flex: 1; min-height: 0; position: relative; }
.pane.active { display: flex; }

/* ---- shared column chrome ---- */
.col-head {
  flex: none;
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 11px; font-weight: 650;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-faint);
}
.col-head .col-actions { margin-left: auto; display: flex; gap: 5px; }
.col-fold {
  width: 24px; height: 24px;
  display: grid; place-items: center;
  background: none; border: 1px solid transparent; border-radius: 7px;
  color: var(--text-faint); cursor: pointer;
}
.col-fold:hover { color: var(--text); border-color: var(--line); background: color-mix(in srgb,var(--text) 4%,transparent); }
.col-fold svg { width: 14px; height: 14px; }

/* ---- column 1: chat history list ---- */
.col-chats,
.col-list {
  width: 252px; flex: none;
  display: flex; flex-direction: column; min-height: 0;
  border-right: 1px solid var(--line);
  background: var(--bg-elev);
  min-height: 0;
}

/* THE SHOWS RAIL HAD NO STYLE OF ITS OWN AT ALL.
   .col-list was in the markup and nowhere in this file, so the rail had no
   width and no flex rule — as a flex child it simply sized itself to whatever
   was inside it. That is why one long line of hint text could push it wide:
   the column was being measured by its own placeholder. It now shares the
   chrome of every other rail, so its width is a decision rather than an
   accident, and its contents scroll instead of stretching it. */
.col-list .col-scroll {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 8px;
  display: flex; flex-direction: column; gap: 4px;
}
.col-list .col-scroll > * { flex: none; }
/* min-height:0 is what makes this scroll at all.
   A flex child will not shrink below its content, so `flex:1; overflow-y:auto`
   on its own grew the column to fit every tree and pushed the bottom ones off
   the screen instead of scrolling them. */
.chats-list { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 4px; }

.new-chat-btn {
  flex: none;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin: 10px 10px 4px;
  padding: 9px 12px;
  background: var(--bg-input); border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
  color: var(--text-dim); font-size: 12.5px; font-weight: 550; cursor: pointer;
  transition: border-color .15s, color .15s;
}
.new-chat-btn:hover { border-color: var(--accent); color: var(--text); border-style: solid; }
.new-chat-btn svg { width: 14px; height: 14px; }

.chat-item {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 9px 10px;
  background: none; border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer; text-align: left; width: 100%;
  color: var(--text-dim);
  transition: background .13s, border-color .13s, color .13s;
}
.chat-item:hover { background: color-mix(in srgb,var(--text) 4%,transparent); color: var(--text); }
.chat-item.active { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 30%,transparent); color: var(--text); }
.chat-thumb {
  width: 34px; height: 34px; flex: none;
  border-radius: 7px; overflow: hidden;
  background: var(--surface3); border: 1px solid var(--line);
  display: grid; place-items: center;
  color: var(--text-faint);
}
.chat-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.chat-thumb svg { width: 14px; height: 14px; }
.chat-meta { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.chat-title {
  font-size: 12.5px; font-weight: 500; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.chat-sub { font-size: 10.5px; color: var(--text-faint); display: flex; gap: 6px; align-items: center; }
.chat-sub .live { color: var(--accent); font-weight: 600; }
.chats-empty { padding: 22px 14px; text-align: center; font-size: 12px; color: var(--text-faint); line-height: 1.6; }

/* ---- the "nothing here yet" note in a rail ----------------------------------
   This class was used in the markup and never written, so the note inherited
   the body font at full size with no padding, no wrapping rule and no width of
   its own — which is why it filled the shows rail and pushed its text past the
   edge. It is a hint, not content: small, quiet, contained, and dismissible. */
.empty-note {
  position: relative;
  margin: 8px;
  padding: 8px 22px 8px 10px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--text-faint);
  background: var(--bg-elev-2);
  border: 1px dashed var(--line);
  border-radius: 6px;

  /* Never wider than the rail, and never spilling out of it. A long word or a
     "…" with nowhere to break used to run past the edge. */
  max-width: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
  hyphens: auto;
}

.empty-note .empty-note-x {
  position: absolute;
  top: 3px; right: 4px;
  width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; line-height: 1;
  color: var(--text-faint);
  border-radius: 4px;
  cursor: pointer;
  opacity: .55;
}
.empty-note .empty-note-x:hover { opacity: 1; background: var(--line); color: var(--text-dim); }

/* ---- column 2: the conversation ---- */
.col-chat { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.chat { flex: 1; overflow-y: auto; padding: 24px 20px 8px; }
.chat-inner { max-width: 860px; margin: 0 auto; display: flex; flex-direction: column; gap: 22px; }

/* ---- column 3: parameters ---- */
.col-params {
  width: 340px; flex: none;
  display: flex; flex-direction: column;
  border-left: 1px solid var(--line);
  background: var(--bg-elev);
  min-height: 0;
}
.params-scroll { flex: 1; overflow-y: auto; padding: 4px 14px 16px; }
.params-foot {
  flex: none;
  display: flex; align-items: center; gap: 9px;
  padding: 10px 14px;
  border-top: 1px solid var(--line-soft);
}

/* ---- the commit bar at the end of a conversation ----------------------------
   The action that finishes a tab used to live only inside a reply's ··· menu.
   When a long answer lands you are at the bottom of the chat and that menu is
   several screens up, so the one thing you came to do was the hardest thing to
   find. This sits after the last finished reply, where the reading stops. */
.chat-commit {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 4px 0 8px 46px;            /* clears the avatar gutter */
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--bg-elev);
}
.chat-commit-btn { flex: none; }
.chat-commit-note {
  flex: 1; min-width: 0;
  font-size: 11px; line-height: 1.45; color: var(--text-faint);
  overflow-wrap: anywhere;
}

/* ---- folded state + reopen handles ----
   THE LEFT RAIL IS NOT ALWAYS .col-chats.
   Every tab that lists conversations uses .col-chats, but the Series Creator's
   rail of SHOWS is .col-list — so folding it added .fold-left to the pane and
   nothing matched, and the button looked broken. The rule names both rails,
   because "the left column" is what is being hidden, not one class of it. */
.pane.fold-left  .col-chats,
.pane.fold-left  .col-list   { display: none; }
.pane.fold-right .col-params { display: none; }

.reopen {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 22px; height: 62px;
  display: none; place-items: center;
  background: var(--bg-elev-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  cursor: pointer; z-index: 20;
  transition: background .15s, color .15s, border-color .15s;
}
.reopen:hover { background: var(--accent-soft); color: var(--text); border-color: color-mix(in srgb,var(--accent) 50%,transparent); }
.reopen svg { width: 14px; height: 14px; }
.reopen-left  { left: 0;  border-left: none;  border-radius: 0 9px 9px 0; }
.reopen-right { right: 0; border-right: none; border-radius: 9px 0 0 9px; }
.pane.fold-left  .reopen-left  { display: grid; }
.pane.fold-right .reopen-right { display: grid; }

/* ==========================================================================
   Messages
   ========================================================================== */

.empty { margin: auto; padding: 36px 18px; max-width: 620px; text-align: center; }
.empty-icon {
  width: 56px; height: 56px; margin: 0 auto 16px;
  display: grid; place-items: center; border-radius: 16px;
  background: linear-gradient(135deg, color-mix(in srgb,var(--accent) 18%,transparent), color-mix(in srgb,var(--accent2) 18%,transparent));
  border: 1px solid color-mix(in srgb,var(--accent) 26%,transparent); color: var(--accent-text);
}
.empty-icon svg { width: 26px; height: 26px; }
.empty h3 { margin: 0 0 8px; font-size: 19px; font-weight: 620; letter-spacing: -.015em; }
.empty p  { margin: 0 0 20px; color: var(--text-dim); font-size: 13.5px; }
.suggestions { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px; text-align: left; }
.suggestion {
  padding: 11px 13px;
  background: var(--bg-elev); border: 1px solid var(--line);
  border-radius: var(--radius-sm); cursor: pointer;
  font-size: 12.5px; color: var(--text-dim);
  transition: border-color .15s, background .15s, color .15s;
}
.suggestion:hover { border-color: color-mix(in srgb,var(--accent) 40%,transparent); background: var(--bg-elev-2); color: var(--text); }
.suggestion b { display: block; color: var(--text); font-weight: 550; margin-bottom: 3px; }

.msg { display: flex; gap: 13px; animation: rise .22s ease-out; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.msg-avatar {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center; border-radius: 9px;
  font-size: 11px; font-weight: 650;
}
.msg.user .msg-avatar   { background: var(--line); color: var(--text-dim); border: 1px solid var(--line); }
.msg.system .msg-avatar { background: var(--accent); color: var(--accentInk); }
.msg-avatar svg { width: 15px; height: 15px; }
.msg-body { flex: 1; min-width: 0; }
.msg-role { font-size: 12px; font-weight: 600; color: var(--text-dim); margin-bottom: 5px; }
.msg-text { white-space: pre-wrap; word-break: break-word; font-size: 14.5px; }

.msg-files { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.file-chip {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px 6px 6px;
  background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: 10px; font-size: 12px; color: var(--text-dim); max-width: 260px;
}
.file-chip img { width: 34px; height: 34px; object-fit: cover; border-radius: 7px; flex: none; }
.file-chip .fi {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center; border-radius: 7px;
  background: var(--surface3); color: var(--text-dim);
}
.file-chip .fi svg { width: 16px; height: 16px; }
.file-chip .fname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.file-chip .fsize { font-size: 11px; color: var(--text-faint); }

/* ---- job card ---- */
.job { margin-top: 4px; background: var(--bg-elev); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.job-head { display: flex; align-items: center; gap: 10px; padding: 10px 13px; border-bottom: 1px solid var(--line-soft); font-size: 12.5px; }
.job-state { display: flex; align-items: center; gap: 7px; font-weight: 550; }
.job-state .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-faint); }
.job-state.running .dot { background: var(--accent); animation: pulse 1.2s ease-in-out infinite; }
.job-state.done    .dot { background: var(--ok); }
.job-state.error   .dot { background: var(--bad); }
.job-meta { margin-left: auto; color: var(--text-faint); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.job-bar { height: 3px; background: var(--surface3); }
.job-bar i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width .4s; }
.job-body { padding: 13px; }
.job-stage { font-size: 12.5px; color: var(--text-dim); display: flex; align-items: center; gap: 8px; }
.spinner {
  width: 13px; height: 13px; flex: none;
  border: 2px solid color-mix(in srgb,var(--text) 14%,transparent); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.job-error {
  font-family: var(--mono); font-size: 12px; color: var(--bad-text);
  background: color-mix(in srgb,var(--bad) 7%,transparent); border: 1px solid color-mix(in srgb,var(--bad) 22%,transparent);
  border-radius: var(--radius-sm); padding: 10px 12px;
  white-space: pre-wrap; word-break: break-word; max-height: 220px; overflow: auto;
}
.results { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; }
.result { position: relative; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; background: var(--code-bg); }
.result img, .result video { display: block; width: 100%; height: auto; }
.result-actions { position: absolute; top: 8px; right: 8px; display: flex; gap: 6px; opacity: 0; transition: opacity .15s; }
.result:hover .result-actions { opacity: 1; }
.result-actions a {
  width: 28px; height: 28px; display: grid; place-items: center;
  background: rgba(10,12,15,.82); border: 1px solid rgba(255,255,255,.14);
  border-radius: 8px; color: #f2f2f2; backdrop-filter: blur(6px);
}
.result-actions a:hover { background: rgba(10,12,15,.95); border-color: var(--accent); }
.result-actions svg { width: 14px; height: 14px; }
.result-cap {
  padding: 7px 10px; font-size: 11px; color: var(--text-faint);
  border-top: 1px solid var(--line-soft); display: flex; justify-content: space-between; gap: 8px;
}
.params-dump { margin-top: 12px; border-top: 1px solid var(--line-soft); padding-top: 10px; }
.params-dump summary { cursor: pointer; font-size: 12px; color: var(--text-faint); list-style: none; user-select: none; }
.params-dump summary::-webkit-details-marker { display: none; }
.params-dump summary:hover { color: var(--text-dim); }
.params-dump pre {
  margin: 9px 0 0; padding: 11px;
  background: var(--code-bg); border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  font-family: var(--mono); font-size: 11.5px; color: var(--text-dim); overflow-x: auto;
}

/* ==========================================================================
   Composer — fixed height box, edge-to-edge buttons, black field
   ========================================================================== */

.composer-wrap { flex: none; padding: 8px 20px 16px; background: var(--bg); }
.composer-inner { max-width: 860px; margin: 0 auto; }

.dropzone {
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--bg-input);
  transition: border-color .15s, box-shadow .15s;
  overflow: hidden;
}
.dropzone:focus-within { border-color: color-mix(in srgb,var(--accent) 55%,transparent); box-shadow: 0 0 0 3px var(--accent-soft); }
.dropzone.dragover { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.attach-strip { display: none; flex-wrap: wrap; gap: 8px; padding: 10px 10px 0; }
.attach-strip.on { display: flex; }
.attachment {
  position: relative; display: flex; align-items: center; gap: 8px;
  padding: 6px 26px 6px 6px;
  background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: 10px; font-size: 12px; max-width: 230px;
}
.attachment img { width: 32px; height: 32px; object-fit: cover; border-radius: 6px; flex: none; }
.attachment .fi { width: 32px; height: 32px; flex: none; display: grid; place-items: center; border-radius: 6px; background: var(--surface3); color: var(--text-dim); }
.attachment .fi svg { width: 15px; height: 15px; }
.attachment .meta { min-width: 0; display: flex; flex-direction: column; }
.attachment .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attachment .sz { font-size: 10.5px; color: var(--text-faint); }
.attachment .rm {
  position: absolute; top: 4px; right: 4px;
  width: 17px; height: 17px; display: grid; place-items: center;
  background: rgba(0,0,0,.5); border: none; border-radius: 50%;
  color: #e6e6e6; cursor: pointer; font-size: 12px; line-height: 1;
}
.attachment .rm:hover { background: var(--bad); color: #fff; }
.attachment.uploading { opacity: .6; }
.attachment .prog { position: absolute; left: 0; bottom: 0; height: 2px; background: var(--accent); transition: width .2s; }

/* The row keeps + hard against the left edge and send hard against the right. */
.composer-row { display: flex; align-items: flex-end; gap: 8px; padding: 8px; }

.prompt-input {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  height: 44px;                 /* fixed starting height */
  max-height: 200px;
  padding: 11px 12px;
  background: var(--bg);          /* black field, not the browser default */
  color: var(--text);
  border: 1px solid var(--line-soft);
  border-radius: 11px;
  outline: none;
  resize: none;                 /* no drag handle */
  overflow-y: auto;
  font-family: inherit;
  font-size: 14.5px;
  line-height: 1.45;
}
.prompt-input:focus { border-color: color-mix(in srgb,var(--accent) 45%,transparent); }
.prompt-input::placeholder { color: var(--text-faint); }

.composer-btn {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: 11px; color: var(--text-dim); cursor: pointer;
  transition: background .14s, color .14s, border-color .14s;
}
.composer-btn:hover:not(:disabled) { background: var(--surface3); color: var(--text); border-color: var(--line-strong); }
.composer-btn:disabled { opacity: .4; cursor: not-allowed; }
.composer-btn svg { width: 17px; height: 17px; }

.send-btn {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  background: var(--accent);
  border: none; border-radius: 999px; color: var(--accentInk); cursor: pointer;
  transition: filter .14s, opacity .14s;
}
.send-btn:hover:not(:disabled) { filter: brightness(1.1); }
.send-btn:disabled { opacity: .35; cursor: not-allowed; }
.send-btn svg { width: 17px; height: 17px; }

/* STOP. The same button, while the model is thinking.
   Deliberately NOT the accent gradient: it is a different action with a
   different consequence, and the two swap in place — if they looked alike the
   operator would press stop meaning send. */
.send-btn.is-stop {
  background: var(--bad, var(--bad));
  animation: send-stop-pulse 1.6s ease-in-out infinite;
}
.send-btn.is-stop:hover { filter: brightness(1.12); animation: none; }

@keyframes send-stop-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb,var(--bad) 45%,transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb,var(--bad) 0%,transparent); }
}

/* Somebody who has turned motion down should still get the colour and the
   square, just not the pulse. */
@media (prefers-reduced-motion: reduce) {
  .send-btn.is-stop { animation: none; }
}

.composer-foot { display: flex; align-items: center; gap: 10px; margin-top: 8px; font-size: 11.5px; color: var(--text-faint); }
.composer-foot .hint { margin-left: auto; }
kbd {
  padding: 1px 5px; background: var(--bg-elev-2); border: 1px solid var(--line);
  border-bottom-width: 2px; border-radius: 5px;
  font-family: var(--mono); font-size: 10.5px; color: var(--text-dim);
}

/* ==========================================================================
   Parameter fields (column 3)
   ========================================================================== */

.group { padding: 14px 0; border-bottom: 1px dashed var(--line-soft); }
.group:last-child { border-bottom: none; }
.group-title {
  font-size: 10.5px; font-weight: 650; text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-faint); margin-bottom: 12px;
}
.group-fields { display: flex; flex-direction: column; gap: 14px; }

.pfield { display: flex; flex-direction: column; gap: 6px; }
.pfield-head { display: flex; align-items: baseline; gap: 8px; }
.pfield-label { font-size: 12.5px; font-weight: 500; color: var(--text-dim); }
.pfield-value { margin-left: auto; font-family: var(--mono); font-size: 12px; color: var(--accent); font-variant-numeric: tabular-nums; }
.pfield-help { font-size: 11px; color: var(--text-faint); line-height: 1.45; }

.pfield select,
.pfield input[type="number"],
.pfield input[type="text"],
.pfield textarea {
  width: 100%; padding: 8px 10px;
  background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 9px; outline: none; font-size: 13px;
  transition: border-color .15s, box-shadow .15s;
}
.pfield select:focus, .pfield input:focus, .pfield textarea:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.pfield textarea { resize: vertical; min-height: 54px; line-height: 1.5; }
.pfield select {
  appearance: none; cursor: pointer; padding-right: 30px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2397a2b1' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; background-size: 15px;
}

input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 4px; margin: 7px 0;
  background: var(--surface3); border-radius: 3px; outline: none; cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--accent); border: 2px solid var(--bg-elev);
  box-shadow: 0 0 0 1px var(--accent); cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--accent); border: 2px solid var(--bg-elev); cursor: pointer;
}

.switch { display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; }
.switch input { display: none; }
.switch .track { width: 36px; height: 20px; flex: none; background: var(--line-strong); border-radius: 20px; position: relative; transition: background .18s; }
.switch .track::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--dim); transition: transform .18s, background .18s;
}
.switch input:checked + .track { background: color-mix(in srgb,var(--accent) 35%,transparent); }
.switch input:checked + .track::after { transform: translateX(16px); background: var(--accent); }

.seed-row { display: flex; gap: 7px; }
.seed-row input { flex: 1; }
.seed-btn {
  width: 34px; flex: none; display: grid; place-items: center;
  background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 9px; color: var(--text-dim); cursor: pointer;
}
.seed-btn:hover { color: var(--text); border-color: var(--line-strong); }
.seed-btn svg { width: 14px; height: 14px; }

.btn-ghost {
  padding: 7px 13px;
  background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 9px; color: var(--text-dim);
  font-size: 12.5px; cursor: pointer;
}
.btn-ghost:hover { color: var(--text); border-color: var(--line-strong); }
.params-note { margin-left: auto; font-size: 11px; color: var(--text-faint); text-align: right; }

/* ==========================================================================
   Queue modal
   ========================================================================== */

.modal-back {
  position: fixed; inset: 0; z-index: 100;
  background: var(--overlay);
  backdrop-filter: blur(4px);
  display: none; place-items: center;
  padding: 24px;
}
.modal-back.open { display: grid; }

.modal {
  width: min(760px, 100%); max-height: min(78vh, 760px);
  display: flex; flex-direction: column;
  background: var(--bg-elev); border: 1px solid var(--line);
  border-radius: 18px; box-shadow: var(--shadow);
  animation: rise .18s ease-out;
}
.modal-head {
  flex: none; display: flex; align-items: center; gap: 11px;
  padding: 16px 18px; border-bottom: 1px solid var(--line-soft);
}
.modal-head h3 { margin: 0; font-size: 16px; font-weight: 620; }
.modal-head .sub { font-size: 12px; color: var(--text-faint); }
.modal-close {
  margin-left: auto; width: 30px; height: 30px;
  display: grid; place-items: center;
  background: none; border: 1px solid var(--line); border-radius: 9px;
  color: var(--text-dim); cursor: pointer; font-size: 16px; line-height: 1;
}
.modal-close:hover { color: var(--text); border-color: var(--line-strong); }
.modal-body { flex: 1; overflow-y: auto; padding: 14px 18px 18px; }

.qsection { margin-bottom: 20px; }
.qsection:last-child { margin-bottom: 0; }
.qsection h4 {
  margin: 0 0 10px; font-size: 10.5px; font-weight: 650;
  text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint);
}
.qrow {
  display: flex; gap: 12px; align-items: center;
  padding: 11px 13px; margin-bottom: 8px;
  background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.qrow.running { border-color: color-mix(in srgb,var(--accent) 40%,transparent); background: color-mix(in srgb,var(--accent) 7%,transparent); }
.qrow.error   { border-color: color-mix(in srgb,var(--bad) 30%,transparent); }
.qpos {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center; border-radius: 9px;
  background: var(--line-strong); color: var(--text-dim);
  font-size: 12px; font-weight: 650; font-variant-numeric: tabular-nums;
}
.qrow.running .qpos { background: var(--accent); color: var(--accentInk); }
.qmeta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.qengine { font-size: 12.5px; font-weight: 600; }
.qprompt { font-size: 11.5px; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qstate { font-size: 11px; color: var(--text-dim); font-variant-numeric: tabular-nums; text-align: right; flex: none; }
.qbar { height: 3px; background: var(--surface3); border-radius: 3px; margin-top: 5px; overflow: hidden; }
.qbar i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width .4s; }
.qthumb { width: 34px; height: 34px; flex: none; border-radius: 7px; overflow: hidden; background: var(--surface3); border: 1px solid var(--line); }
.qthumb img, .qthumb video { width: 100%; height: 100%; object-fit: cover; display: block; }
.qempty { padding: 14px; text-align: center; font-size: 12.5px; color: var(--text-faint); }
.qcancel {
  flex: none; padding: 5px 10px;
  background: none; border: 1px solid var(--line); border-radius: 8px;
  color: var(--text-faint); font-size: 11.5px; cursor: pointer;
}
.qcancel:hover { color: var(--bad-text); border-color: color-mix(in srgb,var(--bad) 40%,transparent); }

/* ==========================================================================
   Toasts + responsive
   ========================================================================== */

.toast-host {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 8px; z-index: 120; pointer-events: none;
}
.toast {
  padding: 10px 15px; background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); box-shadow: var(--shadow); font-size: 13px;
  animation: rise .2s ease-out;
}
.toast.err { border-color: color-mix(in srgb,var(--bad) 40%,transparent); color: var(--bad-text); }
.toast.ok  { border-color: color-mix(in srgb,var(--ok) 40%,transparent);  color: var(--ok-text); }

/* THE DIM LAYER SITS UNDER THE DRAWER, AT EVERY WIDTH.
   These two numbers decide whether an opened menu is readable or looks
   switched off, so they are stated here, together, in the base rules — not in
   a breakpoint. They were 45 (scrim) over 40 (rail), corrected only inside a
   max-width query: at any width that query did not cover, the menu opened
   UNDERNEATH its own dimming and every item read as greyed out. On a desktop
   neither element is positioned, so a z-index there is inert. */
.scrim {
  position: fixed; inset: 0; z-index: 55;
  background: var(--overlay); display: none;
}
.scrim.on { display: block; }

@media (max-width: 1180px) {
  .col-params { width: 300px; }
  .col-chats  { width: 220px; }
}

@media (max-width: 900px), (max-height: 500px) {
  .hamburger { display: grid; }

  .rail {
    position: fixed; inset: 0 auto 0 0;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: 0 0 40px var(--shadow-color);
  }
  .rail.open { transform: none; }

  .head-badges { display: none; }
  .main-head { padding: 10px 14px; }

  /* The side columns become overlays so column 2 always owns the width. */
  .col-chats, .col-params {
    position: absolute; top: 0; bottom: 0; z-index: 35;
    width: min(300px, 82vw);
    box-shadow: 0 0 40px var(--shadow-color);
  }
  .col-chats  { left: 0; }
  .col-params { right: 0; }

  .chat { padding: 18px 12px 6px; }
  .composer-wrap { padding: 6px 12px 12px; }
  .results { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Compact rail — everything visible without scrolling
   ========================================================================== */

.rail { width: 214px; }
.rail-head { padding: 11px 12px 10px; gap: 9px; }
.rail-logo { width: 28px; height: 28px; border-radius: 8px; }
.rail-logo svg { width: 15px; height: 15px; }
.rail-title { font-size: 13.5px; }
.rail-sub { font-size: 10.5px; }

.rail-section { padding: 10px 12px 4px; font-size: 9.5px; letter-spacing: .09em; }
.tabs { padding: 0 7px; gap: 2px; }
.tab { padding: 6px 8px; gap: 8px; border-radius: 9px; }
.tab-icon { width: 24px; height: 24px; border-radius: 7px; }
.tab-icon svg { width: 13px; height: 13px; }
.tab-name { font-size: 12px; }
.tab-purpose { font-size: 10px; }
.tab-dot { width: 6px; height: 6px; }
.tab-badge { min-width: 16px; height: 16px; font-size: 9.5px; }

.meters { padding: 2px 12px 8px; gap: 7px; }
.meter-head { font-size: 10.5px; }
.meter-val { font-size: 10px; }
.meter-track { height: 4px; }
.meter-sub { font-size: 9.5px; }

.queue-btn { padding: 7px 10px; gap: 8px; margin-bottom: 8px; }
.queue-btn .qlabel { font-size: 12px; }
.queue-btn .qcount { font-size: 10.5px; padding: 1px 6px; }
.rail-foot { padding: 8px 10px 10px; }
.avatar { width: 24px; height: 24px; font-size: 10.5px; }
.rail-email { font-size: 11px; }
.icon-btn { width: 26px; height: 26px; }
.icon-btn svg { width: 14px; height: 14px; }

/* ==========================================================================
   Library views
   ========================================================================== */

.view { display: none; flex: 1; flex-direction: column; min-width: 0; min-height: 0; }
.view.active { display: flex; }

.view-bar {
  flex: none;
  display: flex; align-items: center; gap: 10px;
  padding: 11px 18px;
  border-bottom: 1px solid var(--line-soft);
}
.view-bar .count { font-size: 12px; color: var(--text-faint); }
.view-bar .spacer { margin-left: auto; }
.view-bar .count { flex: 1 1 auto; min-width: 0; }

.search {
  width: 240px; padding: 7px 11px;
  background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 9px; outline: none; font-size: 12.5px;
}
.search:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.view-scroll { flex: 1; overflow-y: auto; padding: 16px 18px 26px; }

.gallery {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.gal-item {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg-elev); overflow: hidden;
  display: flex; flex-direction: column;
  transition: border-color .15s, transform .12s;
}
.gal-item:hover { border-color: color-mix(in srgb,var(--accent) 45%,transparent); transform: translateY(-2px); }
.gal-media { position: relative; background: var(--code-bg); aspect-ratio: 1 / 1; overflow: hidden; }
.gal-media img, .gal-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
.gal-badge {
  position: absolute; top: 8px; left: 8px;
  padding: 2px 8px; border-radius: 20px;
  background: rgba(10,12,15,.8); border: 1px solid rgba(255,255,255,.14);
  font-size: 10.5px; color: #d9d9d9; backdrop-filter: blur(6px);
}
.gal-actions { position: absolute; top: 8px; right: 8px; display: flex; gap: 6px; opacity: 0; transition: opacity .15s; }
.gal-item:hover .gal-actions { opacity: 1; }
.gal-actions a, .gal-actions button {
  width: 26px; height: 26px; display: grid; place-items: center;
  background: rgba(10,12,15,.85); border: 1px solid rgba(255,255,255,.14);
  border-radius: 8px; color: #f2f2f2; cursor: pointer; backdrop-filter: blur(6px);
}
.gal-actions a:hover, .gal-actions button:hover { border-color: var(--accent); }
.gal-actions svg { width: 13px; height: 13px; }
.gal-info { padding: 9px 11px; display: flex; flex-direction: column; gap: 4px; }
.gal-prompt {
  font-size: 12px; color: var(--text-dim); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.gal-meta { font-size: 10.5px; color: var(--text-faint); display: flex; justify-content: space-between; gap: 8px; }

.view-empty { margin: 60px auto; text-align: center; max-width: 420px; color: var(--text-faint); }
.view-empty h3 { margin: 0 0 8px; font-size: 17px; color: var(--text); font-weight: 600; }
.view-empty p { margin: 0; font-size: 13px; line-height: 1.6; }

/* ==========================================================================
   API keys view
   ========================================================================== */

.keys-wrap { max-width: 980px; margin: 0 auto; }
.key-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg-elev); padding: 15px 16px; margin-bottom: 12px;
}
.key-top { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.key-name { font-size: 14px; font-weight: 600; }
.key-prefix {
  font-family: var(--mono); font-size: 12px; color: var(--text-dim);
  background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 7px; padding: 2px 8px;
}
.key-stats { margin-left: auto; font-size: 11.5px; color: var(--text-faint); text-align: right; }
.key-engines { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.key-engine {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 10px; border-radius: 9px;
  background: var(--bg-input); border: 1px solid var(--line);
  font-size: 12px; color: var(--text-dim); cursor: pointer; user-select: none;
}
.key-engine input { accent-color: var(--accent); width: 14px; height: 14px; cursor: pointer; }
.key-engine.on { border-color: color-mix(in srgb,var(--accent) 50%,transparent); color: var(--text); background: var(--accent-soft); }
.key-engine .alias { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); }
.key-actions { display: flex; align-items: center; gap: 8px; margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.btn-danger {
  padding: 7px 13px; background: color-mix(in srgb,var(--bad) 8%,transparent);
  border: 1px solid color-mix(in srgb,var(--bad) 30%,transparent); border-radius: 9px;
  color: var(--bad-text); font-size: 12.5px; cursor: pointer;
}
.btn-danger:hover { background: color-mix(in srgb,var(--bad) 16%,transparent); }

.newkey {
  border: 1px dashed var(--line); border-radius: var(--radius);
  background: var(--bg-elev); padding: 15px 16px; margin-bottom: 16px;
}
.newkey-row { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.newkey-row .field-block { display: flex; flex-direction: column; gap: 6px; }
.newkey-row label { font-size: 11.5px; color: var(--text-dim); font-weight: 550; }
.newkey-row input[type="text"], .newkey-row input[type="number"] {
  padding: 8px 11px; background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 9px; outline: none; font-size: 13px;
}
.newkey-row input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.key-reveal {
  margin-top: 13px; padding: 13px;
  background: color-mix(in srgb,var(--ok) 7%,transparent); border: 1px solid color-mix(in srgb,var(--ok) 32%,transparent);
  border-radius: var(--radius-sm);
}
.key-reveal .label { font-size: 11.5px; color: var(--ok-text); margin-bottom: 7px; }
.key-reveal .value {
  font-family: var(--mono); font-size: 12.5px; word-break: break-all;
  background: var(--code-bg); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px; color: var(--text);
}
.key-reveal .warn { margin-top: 8px; font-size: 11.5px; color: var(--text-faint); }

.docs-link {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; flex: none;
  padding: 7px 12px; border-radius: 9px;
  background: var(--bg-input); border: 1px solid var(--line);
  color: var(--text-dim); font-size: 12.5px; text-decoration: none;
}
.docs-link:hover { color: var(--text); border-color: var(--accent); text-decoration: none; }

/* ==========================================================================
   Attachment picker
   ========================================================================== */

.picker-tabs { flex: none; display: flex; gap: 6px; padding: 0 18px 12px; border-bottom: 1px solid var(--line-soft); }
.picker-tab {
  padding: 7px 13px; border-radius: 9px;
  background: none; border: 1px solid var(--line);
  color: var(--text-dim); font-size: 12.5px; cursor: pointer;
}
.picker-tab:hover { color: var(--text); }
.picker-tab.active { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 40%,transparent); color: var(--text); }

.picker-drop {
  border: 1px dashed var(--line); border-radius: var(--radius);
  padding: 34px 20px; text-align: center; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.picker-drop:hover, .picker-drop.dragover { border-color: var(--accent); background: var(--accent-soft); }
.picker-drop svg { width: 26px; height: 26px; color: var(--text-dim); margin-bottom: 10px; }
.picker-drop h4 { margin: 0 0 5px; font-size: 14px; font-weight: 600; }
.picker-drop p { margin: 0; font-size: 12px; color: var(--text-faint); }

.picker-grid { display: grid; gap: 11px; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.picker-item {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  overflow: hidden; cursor: pointer; background: var(--code-bg);
  transition: border-color .14s, transform .12s;
}
.picker-item:hover { border-color: var(--accent); transform: translateY(-2px); }
.picker-item .pm { aspect-ratio: 1 / 1; background: var(--code-bg); }
.picker-item .pm img, .picker-item .pm video { width: 100%; height: 100%; object-fit: cover; display: block; }
.picker-item .pi { padding: 7px 9px; font-size: 10.5px; color: var(--text-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ==========================================================================
   Tighter rail — fit engines, library, meters and queue without scrolling
   ========================================================================== */

.rail { width: 196px; }
.rail-head { padding: 9px 10px 8px; gap: 8px; }
.rail-logo { width: 25px; height: 25px; border-radius: 7px; }
.rail-logo svg { width: 13px; height: 13px; }
.rail-title { font-size: 12.5px; }
.rail-sub { font-size: 9.5px; }

.rail-section { padding: 8px 10px 3px; font-size: 9px; letter-spacing: .1em; }
.tabs { padding: 0 6px; gap: 1px; }
.tab { padding: 5px 7px; gap: 7px; border-radius: 8px; }
.tab-icon { width: 21px; height: 21px; border-radius: 6px; }
.tab-icon svg { width: 11.5px; height: 11.5px; }
.tab-name { font-size: 11.5px; line-height: 1.25; }
.tab-purpose { font-size: 9.5px; line-height: 1.25; }
.tab-dot { width: 5.5px; height: 5.5px; }
.tab-badge { min-width: 15px; height: 15px; font-size: 9px; padding: 0 4px; }

.meters { padding: 2px 10px 7px; gap: 6px; }
.meter-head { font-size: 10px; }
.meter-val { font-size: 9.5px; }
.meter-track { height: 3.5px; }
.meter-sub { font-size: 9px; }
.meter-name { display: flex; align-items: center; gap: 5px; }

/* DUMP sits on the GPU row itself */
.dump-btn {
  padding: 1px 6px; border-radius: 5px;
  background: var(--bg-input); border: 1px solid var(--line);
  color: var(--text-faint); font-size: 8.5px; font-weight: 700;
  letter-spacing: .06em; cursor: pointer; line-height: 1.5;
}
.dump-btn:hover { color: var(--bad-text); border-color: color-mix(in srgb,var(--bad) 45%,transparent); background: color-mix(in srgb,var(--bad) 8%,transparent); }
.dump-btn:disabled { opacity: .5; cursor: progress; }

.queue-btn { padding: 6px 9px; gap: 7px; margin-bottom: 6px; }
.queue-btn .qlabel { font-size: 11.5px; }
.queue-btn .qcount { font-size: 10px; }
.queue-btn svg { width: 13px; height: 13px; }
.rail-foot { padding: 7px 9px 9px; }
.avatar { width: 22px; height: 22px; font-size: 9.5px; }
.rail-email { font-size: 10.5px; }
.icon-btn { width: 24px; height: 24px; }
.icon-btn svg { width: 13px; height: 13px; }

/* ==========================================================================
   Derived readout under a parameter (e.g. the length a frame count produces)
   ========================================================================== */

.pfield-derived {
  font-size: 11.5px; color: var(--accent-text);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb,var(--accent) 28%,transparent);
  border-radius: 8px; padding: 6px 9px;
}
.pfield-derived b { color: var(--text); font-variant-numeric: tabular-nums; }
.pfield-derived.warn { color: var(--warn-text); background: color-mix(in srgb,var(--warn) 10%,transparent); border-color: color-mix(in srgb,var(--warn) 30%,transparent); }
.pfield-derived.bad  { color: var(--bad-text); background: color-mix(in srgb,var(--bad) 10%,transparent); border-color: color-mix(in srgb,var(--bad) 32%,transparent); }

/* ==========================================================================
   Library selection + deletion
   ========================================================================== */

.gal-item { position: relative; }
.gal-check {
  position: absolute; top: 8px; left: 8px; z-index: 3;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  background: rgba(10,12,15,.82); border: 1px solid rgba(255,255,255,.2);
  border-radius: 6px; cursor: pointer;
  opacity: 0; transition: opacity .14s, background .14s, border-color .14s;
  backdrop-filter: blur(6px);
}
.gal-item:hover .gal-check,
.gal-item.selected .gal-check,
.gallery.selecting .gal-check { opacity: 1; }
.gal-check svg { width: 13px; height: 13px; color: transparent; }
.gal-item.selected .gal-check { background: var(--accent); border-color: var(--accent); }
.gal-item.selected .gal-check svg { color: var(--accentInk); }
.gal-item.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.gal-item.selected .gal-badge { opacity: 0; }

.select-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 13px; margin-bottom: 14px;
  background: var(--accent-soft); border: 1px solid color-mix(in srgb,var(--accent) 35%,transparent);
  border-radius: var(--radius-sm);
  position: sticky; top: 0; z-index: 5;
  backdrop-filter: blur(10px);
}
.select-bar .sel-count { font-size: 12.5px; font-weight: 600; }
.select-bar .spacer { margin-left: auto; }

/* ==========================================================================
   Parameter panel at rail scale — same type sizes as the sidebar
   ========================================================================== */

.col-params { width: 300px; }
.col-params .col-head { padding: 8px 10px; font-size: 9px; letter-spacing: .1em; }
.col-params .col-fold { width: 21px; height: 21px; border-radius: 6px; }
.col-params .col-fold svg { width: 12px; height: 12px; }

.params-scroll { padding: 2px 10px 12px; }

.group { padding: 10px 0; }
.group-title { font-size: 9px; letter-spacing: .1em; margin-bottom: 8px; }
.group-fields { gap: 10px; }

.pfield { gap: 4px; }
.pfield-label { font-size: 11px; line-height: 1.3; }
.pfield-value { font-size: 10.5px; }
.pfield-help  { font-size: 9.5px; line-height: 1.4; }

.pfield select,
.pfield input[type="number"],
.pfield input[type="text"],
.pfield textarea {
  padding: 6px 8px;
  font-size: 11.5px;
  border-radius: 7px;
}
.pfield select { padding-right: 24px; background-size: 13px; background-position: right 7px center; }
.pfield textarea { min-height: 44px; line-height: 1.45; }

input[type="range"] { height: 3px; margin: 5px 0; }
input[type="range"]::-webkit-slider-thumb { width: 12px; height: 12px; border-width: 2px; }
input[type="range"]::-moz-range-thumb { width: 11px; height: 11px; border-width: 2px; }

.switch { gap: 8px; }
.switch .track { width: 30px; height: 17px; }
.switch .track::after { width: 13px; height: 13px; }
.switch input:checked + .track::after { transform: translateX(13px); }

.seed-row { gap: 5px; }
.seed-btn { width: 28px; border-radius: 7px; }
.seed-btn svg { width: 12px; height: 12px; }

.pfield-derived { font-size: 10.5px; padding: 5px 7px; border-radius: 7px; line-height: 1.45; }

.params-foot { padding: 8px 10px; gap: 7px; }
.params-foot .btn-ghost { padding: 5px 10px; font-size: 11px; border-radius: 7px; }
.params-note { font-size: 9.5px; }

@media (max-width: 1180px) {
  .col-params { width: 268px; }
}

/* ==========================================================================
   Per-chat menu in the history list
   ========================================================================== */

.chat-item { padding-right: 26px; }
.chat-menu-btn {
  position: absolute; top: 6px; right: 4px;
  width: 20px; height: 20px;
  display: grid; place-items: center;
  background: none; border: none; border-radius: 5px;
  color: var(--text-faint); cursor: pointer;
  opacity: 0; transition: opacity .13s, background .13s, color .13s;
  font-size: 14px; line-height: 1;
}
.chat-item { position: relative; }
.chat-item:hover .chat-menu-btn,
.chat-item.menu-open .chat-menu-btn { opacity: 1; }
.chat-menu-btn:hover { background: color-mix(in srgb,var(--text) 8%,transparent); color: var(--text); }

.chat-menu {
  position: fixed; z-index: 80;
  min-width: 168px; padding: 5px;
  background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); box-shadow: var(--shadow);
  animation: rise .13s ease-out;
}
.chat-menu button {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 7px 9px;
  background: none; border: none; border-radius: 7px;
  color: var(--text-dim); font-size: 12px; text-align: left; cursor: pointer;
}
.chat-menu button:hover { background: color-mix(in srgb,var(--text) 6%,transparent); color: var(--text); }
.chat-menu button.danger:hover { background: color-mix(in srgb,var(--bad) 12%,transparent); color: var(--bad-text); }
.chat-menu svg { width: 13px; height: 13px; flex: none; }

/* ==========================================================================
   MOVIE MAKER — the orchestrator
   ==========================================================================

   Everything below is added on top of the base design above. It reuses the
   same tokens: change a colour in :root and this changes with it.

   Two structural changes to the shell:

     1. .app is now a COLUMN — .app-body (rail + main) above, .statusbar
        pinned below. The bar has to span the whole window, not just the
        workspace, so it cannot live inside .main.

     2. Every tab is one .pane with the same three columns, so a tab is only
        ever a different set of children — never a different layout.
   ========================================================================== */

.app { flex-direction: column; }
.app-body { flex: 1 1 auto; display: flex; min-height: 0; }

/* ==========================================================================
   The live status bar
   ==========================================================================

   Folded is the resting state and it is one row high: a lamp, a word, and
   whatever is happening right now. Unfolded it becomes a 320px pane with the
   running jobs above the log, and it takes its height from the viewport so a
   long log scrolls inside it rather than pushing the console off the screen.
   ========================================================================== */

.statusbar {
  flex: none;
  border-top: 1px solid var(--line);
  background: linear-gradient(180deg, color-mix(in srgb,var(--code-bg) 25%,transparent), var(--bg-elev));
  backdrop-filter: blur(6px);
  z-index: 40;
}

.status-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  text-align: left;
  font-size: 12.5px;
}
.status-head:hover { background: color-mix(in srgb,var(--text) 3%,transparent); color: var(--text); }

.status-caret { display: grid; place-items: center; width: 16px; height: 16px; color: var(--text-faint); transition: transform .18s; }
.status-caret svg { width: 15px; height: 15px; }
.statusbar.open .status-caret { transform: rotate(180deg); }

/* The lamp is the whole point of the folded bar: one glance, one answer. */
.status-lamp {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--text-faint);
  flex: none;
  transition: background .2s, box-shadow .2s;
}
.status-lamp.busy { background: var(--accent); box-shadow: 0 0 10px color-mix(in srgb,var(--accent) 80%,transparent); animation: pulse 1.2s ease-in-out infinite; }
.status-lamp.ok   { background: var(--ok);     box-shadow: 0 0 8px color-mix(in srgb,var(--ok) 55%,transparent); }
.status-lamp.bad  { background: var(--bad);    box-shadow: 0 0 10px color-mix(in srgb,var(--bad) 70%,transparent); }

.status-state { font-weight: 600; color: var(--text); flex: none; }
.status-now {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-dim); font-size: 12px;
}
.status-spacer { flex: 1 1 auto; }

.status-fails {
  flex: none; font-size: 11px; font-weight: 600;
  padding: 2px 8px; border-radius: 999px;
  background: color-mix(in srgb,var(--bad) 14%,transparent); border: 1px solid color-mix(in srgb,var(--bad) 36%,transparent); color: var(--bad-text);
}
.status-count { flex: none; font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums; }

.status-body { display: none; border-top: 1px solid var(--line-soft); }
.statusbar.open .status-body { display: flex; flex-direction: column; max-height: min(46vh, 420px); }

.status-tools {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: 8px 14px; border-bottom: 1px solid var(--line-soft);
}
.status-filters { display: flex; gap: 4px; }
.sf {
  background: transparent; border: 1px solid transparent; color: var(--text-faint);
  padding: 3px 10px; border-radius: 999px; font-size: 11.5px; cursor: pointer;
}
.sf:hover { color: var(--text); }
.sf.active { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 36%,transparent); color: var(--text); }
.status-follow { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--text-faint); cursor: pointer; }
.status-follow input { accent-color: var(--accent); }
.status-tools .btn-ghost { margin-left: auto; }
.status-tools .btn-ghost + .btn-ghost { margin-left: 0; }

.status-jobs { flex: none; max-height: 132px; overflow-y: auto; padding: 6px 14px; display: flex; flex-direction: column; gap: 5px; }
.status-jobs:empty { display: none; }

.sjob {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 9px; border-radius: 9px;
  background: var(--bg-elev-2); border: 1px solid var(--line-soft);
  font-size: 11.5px;
}
.sjob.running { border-color: color-mix(in srgb,var(--accent) 40%,transparent); background: color-mix(in srgb,var(--accent) 7%,transparent); }
.sjob.error   { border-color: color-mix(in srgb,var(--bad) 36%,transparent); }
.sjob .sj-kind {
  flex: none; font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-faint); min-width: 62px;
}
.sjob .sj-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.sjob .sj-stage { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-dim); }
.sjob .sj-bar { flex: none; width: 78px; height: 4px; background: var(--surface3); border-radius: 3px; overflow: hidden; }
.sjob .sj-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width .4s; }
.sjob .sj-x {
  flex: none; background: transparent; border: 1px solid var(--line); color: var(--text-faint);
  border-radius: 6px; width: 20px; height: 20px; line-height: 1; cursor: pointer;
}
.sjob .sj-x:hover { color: var(--bad-text); border-color: color-mix(in srgb,var(--bad) 45%,transparent); }

.status-log {
  flex: 1 1 auto; overflow-y: auto; min-height: 0;
  padding: 8px 14px 14px;
  font-family: var(--mono); font-size: 11.5px; line-height: 1.55;
}
.slog { display: flex; gap: 9px; padding: 2px 0; border-bottom: 1px solid color-mix(in srgb,var(--text) 2.5%,transparent); }
.slog:last-child { border-bottom: none; }
.slog .st { flex: none; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.slog .ss { flex: none; width: 74px; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.slog .sm { flex: 1 1 auto; min-width: 0; word-break: break-word; color: var(--text-dim); }
.slog.info .sm { color: var(--text-dim); }
.slog.ok   .sm { color: var(--ok-text); }
.slog.warn .sm { color: var(--warn-text); }
.slog.error .sm { color: var(--bad-text); font-weight: 500; }

/* The provider's own words, folded away until asked for. This is the thing
   the operator copies into a support ticket, so it is selectable and wraps. */
.slog details { margin-top: 3px; }
.slog summary { cursor: pointer; color: var(--text-faint); font-size: 10.5px; list-style: none; }
.slog summary::-webkit-details-marker { display: none; }
.slog summary:hover { color: var(--text-dim); }
.slog pre {
  margin: 5px 0 2px; padding: 8px 10px;
  background: var(--code-bg); border: 1px solid var(--line-soft); border-radius: 8px;
  white-space: pre-wrap; word-break: break-word; color: var(--text-dim);
  max-height: 260px; overflow: auto; user-select: text;
}
.status-empty { padding: 20px 4px; text-align: center; color: var(--text-faint); font-family: var(--font); }

/* ==========================================================================
   Rail — the selected project
   ========================================================================== */

.rail-project { padding: 4px 12px 12px; }
.rp-empty { font-size: 11.5px; color: var(--text-faint); padding: 6px 0; }
.rp-card {
  border: 1px solid color-mix(in srgb,var(--accent) 30%,transparent); background: var(--accent-soft);
  border-radius: 10px; padding: 8px 10px;
}
.rp-code {
  font-family: var(--mono); font-size: 10.5px; color: var(--accent-text);
  word-break: break-all; line-height: 1.4;
}
.rp-steps { display: flex; gap: 3px; margin-top: 7px; }
.rp-step {
  flex: 1; height: 4px; border-radius: 2px; background: var(--line-strong);
}
.rp-step.done { background: var(--ok); }
.rp-step.part { background: var(--warn); }

/* ==========================================================================
   Panes — three columns, on every tab
   ========================================================================== */

.col-chats, .col-list { width: 250px; }
.col-params { width: 340px; }
.pane.wide .col-params { width: 400px; }

.col-mid { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.mid-scroll { flex: 1; overflow-y: auto; min-height: 0; padding: 16px 18px 20px; }

.col-head .col-title { font-size: 12px; font-weight: 600; color: var(--text-dim); letter-spacing: .02em; }
.col-head .col-sub { font-size: 10.5px; color: var(--text-faint); }

/* The list of films, shared by tabs 2 through 8. */
.proj-item {
  display: flex; flex-direction: column; gap: 5px;
  padding: 8px 10px; border-radius: 10px; cursor: pointer;
  border: 1px solid transparent; background: transparent; text-align: left; width: 100%;
  color: var(--text-dim);
}
.proj-item:hover { background: color-mix(in srgb,var(--text) 4%,transparent); color: var(--text); }
.proj-item.active { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 32%,transparent); color: var(--text); }
.proj-code { font-family: var(--mono); font-size: 10.5px; line-height: 1.4; word-break: break-all; }
.proj-meta { font-size: 10.5px; color: var(--text-faint); display: flex; gap: 8px; flex-wrap: wrap; }
.proj-steps { display: flex; gap: 2px; }
.proj-steps i { width: 9px; height: 3px; border-radius: 2px; background: var(--line-strong); display: block; }
.proj-steps i.done { background: var(--ok); }
.proj-steps i.part { background: var(--warn); }

/* ==========================================================================
   Messages — the "…" menu that promotes a reply to the answer
   ========================================================================== */

.msg-head { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.msg-head .msg-role { margin: 0; }
.msg-tools { margin-left: auto; position: relative; }
.dots-btn {
  background: transparent; border: 1px solid var(--line); color: var(--text-faint);
  border-radius: 7px; width: 26px; height: 22px; cursor: pointer; line-height: 1;
  font-size: 13px; letter-spacing: 1px;
}
.dots-btn:hover { color: var(--text); border-color: var(--line-strong); background: color-mix(in srgb,var(--text) 4%,transparent); }
.dots-menu {
  display: none; position: absolute; right: 0; top: 26px; z-index: 30;
  min-width: 250px; background: var(--bg-elev-2); border: 1px solid var(--line);
  border-radius: 11px; box-shadow: var(--shadow); padding: 5px;
}
.dots-menu.open { display: block; }
.dots-menu button {
  display: block; width: 100%; text-align: left; background: transparent; border: none;
  color: var(--text-dim); padding: 8px 10px; border-radius: 8px; cursor: pointer; font-size: 12.5px;
}
.dots-menu button:hover:not(:disabled) { background: var(--accent-soft); color: var(--text); }
.dots-menu button:disabled { opacity: .4; cursor: not-allowed; }
.dots-menu .dm-note { padding: 6px 10px 8px; font-size: 11px; color: var(--text-faint); line-height: 1.5; }
.dots-menu hr { border: none; border-top: 1px solid var(--line-soft); margin: 4px 0; }

.msg.chosen .msg-body { border-left: 2px solid var(--ok); padding-left: 12px; }
.msg-chosen-tag {
  font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ok-text); background: color-mix(in srgb,var(--ok) 12%,transparent);
  border: 1px solid color-mix(in srgb,var(--ok) 30%,transparent); border-radius: 999px; padding: 1px 8px;
}
.msg-nojson {
  font-size: 10px; color: var(--text-faint);
  border: 1px dashed var(--line); border-radius: 999px; padding: 1px 8px;
}

/* ==========================================================================
   Parameter panel additions
   ========================================================================== */

.sep { height: 1px; background: var(--line-soft); margin: 14px 0; }
.sep-label {
  display: flex; align-items: center; gap: 9px;
  margin: 16px 0 10px; font-size: 10px; text-transform: uppercase;
  letter-spacing: .1em; color: var(--text-faint);
}
.sep-label::after { content: ""; flex: 1; height: 1px; background: var(--line-soft); }

.pfield input[type="search"] {
  width: 100%; background: var(--bg-input); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 8px 11px; outline: none;
}
.pfield select:disabled, .pfield input:disabled, .pfield textarea:disabled {
  opacity: .5; cursor: not-allowed;
}

.big-text {
  width: 100%; min-height: 320px; resize: vertical;
  background: var(--code-bg); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 11px 12px; font-family: var(--mono); font-size: 12px; line-height: 1.6;
  white-space: pre; overflow: auto; outline: none;
}
.big-text:focus { border-color: color-mix(in srgb,var(--accent) 45%,transparent); }
.big-text.fill { min-height: 0; flex: 1 1 auto; }

.params-flex { display: flex; flex-direction: column; min-height: 0; flex: 1; }

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.btn-inline { padding: 8px 14px; font-size: 12.5px; border-radius: 9px; width: auto; }
.btn-sm { padding: 5px 10px; font-size: 11.5px; border-radius: 8px; }

.note {
  font-size: 11.5px; line-height: 1.55; color: var(--text-faint);
  border-left: 2px solid var(--line); padding-left: 9px; margin: 8px 0;
}
.note.warn { border-color: var(--warn); color: var(--warn-text); }
.note.bad  { border-color: var(--bad);  color: var(--bad-text); }
.note.good { border-color: var(--ok);   color: var(--ok-text); }

/* ==========================================================================
   Cast, scenes, lines — the list views in the middle column
   ========================================================================== */

.card {
  background: var(--bg-elev); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 14px; margin-bottom: 11px;
}
.card.sel { border-color: color-mix(in srgb,var(--accent) 50%,transparent); background: color-mix(in srgb,var(--accent) 6%,transparent); }
.card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.card-title { font-size: 14px; font-weight: 600; }
.card-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }

.chip {
  font-size: 10.5px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--text-faint); white-space: nowrap;
}
.chip.ok   { border-color: color-mix(in srgb,var(--ok) 35%,transparent);  color: var(--ok-text);  background: color-mix(in srgb,var(--ok) 10%,transparent); }
.chip.warn { border-color: color-mix(in srgb,var(--warn) 35%,transparent);  color: var(--warn-text);  background: color-mix(in srgb,var(--warn) 10%,transparent); }
.chip.bad  { border-color: color-mix(in srgb,var(--bad) 35%,transparent); color: var(--bad-text);  background: color-mix(in srgb,var(--bad) 10%,transparent); }
.chip.busy { border-color: color-mix(in srgb,var(--accent) 40%,transparent);  color: var(--accent-text);  background: color-mix(in srgb,var(--accent) 10%,transparent); }

.cast-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; }
.cast-card {
  background: var(--bg-elev); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; cursor: pointer;
  transition: border-color .15s, transform .15s;
}
.cast-card:hover { border-color: color-mix(in srgb,var(--accent) 45%,transparent); transform: translateY(-2px); }
.cast-card.sel { border-color: var(--accent); }
.cast-media { aspect-ratio: 16/9; background: var(--code-bg); display: grid; place-items: center; position: relative; }
.cast-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cast-media .ph { color: var(--text-faint); font-size: 11.5px; text-align: center; padding: 12px; }
.cast-info { padding: 9px 11px; display: flex; flex-direction: column; gap: 5px; }
.cast-name { font-size: 13px; font-weight: 600; }
.cast-chips { display: flex; gap: 5px; flex-wrap: wrap; }

.line-row {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 9px 11px; border-radius: 10px; margin-bottom: 6px;
  background: var(--bg-elev); border: 1px solid var(--line-soft);
}
.line-row.done { border-color: color-mix(in srgb,var(--ok) 25%,transparent); }
.line-row.err  { border-color: color-mix(in srgb,var(--bad) 35%,transparent); }
.line-no {
  flex: none; min-width: 30px; height: 22px; display: grid; place-items: center;
  border-radius: 6px; background: var(--surface3); font-size: 10.5px; color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.line-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.line-who { font-size: 11.5px; font-weight: 600; color: var(--text); }
.line-text { font-size: 12.5px; color: var(--text-dim); word-break: break-word; }
.line-file { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); word-break: break-all; }
.line-side { flex: none; display: flex; align-items: center; gap: 6px; }
.line-side audio { height: 30px; }

.scene-row { display: flex; flex-direction: column; gap: 8px; }
.scene-video { width: 100%; max-width: 420px; border-radius: 10px; background: #000; display: block; }

.kv { display: grid; grid-template-columns: 150px 1fr; gap: 4px 12px; font-size: 12px; }
.kv dt { color: var(--text-faint); }
.kv dd { margin: 0; color: var(--text-dim); word-break: break-word; }

.sheet-group { margin-bottom: 14px; }
.sheet-group > h4 {
  margin: 0 0 8px; font-size: 10px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-faint);
}

/* ==========================================================================
   Settings tab
   ========================================================================== */

.settings-wrap { max-width: 960px; margin: 0 auto; }
.skill-card {
  background: var(--bg-elev); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px 16px; margin-bottom: 14px;
}
.skill-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 4px; }
.skill-name { font-size: 14px; font-weight: 600; }
.skill-help { font-size: 11.5px; color: var(--text-faint); }
.skill-actions { margin-left: auto; display: flex; gap: 6px; }
.skill-card textarea {
  width: 100%; min-height: 200px; resize: vertical; margin-top: 9px;
  background: var(--code-bg); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 11px 12px; font-family: var(--mono); font-size: 12px; line-height: 1.6; outline: none;
}
.skill-card textarea:focus { border-color: color-mix(in srgb,var(--accent) 45%,transparent); }

.key-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 9px; }
.key-row label { min-width: 130px; font-size: 12.5px; color: var(--text-dim); }
.key-row input[type="text"], .key-row input[type="password"] {
  flex: 1; min-width: 240px; background: var(--bg-input); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 8px 11px; font-family: var(--mono); font-size: 12px; outline: none;
}
.key-row input:focus { border-color: color-mix(in srgb,var(--accent) 45%,transparent); }

/* ==========================================================================
   Modal footer, small modal
   ========================================================================== */

.modal-sm { max-width: 460px; }
.modal-foot {
  flex: none; display: flex; gap: 9px; justify-content: flex-end;
  padding: 12px 18px 16px; border-top: 1px solid var(--line-soft);
}
.modal-foot .btn-primary { width: auto; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1300px) {
  .col-params { width: 300px; }
  .col-chats  { width: 210px; }
}
@media (max-width: 1100px) {
  .statusbar.open .status-body { max-height: 55vh; }
}

/* ---------------------------------------------------------------------------
   Live status — the render farms, and the failures
   --------------------------------------------------------------------------- */

.status-farms { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 12px 0; }

.sfarm {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 10px; border-radius: 8px; font-size: 12px;
  border: 1px solid var(--line, var(--line)); background: var(--panel-2, var(--surface));
  min-width: 260px; flex: 1 1 260px;
}
.sfarm-lamp { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); flex: 0 0 auto; }
.sfarm.warn .sfarm-lamp { background: var(--warn); }
.sfarm.bad  .sfarm-lamp { background: var(--bad); }
.sfarm.bad  { border-color: var(--bad-line); }
.sfarm.warn { border-color: var(--warn-line); }
.sfarm-name  { font-weight: 600; letter-spacing: .02em; }
.sfarm-state { opacity: .85; text-transform: lowercase; }
.sfarm-bits  { opacity: .6; margin-left: auto; text-align: right; }

/* THE LIST SCROLLS; THE ROWS ARE ONE LINE UNTIL OPENED.
   Sixteen failures, each carrying the provider's own multi-line words, filled
   the panel and hid every failure after the second. */
.status-fails-list {
  padding: 8px 12px 0; display: flex; flex-direction: column; gap: 6px;
  max-height: min(38vh, 320px); overflow-y: auto; overscroll-behavior: contain;
}
.sfail-head { font-size: 12px; font-weight: 600; color: var(--bad-text); position: sticky; top: 0;
  background: var(--panel, var(--surface)); padding: 2px 0 4px; z-index: 1; }
.sfail {
  border: 1px solid var(--bad-line); border-radius: 8px; padding: 7px 10px;
  background: color-mix(in srgb,var(--bad) 12%,transparent); font-size: 12px;
}
.sfail-top { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.sfail-caret { flex: none; opacity: .7; width: .8em; }
.sfail-kind { font-weight: 600; flex: none; }
/* The reason, on the same line, cut where it runs out of room. */
.sfail-one {
  flex: 1 1 auto; min-width: 0; opacity: .8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sfail-when { opacity: .55; flex: none; }
.sfail-retry { flex: none; padding: 2px 10px; font-size: 11px; }
.sfail-body { display: none; }
.sfail.open .sfail-body { display: block; }
.sfail.open .sfail-one { display: none; }
.sfail-msg {
  margin-top: 4px; opacity: .85; white-space: pre-wrap; word-break: break-word;
  max-height: 12em; overflow: auto; font-family: var(--mono, ui-monospace, monospace);
}
.sfail-fix { margin-top: 5px; color: var(--ok-text); font-size: 11px; }

/* ---------------------------------------------------------------------------
   Auto Generate ALL, under the Script tab's send box
   --------------------------------------------------------------------------- */

.autoall {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 8px 0 2px; padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--line, var(--line)); background: var(--panel-2, var(--surface));
}
.autoall-switch { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.autoall-label { font-weight: 600; letter-spacing: .01em; }
.autoall-go { margin-left: auto; padding: 7px 16px; }
.autoall-go[disabled] { opacity: .45; cursor: not-allowed; }
.autoall-help { flex: 1 1 100%; font-size: 12px; opacity: .62; line-height: 1.5; }

/* ---------------------------------------------------------------------------
   Total Cost
   --------------------------------------------------------------------------- */

.cost-head { display: flex; gap: 14px; flex-wrap: wrap; margin: 4px 0 12px; }
.cost-big {
  flex: 1 1 240px; padding: 16px 18px; border-radius: 12px;
  border: 1px solid var(--line, var(--line)); background: var(--panel-2, var(--surface));
}
.cost-big.free { border-color: color-mix(in srgb,var(--ok) 32%,transparent); background: color-mix(in srgb,var(--ok) 7%,transparent); }
.cost-amount { font-size: 30px; font-weight: 700; letter-spacing: -.02em; }
.cost-big.free .cost-amount { color: var(--ok-text); }
.cost-cap { margin-top: 4px; font-size: 12px; opacity: .6; }

.cost-table { width: 100%; border-collapse: collapse; font-size: 13px; margin: 6px 0 4px; }
.cost-table th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  opacity: .5; padding: 6px 10px; border-bottom: 1px solid var(--line, var(--line)); font-weight: 600;
}
.cost-table td { padding: 7px 10px; border-bottom: 1px solid color-mix(in srgb,var(--text) 5%,transparent); vertical-align: top; }
.cost-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cost-table .cost-what { opacity: .62; white-space: pre-line; font-size: 12px; }
.cost-table tr.freerow td { opacity: .58; }
.cost-table tr.freerow .num { color: var(--ok-text); opacity: .9; }
.cost-table tr.total td { font-weight: 700; border-top: 2px solid var(--line, var(--line)); border-bottom: none; }

/* ---------------------------------------------------------------------------
   Thumbnails, clip tiles and the full-size viewer
   --------------------------------------------------------------------------- */

.tile-img {
  border-radius: 8px; border: 1px solid var(--line, var(--line));
  cursor: zoom-in; background: #000; display: block; object-fit: cover;
  transition: border-color .12s ease, transform .12s ease;
}
.tile-img:hover { border-color: var(--accent, var(--accent)); }
.tile-img.primary { border: 2px solid var(--ok, var(--ok)); cursor: zoom-in; }

.tile-empty {
  border-radius: 8px; border: 1px dashed var(--line, var(--line));
  display: grid; place-items: center; text-align: center; padding: 6px;
  font-size: 10.5px; color: var(--text-faint, var(--dim)); min-width: 62px;
}

.cliptile { position: relative; border-radius: 8px; overflow: hidden; }
.cliptile .tile-img { cursor: pointer; }
.cliptile-play {
  position: absolute; inset: 0; margin: auto; width: 40px; height: 40px;
  border-radius: 50%; border: none; cursor: pointer; display: grid; place-items: center;
  background: rgba(0, 0, 0, .58); color: #fff; backdrop-filter: blur(2px);
  transition: background .12s ease, transform .12s ease;
}
.cliptile-play:hover { background: rgba(0, 0, 0, .8); transform: scale(1.08); }
.cliptile-play svg { width: 20px; height: 20px; margin-left: 2px; }

.lightbox {
  position: fixed; inset: 0; z-index: 900; display: grid; place-items: center;
  background: rgba(0, 0, 0, .86); padding: 24px; cursor: zoom-out;
}
.lightbox-inner { position: relative; max-width: 94vw; max-height: 92vh; cursor: default; }
.lightbox-inner img,
.lightbox-inner video {
  max-width: 94vw; max-height: 86vh; border-radius: 10px; display: block; background: #000;
}
.lightbox-cap { margin-top: 8px; text-align: center; font-size: 12px; color: #e6e6e6; }
.lightbox-x {
  position: absolute; top: -14px; right: -14px; width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid color-mix(in srgb,var(--text) 25%,transparent); background: #111; color: #fff;
  font-size: 20px; line-height: 1; cursor: pointer;
}
.lightbox-x:hover { background: #222; }

/* ---------------------------------------------------------------------------
   The style picker
   --------------------------------------------------------------------------- */

.style-grid {
  display: grid; gap: 14px; margin: 14px 0 8px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.style-card {
  cursor: pointer; border-radius: 12px; overflow: hidden;
  border: 2px solid transparent; background: var(--panel-2, var(--surface));
  transition: border-color .12s ease, transform .12s ease;
}
.style-card:hover { border-color: var(--accent, var(--accent)); transform: translateY(-2px); }
.style-img { width: 100%; aspect-ratio: 9 / 16; object-fit: cover; display: block; background: #000; }
.style-name {
  padding: 9px 10px; font-size: 13px; font-weight: 600; text-align: center;
  letter-spacing: .01em;
}

/* ---------------------------------------------------------------------------
   The show's cast, on tab 1
   --------------------------------------------------------------------------- */

.cast-strip { display: flex; gap: 12px; flex-wrap: wrap; padding: 4px 0 2px; }
.cast-card {
  width: 168px; cursor: pointer; border-radius: 12px; overflow: hidden;
  border: 2px solid transparent; background: var(--panel-2, var(--surface));
  transition: border-color .12s ease, transform .12s ease;
}
.cast-card:hover { border-color: var(--accent, var(--accent)); transform: translateY(-2px); }
.cast-card.sel   { border-color: var(--accent, var(--accent)); }
.cast-img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; background: #000;
}
.cast-img.empty {
  display: grid; place-items: center; font-size: 11px; color: var(--text-faint, var(--dim));
  border-bottom: 1px dashed var(--line, var(--line));
}
.cast-name { padding: 8px 10px 2px; font-size: 13px; font-weight: 600; }
.cast-role { padding: 0 10px 9px; font-size: 11px; opacity: .58; }

.sheet-preview {
  width: 100%; border-radius: 10px; border: 1px solid var(--line, var(--line));
  margin-bottom: 10px; cursor: zoom-in; display: block; background: #000;
}

/* A cast member the current bible no longer mentions. Kept, not deleted —
   its sheet is still on disk and un-retiring is one refresh away. */
.cast-card.retired { opacity: .48; border-style: dashed; }
.cast-card.retired .cast-role { color: var(--warn); }

/* The bible's version history */
.rev-panel { background: var(--panel, var(--surface)); padding: 20px 22px; border-radius: 12px; min-width: 420px; }
.rev-panel h3 { margin: 0 0 6px; font-size: 16px; }
.rev-list { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.rev-row {
  display: flex; align-items: center; gap: 12px; padding: 8px 10px;
  border: 1px solid var(--line, var(--line)); border-radius: 8px; font-size: 13px;
}
.rev-row.current { border-color: var(--ok, var(--ok)); background: color-mix(in srgb,var(--ok) 6%,transparent); }
.rev-no { font-weight: 600; min-width: 56px; }
.rev-meta { opacity: .58; margin-right: auto; font-size: 12px; }

/* Live progress on a cast card while its sheet is being generated */
.cast-prog {
  padding: 0 10px 9px; font-size: 11px; color: var(--accent, var(--accent));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cast-img.empty { gap: 6px; }
.cast-retired-tools {
  display: flex; gap: 6px; padding: 0 8px 9px;
}
.cast-retired-tools .btn-sm { flex: 1; padding: 3px 6px; font-size: 11px; }
.cast-retired-tools .danger { color: var(--bad-text); }
.cast-retired-tools .danger:hover { background: color-mix(in srgb,var(--bad) 25%,transparent); }

/* Duration as minutes + seconds */
.dur-row { display: flex; align-items: center; gap: 8px; }
.dur-row input { width: 82px; }
.dur-unit { font-size: 12px; opacity: .6; }

/* The script list: title first, code beneath, state on the row */
.proj-title { font-size: 13px; font-weight: 600; letter-spacing: .01em; }
.proj-code  { font-size: 10.5px; opacity: .5; font-family: var(--mono, ui-monospace, monospace); }
.proj-meta .ok   { color: var(--ok, var(--ok)); }
.proj-meta .warn { color: var(--warn, var(--warn)); }

/* ---------------------------------------------------------------------------
   GPU / CPU / MEM / DISK on the folded status line
   --------------------------------------------------------------------------- */

.status-meters { display: flex; align-items: center; gap: 14px; margin-left: 18px; }

.sm { display: flex; align-items: center; gap: 6px; }
.sm-name {
  font-size: 10px; font-weight: 700; letter-spacing: .06em;
  color: var(--text-faint, var(--dim)); min-width: 26px;
}
.sm-track {
  width: 54px; height: 5px; border-radius: 3px;
  background: var(--surface3); overflow: hidden; display: block;
}
.sm-fill {
  display: block; height: 100%; width: 0; border-radius: 3px;
  background: linear-gradient(90deg, var(--accent, var(--accent)), var(--accent-2, var(--accent-hover)));
  transition: width .45s ease, background .3s ease;
}
.sm-fill.warm { background: linear-gradient(90deg, var(--warn), color-mix(in srgb,var(--warn) 55%,var(--bad))); }
.sm-fill.hot  { background: linear-gradient(90deg, var(--bad), color-mix(in srgb,var(--bad) 80%,var(--accent))); }
.sm-val {
  font-size: 10.5px; font-variant-numeric: tabular-nums;
  color: var(--text-dim, var(--muted)); min-width: 30px; text-align: right;
}

/* The bar is one line; on a narrow screen the meters are the first thing to go,
   because the lamp and the current job matter more. */
@media (max-width: 1100px) { .status-meters .sm:nth-child(n+3) { display: none; } }
@media (max-width: 820px), (max-height: 500px)  { .status-meters { display: none; } }

/* Delete a film, from the script list */
.proj-item { position: relative; }
.proj-x {
  position: absolute; top: 6px; right: 6px;
  width: 20px; height: 20px; border-radius: 5px; line-height: 1;
  border: 1px solid transparent; background: none; cursor: pointer;
  color: var(--text-faint, var(--dim)); font-size: 15px;
  opacity: 0; transition: opacity .12s ease, background .12s ease, color .12s ease;
}
.proj-item:hover .proj-x { opacity: 1; }
.proj-x:hover { background: color-mix(in srgb,var(--bad) 35%,transparent); color: var(--bad-text); border-color: var(--bad-line); }

/* =========================================================================
   THE SHELVES  —  films sorted by what is left to do, and by shape
   =========================================================================
   Four trees on the Script tab, four more on the editing tab. They replace a
   flat list of conversations, which answered "which chats exist" when the
   question standing in front of the screen is "have I got anything ready to
   post tomorrow, and is it the right shape".
   ========================================================================= */

.shelf { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; margin-bottom: 6px; }

.shelf-head {
  width: 100%; display: flex; align-items: center; gap: 7px;
  padding: 8px 9px; background: color-mix(in srgb,var(--text) 2%,transparent); border: 0;
  color: var(--text-dim); font: inherit; font-size: 12px; font-weight: 600;
  cursor: pointer; text-align: left;
}
.shelf-head:hover { background: color-mix(in srgb,var(--text) 5%,transparent); color: var(--text); }
.shelf-head.open { color: var(--text); border-bottom: 1px solid var(--line); }
.shelf-caret { width: 10px; color: var(--text-faint); font-size: 10px; }
.shelf-label { flex: 1; }

.shelf-count {
  min-width: 20px; padding: 1px 6px; border-radius: 999px; text-align: center;
  background: var(--accent-soft); color: var(--text); font-size: 11px; font-variant-numeric: tabular-nums;
}
.shelf-count.zero { background: color-mix(in srgb,var(--text) 5%,transparent); color: var(--text-faint); }

.shelf-body { padding: 6px; display: flex; flex-direction: column; gap: 4px; }
.shelf-empty { padding: 8px 6px; color: var(--text-faint); font-size: 11.5px; line-height: 1.5; }

.shelf-item {
  padding: 7px 8px; border: 1px solid transparent; border-radius: 7px;
  cursor: pointer; color: var(--text-dim);
}
.shelf-item:hover { background: color-mix(in srgb,var(--text) 4%,transparent); color: var(--text); }
.shelf-item.active { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 30%,transparent); color: var(--text); }

/* A film being carried to the end on its own gets a moving edge, so the rail
   answers "is anything happening" without being read. */
.shelf-item.flying { border-color: color-mix(in srgb,var(--accent) 45%,transparent); }
.shelf-item.flying .shelf-stamp::after {
  content: ' · running'; color: var(--accent); animation: shelfPulse 1.8s ease-in-out infinite;
}
@keyframes shelfPulse { 0%,100% { opacity: .45; } 50% { opacity: 1; } }

.shelf-title { font-size: 12.5px; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shelf-stamp { margin-top: 2px; font-size: 10.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }

/* DELETE ON THE LEFT, EVERYTHING ELSE ON THE RIGHT EDGE.
   Delete used to sit last, which put it in the middle of a two- or three-chip
   row — the spot a thumb lands on when it means the row itself, and one press
   from losing a film's whole folder. It is now the first chip, directly under
   the episode number, and auto margin throws the safe actions (Open, Archive,
   Edit Full) across to the far side so the two are never adjacent. */
.shelf-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 6px; }
.shelf-acts > .chip-danger:first-child { margin-right: auto; }

.chip {
  padding: 3px 8px; border-radius: 999px; border: 1px solid var(--line);
  background: transparent; color: var(--text-dim); font: inherit; font-size: 10.5px;
  cursor: pointer; white-space: nowrap;
}
.chip:hover { border-color: var(--accent); color: var(--text); }
.chip-on { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 45%,transparent); color: var(--text); }
.chip-danger:hover { border-color: var(--bad, var(--bad)); color: var(--bad, var(--bad)); }

/* ---- the standing orders ------------------------------------------------- */

.orders {
  border: 1px solid var(--line); border-radius: 8px; padding: 9px;
  margin-bottom: 6px; background: color-mix(in srgb,var(--text) 2%,transparent);
}
.orders-title { font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 7px; }
.orders-help { margin-top: 7px; font-size: 10.5px; line-height: 1.5; color: var(--text-faint); }

.order-row { display: flex; flex-direction: column; gap: 4px; padding: 5px 0; }
.order-row + .order-row { border-top: 1px dashed var(--line); }
.order-check { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text-dim); cursor: pointer; }
.order-row.on .order-check { color: var(--text); }
.order-target { display: flex; align-items: center; gap: 6px; padding-left: 23px; }
.order-lbl { font-size: 10.5px; color: var(--text-faint); }
.order-num {
  width: 52px; padding: 3px 6px; border-radius: 6px; border: 1px solid var(--line);
  background: var(--bg-input, rgba(0,0,0,.25)); color: var(--text);
  font: inherit; font-size: 11.5px; font-variant-numeric: tabular-nums;
}
.order-have { font-size: 10.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
/* Below target is the whole point of the rule, so it is the state that shows. */
.order-have.short { color: var(--accent); }

/* ---- bulk creation, under the send box ---------------------------------- */

.bulk-row { display: flex; flex-direction: column; gap: 6px; }
.bulk-title { font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-faint); }
.bulk-check { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text-dim); cursor: pointer; }
.bulk-n { display: flex; align-items: center; gap: 6px; }
.bulk-go { margin-top: 9px; gap: 6px; }
.bulk-go .btn-primary, .bulk-go .btn-ghost { flex: 1; }

/* =========================================================================
   THE TREES, THE WAY AN EDITOR DOES THEM
   =========================================================================
   Sticky section headers, indent guides down the children, tight rows, and a
   thin scrollbar that only appears over the tree it belongs to. The point is
   that the header you are under stays readable while you scroll inside it —
   otherwise a long Unedited list scrolls its own title away and you are
   looking at rows with nothing to say which shelf they are on.
   ========================================================================= */

.shelf-head {
  position: sticky; top: 0; z-index: 2;
  /* Opaque, not translucent: rows scrolling underneath must not show through. */
  background: var(--bg-elev);
  box-shadow: 0 1px 0 var(--line-soft);
}
.shelf-head.open { background: var(--bg-elev); }

/* Each tree scrolls inside itself once it is taller than this, so one shelf
   with forty films cannot bury the three below it. */
.shelf-body {
  max-height: 46vh; overflow-y: auto; overflow-x: hidden;
  padding: 4px 4px 4px 0;
}

/* The indent guide — one hairline down the left of the children, exactly like
   a file tree, so a row is visibly INSIDE the section above it. */
.shelf-body > * { position: relative; margin-left: 15px; }
.shelf-body::before {
  content: ''; position: absolute; left: 14px; top: 4px; bottom: 4px;
  width: 1px; background: var(--line-soft); pointer-events: none;
}
.shelf-body { position: relative; }

.shelf-item { padding: 5px 8px; border-radius: 5px; }
.shelf-item:hover { background: color-mix(in srgb,var(--text) 5%,transparent); }


/* The actions only appear on the row you are pointing at or the one that is
   selected — a rail with four buttons on every row is unreadable. */
.shelf-acts { display: none; }
.shelf-item:hover .shelf-acts,
.shelf-item.active .shelf-acts,
.shelf-item.flying .shelf-acts { display: flex; }

/* ---- run-now, beside each standing order ------------------------------- */

.order-now {
  margin-left: auto; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--line); background: transparent; color: var(--text-dim);
  font: inherit; font-size: 10.5px; cursor: pointer; white-space: nowrap;
}
.order-now:hover { border-color: var(--accent); color: var(--text); }
.order-now:disabled { opacity: .45; cursor: default; border-color: var(--line); color: var(--text-faint); }

/* =========================================================================
   WHY THE TREES WOULD NOT SCROLL
   =========================================================================
   .chats-list is a flex COLUMN, and a flex item shrinks by default. So six
   trees taller than the rail were not overflowing it — they were being
   squeezed into it, every one of them a little shorter than its content, and
   a container whose children have politely shrunk to fit has nothing to
   scroll. Measured: scrollHeight and clientHeight both exactly 694px, with
   about 1900px of content inside.

   flex: none is the whole fix. The children keep their real height, the
   column overflows, and overflow-y: auto finally has something to do.
   ========================================================================= */

.chats-list > * { flex: none; }

/* Each tree is now free to be its natural height and the RAIL scrolls as one
   list — which is how a file tree behaves, and why the per-tree cap and its
   private scrollbar are gone. Two nested scrollers in a 250px column meant the
   wheel did something different depending on which pixel you were over. */
.shelf-body { max-height: none; overflow: visible; }

/* Sticky headers need every ancestor between them and the scroller to not clip.
   .shelf had overflow: hidden for its rounded corners, which silently killed
   the stickiness — the corners are worth less than the behaviour. */
.shelf { overflow: visible; }

/* =========================================================================
   THE STRIP UNDER THE TAB'S TITLE BAR
   ========================================================================= */

.pane.has-top { flex-direction: column; }
.pane-cols { flex: 1; min-height: 0; display: flex; }

.pane-top {
  flex: none;
  display: flex; flex-direction: column; gap: 4px;
  padding: 6px 14px 7px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-elev);
}

/* ALL FOUR RULES ON ONE LINE — both shapes of Auto Create, then both shapes of
   Auto Edit, no headings. Smaller type than the panel it replaced, because the
   strip is a header and every pixel it takes is one the trees do not get. */
.orders-line {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  font-size: 11px;
}
.orders-split {
  width: 1px; align-self: stretch; margin: 1px 2px; background: var(--line);
}

.pane-top .order-row {
  flex: none; flex-direction: row; align-items: center; gap: 6px;
  padding: 1px 0; border: 0;
}
.pane-top .order-row + .order-row { border-top: 0; }
.pane-top .order-check { flex: none; gap: 5px; font-size: 11px; }
.pane-top .order-check input { width: 13px; height: 13px; margin: 0; }
.pane-top .order-target { padding-left: 0; flex: none; gap: 5px; }
.pane-top .order-lbl,
.pane-top .order-have { font-size: 10px; }
.pane-top .order-num { width: 40px; padding: 1px 4px; font-size: 11px; }
.pane-top .order-now { margin-left: 0; padding: 1px 7px; font-size: 10px; }

/* ---- the editing queue, under the rules ---------------------------------- */

.queue-line {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding-top: 5px; margin-top: 4px; border-top: 1px dashed var(--line);
}
.queue-lbl { font-size: 10px; color: var(--text-faint); text-transform: uppercase;
  letter-spacing: .04em; font-weight: 700; }
.queue-note { font-size: 10px; color: var(--text-faint); }

.queue-chip {
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 300px; padding: 2px 4px 2px 7px;
  border: 1px solid var(--line); border-radius: 999px;
  font-size: 10.5px; color: var(--text-dim); white-space: nowrap;
}
.queue-chip > span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; }
/* The one actually being cut is the only one that is doing anything. */
.queue-chip.on {
  border-color: color-mix(in srgb,var(--accent) 45%,transparent); background: var(--accent-soft); color: var(--text);
}
.queue-shape {
  padding: 0 5px; border-radius: 3px; background: color-mix(in srgb,var(--text) 6%,transparent);
  font-family: var(--mono); font-size: 9.5px;
}
.queue-x {
  width: 15px; height: 15px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: transparent;
  color: var(--text-faint); font: inherit; font-size: 13px; line-height: 1; cursor: pointer;
}
.queue-x:hover { background: color-mix(in srgb,var(--text) 10%,transparent); color: var(--text); }

/* What each rule does now lives on the switch's own tooltip rather than in a
   line of help under it — the strip cannot afford four lines of prose. */

/* THE EPISODE NUMBER, in front of the film's name on every tab.
   One class, because it has to look identical in a shelf row, a film list, a
   rail card and a cost table — an identifier that changes appearance stops
   being an identifier. */
.ep-tag, .shelf-ep {
  display: inline-block; margin-right: 6px; padding: 0 5px;
  border-radius: 4px; background: var(--accent-soft); color: var(--accent-text);
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  vertical-align: 1px;
}

.rp-ep {
  font-size: 11px; font-weight: 600; color: var(--accent-text); margin-bottom: 3px;
  font-variant-numeric: tabular-nums;
}
.badge.ep { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 35%,transparent); color: var(--accent-text); }
.proj-title { display: flex; align-items: baseline; gap: 0; }
.proj-title > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A rule between series, so a hundred episodes still read as seasons. */
.cost-table tr.cost-group td {
  padding: 12px 10px 5px; border-bottom: 1px solid var(--line);
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-faint);
}
.cost-table td.dim { color: var(--text-faint); font-size: 12px; }
.cost-table .ep-tag { margin-right: 0; }

/* =========================================================================
   THUMBNAIL AND UPLOAD CAPTION
   ========================================================================= */

.thumb-controls {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 0 4px;
}
.thumb-controls .btn-row { margin-left: auto; gap: 8px; }

.thumb-body { display: flex; gap: 16px; align-items: flex-start; margin-top: 10px; }
.thumb-left { flex: 1 1 auto; min-width: 0; }
.thumb-right {
  flex: none; width: 190px; display: flex; flex-direction: column; gap: 7px; align-items: stretch;
}

/* The preview is shown at its real aspect ratio — a thumbnail squeezed into a
   square in the console is a thumbnail you cannot judge. */
.thumb-preview {
  width: 100%; height: auto; border-radius: 8px;
  border: 1px solid var(--line); background: #000; display: block;
}
.thumb-empty {
  display: grid; place-items: center; min-height: 150px;
  border: 1px dashed var(--line); border-radius: 8px;
  color: var(--text-faint); font-size: 11.5px;
}

.upload-panel .thumb-preview { max-width: 100%; }

/* ---- the preset modal --------------------------------------------------- */

.thumb-settings { display: flex; flex-direction: column; gap: 2px; text-align: left; }
.tset-group-title {
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 8px;
}
.tset-row { padding: 7px 0; border-bottom: 1px solid color-mix(in srgb,var(--text) 5%,transparent); }
.tset-row:last-child { border-bottom: 0; }
.tset-label { display: block; font-size: 12px; color: var(--text-dim); margin-bottom: 5px; font-weight: 550; }
.tset-help { margin-top: 5px; font-size: 10.5px; line-height: 1.5; color: var(--text-faint); }

.tset-select, .tset-text {
  width: 100%; padding: 6px 8px; border-radius: 7px;
  border: 1px solid var(--line); background: var(--bg-input, rgba(0,0,0,.25));
  color: var(--text); font: inherit; font-size: 12.5px;
}

.tset-colour { display: flex; align-items: center; gap: 8px; }
.tset-colour input[type="color"] {
  width: 44px; height: 30px; padding: 0; border: 1px solid var(--line);
  border-radius: 6px; background: transparent; cursor: pointer;
}
.tset-hex {
  width: 96px; padding: 5px 7px; border-radius: 6px; border: 1px solid var(--line);
  background: var(--bg-input, rgba(0,0,0,.25)); color: var(--text);
  font-family: var(--mono); font-size: 12px;
}

.tset-pct { display: flex; align-items: center; gap: 10px; }
.tset-pct input[type="range"] { flex: 1; }
.tset-num {
  flex: none; min-width: 84px; text-align: right;
  font-size: 11.5px; color: var(--text-dim); font-variant-numeric: tabular-nums;
}

@media (max-width: 900px), (max-height: 500px) {
  .thumb-body { flex-direction: column; }
  .thumb-right { width: 100%; max-width: 260px; }
}

/* =========================================================================
   STOP PROCESS
   =========================================================================
   On the folded status line, which is the one line that is always on screen.
   Quiet until something is running — a stop button that shouts while nothing
   is happening is a button people learn to ignore.
   ========================================================================= */

.statusbar { position: relative; }

.status-stop {
  position: absolute; top: 50%; right: 14px; transform: translateY(-50%);
  z-index: 5;
  padding: 4px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: transparent;
  color: var(--text-faint);
  font: inherit; font-size: 10.5px; font-weight: 700; letter-spacing: .05em;
  cursor: pointer; white-space: nowrap;
}
.status-stop:hover { border-color: var(--bad, var(--bad)); color: var(--bad, var(--bad)); }

/* While work is in flight it is the thing on the bar you can act on. */
.statusbar.busy .status-stop {
  border-color: color-mix(in srgb,var(--bad) 55%,transparent); color: var(--bad-text);
}
.statusbar.busy .status-stop:hover { background: color-mix(in srgb,var(--bad) 12%,transparent); color: var(--bad-text); }

.status-stop:disabled { opacity: .4; cursor: default; border-color: var(--line); color: var(--text-faint); }

/* The fold toggle runs the full width, so keep its contents clear of the
   button sitting on top of it. */
.status-head { padding-right: 132px; }

/* =========================================================================
   THE RENDER FARM'S QUEUE
   =========================================================================
   Two halves of one line: what the farm is working on — ours or somebody
   else's — and what we have waiting behind it. "1 of ours" said nothing about
   the seven behind it, and "3 in its queue" said nothing about whose.
   ========================================================================= */

.sfarm-queue {
  margin: 2px 0 8px 22px;
  border-left: 1px solid var(--line);
  padding-left: 10px;
  display: flex; flex-direction: column; gap: 2px;
}

.sq-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 10.5px; color: var(--text-faint); line-height: 1.5;
}
/* Ours on the farm right now is the row that matters. */
.sq-row.mine { color: var(--text-dim); }
.sq-row.mine .sq-pct { color: var(--ok); }
.sq-row.waiting { opacity: .72; }

.sq-pos   { flex: none; width: 24px; font-family: var(--mono); }
.sq-who   { flex: none; min-width: 130px; max-width: 200px; overflow: hidden;
            text-overflow: ellipsis; white-space: nowrap; }
.sq-stage { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sq-pct   { flex: none; width: 54px; text-align: right; font-variant-numeric: tabular-nums; }

/* ---- the mix, and whether it is saved ---------------------------------- */
.mix-save { display: flex; align-items: center; gap: 10px; margin: 10px 0 4px; }
.mix-state { font-size: 11px; color: var(--text-faint); }
.mix-state.dirty { color: var(--warn); }


/* ---------------------------------------------------------------------------
   THE BUFFERING NOTE
   A player that is charging says so. Without this the wait looks identical to
   a player that has simply failed, which is what made the old one feel broken
   rather than slow.
--------------------------------------------------------------------------- */
.vid-wrap { position: relative; display: block; }
.vid-wrap video { display: block; width: 100%; }

.vid-buffer {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  padding: 7px 13px; border-radius: 999px;
  background: rgba(0, 0, 0, .72); color: #fff;
  font-size: 12.5px; font-variant-numeric: tabular-nums;
  letter-spacing: .01em; pointer-events: none; white-space: nowrap;
  box-shadow: 0 2px 10px var(--shadow-color);
}

/* The medium the show enforces, stated on the Characters & Scene tab. It is
   what every prompt is written in and what the checker rejects against, so it
   is deliberately the loudest chip on the card. */
.chip.medium-chip {
  background: var(--accent);
  color: var(--accentInk); border: none; font-weight: 600; letter-spacing: .04em;
}

/* ============================ SERIES SELECTOR ============================
   The console is scoped to one series at a time. Two controls drive the same
   choice: a combo box in the header, visible from every tab, and the cards in
   the panel below it, which show at a glance what each series is and how many
   episodes it has. */
.head-series { display:flex; align-items:center; gap:.45rem; margin-left:auto; }
.head-series-label {
  font-size:.68rem; text-transform:uppercase; letter-spacing:.07em; opacity:.6;
}
.head-series-select {
  background:var(--panel,var(--surface2)); color:inherit;
  border:1px solid var(--line,var(--line)); border-radius:8px;
  padding:.32rem .55rem; font:inherit; font-size:.84rem; max-width:15rem;
}
.series-grid { display:flex; flex-wrap:wrap; gap:.5rem; }
.series-card {
  text-align:left; cursor:pointer; font:inherit; color:inherit;
  background:var(--panel,var(--surface2)); border:1px solid var(--line,var(--line));
  border-radius:10px; padding:.5rem .7rem; min-width:11rem;
}
.series-card:hover { border-color:var(--accent,var(--accent)); }
.series-card.active {
  border-color:var(--accent,var(--accent));
  box-shadow:inset 0 0 0 1px var(--accent,var(--accent));
}
.series-name { font-weight:600; font-size:.86rem; }
.series-meta { font-size:.73rem; opacity:.68; margin-top:.15rem; }

/* ---- the panel folds ----------------------------------------------------
   Same shape as the status bar's fold: a full-width header button carrying
   the caret, the state on the section as .open, and the body hidden while it
   is closed. The caret points DOWN when folded here, because this panel opens
   downward — the status bar sits at the foot of the window and opens upward. */
.fold-h2 { margin:0; font-size:.9rem; }
.fold-head {
  display:flex; align-items:center; gap:.45rem; width:100%;
  padding:0; background:none; border:0; color:var(--text-dim,inherit);
  font:inherit; font-size:.9rem; font-weight:600; text-align:left; cursor:pointer;
}
.fold-head:hover { color:var(--text,inherit); }
.fold-caret {
  display:grid; place-items:center; width:16px; height:16px;
  color:var(--text-faint); transition:transform .18s;
}
.fold-caret svg { width:15px; height:15px; }
.panel.open > .fold-h2 .fold-caret { transform:rotate(180deg); }
.fold-hint { margin-left:auto; font-size:.73rem; font-weight:400; opacity:.6; }
/* The body is present but not shown, so nothing has to be re-rendered on open
   and the cards keep their scroll position. */
#seriesbox:not(.open) > #seriesList { display:none; }
#seriesbox.open > #seriesList { margin-top:.5rem; }

/* =========================================================================
   PHONES — ONE COLUMN AT A TIME
   =========================================================================
   Nothing here reaches a desktop: every rule is inside a max-width query, and
   .mob-views (the List | Main | Settings switch app.js puts on each pane) is
   display:none until one of them opens it.

   What broke on a phone (2026-09-15, audited at 390x844):
     - the scrim sat ABOVE the drawer (45 over 40), so the menu opened dimmed
       and every tap on a tab landed on the scrim and closed it;
     - the Series panel's fifteen cards took 531px, leaving the tab ~150px;
     - the list and the parameters opened as overlays at the same time, on
       top of the middle column and of each other.
   So: the drawer above its scrim, the series as one swipeable row, and the
   three columns as three full-screen views with the middle shown first.
   ========================================================================= */

.mob-views { display: none; }

/* The drawer/scrim order used to be corrected here, for widths up to 900px
   only. It is now stated once in the base rules above, where it cannot be
   missed by a breakpoint. */

@media (max-width: 820px), (max-height: 500px) {
  html, body { overflow: hidden; }
  .app { height: 100vh; height: 100dvh; }
  /* Below 16px iOS zooms the page on focus and never zooms back. */
  input, select, textarea { font-size: 16px !important; }

  /* NOTHING IS PRESSED BY ACCIDENT, AND NOTHING WAITS 300ms.
     Without this a phone treats a tap as a possible double-tap-to-zoom and
     holds every press for a third of a second, which reads as a control that
     did not respond — so the press is repeated, on whatever has moved under
     the finger by then. */
  button, select, a, input, label, .tab, .chip, .mob-view { touch-action: manipulation; }

  /* ---- drawer ---- */
  /* The whole drawer scrolls: with the pinned script card and the user row
     fixed, only ~9 of the 14 tabs fit a phone and the rest hid in an inner list. */
  /* THE LIST SCROLLS INSIDE THE DRAWER; THE DRAWER ITSELF DOES NOT.
     Scrolling the whole drawer put its foot — the selected script and the only
     way to sign out — 200px below the bottom of an 844px phone, with nothing
     on screen to say either existed. Making the tab list the scroller is what
     the desktop already does: the list gives up the height, and the two things
     you always need stay on the last lines of the screen. */
  .rail {
    width: min(300px, 86vw); overflow: hidden;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .rail-scroll {
    flex: 1 1 auto; min-height: 0; overflow-y: auto;
    /* A list scrolled to its end must not start scrolling the page behind it,
       which on a phone is how a menu closes itself mid-press. */
    overscroll-behavior: contain;
  }
  .rail .tab { padding: 10px; }
  /* The script card is a summary, not a screenful: it takes a quarter of the
     drawer at most, and scrolls inside that if the title is long. */
  .rail-pinned { flex: none; max-height: 26vh; overflow-y: auto; overscroll-behavior: contain; }
  .rail-foot { flex: none; }
  .rail-foot .icon-btn { width: 40px; height: 40px; }

  /* A MENU READ IN DAYLIGHT, NOT A MENU THAT LOOKS DISABLED.
     The rail's dimmed palette is right on a desktop monitor a foot away; on a
     phone held at arm's length the same greys read as switched off. The drawer
     is a full-screen surface on a phone, so its text carries full contrast. */
  .rail .tab { color: var(--text); }
  .rail .tab-purpose { color: var(--text-dim); }
  .rail .rail-section { color: var(--text-dim); }

  /* ---- header: one line, always on top ---- */
  /* One scroll per view, never two: the header and the series row keep a fixed
     height and the workspace takes exactly what is left above the status bar. */
  .main { overflow: hidden; }
  /* The side padding clears a notch when the phone is turned; the height is
     fixed so the workspace below it can take exactly what is left. */
  .main-head {
    height: 56px; gap: 8px;
    padding: 0 max(10px, env(safe-area-inset-right, 0px)) 0 max(10px, env(safe-area-inset-left, 0px));
  }
  /* .main-head wins over the plain .icon-btn size further down this block,
     which otherwise shrank the one control that opens the menu to 36px. */
  .main-head .hamburger { width: 44px; height: 44px; border-color: var(--line); }
  .hamburger svg { width: 20px; height: 20px; }
  .head-title { flex: 1 1 auto; min-width: 0; }
  .head-title h2 { font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .head-title p { display: none; }
  /* The series control is the one thing in this header that is pressed rather
     than read, so it gets the room: the tab name beside it truncates instead. */
  .head-series { margin-left: 0; flex: 1 1 52%; min-width: 46%; }
  .head-series-label { display: none; }
  /* SMALLER THAN THE 16px RULE ABOVE, ON PURPOSE.
     The label carries the style and both counts now - "Origin Rules
     (Photograph, S:3, E:1)" - and at 16px a phone shows about half of it.
     iOS zooms a focused control under 16px, but a <select> opens a native
     picker rather than a caret, so there is nothing to zoom into.
     44px tall because that is a fingertip; 40 was the whole header's height
     minus its padding, which left the control's edges touching the row. */
  .head-series-select {
    width: 100%; max-width: none; min-height: 44px;
    font-size: 13px !important; padding: .3rem 1.4rem .3rem .55rem;
    /* Room for the caret the phone draws inside the control, so a long series
       name cannot run underneath it and look like a mis-tap target. */
    background-image: none;
  }

  /* ---- series: one row you swipe ---- */
  #seriesbox, #ratesbox { flex: none; margin: 8px 8px 0 !important; padding: 8px 10px; }
  #ratesbox { max-height: 28vh; overflow: auto; }
  /* The heading stays on a phone now that it carries the fold toggle — hiding
     it would leave the panel shut with nothing to open it. It is the one line
     the panel costs while folded. */
  #seriesbox > .fold-h2 { display: block; }
  /* A fingertip, not a caret: this one line is the only way to reach the
     series cards on a phone, so it is a full-width 44px target. */
  #seriesbox > .fold-h2 .fold-head { min-height: 44px; font-size: 13px; }
  .series-grid { flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x proximity; padding-bottom: 4px; }
  .series-card { flex: none; min-width: 0; width: 44vw; scroll-snap-align: start; padding: .5rem .65rem; }
  .series-name, .series-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  /* ---- the workspace is a full screen below the header ---- */
  .workspace { flex: 1 1 auto; min-height: 0; margin-top: 8px; border-top: 1px solid var(--line); }
  .pane.active { flex-direction: column; width: 100%; }
  .pane-cols { position: relative; flex-direction: column; }
  .pane .col-mid, .pane .col-chat { flex: 1 1 auto; width: 100%; min-width: 0; }
  .mid-scroll { padding: 12px 12px 18px; overflow-x: auto; }
  .mid-scroll table { display: block; max-width: 100%; overflow-x: auto; }

  .mob-views {
    display: flex; flex: none; gap: 6px; padding: 6px 8px;
    background: var(--bg-elev); border-bottom: 1px solid var(--line);
    position: relative; z-index: 38;
  }
  .mob-view {
    flex: 1 1 0; min-width: 0; height: 42px; padding: 0 8px;
    border-radius: 10px; border: 1px solid var(--line);
    background: var(--bg-elev-2); color: var(--text-dim);
    font: inherit; font-size: 13px; font-weight: 600;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
  }
  .mob-view.active { background: var(--accent-soft); border-color: color-mix(in srgb,var(--accent) 50%,transparent); color: var(--text); }

  /* The side columns are full-screen views, shown only when chosen. Folding
     does not apply on a phone: the switch replaces both fold handles. */
  .pane > .col-list, .pane > .col-chats, .pane > .col-params,
  .pane-cols > .col-list, .pane-cols > .col-chats, .pane-cols > .col-params {
    position: absolute; left: 0; right: 0; bottom: 0; top: 50px;
    width: auto !important; z-index: 37; box-shadow: none;
    border-left: 0; border-right: 0;
    display: none !important;
  }
  .pane-cols > .col-list, .pane-cols > .col-chats, .pane-cols > .col-params { top: 0; }
  .pane.mob-left > .col-list, .pane.mob-left > .col-chats,
  .pane.mob-left .pane-cols > .col-list, .pane.mob-left .pane-cols > .col-chats,
  .pane.mob-right > .col-params, .pane.mob-right .pane-cols > .col-params { display: flex !important; }
  .pane .reopen, .pane .col-fold { display: none !important; }
  /* What is behind a chosen view is out of reach anyway; hiding it keeps a
     finger, and a screen reader, from landing on it. */
  .pane.mob-left > .col-mid, .pane.mob-left > .col-chat,
  .pane.mob-right > .col-mid, .pane.mob-right > .col-chat,
  .pane.mob-left .pane-cols > .col-mid, .pane.mob-left .pane-cols > .col-chat,
  .pane.mob-right .pane-cols > .col-mid, .pane.mob-right .pane-cols > .col-chat { visibility: hidden; }
  /* The Script tab's strip is its own view ("Auto & queue"), so the middle
     keeps the whole screen instead of sharing it with twenty queue chips. */
  .pane.has-top > .pane-top { display: none; }
  .pane.mob-top > .pane-top {
    display: flex; position: absolute; left: 0; right: 0; top: 50px; bottom: 0;
    max-height: none; z-index: 37; overflow-y: auto;
  }
  .pane.mob-top > .pane-cols { visibility: hidden; }

  /* ---- the strip across the Script tab ---- */
  .pane-top { max-height: 32vh; overflow-y: auto; padding: 8px 10px; }
  .orders-line { gap: 8px 12px; font-size: 12px; }
  .orders-split { display: none; }
  .pane-top .order-row { flex-wrap: wrap; }
  .pane-top .order-check { font-size: 12.5px; }
  .pane-top .order-check input { width: 18px; height: 18px; }
  .pane-top .order-num { width: 60px; padding: 5px 6px; }
  .pane-top .order-now { padding: 6px 12px; font-size: 12px; }
  .queue-chip { max-width: 100%; font-size: 12px; padding: 3px 4px 3px 9px; }
  .queue-x { width: 28px; height: 28px; font-size: 16px; }

  /* ---- readable columns, fingers-sized controls ---- */
  .col-head { padding: 10px 12px; }
  .col-params .col-head { font-size: 11px; }
  .params-scroll { padding: 4px 14px 16px; }
  .pfield-label { font-size: 13px; }
  .pfield-help { font-size: 11.5px; }
  .pfield select, .pfield input[type="number"], .pfield input[type="text"], .pfield textarea { padding: 9px 10px; border-radius: 9px; }
  .switch .track { width: 40px; height: 22px; }
  .switch .track::after { width: 18px; height: 18px; }
  .switch input:checked + .track::after { transform: translateX(18px); }
  .btn-ghost { min-height: 40px; }
  /* 36px is under a fingertip. Every icon button on a phone is 40. */
  .icon-btn { width: 40px; height: 40px; }
  /* The small pill buttons in the lists and columns (Open, Delete, autopilot,
     reply actions) were 22-24px tall — under a fingertip. */
  .workspace button:not(.mob-view), .status-body button, .shelf-acts .chip { min-height: 34px; min-width: 34px; }
  .shelf-acts { gap: 8px; flex-wrap: wrap; }
  .proj-x { width: 30px; height: 30px; }
  .chat-item { padding-right: 40px; }
  .chat-menu-btn { opacity: 1; width: 32px; height: 32px; }   /* hover never happens on touch */
  .suggestions { grid-template-columns: 1fr; }
  .kv { grid-template-columns: 110px 1fr; }
  .thumb-controls .btn-row { margin-left: 0; }

  /* ---- status bar ---- */
  /* The home indicator sits over the last few pixels of the window; without
     this the folded line and STOP PROCESS end up underneath it. */
  .statusbar { padding-bottom: env(safe-area-inset-bottom, 0px); }
  .status-head { min-height: 44px; padding: 6px 12px; padding-right: 128px; gap: 8px; }
  .status-now, .status-count { display: none; }
  /* Pinned to the folded line: top:50% of an OPEN bar put it over the log. */
  .status-stop { top: 21px; right: 8px; padding: 8px 12px; font-size: 11px; }
  .sq-row { flex-wrap: wrap; row-gap: 0; }
  .sq-who { flex: 1 1 auto; min-width: 0; max-width: none; }
  .sq-stage { flex-basis: 100%; padding-left: 32px; white-space: normal; }
  .sfarm-queue { margin-left: 8px; }
  .statusbar.open .status-body { max-height: 62dvh; }
  .status-tools { flex-wrap: wrap; gap: 8px; padding: 8px 12px; }
  .status-tools .btn-ghost { margin-left: 0; }
  .sf { padding: 7px 12px; font-size: 12.5px; }
  .sjob { flex-wrap: wrap; }
  .sjob .sj-bar { width: 100%; order: 9; }
  .sjob .sj-x { width: 32px; height: 32px; }
  .slog .ss { display: none; }

  /* ---- dialogs ---- */
  .modal-back { padding: 8px; }
  .modal { width: 100%; max-height: calc(100dvh - 16px); border-radius: 16px; }
  .modal-head { padding: 12px 14px; }
  .modal-body { padding: 12px 14px 16px; }
  .modal-foot { padding: 10px 14px 14px; flex-wrap: wrap; }
  .modal-close { width: 40px; height: 40px; }
}

/* 13. Auto Upload - Combined: finished episodes | upload queue. One column on a phone. */
.au-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
@media (max-width: 820px), (max-height: 500px) { .au-grid { grid-template-columns: 1fr; } }

/* ---- MovieMaker brand (2026-09-29): cinema crimson ----------------------- */
/* colours: site/app-theme.css (generated from shared/site/brands.php) */
.auth-logo-img { width: 46px; height: 46px; border-radius: 12px; flex: none; }

/* ---- accounts: terms tick, Google button, links (2026-09-29) ------------- */
.terms-check { display: flex; gap: 10px; align-items: flex-start; margin: 4px 0 2px; font-size: 13.5px; line-height: 1.45; color: var(--text-dim); cursor: pointer; }
.terms-check input { width: 18px; height: 18px; margin-top: 1px; flex: none; accent-color: var(--accent); }
.terms-check a, .auth-links a { color: var(--accent); }
.or-sep { display: flex; align-items: center; gap: 12px; color: var(--text-faint); font-size: 12.5px; margin: 14px 0; }
.or-sep::before, .or-sep::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.btn-google { width: 100%; display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 42px; border-radius: 8px;
  border: 1px solid var(--line); background: #fff; color: #1f1f1f; font: 600 14px system-ui, sans-serif; cursor: pointer; }
.btn-google:hover { background: #f3f4f6; }
.auth-links { display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 13px; margin-top: 12px; }
.auth-sub { margin: -4px 0 14px; color: var(--text-dim); font-size: 14px; }
.rail-links { display: block; font-size: 11.5px; margin-top: 2px; }
.rail-links a { color: var(--text-dim); text-decoration: none; } .rail-links a:hover { color: var(--accent); }
.acct-sec { border-top: 1px solid var(--line); padding-top: 16px; margin-top: 16px; }
.acct-sec h2 { font-size: 15px; margin: 0 0 10px; color: var(--text); }
.acct-links { display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 13px; margin: 0 0 6px; }
.acct-links a, .acct-sec a { color: var(--accent); }
.acct-inline { margin: -6px 0 0; }
.btn-link { background: none; border: 0; padding: 0; color: var(--accent); font: inherit; font-size: 13px; cursor: pointer; text-decoration: underline; }

/* Choose-a-plan strip (shared/account/billingflow.php bf_banner) */
.plan-banner { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 12px 0; padding: 12px 16px; border-radius: 12px; border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); background: color-mix(in srgb, var(--accent) 12%, transparent); font-size: 14.5px; }
.plan-banner.warn { border-color: color-mix(in srgb,var(--warn) 45%,transparent); background: color-mix(in srgb,var(--warn) 12%,transparent); }
.plan-banner-btn { display: inline-block; padding: 8px 14px; border-radius: 8px; background: var(--accent); color: var(--accentInk); font-weight: 600; text-decoration: none; white-space: nowrap; }

/* ---- Settings: credentials and the folded price book (2026-09-30) -------- */
details.fold { border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-elev); margin: 18px 0 12px; }
details.fold > summary { list-style: none; cursor: pointer; padding: 12px 16px; display: flex; align-items: baseline; gap: 12px; user-select: none; }
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary::before { content: "▸"; color: var(--text-dim); font-size: 12px; }
details.fold[open] > summary::before { content: "▾"; }
details.fold .fold-title { font-size: 16px; font-weight: 600; }
details.fold .fold-hint { font-size: 12px; color: var(--text-faint); }
details.fold > .note, details.fold > .key-card { margin: 0 16px 14px; }
details.fold > .key-card { background: transparent; }
.creds .key-row .chip { white-space: nowrap; }
.creds .key-row select { background: var(--bg-input); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; font-size: 12.5px; color: inherit; max-width: 260px; }
.creds .pfield-help a { color: inherit; text-decoration: underline; }
.cred-result { font-size: 12px; margin: 0 0 10px; min-height: 0; }
.cred-result.bad { color: var(--bad-text); }

/* =========================================================================
   THE PUBLIC SITE'S LOOK (2026-09-30)
   Colours come from /site/app-theme.css, generated from shared/site/brands.php
   - the same crimson palette the homepage uses, in dark and light, switched by
   the same 'av-theme' choice (site/theme.js). Here only the type and shapes:
   Inter for text, Bricolage Grotesque for names and headings, pill buttons.
   ========================================================================= */
html, body { font-family: var(--ui, var(--font)); }
.head-title h2, .auth-brand h1, .rail-title, .modal-head h3, .panel > h2, .fold-title,
details.fold .fold-title, .acct-sec h2 { font-family: var(--display, inherit); letter-spacing: -.01em; }
a { color: var(--accent-text, var(--accent)); }
input[type=checkbox], input[type=radio], input[type=range], progress { accent-color: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.rail-logo-img { width: 34px; height: 34px; border-radius: 10px; flex: none; display: block; }
.rail-title { font-size: 16px; font-weight: 700; }
.tab.active { border-color: var(--accent-line); }
.tab.active .tab-icon { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); }
.main-head { background: color-mix(in srgb, var(--bg) 84%, var(--surface)); }
.main-head > .theme-toggle { flex: none; }
.head-badges + .theme-toggle { margin-left: 4px; }

.btn-ghost { border-radius: 999px; }
.btn-ghost:hover { background: var(--hover-strong); }
.btn-inline, .btn-sm { border-radius: 999px; }
.btn-danger { border-radius: 999px; }

.auth-card { border-radius: 22px; }
.auth-body { background: radial-gradient(ellipse 80% 55% at 50% -10%, var(--glow), transparent 70%), var(--bg); background-attachment: fixed; }
.theme-float { position: fixed; top: 14px; right: 14px; z-index: 10; width: 42px; height: 42px; background: var(--surface); }
.plan-banner-btn { border-radius: 999px; }

@media (max-width: 900px), (max-height: 500px) {
  .main-head > .theme-toggle { width: 40px; height: 40px; }
}
@media (max-width: 900px), (max-height: 500px) {
  /* Account · Billing were 14px-tall text links: finger-sized hit area, same look. */
  .rail-links a { display: inline-block; padding: 10px 4px; margin: -8px 0; }
}

/* Sign-in / sign-up: the links under the form are standalone controls and were
   16-20px tall; the terms links broke across two lines on a phone. */
.auth-links a, .auth-foot a { display: inline-block; padding: 10px 2px; margin: -8px 0; white-space: nowrap; }
.terms-check a { white-space: nowrap; }
/* Touch screens: the column fold button and the Series fold line were 21px. */
@media (pointer: coarse) {
  .col-fold { min-width: 36px; min-height: 36px; }
  .fold-head { min-height: 40px; }
}
.switch { min-height: 32px; }
