/* Harmoniva Studio — panel styling.
   The product's own palette, so the tool looks like the thing it makes work for:
   near-black violet ground, raised panels, cream type, brand purple for primary
   actions, orange as the sparing second accent. */

:root {
  --bg: #0C0A10;
  --bg-alt: #14111C;
  --panel: #1C1828;
  --line: #2E2740;
  --edge: #3A3252;
  --text: #FAF7F2;
  --dim: #A79FB8;
  --accent: #9333EA;
  --accent-dark: #7C3AED;
  --deep: #581C87;
  --gold: #F97316;
  --danger: #F87171;
  --ok: #4ADE80;
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;
}

* { box-sizing: border-box; }
/* Stated explicitly: .drawer, .seg and .btn all set display themselves, and an
   author rule beats the UA stylesheet's [hidden] rule. */
[hidden] { display: none !important; }

html, body { margin: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ------------------------------------------------------------------- gate -- */
.gate { min-height: 100vh; display: grid; place-items: center; padding: 24px;
        background: radial-gradient(1200px 600px at 50% -10%, #2A1B45 0%, var(--bg) 60%); }
.gate-card { width: min(400px, 100%); background: var(--panel); border: 1px solid var(--line);
             border-radius: var(--r-lg); padding: 34px 30px; display: grid; gap: 14px; }
.gate-mark { font-size: 34px; line-height: 1; color: var(--accent); }
.gate-card h1 { margin: 0; font-size: 22px; letter-spacing: -0.3px; }
.gate-sub, .gate-note { margin: 0; color: var(--dim); font-size: 13px; }
.gate-note { border-top: 1px solid var(--line); padding-top: 12px; }
.gate-err { margin: 0; color: var(--danger); font-size: 13px; }
.gate-card input { width: 100%; }

/* ----------------------------------------------------------------- topbar -- */
.topbar { display: flex; align-items: center; justify-content: space-between; gap: 16px;
          padding: 14px 26px; border-bottom: 1px solid var(--line);
          background: var(--bg-alt); position: sticky; top: 0; z-index: 20; }
.brand { font-weight: 700; letter-spacing: -0.2px; }
.brand em { font-style: normal; color: var(--dim); font-weight: 500; }
.brand-mark { color: var(--accent); margin-right: 6px; }
.readouts { display: flex; align-items: center; gap: 18px; font-size: 13px; color: var(--dim); }
.readout b { color: var(--text); font-weight: 600; }
.readout.link { color: var(--dim); text-decoration: none; }
.readout.link:hover { color: var(--text); }
.readout.warn b, .readout.warn { color: var(--gold); }

/* ------------------------------------------------------------------- wrap -- */
.wrap { max-width: 1240px; margin: 0 auto; padding: 26px;
        display: grid; grid-template-columns: 380px 1fr; gap: 26px; align-items: start; }
@media (max-width: 980px) { .wrap { grid-template-columns: 1fr; } }

.panel { background: var(--panel); border: 1px solid var(--line);
         border-radius: var(--r-lg); padding: 22px; }
.maker-head h2, .lib-head h2 { margin: 0 0 4px; font-size: 17px; letter-spacing: -0.2px; }
.muted { color: var(--dim); font-size: 12.5px; margin: 0; }

.lbl { display: grid; gap: 6px; font-size: 13px; color: var(--dim); }
.lbl.inline { display: flex; align-items: center; gap: 8px; }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* The video rows carry the long option text — "Woman, 40s — music teacher,
   studio room", "Hook + closing CTA (same person)". Two of those side by side in
   a 380px sidebar are two ellipses, so they pair up only where each half gets
   200px and stack where it does not. */
#video-only .row { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }

input[type=text], input[type=password], input[type=number], input[type=date],
select, textarea {
  background: var(--bg); color: var(--text); border: 1px solid var(--edge);
  border-radius: var(--r-sm); padding: 9px 11px; font: inherit; font-size: 14px;
  /* A <select> is as wide as its widest OPTION unless told otherwise, and this
     panel has options like "Hook + closing CTA (same person)". Left alone, one
     of those sets the width of its column, its row, and the whole wizard — which
     is what made the video fields burst out of the panel when Video was picked.
     width + min-width together are what let it take the column's width instead
     of demanding its content's. */
  width: 100%; min-width: 0; max-width: 100%;
}
/* Except where the field shares a line with its own label, where it takes the
   leftover width instead. Checkboxes are excluded by listing the types that may
   grow — `.lbl.inline input` would also match the "Burn in captions" box and
   stretch a 16px control across the row. */
.lbl.inline select,
.lbl.inline input[type=text],
.lbl.inline input[type=number],
.lbl.inline input[type=date] { width: auto; flex: 1 1 auto; }
/* Safari draws the date picker's own glyph in the system colour, which is black
   on this ground. */
input[type=date]::-webkit-calendar-picker-indicator { filter: invert(.7); }
textarea { resize: vertical; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(147,51,234,.22);
}

.seg { display: flex; gap: 6px; flex-wrap: wrap; }
.seg button, .filters button {
  background: var(--bg); color: var(--dim); border: 1px solid var(--edge);
  border-radius: 999px; padding: 7px 14px; font: inherit; font-size: 13px; cursor: pointer;
}
.seg button.on, .filters button.on {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}

/* Beat picker — many small toggles, so they wrap rather than scroll. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chips button {
  background: var(--bg); color: var(--dim); border: 1px solid var(--edge);
  border-radius: 999px; padding: 5px 11px; font: inherit; font-size: 12px; cursor: pointer;
}
.chips button.on { background: var(--deep); border-color: var(--accent); color: var(--text); }

/* Voice picker: the select takes the space, the preview button keeps its own
   width so its label does not reflow as it changes between states. */
.voice-pick { display: flex; align-items: center; gap: 8px; min-width: 0; }
.voice-pick select { flex: 1 1 auto; min-width: 0; }
.voice-pick .btn { flex: 0 0 auto; padding: 8px 14px; font-size: 13px; white-space: nowrap; }

.lbl.check { flex-direction: row; align-items: center; align-self: end; padding-bottom: 9px; }
.lbl.check input { accent-color: var(--accent); width: 16px; height: 16px; }

/* The presenter reference. The thumbnail is the whole point of the block — an
   uploaded face nobody can see until the render lands is a face nobody trusts —
   so it holds its 3:4 box whether or not the source photo is that shape. */
.ref { display: flex; gap: 12px; align-items: flex-start; }
.ref-pic { flex: 0 0 auto; width: 84px; height: 112px; overflow: hidden;
           border: 1px solid var(--edge); border-radius: 8px; background: var(--bg); }
.ref-pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ref-body { flex: 1 1 auto; min-width: 0; display: grid; gap: 10px; }
.ref-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ref-actions .btn { flex: 0 0 auto; padding: 8px 14px; font-size: 13px; }

/* The same image in a finished piece's drawer, where there is room to see it. */
.ref-shot img { display: block; width: 100%; max-width: 220px;
                border: 1px solid var(--edge); border-radius: 10px; }

#video-only { display: grid; gap: 14px; }

.btn { border: 1px solid var(--edge); background: var(--bg); color: var(--text);
       border-radius: 999px; padding: 9px 18px; font: inherit; font-size: 14px; cursor: pointer; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.btn.primary:hover { background: var(--accent-dark); }
.btn.ghost { color: var(--dim); }
.btn.danger { color: var(--danger); border-color: #52304a; }
.btn[disabled] { opacity: .5; cursor: default; }
.maker-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px;
              border-top: 1px solid var(--line); padding-top: 14px; }
/* The action never wraps to two lines — the model picker beside it gives way. */
.maker-foot .btn { flex: 0 0 auto; white-space: nowrap; }
.err { color: var(--danger); font-size: 13px; margin: 0; }

/* The prompt writer, under the Describe-it box. Right-aligned and small: it is
   an offer, not the thing the wizard is for — Build it stays the only action
   with weight in this dialog. */
.notes-tools { display: flex; align-items: center; justify-content: flex-end; gap: 10px;
               flex-wrap: wrap; }
.notes-tools .muted { flex: 1 1 auto; font-size: 12px; min-width: 0; }
.notes-tools .btn { flex: 0 0 auto; padding: 6px 14px; font-size: 13px; white-space: nowrap; }
.notes-tools .spark { color: var(--accent); }
/* Held while the agent is running, so a slow call still looks alive. */
.notes-tools .btn.working { opacity: 1; color: var(--dim); }
.notes-tools .btn.working .spark { animation: spark 1.1s ease-in-out infinite; }
@keyframes spark { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .notes-tools .btn.working .spark { animation: none; }
}

/* ---------------------------------------------------------------- library -- */
.lib-head { display: flex; align-items: center; justify-content: space-between;
            gap: 16px; margin-bottom: 14px; flex-wrap: wrap; }
.filters { display: flex; gap: 6px; flex-wrap: wrap; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 16px; }
.empty { padding: 30px 0; }

.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md);
        overflow: hidden; cursor: pointer; transition: border-color .15s, transform .15s; }
.card:hover { border-color: var(--edge); transform: translateY(-2px); }
.card-media { position: relative; background: var(--bg-alt); aspect-ratio: 4 / 5;
              display: grid; place-items: center; overflow: hidden; }
.card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card-media .placeholder { color: var(--edge); font-size: 30px; }
.card-count { position: absolute; right: 8px; bottom: 8px; background: rgba(12,10,16,.82);
              border: 1px solid var(--edge); border-radius: 999px;
              padding: 3px 9px; font-size: 11px; color: var(--text); }
.card-body { padding: 11px 13px 13px; display: grid; gap: 5px; }
.card-title { font-size: 14px; font-weight: 600; line-height: 1.3; }
.card-sub { font-size: 11.5px; color: var(--dim); }
/* The live line on a building card. One line, clipped — the drawer is where the
   whole trail lives; this only has to prove the thing is moving. */
.card-now { font: 10.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
            color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px;
         border-radius: 999px; padding: 2px 9px; border: 1px solid var(--edge); color: var(--dim); }
.badge.ready { color: var(--ok); border-color: #235c3a; }
.badge.failed { color: var(--danger); border-color: #52303a; }
.badge.building, .badge.queued { color: var(--gold); border-color: #5c3f22; }

/* ------------------------------------------------------------------- live --
   The "Right now" panel and the drawer's live section share these. A build is
   ten to forty minutes of someone else's work, and the whole point of this
   block is that something in it visibly changes while you watch it. */
.live { display: grid; gap: 12px; }
.live-row { border-top: 1px solid var(--line); padding-top: 12px; display: grid; gap: 8px; }
.live-row:first-child { border-top: 0; padding-top: 0; }
.live-row-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 13.5px; }
.live-when { margin-left: auto; display: flex; align-items: center; gap: 7px; }

/* The stage rail: the whole path, so a stage name means something relative to
   what is left rather than only to itself. */
.rail { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.rail-step { font-size: 10.5px; letter-spacing: .6px; text-transform: uppercase;
             color: var(--edge); border: 1px solid var(--line); border-radius: 999px;
             padding: 2px 9px; }
.rail-step.done { color: var(--dim); border-color: var(--edge); }
.rail-step.on { color: var(--bg); background: var(--gold); border-color: var(--gold);
                font-weight: 700; }

.live-line { margin: 0; font-size: 13px; }
.live-now { margin: 0; font: 11.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
            color: var(--text); background: var(--bg); border: 1px solid var(--line);
            border-radius: var(--r-sm); padding: 8px 10px;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.live-now.muted { color: var(--dim); }

/* The agent's own trail. Newest last, because that is the order it happened in
   and the eye is already at the bottom of the block. */
.events { list-style: none; margin: 0; padding: 0; display: grid; gap: 3px;
          max-height: 300px; overflow-y: auto; }
.ev { display: grid; grid-template-columns: 14px auto 1fr; gap: 7px; align-items: baseline;
      font-size: 11.5px; color: var(--dim); }
.ev-mark { color: var(--edge); }
.ev b { color: var(--text); font-weight: 600; }
.ev span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
           font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; }
.ev.text b, .ev.think b { color: var(--dim); font-weight: 500; font-style: italic; }
.ev.think span { color: var(--edge); }
.ev.result b { color: var(--ok); }
.ev.bad b, .ev.bad span { color: var(--danger); }
.ev.bad .ev-mark { color: var(--danger); }

.live h5, .live-sec h5 { margin: 12px 0 6px; font-size: 11px; color: var(--dim); font-weight: 600;
               text-transform: uppercase; letter-spacing: 1px; }
pre.log.tail { max-height: 220px; }

/* ------------------------------------------------------------ maker modal -- */
/* The wizard is a centred dialog rather than a column, so the make tab is the
   library. Its own scrim sits under the drawer's, so a card opened from behind
   the wizard still layers correctly. */
.modal-scrim { position: fixed; inset: 0; background: rgba(6,4,10,.66); z-index: 28; }
.modal { position: fixed; z-index: 29; left: 50%; top: 50%; transform: translate(-50%, -50%);
         width: min(900px, calc(100% - 48px)); max-height: min(920px, calc(100dvh - 48px));
         background: var(--bg-alt); border: 1px solid var(--line);
         border-radius: var(--r-lg); display: flex; flex-direction: column;
         box-shadow: 0 24px 60px rgba(0,0,0,.55); }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between;
              gap: 16px; padding: 18px 26px; border-bottom: 1px solid var(--line); }
.modal-head h3 { margin: 0 0 3px; font-size: 16px; }
.modal-body { padding: 22px 26px; overflow-y: auto; display: grid; gap: 16px; }
.modal-foot { padding: 14px 26px; border-top: 1px solid var(--line); margin: 0; }

/* The make tab's header: what the wizard used to say, then the way in. With the
   form gone the page opens on a library, so the one control that makes anything
   new gets the full width rather than sitting as a pill in the corner. */
.make-bar { display: grid; gap: 14px; }
.make-bar .btn.cta {
  width: 100%; padding: 18px 22px; font-size: 16px; font-weight: 600;
  border-radius: var(--r-md); display: flex; align-items: center;
  justify-content: center; gap: 10px;
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  border: 1px solid var(--accent);
  box-shadow: 0 10px 26px rgba(147,51,234,.32);
}
/* Restated, because `.btn.primary:hover` would otherwise flatten the gradient
   back to a single fill on hover. */
.make-bar .btn.cta:hover { background: linear-gradient(135deg, var(--accent), var(--accent-dark));
                           filter: brightness(1.1); box-shadow: 0 12px 30px rgba(147,51,234,.42); }
.make-bar .btn.cta .plus { font-size: 20px; line-height: 1; font-weight: 400; }

/* ----------------------------------------------------------------- drawer -- */
.drawer-scrim { position: fixed; inset: 0; background: rgba(6,4,10,.66); z-index: 30; }
.drawer { position: fixed; top: 0; right: 0; height: 100vh; width: min(660px, 100%);
          background: var(--bg-alt); border-left: 1px solid var(--line); z-index: 31;
          display: flex; flex-direction: column; }
.drawer-head { display: flex; align-items: flex-start; justify-content: space-between;
               gap: 16px; padding: 18px 22px; border-bottom: 1px solid var(--line); }
.drawer-head h3 { margin: 0 0 3px; font-size: 16px; }
.drawer-body { padding: 20px 22px 40px; overflow-y: auto; display: grid; gap: 20px; }

.shots { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.shot { border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden;
        background: var(--bg); position: relative; display: block; }
.shot img { width: 100%; display: block; }
.shot span { position: absolute; left: 6px; top: 6px; background: rgba(12,10,16,.8);
             border-radius: 999px; padding: 2px 8px; font-size: 10.5px; color: var(--dim); }

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.fact { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-sm);
        padding: 10px 12px; }
.fact b { display: block; font-size: 15px; }
.fact span { font-size: 11px; color: var(--dim); }
/* Over the cap: the number that explains why nothing is building. */
.fact.bad { border-color: #52303a; }
.fact.bad b, .fact.bad span { color: var(--danger); }

/* --------------------------------------------------------------- settings -- */
.cap-now .facts { margin-bottom: 2px; }
#tab-settings code { font-size: 11.5px; background: var(--bg); border: 1px solid var(--line);
                     border-radius: 5px; padding: 1px 5px; }
/* The save row pairs a field with buttons; the spacer label keeps their
   baselines aligned without a wrapper element. */
#tab-settings .actions { align-items: center; }

.sec h4 { margin: 0 0 8px; font-size: 13px; color: var(--dim); font-weight: 600;
          text-transform: uppercase; letter-spacing: 1px; }
pre.log { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
          padding: 12px; overflow-x: auto; font-size: 11.5px; line-height: 1.5;
          color: var(--dim); max-height: 320px; white-space: pre-wrap; word-break: break-word; }
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
.iterate { display: grid; gap: 8px; }

.player { width: 100%; max-height: 62vh; border-radius: var(--r-sm);
          background: #000; display: block; }

/* ------------------------------------------------------------- post copy -- */
.copy-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
             margin-bottom: 10px; }
.copy-head .chips { flex: 1 1 auto; }
.copy-busy { margin: 0 0 10px; color: var(--gold); }

.post { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--panel);
        padding: 12px 13px; margin-bottom: 10px; }
.post-head { display: flex; align-items: baseline; gap: 6px; row-gap: 6px;
             flex-wrap: wrap; margin-bottom: 8px; }
.post-head b { font-size: 14px; }
.post-meta { font-size: 11px; margin-left: auto; }
/* Narrow: the platform and its Copy button hold the first line, and the counts
   take a line of their own rather than orphaning the button below them. */
@media (max-width: 720px) {
  .post-meta { order: 3; flex: 1 0 100%; margin-left: 0; }
  .copy-btn { margin-left: auto; }
}
.post-meta .bad { color: var(--danger); font-weight: 600; }
.copy-btn { padding: 4px 12px; font-size: 12px; min-height: 0; }

/* The caption, with the pre-fold window lit. Everything after the highlight is
   what a scroller never reads unless the first part earned the tap. */
.fold { font-size: 13.5px; line-height: 1.6; white-space: pre-wrap; color: var(--dim);
        overflow-wrap: anywhere; }
.fold span { color: var(--text); background: rgba(147,51,234,.14);
             box-shadow: inset 0 -1px 0 var(--accent); }
.tags { margin: 8px 0 0; font-size: 12.5px; color: var(--accent); overflow-wrap: anywhere; }
.post .muted { margin-top: 8px; }
.hooks-alt { margin: 4px 0 0; padding-left: 18px; color: var(--dim); font-size: 12px; }
.hooks-alt li { margin: 2px 0; }

/* ------------------------------------------------------------------- tabs -- */
.tabs { display: flex; gap: 6px; padding: 14px 26px 0; max-width: 1240px;
        margin: 0 auto; flex-wrap: wrap; }
.tabs button { background: transparent; color: var(--dim); border: 1px solid transparent;
               border-radius: 999px; padding: 8px 16px; font: inherit; font-size: 14px;
               cursor: pointer; }
.tabs button:hover { color: var(--text); }
.tabs button.on { background: var(--panel); border-color: var(--line); color: var(--text);
                  font-weight: 600; }

.wrap-1 { grid-template-columns: 1fr; }
.row3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.row4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
@media (max-width: 720px) { .row3, .row4 { grid-template-columns: 1fr 1fr; } }
.wrap-1 .panel { display: grid; gap: 14px; }
.wrap-1 .panel h2, .wrap-1 .panel h3 { margin: 0; font-size: 17px; letter-spacing: -0.2px; }
/* "Right now" already spaces itself with the head's own margin; the wrap-1 gap
   on top of that opens a hole between the heading and the first job row. */
.wrap-1 .panel.live { display: block; }

/* ------------------------------------------------------------------ ideas -- */
.ideas { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }
.idea { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md);
        padding: 16px; display: grid; gap: 10px; align-content: start; }
.idea.shortlisted { border-color: var(--accent); }
.idea h4 { margin: 0; font-size: 15px; line-height: 1.35; }
.idea .meta { display: flex; gap: 6px; flex-wrap: wrap; }
.hooks { display: grid; gap: 5px; font-size: 12.5px; }
.hooks div { display: grid; grid-template-columns: 62px 1fr; gap: 8px; }
.hooks span { color: var(--dim); font-size: 11px; text-transform: uppercase;
              letter-spacing: .6px; padding-top: 2px; }
.idea .why { font-size: 12px; color: var(--dim); border-top: 1px solid var(--line);
             padding-top: 9px; }
.idea .actions { border-top: 1px solid var(--line); padding-top: 10px; }
.idea .btn { padding: 6px 13px; font-size: 13px; }
.beats { font-size: 12px; color: var(--dim); display: grid; gap: 4px;
         border-top: 1px solid var(--line); padding-top: 9px; }
.beats b { color: var(--text); font-weight: 600; }

/* --------------------------------------------------------------- calendar -- */
.cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal .day { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-sm);
            padding: 8px; min-height: 84px; }
.cal .day.empty { background: transparent; border-style: dashed; }
.cal .dnum { font-size: 11px; color: var(--dim); margin-bottom: 5px; }
.cal .pill { display: block; font-size: 11px; background: var(--deep); color: var(--text);
             border-radius: 6px; padding: 3px 6px; margin-bottom: 3px; cursor: pointer;
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal .pill.ready { background: #1c4a30; }
.cal .pill.failed { background: #4a2030; }

/* ---------------------------------------------------------- perf/learnings -- */
table.data { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.data th { text-align: left; color: var(--dim); font-weight: 600; font-size: 11px;
                text-transform: uppercase; letter-spacing: .6px;
                border-bottom: 1px solid var(--line); padding: 6px 8px; }
table.data td { padding: 7px 8px; border-bottom: 1px solid var(--line); }
td.up { color: var(--ok); } td.down { color: var(--danger); }
.learn { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 12px;
         margin-bottom: 8px; background: var(--panel); }
.learn.weak { opacity: .6; }
.learn .s { font-size: 13.5px; }
.learn .m { font-size: 11.5px; color: var(--dim); margin-top: 5px;
            display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

/* ================================================================ mobile ==
   The panel is used on a phone to check on a build that is already running —
   which is why the live view, the cards and the drawer are what get the care
   here, and the wizard merely has to stay usable.

   Three rules run through all of it:
     · nothing may scroll the PAGE sideways. Where content is genuinely wide (a
       month grid, a metrics table) the ELEMENT scrolls instead.
     · every grid child that ellipsises needs `min-width: 0`, or it takes its
       content's full width and pushes the layout out regardless.
     · form controls go to 16px. Below that iOS Safari zooms the viewport on
       focus and never zooms back out, which feels like the page broke. */

/* Ellipsis inside a grid track only works if the item may shrink below its
   content — a grid/flex item's automatic minimum size is min-content, so one
   unbreakable line of log makes its whole ANCESTOR CHAIN that wide. It is not
   enough to set this on the line itself: every grid between it and the viewport
   has to be allowed to shrink too, which is what the second rule does.

   Symptom when this is missing: the drawer's stat tiles and event rows run off
   the right edge of a phone, because one 200-character Bash command sized the
   whole column. */
.card-now, .live-now, .ev span, .cal .pill { min-width: 0; }
.wrap > *, .panel > *, .drawer-body > *, .sec, .live, .live-row, .events, .ev,
.card-body { min-width: 0; }
/* The wizard's own chain. `#video-only` appears only for a video, which is why
   the overflow it caused looked like "the fields go oversize when I pick Video"
   rather than a layout that was always one long option away from breaking. */
.modal-body > *, #video-only, #video-only > *, .row > *, .lbl, .chips, .seg { min-width: 0; }

/* Long slugs, URLs and agent sentences have no spaces to break at. */
.card-title, .card-sub, .idea h4, .learn .s,
.drawer-head h3, .modal-head h3 { overflow-wrap: anywhere; }

/* Genuinely wide children scroll themselves rather than the page. */
#calendar-grid, .tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tablewrap table.data { min-width: 520px; }

@media (max-width: 980px) {
  .wrap { padding: 18px 16px; gap: 18px; }
  .tabs { padding: 12px 16px 0; }
  .topbar { padding: 12px 16px; }
}

@media (max-width: 720px) {
  /* Header: the brand on its own line, the numbers under it. They are readouts,
     not controls, so they may shrink; the sign-out link may not. */
  .topbar { flex-wrap: wrap; gap: 8px 14px; }
  .brand { font-size: 15px; }
  .readouts { gap: 12px; font-size: 12px; width: 100%; flex-wrap: wrap; }
  /* The only control in the header, and as plain text it was a 19px target. */
  .readout.link { display: inline-flex; align-items: center; min-height: 34px;
                  margin-left: auto; }

  /* Tabs become one swipeable strip. Wrapping them cost two lines of height at
     the top of every screen, permanently. */
  .tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
          -webkit-overflow-scrolling: touch; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs button { flex: 0 0 auto; }

  .row, .row3 { grid-template-columns: 1fr; }
  .row4 { grid-template-columns: 1fr 1fr; }

  /* The role select is the widest thing in the reference block, and squeezed
     beside the thumbnail its label truncates — which loses the half of the
     choice that explains what the choice is. Give it the whole width. */
  .ref { flex-wrap: wrap; }
  .ref-body { flex: 1 1 100%; }

  /* Two cards across at 360px, which is what makes the library scannable on a
     phone rather than a column of postcards. */
  .grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 150px), 1fr)); gap: 12px; }
  .ideas { grid-template-columns: 1fr; }

  .panel { padding: 16px; border-radius: var(--r-md); }
  /* Stacked, and the model picker takes the width rather than collapsing to the
     few pixels left over beside its own label. */
  .maker-foot { flex-direction: column; align-items: stretch; gap: 10px; }
  .maker-foot .btn { width: 100%; }
  .maker-foot .lbl.inline { width: 100%; padding-bottom: 0; }
  .maker-foot .lbl.inline select { flex: 1 1 auto; min-width: 0; }

  /* A month grid does not compress — seven columns is what makes it a month.
     So it keeps its width and scrolls inside its own box. */
  .cal { min-width: 620px; }

  /* Touch targets. 14px pills are a mouse size. */
  .btn, .seg button, .filters button, .tabs button { min-height: 40px; }
  .chips button { min-height: 34px; }

  /* 16px stops iOS from zooming the viewport when a field takes focus. */
  input[type=text], input[type=password], input[type=number], input[type=date],
  select, textarea { font-size: 16px; }

  /* Full-screen sheet. 100dvh follows the browser chrome as it hides on scroll;
     100vh does not, and the bottom of the drawer ends up under it. */
  .drawer { width: 100%; height: 100dvh; border-left: 0; }
  .drawer-head { padding: 14px 16px; }
  .drawer-body { padding: 16px 16px calc(32px + env(safe-area-inset-bottom));
                 gap: 16px; -webkit-overflow-scrolling: touch; }

  /* The wizard is a screen and a half of form, so on a phone it is the screen
     rather than a card floating on one. */
  .modal { left: 0; top: 0; transform: none; width: 100%; height: 100dvh;
           max-height: 100dvh; border: 0; border-radius: 0; }
  .modal-head { padding: 14px 16px; }
  .modal-body { padding: 16px; gap: 12px; -webkit-overflow-scrolling: touch; }
  .modal-foot { padding: 14px 16px calc(14px + env(safe-area-inset-bottom)); }
  .actions .btn { flex: 1 1 auto; }

  /* The live view is the reason to open this on a phone at all, so it keeps its
     full height budget while the finished-job logs give theirs up. */
  .events { max-height: 260px; }
  pre.log { max-height: 200px; font-size: 11px; }
  .facts { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
}

@media (max-width: 430px) {
  .gate { padding: 16px; }
  .gate-card { padding: 26px 20px; }
  .wrap { padding: 14px 12px; }
  .topbar { padding: 10px 12px; }
  .tabs { padding: 10px 12px 0; }
  .row4 { grid-template-columns: 1fr; }
  .shots { grid-template-columns: 1fr 1fr; }
  .hooks div { grid-template-columns: 1fr; gap: 2px; }
  .live-row-head { font-size: 13px; }
  .live-when { margin-left: 0; width: 100%; }
  .refadd .ref-actions .muted { flex-basis: 100%; }
}

/* The format-reference block.
   Boxed rather than inlined because it is the one field in this wizard that
   reaches outside the panel, and a URL input that looks like every other input
   is one people paste into without reading the line underneath it. */
.refadd {
  margin-top: .5rem;
  padding: .7rem .8rem;
  border: 1px solid var(--line);
  border-radius: 10px;
}

/* How the notes field will be read. Two states that have to be told apart at a
   glance and without relying on colour alone — each carries its own glyph — and
   a left border rather than a fill, so it reads as a note about the box above
   it rather than as another control. */
.notes-mode {
  margin: .45rem 0 0;
  padding: .5rem .7rem;
  border-left: 3px solid var(--line);
  border-radius: 0 8px 8px 0;
  font-size: 13px;
  line-height: 1.45;
  opacity: .92;
}
.notes-mode.script    { border-left-color: #7c5cff; }
.notes-mode.direction { border-left-color: #4a9d7f; }

/* The estimate beside Build. Tabular figures so it does not jitter as the
   numbers change under the cursor. */
.estimate { font-variant-numeric: tabular-nums; }
.refadd input[type="url"] { width: 100%; }
.refadd .check { margin: .55rem 0 .1rem; }
.refadd .ref-actions {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  margin-top: .55rem;
}
.refadd .ref-actions .muted { flex: 1 1 16rem; line-height: 1.35; }

/* The rating row. Four named verdicts rather than a slider — a scale people
   cannot use reliably produces noise shaped like data. The selected one is
   filled rather than merely outlined, because at a glance "which did I pick"
   has to survive being read quickly. */
.rate-row { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .5rem; }
.rate-row .btn.rate.on { background: var(--accent, #7c5cff); border-color: transparent; color: #fff; }
.rate-note { width: 100%; resize: vertical; }
