/* Tokens are DECISIONS, see web/DESIGN.md before changing. Dark-first, near-black
   (never #000), hairline white-alpha lines, ONE accent, functional-only status colors.
   Palette unified with the vodsmith.com landing system, 2026-08-13: the app is the
   product the landing sold, so surfaces and the mint accent match exactly. */
:root {
  --bg: #08090b;
  --bg-2: #0b0d11;
  --panel: #0e1013;
  --panel-2: #14171b;
  --panel-3: #1a1e23;
  --line: rgba(255, 255, 255, 0.09);
  --line-strong: rgba(255, 255, 255, 0.16);
  --border: var(--line-strong);
  --text: #edeef0;
  --fg: var(--text);
  --ink: var(--text);              /* was read but never defined (audit 2026-09-10) */
  --text-2: #b3b9c0;               /* secondary text, brighter than --muted for small sizes */
  --muted: #9ba1a8;
  --muted2: #6b7280;
  --faint: #6b7280;
  --accent: #2ee6a6;
  --accent-wash: color-mix(in srgb, var(--accent) 8%, transparent);   /* selected surfaces */
  --accent-edge: color-mix(in srgb, var(--accent) 40%, transparent);  /* selected edges, focus ring */
  --accent-dim: var(--accent-wash);
  --accent-ink: #062017; /* text on accent fills: 10.6:1 (white on this mint is 1.6:1, refused) */
  --good: #5fc98a;
  --success: var(--good);          /* the SEMANTIC success token: ask for meaning, not for green */
  --ok: var(--good);
  --bad: #ff5a5a;
  --err: var(--bad);
  --warn: #d9a13b;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  /* v2 TYPE RUNGS (B2, 2026-09-10): explicit px, the root stays 15px. Every font-size in
     this file is one of these; nothing under --fs-lane, and --fs-lane only on the timeline. */
  --fs-title: 26px;      /* page title */
  --fs-section: 17px;    /* section title, card name */
  --fs-body: 15px;       /* body, descriptions */
  --fs-control: 14px;    /* buttons, inputs, tabs, rows */
  --fs-secondary: 13px;  /* metadata, hints, fine print */
  --fs-micro: 12px;      /* badges, pills, eyebrows */
  --fs-lane: 11px;       /* timeline lane labels and chips ONLY */
  --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600;
  font-size: 15px;   /* STAYS 15 (v2): 177 of 192 rem uses are font sizes; the root moves only when none remain */

  /* v2 (2026-09-10): four surface LEVELS (structure) and separate STATES (interaction).
     A surface change separates; a hairline is used only where two same-level surfaces touch. */
  --surface-1: var(--panel);       /* sidebar, rails, editor chrome */
  --surface-2: var(--panel-2);     /* panels, cards */
  --surface-3: var(--panel-3);     /* controls, raised rows */
  --surface-4: #21262c;            /* overlays: menus, popovers, dialogs (highest elevation) */
  --surface-hover: color-mix(in srgb, var(--text) 6%, transparent); /* a STATE laid over any surface */
  --well: var(--bg-2);             /* input wells */
  --video-bed: #000;               /* the ONLY pure black: the letterbox behind video */
  --glass: rgba(14, 17, 22, 0.86); /* the one translucent chrome fill (topbar, editor bars, floating pills) */
  /* black washes by ROLE, each at the value it shipped with (B1 tokenizes, it does not
     re-tune states the four baseline screens never reach) */
  --scrim-modal: rgba(0, 0, 0, 0.55);   /* dialog backdrops, the idle Play disc */
  --scrim-heavy: rgba(0, 0, 0, 0.72);   /* the music modal, the pressed Play disc, the player tooltip */
  --scrim-chip: rgba(0, 0, 0, 0.62);    /* on-video chips and small buttons */
  --scrim-soft: rgba(0, 0, 0, 0.5);     /* the "Press Play" hint */
  --scrim-label: rgba(0, 0, 0, 0.8);    /* on-video labels and their text shadow */
  --player-fade: rgba(0, 0, 0, 0.85);   /* the controls gradient at the bottom of the player */
  --wash-dark: rgba(0, 0, 0, 0.4);      /* the duck tag */
  --wash-faint: rgba(0, 0, 0, 0.18);    /* the status pill */
  --video-shade: rgba(0, 0, 0, 0.25);   /* the facecam region picker shade */
  --lane-recessed: rgba(0, 0, 0, 0.14); /* the recessed gameplay (VOD) lane */
  --shadow-overlay: 0 12px 32px rgba(0, 0, 0, 0.5);  /* overlays only */
  --shadow-marker: 0 1px 3px rgba(0, 0, 0, 0.45);  /* marker legibility (playhead grip): semantic, not elevation */
  --shadow-clip: 0 5px 18px rgba(0, 0, 0, 0.22);  /* EDITOR EXCEPTION: the raised clip and editor bar, at the shipped value */
  --scrub-grip: rgba(255, 255, 255, 0.3);
  --scrub-grip-hover: rgba(255, 255, 255, 0.55);
  --lane-wash: rgba(255, 255, 255, 0.03);            /* timeline lane backgrounds */
  --border-subtle: rgba(255, 255, 255, 0.065);       /* the editor's quieter hairline */
  --border-subtle-hc: rgba(255, 255, 255, 0.22);     /* its prefers-contrast: more value */
  --playhead: #ff6b5e;

  /* Semantic lane colours: colour is INFORMATION on the timeline (as in Premiere/Resolve),
     so these are functional tokens outside the one-chrome-accent rule. Values are the ones
     the editor already shipped; B1 tokenizes, it does not recolour. */
  --lane-video: #3d7f96;
  --lane-gameplay: #2f6a5f;
  --lane-music: #6f63b8;           /* a restrained purple: banned as chrome, kept as data */
  --lane-overlay: #96803d;
  --lane-audio: #8a7f5a;
  --clip-video: #1a5850;  --clip-video-2: #113f3a;
  --clip-compound: #2a7d54;  --clip-compound-2: #1a5a3a;
  --clip-overlay: #6b5322;  --clip-overlay-2: #4a3a18;  --clip-overlay-edge: #caa64a;
  --clip-vod: #152a30;  --clip-vod-edge: #24444d;
  --clip-music: #241f42;  --clip-music-edge: #3a3260;  --clip-music-ink: #b9adf7;
  --clip-music-deep: rgb(35, 27, 69);
  --clip-sfx: #2a2418;  --clip-sfx-edge: #4a4028;
  --duck-wash: rgba(10, 6, 24, 0.38);  --duck-wash-hover: rgba(10, 6, 24, 0.5);
}

/* ===== v2 PRIMITIVES (B3, 2026-09-10): one rule per control. Old class names are kept as
   aliases in these selector lists so no render site changes. Editor metrics are preserved
   by the .ed2 overrides below (frozen geometry). ===== */

/* text fields: one well, one edge, one focus ring (five styles before) */
input:where(:not([type]), [type="text"], [type="url"], [type="email"], [type="password"], [type="search"], [type="number"]),
select, textarea {
  background: var(--well); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: 8px;
  padding: 0 12px; font: inherit; font-size: var(--fs-control); line-height: 34px;
  height: 36px; box-sizing: border-box;          /* deterministic: 36px, not padding + inherited line-height */
}
select { padding-right: 28px; }
textarea { height: auto; min-height: 72px; padding: 8px 12px; line-height: 1.45; }
input:where(:not([type]), [type="text"], [type="url"], [type="email"], [type="password"], [type="search"], [type="number"]):focus-visible,
select:focus-visible, textarea:focus-visible {
  outline: none; border-color: var(--accent-edge); box-shadow: 0 0 0 2px var(--accent-edge);
}

/* .pill: 24px, --fs-micro, tones by meaning (six implementations before) */
.pill, .chip, .credits-chip, .ed-pill, .row-owner, .key-warning, .engine-card .ec-badge {
  display: inline-flex; align-items: center; height: 24px; padding: 0 10px; box-sizing: border-box;
  border-radius: 999px; border: 1px solid var(--line); background: transparent;
  color: var(--muted); font-size: var(--fs-micro); font-weight: 500; letter-spacing: 0.02em;
  white-space: nowrap; line-height: 1;
}
.pill.ok, .ed-pill.ok { color: var(--success); border-color: color-mix(in srgb, var(--success) 40%, transparent); background: color-mix(in srgb, var(--success) 8%, transparent); }
.pill.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.pill.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.pill.quiet { color: var(--muted); }

/* .card: a surface, not an outline (five byte-equivalent panels before). Editor panels keep
   their hairline until the editor page pass. */
.card, .ph-card, .expired-panel, .video-row, .plan-card {
  background: var(--surface-2); border: 1px solid transparent; border-radius: 12px;
}

/* .option-card: rest = surface-2 + hairline; selected = wash + edge; preferred = the same wash */
.option-card, .engine-card, .mode-opt, .style-card {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 12px; color: var(--text);
}
.option-card:hover, .engine-card:hover:not([disabled]), .mode-opt:hover, .style-card:hover:not([disabled]) { border-color: var(--accent-edge); }
.option-card.selected, .mode-opt.on, .engine-card.primary, .style-card.sel { background: var(--accent-wash); border-color: var(--accent-edge); }

/* .menu: the overlay surface (three implementations before) */
.menu, .pbq-menu, .ed-menu, .ctx-menu {
  background: var(--surface-4); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow-overlay); padding: 6px;
}

/* .tab: the underline tab (two implementations before) */
.tab, .lib-tab, .mp-tab {
  background: none; border: 0; border-bottom: 2px solid transparent; color: var(--muted);
  font-size: var(--fs-control); font-weight: 500; padding: 5px 7px; cursor: pointer;
}
.tab.on, .lib-tab.on, .mp-tab.on { color: var(--text); border-bottom-color: var(--accent); }

/* .eyebrow: the section label */
.eyebrow { font-size: var(--fs-micro); font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }

/* .linklike: a button that reads as a link, anywhere (was styled under .plan-gate only) */
.linklike { background: none; border: 0; padding: 0; color: var(--accent); cursor: pointer; font: inherit; }

* { box-sizing: border-box; }

/* every native control wears the accent, and links are never browser-blue: a stray
   default-styled control is the loudest "unstyled" tell in a token-disciplined view */
input[type="range"], input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }
a { color: var(--accent); }

/* keyboard focus is VISIBLE, pointer focus stays quiet — :focus-visible only.
   (`.ctx-menu button { all: unset }` and friends must not strip this.) */
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.45;
}

.app-header, .topbar {   /* DESIGN.md calls this .app-header; .topbar is the implementation name */
  min-height: 56px; box-sizing: border-box;   /* deterministic: 56px whatever its controls are */
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 28px;
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  background: var(--glass);
  backdrop-filter: blur(16px) saturate(125%);
  -webkit-backdrop-filter: blur(16px) saturate(125%);
  z-index: 10;
}

h1, h2, .section-title { letter-spacing: -0.02em; }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-section);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  text-decoration: none;
}
.brand .logo-mark {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: var(--accent);
  display: grid;
  place-items: center;
  color: var(--accent-ink);
  flex: none;
}
.brand .logo-mark svg { width: 12px; height: 12px; display: block; }
.key-warning { margin-left: auto; color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.lang-switch { align-self: center; font-size: var(--fs-secondary); }
.lang-switch, .gen-sel, .music-select {
  appearance: none;
  -webkit-appearance: none;
  /* the chevron stroke is --muted (#9ba1a8) copied into the data URI: a <select> cannot
     host a pseudo-element, so this is the ONE documented literal outside :root */
  background: var(--well) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ba1a8' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 8px center / 14px;
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 0 28px 0 10px;
  cursor: pointer;
  transition: border-color 0.14s ease;
}
.lang-switch:hover, .gen-sel:hover, .music-select:hover { border-color: var(--line-strong); }
/* the header's language control is quiet: transparent box, chevron kept. AFTER the shared
   select rule on purpose (equal specificity: source order decides; B3 review) */
.topbar .lang-switch { height: 28px; line-height: 26px; padding: 0 28px 0 10px; background-color: transparent; border-color: transparent; }
.topbar .lang-switch:hover { border-color: var(--line); }

/* ---------- app shell: sidebar + main ---------- */
.shell { display: flex; min-height: calc(100vh - 120px); }
.sidebar {
  width: 208px;
  flex: none;
  padding: 22px 14px;
  background: var(--surface-1);   /* v2: the sidebar is a surface, not an outlined void */
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.side-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  border-radius: 12px;
  text-decoration: none;
  color: var(--muted);
  border: 1px solid transparent;
}
.side-row:hover { background: var(--panel); color: var(--text); }
.side-row .sr-name { font-size: var(--fs-control); font-weight: 600; }
.side-row .sr-sub { font-size: var(--fs-secondary); }
/* the flagship row is the visually heaviest element in the rail */
.side-row.flagship .sr-name { font-size: var(--fs-body); font-weight: 600; }
.side-row.active {
  background: var(--accent-dim);
  color: var(--text);
  border-color: var(--line);
}
.side-row.active .sr-name { color: var(--accent); }
main { flex: 1; min-width: 0; max-width: 1180px; margin: 0 auto; padding: 28px; }
/* ---------- compact screens (PLAN_MOBILE.md, 2026-08-19) ----------
   Everything narrow-screen lives in THIS block, so the desktop layout above is
   provably untouched. THE BREAKPOINT IS 960px, shared with app.js (PHONE_MQ):
   phones in landscape are ~844-932 CSS px wide and must keep the phone
   experience, and a portrait tablet (768px) is a touch screen, not a mouse
   editor. Root cause of the launch-day phone screenshot: `.shell` becomes a
   COLUMN flex box here, and an item with `margin: 0 auto` in a column flex box
   is sized shrink-to-fit (not stretched), so `main` grew to its widest
   fixed-width child (the 560px intake card, a nowrap library row) and the page
   laid out at 630px on a 390px phone. Fix the widths; never `overflow-x: hidden`
   (that hides the symptom and blinds tests/browser/mobile_layout.py). */
@media (max-width: 960px) {
  .shell { flex-direction: column; min-height: calc(100dvh - 120px); }
  main { margin: 0; max-width: none; width: auto; padding: 16px; }
  /* header: brand left, everything else packed right; deterministic, no
     competing auto margins (.credits-chip and .account-btn carry their own
     desktop margins) */
  .topbar { padding: 10px 14px; gap: 10px; flex-wrap: wrap; }
  .brand { margin-right: auto; }
  .credits-chip, .account-btn, .lang-switch { margin-left: 0; }
  /* the nav is a horizontal tab strip that scrolls, never wraps a label */
  .sidebar { width: auto; flex-direction: row; border-right: 0; border-bottom: 1px solid var(--line);
    padding: 10px 14px; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .side-row { flex: none; }
  .side-row .sr-name { white-space: nowrap; }
  .side-row .sr-sub { display: none; }
  .feedback-open { width: auto; }        /* desktop rule is width: 100% (a rail row) */
  /* library */
  /* the intake card's phone rules live right after its grid rule (cascade order) */
  .video-row { flex-wrap: wrap; gap: 8px 12px; padding: 12px 14px; }
  .video-row .title { flex-basis: 100%; }
  .tw-vod { flex-wrap: wrap; }
  .tw-vod img, .tw-thumb-ph { width: 96px; height: 54px; }
  /* video page, pre-editor states */
  .page-head h1 { font-size: var(--fs-section); overflow-wrap: anywhere; }
  .job-steps, .status-line, .wiz-actions, .track-row, .win-inputs { flex-wrap: wrap; }
  .track-row audio { max-width: 100%; }
  .cost-callout, .wiz-sub, .wiz-legal { max-width: none; }
  /* iOS zooms the page when a focused control is under 16px */
  input, select, textarea { font-size: 16px; }
  /* the editor never renders at this width (renderEditor hands off to
     renderPhoneProject below 961px); these rules are a holding position for
     any non-editor page that reuses its bars */
  .ed-main { height: auto; min-height: 0; flex-wrap: wrap; }
  .ed-bar, .tl-toolbar, .below-player { flex-wrap: wrap; }
}
/* touch has no hover: the transport bar is always reachable (desktop/tablet
   editor; the phone page uses the browser's own <video> controls) */
@media (hover: none) {
  .player-ctrls { opacity: 1; pointer-events: auto; }
}

/* ---------- the phone project page (PLAN_MOBILE.md size B) ----------
   A finished project on a compact screen: the server-assembled preview.mp4
   (the same timeline through the same assembler as the export; the export
   itself is rendered separately from the full source) in the browser's own
   player (its scrub bar IS the scrubber), then, where the timeline would be,
   one card that says where editing happens and the things a phone is for:
   export/download, generate again, the small downloads. No timeline, no rail,
   no inspector: a picture of a timeline on a phone is a promise we cannot
   keep. */
.ph-project { display: flex; flex-direction: column; gap: 14px; }
.ph-player { width: 100%; aspect-ratio: 16 / 9; background: var(--video-bed); border-radius: 12px; display: block; }
.ph-pending { width: 100%; aspect-ratio: 16 / 9; border-radius: 12px; background: var(--panel);
  border: 1px solid var(--line); display: flex; align-items: center; justify-content: center;
  gap: 10px; color: var(--muted); font-size: var(--fs-control); padding: 16px; text-align: center; }
.ph-card { padding: 16px; }
.ph-card p { margin: 0 0 12px; }
.ph-actions { display: flex; flex-direction: column; gap: 8px; }
.ph-actions .btn { width: 100%; text-align: center; padding: 11px 14px; }
.ph-status { min-height: 1.2em; font-size: var(--fs-secondary); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ph-more summary { cursor: pointer; color: var(--muted); font-size: var(--fs-secondary); margin-top: 4px; }
.ph-more .pv-link { display: block; padding: 8px 0; }
.hidden { display: none !important; }
.muted { color: var(--muted); }

/* ---------- library ---------- */
.intake { display: block; margin-bottom: 40px; }   /* C1 (founder, A): the intake spans the column */
.intake-card {
  width: 100%;
  text-align: left;
  /* C1: a two-part card, upload left, the Twitch connection right; one column at 960px */
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 32px; align-items: start;
  background: var(--panel);
  border: 1.5px dashed var(--line);
  border-radius: 12px;
  padding: 24px 28px;
  transition: border-color 0.15s;
}
.intake-card > h2 { grid-column: 1 / -1; font-size: var(--fs-title); letter-spacing: -0.02em; margin: 0 0 8px; }
.intake-card > .muted { font-size: var(--fs-body); color: var(--text-2); margin: 0 0 14px; }
.intake-card > .btn.primary { justify-self: start; width: auto; padding: 11px 20px; line-height: 16px; font-size: var(--fs-body); }
.intake-card > .fineprint { margin: 12px 0 0; }
.intake-card > .twitch-intake { grid-column: 2; grid-row: 2 / span 6; margin: 0; padding-left: 32px; border-left: 1px solid var(--line); align-self: stretch; }
.intake-card.dragover { border-color: var(--accent); background: var(--panel-2); }
/* PHONES: ONE column. This block must come AFTER the grid rule above: the shared 960px block
   earlier in the file has the same specificity and LOST the cascade, so phones got the
   two-column card with the Twitch connection crushed into a 160px column (founder's phone,
   2026-09-11). */
@media (max-width: 960px) {
  .intake-card { display: block; width: auto; padding: 22px 16px; }
  .intake-card > h2 { font-size: var(--fs-section); }
  .intake-card > .twitch-intake { padding-left: 0; border-left: 0; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
  .tw-connected { flex-wrap: wrap; row-gap: 8px; }
}
.or { color: var(--muted); font-size: var(--fs-micro); margin: 18px 0 10px; }
.url-row { display: flex; gap: 8px; }
.url-row input { flex: 1; }
.fineprint { color: var(--muted); font-size: var(--fs-secondary); margin: 14px 0 0; }

.section-title { font-size: var(--fs-section); color: var(--text); font-weight: 600; margin: 0 0 12px; }
.video-list { display: flex; flex-direction: column; gap: 10px; }
.video-row {
  /* C1 row grammar: line 1 = title, then status and actions at the right; a zero-height 100%
     pseudo forces the break; line 2 = the metadata joined with dots. Pure CSS over the
     flat span markup refreshLibraryList renders. */
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 12px; row-gap: 4px;
  padding: 12px 16px;
  cursor: pointer;
  transition: background 0.12s;
}
.video-row:hover { background: color-mix(in srgb, var(--text) 6%, var(--surface-2)); }
.video-row .title { order: 0; flex: 1 1 200px; min-width: 0; font-size: var(--fs-body); font-weight: 600; }
.video-row .chip, .video-row .row-dl, .video-row .row-ren, .video-row .row-del { order: 1; }
.video-row::before { content: ""; order: 2; flex-basis: 100%; height: 0; }
.video-row .meta { order: 3; color: var(--muted); font-size: var(--fs-secondary); }
.video-row .meta:empty { display: none; }
.video-row .meta + .meta:not(:empty)::before { content: "·"; color: var(--faint); margin-right: 12px; }

.chip { font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }   /* status chips shout; expiry chips opt out below */
.chip.processing, .chip.downloading, .chip.queued, .chip.rendering {
  color: var(--accent);
  border-color: var(--accent-dim);
}
.chip.awaiting_review { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.chip.done { color: var(--good); border-color: color-mix(in srgb, var(--good) 35%, transparent); }
.chip.error { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, transparent); }
/* the game count in words beside the price and Start (2026-08-27) */
.qp-games { color: var(--muted); font-size: var(--fs-micro); font-weight: 500; margin-left: 4px; }
.wiz-selection { color: var(--muted); font-size: var(--fs-secondary); align-self: center; }
/* project lifecycle (2026-08-28): the 14-day window, escalating tone */
.chip.expiry-ok { text-transform: none; letter-spacing: 0; font-weight: 600; }
.chip.expiry-soon { text-transform: none; letter-spacing: 0; font-weight: 600; color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.chip.expiry-urgent { text-transform: none; letter-spacing: 0; font-weight: 600; color: var(--bad); border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
.chip.expiry-expired { text-transform: none; letter-spacing: 0; font-weight: 600; color: var(--muted); border-style: dashed; }
.row-dl { color: var(--accent); font-size: var(--fs-secondary); white-space: nowrap; }
.expiry-banner { background: color-mix(in srgb, var(--warn) 14%, var(--panel)); border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent); border-radius: 10px; padding: 10px 14px; margin: 0 0 12px; font-weight: 600; }
.expiry-banner.urgent { background: color-mix(in srgb, var(--bad) 12%, var(--panel)); border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
.expired-panel { padding: 18px 20px; max-width: 640px; }
.expired-panel .expired-lead { font-weight: 600; font-size: var(--fs-body); margin: 0 0 6px; }
.expired-panel .btn { margin: 8px 0 4px; display: inline-block; }
.expiry-modal { border: 1px solid var(--line); border-radius: 14px; background: var(--panel); color: var(--text); padding: 22px 24px; max-width: 460px; }
.expiry-modal::backdrop { background: var(--scrim-modal); }

/* ---------- video page ---------- */
.crumb { color: var(--muted); text-decoration: none; font-size: var(--fs-secondary); }
.crumb:hover { color: var(--text); }
.page-head { display: flex; align-items: center; gap: 14px; margin: 10px 0 18px; flex-wrap: wrap; }
.page-head h1 { margin: 0; font-size: var(--fs-section); }
.page-head .spacer { flex: 1; }

.status-line {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 16px;
  margin-bottom: 18px;
}
.spinner {
  width: 14px; height: 14px;
  border: 2px solid var(--accent-dim);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.progress {
  height: 6px;
  background: var(--panel-2);
  border-radius: 999px;
  overflow: hidden;
  margin: -8px 0 14px;
}
.progress-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.6s ease;
}
.progress-meta {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-secondary);
  color: var(--muted);
  margin: -8px 0 14px;
}

.error-box {
  background: color-mix(in srgb, var(--bad) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--bad) 40%, transparent);
  border-radius: 12px;
  padding: 14px 16px;
  white-space: pre-wrap;
  font-family: ui-monospace, monospace;
  font-size: var(--fs-micro);
  margin-bottom: 16px;
  max-height: 220px;
  overflow: auto;
}

.run-choice { display: flex; gap: 12px; margin: 18px 0 6px; flex-wrap: wrap; }
.run-choice .btn { display: inline-flex; align-items: center; gap: 8px; }
.rc-sub {
  font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  opacity: 0.75; padding: 2px 7px; border-radius: 999px; background: var(--wash-faint);
}
.find-hl { width: 100%; margin-top: 10px; }

.cost-callout {
  background: var(--panel);
  border: 1px solid var(--accent-dim);
  border-radius: 12px;
  padding: 12px 16px;
  margin: 14px 0;
  font-size: var(--fs-control);
  max-width: 620px;
}
.cost-callout b { color: var(--accent); }
.cost-callout.warn { border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.cost-callout.warn b { color: var(--warn); }

/* ---------- editor (CapCut layout) ---------- */
.ed { display: flex; flex-direction: column; gap: 10px; }
.ed-top { display: flex; gap: 12px; height: 52vh; min-height: 360px; }

.media-panel {
  width: 240px;
  flex: none;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 12px 14px;
  overflow-y: auto;
  position: relative;
  transition: width 0.18s ease, padding 0.18s ease;
}
/* collapsed: a thin rail with one expand affordance; the timeline gets the width back */
.media-panel.collapsed { width: 34px; padding: 8px 4px; overflow: hidden; }
.media-panel.collapsed .mp-head, .media-panel.collapsed .mp-body { display: none; }
.mp-head { display: flex; align-items: center; margin-bottom: 6px; }
.mp-head-label {
  font-size: var(--fs-micro); color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.06em; font-weight: 600;
}
.mp-collapse, .mp-expand {
  background: transparent; border: 1px solid var(--line); border-radius: 6px;
  color: var(--muted); cursor: pointer; font-size: var(--fs-micro); padding: 0 7px; line-height: 1.4;
}
.mp-collapse { margin-left: auto; }
.mp-collapse:hover, .mp-expand:hover { color: var(--text); border-color: var(--line-strong); }
.mp-expand { display: block; margin: 0 auto; }
/* collapsible tool sections */
.mp-sec { border-top: 1px solid var(--line); }
.mp-sec:first-of-type { border-top: none; }
.mp-sec > summary {
  list-style: none; cursor: pointer; padding: 8px 0; display: flex; align-items: center;
  font-size: var(--fs-micro); color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.06em; font-weight: 600;
}
.mp-sec > summary::-webkit-details-marker { display: none; }
.mp-sec > summary::after { content: "›"; margin-left: auto; font-size: var(--fs-secondary); transition: transform 0.15s ease; }
.mp-sec[open] > summary::after { transform: rotate(90deg); }
.mp-sec > summary:hover { color: var(--text); }
.mp-sec .trans-shelf { margin-top: 0; padding-bottom: 10px; }
.mp-sec .media-list { margin-top: 4px; padding-bottom: 10px; }
.media-panel h2 { margin: 0 0 2px; font-size: var(--fs-control); }
.mp-tabs { display: flex; align-items: center; gap: 6px; }
.ed2 .mp-tab { font-size: var(--fs-micro); font-weight: 600; padding: 4px 2px; }
.mp-import { margin-left: auto; }
.mp-subtabs { display: flex; gap: 4px; margin-bottom: 4px; }
.mp-subtab {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--muted);
  border-radius: 6px; font-size: var(--fs-micro); padding: 2px 8px; cursor: pointer; text-transform: capitalize;
}
.mp-subtab.on { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
.media-item.import .mi-tag { color: var(--muted); }
.media-list { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.media-item {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 12px;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.media-item:hover { border-color: var(--accent); }
.media-item.cut .mi-tag { color: var(--accent); }

.media-item.reel .mi-tag { color: var(--muted); }
.mi-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.mi-title { font-weight: 600; font-size: var(--fs-control); }
.mi-tag { color: var(--muted); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.04em; }
.mi-sub { color: var(--muted); font-size: var(--fs-micro); margin-top: 3px; }

.drag-ghost {
  position: fixed; z-index: 1000; pointer-events: none;
  background: var(--accent); color: var(--accent-ink); font-weight: 600; font-size: var(--fs-micro);
  padding: 5px 10px; border-radius: 6px; box-shadow: var(--shadow-overlay);
}

.preview-pane { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.player-wrap {
  /* the player NEVER collapses: side content (brief report, disclaimers) scrolls in its
     own box instead of eating the video's flex space (the 7/20 vanishing-preview bug) */
  position: relative; flex: 1; min-height: 240px;
  background: var(--video-bed); border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
}
/* BOTH surfaces stay MOUNTED (always display:block) and stacked on top of each other; we switch
   which is VISIBLE with opacity — never display:none/hidden. Why: calling player.play() on a
   display:none <video> stays pending forever on real Chrome until it becomes a visible rendering
   surface (entering fullscreen "woke" it) — the deadlock this replaces. display:block overrides the
   UA [hidden]{display:none}, so the <video> is always a live, playable surface. DOM order is
   video, canvas, then overlays, so the canvas sits above the video and the controls above both. */
.player-wrap > video, .player-wrap > #reelCanvas {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: contain;
}
.player-wrap > #reelCanvas { opacity: 1; background: var(--video-bed); }   /* canvas visible while paused/editing */
.player-wrap > video { opacity: 0; }                            /* mounted + decodable, behind the canvas */
.player-wrap.video-live > #reelCanvas { opacity: 0; }
.player-wrap.video-live > video { opacity: 1; }                 /* native video after playback starts */
.player-ctrls {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: 4px; padding: 18px 12px 9px;
  background: linear-gradient(transparent, var(--player-fade));
  opacity: 0; transition: opacity 0.2s; pointer-events: none;
}
/* Show on hover, and whenever the video is paused; hidden while playing so they
   stay out of the way (including in fullscreen). */
.player-wrap:hover .player-ctrls,
.player-wrap.ctl-hot .player-ctrls,
.player-wrap.paused .player-ctrls { opacity: 1; pointer-events: auto; }
.pc-btn {
  background: transparent; border: none; color: var(--text); cursor: pointer;
  font-size: var(--fs-body); width: 30px; height: 30px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
}
.pc-btn:hover { background: var(--line-strong); }
.pc-play { font-size: var(--fs-section); }
.pc-vol { width: 68px; accent-color: var(--accent); cursor: pointer; }
.pc-time { font-family: var(--mono); font-size: var(--fs-micro); color: var(--text); margin-left: 6px; }
.pc-spacer { flex: 1; }
.pc-seek { flex: 1; min-width: 80px; height: 6px; align-self: center; background: var(--scrub-grip); border-radius: 999px; cursor: pointer; position: relative; }
.pc-seek:hover { height: 8px; }
.pc-seek-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--accent); border-radius: 999px; pointer-events: none; }
.pc-rate {
  appearance: none; -webkit-appearance: none; text-align: center;
  background: transparent; color: var(--text); border: 1px solid var(--scrub-grip);
  border-radius: 6px; font-size: var(--fs-micro); padding: 2px 6px; cursor: pointer;
}
.pc-rate option { color: var(--bg); }   /* native popup paints its own light ground */
/* EDITOR EXCEPTION (frozen transport geometry): .pc-rate is a <select> and would inherit the
   36px field primitive; its shipped compact size (padding 2px 6px) governs instead */
.ed2 .pc-rate { height: auto; line-height: normal; }
.pc-btn.on { background: var(--accent); color: var(--accent-ink); }
.player-empty, .player-busy { position: absolute; pointer-events: none; }
.player-empty {
  inset: 0; display: none; align-items: center; justify-content: center; text-align: center;
  color: var(--muted); font-size: var(--fs-control); padding: 24px;
}
.player-empty.show { display: flex; }
.player-busy {
  top: 10px; right: 10px; display: none; align-items: center; gap: 6px;
  background: var(--scrim-heavy); color: var(--text); padding: 5px 10px; border-radius: 6px; font-size: var(--fs-micro);
}
.player-busy.show { display: flex; }
.player-buffer {
  position: absolute; pointer-events: none; z-index: 50; left: 50%; top: 50%; transform: translate(-50%,-50%);
  display: flex; align-items: center; gap: 8px;
  background: var(--scrim-chip); color: var(--text); padding: 8px 14px; border-radius: 8px; font-size: var(--fs-micro);
}
.player-buffer[hidden] { display: none; }
/* Full-cover only to CENTER the button; the container passes pointer events through
   so the transport bar stays usable before first play. Only .pi-btn is clickable. */
.player-idle {
  position: absolute; inset: 0; z-index: 55; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.player-idle[hidden] { display: none; }
.player-idle .pi-btn {
  pointer-events: auto; cursor: pointer; margin: 0; padding: 0; border: 0; background: transparent;
  color: var(--text); display: flex; flex-direction: column; align-items: center; gap: 12px;
}
.player-idle .pi-play {
  display: flex; align-items: center; justify-content: center;
  width: 66px; height: 66px; border-radius: 50%;
  background: var(--scrim-modal); transition: background .12s ease, transform .12s ease;
}
.player-idle .pi-play svg { width: 30px; height: 30px; fill: currentColor; }
.player-idle .pi-btn:hover .pi-play, .player-idle .pi-btn:focus-visible .pi-play {
  background: var(--scrim-heavy); transform: scale(1.05);
}
.player-idle .pi-text {
  font-size: var(--fs-micro); background: var(--scrim-soft); padding: 3px 11px; border-radius: 6px;
}
/* Playback-quality selector (preview quality, not export). Text label + drop-up menu. */
.pc-pbqual { position: relative; display: inline-flex; }
.pbq-btn, .ed2 .pc-btn.pbq-btn {
  width: auto; min-width: 60px; padding: 0 9px; font-size: var(--fs-micro); font-weight: 600;
  white-space: nowrap; border-radius: 999px;
}
.pbq-menu {
  position: absolute; bottom: calc(100% + 8px); right: 0; z-index: 60; min-width: 232px;
  display: flex; flex-direction: column; gap: 2px;
}
.pbq-menu[hidden] { display: none; }
.pbq-opt {
  text-align: left; background: transparent; border: 0; color: var(--text); font-size: var(--fs-micro);
  padding: 8px 10px; border-radius: 7px; cursor: pointer;
}
.pbq-opt:hover { background: var(--surface-hover); }
.pbq-opt.sel { background: var(--accent-wash); color: var(--text); }
.pbq-note {
  color: var(--muted); font-size: var(--fs-secondary); padding: 6px 10px 2px;
  border-top: 1px solid var(--line); margin-top: 4px;
}
.below-player { display: flex; align-items: center; gap: 14px; }
.below-player .pv-link, .below-player .tl-info-mini { white-space: nowrap; }
.below-player .btn { white-space: nowrap; }
.below-player .spacer { flex: 1; }
.tl-info-mini { color: var(--muted); font-size: var(--fs-micro); }
.pv-link { color: var(--muted); cursor: pointer; text-decoration: underline; font-size: var(--fs-micro); }
.pv-link:hover { color: var(--accent); }
.hd-note {
  cursor: pointer; font-size: var(--fs-secondary); color: var(--warn);
  white-space: nowrap;
}
.hd-note:hover { text-decoration: underline; }
.hd-note.hidden { display: none; }
.save-warn { font-size: var(--fs-micro); color: var(--warn); white-space: nowrap; }
.save-warn.hidden { display: none; }
#exportStatus { display: flex; align-items: center; gap: 10px; min-height: 22px; font-size: var(--fs-secondary); }
#exportStatus .good { color: var(--good); }
#exportStatus .bad { color: var(--bad); }
/* Determinate export bar (real remote encode progress). */
.export-prog { width: 140px; height: 6px; border: none; border-radius: 3px; background: var(--line); vertical-align: middle; }
.export-prog::-webkit-progress-bar { background: var(--line); border-radius: 3px; }
.export-prog::-webkit-progress-value { background: var(--accent); border-radius: 3px; }
.export-prog::-moz-progress-bar { background: var(--accent); border-radius: 3px; }

/* timeline */
.tl-panel {
  flex: none;
  height: 250px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative; /* anchors the floating on-clip bar */
}
/* on-clip contextual bar: volume / split / delete / story-why over the selected clip */
.clip-bar {
  position: absolute; z-index: 30;
  display: flex; align-items: center; gap: 10px;
  background: var(--panel-2); border: 1px solid var(--line-strong);
  border-radius: 8px; padding: 5px 10px;
  box-shadow: var(--shadow-overlay);
}
.clip-bar:not([hidden]) { animation: clip-bar-in 0.12s ease; }
@keyframes clip-bar-in { from { opacity: 0; transform: translateY(4px); } }
.cb-why {
  color: var(--muted); font-size: var(--fs-micro); max-width: 260px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-left: 1px solid var(--line); padding-left: 10px;
}
@media (prefers-reduced-motion: reduce) {
  .media-panel { transition: none; }
  .clip-bar:not([hidden]) { animation: none; }
  .mp-sec > summary::after { transition: none; }
}
.tl-toolbar { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--line); }
.tl-toolbar .spacer { flex: 1; }
.tl-clock { font-family: var(--mono); color: var(--accent); font-size: var(--fs-secondary); }

.tl-scroll { flex: 1; overflow: auto; }
.tl-canvas { position: relative; min-height: 100%; min-width: 100%; }
.tl-ruler { position: sticky; top: 0; z-index: 6; height: 22px; border-bottom: 1px solid var(--line); cursor: pointer; touch-action: none; background: var(--panel-2); }
.tl-ruler:hover { background: var(--panel); }
.tl-tick {
  position: absolute; top: 0; height: 20px; line-height: 20px;
  border-left: 1px solid var(--line); padding-left: 4px;
  color: var(--muted); font-size: var(--fs-lane); white-space: nowrap; pointer-events: none;
}
.tl-lanes { position: relative; padding: 4px 0; }
.tl-track {
  position: relative; height: 60px; margin-bottom: 4px; min-width: 100%;
  background: var(--lane-wash);
  border: 1px solid var(--line); border-radius: 6px;
}
.tl-track.audio-lane { height: 42px; }
.tl-track.drop-hot { border-color: var(--accent); background: var(--accent-dim); box-shadow: inset 0 0 0 1px var(--accent); }
.tl-dropmarker {
  position: absolute; width: 3px; background: var(--accent); z-index: 8;
  pointer-events: none; border-radius: 999px; box-shadow: 0 0 7px var(--accent);
}
.tl-clip {
  position: absolute; top: 6px; bottom: 6px;
  background: linear-gradient(180deg, var(--clip-video), var(--clip-video-2));
  border: 1px solid var(--accent-edge);
  border-radius: 6px; cursor: grab; overflow: hidden;
  display: flex; align-items: center; touch-action: none; user-select: none;
  font-size: var(--fs-lane);
}
.tl-clip .tc-title { color: var(--text-2); }
.tl-clip.compound { background: linear-gradient(180deg, var(--clip-compound), var(--clip-compound-2)); border-color: var(--good); }
/* the SELECTED clip must beat the transition markers (z 6): its trim grips are the
   promise of direct manipulation, and an invisible .tl-trans hotspot was swallowing
   pointer-downs on the grip's middle band (measured via elementFromPoint, 7/22) */
.tl-clip.sel { box-shadow: 0 0 0 2px var(--text); z-index: 7; }
.tl-clip.dragging { opacity: 0.85; z-index: 7; }
.tl-clip.audio { background: linear-gradient(180deg, var(--panel-2), var(--panel)); border-color: var(--line-strong); }
.tl-clip.audio .tc-wave { height: 100%; opacity: 0.55; }
.tl-track.overlay-lane { height: 46px; }

/* --- gain envelopes: the volume line + keyframes over every audio clip --- */
.tl-track.vod-lane { height: 46px; }
.tl-clip.vod-linked { cursor: default; }
.tc-env { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; pointer-events: none; overflow: visible; }
.tc-env .env-hit { fill: none; stroke: var(--bg); stroke-width: 11; opacity: 0; pointer-events: stroke; cursor: ns-resize; }
.tc-env .env-line { fill: none; stroke: var(--accent); stroke-width: 2; pointer-events: none; }
.tc-env .env-fill { fill: var(--accent); opacity: 0.14; pointer-events: none; }
.tc-env .env-dot { fill: var(--accent); stroke: var(--bg); stroke-width: 1; pointer-events: auto; cursor: grab; }
.tc-env .env-dot.auto { fill: var(--bg); stroke: var(--accent); }

/* --- simple audio surface: flat level line + duck regions (design v2) ---
   Calm by default: the duck is SHADING first; its line, grips, seams, and dB tag
   only assert themselves on hover/selection. Selection > hover > duck tint. */
.tc-level {
  position: absolute; left: 0; right: 0; height: 2px; z-index: 4;
  background: var(--text); opacity: 0.35;
  cursor: ns-resize; touch-action: none; transition: opacity 0.12s;
}
.tl-clip:hover .tc-level, .tc-level.dragging { opacity: 0.95; }
.tc-level::before { content: ""; position: absolute; left: 0; right: 0; top: -7px; bottom: -7px; }
.tc-level-badge {
  position: absolute; right: 4px; top: -17px; z-index: 5; pointer-events: none;
  font: 600 var(--fs-lane)/1.4 var(--mono); color: var(--text);
  background: var(--scrim-chip); padding: 1px 5px; border-radius: 4px;
  opacity: 0; transition: opacity 0.12s;
}
.tc-level.dragging > .tc-level-badge { opacity: 1; }
.tc-duck {
  /* above .tc-level (z 4): inside a duck section the section is what you grab —
     the bed-level line's fat hit area must not eat the region's clicks */
  position: absolute; top: 0; bottom: 0; z-index: 5; cursor: pointer;
  background: var(--duck-wash);
  border-left: 1px solid var(--line-strong);
  border-right: 1px solid var(--line-strong);
  transition: background 0.12s, border-color 0.12s;
}
.tc-duck:hover { background: var(--duck-wash-hover); border-color: var(--scrub-grip); }
.tc-duck.sel {
  background: var(--duck-wash-hover);
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
}
.tc-duck.own { border-left-style: dashed; border-right-style: dashed; }
.tc-duck-tag {
  position: absolute; left: 4px; top: 2px; pointer-events: none;
  font: 600 var(--fs-lane)/1.4 var(--mono); color: var(--text-2);
  background: var(--wash-dark); padding: 1px 4px; border-radius: 3px;
  opacity: 0; transition: opacity 0.12s;
}
.tc-duck.sel .tc-duck-tag, .tc-duck.wide:hover .tc-duck-tag { opacity: 1; }
.tc-duck-line {
  position: absolute; left: 0; right: 0; height: 2px; z-index: 6;
  background: var(--accent); opacity: 0; cursor: ns-resize; touch-action: none;
  transition: opacity 0.12s;
}
.tc-duck:hover .tc-duck-line, .tc-duck.sel .tc-duck-line, .tc-duck-line.dragging { opacity: 0.9; }
.tc-duck-line::before { content: ""; position: absolute; left: 0; right: 0; top: -6px; bottom: -6px; }
.tc-duck-line.dragging > .tc-level-badge { opacity: 1; }
.tc-duck-grip {
  position: absolute; top: 0; bottom: 0; width: 12px; z-index: 6; cursor: ew-resize;
  touch-action: none; opacity: 0; background: var(--accent); transition: opacity 0.12s;
}
.tc-duck-grip.l { left: -2px; border-radius: 3px 0 0 3px; }
.tc-duck-grip.r { right: -2px; border-radius: 0 3px 3px 0; }
.tc-duck:hover .tc-duck-grip, .tc-duck.sel .tc-duck-grip { opacity: 0.55; }
.duck-bar {
  position: absolute; z-index: 40; display: flex; align-items: center; gap: 8px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 8px; padding: 4px 8px; box-shadow: var(--shadow-overlay);
}
.duck-bar-db { font: 600 var(--fs-lane)/1.4 var(--mono); color: var(--accent); }
.duck-bar-btn {
  background: none; border: 1px solid var(--line); color: var(--fg);
  border-radius: 6px; padding: 3px 8px; font-size: var(--fs-lane); cursor: pointer;
}
.duck-bar-btn:hover { border-color: var(--accent); }
.lane-chips { position: sticky; left: 2px; z-index: 6; display: inline-flex; gap: 3px; align-items: center; padding: 2px 3px; width: max-content; pointer-events: none; }
.lane-chips .lane-chip { pointer-events: auto; }
.lane-chip {
  font-size: var(--fs-lane); line-height: 1; padding: 3px 5px; border-radius: 4px;
  background: var(--surface-hover); color: var(--muted);
  border: 1px solid var(--line); cursor: pointer;
}
.lane-chip.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.lane-label { font-size: var(--fs-lane); color: var(--muted); letter-spacing: 0.04em; padding-right: 2px; }
.tc-link {
  position: absolute; right: 4px; top: 3px; z-index: 4; pointer-events: none;
  font-size: var(--fs-lane); letter-spacing: 0.04em; color: var(--muted);
  background: var(--surface-hover); padding: 1px 4px; border-radius: 3px;
}
.tl-clip.overlay { background: linear-gradient(180deg, var(--clip-overlay), var(--clip-overlay-2)); border-color: var(--clip-overlay-edge); }

/* transitions: independent markers on the seam between two adjacent main clips */
.tl-trans {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  width: 20px; height: 20px; z-index: 6; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; border: 1px solid var(--line);
  background: var(--glass); color: var(--muted);
  font-size: var(--fs-lane); line-height: 1; opacity: 0.4;
  transition: opacity 0.12s, transform 0.12s, border-color 0.12s;
}
.tl-trans { opacity: 0; }
.tl-trans.active { opacity: 0.55; }
.main-lane:hover .tl-trans { opacity: 0.85; }
.tl-trans:hover { opacity: 1; transform: translate(-50%, -50%) scale(1.18); border-color: var(--accent); }
.tl-trans.active {
  opacity: 1; color: var(--accent-ink); background: var(--accent); border-color: var(--accent);
  box-shadow: 0 0 7px color-mix(in srgb, var(--accent) 60%, transparent);
}
.tl-trans .tt-ico { pointer-events: none; }

/* assets-panel transition shelf + draggable chip */
.trans-shelf { margin-top: 18px; }
.trans-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 6px; font-size: var(--fs-micro); cursor: grab; touch-action: none; user-select: none;
}
.trans-chip:hover { border-color: var(--accent); }
.trans-chip .tt-ico { color: var(--accent); }

/* transition edit popover */
.trans-pop {
  position: absolute; z-index: 40; width: 220px; padding: 12px;
  background: var(--panel); border: 1px solid var(--accent); border-radius: 12px;
  box-shadow: var(--shadow-overlay); font-size: var(--fs-micro); color: var(--text);
}
.tp-title { font-weight: 600; margin-bottom: 8px; }
.tp-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.tp-row input[type=range] { flex: 1; }
.tp-remove { width: 100%; }

/* sliver clips: controls would cover the whole block — selection must win */
.tl-clip.tiny .tc-del, .tl-clip.tiny .tc-zoom, .tl-clip.tiny .tc-grip { display: none; }

/* right-click context menu on timeline clips */
.ctx-menu {
  position: fixed; z-index: 60; min-width: 190px;
  display: flex; flex-direction: column;
}
.ctx-menu button {
  all: unset; box-sizing: border-box; width: 100%; padding: 7px 10px;
  font-size: var(--fs-micro); color: var(--text); border-radius: 6px; cursor: pointer;
}
.ctx-menu button:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* `all: unset` above nukes the focus outline — restore it for keyboard users */
.ctx-menu button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ctx-menu button:disabled { color: var(--muted); opacity: 0.5; cursor: default; }

.pip-box {
  position: absolute; z-index: 8; border: 2px solid var(--accent); border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 8%, transparent); cursor: move; touch-action: none; min-width: 24px; min-height: 16px;
}
.pip-handle {
  position: absolute; right: -7px; bottom: -7px; width: 14px; height: 14px;
  background: var(--accent); border: 2px solid var(--accent-ink); border-radius: 50%; cursor: nwse-resize;
}
.pip-bar {
  position: absolute; left: 0; top: -30px; display: flex; align-items: center; gap: 6px;
  background: var(--scrim-label); padding: 4px 8px; border-radius: 6px; white-space: nowrap;
  font-size: var(--fs-micro); color: var(--text);
}
.pip-bar input { width: 70px; accent-color: var(--accent); }
.pip-del { background: transparent; border: none; color: var(--bad); cursor: pointer; font-size: var(--fs-micro); }
.tc-thumbs {
  position: absolute; inset: 0; background-repeat: no-repeat; opacity: 0.32; pointer-events: none;
}
.tc-wave {
  position: absolute; left: 0; right: 0; bottom: 0; height: 42%;
  background-repeat: no-repeat; opacity: 0.85; pointer-events: none; mix-blend-mode: screen;
}
.tc-title {
  position: relative; z-index: 1;
  font-size: var(--fs-lane); font-weight: 600; padding: 0 8px; text-shadow: 0 1px 3px var(--scrim-label);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none;
}
.tc-del {
  position: absolute; top: 3px; right: 3px;
  width: 22px; height: 22px; line-height: 20px; text-align: center;
  background: var(--scrim-chip); color: var(--text); border: none; border-radius: 6px;
  cursor: pointer; font-size: var(--fs-body); opacity: 0; padding: 0; touch-action: none; z-index: 3;
  /* delete only exists on the SELECTED clip: an invisible × was swallowing the
     select-click on 44-50px clips (its 22px box covers their center) and deleting
     them. First click now always selects; ⌫ / context menu / clip bar still delete. */
  pointer-events: none;
}
.tc-del:hover { background: var(--bad); }
.tl-clip.sel .tc-del { opacity: 1; pointer-events: auto; }
.tc-grip {
  position: absolute; top: 0; bottom: 0; width: 8px; cursor: ew-resize;
  background: transparent; touch-action: none;
  /* z 4: above the × delete button (3), whose invisible corner overlapped the right
     grip and stole its pointer-downs (second click-thief found 7/22; first was the
     .tl-trans marker). The × keeps its 17px clear of the grip strip. */
  z-index: 4;
}
.tc-l { left: 0; } .tc-r { right: 0; }
/* free-audio trim handles (2026-09-15): the same affordance as the video grips */
.tl-clip.audio .ac-grip {
  position: absolute; top: 0; bottom: 0; width: 8px; cursor: ew-resize;
  background: transparent; touch-action: none;
  /* above the level/gain control (.tc-level) that covers the block, or the handles
     never receive the pointer-down (found by elementFromPoint on staging, 2026-09-15) */
  z-index: 20;
}
.tl-clip.audio .ac-l { left: 0; } .tl-clip.audio .ac-r { right: 0; }
.tl-clip.audio:hover .ac-grip { background: var(--scrub-grip); }
.tl-clip.audio .ac-grip:hover { background: var(--scrub-grip-hover); }
.tl-clip.audio.tiny .ac-grip { width: 5px; }
.tl-clip.audio.vod-linked .ac-grip { display: none; }
.tl-clip:hover .tc-grip { background: var(--scrub-grip); }
.tl-clip .tc-grip:hover { background: var(--scrub-grip-hover); }
.tl-playhead { position: absolute; top: 0; bottom: 0; width: 0; border-left: 2px solid var(--bad); z-index: 8; pointer-events: none; }
.tl-playhead::before {
  content: ""; position: absolute; top: 0; left: -7px;
  width: 14px; height: 11px; border-radius: 0 0 4px 4px;
  background: var(--bad); box-shadow: var(--shadow-marker);
}
/* real (not pseudo) grab handle so it works over the pointer-events:none playhead line */
.ph-grip {
  position: absolute; top: -2px; left: -10px;
  width: 20px; height: 17px; border-radius: 0 0 5px 5px;
  pointer-events: auto; cursor: ew-resize; z-index: 9;
}
.ph-grip:hover { background: var(--line-strong); }

/* highlights panel (below the timeline) */
.hl-panel { margin-top: 4px; }
.hl-head { font-size: var(--fs-control); font-weight: 600; margin: 8px 2px 10px; }
.hl-head .muted { font-weight: 400; font-size: var(--fs-micro); }
.hl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 10px; }
.hl-card {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 12px;
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.hl-card:hover { border-color: var(--line-strong); }
.hc-top { display: flex; align-items: baseline; gap: 8px; padding-right: 48px; }
.hc-n {
  background: var(--panel-2); color: var(--muted); font-weight: 600; font-size: var(--fs-micro);
  border: 1px solid var(--line-strong);
  min-width: 18px; height: 18px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.hc-title { font-weight: 600; font-size: var(--fs-secondary); }
.hc-why {
  color: var(--muted); font-size: var(--fs-micro); margin: 6px 0; line-height: 1.35;
  /* two-line truncation: the -webkit- pattern is what browsers actually
     implement today; the unprefixed `line-clamp` is the standardized name,
     declared alongside for the day the prefix is dropped */
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.hc-meta { font-size: var(--fs-secondary); color: var(--muted); }
.hc-cat { color: var(--muted); }
.hc-add {
  position: absolute; top: 8px; right: 8px;
  background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  border-radius: 6px; padding: 3px 8px; font-size: var(--fs-micro); cursor: pointer;
}
.hc-add:hover { border-color: var(--accent); }

.spinner.small { width: 12px; height: 12px; border-width: 2px; }
.btn.small { padding: 5px 10px; line-height: 16px; font-size: var(--fs-secondary); }   /* 28px tall */
.cost-note { color: var(--muted); font-size: var(--fs-secondary); margin-left: auto; }

.btn {
  display: inline-block;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--text);
  border-radius: 8px;
  padding: 7px 16px; line-height: 16px;     /* 32px tall */
  font-size: var(--fs-control);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.14s ease, background 0.14s ease, color 0.14s ease;
}
.btn.cta { padding: 11px 20px; line-height: 16px; font-size: var(--fs-body); }   /* 40px */
.ed2 .btn { padding: 9px 18px; line-height: normal; font-weight: 600; }           /* editor metrics frozen */
.ed2 .btn.small { padding: 5px 12px; line-height: normal; font-size: var(--fs-micro); }
.btn:hover { border-color: var(--line-strong); background: var(--panel-3); }
.btn.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
.btn.primary:hover { filter: brightness(1.06); background: var(--accent); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.reel-section { margin-top: 26px; }
.reel-section h2 { font-size: var(--fs-body); color: var(--muted); }
.cost-note { color: var(--muted); font-size: var(--fs-secondary); margin-left: auto; }

/* --- the Narrative Edit price (one engine — the tier picker is retired, 7/20) --- */
.quality-pick { margin: 18px 0 6px; }
.quality-pick .qp-label {
  font-size: var(--fs-micro); font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.06em; margin: 0 0 10px;
}
.qp-price { font-size: var(--fs-title); font-weight: 700; margin: 0 0 6px; }
.qp-balance { margin-top: 8px; }
.qp-balance.short { color: var(--warn); }
.cr-ico { width: 0.95em; height: 0.95em; vertical-align: -0.12em; margin-right: 2px; }
#genBtn.confirm { background: var(--warn); border-color: var(--warn); }
.credits-chip { font-family: var(--mono); }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.quality-pick #runAi, .quality-pick .find-hl { margin-top: 12px; width: 100%; }
.quality-pick #runAiNote { margin-top: 8px; }

/* --- generate picker: style + game (Phase 0) --- */
.gen-pick { display: flex; flex-direction: column; gap: 14px; max-width: 560px; }
.gen-row { display: flex; align-items: center; gap: 10px; }
.gen-lab { font-size: var(--fs-micro); color: var(--muted); min-width: 48px; }
.gen-sel { flex: 1; font-size: var(--fs-control); padding-top: 8px; padding-bottom: 8px; }
/* ---------- shorts: ranked moments + proxy preview ---------- */
.shorts-layout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(280px, 1fr); gap: 22px; }
.shorts-player video { width: 100%; border-radius: 12px; background: var(--video-bed); aspect-ratio: 16 / 9; }
/* previewing a finished 9:16 short: keep it upright and contained, not stretched */
.shorts-player video.vertical { aspect-ratio: 9 / 16; max-height: 70vh; object-fit: contain; }
.moments { display: flex; flex-direction: column; gap: 8px; max-height: 70vh; overflow-y: auto; }
.moment-row {
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 14px;
  cursor: pointer;
  color: var(--text);
}
.moment-row:hover { border-color: var(--line-strong); }
.moment-row.sel { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.mr-rank { color: var(--muted); font-weight: 600; font-size: var(--fs-secondary); flex: none; }
.mr-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mr-title { font-weight: 600; font-size: var(--fs-control); }
.mr-meta { color: var(--muted); font-size: var(--fs-secondary); }
.mr-score { flex: none; margin-left: auto; font-weight: 600; font-size: var(--fs-micro);
  color: var(--accent); background: var(--accent-dim); border-radius: 6px; padding: 2px 8px; }
.short-actions { display: flex; gap: 10px; align-items: center; margin-top: 10px; }
.short-actions .music-select { flex: 1; }
.moments-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.batch-row { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: var(--fs-micro); padding: 5px 2px; border-bottom: 1px solid var(--line); }
.batch-row .bs { color: var(--muted); }
#batchResults { margin-bottom: 8px; }
@media (max-width: 960px) { .shorts-layout { grid-template-columns: 1fr; } }

/* ---------- the Content panel: the highlight browser, its player and its selection ---------- */
.content-layout { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(300px, 1fr); gap: 22px; align-items: start; }
.content-list { display: flex; flex-direction: column; gap: 10px; }
.content-analysis { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; margin: 6px 0 8px; border: 1px solid var(--line); border-radius: 8px; }
.content-analysis p { margin: 0; }
.content-batch { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 4px 0 6px; }
.content-batch .music-select { flex: 0 1 180px; }
.short-card { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; cursor: pointer; }
.short-card:hover { border-color: var(--line-strong); }
.short-card.sel { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.sc-head { display: flex; align-items: center; gap: 10px; }
.sc-title { flex: 1; min-width: 0; font: inherit; font-size: var(--fs-control); font-weight: 600; color: var(--text); background: transparent; border: 1px solid transparent; border-radius: 6px; padding: 4px 6px; }
.sc-title:hover, .sc-title:focus { border-color: var(--line-strong); background: var(--surface-2); outline: none; }
.beat-strip { display: flex; align-items: flex-end; gap: 8px; overflow-x: auto; padding-bottom: 2px; }
.beat { display: flex; flex-direction: column; align-items: center; gap: 3px; flex: none; }
.beat-thumb { width: 96px; height: 54px; border-radius: 6px; background-color: var(--video-bed); background-repeat: no-repeat; border: 1px solid var(--line); }
.beat-role { font-size: var(--fs-micro); color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.beat-dur { font-size: var(--fs-micro); color: var(--faint); }
.beat-total { margin-left: auto; align-self: center; font-size: var(--fs-micro); color: var(--muted); white-space: nowrap; }
.sc-hook { display: flex; align-items: center; gap: 8px; }
.sc-badges { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.sc-tag { font-size: var(--fs-micro); color: var(--muted); }
.sc-by { margin-left: auto; }
.sc-arc { margin: 0; font-size: var(--fs-secondary); color: var(--text-2); font-style: italic; }
.beat-role { display: flex; align-items: center; gap: 3px; cursor: pointer; }
.beat-trim { display: flex; gap: 2px; }
.beat-trim input { width: 44px; font: inherit; font-size: var(--fs-micro); padding: 1px 3px; background: var(--surface-2); color: var(--text); border: 1px solid var(--line); border-radius: 4px; }
.sc-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sc-controls .music-select { flex: 0 1 150px; }
.sc-hook-in { flex: 1; min-width: 0; font: inherit; font-size: var(--fs-secondary); color: var(--text); background: var(--surface-2); border: 1px solid var(--line); border-radius: 6px; padding: 4px 8px; }
.sc-reason { margin: 0; font-size: var(--fs-secondary); color: var(--muted); }
.sc-actions { display: flex; align-items: center; gap: 10px; }
.sc-state[data-state="running"], .sc-state[data-state="queued"] { color: var(--warn); }
.sc-state[data-state="done"] { color: var(--good); }
.sc-state[data-state="error"] { color: var(--bad); }
.content-side { display: flex; flex-direction: column; gap: 16px; position: sticky; top: 12px; }
.short-player video.vertical { width: 100%; aspect-ratio: 9 / 16; max-height: 70vh; object-fit: contain; border-radius: 12px; background: var(--video-bed); }
.content-meta { display: flex; flex-direction: column; gap: 6px; }
.meta-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: var(--fs-secondary); padding: 4px 0; border-bottom: 1px solid var(--line); }
.meta-row > span { min-width: 0; overflow-wrap: anywhere; }
.meta-pre { margin: 0; font-size: var(--fs-micro); color: var(--muted); white-space: pre-wrap; }
/* HIGHLIGHTS (founder ruling, 2026-09-15): a scannable result list, not a planner form.
   A row is a thumbnail, a name, when and how long, a score and ONE button. */
.hl-tabs { display: flex; gap: 6px; margin: 6px 0 10px; }
.hl-tab { font: inherit; font-size: var(--fs-control); color: var(--muted); background: transparent;
  border: 1px solid transparent; border-radius: 999px; padding: 5px 14px; cursor: pointer; }
.hl-tab:hover { color: var(--text); }
.hl-tab.on { color: var(--text); border-color: var(--line-strong); background: var(--surface-2); }
.hl-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin-bottom: 10px; }
.hl-cats { display: flex; gap: 6px; flex-wrap: wrap; }
.hl-cat { font: inherit; font-size: var(--fs-secondary); color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 999px; padding: 4px 12px; cursor: pointer; }
.hl-cat:hover { border-color: var(--line-strong); color: var(--text); }
.hl-cat.on { color: var(--text); border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.hl-n { color: var(--faint); margin-left: 4px; }
.hl-sort { display: flex; align-items: center; gap: 6px; font-size: var(--fs-secondary); color: var(--muted); }
.hl-sort .music-select { flex: 0 1 160px; }
.hl-intro { max-width: 620px; }
.hl-intro h3 { margin: 0 0 6px; }
.hl-row { display: grid; grid-template-columns: 22px 128px minmax(0, 1fr) auto; gap: 12px;
  align-items: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; cursor: pointer; }
.hl-row:hover { border-color: var(--line-strong); }
/* THE CREATOR'S EDITS (2026-09-17): the same row, a kind chip where the thumbnail was */
.hl-row.hl-edit { grid-template-columns: auto minmax(0, 1fr) auto; }
.hl-kind { font-size: var(--fs-micro); padding: 4px 8px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--line-strong); color: var(--muted); }
.hl-kind.short { color: var(--accent); border-color: var(--accent-edge); }
.ed-name:hover { border-color: var(--line); }
.ed-name:focus { border-color: var(--accent-edge); outline: none; background: var(--surface-1); }
/* REFRAME BY DRAGGING (2026-09-17): the 9:16 preview is a grab surface in short mode */
body.in-short-editor #playerWrap { cursor: grab; }
body.in-short-editor #playerWrap.reframing { cursor: grabbing; }
body.in-short-editor #playerWrap button { cursor: pointer; }
.sfx-tools-shelf .sfx-shelf { width: 100%; }
.hl-row.sel { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* SELECTION IS ITS OWN AFFORDANCE: clicking the card plays the moment, ticking the box
   selects it. One gesture per meaning. */
.hl-pick { display: flex; align-items: center; justify-content: center; cursor: pointer; }
.hl-pick input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
.hl-row.picked { background: var(--surface-2); }
.hl-thumb { width: 128px; height: 72px; border-radius: 8px; background-color: var(--video-bed);
  background-repeat: no-repeat; border: 1px solid var(--line); }
.hl-meat { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.hl-line1 { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.hl-rank { font-size: var(--fs-micro); color: var(--faint); }
.hl-label { font-size: var(--fs-control); font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hl-score { margin-left: auto; font-size: var(--fs-secondary); color: var(--muted); font-variant-numeric: tabular-nums; }
.hl-line2 { font-size: var(--fs-micro); color: var(--muted); }
.hl-why { margin: 2px 0 0; font-size: var(--fs-secondary); color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hl-act { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.hl-state { font-size: var(--fs-micro); color: var(--muted); }
.hl-detail { display: flex; flex-direction: column; gap: 8px; }
.hl-modes { display: flex; gap: 6px; }
.hl-mode { font: inherit; font-size: var(--fs-micro); color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px 10px; cursor: pointer; }
.hl-mode.on { color: var(--text); border-color: var(--accent); }
.hl-detail .short-player video { width: 100%; border-radius: 12px; background: var(--video-bed); }
.hl-detail .short-player video:not(.vertical) { aspect-ratio: 16 / 9; }
.hl-dtitle { margin: 4px 0 0; font-size: var(--fs-control); }
.hl-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
@media (max-width: 960px) { .content-layout { grid-template-columns: 1fr; } .content-side { position: static; }
  .hl-row { grid-template-columns: 22px 96px minmax(0, 1fr); }
  .hl-thumb { width: 96px; height: 54px; }
  .hl-act { grid-column: 1 / -1; flex-direction: row; align-items: center; justify-content: space-between; } }

/* ---- FIND HIGHLIGHTS: identity, run state, selection (founder review, 2026-09-15) ---- */
/* The page must say WHICH VOD's highlights these are, show the run honestly while it is
   in flight, and give the selection ONE obvious action instead of a per-row button. */
/* THE VIDEO'S IDENTITY takes the row and pushes the page action to the far edge; without
   the grow the title, the subtitle and the button bunched together on the left. */
.page-ident { min-width: 0; flex: 1 1 auto; }
.page-head .page-ident + .btn { margin-left: auto; flex: 0 0 auto; }
.page-ident h2 { margin: 0; font-size: var(--fs-section); }
.page-sub { margin: 2px 0 0; font-size: var(--fs-secondary); color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hl-runbar { height: 4px; border-radius: 999px; background: var(--surface-2);
  overflow: hidden; margin: 14px 0; }
.hl-runfill { height: 100%; width: 34%; border-radius: 999px; background: var(--accent);
  animation: hl-run 1.6s ease-in-out infinite; }
@keyframes hl-run { 0% { transform: translateX(-100%); } 100% { transform: translateX(320%); } }
@media (prefers-reduced-motion: reduce) { .hl-runfill { animation: none; width: 100%; opacity: .5; } }
/* a DETERMINATE bar once the worker reports a percentage (2026-09-17) */
.hl-runbar.det .hl-runfill { animation: none; transform: none; transition: width .6s ease; opacity: 1; }
.hl-degraded { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; margin: 0 0 12px; border: 1px solid var(--line-strong);
  border-radius: 10px; background: var(--surface-2); }
.hl-degraded p { margin: 0; font-size: var(--fs-secondary); color: var(--muted); }
/* THE SELECTION ACTION is one sticky bar, not a button on every row: several moments
   become ONE Short, and a per-row button taught the opposite. */
.hl-selbar { position: sticky; bottom: 0; z-index: 4; display: flex; align-items: center;
  gap: 12px; margin-top: 14px; padding: 12px 16px; border: 1px solid var(--line-strong);
  border-radius: 12px; background: var(--surface-1);
  box-shadow: 0 -6px 20px rgb(0 0 0 / 18%); }
.hl-selbar[hidden] { display: none; }
body.has-selbar .content-layout { padding-bottom: 88px; }
.hl-selcount { font-size: var(--fs-secondary); color: var(--muted); margin-right: auto; }
/* KEYBOARD REACH. `.hl-row` is a control (role=button, tabindex=0), so it needs a focus
   ring like every other control; without one it is unusable without a mouse. */
.hl-row:focus-visible, .hl-cat:focus-visible, .hl-tab:focus-visible,
.hl-mode:focus-visible, .hl-selbar .btn:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; }
.hl-row { cursor: pointer; }
.confirm-dialog { max-width: 420px; }
.confirm-rows { margin: 12px 0 0; display: flex; flex-direction: column; gap: 6px; }
.confirm-rows > div { display: flex; justify-content: space-between; gap: 16px;
  font-size: var(--fs-secondary); }
.confirm-rows dt { color: var(--muted); margin: 0; }
.confirm-rows dd { margin: 0; font-variant-numeric: tabular-nums; }
@media (max-width: 960px) {
  .hl-selbar { flex-wrap: wrap; }
  .hl-selcount { width: 100%; margin-right: 0; }
}

/* ---------- engine chooser: one primary card, one secondary, one quiet link ---------- */
/* ===== C2 (2026-09-11): creation selector + game grid. Page-local composition on the Stage B primitives. ===== */
.engine-cards { display: flex; flex-direction: column; gap: 12px; max-width: 760px; }
.engine-card {
  position: relative;
  text-align: left;
  padding: 18px 20px;
  cursor: pointer;
  color: var(--text);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.engine-card .ec-name { font-size: var(--fs-section); font-weight: 600; }
.engine-card .ec-sub { color: var(--muted); font-size: var(--fs-secondary); max-width: 52ch; }
.engine-card .ec-badge {
  position: absolute; top: 14px; right: 16px;
  color: var(--accent); border-color: var(--accent-edge); background: var(--accent-wash);
  font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
}
/* the flagship card carries more visual weight than the secondary */
.engine-card { padding: 20px 22px; gap: 8px; }
.engine-card .ec-sub { max-width: 60ch; }
.engine-card.secondary .ec-name { font-size: var(--fs-section); font-weight: 600; }   /* C2: a peer choice, not a footnote */
.engine-card .ec-badge { top: 18px; right: 20px; }
.engine-alt { margin-top: 16px; font-size: var(--fs-secondary); color: var(--muted); }
.engine-alt a { color: var(--muted); text-decoration: underline; cursor: pointer; }
.engine-alt a:hover { color: var(--text); }
/* supported-game grid: unsupported games are visible but visibly not-yet */
.game-card.soon { opacity: 0.55; background: transparent; border-style: dashed; }
.game-card.soon .gc-mark { filter: saturate(0.4); }
.game-card.soon:hover { border-color: var(--line-strong); background: transparent; transform: none; opacity: 0.8; }
.gc-soon { font-size: var(--fs-micro); color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; }
.soon-hint {
  margin-top: 14px;
  background: var(--surface-2);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: var(--fs-secondary);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.sc-sub { font-size: var(--fs-micro); color: var(--muted); }

/* ---------- intake wizard ---------- */
.wiz { max-width: 760px; margin: 6px auto 0; }
.wiz-steps {
  display: flex; gap: 14px; list-style: none; padding: 0; margin: 0 0 22px;
  font-size: var(--fs-micro); letter-spacing: 0.06em; text-transform: uppercase;
}
.wiz-steps .ws { color: var(--muted); position: relative; padding-left: 22px; }
.wiz-steps .ws::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 13px; height: 13px; border-radius: 50%; border: 1.5px solid var(--line);
}
.wiz-steps .ws.on { color: var(--accent); }
.wiz-steps .ws.on::before { border-color: var(--accent); background: var(--accent); }
.wiz-steps .ws.done { color: var(--text); cursor: pointer; }
.wiz-steps .ws.done::before { border-color: var(--accent); }
.wiz-h { font-size: var(--fs-title); letter-spacing: -0.02em; line-height: 1.2; margin: 0 0 6px; }
.wiz-sub { margin: 0 0 24px; max-width: 60ch; font-size: var(--fs-body); color: var(--text-2); }
.game-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 12px; }
.game-card {
  display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 18px 10px 16px;
  background: var(--surface-2); border: 1px solid transparent; border-radius: 12px; cursor: pointer;
  color: var(--text); font: inherit; transition: border-color .12s, transform .08s, background .12s;
}
.game-card:hover { border-color: var(--accent-edge); background: var(--surface-2); transform: translateY(-2px); }
.gc-mark {
  width: 54px; height: 54px; border-radius: 12px; display: flex; align-items: center;
  justify-content: center; font-weight: 600; font-size: var(--fs-body); letter-spacing: 0.04em;
  /* the per-game hue is generated data: app.js sets --mark-h on the element (DESIGN.md v2) */
  --mark-h: 0;
  background: hsl(var(--mark-h) 36% 33%); color: var(--text);
}
.wiz-legal { color: var(--muted); font-size: var(--fs-secondary); line-height: 1.4; margin: 24px 0 0; max-width: 64ch; }
.gc-name { font-size: var(--fs-control); font-weight: 500; text-align: center; line-height: 1.25; }
.wiz-actions { display: flex; justify-content: space-between; align-items: center; margin-top: 22px; }
.btn.ghost { background: transparent; border-color: var(--line); color: var(--muted); }
.btn.ghost:hover { color: var(--text); border-color: var(--muted); }
.btn.danger, .btn.danger:hover { color: var(--bad); }   /* after .ghost on purpose: danger wins at rest and on hover */
.qp-note { color: var(--muted); font-size: var(--fs-secondary); margin: 10px 0 0; }
.site-legal { max-width: 1100px; margin: 40px auto 22px; padding: 0 24px; color: var(--muted); font-size: var(--fs-secondary); line-height: 1.5; text-align: center; opacity: 0.72; }
.site-legal .legal-links { display: block; margin-top: 6px; }
.site-legal .legal-links a { color: var(--muted); text-decoration: underline; }
.row-ren, .row-del {
  background: transparent; border: none; color: var(--muted); cursor: pointer;
  font-size: var(--fs-body); line-height: 1; padding: 4px 9px; border-radius: 6px; opacity: 0.45;
  transition: opacity .12s, color .12s, background .12s;
}
.video-row:hover .row-ren, .row-del { opacity: 1; }
.row-ren:hover, .row-del:hover { color: var(--bad); background: color-mix(in srgb, var(--bad) 12%, transparent); }

/* multi-game checklist + music select (PLAN items 1+3) */
.game-picks { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 4px; }
.game-pick { display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: 6px; cursor: pointer;
  font-size: var(--fs-control); }
.game-pick img { width: 64px; border-radius: 6px; }
.game-pick.all { border-style: dashed; }
.win-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.win-inputs { display: inline-flex; align-items: center; gap: 6px; }
.win-in { width: 84px; padding: 0 8px; text-align: center; }   /* appearance from the field primitive */
.music-select { width: 100%; margin: 4px 0 10px; }   /* C3: the field primitive owns the height */
#musicShelf .btn { margin: 4px 4px 4px 0; }

.track-list { margin: 6px 0 10px; display: flex; flex-direction: column; gap: 6px; }
.track-row { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 6px 10px; background: var(--bg); border: 1px solid var(--line-strong); border-radius: 6px;
  font-size: var(--fs-secondary); }
.track-row audio { height: 30px; max-width: 46%; }
.track-ord { display: flex; gap: 4px; flex-shrink: 0; }
.track-ord .btn { padding: 2px 8px; }

/* user track-library picker (persistent "Your tracks") */
.mm-pick { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; cursor: pointer; }
.mm-pick input[type="checkbox"] { flex-shrink: 0; accent-color: var(--accent); }
.mm-ord { flex-shrink: 0; min-width: 18px; height: 18px; padding: 0 5px; display: inline-flex;
  align-items: center; justify-content: center; border-radius: 9px; background: var(--accent);
  color: var(--accent-ink); font-size: var(--fs-micro); font-variant-numeric: tabular-nums; }
.mm-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: text; }
.mm-name:hover { text-decoration: underline dotted; }
.mm-attest { display: flex; align-items: center; gap: 6px; margin: 4px 0 2px; cursor: pointer; }
.mm-attest input[type="checkbox"] { accent-color: var(--accent); }

/* Twitch connection + VOD picker */
.twitch-intake { margin-top: 12px; }
.tw-connected { display: flex; align-items: center; gap: 10px; font-size: var(--fs-control); }
.tw-vod { display: flex; align-items: center; gap: 12px; padding: 10px 12px; background: var(--surface-2);
  border-radius: 8px; margin-bottom: 6px; }
.tw-vod img, .tw-thumb-ph { width: 96px; height: 54px; object-fit: cover; border-radius: 6px;
  background: var(--surface-3); flex-shrink: 0; }
.tw-meta .fineprint { margin: 2px 0 0; }
.tw-meta { flex: 1; min-width: 0; }
.tw-title { font-size: var(--fs-body); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tw-muted { color: var(--warn); font-size: var(--fs-micro); margin-top: 2px; }
.tw-kind { color: var(--accent); }

.vol-row { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: var(--fs-micro); }
.vol-row input[type="range"] { flex: 1; min-width: 0; accent-color: var(--accent); }
/* The Twitch-chat attach row (Find Highlights card): the URL field must SHRINK to its
   column like the range inputs do; a text input's `size` gives it an intrinsic width
   that pushed the Attach button past the card's edge (founder screenshot, 2026-09-17). */
.hl-chat .vol-row input[type="text"] { flex: 1 1 auto; min-width: 0; width: 100%; }
.hl-chat .vol-row .btn { flex: 0 0 auto; }
.vol-db { min-width: 58px; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }

.tl-clip.audio.alt { filter: brightness(1.35); }
.tc-zoom { position: absolute; right: 22px; top: 2px; background: var(--scrim-chip); border: none;
  border-radius: 6px; font-size: var(--fs-lane); cursor: pointer; padding: 1px 3px; }

.music-modal { position: fixed; inset: 0; background: var(--scrim-heavy); z-index: 90;
  display: flex; align-items: center; justify-content: center; }
.mm-card { padding: 20px 22px; width: min(520px, 92vw); max-height: 84vh; overflow-y: auto; }
.mm-card h3 { margin: 0 0 10px; }

/* ---------- legal ---------- */
.legal-note {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--muted);
  font-size: var(--fs-secondary);
}
.legal-quote {
  margin: 8px 0;
  padding: 8px 10px;
  background: var(--panel);
  border-radius: 6px;
  color: var(--text);
  user-select: all;
}

/* ---------- long-running job steps ---------- */
.job-steps {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: var(--fs-micro);
  color: var(--muted);
}
.job-step.done { color: var(--good); }
.job-step.now { color: var(--accent); font-weight: 600; }
.job-sep { color: var(--line-strong); }

/* ---------- editor declutter ---------- */
.legal-note summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  gap: 10px;
  align-items: baseline;
}
.legal-note summary::-webkit-details-marker { display: none; }
.legal-note summary::before { content: "\25B8"; color: var(--line-strong); }
.legal-note[open] summary::before { content: "\25BE"; }
.kbd-help {
  width: 20px; height: 20px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 999px;
  color: var(--muted); font-size: var(--fs-secondary); cursor: help; flex: none;
}
.kbd-help:hover { color: var(--text); border-color: var(--line-strong); }
.editor-hint { color: var(--muted); font-size: var(--fs-secondary); margin-right: 8px; }

/* ---------- toasts (the one notice surface; replaces native alert()) ---------- */
#toasts {
  position: fixed; right: 20px; bottom: 20px; z-index: 200;
  display: flex; flex-direction: column; gap: 8px; max-width: 380px;
}
.toast {
  background: var(--panel-2); border: 1px solid var(--line-strong);
  border-radius: 12px; padding: 10px 14px; font-size: var(--fs-secondary); line-height: 1.4;
  box-shadow: var(--shadow-overlay); cursor: pointer;
  animation: toast-in 0.18s ease-out;
}
.toast.error { border-color: color-mix(in srgb, var(--bad) 45%, transparent); color: var(--text); }
.toast.info { color: var(--text); }
.toast.out { opacity: 0; transform: translateY(6px); transition: opacity 0.3s, transform 0.3s; }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }

.mr-quote { display: block; color: var(--muted); font-style: italic; font-size: var(--fs-micro);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.mr-add { font-size: var(--fs-micro); padding: 3px 6px; border-radius: 4px; align-self: center;
  background: var(--surface-hover); border: 1px solid var(--line); color: var(--muted); }
.mr-add:hover { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* --- generate wizard: engine mode / length slider / narrative brief --------------------- */
.mode-pick { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 2px; }
.mode-opt { display: flex; gap: 8px; align-items: baseline; padding: 10px 12px; cursor: pointer; font-size: var(--fs-secondary); }
/* style cards: composition only (appearance from .option-card). No render site references
   these today (audit 2026-09-10); retained so a component's layout never vanishes into a
   primitive. */
.style-cards { display: flex; flex-direction: column; gap: 8px; }
.style-card { text-align: left; padding: 11px 13px; display: flex; flex-direction: column; gap: 4px;
  cursor: pointer; transition: border-color .12s, box-shadow .12s; }
.style-card[disabled] { opacity: .45; cursor: not-allowed; }
.sc-top { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.sc-name { font-weight: 600; font-size: var(--fs-control); }
.sc-tag { font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
  border: 1px solid var(--line); border-radius: 6px; padding: 1px 6px; }
.mode-opt input { accent-color: var(--accent); }
.cutlen { margin: 6px 0 2px; }
.cutlen input[type="range"] { width: 100%; accent-color: var(--accent); }
.cutlen-labels { display: flex; justify-content: space-between; color: var(--muted);
  font-size: var(--fs-micro); margin-top: 2px; }
.cutlen .fineprint { margin-top: 6px; }
.cutlen-hint + .fineprint { margin-top: 3px; }  /* the static hint sits right under the ticks; the live note follows it */
.brief textarea { width: 100%; resize: vertical; }
.brief.disabled { opacity: 0.45; }
.brief .fineprint { margin-top: 4px; }
.cutlen.disabled { opacity: 0.45; }
.mode-opt.off { opacity: 0.45; cursor: default; }
.ai-chip { font-size: var(--fs-micro); padding: 1px 5px; border-radius: 4px; vertical-align: 2px;
  background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
.brief-report { border: 1px solid var(--line); border-radius: 8px; padding: 10px 14px; margin-top: 10px; }
.brief-report summary { cursor: pointer; list-style: none; }
.brief-report summary::-webkit-details-marker { display: none; }
.brief-report summary::before { content: "▸ "; color: var(--muted); }
.brief-report[open] summary::before { content: "▾ "; }
.brief-report .brief-body { max-height: 26vh; overflow-y: auto; margin-top: 6px; }
.brief-verdict { font-size: var(--fs-micro); margin: 4px 0; color: var(--muted); }
.brief-verdict.supported b { color: var(--accent); }
.brief-verdict.partial b { color: var(--warn); }
.brief-verdict.unsupported b { color: var(--bad); }

/* ===================== editor shell v2 (design v2, 2026-07-24) =====================
   Three zones: library (add things) / stage / inspector (adjust the selected thing),
   one Export menu, quiet status pills, fixed track-header column. Overrides the v1
   editor layout rules above; scoped under .ed2 so other pages are untouched. */
.ed2 { gap: 8px; }
.ed-bar {
  display: flex; align-items: center; gap: 8px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  padding: 6px 10px;
}
.ed-pill { background: var(--panel-2); }
.ed-bar .hd-note.ed-pill { margin: 0; cursor: pointer; }
/* the name yields width before anything else in the bar does: on a 1024 px laptop the
   input's default 20-column size squeezed the Render block into two lines, the bar grew
   16 px and pushed the audio lane's trim grips below the fold (measured 2026-09-17) */
.ed-name { font: inherit; font-weight: 600; color: var(--text); background: transparent; border: 1px solid transparent;
  border-radius: 8px; padding: 2px 6px; flex: 0 1 24ch; min-width: 8ch; max-width: 40ch; }
.ed-bar .ed-export { flex-shrink: 0; }
/* the Short's length note is a bar item, not page fineprint: no 14 px top margin, and it
   never wraps into a second line (the wrap is what grew the bar on a 1024 px laptop) */
.ed-bar .fineprint { margin: 0; white-space: nowrap; }
.ed-bar .ed-pill.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
/* the static "Saved / up to date" pills yield when their live warning is showing */
.ed-bar:has(#saveWarn:not(.hidden)) #savedPill { display: none; }
.ed-bar:has(#previewStale:not(.hidden)) #freshPill { display: none; }
.ed-bar .tl-info-mini { color: var(--muted); font-size: var(--fs-micro); }
.ed-export { position: relative; }
.ed-menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 60; width: 250px;
  display: flex; flex-direction: column; gap: 8px;
}
.ed-menu[hidden] { display: none !important; }
.ed-menu .btn { width: 100%; text-align: center; }
.ed-menu .pv-link { display: block; padding: 2px 0; }
.ed-menu-h {
  font-size: var(--fs-micro); color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.06em; margin-top: 4px; border-top: 1px solid var(--line); padding-top: 8px;
}
.ed-menu .legal-note { margin: 0; }

/* --- main three-zone row --- */
.ed-main { display: flex; gap: 10px; height: 52vh; min-height: 380px; }
.ed-lib { display: flex; flex-direction: column; }
.ed-lib .mp-head { gap: 2px; margin-bottom: 8px; }
.ed2 .lib-tab { font-size: var(--fs-micro); }   /* the 240px bin holds three tabs at micro (frozen) */
.ed-lib .mp-collapse { margin-left: auto; }
.lib-pane[hidden] { display: none !important; }
.lib-pane .hl-panel { margin: 0; }
.ed-stage { flex: 1; min-width: 0; }
.ed-insp {
  width: 292px; flex: none; background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px; padding: 12px; overflow-y: auto;
}
.insp-pane2[hidden] { display: none !important; }
.insp-h2 {
  font-size: var(--fs-micro); color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.06em; margin-bottom: 10px;
}
/* the clip pane replaces the old floating clip bar: a static inspector surface */
.ed2 .clip-bar {
  position: static; display: block; background: none; border: none;
  box-shadow: none; padding: 0; animation: none;
}
.ed2 .clip-bar .vol-row { display: flex; }
.ed2 .cb-why {
  display: block; max-width: none; white-space: normal; border-left: none;
  padding: 10px 0 0; font-size: var(--fs-micro); line-height: 1.45;
}
/* Track 1 (2026-09-14): the selected clip's EXPLICIT effects. An automatic shake is a row
   the creator can retune or remove; nothing here is ever baked into the footage. */
.cb-effects { display: block; padding: 10px 0 0; font-size: var(--fs-micro); }
.cb-effects .insp-h3 { margin: 0 0 4px; }
.fx-row { display: flex; align-items: center; gap: 6px; padding: 3px 0; }
.fx-row .fx-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fx-row .fx-strength { font-size: var(--fs-micro); }
.tc-fx { margin-left: 4px; font-size: 10px; opacity: 0.8; }

/* --- timeline: fixed header column + calmer, taller lanes --- */
.ed2 .tl-panel { height: 330px; }
.tl-body { display: flex; flex: 1; min-height: 0; }
.tl-heads {
  width: 148px; flex: none; border-right: 1px solid var(--line);
  padding: 4px 8px 0 8px; overflow: hidden;
}
.tl-head-ruler { margin-bottom: 4px; }
.tl-head {
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  margin-bottom: 4px; box-sizing: border-box; padding: 2px 2px;
  border-radius: 6px;
}
.th-name {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--fs-lane); font-weight: 600; color: var(--fg);
}
.th-dot { width: 7px; height: 7px; border-radius: 2px; flex: none; }
.tl-head .lane-chips {
  position: static; display: flex; gap: 4px; align-items: center;
  background: none; padding: 0;
}
.ed2 .tl-scroll { flex: 1; }
.ed2 .tl-track { height: 64px; }
.ed2 .tl-track.overlay-lane { height: 40px; }
.ed2 .tl-track.audio-lane { height: 56px; }
.ed2 .tl-track.vod-lane { height: 48px; }
/* distinct treatments: gameplay teal-dark, music purple (matches design v2) */
.ed2 .vod-lane .tl-clip.audio { background: var(--clip-vod); border-color: var(--clip-vod-edge); }
.ed2 .role-music .tl-clip.audio { background: var(--clip-music); border-color: var(--clip-music-edge); }
.ed2 .role-music .tl-clip.audio.alt { filter: brightness(1.18); }
.ed2 .role-sfx .tl-clip.audio { background: var(--clip-sfx); border-color: var(--clip-sfx-edge); }
/* linked marker only when you're looking at the clip */
.ed2 .tl-clip.vod-linked .tc-link { opacity: 0; transition: opacity 0.12s; }
.ed2 .tl-clip.vod-linked:hover .tc-link { opacity: 1; }
/* selection reads stronger than hover, hover stronger than the duck tint */
.ed2 .tl-clip.sel { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }
.ed2 .tl-clip:hover:not(.sel) { border-color: var(--line-strong); }
.ed2 .editor-hint { display: none; }

/* boundary transition markers: quiet dots at rest, accent only under the pointer —
   a cut full of dissolves must not read as a row of glowing badges */
.ed2 .tl-trans.active {
  opacity: 0.5; color: var(--accent); background: var(--glass);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: none;
}
.ed2 .tl-trans.active:hover {
  opacity: 1; color: var(--accent-ink); background: var(--accent); border-color: var(--accent);
}
.mp-expand[hidden] { display: none !important; }

/* ===== phases 2+3: inspector panes for duck/transition, feel pass ===== */
/* transition pane: the old floating popover restyled as an inspector surface */
.ed2 .trans-pop {
  position: static; width: auto; box-shadow: none; border: none;
  background: none; padding: 0;
}
.duck-pane .duck-acts { display: flex; gap: 8px; margin: 10px 0 4px; }
/* selected boundary dot mirrors the pane */
.ed2 .tl-trans.tsel {
  opacity: 1; color: var(--accent-ink); background: var(--accent); border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
}

/* --- feel: one motion language (~140ms, eased), fat targets, quiet chrome --- */
.ed2 .tl-clip { transition: border-color 0.14s ease, box-shadow 0.14s ease; }
.ed2 .tl-trans { transition: opacity 0.14s ease, background 0.14s ease, transform 0.14s ease; }
.ed2 .lib-tab, .ed2 .btn, .ed2 .lane-chip, .ed2 .mp-tab { transition: color 0.14s ease, border-color 0.14s ease, background 0.14s ease; }
.insp-pane2:not([hidden]) { animation: insp-in 0.15s ease; }
@keyframes insp-in { from { opacity: 0; transform: translateY(3px); } }
.ed2 .media-item:hover, .ed2 .hl-card:hover { border-color: var(--line-strong); }
/* trim grips: 7px visual, ~21px hit. The boundary dot keeps its small circle ABOVE
   the grips (z6) — grips stay grabbable above/below it (measured y-frac 0.12/0.88),
   the dot stays clickable at center; neither swallows the other. */
.ed2 .tc-grip::before { content: ""; position: absolute; top: 0; bottom: 0; left: -7px; right: -7px; }
/* ...and the × clears that widened hit area. The base rule puts it at right:3px, which
   was 17px clear of the ORIGINAL grip strip; once `::before` grew the grip's hit box to
   16px from the edge, the ×'s own CENTRE sat inside it and every mouse click on delete
   landed on the trim grip instead. Found by the Short-editor gate, 2026-09-16: the
   keyboard path worked, the pointer path silently did not. */
.ed2 .tl-clip .tc-del { right: 18px; }
/* zoom + toolbar buttons: quiet until hovered */
.ed2 .tl-toolbar .btn { background: none; border-color: transparent; color: var(--muted); }
.ed2 .tl-toolbar .btn:hover { border-color: var(--line-strong); color: var(--fg); }
/* highlights tab: cards stack in the narrow library column */
.lib-pane .hl-grid { grid-template-columns: 1fr; gap: 8px; }
.lib-pane .hl-card { width: auto; }
@media (prefers-reduced-motion: reduce) {
  .ed2 .tl-clip, .ed2 .tl-trans, .ed2 .lib-tab, .ed2 .btn, .ed2 .lane-chip, .ed2 .mp-tab { transition: none; }
  .insp-pane2:not([hidden]) { animation: none; }
}

/* --- clip affordances: the edge is a visible HANDLE, the body is a grab surface.
   Cursor + handle styling answer "what will this drag do" BEFORE the drag starts:
   body = grab/grabbing (move), edges = ew-resize tabs with a notch (trim). --- */
.ed2 .tl-clip.dragging { cursor: grabbing; }
.ed2 .tl-clip.trimming { cursor: ew-resize; }
.ed2 .tc-grip { width: 9px; }
.ed2 .tl-clip:hover .tc-grip, .ed2 .tl-clip.sel .tc-grip {
  background: color-mix(in srgb, var(--accent) 72%, transparent);
}
.ed2 .tl-clip .tc-grip:hover { background: var(--accent); }
.ed2 .tc-grip::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  height: 12px; width: 2px; border-radius: 1px; background: var(--accent-ink);
  opacity: 0; transition: opacity 0.12s;
}
.ed2 .tl-clip:hover .tc-grip::after, .ed2 .tl-clip.sel .tc-grip::after { opacity: 1; }
.ed2 .tc-l { border-radius: 5px 0 0 5px; }
.ed2 .tc-r { border-radius: 0 5px 5px 0; }

/* global link toggle: quiet like the toolbar, unmistakable when ON */
.ed2 .tl-toolbar #tlLink.on {
  color: var(--accent); border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.ed2 .tl-toolbar #tlLink:not(.on) { opacity: 0.55; }

/* ============ premium pass (founder-approved GPT spec, 2026-07-24) ============
   Fewer boxes, four surface levels, glass only on chrome, sentence case, quieter
   timeline, standard radii/spacing, tactile motion. Scoped to the editor (.ed2). */
.ed2 {
  --ease-tactile: cubic-bezier(0.2, 0.8, 0.2, 1);
}
.ed-hidden { display: none !important; }

/* --- one glass toolbar (chrome only: bar + menus/popovers; content stays solid) --- */
.ed2 .ed-bar {
  background: var(--glass);
  backdrop-filter: blur(20px) saturate(125%);
  -webkit-backdrop-filter: blur(20px) saturate(125%);
  border: 1px solid var(--border-subtle);
  box-shadow: inset 0 1px var(--line), var(--shadow-clip);
  border-radius: 14px;
}
.ed-back { font-size: var(--fs-micro); color: var(--muted); margin-right: 2px; }
.ed-title { font-size: var(--fs-control); font-weight: 600; margin-right: 6px; }

/* --- typography: sentence case, calm hierarchy, tabular timecodes --- */
.insp-h2 { text-transform: none; letter-spacing: 0; font-size: var(--fs-control); font-weight: 600; color: var(--fg); }
.ed2 .mp-sec summary { text-transform: none; letter-spacing: 0; font-size: var(--fs-micro); font-weight: 600; }
.ed-menu-h { text-transform: none; letter-spacing: 0; font-size: var(--fs-micro); }
.ed2 .tl-clock, .ed2 .pc-time, .ed2 .tl-ruler, .ed2 .vol-db, .th-db { font-variant-numeric: tabular-nums; }

/* --- de-boxed inspector: spacing + hairlines, not nested cards --- */
.ed-insp { border: 1px solid var(--border-subtle); background: var(--surface-panel); }
.ed2 .ed-insp .mp-sec {
  border: none; background: none; border-radius: 0;
  border-top: 1px solid var(--border-subtle);
  margin: 2px 0 0; padding: 10px 0 8px;
}
.ed2 .ed-insp .mp-sec .trans-shelf { border: none; background: none; padding: 4px 0 0; }
.ed2 .ed-insp .insp-kv { padding: 6px 0; }
.ed2 .ed-insp #briefReport .legal-note, .ed2 .ed-insp #briefReport > div {
  border: none; border-top: 1px solid var(--border-subtle); border-radius: 0; background: none;
}
.insp-pane2:not([hidden]) { animation: insp-in 0.16s var(--ease-tactile); }
.th-db { margin-left: auto; font-size: var(--fs-lane); color: var(--muted); font-weight: 500; }
.tl-head.th-click { cursor: pointer; transition: background 0.12s var(--ease-tactile); }
.tl-head.th-click:hover { background: var(--surface-hover); }
.tl-head.hsel { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.duck-pane .insp-actions, #paneTrack .insp-actions { display: flex; gap: 8px; margin-top: 10px; }

/* --- library: rows not cards --- */
.ed2 .media-list .media-item, .ed2 .lib-pane .hl-card {
  border-color: transparent; background: none; border-radius: 10px;
  transition: background 0.12s var(--ease-tactile), border-color 0.12s var(--ease-tactile);
}
.ed2 .media-list .media-item:hover, .ed2 .lib-pane .hl-card:hover {
  background: var(--lane-wash); border-color: var(--border-subtle);
}

/* --- timeline: quieter idle, unmistakable selection, gentle lane depth --- */
.ed2 .tl-track { border: none; border-bottom: 1px solid var(--border-subtle); border-radius: 0; margin-bottom: 3px; }
.ed2 .tl-track.main-lane { background: var(--lane-wash); }
.ed2 .tl-track.vod-lane { background: var(--lane-recessed); }
.ed2 .tl-track.role-music { background: color-mix(in srgb, var(--lane-music) 5%, transparent); }
.ed2 .tl-clip { border-color: color-mix(in srgb, var(--accent) 34%, transparent); }
.ed2 .tl-clip:hover:not(.sel) { border-color: color-mix(in srgb, var(--accent) 68%, transparent); }
.ed2 .tl-clip.sel {
  border-color: color-mix(in srgb, var(--accent) 95%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 28%, transparent), var(--shadow-clip);
}
.ed2 .tl-clip.audio .tc-wave { opacity: 0.4; transition: opacity 0.12s var(--ease-tactile); }
.ed2 .tl-clip.audio:hover .tc-wave, .ed2 .tl-clip.audio.sel .tc-wave { opacity: 0.65; }
.ed2 .role-music .tc-title {
  /* a MASK: #000 here is alpha geometry (opaque), not a colour; exempt from the literal ban */
  -webkit-mask-image: linear-gradient(90deg, #000 72%, transparent);
  mask-image: linear-gradient(90deg, #000 72%, transparent);
}
.ed2 .tl-trans.active { opacity: 0.32; }
.ed2 .main-lane:hover .tl-trans.active { opacity: 0.7; }
.ed2 .tl-trans.active:hover, .ed2 .tl-trans.tsel { opacity: 1; }
/* playhead: 1px crafted line with a soft glow, not a chunky marker */
.ed2 .tl-playhead { width: 1px; background: var(--playhead); box-shadow: 0 0 6px color-mix(in srgb, var(--playhead) 45%, transparent); }
.ed2 .ph-grip { filter: drop-shadow(0 0 3px color-mix(in srgb, var(--playhead) 50%, transparent)); }

/* --- consistent geometry --- */
.ed2 .media-panel, .ed2 .tl-panel { border-radius: 14px; border-color: var(--border-subtle); }
.ed2 .ed-insp { border-radius: 14px; }
.ed2 .btn { border-radius: 8px; }
.ed2 .ed-pill, .ed2 .lane-chip { border-radius: 999px; }

/* --- accessibility fallbacks: glass and motion must degrade honestly --- */
@media (prefers-reduced-transparency: reduce) {
  .ed2 .ed-bar, .ed2 .ed-menu {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: var(--surface-raised);
  }
}
@media (prefers-contrast: more) {
  .ed2 { --border-subtle: var(--border-subtle-hc); }
  .ed2 .tl-clip { border-color: color-mix(in srgb, var(--accent) 80%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .ed2 .ed-menu, .insp-pane2:not([hidden]) { animation: none; }
  .tl-head.th-click, .ed2 .media-list .media-item, .ed2 .tl-clip.audio .tc-wave { transition: none; }
}

/* inspector key/value rows (project summary): label left, value right */
.ed2 .insp-kv {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  font-size: var(--fs-micro); color: var(--muted); padding: 6px 0;
}
.ed2 .insp-kv b { color: var(--fg); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ============ premium pass 2: icons, transport, hierarchy (2026-07-24) ============ */
/* one icon family everywhere */
.ic { width: 17px; height: 17px; display: block; pointer-events: none; }
.ed2 .btn .ic, .ed2 .kbd-help .ic { width: 15px; height: 15px; }
.ed2 .lane-chip .ic { width: 11px; height: 11px; }
.ed2 .kbd-help { display: inline-flex; align-items: center; }
/* the viewer transport reads as ONE object: even spacing, hover circles, quiet icons */
.ed2 .pc-btn {
  width: 30px; height: 30px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--text-2);
  transition: background 0.12s var(--ease-tactile), color 0.12s var(--ease-tactile);
}
.ed2 .pc-btn:hover { background: var(--surface-hover); color: var(--text); }
.ed2 .pc-btn.pc-play { width: 34px; height: 34px; color: var(--text); }
.ed2 .pc-btn.pc-play .ic { width: 20px; height: 20px; }
/* boundary markers: a plain dot, no glyph texture */
.ed2 .tl-trans .tt-ico { width: 4px; height: 4px; border-radius: 50%; background: currentColor; }
/* Export truly trailing + quieter duration readout */
.ed2 .ed-bar .spacer { flex: 1; }
.ed2 .ed-bar .tl-info-mini { font-size: var(--fs-micro); color: var(--muted); }
.ed-title { font-size: var(--fs-body); font-weight: 600; }
/* quieter idle timeline (only selection glows) */
.ed2 .tl-clip { border-color: color-mix(in srgb, var(--accent) 22%, transparent); }
.ed2 .tl-clip:hover:not(.sel) { border-color: color-mix(in srgb, var(--accent) 52%, transparent); }
.ed2 .tl-clip.sel {
  border-color: color-mix(in srgb, var(--accent) 95%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 20%, transparent), var(--shadow-clip);
}
/* music title: gradient backdrop so it never collides with the waveform */
.ed2 .role-music .tc-title {
  -webkit-mask-image: none; mask-image: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--clip-music-deep) 96%, transparent) 0%, color-mix(in srgb, var(--clip-music-deep) 72%, transparent) 70%, transparent 100%);
  padding: 1px 18px 1px 8px; border-radius: 3px; max-width: 60%;
}
/* soundtrack card in the Music tab */
.music-card {
  display: flex; align-items: center; gap: 10px; padding: 10px 4px; margin-bottom: 4px;
}
.mc-swatch {
  width: 38px; height: 38px; border-radius: 10px; flex: none;
  background: linear-gradient(135deg, var(--clip-music-edge), var(--clip-music));
  display: flex; align-items: center; justify-content: center; color: var(--clip-music-ink);
}
.mc-swatch .ic { width: 18px; height: 18px; }
.mc-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.mc-name { font-size: var(--fs-micro); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mc-more { color: var(--muted); font-weight: 500; }
.mc-meta { font-size: var(--fs-secondary); color: var(--muted); font-variant-numeric: tabular-nums; }
/* tactile press, no bounce */
.ed2 .btn, .ed2 .pc-btn { transition-property: background, color, border-color, transform; }
.ed2 .btn:active, .ed2 .pc-btn:active { transform: scale(0.98); }
/* four-level surfaces: majors on --panel, chrome raised */
.ed2 .media-panel, .ed2 .ed-insp, .ed2 .tl-panel { background: var(--panel); }
@media (prefers-reduced-motion: reduce) {
  .ed2 .btn:active, .ed2 .pc-btn:active { transform: none; }
}

/* intro badge on the soundtrack list */
.mc-intro {
  font-size: var(--fs-micro); font-weight: 600; color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); border-radius: 999px;
  padding: 1px 7px; margin-right: 7px;
}

/* local interaction reel: third surface, revealed only while it owns the screen */
.player-wrap > #iplayer {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; object-fit: contain; opacity: 0; background: var(--video-bed);
}
.player-wrap.ivid-live > #iplayer { opacity: 1; }
.player-wrap.ivid-live > #reelCanvas, .player-wrap.ivid-live > video#player { opacity: 0; }

/* ---------- auth gate (web/auth.js) ----------
   A full-viewport overlay rather than a route: the SPA must not render, fetch, or
   reveal ANY project metadata before a principal exists. Hiding a signed-out user
   behind a route is a client-side lie — the server 404s them anyway, but the app
   would flash empty shells and fire doomed requests on the way there. */
body.auth-locked { overflow: hidden; }
body.auth-locked .shell,
body.auth-locked .topbar,
body.auth-locked .site-legal { filter: blur(3px); pointer-events: none; }

.auth-gate {
  position: fixed; inset: 0; z-index: 9999;
  display: grid; place-items: center;
  background: var(--glass);
  backdrop-filter: blur(6px);
}
.auth-card {
  width: min(92vw, 330px);
  display: flex; flex-direction: column; gap: 12.75px;
  padding: 24px 22.5px 20.25px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-overlay);
}
.auth-brand { font-size: var(--fs-title); font-weight: 600; letter-spacing: -0.02em; margin: 0; }
.auth-brand span { color: var(--accent); }
.auth-sub { margin: -5.25px 0 3px; font-size: var(--fs-control); color: var(--muted); }
.auth-field { display: flex; flex-direction: column; gap: 4.5px; font-size: var(--fs-micro); }
/* An explicit `display` BEATS the UA stylesheet's `[hidden] { display: none }`, so
   without this the password field stays on screen in password-reset mode even
   though JS set .hidden = true. Caught by tests/browser/auth_gate.py; it is
   invisible to every non-browser test. */
.auth-field[hidden] { display: none; }
.auth-field span { color: var(--muted); }
.auth-field input { width: 100%; }
.auth-go {
  margin-top: 3px; padding: 9.3px 12px;
  font-size: var(--fs-control); font-weight: 600; color: var(--accent-ink);   /* B1: the ONLY ink on accent (was white, 1.6:1) */
  background: var(--accent); border: 0; border-radius: 8px; cursor: pointer;
}
.auth-go[disabled] { opacity: 0.65; cursor: default; }
.auth-alt { display: flex; justify-content: space-between; gap: 9px; }
.auth-field-row { display: flex; justify-content: space-between; align-items: baseline; }
.auth-alt .linkish, .auth-field .linkish, .auth-msg .linkish {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-size: var(--fs-micro); color: var(--muted); text-decoration: underline;
}
.auth-msg .linkish { color: inherit; font-size: inherit; }
.auth-msg .linkish[disabled] { opacity: 0.6; cursor: default; text-decoration: none; }
.auth-alt .linkish:hover, .auth-field .linkish:hover, .auth-msg .linkish:hover { color: var(--text); }
.auth-legal { margin: 9px 0 0; font-size: var(--fs-secondary); color: var(--muted); }
.auth-legal a { color: inherit; text-decoration: underline; }
.auth-legal a:hover { color: var(--text); }
.auth-msg { min-height: 1.1em; margin: 0; font-size: var(--fs-micro); }
.auth-captcha:empty { display: none; }
.auth-msg.err { color: var(--err); }
.auth-msg.ok { color: var(--ok); }

/* feedback hub (item 44) */
.feedback-open { background: none; border: 0; text-align: left; cursor: pointer; width: 100%; }
.feedback-dialog { border: 1px solid var(--line-strong); border-radius: 12px;
  background: var(--panel); color: var(--text); padding: 20px; max-width: 420px; }
.feedback-dialog::backdrop { background: var(--scrim-modal); }
.feedback-dialog h3 { margin: 0 0 6px; }
.feedback-dialog textarea { width: 100%; margin-top: 10px; resize: vertical; }
.feedback-msg { min-height: 1.1em; margin: 6px 0 0; font-size: var(--fs-micro); color: var(--err); }
.feedback-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }

/* workspace sharing (PLAN_WORKSPACE_SHARING, 2026-08-13) */
.ws-section { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
.ws-section h4 { margin: 8px 0 6px; font-size: var(--fs-secondary); }
.ws-note { font-size: var(--fs-secondary); margin: 0 0 8px; }
.ws-row { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 5px 0; font-size: var(--fs-secondary); }
.ws-row.ws-pending span { color: var(--muted); }
.ws-invite-row { display: flex; gap: 8px; margin-top: 8px; }
.ws-invite-row input { flex: 1; min-width: 0; }
.row-owner { margin-right: 8px; background: var(--panel-2); vertical-align: 1px; }

/* account & billing (P3, 2026-08-04) */
.account-dialog .account-buys { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.account-dialog .account-buys .btn { width: 100%; text-align: left; }
.account-dialog .feedback-actions { justify-content: space-between; }


/* --- the subscription gate (2026-08-18): covers the app for a signed-in
   user with no active plan; plan cards come from /api/auth/me. --- */
.plan-gate { position: fixed; inset: 0; z-index: 900; display: flex;
  align-items: center; justify-content: center; padding: 24px;
  background: var(--bg); overflow: auto; }
.plan-gate[hidden] { display: none; }
.plan-gate-card { width: min(720px, 100%); }
.plan-gate-card h2 { margin: 0 0 6px; font-size: var(--fs-title); }
.plan-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px; margin-top: 18px; }
.plan-card { padding: 18px; display: flex; flex-direction: column; gap: 10px; }
.plan-card h3 { margin: 0; font-size: var(--fs-section); }
.plan-card .plan-price { font-size: var(--fs-title); font-weight: 600; }
.plan-card .plan-price small { font-size: var(--fs-secondary); font-weight: 400; color: var(--muted); }
.plan-card .plan-credits { color: var(--accent); font-weight: 600; }
.plan-card ul { margin: 0; padding-left: 18px; color: var(--muted); font-size: var(--fs-control); }
.plan-card .btn { margin-top: auto; }
.plan-gate-foot { margin-top: 18px; font-size: var(--fs-secondary); display: flex; gap: 8px; align-items: center; }


/* an interrupted upload, called out in the drop zone (2026-08-18) */
.upload-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.resume-note .linkish, #planGateMsg .linkish { background: none; border: 0; padding: 0; cursor: pointer; color: inherit; font: inherit; text-decoration: underline; }
.resume-note { margin: 6px 0 10px; padding: 8px 12px; border-radius: 8px;
  background: var(--accent-dim); color: var(--text); font-size: var(--fs-control); }

/* "Full games only" is a rare, no-editing option: say so loudly when picked (2026-08-18) */
.fullgames-row.on { color: var(--text); }
.fullgames-warn { margin: 6px 0 0; padding: 8px 12px; border-radius: 8px; font-size: var(--fs-secondary);
  border: 1px solid color-mix(in srgb, var(--warn) 55%, transparent); background: color-mix(in srgb, var(--warn) 12%, transparent); color: var(--text); }

/* editable game boundaries (2026-08-18) */
.game-row { flex-wrap: wrap; justify-content: space-between; }
.game-pick-main { display: flex; align-items: center; gap: 10px; flex: 1 1 auto; cursor: pointer; }
.game-txt { display: flex; flex-direction: column; line-height: 1.25; }
.game-tag { font-size: var(--fs-micro); padding: 1px 6px; border-radius: 999px; background: var(--accent-dim); color: var(--accent); margin-left: 6px; }
.game-edit { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.game-edit .win-in { width: 84px; }
.game-editbtn, .game-add, .game-reset { background: none; border: 0; padding: 0; color: var(--accent); cursor: pointer; font: inherit; font-size: var(--fs-secondary); }
.game-reset { margin-left: 10px; }

/* scan progress on the Start button (2026-08-18) */
#genBtn.scanning { position: relative; overflow: hidden; }
#genBtn .scan-bar { position: absolute; left: 0; bottom: 0; height: 3px; width: 0%;
  background: var(--accent); transition: width 0.6s ease; }
/* "Generate a new version…" warning (founder, 2026-08-19): the replace
   consequence is visible BEFORE the click, not only in the confirm. */
.gen-again-warn { margin: 6px 0 10px; color: var(--warn); }

/* ---------- transient service banner (app.js noteServiceDown, 2026-08-19) ----------
   ONE fixed banner while the box restarts for a deploy (~10 s): never a toast per
   failed poll. Above the topbar (z 10) and the plan gate (900), below the login
   gate (9999). */
#serviceBanner {
  position: fixed; top: 10px; left: 50%; transform: translateX(-50%); z-index: 950;
  max-width: min(560px, calc(100vw - 24px)); padding: 10px 16px; border-radius: 10px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line-strong);
  font-size: var(--fs-control); line-height: 1.4; box-shadow: var(--shadow-overlay);
  transition: opacity 0.35s ease;
}
#serviceBanner.svc-down { border-color: color-mix(in srgb, var(--warn) 50%, transparent); }
#serviceBanner.svc-back { border-color: color-mix(in srgb, var(--good) 50%, transparent); color: var(--good); }
#serviceBanner.out { opacity: 0; }

/* the wizard's Story-notes contract line (2026-08-19): what the notes do and
   do not do, stated where they are typed */
.brief-help { margin: -2px 0 8px; max-width: 64ch; }

/* the finished-length estimate (calibrated ranges, 2026-08-19) */
.est-range { color: var(--text); margin: -2px 0 10px; }
.est-long { color: var(--warn); margin: -6px 0 10px; }

/* per-game Parameters (gameplay weight), collapsed by default */
.game-params { flex-basis: 100%; margin: 2px 0 0 30px; }
.game-params summary { cursor: pointer; color: var(--muted); font-size: var(--fs-micro); list-style: none; }
.game-params summary::before { content: "\25B8"; color: var(--line-strong); margin-right: 5px; }
.game-params[open] summary::before { content: "\25BE"; }
.gp-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 0 4px; }
.gp-label { font-size: var(--fs-micro); color: var(--muted); }
.gp-help { display: inline-flex; width: 15px; height: 15px; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 999px; font-size: var(--fs-secondary); color: var(--muted); cursor: help; }
.gp-snaps { display: inline-flex; gap: 4px; }
.gp-snap { background: var(--panel); border: 1px solid var(--line); color: var(--muted);
  border-radius: 8px; padding: 3px 9px; font-size: var(--fs-micro); cursor: pointer; }
.gp-snap.on { color: var(--accent); border-color: var(--accent); background: var(--accent-dim); }
.gp-desc { flex-basis: 100%; margin: 0; }

/* the account dialog's credit breakdown (capped rollover, 2026-08-20): one
   line per fact, the total first */
#accountBalance .credit-line { display: block; }
#accountBalance strong.credit-line { color: var(--text); margin-bottom: 2px; }

/* ---------- BYO music: non-blocking audio-level preparation banner ---------- */
/* Cold-proxy leveling runs a ~5-min measure on the media fleet; the editor stays
   usable and this banner reports progress, then offers the final Apply. */
.music-prep {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%);
  z-index: 95; display: flex; align-items: center; gap: 10px;
  max-width: min(92vw, 560px); padding: 10px 16px; border-radius: 10px;
  font-size: var(--fs-control); line-height: 1.35; box-shadow: var(--shadow-overlay);
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line);
}
.music-prep.preparing { border-color: var(--accent); }
.music-prep.ready { border-color: var(--accent); }
.music-prep.failed { border-color: var(--bad); }
.music-prep button { white-space: nowrap; }

/* ---------- Intro Editor (2026-08-24, PLAN_INTRO_EDITOR phase 4) ---------- */
.tl-clip.tc-intro { box-shadow: inset 0 2px 0 var(--accent); }
.intro-edit-btn { border-color: var(--accent); color: var(--accent); }
.intro-panel { display: flex; flex-direction: column; gap: 10px; padding: 10px 14px;
  overflow-y: auto;
  overflow: auto; min-height: 0; flex: 1; }
.intro-head { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.intro-title { font-size: var(--fs-control); }
/* the strip must NEVER flex-shrink: on a short panel the chips collapsed to a
   sliver behind the controls (founder screenshot, 2026-08-24) — the panel
   scrolls instead */
.intro-slots { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 2px;
  flex-shrink: 0; }
.intro-slot { display: flex; flex-direction: column; gap: 4px; align-items: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 6px; cursor: pointer; color: var(--muted); font-size: var(--fs-micro); flex: 0 0 auto; }
.intro-slot.sel { border-color: var(--accent); color: var(--text); }
.intro-thumb { width: 128px; height: 72px; border-radius: 4px; background: var(--surface-3); display: block; }
.intro-controls { display: grid; grid-template-columns: repeat(3, minmax(200px, 1fr));
  gap: 16px; align-items: start; }
.intro-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.intro-radios { display: flex; gap: 6px; flex-wrap: wrap; }
.intro-radios button { background: var(--panel); border: 1px solid var(--line);
  color: var(--muted); border-radius: 6px; padding: 5px 10px; cursor: pointer; font-size: var(--fs-micro); }
.intro-radios button.on { border-color: var(--accent); color: var(--text); }
.intro-radios button:disabled { opacity: .45; cursor: default; }
.intro-row { display: flex; align-items: center; gap: 8px; font-size: var(--fs-micro); color: var(--muted); }
.intro-row input[type="range"] { flex: 1; min-width: 90px; }
.intro-src { display: flex; flex-direction: column; gap: 6px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 8px; padding: 8px; }
.intro-ts { width: 92px; background: var(--bg); color: var(--text); border: 1px solid var(--line);
  border-radius: 6px; padding: 3px 6px; font: inherit; font-variant-numeric: tabular-nums; }
.intro-ts:focus { border-color: var(--accent); outline: none; }
.intro-slot.intro-add { justify-content: center; color: var(--muted); border-style: dashed; }
.intro-slot.intro-add:hover { border-color: var(--accent); color: var(--text); }
.intro-add-plus { font-size: var(--fs-title); line-height: 1; }
.intro-slot.drop { border-color: var(--accent); }
.intro-del { color: var(--muted); }
.intro-del:hover { color: var(--bad); border-color: var(--bad); }
.intro-empty { padding: 8px 2px; }
.intro-pickbar { position: absolute; z-index: 60; left: 50%; bottom: 46px; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 6px; background: var(--glass); color: var(--text);
  padding: 8px 12px; border-radius: 10px; width: min(640px, 94%); }
.intro-pickbar .ipb-row { display: flex; align-items: center; gap: 8px; }
.intro-pickbar .ipb-span { font-variant-numeric: tabular-nums; font-size: var(--fs-micro); white-space: nowrap; }
.intro-pickbar .ipb-ts { display: flex; align-items: center; gap: 4px; font-size: var(--fs-micro); color: var(--text-2); }
.intro-pickbar .ipb-track { position: relative; height: 26px; background: var(--line);
  border-radius: 6px; cursor: pointer; touch-action: none; }
.intro-pickbar .ipb-win { position: absolute; top: 0; bottom: 0; min-width: 8px;
  background: color-mix(in srgb, var(--accent) 45%, transparent);
  border: 1px solid var(--accent); border-radius: 6px; cursor: grab; }
.intro-pickbar .ipb-handle { position: absolute; top: -3px; bottom: -3px; width: 10px;
  background: var(--accent); border-radius: 4px; cursor: ew-resize; }
.intro-pickbar .ipb-l { left: -5px; }
.intro-pickbar .ipb-r { right: -5px; }
.intro-pickbar .ipb-meta { display: flex; justify-content: space-between;
  font-variant-numeric: tabular-nums; color: var(--text-2); }
.intro-pick { background: var(--panel); color: var(--text); border: 1px solid var(--line);
  border-radius: 10px; padding: 12px; max-width: 460px; width: 92vw; }
.intro-pick::backdrop { background: var(--scrim-modal); }
.intro-pick-h { display: flex; align-items: center; justify-content: space-between;
  font-weight: 600; margin-bottom: 8px; }
.intro-pick-list { display: flex; flex-direction: column; gap: 8px; max-height: 55vh; overflow: auto; }
.intro-pick-row { display: flex; gap: 10px; align-items: center; text-align: left;
  background: none; border: 1px solid var(--line); border-radius: 8px; padding: 6px;
  cursor: pointer; color: var(--text); }
.intro-pick-row:hover { border-color: var(--accent); }
.intro-pick-row .fineprint { display: block; }
.intro-pick-row.tc-current { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.intro-updating { color: var(--accent); animation: pulse 1.6s ease-in-out infinite; }
.intro-updating.done { color: var(--muted); animation: none; }
@keyframes pulse { 50% { opacity: 0.45; } }
.pv-pill { position: fixed; z-index: 200; left: 50%; bottom: 14px; transform: translateX(-50%);
  background: var(--glass); color: var(--accent); border: 1px solid var(--accent);
  padding: 6px 14px; border-radius: 999px; font-size: var(--fs-micro); pointer-events: none;
  animation: pulse 1.6s ease-in-out infinite; }
.pv-pill.done { color: var(--success); border-color: var(--success); animation: none; }
.pv-pill[hidden] { display: none; }
.audio-masters { display: flex; flex-direction: column; gap: 8px; padding: 4px 0; }
.am-row { display: flex; align-items: center; gap: 8px; font-size: var(--fs-micro); }
.am-row .muted { flex: 0 0 44%; }
.am-row input[type="range"] { flex: 1; min-width: 60px; }
.player-buffer .pb-text { display: flex; flex-direction: column; line-height: 1.25; }
.player-buffer .fineprint { color: var(--text-2); }
@media (max-width: 960px) { .intro-controls { grid-template-columns: 1fr; } }

/* --- the free trial (2026-09-07) --- */
.plan-trial { display: flex; flex-direction: column; align-items: center; gap: 6px; margin: 4px 0 14px; }
.plan-trial[hidden] { display: none; }   /* the class rule must not defeat `hidden` (2026-09-08) */
.plan-trial-fine { font-size: var(--fs-micro); margin: 0; }
.trial-banner { display: flex; gap: 12px; align-items: center; justify-content: center;
  padding: 6px 12px; font-size: var(--fs-secondary); background: var(--accent-dim); color: inherit; }
.trial-banner[hidden] { display: none; }

/* AFFILIATES (2026-09-10): the referred visitor's offer, in the plan gate */
.referral-note { grid-column: 1 / -1; margin: 0 0 12px; padding: 10px 14px; border-radius: 10px;
  background: var(--accent-wash); color: inherit; font-size: var(--fs-control); }
.plan-then { font-size: var(--fs-secondary); opacity: 0.7; margin-top: 2px; font-weight: 400; }
.plan-was { opacity: 0.55; font-weight: 400; font-size: var(--fs-section); margin-right: 2px; }
.plan-trial-last { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.plan-trial-warn { margin: 8px 0 0; font-size: var(--fs-secondary); color: var(--warn); }
.plan-trial-warn[hidden] { display: none; }

/* ===== C3 (2026-09-11): Generation Options. Configuration left, a sticky "This edit" summary and
   purchase panel right (DESIGN.md); one column at the 960px breakpoint. Page-local composition on
   the Stage B primitives; the quote, credit and Generate logic are untouched. ===== */
.wiz.gen { max-width: 1120px; }
.gen-body { display: grid; grid-template-columns: minmax(0, 1fr) 300px; column-gap: 32px; align-items: start; }
.gen-config { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
/* section labels become eyebrows: same words, quieter voice */
.gen-config .qp-label { font-size: var(--fs-micro); font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); margin: 28px 0 10px; }
.gen-config > .qp-label:first-child, .gen-config > :first-child .qp-label:first-child { margin-top: 0; }
.gen-config .mode-pick { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 0; }
/* an option card stacks: radio + name (+ AI chip) on line 1, the description on line 2 */
.gen-config .mode-opt { display: flex; flex-wrap: wrap; align-items: center; column-gap: 8px; row-gap: 3px; border-radius: 12px; padding: 12px 14px; font-size: var(--fs-secondary); }
.gen-config .mode-opt input { order: 0; margin: 0; }
.gen-config .mode-opt b { order: 1; font-size: var(--fs-body); }
.gen-config .mode-opt .ai-chip { order: 2; }
.gen-config .mode-opt > .muted { order: 3; flex-basis: 100%; padding-left: 24px; color: var(--muted); }
.gen-config .game-picks { margin: 0; }
.gen-config .game-pick { background: var(--surface-2); border: 1px solid transparent; border-radius: 8px; }
.gen-config .game-pick.all { border-style: dashed; border-color: var(--line); background: transparent; }
.gen-config .cutlen { background: var(--surface-2); border-radius: 12px; padding: 16px; margin: 0; }
.gen-config .fineprint.fullgames-row { margin-top: 10px; }
/* the summary: a card that reads as the purchase decision */
.gen-summary { position: sticky; top: 72px; background: var(--surface-2); border-radius: 12px; padding: 20px; display: flex; flex-direction: column; gap: 14px; }
.gen-summary .eyebrow { margin: 0; }
.gs-rows { display: flex; flex-direction: column; gap: 8px; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.gs-row { display: flex; justify-content: space-between; gap: 12px; font-size: var(--fs-control); }
.gs-k { color: var(--muted); }
.gs-v { font-weight: 500; text-align: right; min-width: 0; }
.gs-v .qp-games { margin: 0; font-size: var(--fs-control); font-weight: 500; color: var(--text); }
.gen-summary .quality-pick { margin: 0; }
.gen-summary .quality-pick.hidden { display: none; }
.gen-summary .qp-price { font-family: var(--mono); font-size: var(--fs-title); font-weight: 700; font-variant-numeric: tabular-nums; margin: 0 0 4px; letter-spacing: -0.02em; }
.gen-summary .qp-note { margin: 4px 0 0; }
.gen-summary .est-range, .gen-summary .est-long { margin: 0; }
.gen-summary .qp-balance { margin: 0; }
.gen-summary .wiz-actions { flex-direction: column; align-items: stretch; gap: 8px; margin: 4px 0 0; }
.gen-summary #genBtn { width: 100%; text-align: center; }
.gen-summary #backBtn { align-self: flex-start; }
@media (max-width: 960px) {
  .gen-body { display: block; }
  .gen-summary { position: static; margin-top: 24px; }
}

/* ===== C4 (2026-09-11): editor polish. Surfaces, not outlines; the stage on the video bed; the
   compact sidebar rail inside a project; per-clip atlas thumbnails; the accent selection ring.
   Geometry (bin 240, inspector 292, heads 148, lanes 64/40/56/48, panel 330) is untouched. ===== */
.sr-ico { display: none; }                                     /* icons appear only on the compact rail */
@media (min-width: 961px) {
  body.in-editor .sidebar { width: 56px; padding: 12px 8px; gap: 4px; }
  body.in-editor .side-row { padding: 9px 0; display: grid; place-items: center; }
  body.in-editor .side-row .sr-sub { display: none; }
  /* the NAME stays in the accessibility tree (the icon is aria-hidden, so it is the control's
     accessible name); visually hidden, never display:none (review, 2026-09-11) */
  body.in-editor .side-row .sr-name { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
  body.in-editor .side-row { position: relative; }
  body.in-editor .sr-ico { display: block; color: var(--muted); line-height: 0; }
  body.in-editor .side-row.active .sr-ico { color: var(--accent); }
  body.in-editor .side-row:hover .sr-ico { color: var(--text); }
  body.in-editor .side-row.feedback-open { margin-top: auto; }
}
/* four levels inside the editor: chrome on surface-1, panels on surface-2, the stage on the bed */
.ed2 .ed-bar { background: var(--surface-1); border-color: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: none; }
.ed2 .media-panel, .ed2 .ed-insp, .ed2 .tl-panel { background: var(--surface-2); border-color: transparent; }
.ed2 .player-wrap { border-color: transparent; }
.ed2 .tl-heads { border-right-color: var(--line); }
.ed2 .tl-toolbar { border-bottom-color: var(--line); }
.ed2 .media-panel .mp-head, .ed2 .insp-h2 { border-bottom-color: var(--line); }
/* selected clip: the accent ring, one language for "selected" across the editor */
.ed2 .tl-clip.sel { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-edge); }
/* clip thumbnails: real frames at the clip's height, tiled, never stretched */
.tc-thumbs { display: flex; align-items: stretch; overflow: hidden; opacity: 0.6; }
.tc-thumbs > i { display: block; flex: none; height: 100%; background-repeat: no-repeat; }
.tl-clip.sel .tc-thumbs, .tl-clip:hover .tc-thumbs { opacity: 0.75; }

/* ===== C5 (2026-09-11): ancillary surfaces. ONE dialog primitive on surface-4 (feedback, account,
   expiry, music picker, the sign-in card), toasts on the same overlay surface, the plan gate's cards
   as ordinary cards on the canvas, the legal footer at its real ink. No copy changes. ===== */
.dialog, .feedback-dialog, .expiry-modal, .mm-card, .auth-card {
  background: var(--surface-4); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow-overlay); color: var(--text); padding: 22px 24px;
}
.dialog::backdrop, .feedback-dialog::backdrop, .expiry-modal::backdrop { background: var(--scrim-modal); }
.dialog h3, .feedback-dialog h3, .expiry-modal h3, .mm-card h3 { margin: 0 0 6px; font-size: var(--fs-section); font-weight: 600; letter-spacing: -0.01em; }
.feedback-dialog { max-width: 440px; width: min(92vw, 440px); }
.expiry-modal { width: min(92vw, 460px); max-width: 460px; }
.mm-card { width: min(520px, 92vw); }
.feedback-dialog textarea { margin-top: 12px; }
.feedback-actions { margin-top: 16px; }
.account-dialog .account-buys { margin-top: 14px; }
.ws-section { margin-top: 16px; padding-top: 12px; }
/* toasts sit on the overlay surface like every other floating thing */
.toast { background: var(--surface-4); border-color: var(--line); }
/* the sign-in card: the dialog primitive, the go button at the 40px large-button height */
.auth-card { width: min(92vw, 340px); padding: 24px; gap: 12px; }
.auth-sub { margin: -4px 0 4px; }
.auth-field { gap: 5px; font-size: var(--fs-secondary); }
.auth-go { margin-top: 4px; height: 40px; padding: 0 12px; }
.auth-alt .linkish, .auth-field .linkish { font-size: var(--fs-secondary); }
/* the plan gate: a page, not a modal; the cards carry the surface, the eyebrow-style foot stays muted */
.plan-gate-card > .muted { max-width: 60ch; }
.plan-cards { gap: 16px; margin-top: 20px; }
.plan-card { padding: 20px 22px; }
/* the legal footer reads at its real ink (the 0.72 opacity pushed it under contrast) */
.site-legal { opacity: 1; color: var(--muted); }
.site-legal .legal-links a { color: var(--muted); }

/* ===== PHONE composition (2026-09-11, the founder's phone). Header, nav strip, intake card and
   project rows get a DELIBERATE phone layout instead of wrapped desktop chrome. Declared LAST so
   every rule here wins the cascade over the desktop rules above (the shared 960px block near the
   top of the file lost that fight for the intake card and the feedback tab). ===== */
@media (max-width: 960px) {
  /* header: ONE row. Brand left; credits, Account and the language control right. */
  .app-header, .topbar { flex-wrap: nowrap; gap: 8px; padding: 10px 12px; min-height: 52px; }
  .topbar .brand { font-size: var(--fs-body); gap: 8px; flex: none; margin-right: auto; }
  .topbar-right { gap: 6px; flex: none; margin-left: 0; }
  .topbar .credits-chip { height: 24px; line-height: 22px; padding: 0 8px; font-size: var(--fs-micro); }
  .topbar .account-btn { padding: 0 10px; }
  /* the language select collapses to a globe control; it is still the same <select> (its
     aria-label and the native picker on tap are unchanged). The stroke is --muted's hex in a
     data URI, the documented select exception. */
  .topbar .lang-switch { width: 34px; padding: 0; color: transparent; text-shadow: none;
    background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ba1a8' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18'/%3E%3C/svg%3E") no-repeat center / 18px 18px; }
  .topbar .lang-switch option { color: var(--text); }
  /* nav strip: three tabs that fit, no horizontal scroll, Send feedback is a tab like the others */
  .sidebar { padding: 8px 12px; gap: 4px; align-items: center; }
  .sidebar .side-row, .sidebar .side-row.feedback-open { width: auto; flex: none; padding: 8px 10px; justify-content: center; }
  .sidebar .side-row .sr-name, .sidebar .side-row.flagship .sr-name { font-size: var(--fs-control); }
  /* project rows: title, then the status and expiry chips, then the metadata line, then actions */
  .video-row { flex-wrap: wrap; gap: 8px 10px; padding: 12px 14px; align-items: center; }
  .video-row .title { order: 0; flex: 1 1 100%; }
  .video-row .chip { order: 1; }
  .video-row::before { order: 2; }
  .video-row .meta { order: 3; }
  .video-row::after { content: ""; order: 4; flex-basis: 100%; height: 0; }
  .video-row .row-dl, .video-row .row-ren, .video-row .row-del { order: 5; opacity: 1; }
  .video-row .row-dl { margin-right: auto; }
}

/* ===== Export quality list (native-export program, 2026-09-12): rows inside the Export menu ===== */
.export-quality { display: flex; flex-direction: column; gap: 4px; padding: 2px 0 8px; }
.export-quality .eq-row { display: flex; align-items: center; gap: 8px; font-size: var(--fs-control);
  color: var(--text); padding: 4px 2px; border-radius: 6px; cursor: pointer; white-space: nowrap; }
.export-quality .eq-row:hover { background: var(--surface-hover); }
.export-quality .eq-row input { accent-color: var(--accent); margin: 0; }
.export-quality .eq-hint { margin: 4px 0 0; white-space: normal; max-width: 34ch; }

/* --- manual text overlays (Phase 4b, 2026-09-14): the vendored OFL faces (the same files
   libass burns with, vodsmith/web/fonts/LICENSES.md), the thin graphics lane and the Text
   inspector. Lane colour is a token like the other lanes (colour is information). --- */
@font-face { font-family: "Anton"; src: url(fonts/Anton-Regular.ttf) format("truetype"); font-weight: 400; font-display: block; }
@font-face { font-family: "Poppins"; src: url(fonts/Poppins-SemiBold.ttf) format("truetype"); font-weight: 600; font-display: block; }
@font-face { font-family: "Varela Round"; src: url(fonts/VarelaRound-Regular.ttf) format("truetype"); font-weight: 400; font-display: block; }
@font-face { font-family: "Fjalla One"; src: url(fonts/FjallaOne-Regular.ttf) format("truetype"); font-weight: 400; font-display: block; }
:root { --lane-text: #4f8f8f; --clip-text: #2b4a4a; --clip-text-2: #1f3838; --clip-text-edge: #4f8f8f; }
.tl-track.text-lane { height: 26px; }
.tl-clip.text { top: 3px; bottom: 3px; background: linear-gradient(180deg, var(--clip-text), var(--clip-text-2)); border-color: var(--clip-text-edge); padding: 0 6px; }
.tl-clip.text .tc-title { color: var(--text); font-size: var(--fs-micro); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-clip.text .tc-t { margin-right: 4px; opacity: 0.8; font-size: 10px; }
.text-shelf { display: flex; flex-wrap: wrap; gap: 6px; }
.gfx-kv { display: grid; grid-template-columns: 5.5em 1fr; align-items: center; gap: 6px; margin: 6px 0; font-size: var(--fs-micro); }
.gfx-kv .muted { white-space: nowrap; }
.gfx-kv input[type="text"], .gfx-kv input[type="number"], .gfx-kv select { width: 100%; min-width: 0; font-size: var(--fs-micro); }
.gfx-kv input[type="color"] { width: 42px; height: 22px; padding: 0; border: 1px solid var(--line); background: none; }
.gfx-kv .gfx-pair { display: flex; gap: 6px; align-items: center; }
.gfx-kv .gfx-pair input { flex: 1; }
.gfx-acts { display: flex; gap: 6px; margin-top: 8px; }

/* ---------------------------------------------------------------------------------
   THE SHORT EDITOR (Stage 2, 2026-09-16)

   It IS the production editor, so this is deliberately a handful of rules rather than a
   second stylesheet: the stage frames 9:16 instead of filling the pane, and the inspector
   gains the layout control. Everything else — timeline, library, clip bar, transport —
   is the editor the creator already knows.
   --------------------------------------------------------------------------------- */
body.in-short-editor .ed-stage {
  display: flex; flex-direction: column; align-items: center;
}
body.in-short-editor .player-wrap {
  /* the phone frame, centred and sized by the pane's HEIGHT so it never grows a
     column taller than the viewport */
  flex: 1; width: auto; aspect-ratio: 9 / 16; max-width: 100%;
  margin: 0 auto; align-self: center;
}
body.in-short-editor .player-wrap > #reelCanvas { object-fit: contain; }
body.in-short-editor .ed-stage > *:not(.player-wrap) { width: 100%; }
.cb-layout { margin-top: 10px; }
.cb-layout .seg-row { display: flex; gap: 4px; flex-wrap: wrap; margin: 6px 0; }
.cb-layout .seg.on { background: var(--accent); color: var(--accent-ink); }
.cb-layout .vol-row { display: flex; align-items: center; gap: 8px; }
.cb-layout .vol-row input[type="range"] { flex: 1; min-width: 0; }
.ed-bar #sdNote { margin: 0 0 0 8px; }
.ed-bar .ed-sub { color: var(--muted); font-size: var(--fs-micro);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 22ch; }
/* the Short's music shelf: the track name, then its provenance on its own line —
   inline it read as one run-on sentence ("...mp3 in this project") */
#sdMusic .media-item { display: block; }
#sdMusic .media-item b { display: block; overflow-wrap: anywhere; }
#sdMusic .mi-sub { display: block; }
/* the last run failed but the cut is still here: the message rides above the editor
   instead of replacing it (2026-09-16) */
.run-error-banner { display: flex; align-items: center; gap: 12px; margin-bottom: 8px;
  padding: 8px 12px; border-radius: 8px; background: var(--panel);
  border: 1px solid var(--bad); color: var(--text); font-size: var(--fs-secondary); }
.run-error-banner span { flex: 1; min-width: 0; }
