:root {
  --bg: #0d0d10;
  --bg-elev: #16161b;
  --bg-elev-2: #1d1d24;
  --border: #2a2a33;
  --text: #ececf0;
  --text-dim: #a0a0ad;
  --accent: #ffb300;
  --accent-soft: rgba(255, 179, 0, 0.18);
  --danger: #ff6b6b;
  --ok: #5dd39e;
  --radius: 12px;
}

* { box-sizing: border-box; }

/* Force the `hidden` HTML attribute to actually hide elements. The browser's
   default UA rule (`[hidden] { display: none }`) loses to any class selector
   that sets `display`, so without this every flex/grid panel marked `hidden`
   in the markup (resume banner, download-ready row, waiting panel, progress
   panel, etc.) would render at page-load with its default text. That's the
   bug behind "Resuming previous wash…" appearing for users who don't
   actually have an active wash. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: radial-gradient(circle at 15% -10%, #2a1d00 0%, #0d0d10 55%) fixed;
  color: var(--text);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  min-height: 100vh;
}

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

.muted { color: var(--text-dim); }
.small { font-size: 13px; }
.error { color: var(--danger); margin: 8px 0 0; }

/* ----- Top bar ----- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 24px;
  background: rgba(0, 0, 0, 0.35);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
  backdrop-filter: blur(12px);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  letter-spacing: 0.2px;
}

.brand-text { font-size: 17px; }

.nav {
  display: flex;
  align-items: center;
  gap: 12px;
}

.nav a {
  color: var(--text);
  font-weight: 500;
  padding: 6px 10px;
  border-radius: 8px;
}
.nav a:hover {
  background: var(--bg-elev);
  text-decoration: none;
}

.user-pill {
  background: var(--accent-soft);
  color: var(--accent);
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
}

/* Credits balance pill — same shape as user-pill but neutral by default,
   click-through to /pricing. Goes red when balance is dangerously low so
   the user notices before submitting a wash that'll bounce. */
.credits-pill {
  background: rgba(255,255,255,0.06);
  color: var(--text);
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid var(--border);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.credits-pill:hover {
  background: rgba(255,255,255,0.1);
  text-decoration: none;
}
.credits-pill .credits-label {
  font-weight: 400;
  color: var(--text-dim);
  font-size: 12px;
}
.credits-pill.is-low {
  background: rgba(255, 107, 107, 0.12);
  border-color: rgba(255, 107, 107, 0.4);
  color: var(--danger);
}
.credits-pill.is-low .credits-label { color: var(--danger); opacity: 0.85; }

/* "Insufficient credits" banner shown when a wash submission gets a 402
   back. Tells the user how short they are and where to top up. */
.credit-warning {
  background: rgba(255, 107, 107, 0.10);
  border: 1px solid rgba(255, 107, 107, 0.35);
  color: var(--text);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 12px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.credit-warning strong { color: var(--danger); }
.credit-warning a.btn { white-space: nowrap; }

/* ----- Container ----- */

.container {
  max-width: 920px;
  margin: 0 auto;
  padding: 32px 24px 80px;
}

.hero h1 {
  font-size: 32px;
  margin: 0 0 6px;
  letter-spacing: -0.5px;
}
.hero p {
  margin: 0;
  font-size: 15px;
  max-width: 640px;
}

/* ----- Panels / forms ----- */

.panel {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  margin: 24px 0;
}

.panel h2 {
  margin: 0 0 14px;
  font-size: 18px;
  letter-spacing: -0.2px;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.panel-head h2 {
  margin: 0;
}
.panel-head-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.panel-row {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: flex-end;
}

/* ---- Wash type chip grid ---- */

.chip-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 8px;
}

.chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  user-select: none;
  transition: background 0.12s, border-color 0.12s;
}
.chip:hover {
  border-color: #3a3a45;
}
.chip input[type=checkbox] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 0; height: 0;
}
.chip .chip-dot {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  border: 1.5px solid #555;
  flex: 0 0 auto;
  position: relative;
  transition: background 0.12s, border-color 0.12s;
}
.chip .chip-label {
  font-size: 13px;
  font-weight: 500;
  line-height: 1.25;
}
.chip.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.chip.active .chip-dot {
  background: var(--accent);
  border-color: var(--accent);
}
.chip.active .chip-dot::after {
  content: "";
  position: absolute;
  inset: 2px 4px 4px 2px;
  border-right: 2px solid #1a1a1a;
  border-bottom: 2px solid #1a1a1a;
  transform: rotate(45deg) translate(-1px, -1px);
}

/* Filter chips with a per-filter strength slider sit in a column so the
   header row (dot + label) stacks above the slider row. */
.chip.has-strength {
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding: 9px 12px 8px;
}
.chip.has-strength .chip-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 18px;
}
.chip-strength {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: default;
}
.chip-strength input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  flex: 1 1 auto;
  height: 4px;
  border-radius: 999px;
  /* Three-tone track so the center "default" is visually distinct. */
  background: linear-gradient(
    to right,
    #2a2a30 0%,
    #444 49%,
    var(--accent) 50%,
    #444 51%,
    #2a2a30 100%
  );
  outline: none;
  cursor: ew-resize;
}
.chip-strength input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #1a1a1a;
  cursor: ew-resize;
  box-shadow: 0 0 0 1px #2a2a30;
}
.chip-strength input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #1a1a1a;
  cursor: ew-resize;
}
.chip-strength input[type="range"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.chip-strength-value {
  flex: 0 0 auto;
  width: 38px;
  text-align: right;
  color: var(--text-dim);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  user-select: none;
}
/* When the chip isn't selected, dim the slider so it reads as "armed but
   not currently doing anything". The value is still saved, so re-selecting
   the chip restores the user's chosen strength. */
.chip:not(.active) .chip-strength {
  opacity: 0.55;
}
.chip-strength.layout-only {
  display: none;
}

/* ----- Per-wash-chip "Include IG filter" toggle -----
   Lives in a second row at the bottom of every wash-type chip. Default ON.
   Click toggles between yellow-accented (filter applied) and dim-grey
   (filter skipped for this wash type). Stops click propagation so it
   doesn't double-toggle the parent wash chip. */
.chip.has-filter-toggle {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
}
.chip.has-filter-toggle .chip-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.chip-filter-toggle {
  display: flex;
  justify-content: flex-start;
}
.chip-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  border-radius: 999px;
  border: 1px solid #3a3a45;
  background: #1d1d24;
  color: var(--text-dim);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
  user-select: none;
}
.chip-filter-btn .chip-filter-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #3a3a45;
  flex: 0 0 auto;
}
.chip-filter-btn.is-on {
  border-color: var(--accent);
  background: rgba(255, 179, 0, 0.18);
  color: #ffcd5b;
}
.chip-filter-btn.is-on .chip-filter-dot {
  background: var(--accent);
}
.chip-filter-btn:hover {
  border-color: #4a4a55;
}
.chip-filter-btn.is-on:hover {
  border-color: #ffd76b;
}
.chip-filter-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* When the wash chip itself isn't selected, dim the filter toggle so it
   reads as "this won't matter unless you check the chip first". */
.chip:not(.active) .chip-filter-toggle {
  opacity: 0.55;
}

/* ---- Segmented control (quality) ---- */

.seg {
  display: inline-flex;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 3px;
  gap: 2px;
}
.seg-btn {
  background: transparent;
  border: none;
  color: var(--text-dim);
  padding: 7px 14px;
  font: inherit;
  font-weight: 600;
  font-size: 13px;
  border-radius: 7px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.seg-btn:hover { color: var(--text); }
.seg-btn.active {
  background: var(--accent);
  color: #1a1a1a;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 220px;
}

.field > span {
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 500;
}

.field.checkbox {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.field.checkbox > span { color: var(--text); font-size: 14px; }

/* ---- Per-output extras ---- */
.extras-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 10px;
}
.extra {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-elev-2);
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}
.extra:hover { border-color: var(--accent); }
.extra input[type=checkbox] { margin-top: 3px; flex-shrink: 0; }
.extra-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.extra-text strong { color: var(--text); font-size: 14px; font-weight: 600; }
.extra-text small { color: var(--text-dim); font-size: 12px; line-height: 1.4; }

/* ---- Progress panel ---- */
.progress-panel {
  margin-top: 16px;
  padding: 16px 18px;
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.progress-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}
.progress-head strong { color: var(--text); font-size: 15px; }
.progress-bar {
  height: 8px;
  background: var(--bg-elev-2);
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 12px;
}
.progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #ffb300, #ff7a00);
  transition: width 200ms ease;
}
.progress-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 320px;
  overflow-y: auto;
}
.progress-row {
  display: grid;
  grid-template-columns: 18px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 13px;
  border: 1px solid transparent;
}
.progress-row-name { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.progress-row-meta { color: var(--text-dim); font-size: 12px; flex-shrink: 0; }
.progress-row-state {
  width: 14px;
  height: 14px;
  border-radius: 999px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.progress-row.queued { color: var(--text-dim); }
.progress-row.running { background: rgba(255, 179, 0, 0.05); border-color: rgba(255, 179, 0, 0.4); }
.progress-row.running .progress-row-state {
  background: var(--accent);
  border-color: var(--accent);
  animation: pulse 1.2s ease-in-out infinite;
}
.progress-row.done .progress-row-state {
  background: #2ecc71;
  border-color: #2ecc71;
}
.progress-row.done .progress-row-state::after {
  content: "";
  display: block;
  text-align: center;
  font-size: 11px;
  color: #0d2218;
  font-weight: 700;
  line-height: 13px;
}
.progress-row.error { background: rgba(231, 76, 60, 0.07); border-color: rgba(231, 76, 60, 0.4); }
.progress-row.error .progress-row-state {
  background: #e74c3c;
  border-color: #e74c3c;
}
.progress-row.error .progress-row-state::after {
  content: "!";
  display: block;
  text-align: center;
  font-size: 11px;
  color: #fff;
  font-weight: 700;
  line-height: 13px;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 179, 0, 0.6); }
  50%      { box-shadow: 0 0 0 4px rgba(255, 179, 0, 0); }
}

input[type=text],
input[type=password],
select {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 9px 12px;
  border-radius: 8px;
  font: inherit;
  outline: none;
}
input[type=text]:focus,
input[type=password]:focus,
select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

input[type=checkbox] {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

/* (DR-347 QA fix #5) Dropdown readability. Browsers render <option>
   and <optgroup> with their own native white-bg/black-text fallback
   regardless of the parent <select>'s color rules — including in
   dark mode where the rest of the form already styles correctly.
   Force both background AND color so the trained-LoRA option (and
   every other option) is readable in the dropdown menu and in the
   selected position. The native menu background follows --bg-elev-2
   in browsers that honour it (Chrome 118+, Firefox 116+); older
   browsers fall back to the explicit hex matching the panel theme. */
option,
optgroup {
  background-color: #1a1a1a;
  color: var(--text);
}
optgroup {
  font-weight: 600;
  color: var(--text-dim);
}
option:checked,
option:hover {
  background-color: var(--accent-soft);
  color: var(--text);
}

select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-dim) 50%),
                    linear-gradient(135deg, var(--text-dim) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 32px;
}

.form-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}
.form-row input,
.form-row select { flex: 1 1 160px; }

/* ----- Buttons ----- */

.btn {
  border: none;
  background: var(--bg-elev-2);
  color: var(--text);
  padding: 10px 16px;
  border-radius: 10px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: background 0.15s, transform 0.05s;
}
.btn:hover:not(:disabled) { background: #2a2a33; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-primary {
  background: var(--accent);
  color: #1a1a1a;
}
.btn-primary:hover:not(:disabled) { background: #ffc233; }

.btn-ghost {
  background: transparent;
  border: 1px solid var(--border);
}
.btn-ghost:hover:not(:disabled) { background: var(--bg-elev-2); }

.btn-danger {
  background: transparent;
  color: var(--danger);
  border: 1px solid #4a2a2a;
}
.btn-danger:hover:not(:disabled) { background: rgba(255, 107, 107, 0.1); }

.btn-sm { padding: 6px 10px; font-size: 13px; border-radius: 8px; }
.btn-lg { padding: 14px 22px; font-size: 16px; }

.btn-spinner {
  width: 14px;
  height: 14px;
  border: 2px solid rgba(0, 0, 0, 0.25);
  border-top-color: #1a1a1a;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ----- Drop zone ----- */

.dropzone {
  border: 2px dashed var(--border);
  border-radius: 16px;
  padding: 56px 20px;
  text-align: center;
  background: var(--bg-elev);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
  outline: none;
}
.dropzone:hover, .dropzone:focus {
  border-color: var(--accent);
  background: var(--bg-elev-2);
}
.dropzone.dragover {
  border-color: var(--accent);
  background: var(--accent-soft);
  border-style: solid;
}

.dropzone-icon { margin-bottom: 14px; }
.dropzone-title { font-size: 22px; font-weight: 700; }
.dropzone-sub { margin-top: 6px; color: var(--text-dim); }
.dropzone-sub .link { color: var(--accent); text-decoration: underline; }
.dropzone-meta { margin-top: 12px; font-size: 13px; }

/* ----- File list ----- */

.file-list-wrap {
  margin: 18px 0 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.file-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 2px 0;
}
.file-list-head strong {
  font-size: 14px;
  color: var(--text);
}

.file-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
}

/* Banner shown while reattaching to a wash that was running before reload. */
.resume-banner {
  margin: 14px 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border: 1px solid #4a3a1a;
  background: rgba(255, 179, 0, 0.10);
  border-radius: 10px;
  color: var(--text);
  font-size: 13px;
}

.file-card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.file-card img,
.file-card video {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 6px;
  background: #000;
  display: block;
}
.file-card.video .media-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  background: rgba(255, 179, 0, 0.95);
  color: #1a1a1a;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 2px 6px;
  border-radius: 4px;
  z-index: 1;
}
.file-card .file-name {
  font-size: 12px;
  color: var(--text-dim);
  word-break: break-all;
  line-height: 1.3;
}
.file-card .file-size { font-size: 11px; color: var(--text-dim); }
.file-card .file-remove {
  position: absolute;
  top: 6px; right: 6px;
  background: rgba(0,0,0,0.7);
  color: #fff;
  border: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}

/* ----- Actions / status ----- */

.actions {
  display: flex;
  gap: 10px;
  margin-top: 22px;
  align-items: center;
}

.status {
  margin-top: 18px;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  font-size: 14px;
}
.status.ok { border-color: #2a4a3a; background: rgba(93, 211, 158, 0.08); color: var(--ok); }
.status.err { border-color: #4a2a2a; background: rgba(255, 107, 107, 0.08); color: var(--danger); }

/* ----- Tables ----- */

.table-wrap { overflow-x: auto; }

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.data-table th, .data-table td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
  text-align: left;
}
.data-table th {
  color: var(--text-dim);
  font-weight: 500;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.data-table tr:last-child td { border-bottom: none; }
.data-table .row-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}
.badge.admin { background: var(--accent-soft); color: var(--accent); }
.badge.user { background: rgba(255,255,255,0.06); color: var(--text-dim); }
.badge.on { background: rgba(93, 211, 158, 0.15); color: var(--ok); }
.badge.off { background: rgba(255, 107, 107, 0.15); color: var(--danger); }
.badge.pending { background: rgba(255, 179, 0, 0.18); color: var(--accent); margin-left: 8px; }

/* ----- Auth page ----- */

.auth-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 440px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 32px 28px;
}

.auth-header {
  text-align: center;
  margin-bottom: 24px;
}
.auth-header h1 {
  margin: 12px 0 4px;
  font-size: 22px;
}
.auth-header .muted { font-size: 13px; }
.hex-logo { display: inline-block; }

/* Container the Clerk SignIn / SignUp widget mounts into. Two CSS rules,
   both on a container we own — no Clerk-internal class targeting, no
   !important overrides, no MutationObservers. The widget gets the
   horizontal centering it needs and its own internal layout (including
   the "Secured by Clerk" branding badge) is left untouched. */
#clerk-sign-in,
#clerk-sign-up {
  text-align: center;
  margin: 0 auto;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.auth-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  color: var(--text-dim);
}
.auth-form .btn { margin-top: 6px; justify-content: center; }

/* Sign-in / request-access tabs at the top of the auth card. */
.auth-tabs {
  display: flex;
  gap: 4px;
  background: var(--bg-elev-2);
  padding: 4px;
  border-radius: 10px;
  margin: 0 0 18px;
}
.auth-tab {
  flex: 1 1 0;
  background: transparent;
  border: none;
  color: var(--text-dim);
  padding: 8px 10px;
  font: inherit;
  font-weight: 600;
  font-size: 13px;
  border-radius: 7px;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.auth-tab:hover { color: var(--text); }
.auth-tab.active {
  background: var(--accent);
  color: #1a1a1a;
}
.ok-msg { color: var(--ok); }

/* Download-ready row inside the progress panel. Sits between the progress
   bar and the per-task list once the wash finishes; keeps the user in the
   driver's seat (no auto-download). */
.download-ready {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  margin: 4px 0 6px;
  border: 1px solid #4a3a1a;
  background: rgba(255, 179, 0, 0.10);
  border-radius: 10px;
}
.download-ready .btn { white-space: nowrap; }

/* ---- Server activity / queue panel ----
   Shown to every signed-in user. Lists currently-running and waiting jobs
   across the whole server so users can see "alice is mid-wash, you're #2".
   Anonymized for everyone else's jobs (username + progress only); your own
   row is highlighted. */
.queue-panel {
  border: 1px solid #2c2c30;
  background: #131318;
  border-radius: 12px;
  padding: 12px 14px;
  margin: 8px 0;
}
.queue-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.queue-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.queue-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  background: #1b1b22;
  border: 1px solid #28282f;
}
.queue-row .qrow-main { flex: 1 1 auto; min-width: 0; }
.queue-row .qrow-bar,
.queue-row .qrow-actions {
  flex: 0 0 auto;
}
.queue-row.is-own {
  background: rgba(255, 179, 0, 0.10);
  border-color: #4a3a1a;
}
.queue-row .qrow-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.queue-row .qrow-name {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.queue-row .qrow-state {
  color: #a8a8b2;
  font-size: 12px;
}
.queue-row.is-own .qrow-name::after {
  content: " (you)";
  color: var(--accent);
  font-weight: 500;
}
.queue-row .qrow-bar {
  width: 140px;
  height: 6px;
  border-radius: 4px;
  background: #2a2a32;
  overflow: hidden;
}
.queue-row .qrow-bar-fill {
  height: 100%;
  background: var(--accent);
  width: 0%;
  transition: width 200ms ease;
}
.queue-row.is-waiting .qrow-bar { display: none; }
.queue-row.is-waiting .qrow-state::before {
  content: "";
}

/* Image-activity rows: lighter background + a small icon prefix to make
   them visually distinct from heavyweight video-job rows. No progress bar,
   no buttons. */
.queue-row.is-image {
  background: rgba(96, 165, 250, 0.06);
  border-color: #2a3a4a;
}
.queue-row.is-image .qrow-state::before {
  content: "";
}
.queue-row.is-image .qrow-bar,
.queue-row.is-image .qrow-actions {
  display: none;
}

/* Complete-recovery rows: show the download button + dismiss in place of
   the running progress bar. The .qrow-actions container is hidden by
   default and only revealed on .is-complete rows so the markup stays the
   same for every row state. */
.queue-row .qrow-actions {
  display: none;
  align-items: center;
  gap: 6px;
}
.queue-row.is-complete {
  border-color: #2a4a3a;
  background: rgba(93, 211, 158, 0.08);
}
.queue-row.is-complete .qrow-bar { display: none; }
.queue-row.is-complete .qrow-actions { display: inline-flex; }
.queue-row.is-complete .qrow-state::before { content: "Done "; }
.qrow-dl { white-space: nowrap; }
.qrow-dismiss {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid #3a3a45;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.qrow-dismiss:hover {
  border-color: var(--danger);
  color: var(--danger);
}

/* ---- Waiting-in-line block inside the progress panel ---- */
.waiting-panel {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  margin: 4px 0 6px;
  border: 1px dashed #4a3a1a;
  background: rgba(255, 179, 0, 0.06);
  border-radius: 10px;
}
.waiting-headline { font-size: 15px; }

/* ============================================================ */
/*  Mode tabs (Video / Image switcher at the top of the page)   */
/* ============================================================ */
.mode-tabs {
  display: flex;
  gap: 0;
  margin: 18px 0 22px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px;
  position: sticky;
  top: 0;
  z-index: 5;
  backdrop-filter: blur(8px);
}
.mode-tab {
  flex: 1;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-dim);
  padding: 10px 16px;
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-family: inherit;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.mode-tab:hover { color: var(--text); background: rgba(255, 255, 255, 0.03); }
.mode-tab.active {
  color: #1a1a1a;
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 6px 18px rgba(255, 179, 0, 0.18);
}
.mode-tab.active .mode-tab-sub { color: rgba(26, 26, 26, 0.75); }
.mode-tab-label { font-size: 16px; font-weight: 700; letter-spacing: 0.2px; }
.mode-tab-sub { font-size: 11px; color: var(--text-dim); }

.mode-panel { display: block; }

/* ============================================================ */
/*  Image tab                                                   */
/* ============================================================ */

.img-actionbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin: 0 0 16px;
  flex-wrap: wrap;
}
.img-actionbar-left { display: inline-flex; gap: 8px; flex-wrap: wrap; }
.img-actionbar-right { color: var(--text-dim); font-size: 13px; }

.img-settings {
  margin-bottom: 18px;
}
.img-settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px 22px;
}
.img-range-row, .img-single-row { display: flex; flex-direction: column; gap: 4px; }
.img-range-head {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--text-dim);
}
.img-range-head .img-range-value {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: #cfcfdc;
}
.img-range-controls { display: flex; gap: 8px; }
.img-range-controls input[type=range],
.img-single-row input[type=range] {
  flex: 1;
  width: 100%;
  accent-color: var(--accent);
  height: 4px;
}
.img-settings-checks {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.img-settings-checks label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
}

.img-dropzone {
  margin-top: 4px;
}

/* Compact drop zone — used while images are already queued, so the user
   can keep dropping more without the giant tile dominating the layout. */
.img-dropzone.is-compact {
  padding: 12px 16px;
  min-height: 0;
}
.img-dropzone.is-compact .dropzone-inner {
  flex-direction: row;
  gap: 10px;
  align-items: center;
  justify-content: center;
}
.img-dropzone.is-compact .dropzone-icon svg {
  width: 28px;
  height: 28px;
}
.img-dropzone.is-compact .dropzone-title {
  font-size: 14px;
  margin: 0;
}
.img-dropzone.is-compact .dropzone-sub,
.img-dropzone.is-compact .dropzone-meta {
  font-size: 12px;
  margin: 0;
}

/* Synthetic "No filter" chip — neutral option in the random pool.
   Same outer height as regular chips (we keep .has-strength on it) so
   the grid stays tidy. Dashed border in the off state, accent fill in
   the on state, and a dedicated explainer strip at the bottom in place
   of the strength slider. */
.chip.is-no-filter {
  border-style: dashed;
}
.chip.is-no-filter.active {
  border-style: solid;
  background: rgba(96, 165, 250, 0.10);
}
.chip-no-filter-sub {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px 8px;
  margin-top: auto;
  border-top: 1px dashed var(--border);
  min-height: 32px;
}
.chip-no-filter-tag {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(96, 165, 250, 0.18);
  color: #b8d4ff;
  white-space: nowrap;
}
.chip-no-filter-text {
  font-size: 11px;
  color: var(--text-dim);
  line-height: 1.3;
}

.img-toolbar {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px;
  margin: 0 0 14px;
}
.img-toolbar-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
/* Math preview shown right below Wash All — answers "what will this
   produce?" before the user clicks. Two parts: the equation (foreground
   color) and a short note (dimmed). */
.img-toolbar-math {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: baseline;
  font-size: 13px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
}
.img-toolbar-math-eq {
  font-variant-numeric: tabular-nums;
}
.img-toolbar-math-eq strong {
  color: var(--accent, #ffb300);
}
.img-toolbar-math-note {
  font-size: 12px;
}

/* Filter-mode toggle — row above the chip grid. Segmented control on
   the right + a single dynamic description line under it. */
.img-filter-mode {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 6px 0 12px;
}
.img-filter-mode-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.img-filter-mode-label {
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.img-filter-mode-desc {
  font-size: 12px;
}
.img-toolbar-actions {
  display: inline-flex;
  gap: 8px;
  flex-wrap: wrap;
}
.btn.btn-ok {
  background: var(--ok);
  color: #0d0d10;
  border: 1px solid var(--ok);
}
.btn.btn-ok:hover { filter: brightness(1.1); }

.img-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 12px;
  border-radius: var(--radius);
  transition: outline-color 120ms ease, background 120ms ease;
  outline: 2px dashed transparent;
  outline-offset: -2px;
}
.img-grid.dragover {
  outline-color: var(--accent, #ffb300);
  background: rgba(255, 179, 0, 0.06);
}
.img-card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: relative;
}
.img-card.is-washed {
  border-color: var(--ok);
  box-shadow: 0 0 0 1px rgba(93, 211, 158, 0.2);
}
.img-card-thumb {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #000;
  overflow: hidden;
}
.img-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.img-card-name {
  padding: 8px 10px 4px;
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.img-card-error {
  padding: 0 10px 6px;
  font-size: 11px;
  color: var(--danger);
}
.img-card-actions {
  display: flex;
  gap: 6px;
  padding: 0 8px 10px;
  flex-wrap: wrap;
}
.img-card-actions .btn { padding: 4px 10px; font-size: 12px; }
.img-card-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: #ffd966;
  pointer-events: none;
}
.img-card-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  background: var(--ok);
  color: #0d0d10;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  padding: 2px 6px;
  border-radius: 4px;
}
.img-card-badge.edits {
  top: 6px;
  left: 6px;
  right: auto;
  background: var(--accent);
}
.img-card-remove {
  position: absolute;
  top: 6px;
  right: 6px;
  background: rgba(0, 0, 0, 0.55);
  color: #ff8a8a;
  border: 1px solid rgba(255, 138, 138, 0.5);
  border-radius: 50%;
  width: 22px;
  height: 22px;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  display: none;
}
.img-card:hover .img-card-remove { display: inline-flex; align-items: center; justify-content: center; }
.img-card.is-washed .img-card-remove { right: auto; left: 6px; }

/* ============================================================ */
/*  Image editor modal                                          */
/* ============================================================ */
.img-editor-root {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.78);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.img-editor {
  background: #15151b;
  border: 1px solid var(--border);
  border-radius: 16px;
  width: min(1100px, 100%);
  max-height: 92vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.img-editor-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  gap: 12px;
}
.img-editor-head h3 {
  margin: 0;
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.img-editor-head-actions { display: inline-flex; gap: 8px; }
.img-editor-body {
  display: flex;
  gap: 16px;
  padding: 16px;
  flex: 1;
  min-height: 0;
}
.img-editor-side {
  width: 220px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  overflow-y: auto;
  max-height: 78vh;
  padding-right: 4px;
}
.img-editor-side h4 {
  margin: 0 0 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.img-editor-tools, .img-editor-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.img-editor-tools .tool-btn,
.img-editor-actions .tool-btn {
  background: #20202a;
  color: var(--text-dim);
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 7px 10px;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.img-editor-tools .tool-btn:hover,
.img-editor-actions .tool-btn:hover { background: #2a2a35; color: var(--text); }
.img-editor-tools .tool-btn.active {
  background: var(--accent);
  color: #1a1a1a;
  border-color: var(--accent);
}
.img-editor-tools .tool-btn:disabled,
.img-editor-actions .tool-btn:disabled { opacity: 0.35; cursor: not-allowed; }

.img-editor-prop {
  background: rgba(255, 179, 0, 0.05);
  border: 1px solid rgba(255, 179, 0, 0.2);
  border-radius: 8px;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.img-editor-prop-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.img-editor-prop h5 {
  margin: 0;
  font-size: 10px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--accent);
}
.img-editor-prop .delete-btn {
  background: transparent;
  border: 0;
  color: var(--danger);
  font-size: 11px;
  cursor: pointer;
}
.img-editor-prop label {
  font-size: 11px;
  color: var(--text-dim);
  display: block;
}
.img-editor-prop input[type=text],
.img-editor-prop textarea,
.img-editor-prop select {
  width: 100%;
  background: #0d0d10;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 6px 8px;
  font-size: 12px;
  font-family: inherit;
  resize: vertical;
}
.img-editor-prop .seg-row {
  display: flex;
  gap: 4px;
}
.img-editor-prop .seg-row button {
  flex: 1;
  background: #20202a;
  color: var(--text-dim);
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 5px;
  font-size: 11px;
  cursor: pointer;
}
.img-editor-prop .seg-row button.active {
  background: var(--accent);
  color: #1a1a1a;
}
.img-editor-prop .row-2 { display: flex; gap: 8px; align-items: center; }
.img-editor-prop input[type=color] {
  width: 24px;
  height: 24px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  padding: 0;
}
.img-editor-prop .checks { display: flex; gap: 12px; align-items: center; font-size: 11px; color: var(--text-dim); }
.img-editor-prop .checks label { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }

.img-editor-canvas-wrap {
  flex: 1;
  background: #0a0a0e;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  min-height: 360px;
}
.img-editor-canvas-wrap canvas {
  max-width: 100%;
  max-height: 78vh;
}
.img-editor-canvas-wrap.tool-blur canvas,
.img-editor-canvas-wrap.tool-crop canvas { cursor: crosshair; }
.img-editor-canvas-wrap.tool-caption canvas { cursor: text; }
.img-editor-tip {
  font-size: 11px;
  color: #666;
  padding: 4px 0 0;
}

/* Auth-state visibility helpers used across the public pages
   (landing / pricing / terms / privacy). pricing.js + the inline
   landing.html script set body.is-anon or body.is-auth on load; these
   rules switch which CTA / pill / button is visible.

   Hidden by default so the page doesn't flash both states before JS
   runs — better to show neither for ~150ms than both. */
.anon-only, .auth-only { display: none !important; }
body.is-anon .anon-only,
body.is-auth .auth-only { display: inline-flex !important; }
/* Sections (panels) inside <main> need block layout, not inline-flex. */
body.is-anon section.anon-only,
body.is-auth section.auth-only { display: block !important; }

/* ----- Public marketing pages ----------------------------------------
 *
 * Layout for /landing, /pricing (anon view), /terms, /privacy. Reuses
 * the dark-theme palette from :root and the .btn primitives — only
 * adds layout primitives unique to the public surface (full-width
 * sections, hero, feature grid, footer). UI polish pass at the end of
 * the integration phases will layer on better typography / spacing /
 * motion. This is the functional shell.
 */

.public-page {
  /* Reset the body's default container constraint (auth pages use
     .auth-page flex centering; public pages span the full viewport). */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.public-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 32px;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  position: sticky;
  top: 0;
  z-index: 10;
}
.public-topbar .brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
}
.public-topbar .brand-text {
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.2px;
}
.public-nav {
  display: inline-flex;
  align-items: center;
  gap: 14px;
}
.public-nav a {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 14px;
}
.public-nav a:hover { color: var(--text); }
.public-nav a.btn { color: #1a1a1a; }

.public-main {
  flex: 1 1 auto;
  max-width: 1080px;
  width: 100%;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

.public-hero {
  text-align: center;
  padding: 64px 0 48px;
}
.public-hero h1 {
  font-size: 44px;
  letter-spacing: -1px;
  line-height: 1.1;
  margin: 0 0 14px;
}
.public-hero-sub {
  max-width: 640px;
  margin: 0 auto 24px;
  font-size: 17px;
  color: var(--text-dim);
  line-height: 1.5;
}
.public-hero-cta {
  display: inline-flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}

.public-section {
  padding: 48px 0;
  border-top: 1px solid var(--border);
}
.public-section:first-of-type { border-top: 0; }
.public-section-title {
  text-align: center;
  font-size: 26px;
  letter-spacing: -0.4px;
  margin: 0 0 28px;
}

.public-features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
}
.public-feature {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 22px;
}
.public-feature-icon {
  font-size: 26px;
  margin-bottom: 8px;
}
.public-feature h3 {
  margin: 0 0 8px;
  font-size: 18px;
}
.public-feature p {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
}

.public-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 720px;
  margin: 0 auto;
}
.public-steps li {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 20px;
}
.public-step-num {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--accent);
  color: #1a1a1a;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.public-steps h4 {
  margin: 0 0 4px;
  font-size: 16px;
}
.public-steps p {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
}

.public-pricing-teaser strong { color: var(--accent); }

.public-cta-section {
  text-align: center;
}
.public-cta-section h2 {
  font-size: 28px;
  margin: 0 0 8px;
}
.public-cta-section p {
  margin: 0 0 18px;
  font-size: 15px;
}

.public-footer {
  border-top: 1px solid var(--border);
  background: var(--bg);
  padding: 24px;
  margin-top: 32px;
}
.public-footer-inner {
  max-width: 1080px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.public-footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.public-footer-nav {
  display: inline-flex;
  gap: 18px;
}
.public-footer-nav a {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 14px;
}
.public-footer-nav a:hover { color: var(--text); }

/* Long-form legal pages (/terms, /privacy). Constrained to a readable
   column (~70 characters at this font size), comfortable line-height
   for paragraph reading, mid-size headings that don't overshoot.
   Reuses the rest of the .public-page chrome (topbar, footer). */
.legal-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 40px 24px 64px;
  line-height: 1.6;
}
.legal-page h1 {
  font-size: 32px;
  letter-spacing: -0.5px;
  margin: 0 0 6px;
}
.legal-page h2 {
  font-size: 20px;
  margin: 28px 0 8px;
  letter-spacing: -0.2px;
}
.legal-page h3 {
  font-size: 16px;
  margin: 18px 0 6px;
  color: var(--text);
}
.legal-page p,
.legal-page li {
  font-size: 15px;
  color: var(--text);
}
.legal-page ul {
  margin: 6px 0 12px;
  padding-left: 22px;
}
.legal-page li { margin: 4px 0; }
.legal-page a {
  color: var(--accent);
}
.legal-page strong { color: var(--text); }

@media (max-width: 640px) {
  .public-topbar { padding: 14px 16px; }
  .public-main { padding: 16px 16px 48px; }
  .public-hero { padding: 32px 0 24px; }
  .public-hero h1 { font-size: 32px; }
  .public-hero-sub { font-size: 15px; }
  .public-section { padding: 32px 0; }
  .public-footer-inner { flex-direction: column; align-items: flex-start; }
  .legal-page { padding: 24px 16px 48px; }
  .legal-page h1 { font-size: 26px; }
}

/* ============================================================ */
/* DR-327 Phase 8: Image Generation UI                          */
/* ============================================================ */

/* Stub-mode banner — visible when the server reports stub_mode:true. */
.img-gen-stub-banner {
  margin: 16px auto 0;
  max-width: 720px;
  padding: 12px 16px;
  border-radius: 10px;
  background: rgba(255, 179, 0, 0.08);
  border: 1px solid rgba(255, 179, 0, 0.3);
  color: var(--text);
  font-size: 13px;
  line-height: 1.5;
}
.img-gen-stub-banner code {
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 12px;
}

/* Sub-tab control under the Generation hero. */
.img-gen-subtabs {
  margin: 0 0 18px;
  width: max-content;
}

/* Form layout */
.img-gen-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.img-gen-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
}
.img-gen-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.img-gen-label {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.img-gen-field textarea,
.img-gen-field input[type="number"],
.img-gen-field select {
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
}
.img-gen-field textarea { resize: vertical; min-height: 78px; }
.img-gen-field textarea:focus,
.img-gen-field input:focus,
.img-gen-field select:focus { outline: 2px solid var(--accent); outline-offset: -2px; }
.img-gen-hint { font-size: 12px; }

.img-gen-advanced {
  border-top: 1px solid var(--border);
  padding-top: 12px;
  margin-top: 4px;
}
.img-gen-advanced > summary {
  cursor: pointer;
  list-style: none;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  padding: 4px 0 8px;
}
.img-gen-advanced > summary::before { content: "▸ "; }
.img-gen-advanced[open] > summary::before { content: "▾ "; }

.img-gen-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.img-gen-actions .btn { min-width: 180px; }

/* Single-image result panel */
.img-gen-result-wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
}
.img-gen-result-wrap img {
  max-width: 100%;
  max-height: 70vh;
  height: auto;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: rgba(0, 0, 0, 0.3);
  display: block;
}
.img-gen-result-meta {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  justify-content: center;
}

/* Batch + history grid */
.img-gen-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px;
}
.img-gen-grid .img-gen-card {
  position: relative;
  aspect-ratio: 7 / 9;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  display: block;
}
.img-gen-grid .img-gen-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.img-gen-grid .img-gen-card .img-gen-card-meta {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 6px 8px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.75), transparent);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.85);
  display: flex;
  justify-content: space-between;
}
.img-gen-grid .img-gen-card.is-pending,
.img-gen-grid .img-gen-card.is-failed {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-family: var(--font-mono, ui-monospace, monospace);
  color: var(--text-dim);
  text-align: center;
  padding: 8px;
}
.img-gen-grid .img-gen-card.is-failed { color: var(--danger); }

.img-gen-history-pager {
  text-align: center;
  margin-top: 14px;
}

/* ==========================================================================
   DR-347 Phase 8.5 — LoRA training wizard
   ========================================================================== */

/* Image upload grid (step 1) reuses .img-gen-grid for the thumbnail tiles
   and adds a compact remove button overlay. */
.lora-image-grid .img-gen-card .lora-image-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 4px;
  font-size: 12px;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
}
.lora-image-grid .img-gen-card .lora-image-remove:hover {
  background: var(--danger, #b00);
}

/* Caption review grid (step 2) — two-column layout per row: thumb + textarea */
.lora-caption-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  margin: 14px 0;
}
.lora-caption-row {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 12px;
  align-items: start;
  padding: 10px;
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.lora-caption-row img {
  width: 120px;
  height: 144px;
  object-fit: cover;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.3);
}
.lora-caption-row textarea {
  width: 100%;
  min-height: 80px;
  resize: vertical;
  font: inherit;
}
.lora-caption-row .lora-caption-meta {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 4px;
}
.lora-caption-row.is-failed { border-color: var(--danger); }
.lora-caption-row.is-failed .lora-caption-meta { color: var(--danger); }
.lora-caption-row.is-generating textarea { opacity: 0.5; }

/* "Preview unavailable" placeholder used by both upload + caption
   thumbnail tiles when an image fails to load (presign expired,
   S3 4xx, etc.). Same dimensions as a real caption-row thumb. */
.lora-caption-thumb-unavailable {
  width: 120px;
  height: 144px;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--text-dim);
  text-align: center;
  padding: 6px;
  flex-shrink: 0;
}

/* Step container — only one active at a time */
.lora-step + .lora-step { margin-top: 16px; }

/* (DR-347 production) Step 1 character block — character name +
   trigger word inputs sit at the top of the upload step so the
   trigger is set before captioning. */
.lora-character-block {
  margin-bottom: 18px;
  padding: 14px 16px;
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.lora-character-title {
  margin: 0 0 6px 0;
  font-size: 15px;
}
.lora-character-block .form-row {
  margin-top: 8px;
  gap: 12px;
}

/* (DR-347 production) Step 3 read-only character summary —
   confirmation of what was set in Step 1; "Edit" jumps back. */
.lora-character-summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  margin-bottom: 14px;
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.lora-character-summary code {
  margin-left: 4px;
  padding: 1px 5px;
  background: rgba(255, 179, 0, 0.1);
  border: 1px solid rgba(255, 179, 0, 0.3);
  color: #ffb300;
  border-radius: 3px;
  font-size: 12px;
}

/* (DR-347 production) Sample-prompt missing-trigger soft-warn —
   yellow text on the inline hint span; doesn't block the user,
   just nudges. */
.lora-prompt-warn-missing {
  color: #ffb300;
}

/* Sample prompt list (step 3) — up to 5 individual rows with a
   remove button each. (DR-347 QA fix #3.) */
.lora-prompt-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 8px 0;
}
.lora-prompt-row {
  display: flex;
  gap: 6px;
  align-items: center;
}
.lora-prompt-row input[type="text"] {
  flex: 1;
}
.lora-prompt-row .lora-prompt-remove {
  white-space: nowrap;
}

/* Billing summary block on step 3 */
.lora-billing-summary {
  margin: 14px 0;
  padding: 12px 14px;
}
.lora-billing-summary p { margin: 6px 0 0 0; }

/* Training progress bar (step 4) */
.lora-progress { margin: 8px 0 16px 0; }
.lora-progress .progress {
  width: 100%;
  height: 14px;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid var(--border);
  border-radius: 7px;
  overflow: hidden;
}
.lora-sample-grid {
  margin-top: 10px;
}
.lora-sample-grid .img-gen-card-meta { font-size: 10px; }

/* (DR-347 v5 grouping) Sample-preview grouping by training step.
   The container .lora-sample-grid switches from a single overflowing
   grid to a column of <section> elements, each holding its own grid.
   That stops a "step 500" preview from landing on the same row as
   the "step 250" group. Per-section grid is min/max 5 columns to
   match the 5-sample-prompt cap, with the same gap as the historical
   grid. Sticky-feeling section header for readability. */
.lora-sample-grid {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.lora-sample-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.lora-sample-section-header {
  margin: 0;
  padding: 4px 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}
.lora-sample-section-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
}
/* Cap to 5 columns max even on wide screens — there are at most 5
   sample prompts, and a row of 5 reads more naturally than a row
   that wraps oddly. */
@media (min-width: 1200px) {
  .lora-sample-section-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}
.lora-sample-card .img-gen-card-meta { font-size: 10px; }

/* (DR-347 v3 worker observability) Structured failure block on the
   training step. The summary line is red (.error). Below it: optional
   meta line (worker version + error code), and two collapsed
   <details> blocks for the worker log tail and the diagnostics dump.
   Both <details> blocks default closed so a healthy run never shows
   anything; the failure path becomes visible on first failure. */
.lora-training-error {
  margin: 12px 0;
  padding: 12px 14px;
  background: #2a1010;
  border: 1px solid #5a1f1f;
  border-radius: 8px;
}
.lora-training-error-summary { margin: 0 0 4px; }
.lora-training-error-meta { margin: 0 0 8px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; }
.lora-training-error-details { margin-top: 8px; }
.lora-training-error-details > summary { cursor: pointer; user-select: none; }
.lora-training-error-tail,
.lora-training-error-diag {
  margin: 6px 0 0;
  padding: 8px 10px;
  background: #100808;
  border: 1px solid #401818;
  border-radius: 6px;
  max-height: 240px;
  overflow: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  color: #e8c8c8;
}

/* (DR-347 production) "+ Train new" sub-tab style — same shape as
   .seg-btn but visually flagged as an action rather than a nav
   target, using a thin accent border. */
.img-gen-subtabs #loraNewRunBtn {
  border-color: var(--accent, #ffb300);
  color: var(--accent, #ffb300);
}
.img-gen-subtabs #loraNewRunBtn:hover {
  background: var(--accent-soft, rgba(255, 179, 0, 0.15));
}

/* (DR-347 production) Confirm-discard modal.
   Lives as a direct child of <body> to escape <main>'s stacking
   context (dashboard.css:51 sets `main { position: relative;
   z-index: 2 }`). z-index 9999 puts us above any topbar.
   `body #loraConfirmModalRoot` selector wins the specificity war
   against any panel-scoped rules from dashboard.css. */
body #loraConfirmModalRoot.lora-modal-root {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
}
body #loraConfirmModalRoot[hidden] { display: none; }

body #loraConfirmModalRoot .lora-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
}
body #loraConfirmModalRoot .lora-modal-card {
  position: relative;
  max-width: 460px;
  width: calc(100% - 32px);
  padding: 22px 24px;
  /* Explicit hex colors — NOT --bg-2 / --bg-elev-2 which the
     dashboard.css `body .panel` rule was redefining mid-page.
     Slightly lighter than the page bg (#0a0a0a-ish) so the card
     reads against the dimmed backdrop. */
  background: #1f1f22;
  color: #f0f0f0;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55);
}
body #loraConfirmModalRoot .lora-modal-card h3 {
  margin: 0 0 10px 0;
  font-size: 18px;
  color: #fff;
}
body #loraConfirmModalRoot .lora-modal-card p {
  margin: 0 0 18px 0;
  color: rgba(255, 255, 255, 0.78);
  line-height: 1.4;
}
body #loraConfirmModalRoot .lora-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* (DR-347 v2 finalize gate) Checkpoint picker — shown on the
   training step when the run is in ready_to_finalize. One card per
   uploaded checkpoint with sample preview + step number + Save
   button. The recommended step (3250) is highlighted. */
.lora-checkpoint-picker {
  margin-bottom: 16px;
  padding: 14px;
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.lora-checkpoint-intro h3 {
  margin: 0 0 6px 0;
  font-size: 16px;
}
.lora-checkpoint-intro p {
  margin: 0 0 10px 0;
}
.lora-checkpoint-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
}
.lora-checkpoint-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.lora-checkpoint-card.is-recommended {
  border-color: rgba(255, 179, 0, 0.6);
  box-shadow: 0 0 0 1px rgba(255, 179, 0, 0.25);
}
.lora-checkpoint-card img {
  width: 100%;
  aspect-ratio: 7 / 9;
  object-fit: cover;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.4);
  display: block;
}
.lora-checkpoint-card .lora-checkpoint-thumb-unavailable {
  width: 100%;
  aspect-ratio: 7 / 9;
  background: rgba(0, 0, 0, 0.4);
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--text-dim);
  text-align: center;
}
.lora-checkpoint-card .lora-checkpoint-meta {
  font-size: 12px;
  color: var(--text);
}
.lora-checkpoint-card .lora-checkpoint-recommended {
  display: inline-block;
  font-size: 10px;
  background: rgba(255, 179, 0, 0.15);
  border: 1px solid rgba(255, 179, 0, 0.4);
  color: #ffb300;
  padding: 1px 5px;
  border-radius: 3px;
  margin-left: 4px;
  vertical-align: middle;
}
/* (DR-347 v5) "Final" badge for the AI Toolkit unsuffixed
   final-export card. Visually subordinate to "Recommended" — it's
   informational ("this is the full-step LoRA"), not a directive
   ("save this"). Same chip footprint, cooler palette. */
.lora-checkpoint-card .lora-checkpoint-final {
  display: inline-block;
  font-size: 10px;
  background: rgba(110, 184, 255, 0.12);
  border: 1px solid rgba(110, 184, 255, 0.35);
  color: #9dd3ff;
  padding: 1px 5px;
  border-radius: 3px;
  margin-left: 4px;
  vertical-align: middle;
}
.lora-checkpoint-card.is-final { /* hairline border so the card itself
                                    reads as a distinct kind, even
                                    before the badge resolves */
  border-color: rgba(110, 184, 255, 0.35);
}

/* Library grid (My LoRAs sub-tab) */
.lora-library-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  margin-top: 12px;
}
.lora-library-card {
  padding: 12px;
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid var(--border);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.lora-library-card .lora-library-name {
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  gap: 8px;
}
.lora-library-card .lora-library-meta {
  font-size: 12px;
  color: var(--text-dim);
}
.lora-library-card .lora-library-actions {
  margin-top: 6px;
  display: flex;
  gap: 6px;
}
.lora-library-card.is-stub { border-color: rgba(255, 179, 0, 0.4); }
.lora-library-card.is-stub .lora-library-name::after {
  content: "stub";
  font-size: 10px;
  background: rgba(255, 179, 0, 0.15);
  border: 1px solid rgba(255, 179, 0, 0.4);
  color: #ffb300;
  padding: 1px 5px;
  border-radius: 3px;
}

/* ═══════════════════════════════════════════════════════════════
   (DR-328 Phase 9) Generation tab — workflow cards, forms,
   active-job card, result preview, history grid, account panel.
   ═══════════════════════════════════════════════════════════════ */

.gen-header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 4px;
}
.gen-account-chip {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 14px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  min-width: 180px;
}
.gen-account-tier {
  font-weight: 700;
  font-size: 14px;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.gen-account-credits {
  font-size: 17px;
  font-weight: 600;
}
.gen-subtabs {
  display: flex;
  gap: 4px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 4px;
}
.gen-subtab {
  background: transparent;
  color: var(--text-dim);
  border: 0;
  padding: 8px 14px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
}
.gen-subtab.active {
  background: var(--accent-soft);
  color: var(--accent);
}
.gen-beta-banner {
  margin-top: 12px;
  padding: 10px 14px;
  background: rgba(110, 184, 255, 0.10);
  border: 1px solid rgba(110, 184, 255, 0.35);
  border-radius: 8px;
  color: #cfe6ff;
  font-size: 13px;
}

/* Workflow grid */
.gen-workflow-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
  margin-top: 10px;
}
.gen-workflow-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 18px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  color: var(--text);
  text-align: left;
  transition: border-color 0.12s, transform 0.12s;
}
.gen-workflow-card:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
}
.gen-workflow-card.is-locked {
  opacity: 0.55;
  cursor: not-allowed;
}
.gen-workflow-icon {
  font-size: 28px;
  line-height: 1;
}
.gen-workflow-title {
  font-size: 16px;
  font-weight: 700;
}
.gen-workflow-blurb {
  font-size: 13px;
  line-height: 1.4;
}
.gen-workflow-lock {
  margin-top: 6px;
  padding: 2px 6px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 11px;
  color: var(--text-dim);
}

/* Workflow form */
.gen-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.gen-form .form-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.gen-form .form-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.gen-form .form-textarea,
.gen-form .form-select {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: 10px 12px;
  font-size: 14px;
  font-family: inherit;
}
.gen-form .form-textarea:focus,
.gen-form .form-select:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.gen-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}
.gen-form-grid > div {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.gen-preview-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}
.gen-preview-img {
  width: 92px;
  height: 92px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--border);
}
.gen-preview-vid {
  width: 240px;
  max-height: 200px;
  border-radius: 6px;
  border: 1px solid var(--border);
}
.gen-submit-row {
  flex-direction: row !important;
  align-items: center;
  gap: 12px;
}
.gen-cost-chip {
  padding: 6px 12px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  min-width: 110px;
  text-align: center;
}

/* Active job card */
.gen-active-job-meta {
  margin-bottom: 8px;
}
.gen-active-job-status {
  margin-top: 8px;
  font-weight: 600;
}
.gen-active-job-error {
  margin-top: 8px;
}

/* Result panel */
.gen-result-media {
  margin: 12px 0;
  display: flex;
  justify-content: center;
}
.gen-result-video,
.gen-result-image {
  max-width: 100%;
  max-height: 640px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: #000;
}
.gen-placeholder {
  padding: 60px 20px;
  text-align: center;
  background: var(--bg-elev-2);
  border: 1px dashed var(--border);
  border-radius: 10px;
  color: var(--text-dim);
}
.gen-placeholder.error {
  color: var(--danger);
  border-color: rgba(255, 107, 107, 0.4);
  background: rgba(255, 107, 107, 0.08);
}

/* (DR-328 hotfix 6) "Video" badge overlaid on History card media
   so video cards have a visible affordance even before the poster
   frame loads. Minimal styling — not a redesign. */
.gen-history-media {
  position: relative;
}
.gen-history-video-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  pointer-events: none;
}

/* History grid */
.gen-history-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px;
  margin-top: 10px;
}
@media (min-width: 1200px) {
  .gen-history-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}
.gen-history-card {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.12s, transform 0.12s;
}
.gen-history-card:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
}
.gen-history-media {
  aspect-ratio: 1 / 1;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.gen-history-media img,
.gen-history-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gen-history-placeholder {
  color: var(--text-dim);
  font-size: 12px;
}
.gen-history-meta {
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.gen-history-title {
  font-weight: 600;
  font-size: 13px;
}
.gen-history-empty {
  padding: 30px 14px;
  text-align: center;
}
.gen-history-pager {
  margin-top: 14px;
  display: flex;
  justify-content: center;
}

/* Account panel */
.gen-sub-card,
.gen-balance-card {
  padding: 14px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.gen-sub-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--accent);
}
.gen-topup-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-top: 10px;
}
.gen-topup-card {
  padding: 14px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: center;
}
.gen-topup-title {
  font-weight: 600;
  font-size: 14px;
}
.gen-topup-price {
  font-size: 22px;
  font-weight: 700;
  color: var(--accent);
}
.gen-ledger-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 8px;
}
.gen-ledger-table th,
.gen-ledger-table td {
  border-bottom: 1px solid var(--border);
  padding: 8px 6px;
  text-align: left;
  font-size: 13px;
}
.gen-ledger-table th {
  color: var(--text-dim);
  font-weight: 500;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* (DR-328 Step 11) Subscribe panel — plan grid with 3 tier cards. */
.gen-no-sub-banner {
  padding: 12px 14px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 14px;
}
.gen-plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
.gen-plan-card {
  position: relative;
  padding: 18px 16px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.gen-plan-card.is-popular {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-soft) inset;
}
.gen-plan-badge {
  position: absolute;
  top: -10px;
  right: 12px;
  background: var(--accent);
  color: #1a1a1a;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 3px 8px;
  border-radius: 999px;
  text-transform: uppercase;
}
.gen-plan-title {
  font-size: 17px;
  font-weight: 700;
}
.gen-plan-price {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.5px;
  color: var(--text);
}
.gen-plan-price .muted {
  font-size: 13px;
  font-weight: 400;
  margin-left: 2px;
}
.gen-plan-card .btn {
  width: 100%;
  justify-content: center;
  margin-top: 4px;
}
