/* ─── The composer — the generate page's control surface ─────────────────────
   The sidebar's controls are RELOCATED at runtime (web/js/composer.js), ids
   intact, into a bar docked under the canvas: a prompt, a row of chips that
   open the old sections as popovers, attachments as a strip, Generate on the
   right with its cost. The empty sidebar column is hidden and the main area
   takes the full width. Nothing here changes what generate.js reads. */

#sceneLayout.composer { grid-template-columns: 1fr; }
#sceneLayout.composer > .sidebar { display: none; }
/* the canvas gives its height to the image: 12px of breathing room, not 24 */
@media (min-width: 901px) { #sceneLayout.composer .canvas-area { padding: 12px 24px; } }
/* the docked editor takes the whole canvas; the bar has nothing to do until it closes */
body.em-docked #sceneLayout.composer .cmp { display: none; }

/* the thread's timeline moves up beside the templates strip */
#sceneLayout.composer #timelineSection {
  padding: 8px 22px 6px; border-bottom: 1px solid var(--border);
}
#sceneLayout.composer #timelineSection .section-label { margin-top: 0; cursor: pointer; user-select: none; }
#sceneLayout.composer #timelineSection .section-label button { cursor: pointer; }
#sceneLayout.composer #timelineSection.collapsed #timeline { display: none; }
#sceneLayout.composer #timelineSection.collapsed { padding-bottom: 6px; }
.tl-toggle { display: inline-flex; align-items: center; gap: 6px; }
.tl-chev { display: inline-block; font-size: 10px; color: var(--text-faint); transition: transform .12s; }
#timelineSection:not(.collapsed) .tl-chev { transform: rotate(90deg); }

.cmp {
  position: relative; flex: none;
  /* a STABLE width from the screen, centred — never from the image. The image is
     height-bound now, so its width (and where its rails sit) changes with every
     render; a control surface that breathed with the artwork read as broken. This
     only changes with the screen format (see the phone rules below). */
  /* …and it is a control surface, not the stage: 60% wide, capped at 1040px, two
     rows tall (attachments strip · prompt row · chips + quick-remix on one line)
     — 72%/1240px and four rows read as "too big for the bar, too small for the
     image" on a 2560×1335 window (owner, 2026-09-03). */
  width: clamp(640px, 60%, 1040px); margin: 6px auto 4px;
  background: color-mix(in srgb, var(--fg) 4%, var(--bg));
  border: 1px solid var(--border-strong);
  border-radius: 16px;
  padding: 8px 12px;
  box-shadow: 0 10px 30px color-mix(in srgb, #000 35%, transparent);
}
.cmp-attach { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 0 0 6px 0; }
.cmp-attach:empty { display: none; }
.cmp-attach > div:empty { display: none; }
/* the moved thumb containers had their own top margins in the sidebar */
.cmp-attach #chosenCharsThumbs, .cmp-attach #charRefsThumbs, .cmp-attach #placedCastThumbs,
.cmp-attach #baseSceneBadge { margin-top: 0 !important; }
.cmp-attach #baseSceneBadge { padding: 4px 8px !important; }
.cmp-chip-att {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--border-strong); border-radius: 8px; padding: 2px 7px 2px 2px;
  font-size: 11px; color: var(--text-dim); background: var(--surface); cursor: pointer;
}
.cmp-chip-att img { width: 24px; height: 18px; object-fit: cover; border-radius: 4px; }
/* the attached characters' own chips, tightened to match */
.cmp-attach .chosen-char { padding: 2px 6px 2px 2px; font-size: 11px; }
.cmp-attach .chosen-char-av, .cmp-attach .chosen-char-av img { width: 20px; height: 20px; }
.cmp-chip-att b { font-weight: 600; color: var(--text); max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmp-chip-att .x { border: 0; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 13px; padding: 0 2px; }

.cmp-row { display: flex; align-items: flex-end; gap: 10px; }
.cmp-plus {
  flex: none; width: 36px; height: 36px; border-radius: 10px;
  border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text);
  font-size: 20px; line-height: 1; cursor: pointer; display: grid; place-items: center;
}
.cmp-plus:hover { background: color-mix(in srgb, var(--fg) 9%, transparent); }
.cmp-plus.on { border-color: var(--accent); color: var(--accent); }
.cmp-input { flex: 1; min-width: 0; display: flex; align-items: center; min-height: 36px; }
.cmp #noteInput {
  width: 100%; margin: 0; padding: 7px 4px; resize: none;
  background: transparent; border: 0; outline: 0; box-shadow: none;
  font-size: 14px; line-height: 1.45; color: var(--text); font-family: inherit;
  max-height: 132px; overflow-y: auto;
}
.cmp #noteInput::placeholder { color: var(--text-muted); }
.cmp #genBtn {
  flex: none; width: auto; margin: 0; padding: 0 16px; height: 40px;
  border-radius: 11px; font-size: 13.5px; gap: 10px;
}
.cmp #genBtn #genCost {
  font-weight: 700; padding-left: 10px; border-left: 1px solid color-mix(in srgb, #000 18%, transparent);
}
.cmp #genBtn:disabled #genCost { display: none; }

.cmp-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 6px 0 0 0; }
/* quick-remix (Basic | Advanced + credits) shares the chips' line, pushed right */
.cmp-chips .cmp-foot { order: 99; margin: 0 0 0 auto; }
.cmp-chip {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-dim);
  border-radius: 9px; padding: 6px 10px; font-size: 12px; font-family: inherit; cursor: pointer;
  transition: background .12s, border-color .12s, color .12s; white-space: nowrap;
}
.cmp-chip:hover { color: var(--text); background: var(--surface-2); }
.cmp-chip.on { border-color: var(--accent); color: var(--text); background: var(--accent-soft); }
.cmp-chip .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); display: none; }
.cmp-chip.set .dot { display: inline-block; }
.cmp-chip .arr { color: var(--text-faint); font-size: 11px; }
/* Apply-my-taste rides in the chip row */
.cmp-chips #tasteBtn { width: auto !important; margin: 0 !important; padding: 6px 10px !important; font-size: 12px !important; border-radius: 9px !important; }

/* popovers: one at a time, above the bar */
.cmp-pop {
  display: none; position: absolute; left: 12px; right: 12px; bottom: calc(100% + 8px);
  max-width: 560px; max-height: min(62vh, 520px); overflow-y: auto; z-index: 40;
  background: var(--bg); border: 1px solid var(--border-strong); border-radius: 14px;
  padding: 14px 16px; box-shadow: 0 14px 40px color-mix(in srgb, #000 45%, transparent);
}
.cmp-pop.open { display: block; }
.cmp-pop .section-label:first-child { margin-top: 0; }
.cmp-pop textarea { width: 100%; }
.cmp-pop-title { font-size: 12.5px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.cmp-menu { display: flex; flex-direction: column; gap: 2px; }
.cmp-menu button {
  display: flex; align-items: center; gap: 10px; text-align: left; width: 100%;
  background: transparent; border: 0; color: var(--text); font-family: inherit; font-size: 13px;
  padding: 9px 10px; border-radius: 9px; cursor: pointer;
}
.cmp-menu button:hover { background: var(--surface-2); }
.cmp-menu button small { color: var(--text-muted); font-size: 11px; margin-left: auto; }
.cmp-pop .cmp-sec { margin-top: 12px; }

@media (max-width: 900px) {
  /* iOS zooms the page when a focused input is under 16px — every text field in the
     bar and its sheets sits at 16px on phones */
  .cmp #noteInput, .cmp-pop input, .cmp-pop textarea, .cmp-pop select { font-size: 16px !important; }
  /* the page scrolls here, not the pane — so the bar pins to the viewport and
     the content gets room to scroll out from under it */
  .cmp { position: fixed; left: 8px; right: 8px; bottom: 8px; margin: 0; z-index: 30;
         width: auto; min-width: 0; }   /* the desktop clamp() has a 640px floor — never here */
  body.composer-on .main { padding-bottom: 170px; }
  body.rail-docked .cmp, body.rail-docked .cmp-pop { bottom: 78px; }
  .cmp-attach, .cmp-chips { margin-left: 0; }
  .cmp-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .cmp-chips::-webkit-scrollbar { display: none; }
  .cmp-chips .cmp-chip, .cmp-chips #tasteBtn { flex: 0 0 auto; }
  .cmp-pop { position: fixed; left: 8px; right: 8px; bottom: 8px; max-width: none; max-height: 72vh; }
  .cmp-pop.cmp-at { position: absolute; left: 8px; right: 8px; bottom: calc(100% + 8px); max-height: 40vh; }
  /* the sheets' fields stay inside the sheet */
  .cmp-pop { overflow-x: hidden; }
  .cmp-pop textarea, .cmp-pop input { box-sizing: border-box; max-width: 100%; }
}
@media (max-width: 600px) {
  .cmp-step { padding: 10px; }
  .cmp-step-h { font-size: 12px; margin-bottom: 6px; }
  .cmp-step-b img, .cmp-step-av { width: 44px; height: 44px; }
  .cmp-step-gen #genBtn { height: 44px; }
  /* Generate takes its own full-width row under the chips — thumb-sized, and
     the prompt keeps the whole first line */
  .cmp-row { flex-wrap: wrap; }
  .cmp #genBtn { width: 100%; order: 3; margin-top: 8px; height: 46px; }
  .cmp-chips { margin-top: 8px; }
}
body.composer-on #stFab { bottom: 148px; }
@media (max-width: 900px) {
  body.composer-on #stFab, body.composer-on .bugFab { bottom: 176px; }
}

/* @ mentions: a compact list above the bar */
.cmp-at { padding: 6px; max-width: 360px; left: 14px; right: auto; width: min(360px, calc(100% - 28px)); }
.cmp-at-row {
  display: flex; align-items: center; gap: 9px; padding: 6px 8px; border-radius: 8px; cursor: pointer;
  font-size: 12.5px; color: var(--text);
}
.cmp-at-row.on, .cmp-at-row:hover { background: var(--surface-2); }
.cmp-at-av { width: 26px; height: 26px; border-radius: 50%; background: var(--surface-2); overflow: hidden; flex: none; display: grid; place-items: center; font-size: 11px; color: var(--text-faint); }
.cmp-at-av img { width: 100%; height: 100%; object-fit: cover; }
.cmp-at-row small { color: var(--text-muted); margin-left: auto; font-size: 11px; }
.cmp-at-empty { padding: 8px 10px; font-size: 12px; color: var(--text-muted); }
@media (max-width: 600px) { .cmp-at { left: 8px; width: auto; right: 8px; max-width: none; } }

/* ─── Basic mode: four steps over the same pipeline ─────────────────────── */
.cmp-basic { display: none; }
.cmp.basic .cmp-attach, .cmp.basic .cmp-row, .cmp.basic .cmp-chips { display: none; }
.cmp.basic .cmp-basic {
  display: grid; grid-template-columns: 1.2fr 1.2fr 1.2fr auto; gap: 0;
  border: 1px solid var(--border); border-radius: 12px; overflow: hidden; background: var(--surface);
}
.cmp-step { padding: 12px 14px; border-right: 1px solid var(--border); min-width: 0; }
.cmp-step:last-child { border-right: 0; }
.cmp-step-h { font-size: 12.5px; font-weight: 600; color: var(--text); margin-bottom: 10px; }
.cmp-step-h .opt { font-weight: 400; color: var(--text-muted); }
.cmp-step-b { display: flex; align-items: center; gap: 10px; }
.cmp-step-b img, .cmp-step-av {
  width: 56px; height: 56px; border-radius: 10px; object-fit: cover; flex: none;
  background: var(--surface-2); display: grid; place-items: center; color: var(--text-faint); font-size: 16px; overflow: hidden;
}
.cmp-step-av img { width: 100%; height: 100%; object-fit: cover; }
.cmp-step-av.set { color: var(--accent); background: var(--accent-soft); }
.cmp-step-t { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cmp-step-t b { font-size: 13px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmp-step-t small { font-size: 11px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmp-step-btn {
  align-self: flex-start; margin-top: 4px; border: 1px solid var(--border-strong); background: transparent;
  color: var(--text-dim); border-radius: 7px; padding: 3px 9px; font-size: 11px; font-family: inherit; cursor: pointer;
}
.cmp-step-btn:hover { color: var(--text); background: var(--surface-2); }
.cmp-step-gen { display: flex; flex-direction: column; justify-content: center; align-items: stretch; padding-right: 14px; }
.cmp-step-gen .cmp-step-b { justify-content: center; }
.cmp-step-gen #genBtn { height: 44px; width: 100%; }
.cmp-step-cost { display: block; text-align: center; font-size: 11px; color: var(--text-muted); margin-top: 6px; }

.cmp-foot { display: flex; align-items: center; gap: 12px; font-size: 12px; color: var(--text-muted); }
.cmp.basic > .cmp-foot { margin-top: 10px; }      /* under the Basic steps it is its own row again */
.cmp-foot-r { margin-left: auto; }
.cmp-chips .cmp-foot .cmp-foot-r { margin-left: 4px; }
.cmp-seg { display: inline-flex; border: 1px solid var(--border-strong); border-radius: 8px; overflow: hidden; }
.cmp-seg button {
  border: 0; background: transparent; color: var(--text-dim); font-family: inherit; font-size: 11.5px;
  padding: 4px 10px; cursor: pointer;
}
.cmp-seg button.on { background: var(--surface-2); color: var(--text); font-weight: 600; }

/* the result */
.cmp-res { display: none; position: fixed; inset: 0; z-index: 80; background: rgba(0,0,0,.6); align-items: center; justify-content: center; padding: 20px; }
.cmp-res.open { display: flex; }
.cmp-res-box {
  width: min(560px, 100%); max-height: calc(100dvh - 40px); overflow-y: auto;
  background: var(--bg); border: 1px solid var(--border-strong); border-radius: 16px; padding: 16px 18px 18px;
  box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
.cmp-res-h { display: flex; align-items: center; justify-content: space-between; font-size: 15px; font-weight: 600; }
.cmp-res-h .new { font-style: normal; font-size: 9px; letter-spacing: .1em; background: var(--accent); color: var(--gen-btn-text, #111); border-radius: 4px; padding: 2px 5px; margin-left: 8px; vertical-align: middle; }
.cmp-res-x { border: 0; background: transparent; color: var(--text-muted); font-size: 20px; cursor: pointer; line-height: 1; }
.cmp-res-meta { display: block; font-size: 11.5px; color: var(--text-muted); margin: 2px 0 10px; }
.cmp-res-meta b { color: var(--text); font-weight: 600; }
#cmpResImg { width: 100%; border-radius: 12px; display: block; background: var(--surface-2); }
.cmp-res-acts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 12px; }
.cmp-res-acts button {
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); border-radius: 10px;
  padding: 10px 6px; font-size: 12px; font-family: inherit; cursor: pointer;
}
.cmp-res-acts button:hover { background: var(--surface-2); }
.cmp-res-adv {
  display: block; margin: 12px auto 0; border: 1px solid var(--accent-border); background: var(--accent-soft);
  color: var(--accent); border-radius: 9px; padding: 7px 14px; font-size: 12px; font-family: inherit; cursor: pointer;
}
@media (max-width: 900px) {
  /* 2×2 on phones: Scene | Character over Style | Generate — no empty cell */
  .cmp.basic .cmp-basic { grid-template-columns: 1fr 1fr; }
  .cmp-step:nth-child(2), .cmp-step:nth-child(4) { border-right: 0; }
  .cmp-step:nth-child(1), .cmp-step:nth-child(2) { border-bottom: 1px solid var(--border); }
  .cmp-step-gen { grid-column: auto; }
}

/* ─── Every card fits the visible canvas ─────────────────────────────────────
   The card image used to be width:100% of a 680px column, so a tall render ran
   off the bottom of the canvas with the bar under it. Now a LOADED image is sized
   by the canvas height (the canvas is a size container on desktop): as tall as
   the visible area allows, never wider than the column, ratio preserved — small
   renders scale up to it, panoramas cap on width. The card, the feed column and
   the feed block shrink-wrap the image, so the trace rail on the left and the
   action rail on the right hug whatever size that produces, and the composer
   (which measures those rails) follows. The lazy placeholder keeps its old
   width until the image has loaded — an unloaded image has no ratio to size by. */
@media (min-width: 901px) {
  /* height: the canvas, nearly to its bottom edge. width: whatever is left beside the
     rails — composer.js measures the tool pill, the trace rail (its width depends on
     how many branches the thread has) and the action rail, and writes --cmp-img-maxw.
     The old 680px column cap is lifted; it was what kept a landscape render short. */
  /* height: the canvas — OR the width cap divided by the image's own ratio (--r,
     written by composer.js at load), whichever is smaller. With only the width
     capped, an explicit height would stretch the image: a landscape render on a
     930px window became a 320×614 portrait of a very tall elf (owner, 2026-09-03). */
  #sceneLayout.composer .scene-card > img.fit {
    height: min(calc(100cqh - 8px), calc(var(--cmp-img-maxw, calc(100cqw - 400px)) / var(--r, 1.5)));
    width: auto; aspect-ratio: auto;
    max-width: var(--cmp-img-maxw, calc(100cqw - 400px));
  }
  #sceneLayout.composer .scene-card:has(> img.fit) { width: fit-content; max-width: none; margin-left: auto; margin-right: auto; }
  #sceneLayout.composer .scene-feed:has(> .scene-card > img.fit) { flex: 0 1 auto; width: fit-content; max-width: none; align-items: center; }
  #sceneLayout.composer .feed-wrap:has(img.fit) { width: auto; max-width: none; padding-right: var(--cmp-rail-w, 0px); }
  /* a PORTRAIT render is narrow, and the column's other children — the version
     pill, the notes, the connectors — used to be wider than it, so THEY set the
     column width, the image floated in a gap, and the action rail (placed off the
     image's edge) landed on top of them. The image is the only thing allowed to set
     the column's width now: everything else takes that width without contributing
     to it (width:0 + min-width:100%), and wraps. A floor keeps a very narrow image
     from squeezing the pills into a sliver. */
  #sceneLayout.composer .scene-feed:has(> .scene-card > img.fit) { min-width: 320px; }
  #sceneLayout.composer .scene-feed:has(> .scene-card > img.fit) > :not(.scene-card) { width: 0; min-width: 100%; box-sizing: border-box; }
}
/* the overlays inside the image never spill outside it, at any width */
#sceneLayout.composer .scene-card > .result-tag { max-width: 55%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#sceneLayout.composer .scene-card > div[title^="Shot at"] { max-width: 40%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
