/* Comic Chat Composer — demo styles (Onion Madder neon house style).
   Loaded by index.html; the page markup is generated by build.ts and the app
   logic is bundled into app.js. Edit this file directly. */

@font-face {
  font-family: 'Chakra Petch';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('assets/ChakraPetch-Regular.ttf') format('truetype');
}

:root {
  --bg-deep: #050505; --panel: rgba(10, 0, 15, .85); --tile: rgba(20, 0, 30, .6);
  --pink: #ff2bb3; --cyan: #26ffe6; --violet: #a95eff;
  --text: #f2f0f6; --dim: #c3bdd2;
  --border-sharp: rgba(169, 94, 255, .5); --border-soft: rgba(169, 94, 255, .22);
  --glow-cyan: 0 0 7px rgba(38, 255, 230, .5); --glow-pink: 0 0 7px rgba(255, 43, 179, .5);
  --shadow-card: 0 2px 14px rgba(0, 0, 0, .5); --shadow-hover: 0 6px 22px rgba(38, 255, 230, .2);
  --radius: 8px; --t: .2s ease;
  /* Chakra Petch is the brand display face; body copy uses a plain readable
     sans so long text and the script stay legible (low-vision friendly). */
  --display: 'Chakra Petch', system-ui, sans-serif;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "JetBrains Mono", "IBM Plex Mono", Consolas, monospace;
}
* { box-sizing: border-box }
body {
  margin: 0; background: var(--bg-deep); color: var(--text);
  font: 16px/1.6 var(--sans); -webkit-font-smoothing: antialiased;
  background-image: radial-gradient(1200px 600px at 15% -10%, rgba(169, 94, 255, .10), transparent 60%), radial-gradient(1000px 500px at 100% 0%, rgba(38, 255, 230, .06), transparent 55%);
}
::selection { background: var(--pink); color: #000 }
.wrap { max-width: 1180px; margin: 0 auto; padding: 26px 22px 70px }
header.top { display: flex; align-items: center; gap: 14px; margin: 4px 0 26px }
.logo {
  width: 46px; height: 46px; flex: 0 0 auto; border-radius: 10px; display: grid; place-items: center;
  color: var(--cyan); border: 1px solid var(--cyan); background: rgba(38, 255, 230, .06); box-shadow: var(--glow-cyan)
}
.logo svg { width: 25px; height: 25px }
.brand h1 {
  font-family: var(--display); font-size: 26px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; margin: 0; line-height: 1.05;
  color: var(--pink); text-shadow: 0 0 12px rgba(255, 43, 179, .4)
}
.brand p { margin: 4px 0 0; color: var(--dim); font-size: 15px }
/* `minmax(0, 1fr)`, not `1fr`. A bare `1fr` is `minmax(auto, 1fr)`, and that auto
   minimum is the track's *min-content* — here the builder grid, which does not
   want to go below ~945px. The track refused to shrink and the whole page
   overflowed by 434px between 821px and 979px wide. Measured on the live site
   before any of this layout work, so it was long-standing, not new. */
.workspace { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 18px; align-items: start }
.card { background: var(--panel); border: 1px solid var(--border-soft); border-radius: var(--radius); box-shadow: var(--shadow-card); backdrop-filter: blur(6px) }
/* Wraps, because it must. The tabs plus the action buttons need ~711px laid out
   in one line, and without wrapping that became the card's min-content — so on a
   375px phone the whole page shrink-to-fit down to a 735px layout viewport and
   every control rendered at half size. */
.card > .hd { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 13px 16px; border-bottom: 1px solid var(--border-soft) }
.card > .hd .t { font-family: var(--display); font-weight: 700; font-size: 14px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--cyan) }
.card > .bd { padding: 16px }
.linkbtn { font-family: var(--display); background: none; border: 0; color: var(--pink); font-size: 13px; text-transform: uppercase; letter-spacing: 1px; cursor: pointer; padding: 0 }
.linkbtn:hover { text-shadow: var(--glow-pink) }
textarea {
  width: 100%; height: 250px; resize: vertical; border: 1px solid var(--border-sharp); border-radius: var(--radius);
  padding: 13px 14px; background: #000; color: var(--text); font: 15px/1.85 var(--mono)
}
textarea:focus, select:focus, input:focus { outline: none; box-shadow: var(--glow-cyan); border-color: var(--cyan) }
.help { margin-top: 12px }
.help summary { font-family: var(--display); cursor: pointer; color: var(--dim); font-size: 13px; text-transform: uppercase; letter-spacing: 1px; list-style: none }
.help summary:hover { color: var(--cyan) }
.help summary::-webkit-details-marker { display: none }
.help summary::before { content: "\203A"; display: inline-block; margin-right: 6px; color: var(--cyan); transition: transform .15s }
.help[open] summary::before { transform: rotate(90deg) }
.help-body { margin-top: 11px; padding: 14px; border: 1px dashed var(--border-soft); border-radius: var(--radius); background: var(--tile); font-size: 14.5px; line-height: 1.7 }
.help-body p { margin: 0 0 10px }
.hint-row { display: flex; flex-wrap: wrap; gap: 7px; align-items: baseline; margin: 6px 0 }
.hint-label { color: var(--dim); min-width: 84px; font-size: 12.5px; text-transform: uppercase; letter-spacing: .5px }
code { background: rgba(38, 255, 230, .08); color: var(--cyan); border: 1px solid rgba(38, 255, 230, .2); padding: 2px 7px; border-radius: 5px; font: 13.5px var(--mono) }
.setting { margin-bottom: 16px }
.setting > label { font-family: var(--display); display: block; font-size: 12.5px; text-transform: uppercase; letter-spacing: .5px; color: var(--dim); margin-bottom: 6px }
select, input[type=number], .setting input[type=text] { width: 100%; height: 42px; border: 1px solid var(--border-sharp); border-radius: var(--radius); background: #000; color: var(--text); padding: 0 12px; font: 15px var(--sans) }
.setting input[type=text]::placeholder { color: var(--dim); opacity: .6 }
select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%2326ffe6' stroke-width='2'%3E%3Cpath d='M2 4l4 4 4-4'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 13px center; padding-right: 32px; cursor: pointer }
.seedrow { display: flex; gap: 8px }
.seedrow input { flex: 1 }
.btn {
  font-family: var(--display); height: 42px; padding: 0 15px; border-radius: var(--radius); border: 1px solid var(--cyan); background: transparent; color: var(--cyan);
  font-weight: 700; font-size: 13.5px; text-transform: uppercase; letter-spacing: 1px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; justify-content: center; transition: var(--t)
}
.btn:hover { background: var(--cyan); color: #000; box-shadow: var(--glow-cyan) }
.btn.icon { flex: 0 0 auto; width: 42px; padding: 0; font-size: 18px }
.btn.primary { border-color: var(--pink); color: var(--pink) }
.btn.primary:hover { background: var(--pink); color: #000; box-shadow: var(--glow-pink) }
.toggle { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 14px; color: var(--dim) }
.toggle input { appearance: none; width: 38px; height: 22px; border-radius: 22px; background: #000; border: 1px solid var(--border-sharp); position: relative; cursor: pointer; transition: var(--t); flex: 0 0 auto }
.toggle input:checked { background: rgba(38, 255, 230, .2); border-color: var(--cyan); box-shadow: var(--glow-cyan) }
.toggle input::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--dim); transition: var(--t) }
.toggle input:checked::after { left: 17px; background: var(--cyan) }
.divider { height: 1px; background: var(--border-soft); margin: 18px 0 }
.exports { display: flex; gap: 8px }
.exports .btn { flex: 1 }
.share-btn { width: 100%; margin-top: 8px; justify-content: center }
.section-label { font-family: var(--display); font-size: 14px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--pink); margin: 30px 0 13px; display: flex; align-items: center; gap: 11px }
.section-label::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, var(--border-sharp), transparent) }
#status { font-family: var(--sans); color: var(--dim); font-size: 14px; letter-spacing: 0; text-transform: none }
#cast { display: flex; flex-wrap: wrap; gap: 10px }
.chip { display: inline-flex; align-items: center; gap: 9px; padding: 6px 8px 6px 12px; border: 1px solid var(--border-sharp); border-radius: 999px; background: var(--tile); transition: var(--t) }
.chip:hover { border-color: var(--cyan); box-shadow: var(--glow-cyan) }
.chip.is-manual { border-color: var(--pink); box-shadow: var(--glow-pink) }
.chip .sw { width: 11px; height: 11px; border-radius: 50%; background: var(--c, var(--dim)); flex: 0 0 auto; box-shadow: 0 0 6px var(--c) }
.chip .who { font-weight: 700; font-size: 15px; color: var(--text) }
.chip .arr { color: var(--dim); font-size: 12px; text-transform: uppercase; letter-spacing: .5px }
.chip select { height: 32px; border: none; background: transparent; box-shadow: none; padding: 0 24px 0 9px; width: auto; color: var(--cyan); font-size: 15px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' fill='none' stroke='%2326ffe6' stroke-width='2'%3E%3Cpath d='M1 3l4 4 4-4'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 7px center; font-weight: 700; cursor: pointer }
.comic-title { text-align: center; margin: -4px 0 20px; font-family: var(--display); color: var(--text) }
.comic-title .ct-title { font-size: 26px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--pink); text-shadow: 0 0 12px rgba(255, 43, 179, .4) }
.comic-title .ct-sub { margin-top: 4px; font-family: var(--sans); font-style: italic; font-size: 15px; color: var(--dim) }
#out { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 18px }
figure.panel { margin: 0 }
.frame { background: #000; border: 1px solid var(--border-sharp); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-card); transition: var(--t) }
figure.panel:hover .frame { transform: translateY(-3px); border-color: var(--cyan); box-shadow: var(--shadow-hover) }
.frame svg { display: block; width: 100%; height: auto }
figcaption { display: flex; align-items: center; gap: 8px; margin-top: 9px; font-size: 13px; color: var(--dim) }
.pn { display: inline-grid; place-items: center; width: 21px; height: 21px; border-radius: 5px; background: var(--pink); color: #000; font-size: 12px; font-weight: 700 }

/* Tabs: Builder / Script */
.tabs { display: flex; gap: 5px }
.tab {
  font-family: var(--display); font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px;
  padding: 6px 13px; border: 1px solid var(--border-soft); border-radius: 6px; background: transparent; color: var(--dim); cursor: pointer; transition: var(--t)
}
.tab:hover { color: var(--cyan) }
.tab.is-active { color: var(--cyan); border-color: var(--cyan); box-shadow: var(--glow-cyan) }

/* Builder layout: rows on the left, the shared emote console on the right */
/* `minmax(0, 1fr)` for the same reason as `.workspace` above — the row editor's
   min-content was holding this track open and shoving the 250px console off the
   right edge. */
.builder { display: grid; grid-template-columns: minmax(0, 1fr) 250px; gap: 16px; align-items: start }

/* The Comic-Chat "member list" — who is in the scene, each in their colour */
.members {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin-bottom: 12px;
  padding: 9px 11px; border: 1px solid var(--border-soft); border-radius: var(--radius); background: var(--tile)
}
.members-cap { font-family: var(--display); font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--dim); margin-right: 2px }
.members-empty { font-family: var(--sans); font-size: 13px; color: var(--dim) }
.member {
  display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px; border-radius: 999px; cursor: pointer; transition: var(--t);
  font: 700 13px var(--sans); color: var(--text); background: rgba(0, 0, 0, .4); border: 1px solid var(--c)
}
.member:hover { box-shadow: 0 0 8px var(--c) }
.member .sw { width: 11px; height: 11px; border-radius: 50%; background: var(--c); flex: 0 0 auto; box-shadow: 0 0 6px var(--c) }
.member .ct { font-family: var(--mono); font-size: 11px; color: var(--c); opacity: .85 }

.rows { margin-bottom: 9px }
/* `flex-wrap: wrap` is unconditional, and has to be — it cannot be done in the
   680px media query, because of a loop that query is on the wrong side of.
   Unwrapped, a row's fixed children (speaker, to, delivery, the line input, the
   badge) come to a min-content of 679px. That propagates all the way up, the
   page overflows 375px, the browser widens the *layout viewport* to 735px to
   shrink-to-fit — and at 735px `max-width: 680px` no longer matches, so the
   mobile rules that would have fixed it never apply. Breaking the min-content
   floor here is what lets the rest of the mobile CSS start working.
   On a wide screen there is room and it never wraps, so nothing changes. */
.brow {
  display: flex; flex-wrap: wrap; gap: 7px; align-items: center; padding: 7px 8px; margin-bottom: 7px;
  border: 1px solid var(--border-soft); border-left: 3px solid var(--c, var(--border-soft)); border-radius: var(--radius); background: var(--tile); transition: border-color var(--t), box-shadow var(--t)
}
.brow:hover { border-color: var(--border-sharp) }
.brow.is-active { border-color: var(--cyan); box-shadow: var(--glow-cyan) }
.brow.dragging { opacity: .45 }
.brow .grip { color: var(--dim); cursor: grab; font-size: 15px; line-height: 1; flex: 0 0 auto }
.brow .rsw { width: 9px; height: 9px; border-radius: 50%; background: var(--c, var(--dim)); flex: 0 0 auto; box-shadow: 0 0 5px var(--c) }
.brow select, .brow input { height: 32px; font: 13px var(--sans) }
.brow .who { width: auto; max-width: 130px; flex: 0 0 auto }
.brow .to, .brow .kind { width: auto; max-width: 118px; flex: 0 0 auto }
.brow .line { flex: 1 1 90px; min-width: 80px; border: 1px solid var(--border-sharp); border-radius: 6px; background: #000; color: var(--text); padding: 0 10px }
.brow .badge {
  font-family: var(--display); font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: var(--violet);
  border: 1px solid var(--border-soft); border-radius: 999px; padding: 3px 9px; white-space: nowrap; flex: 0 0 auto
}
.brow .rm { width: 26px; height: 26px; flex: 0 0 auto; border: none; background: transparent; color: var(--dim); font-size: 14px; line-height: 1; cursor: pointer; border-radius: 6px; padding: 0 }
.brow .rm:hover { color: var(--pink); background: rgba(255, 43, 179, .12) }
.add-row { width: 100%; justify-content: center; border-style: dashed }

/* The emote console: preview + wheel + gestures */
.console { position: sticky; top: 14px; display: flex; flex-direction: column }
.console-cap { font-family: var(--display); font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--pink); margin: 0 0 7px }
.console-cap:not(:first-child) { margin-top: 15px }
.preview { background: #fdfdf8; border: 1px solid var(--border-sharp); border-radius: var(--radius); overflow: hidden; aspect-ratio: 4/3; display: grid; place-items: center }
.preview svg { width: 100%; height: 100%; display: block }
.preview-empty { color: #888; font-size: 12.5px; padding: 16px; text-align: center; font-family: var(--sans) }
.wheel { width: 100%; max-width: 250px; margin: 0 auto; touch-action: none; -webkit-user-select: none; user-select: none }
.wheel-svg { width: 100%; height: auto; display: block; cursor: pointer }
.wheel-svg.is-off { opacity: .4; pointer-events: none }
.wheel-rim { fill: rgba(20, 0, 30, .55); stroke: var(--border-sharp); stroke-width: 1.5 }
.wheel-spoke { stroke: var(--border-soft); stroke-width: 1 }
.wheel-needle { stroke: var(--pink); stroke-width: 2.5; stroke-linecap: round }
.wheel-tip { fill: var(--pink) }
.wheel-node { fill: #000; stroke: var(--border-sharp); stroke-width: 1.5; transition: fill .12s }
.wheel-node.is-on { fill: var(--cyan); stroke: var(--cyan) }
.wheel-label { fill: var(--dim); font: 700 10px var(--display); text-transform: uppercase; letter-spacing: .4px }
.wheel-label.is-on { fill: var(--cyan) }
/* Selection ring around a pose-thumbnail node. */
.wheel-ring { fill: none; stroke: var(--border-sharp); stroke-width: 1.5 }
.wheel-ring.is-on { stroke: var(--cyan); stroke-width: 2.5 }
.wheel-center { fill: #000; stroke: var(--border-sharp); stroke-width: 1.5 }
.wheel-center.is-on { fill: var(--violet); stroke: var(--violet) }
.wheel-clabel { fill: var(--dim); font: 700 9px var(--display); text-transform: uppercase; letter-spacing: .4px; pointer-events: none }
.wheel-clabel.is-on { fill: #fff }
.gestures { display: flex; flex-wrap: wrap; gap: 6px }
.gest {
  font-family: var(--display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  padding: 6px 9px; border-radius: 6px; border: 1px solid var(--border-sharp); background: #000; color: var(--dim); cursor: pointer; transition: var(--t)
}
.gest:hover { border-color: var(--cyan); color: var(--cyan) }
.gest.is-on { background: var(--cyan); color: #000; border-color: var(--cyan) }
.gest:disabled { opacity: .4; cursor: default }

/* Keyboard focus — a clear ring on every interactive control (the neon glows
   are hover-only and easy to miss when tabbing). */
.btn:focus-visible, .tab:focus-visible, .gest:focus-visible, .member:focus-visible,
.linkbtn:focus-visible, .chip select:focus-visible, .toggle input:focus-visible {
  outline: 2px solid var(--cyan); outline-offset: 2px
}
.brow:focus-within { border-color: var(--cyan); box-shadow: var(--glow-cyan) }
.wheel-svg:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; border-radius: 50% }

/* Respect reduced-motion: drop the transitions/hover lifts. */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important }
  figure.panel:hover .frame { transform: none }
}

.site-foot { margin-top: 52px; padding-top: 22px; border-top: 1px solid var(--border-soft); max-width: 820px; color: var(--dim); font-size: 13px; line-height: 1.75 }
.site-foot p { margin: 0 0 8px }
.site-foot strong { color: var(--text); font-family: var(--display); letter-spacing: .5px }
.site-foot a { color: var(--cyan); text-decoration: none }
.site-foot a:hover { text-shadow: var(--glow-cyan) }
.foot-links { margin-top: 12px; font-family: var(--display); text-transform: uppercase; letter-spacing: 1px; font-size: 11.5px }

@media (max-width: 820px) { .workspace { grid-template-columns: 1fr } }
@media (max-width: 680px) { .builder { grid-template-columns: 1fr } .console { position: static } }

/* ---- Wide screens: the comic sits beside the editor, not below it ----
   Stacked, the controls came to 872px before the comic began — on a 910px-tall
   window that left 38px of it, so the page's entire point was below the fold and
   a visitor had to scroll to discover the thing was working at all.

   Side by side, the comic is visible on arrival and stays put: `.col-right` is
   sticky, so editing a line up in the builder never scrolls the result away.
   The workspace drops to a single column here — the left side is ~495px at the
   breakpoint, and its 1fr + 300px split would leave the editor about 170px wide.
   The two cards stack instead, which is what the 820px rule already does. */
/* ---- Narrow screens: the comic goes first ----
   Stacked in source order the comic sat 2765px down a phone — the same "I had to
   scroll to find it" problem the two-column layout solves on desktop, in the one
   place two columns cannot fit. So below the breakpoint the order flips and you
   land on the comic; the editor is directly under it.

   Every child needs an explicit `order`, not just the comic. `order: -1` alone
   would hoist it above the header too, since everything else defaults to 0. */
@media (max-width: 1029.98px) {
  .wrap { display: flex; flex-direction: column }
  header.top { order: 0 }
  .col-right { order: 1 }
  .col-left  { order: 2 }
  .site-foot { order: 3 }
}

@media (min-width: 1030px) {
  /* The left track's minimum is not arbitrary: a builder row needs ~679px, plus
     the card's padding and border, to sit on one line. The breakpoint follows
     from the tracks — 730 + 26 gap + 230 + 44 of page padding is 1030 — rather
     than being a round number picked first and made to fit. */
  .wrap { max-width: 1500px; display: grid;
          grid-template-columns: minmax(730px, 1.3fr) minmax(230px, 1fr);
          column-gap: 26px; align-items: start }
  /* Wrapping is a narrow-screen measure (see `.brow`). Here there is room for a
     row on one line, and 87px-tall rows would be a poor trade for a layout whose
     whole purpose is showing more at once. */
  .brow { flex-wrap: nowrap }
  header.top, .site-foot { grid-column: 1 / -1 }
  .workspace { grid-template-columns: 1fr }
  .col-right {
    position: sticky; top: 18px;
    max-height: calc(100dvh - 36px);
    overflow-y: auto;
    /* Its own scrollbar shouldn't crowd the panels. */
    scrollbar-width: thin;
  }
  /* Smaller minimum so a ~470px column still fits two panels across. */
  #out { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px }
}
