/* ============================================================================
   Studio — minimal phone-first UI for a local ComfyUI instance.
   Dark, quiet, image-forward. One accent, used sparingly.
   ========================================================================== */

:root {
  --bg:        #0b0b0d;
  --surface:   #141417;
  --surface-2: #1c1c21;
  --line:      #26262c;
  --line-soft: #1e1e23;
  --text:      #ededf0;
  --text-dim:  #9a9aa6;
  --text-faint:#65656f;
  --accent:    #b3a4ff;
  --accent-dim:#4a4173;
  --danger:    #ff6b6b;
  --ok:        #5bd18b;

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-full: 999px;

  --pad: 16px;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Several components below set `display`, which would otherwise beat the UA
   stylesheet's `[hidden] { display: none }`. Settle it once, here. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.45;
  overscroll-behavior-y: none;
}

body { -webkit-font-smoothing: antialiased; }

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

.ico {
  width: 22px; height: 22px;
  fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  display: block;
}
.ico circle { fill: currentColor; stroke: none; }

/* ── screens ─────────────────────────────────────────────────────────── */

.screen {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  background: var(--bg);
  /* Scroll vertically, but do not pinch-zoom the interface. The page as a
     whole is zoomable again (removing that was an accessibility problem and
     what stopped images zooming), and without this a stray pinch — easy to
     make when you are pinching pictures — scales the whole UI, moves the
     composer out of the visual viewport, and taps stop landing on the
     Generate button. The viewer sets touch-action: none and runs its own
     zoom, so images are unaffected. */
  touch-action: pan-y;
}
.screen[hidden] { display: none; }

.scroll {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
}

/* Phone-first: scrollbars are overlays on touch devices anyway, and a desktop
   gutter just makes the layout look like a web page instead of an app. */
.scroll::-webkit-scrollbar,
.sheet-body::-webkit-scrollbar,
.prompt-input::-webkit-scrollbar { width: 0; height: 0; }
.scroll, .sheet-body, .prompt-input { scrollbar-width: none; }

/* ── top bar ─────────────────────────────────────────────────────────── */

.topbar {
  display: flex; align-items: center; gap: 4px;
  padding: calc(var(--safe-t) + 8px) 8px 8px;
  border-bottom: 1px solid var(--line-soft);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(12px);
  min-height: 52px;
  flex: none;
}
.topbar-title {
  font-size: 17px; font-weight: 600; margin: 0;
  letter-spacing: -0.01em;
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar-stack { flex: 1; min-width: 0; }
.topbar-stack .topbar-title { font-size: 16px; }
.topbar-sub {
  margin: 0; font-size: 12px; color: var(--text-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar-spacer { width: 40px; flex: none; }

.icon-btn {
  flex: none;
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 0; border-radius: var(--r-full);
  background: transparent; color: var(--text);
  cursor: pointer;
  text-decoration: none;
}
.icon-btn:active { background: var(--surface-2); }
/* Held while a delete is on its way to the PC, and while the viewer is still
   fetching the full size it would save — so a tap that cannot do the right
   thing yet looks unavailable rather than being silently ignored. */
.icon-btn:disabled,
.icon-btn[aria-disabled="true"] { opacity: .4; cursor: default; pointer-events: none; }
.icon-btn:disabled:active,
.icon-btn[aria-disabled="true"]:active { background: transparent; }

.status-dot {
  width: 9px; height: 9px; border-radius: var(--r-full);
  background: var(--text-faint);
}
.status-dot[data-state="ok"]   { background: var(--ok); }
.status-dot[data-state="down"] { background: var(--danger); }
.status-dot[data-state="busy"] { background: var(--accent); animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }

/* The backend pill: connection state and which machine, in one always-visible
   control. Replaces a bare dot that could only be interpreted by hovering a
   title attribute, which a phone cannot do. */
.backend-pill {
  flex: none;
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 10px 0 9px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-full);
  background: var(--surface-2); color: var(--text);
  font: inherit; font-size: 12px; font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  max-width: 46vw;
}
.backend-pill:active { background: var(--surface-3, var(--surface-2)); }
.backend-pill-text {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Cloud costs money, so it does not look like the resting state. */
.backend-pill[data-where="cloud"] {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  color: var(--accent);
}
.backend-pill[data-where="mixed"] {
  border-color: color-mix(in srgb, var(--accent) 30%, transparent);
}

/* ── buttons ─────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid transparent;
  border-radius: var(--r-full);
  padding: 12px 20px;
  font-size: 15px; font-weight: 600;
  letter-spacing: -0.01em;
  background: var(--surface-2);
  cursor: pointer;
  min-height: 46px;
  transition: opacity .12s ease, transform .06s ease;
}
.btn:active { transform: scale(.985); }
.btn:disabled { opacity: .4; pointer-events: none; }

.btn-primary { background: var(--text); color: #101013; }
.btn-ghost   { background: transparent; border-color: var(--line); color: var(--text-dim); font-weight: 500; }
.btn-block   { width: 100%; }
.btn-generate { width: 100%; }

.link-btn {
  background: none; border: 0; padding: 6px 2px;
  color: var(--accent); font-size: 15px; font-weight: 500;
  cursor: pointer;
}
/* Phone: text actions need a real finger target */
.cast-actions .link-btn,
.beat-actions .link-btn {
  min-height: 40px;
  padding: 8px 10px;
  margin: -4px 0;
  border-radius: var(--r-sm);
}
.cast-actions .link-btn:active,
.beat-actions .link-btn:active {
  background: var(--surface-2);
}

/* ── passcode gate ───────────────────────────────────────────────────── */

.gate {
  margin: auto;
  width: 100%; max-width: 320px;
  padding: 24px;
  text-align: center;
}
.gate-mark {
  width: 44px; height: 44px; margin: 0 auto 20px;
  border-radius: 14px;
  background: linear-gradient(150deg, var(--accent), var(--accent-dim));
}
.gate-title { font-size: 22px; font-weight: 600; margin: 0 0 28px; letter-spacing: -0.02em; }
.gate-form { display: flex; flex-direction: column; gap: 12px; }
.gate-input {
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--r-md);
  padding: 14px 16px;
  font-size: 17px;
  text-align: center;
  letter-spacing: 0.12em;
  outline: none;
}
.gate-input:focus { border-color: var(--accent-dim); }
.gate-error { color: var(--danger); font-size: 14px; margin: 14px 0 0; }

/* ── session list ────────────────────────────────────────────────────── */

.session-list { list-style: none; margin: 0; padding: 8px 0 0; }

.session-row {
  display: flex; align-items: center; gap: 14px;
  padding: 10px var(--pad);
  cursor: pointer;
}
.session-row:active { background: var(--surface); }

/* Explicit affordance — long-press alone is undiscoverable on a phone. */
.session-more {
  flex: none;
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border: 0; border-radius: var(--r-full);
  background: transparent; color: var(--text-faint);
  cursor: pointer;
}
.session-more:active { background: var(--surface-2); color: var(--text); }

.session-thumb {
  width: 54px; height: 54px; flex: none;
  border-radius: var(--r-md);
  background: var(--surface-2);
  object-fit: cover;
  display: block;
}
.session-thumb-empty {
  display: grid; place-items: center;
  color: var(--text-faint); font-size: 11px;
}
.session-meta { flex: 1; min-width: 0; }
.session-name {
  font-size: 16px; font-weight: 500; margin: 0 0 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.session-sub {
  font-size: 13px; color: var(--text-faint); margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.empty { padding: 64px 32px; text-align: center; }
.empty-title { font-size: 16px; font-weight: 500; margin: 0 0 6px; }
.empty-sub { font-size: 14px; color: var(--text-faint); margin: 0; line-height: 1.5; }
.empty-sub code {
  font-family: var(--mono); font-size: 12.5px;
  background: var(--surface-2); padding: 2px 5px; border-radius: 5px;
}

.fineprint {
  padding: 24px var(--pad) 8px;
  font-size: 12px; color: var(--text-faint);
  text-align: center; margin: 0;
}

.dock {
  flex: none;
  padding: 12px var(--pad) calc(var(--safe-b) + 12px);
  border-top: 1px solid var(--line-soft);
  background: var(--bg);
}

/* ── workflow picker ─────────────────────────────────────────────────── */

.wf-list { list-style: none; margin: 0; padding: 8px 0; }
.wf-row {
  display: flex; align-items: center; gap: 12px;
  padding: 16px var(--pad);
  border-bottom: 1px solid var(--line-soft);
  cursor: pointer;
}
.wf-row:active { background: var(--surface); }
.wf-meta { flex: 1; min-width: 0; }
.wf-name { font-size: 16px; font-weight: 500; margin: 0 0 3px; }
.wf-sub { font-size: 13px; color: var(--text-faint); margin: 0; }
.wf-chevron { color: var(--text-faint); }

.tag {
  display: inline-block;
  font-size: 11px; font-weight: 500;
  padding: 2px 7px; border-radius: var(--r-full);
  background: var(--surface-2); color: var(--text-dim);
  margin-left: 6px; vertical-align: 1px;
}

/* ── feed ────────────────────────────────────────────────────────────── */

.feed { padding: 12px var(--pad) 8px; display: flex; flex-direction: column; gap: 22px; }

.gen { display: flex; flex-direction: column; gap: 8px; }

.gen-prompt {
  font-size: 14px; color: var(--text-dim);
  line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
  cursor: pointer;
}
.gen-prompt.expanded { -webkit-line-clamp: unset; }

.gen-images { display: grid; gap: 6px; grid-template-columns: 1fr; }
.gen-images[data-count="2"],
.gen-images[data-count="4"]    { grid-template-columns: repeat(2, 1fr); }
.gen-images[data-count="3"]    { grid-template-columns: repeat(3, 1fr); }
/* A batch of up to 32 becomes a contact sheet — tap any tile for the full one. */
.gen-images[data-count="many"] { grid-template-columns: repeat(4, 1fr); gap: 4px; }
.gen-images[data-count="many"] .gen-img { border-radius: 6px; }

.gen-img {
  width: 100%;
  /* The width/height ATTRIBUTES are set on each <img> so the browser can
     reserve the right space before the blob decodes. They also act as
     presentational hints, so overriding only `width` here would leave the
     image locked to its full pixel height — squashing a 832x1216 render into
     a ~343px-wide column and stretching it. `height: auto` hands the sizing
     back to the intrinsic aspect ratio. */
  height: auto;
  display: block;
  border-radius: var(--r-md);
  background: var(--surface);
  cursor: zoom-in;
}

/* Multi-image runs share a row, so crop to a square tile instead of letting
   one portrait render set the height for the whole grid. */
.gen-images:not([data-count="1"]) .gen-img {
  aspect-ratio: 1;
  object-fit: cover;
}

.gen-foot {
  display: flex; align-items: center; gap: 12px;
  font-size: 12px; color: var(--text-faint);
  font-family: var(--mono);
}
.gen-foot .grow { flex: 1; }
.gen-reuse {
  background: none; border: 0; padding: 4px 0;
  color: var(--text-dim); font-size: 12px; cursor: pointer;
  font-family: var(--font);
}

.gen-error {
  border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
  background: color-mix(in srgb, var(--danger) 8%, transparent);
  color: var(--danger);
  border-radius: var(--r-md);
  padding: 12px 14px;
  font-size: 13.5px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── composer ────────────────────────────────────────────────────────── */

.composer {
  flex: none;
  border-top: 1px solid var(--line-soft);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(12px);
  padding: 10px var(--pad) calc(var(--safe-b) + 10px);
  display: flex; flex-direction: column; gap: 10px;
}
.composer[hidden] { display: none; }
#composer-designer {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
#composer-designer[hidden] { display: none; }

.workflow-chip {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  margin: 0;
  padding: 4px 8px 4px 10px;
  border: 0;
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.workflow-chip-label,
#workflow-chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.workflow-chip-caret { flex: none; width: 16px; height: 16px; }

.composer-row { display: flex; }

.prompt-input {
  width: 100%;
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: 12px 14px;
  font-size: 16px;          /* 16px stops iOS zoom-on-focus */
  line-height: 1.45;
  resize: none;
  outline: none;
  min-height: 88px;
  max-height: 40vh;
  overflow-y: auto;
}
.prompt-input:focus { border-color: var(--accent-dim); }
.prompt-input::placeholder { color: var(--text-faint); }

.composer-actions {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.composer-shot-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.composer-shot-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
}
.composer.is-board #btn-generate,
.composer.is-cast #btn-generate { width: 100%; }
.config-preview {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 56px;
  padding: 10px 10px 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.config-preview:active { background: var(--line); }
.config-preview-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 0;
  flex: 1;
}
.config-preview-affordance {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 6px 8px 6px 10px;
  border-radius: var(--r-full);
  background: var(--surface);
  color: var(--text-dim);
}
.config-preview-action {
  font-size: 13px;
  font-weight: 600;
}
.config-preview-caret {
  flex: none;
  width: 18px;
  height: 18px;
}
.config-model {
  font-size: 15px;
  font-weight: 650;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.config-meta {
  font-size: 12px;
  color: var(--text-dim);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.btn-generate {
  width: 100%;
  min-height: 52px;
  font-size: 17px;
}
.sheet-wf-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 18px;
}
.sheet-wf {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.sheet-wf.is-on { border-color: var(--accent); }
.sheet-wf-sub { font-size: 12px; color: var(--muted); }

/* ── queue ───────────────────────────────────────────────────────────── */

.queue { display: flex; flex-direction: column; gap: 7px; }
.queue[hidden] { display: none; }

.queue-head {
  display: flex; align-items: center; justify-content: space-between;
  background: none; border: 0; padding: 0;
  color: var(--text-dim); font-size: 13px;
  cursor: pointer;
}
.queue-count { font-size: 13px; }
/* flex: none — without it the flex row collapses the svg to zero width. */
.queue-chevron { flex: none; width: 16px; height: 16px; transition: transform .15s ease; }
.queue-head[aria-expanded="true"] .queue-chevron { transform: rotate(180deg); }

.queue-list {
  display: flex; flex-direction: column;
  max-height: 34vh; overflow-y: auto;
  margin-top: 2px;
}
.queue-list[hidden] { display: none; }

.queue-row {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line-soft);
}
.queue-row:last-child { border-bottom: 0; }

.queue-dot {
  flex: none; width: 7px; height: 7px; border-radius: var(--r-full);
  background: var(--text-faint);
}
.queue-row.running .queue-dot { background: var(--accent); animation: pulse 1.4s ease-in-out infinite; }

.queue-prompt {
  flex: 1; min-width: 0;
  font-size: 13px; color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.queue-state {
  flex: none; font-size: 11.5px; color: var(--text-faint);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.queue-cancel {
  flex: none;
  width: 28px; height: 28px;
  border: 0; border-radius: var(--r-full);
  background: transparent; color: var(--text-faint);
  font-size: 15px; line-height: 1; cursor: pointer;
}
.queue-cancel:active { background: var(--surface-2); color: var(--text); }

/* ── progress ────────────────────────────────────────────────────────── */

.progress { display: flex; flex-direction: column; gap: 7px; }
.progress-row { display: flex; align-items: center; justify-content: space-between; }
.progress-label { font-size: 13px; color: var(--text-dim); }
.progress-track {
  height: 3px; border-radius: var(--r-full);
  background: var(--surface-2); overflow: hidden;
}
.progress-bar {
  height: 100%; width: 0%;
  background: var(--accent);
  border-radius: var(--r-full);
  transition: width .18s ease;
}
.progress-bar.indeterminate {
  width: 35%;
  animation: slide 1.15s ease-in-out infinite;
}
@keyframes slide {
  0%   { transform: translateX(-100%) }
  100% { transform: translateX(330%) }
}

/* ── settings sheet ──────────────────────────────────────────────────── */

.backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.55);
  z-index: 40;
}
#menu-backdrop {
  z-index: 69;
}
.backdrop[hidden] { display: none; }

.sheet {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 50;
  touch-action: pan-y;
  max-height: 86dvh;
  display: flex; flex-direction: column;
  background: var(--surface);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  border-top: 1px solid var(--line);
  animation: rise .22s cubic-bezier(.2,.8,.2,1);
}
.sheet[hidden] { display: none; }
@keyframes rise { from { transform: translateY(100%) } to { transform: translateY(0) } }

.sheet-grip {
  width: 36px; height: 4px; border-radius: var(--r-full);
  background: var(--line); margin: 8px auto 0;
}
.sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px var(--pad) 10px;
  border-bottom: 1px solid var(--line-soft);
}
.sheet-title { font-size: 16px; font-weight: 600; margin: 0; }
.sheet-body {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px var(--pad) calc(var(--safe-b) + 20px);
}

.field { padding: 14px 0; border-bottom: 1px solid var(--line-soft); }
.field:last-child { border-bottom: 0; }

.field-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-bottom: 9px;
}
.field-label { font-size: 14px; font-weight: 500; }
.field-optional {
  margin-left: 6px;
  color: var(--text-faint);
  font-size: 12px;
  font-weight: 500;
}
.field-value {
  font-size: 13px; color: var(--text-dim);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.group-label {
  font-size: 11px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-faint);
  padding: 20px 0 2px;
}

/* range */
input[type=range] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 26px; background: transparent; margin: 0;
}
input[type=range]::-webkit-slider-runnable-track {
  height: 3px; border-radius: var(--r-full); background: var(--line);
}
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px; height: 22px; border-radius: var(--r-full);
  background: var(--text); margin-top: -9.5px;
  border: 0;
}
input[type=range]::-moz-range-track { height: 3px; border-radius: var(--r-full); background: var(--line); }
input[type=range]::-moz-range-thumb { width: 22px; height: 22px; border: 0; border-radius: var(--r-full); background: var(--text); }

/* select + text input */
.select, .text-input {
  width: 100%;
  -webkit-appearance: none; appearance: none;
  border: 1px solid var(--line);
  background: var(--surface-2);
  border-radius: var(--r-sm);
  padding: 11px 34px 11px 12px;
  font-size: 15px;
  outline: none;
  text-overflow: ellipsis;
}
.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239a9aa6' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px;
}
.text-input { padding-right: 12px; font-variant-numeric: tabular-nums; }
.select:focus, .text-input:focus { border-color: var(--accent-dim); }

/* segmented control */
.seg {
  display: flex; gap: 4px;
  background: var(--surface-2);
  border-radius: var(--r-sm);
  padding: 3px;
}
.seg button {
  flex: 1;
  border: 0; background: transparent;
  color: var(--text-dim);
  padding: 9px 4px;
  font-size: 13px; font-weight: 500;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.seg button[aria-pressed="true"] { background: var(--line); color: var(--text); }

/* lora slot */
.lora {
  padding: 14px 0;
  border-bottom: 1px solid var(--line-soft);
}
.lora-top { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
.lora-top .select { flex: 1; min-width: 0; }
.lora-strength-row { display: flex; align-items: center; gap: 12px; }
.lora-strength-row input[type=range] { flex: 1; }
.lora-strength-row .field-value { width: 42px; text-align: right; flex: none; }
/* Switched off: the whole slot recedes, so what's active is obvious at a glance. */
.lora.off .lora-top,
.lora.off .lora-strength-row { opacity: .38; }
.lora .field-head { align-items: center; }

.row-2 { display: flex; gap: 10px; }
.row-2 > * { flex: 1; min-width: 0; }

.toggle-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.switch {
  position: relative; flex: none;
  width: 46px; height: 28px;
  border-radius: var(--r-full);
  background: var(--line);
  border: 0; cursor: pointer;
  transition: background .15s ease;
}
.switch::after {
  content: ""; position: absolute;
  top: 3px; left: 3px;
  width: 22px; height: 22px; border-radius: var(--r-full);
  background: var(--text);
  transition: transform .15s ease;
}
.switch[aria-pressed="true"] { background: var(--accent-dim); }
.switch[aria-pressed="true"]::after { transform: translateX(18px); }

.hint { font-size: 12px; color: var(--text-faint); margin: 8px 0 0; line-height: 1.45; }
.auto-ref-details {
  margin: 14px 0 4px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.auto-ref-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  list-style: none;
}
.auto-ref-summary::-webkit-details-marker { display: none; }
.auto-ref-summary::after {
  content: "›";
  color: var(--muted);
  font-size: 20px;
  line-height: 1;
  transform: rotate(90deg);
  transition: transform .15s ease;
}
.auto-ref-details[open] .auto-ref-summary::after { transform: rotate(-90deg); }
.auto-ref-state {
  margin-left: auto;
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
}
.auto-ref-body {
  padding: 0 12px 14px;
  border-top: 1px solid var(--line-soft);
}

/* ── contact sheet ───────────────────────────────────────────────────── */

.grid-screen {
  position: fixed; inset: 0; z-index: 45;
  display: flex; flex-direction: column;
  background: var(--bg);
}
.grid-screen[hidden] { display: none; }

.canon-library-screen {
  position: fixed;
  inset: 0;
  z-index: 46;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}
.canon-library-screen[hidden] { display: none; }
.canon-library-scroll {
  flex: 1;
  padding: 14px var(--pad) 28px;
}
.canon-library-tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.canon-library-tile {
  position: relative;
  appearance: none;
  min-width: 0;
  padding: 0;
  overflow: hidden;
  border: 2px solid transparent;
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.canon-library-tile.is-selected { border-color: #8dcc9a; }
.canon-library-tile img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: contain;
}
.canon-library-tile-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-height: 32px;
  padding: 7px 9px;
  color: var(--muted);
  font-size: 11px;
}
.canon-library-selected {
  color: #8dcc9a;
  font-weight: 700;
}
.canon-library-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  flex: none;
  padding: 10px var(--pad) calc(var(--safe-b) + 10px);
  border-top: 1px solid var(--line-soft);
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(12px);
}
.shot-library-actions { grid-template-columns: 1fr; }

.grid-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3px;
  padding: 3px;
}
.grid-tile {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  background: var(--surface);
  cursor: pointer;
}
.grid-tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.grid-tile-seed {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 10px 5px 3px;
  font-family: var(--mono); font-size: 9px;
  color: rgba(255,255,255,.75);
  background: linear-gradient(to top, rgba(0,0,0,.65), transparent);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

@media (min-width: 500px) {
  .grid-tiles { grid-template-columns: repeat(4, 1fr); }
}

/* ── favourites ──────────────────────────────────────────────────────────
   A locked session's tile is a frosted stand-in, not a blurred copy of the
   picture: without that session's passcode there is nothing to blur, and
   holding a readable version outside the lock would defeat it. */

.locked-tile {
  background:
    repeating-linear-gradient(45deg,
      var(--surface) 0 6px, var(--surface-2) 6px 12px);
}
.locked-veil {
  position: absolute; inset: 0;
  display: grid; place-content: center; gap: 6px; justify-items: center;
  padding: 8px;
  color: var(--text-faint);
  backdrop-filter: blur(6px);
  background: color-mix(in srgb, var(--bg) 55%, transparent);
}
.locked-tile:active .locked-veil { background: color-mix(in srgb, var(--bg) 35%, transparent); }
.lock-glyph { width: 20px; height: 20px; }
.locked-name {
  font-size: 10px;
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The heart fills in once the image is kept. */
#viewer-fav .ico { transition: fill .12s ease, stroke .12s ease; }
#viewer-fav.on .ico { fill: var(--danger); stroke: var(--danger); }

/* Where the feed lands after tapping a tile. */
@keyframes flash {
  0%, 100% { box-shadow: 0 0 0 0 transparent }
  30%      { box-shadow: 0 0 0 3px var(--accent) }
}
.gen.located .gen-images { border-radius: var(--r-md); animation: flash 1.1s ease-out; }

/* ── viewer ──────────────────────────────────────────────────────────── */

.viewer {
  position: fixed; inset: 0; z-index: 60;
  background: #000;
  display: flex; flex-direction: column;
}
.viewer[hidden] { display: none; }

.viewer-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: calc(var(--safe-t) + 8px) 8px 8px;
  color: #fff;
}
.viewer-bar .icon-btn { color: #fff; }
.viewer-meta {
  flex: 1 1 80px; min-width: 0;
  font-size: 12px; color: #8b8b96; font-family: var(--mono);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.viewer-choice {
  flex: none;
  padding: 10px 12px calc(var(--safe-b) + 10px);
  border-top: 1px solid rgba(255,255,255,.12);
  background: rgba(0,0,0,.92);
}
.viewer-choice[hidden] { display: none; }
.viewer-canon-btn {
  width: 100%;
  min-height: 48px;
  font-size: 14px;
}
.viewer-canon-btn:disabled {
  opacity: 0.55;
}
.viewer-stage {
  flex: 1; position: relative;
  display: grid; place-items: center;
  overflow: hidden;
  padding: 0 0 calc(var(--safe-b) + 8px);
  /* Claim the gesture. Without this the browser's own pinch-zoom competes with
     the handler below and neither behaves. */
  touch-action: none;
}
#viewer-img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  display: block;
  transform-origin: 0 0;
  will-change: transform;
  user-select: none; -webkit-user-drag: none;
}
/* Only while a pinch or drag is in flight — otherwise zooming feels laggy. */
#viewer-img.settling { transition: transform .18s ease-out; }

.viewer-hint {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--safe-b) + 18px);
  padding: 7px 14px; border-radius: var(--r-full);
  background: rgba(0,0,0,.55); color: rgba(255,255,255,.8);
  font-size: 12.5px; pointer-events: none;
  transition: opacity .4s ease;
}
.viewer-hint[hidden] { display: none; }
.viewer-hint.gone { opacity: 0; }

.spinner {
  position: absolute;
  width: 26px; height: 26px;
  border: 2px solid rgba(255,255,255,.2);
  border-top-color: #fff;
  border-radius: var(--r-full);
  animation: spin .7s linear infinite;
}
.spinner[hidden] { display: none; }
@keyframes spin { to { transform: rotate(360deg) } }

/* ── action menu ─────────────────────────────────────────────────────── */

.menu {
  position: fixed; left: var(--pad); right: var(--pad);
  bottom: calc(var(--safe-b) + 12px);
  z-index: 70;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  max-height: min(70vh, 560px);
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  animation: rise .18s cubic-bezier(.2,.8,.2,1);
}
.menu[hidden] { display: none; }
.menu-heading {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0;
  padding: 14px var(--pad) 8px;
  background: var(--surface);
  /* Only section titles carry weight — selected rows must not. */
  font-size: 15px;
  font-weight: 650;
  letter-spacing: normal;
  text-transform: none;
  color: var(--text);
  border-bottom: 1px solid var(--line-soft);
}
.menu-heading:not(:first-child) {
  margin-top: 6px;
  border-top: 1px solid var(--line-soft);
}
.menu > button {
  display: block; width: 100%;
  border: 0; background: transparent;
  padding: 13px var(--pad);
  font-size: 15px;
  font-weight: 400;
  text-align: left; cursor: pointer;
  border-bottom: 1px solid var(--line-soft);
  color: var(--text-dim);
}
.menu > button:last-child { border-bottom: 0; }
.menu > button:active { background: var(--surface-2); }
.menu > button.destructive { color: var(--danger); }
.menu > button.is-selected {
  background: color-mix(in srgb, var(--ok) 16%, var(--surface));
  box-shadow: inset 3px 0 0 var(--ok);
  font-weight: 400;
  color: var(--text);
}
.menu-row {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--line-soft);
}
.menu-row:last-child { border-bottom: 0; }
.menu-row.is-selected {
  background: color-mix(in srgb, var(--ok) 16%, var(--surface));
  box-shadow: inset 3px 0 0 var(--ok);
}
.menu-row .menu-row-main {
  flex: 1;
  min-width: 0;
  border: 0;
  border-bottom: 0;
  background: transparent;
  padding: 13px var(--pad);
  font-size: 15px;
  font-weight: 400;
  text-align: left;
  cursor: pointer;
  color: var(--text-dim);
}
.menu-row.is-selected .menu-row-main {
  font-weight: 400;
  box-shadow: none;
  background: transparent;
  color: var(--text);
}
.menu-row .menu-row-main:active,
.menu-row .menu-row-accessory:active {
  background: var(--surface-2);
}
.menu-row-accessory {
  flex: none;
  display: grid;
  place-items: center;
  width: 52px;
  border: 0;
  border-left: 1px solid var(--line-soft);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.menu-row-accessory .ico { width: 20px; height: 20px; }
.menu.is-form {
  left: 0;
  right: 0;
  bottom: 0;
  padding: 12px var(--pad) calc(var(--safe-b) + 16px);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  max-height: min(82dvh, 640px);
}
.menu-select-label {
  display: block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.menu-dd {
  padding: 10px 0;
}
.menu-dd + .menu-dd {
  border-top: 1px solid var(--line-soft);
}
.menu-dd-toggle {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 48px;
  margin-top: 6px;
  padding: 12px 40px 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background-color: var(--surface-2);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239a9aa6' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.menu-dd.is-set .menu-dd-toggle {
  border-color: color-mix(in srgb, var(--ok) 55%, var(--line));
  background-color: color-mix(in srgb, var(--ok) 10%, var(--surface-2));
}
.menu-dd-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu-drill-head {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0 0 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
}
.menu-drill-back {
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.menu-drill-back:active { background: var(--surface-2); }
.menu-drill-back .ico { width: 22px; height: 22px; }
.menu-drill-title {
  margin: 0;
  font-size: 18px;
  font-weight: 650;
}
.menu-drill-list {
  margin: 0 calc(var(--pad) * -1);
}
.menu-drill-opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 14px var(--pad);
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  background: transparent;
  font: inherit;
  font-size: 17px;
  text-align: left;
  cursor: pointer;
}
.menu-drill-opt:active { background: var(--surface-2); }
.menu-drill-opt.is-selected {
  background: color-mix(in srgb, var(--ok) 16%, var(--surface));
  box-shadow: inset 3px 0 0 var(--ok);
  font-weight: 400;
}
.menu-drill-check {
  flex: none;
  color: var(--ok);
  font-weight: 700;
}

/* ── passcode prompt ─────────────────────────────────────────────────── */

.ask {
  position: fixed; left: var(--pad); right: var(--pad);
  top: 50%; transform: translateY(-50%);
  z-index: 65;
  max-width: 340px; margin: 0 auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 22px 20px 18px;
}
.ask[hidden] { display: none; }
.ask-title { font-size: 17px; font-weight: 600; margin: 0 0 6px; }
.ask-note { font-size: 13.5px; color: var(--text-faint); margin: 0 0 16px; line-height: 1.5; }
.ask-error { color: var(--danger); font-size: 13px; margin: 10px 0 0; }

.trail {
  max-height: 44vh; overflow: auto;
  margin: 0; padding: 10px 12px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-family: var(--mono); font-size: 11px; line-height: 1.6;
  color: var(--text-dim);
  white-space: pre-wrap; word-break: break-word;
  user-select: text; -webkit-user-select: text;
}
.trail[hidden] { display: none; }
.ask-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}
.ask-actions .btn {
  width: 100%;
  min-height: 42px;
  font-size: 15px;
}
.ask-count-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 4px;
}
.ask-count-wrap[hidden] { display: none; }
.ask-count-wrap .field-label {
  font-size: 14px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text);
}
.ask-count-seg button {
  min-height: 44px;
  font-size: 16px;
  font-weight: 600;
}
/* Bottom sheets for phone — scroll body, actions stay under the thumb */
.cast-editor,
.phone-sheet {
  top: auto;
  bottom: calc(var(--safe-b) + 10px);
  transform: none;
  left: max(var(--pad), env(safe-area-inset-left, 0px));
  right: max(var(--pad), env(safe-area-inset-right, 0px));
  max-width: 420px;
  max-height: min(88dvh, 640px);
  padding: 18px 16px 14px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.phone-sheet-form {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
  margin: 0;
}
.phone-sheet-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding-bottom: 4px;
}
.phone-sheet-actions {
  flex: none;
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--line-soft);
  background: var(--surface);
}
.cast-editor-look {
  min-height: 96px;
  max-height: 36vh;
  resize: vertical;
  font-size: 16px; /* avoid iOS focus-zoom */
  line-height: 1.4;
}
#cast-editor-name.field-control {
  font-size: 16px;
}
.cast-editor-check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 8px 0;
  padding: 12px 10px;
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-size: 14px;
  color: var(--text-dim);
  line-height: 1.4;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cast-editor-check input {
  width: 20px;
  height: 20px;
  margin-top: 1px;
  flex: none;
  accent-color: var(--accent);
}

.busy-row { display: flex; align-items: center; gap: 14px; font-size: 15px; }
.busy-row .spinner { position: static; flex: none; }
.spinner-dark { border-color: var(--line); border-top-color: var(--text); }

/* ── locked sessions ─────────────────────────────────────────────────── */

.session-thumb-locked {
  display: grid; place-items: center;
  background: var(--surface-2);
  color: var(--text-faint);
}
.session-thumb-locked .ico { width: 20px; height: 20px; }
.session-name .lock-mark {
  color: var(--text-faint);
  font-size: 12px;
  margin-left: 6px;
}

/* ── toast ───────────────────────────────────────────────────────────── */

.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--safe-b) + 84px);
  /* Below phone sheets (.ask z-index 65) so toasts never cover Cancel/Generate */
  z-index: 60;
  max-width: calc(100vw - 48px);
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  padding: 10px 18px;
  font-size: 14px;
  box-shadow: 0 8px 28px rgba(0,0,0,.5);
  animation: rise .18s ease;
}
.toast[hidden] { display: none; }
.toast-undo {
  flex: none;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-weight: 650;
  padding: 0;
  cursor: pointer;
}

/* ── ComfyUI settings ─────────────────────────────────────────────────
   Reuses the LLM screen's field styles wholesale; only the folded-away
   header/scheme pair needs anything of its own. */

.comfy-advanced {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 0 14px;
  margin: 0 0 20px;
}
.comfy-advanced > summary {
  cursor: pointer;
  padding: 12px 0;
  font-size: 13px;
  color: var(--muted);
  /* The default triangle sits badly against the uppercase field labels. */
  list-style: none;
}
.comfy-advanced > summary::-webkit-details-marker { display: none; }
.comfy-advanced > summary::after {
  content: '+';
  float: right;
  font-size: 15px;
  line-height: 1;
}
.comfy-advanced[open] > summary::after { content: '−'; }
.comfy-advanced[open] > summary { border-bottom: 1px solid var(--line); margin-bottom: 14px; }
/* The last field's own margin would double the panel's bottom padding. */
.comfy-advanced .field:last-of-type { margin-bottom: 10px; }

/* ── LLM settings ────────────────────────────────────────────────────── */

/* ── LLM / Comfy settings ──────────────────────────────────────────────
   Horizontal pad so field controls do not kiss the screen edge on phones. */

#llm-scroll,
#comfy-scroll {
  padding: 12px max(var(--pad), env(safe-area-inset-right, 0px))
    calc(var(--safe-b) + 24px) max(var(--pad), env(safe-area-inset-left, 0px));
}

.llm-lead {
  margin: 8px 0 20px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.45;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
}
.field-label {
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.field-control {
  width: 100%;
  appearance: none;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  font: inherit;
  font-size: 16px;
}
.field-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.field-row .field-control { flex: 1; }
.llm-auth {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}
.llm-auth-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.llm-paste {
  margin-top: 4px;
}
.llm-paste textarea {
  width: 100%;
  min-height: 72px;
  resize: vertical;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  font: inherit;
  font-size: 15px;
}
.llm-status {
  margin: 4px 0 12px;
  font-size: 13px;
  color: var(--muted);
  min-height: 1.2em;
}
.llm-status[data-ok="true"] { color: #8dcc9a; }
.llm-status[data-ok="false"] { color: #e08a8a; }
.llm-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 8px 0 32px;
}
.llm-usercode {
  font-size: 28px;
  letter-spacing: .18em;
  font-weight: 600;
  text-align: center;
  padding: 12px;
  border: 1px dashed var(--line);
  border-radius: 12px;
  margin: 8px 0;
}

/* ── story mode ──────────────────────────────────────────────────────── */

.story-tabs {
  display: flex;
  gap: 4px;
  padding: 0 12px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--bg);
  flex: none;
}
.story-tab {
  flex: 1;
  appearance: none;
  background: transparent;
  color: var(--muted);
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 14px 8px;
  min-height: 48px;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.story-tab.is-active {
  color: var(--text);
  border-bottom-color: var(--text);
}
.story-panel { padding: 12px 16px 24px; }
.cast-wizard {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
}
.cast-handle {
  color: var(--muted);
  font-weight: 500;
  font-size: 13px;
  margin-left: 6px;
}
.cast-handle-hint {
  margin: -4px 0 12px;
  color: var(--muted);
  font-size: 13px;
}
.cast-used {
  color: var(--muted);
  font-size: 13px;
}
.link-btn:disabled {
  opacity: 0.4;
  pointer-events: none;
}
.story-premise {
  min-height: 72px;
  resize: vertical;
  font-size: 16px;
}
.story-board-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}
.story-board-actions .btn {
  width: 100%;
  min-height: 48px;
}
.story-board-actions .btn.is-on {
  border-color: var(--accent-dim);
}
.cast-list, .beat-list {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.shot-insert {
  display: flex;
  justify-content: center;
  margin: -6px 0;
}
.shot-insert-btn {
  appearance: none;
  background: none;
  border: none;
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 8px 12px;
  min-height: 36px;
  cursor: pointer;
  border-radius: var(--r-sm);
}
.shot-insert-btn:active {
  background: var(--surface-2);
}
#beats-empty .shot-insert-btn {
  margin-top: 4px;
}
.cast-card, .beat-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 12px 14px;
}
.cast-card.is-active,
.beat-card.is-active {
  border-color: var(--accent-dim);
}
.cast-tools {
  display: flex;
  align-items: center;
  gap: 0;
  flex: none;
}
.cast-card-head, .beat-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px 8px;
  margin-bottom: 6px;
}
.cast-card-head { flex-wrap: wrap; }
.beat-card-head { flex-wrap: nowrap; }
.beat-card-head > .beat-tool {
  margin: -6px -8px -6px 0;
}
.beat-tool.is-on { color: var(--accent); }
.cast-name, .beat-index {
  font-weight: 600;
  font-size: 15px;
  flex: 1 1 auto;
  min-width: 0;
}
.cast-look, .beat-text {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.4;
  white-space: pre-wrap;
}
.beat-text-input {
  width: 100%;
  min-height: 72px;
  resize: vertical;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  padding: 12px;
  font: inherit;
  font-size: 16px; /* avoid iOS focus-zoom */
  line-height: 1.4;
}
.shot-text-view {
  width: 100%;
  min-height: 72px;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  padding: 12px;
  font-size: 16px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
}
.shot-text-placeholder { color: var(--muted); }
.handle-chip {
  display: inline;
  appearance: none;
  border: 0;
  margin: 0 1px;
  padding: 0 2px;
  background: none;
  color: var(--accent);
  font: inherit;
  font-weight: 650;
  cursor: pointer;
  border-radius: 4px;
}
.handle-chip:active { background: var(--accent-dim); }
.handle-chip.is-unknown {
  color: var(--muted);
  text-decoration: underline dotted;
}
.handle-chip-add {
  margin-left: 6px;
  color: var(--muted);
  font-weight: 700;
}
.cast-handle-chip {
  margin-left: 6px;
  font-size: 13px;
  font-weight: 600;
  min-height: 32px;
}
.cast-actions, .beat-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  justify-content: flex-end;
  margin: -4px -6px 0 0;
}
.beat-actions {
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: center;
  gap: 6px 10px;
  margin: 10px -8px 0;
}
.beat-panel-preview {
  position: relative;
  appearance: none;
  display: block;
  width: 100%;
  margin: 12px 0 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.beat-panel-preview.is-selected { border-color: #8dcc9a; }
.beat-panel-preview img {
  display: block;
  width: 100%;
  max-height: 380px;
  object-fit: contain;
  background: var(--surface-2);
}
.shot-pic-pair {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
  margin-left: auto;
  padding: 6px 8px 6px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  background: var(--surface-2);
  color: var(--accent);
  font: inherit;
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
}
.shot-pic-pair .ico {
  width: 18px;
  height: 18px;
  color: var(--text-dim);
}
.shot-pic-pair.is-on {
  border-color: var(--accent-dim);
  background: var(--surface);
}
.shot-pic-pair.is-on .ico { color: var(--accent); }
.outfit-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 12px;
}
.outfit-title {
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.outfit-tabs {
  display: flex;
  gap: 7px;
  margin: 7px -2px 0;
  padding: 2px;
  overflow-x: auto;
  scrollbar-width: none;
}
.outfit-tabs::-webkit-scrollbar { display: none; }
.outfit-tab {
  flex: none;
  min-height: 38px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.outfit-tab.is-on {
  border-color: var(--accent-dim);
  background: var(--accent-dim);
  color: var(--text);
}
.outfit-meta {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  margin-top: 8px;
}
.outfit-meta .cast-look { flex: 1; }
.outfit-tools { display: flex; gap: 4px; flex: none; }
.destructive-link { color: var(--danger); }
.canon-slots {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 10px 0 2px;
}
@media (min-width: 520px) {
  .canon-slots { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.canon-slot {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  min-width: 0;
}
.canon-slot .thumb-btn,
.canon-slot-empty {
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: 10px;
}
.canon-slot .cast-thumb,
.canon-slot .cast-thumb.is-canon {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border: 0;
}
.canon-slot-empty {
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--line);
  background: var(--surface-2);
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.canon-slot-empty:active { background: var(--surface); }
.canon-slot.is-on .thumb-btn,
.canon-slot.is-on .canon-slot-empty {
  box-shadow: 0 0 0 2px var(--accent);
}
.canon-slot-label {
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: center;
}
.canon-slot-gen {
  appearance: none;
  border: 0;
  margin: 0;
  padding: 6px 0 2px;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-align: center;
}
.canon-slot-gen.is-on { color: var(--text); }
.canon-slot-count {
  appearance: none;
  border: 0;
  margin: 0;
  padding: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  text-align: center;
}
.cast-canon {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 10px 0 4px;
}
.cast-canon-label {
  font-size: 12px;
  color: var(--muted);
}
.cast-status {
  margin: 8px 0 0;
  font-size: 13px;
  color: #8dcc9a;
}
.thumb-strip {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: 6px 0 2px;
  -webkit-overflow-scrolling: touch;
}
.thumb-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
}
.thumb-approve {
  font-size: 12px;
}
.thumb-btn {
  appearance: none;
  background: transparent;
  border: 2px solid transparent;
  border-radius: 12px;
  padding: 0;
  flex: 0 0 auto;
}
.thumb-btn.is-approved {
  border-color: #8dcc9a;
}
.cast-thumb, .beat-thumb {
  display: block;
  width: 96px;
  height: 128px;
  object-fit: contain;
  border-radius: 10px;
  background: var(--surface-2);
}
.cast-thumb.is-canon {
  width: 120px;
  height: 160px;
  border: 2px solid #8dcc9a;
}
.canon-setup-loras {
  /* Sheet scroll owns overflow; don't nest a tiny 42vh scroller on phones */
  max-height: none;
  overflow: visible;
  margin: 0;
}
.canon-setup-loras .lora {
  padding: 12px 0;
}
.canon-setup-loras .lora:last-child {
  border-bottom: 0;
}
.canon-lora .field-head {
  min-height: 40px;
}
.canon-lora .switch {
  width: 52px;
  height: 32px;
}
.canon-lora .switch::after {
  width: 26px;
  height: 26px;
}
.canon-lora .switch[aria-pressed="true"]::after {
  transform: translateX(20px);
}
.canon-lora-state {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-left: auto;
  margin-right: 10px;
}
.canon-lora:not(.off) .canon-lora-state {
  color: #8dcc9a;
}
.ref-slots {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 8px;
}
.ref-field {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}
.ref-slots .ref-field {
  margin-bottom: 0;
}
.ref-slot-name {
  margin: 0;
  font-size: 12px;
  color: var(--text-faint);
}
.ref-thumb {
  width: 72px;
  height: 96px;
  flex: none;
  border: 0;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-2);
  display: grid;
  place-items: center;
  color: var(--text-faint);
  font: inherit;
  font-size: 11px;
  text-align: center;
  padding: 6px;
}
.ref-thumb.has-photo {
  padding: 0;
  cursor: zoom-in;
}
.ref-thumb.has-photo:focus-visible {
  outline: 2px solid var(--accent, #8dcc9a);
  outline-offset: 2px;
}
.ref-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--surface-2);
  pointer-events: none;
}
.ref-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  flex: 1;
}
.ref-actions .btn {
  min-height: 40px;
}

.session-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  vertical-align: middle;
}

/* ── wider screens: keep it centred and phone-shaped ─────────────────── */

@media (min-width: 640px) {
  .screen {
    max-width: 560px;
    margin: 0 auto;
    border-left: 1px solid var(--line-soft);
    border-right: 1px solid var(--line-soft);
  }
  .sheet { max-width: 560px; margin: 0 auto; }
  .menu  { max-width: 528px; margin: 0 auto; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
