/* SendTroy AI
 *
 * One stream, threaded on a spine. Your words, Troy's answers and the team's
 * work share a single timeline, because in an agent platform the work is the
 * event - putting it in a side panel makes it something you must remember to
 * look at.
 *
 * The layout is fluid rather than breakpointed: the spine narrows, the crew
 * strip scrolls, the composer docks. Nothing is removed on a small screen.
 */

:root {
  --bg: #06060b;
  --ink: #f1f5f9;
  --dim: #8b97ab;
  --faint: #5a6577;
  --line: rgba(255, 255, 255, 0.07);
  --panel: #0c0c14;
  --brand: #6366f1;
  --brand-2: #8b5cf6;
  --brand-soft: #a5b4fc;
  --live: #34d399;
  --warn: #fbbf24;
  --bad: #f87171;
  --radius: 14px;
  --speed: 0.22s cubic-bezier(0.32, 0.72, 0, 1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0; height: 100%;
  background: var(--bg); color: var(--ink);
  font-family: 'Inter', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}

button, input, textarea { font: inherit; color: inherit; }
button { background: none; border: none; cursor: pointer; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em;
       background: rgba(255,255,255,0.06); padding: 1px 5px; border-radius: 5px; }

.icon-btn {
  width: 34px; height: 34px; border-radius: 10px; color: var(--faint);
  display: grid; place-items: center; transition: var(--speed);
}
.icon-btn:hover { color: var(--ink); background: rgba(255,255,255,0.06); }

/* ── Sign in ─────────────────────────────────────────────────────────────
   Deliberately spare. There is one way in and nothing else to look at. */
.gate {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center; padding: 6vmin;
  background:
    radial-gradient(60vmin 60vmin at 20% 10%, rgba(99,102,241,0.16), transparent 70%),
    radial-gradient(50vmin 50vmin at 85% 90%, rgba(16,185,129,0.10), transparent 70%),
    var(--bg);
}
.gate[hidden] { display: none; }

.gate-card {
  width: min(400px, 100%);
  background: rgba(12,12,20,0.86);
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: 30px 28px;
  display: flex; flex-direction: column; gap: 16px;
  box-shadow: 0 30px 80px rgba(0,0,0,0.6);
}

.gate-brand { display: flex; align-items: center; gap: 13px; margin-bottom: 6px; }
.gate-mark, .crew-mark, .opening-mark, .composer-mark {
  display: grid; place-items: center;
  background: linear-gradient(140deg, var(--brand), var(--brand-2));
  color: #fff; border-radius: 12px;
}
.gate-mark { width: 40px; height: 40px; font-size: 15px; }
.gate-name { font-family: 'Outfit'; font-weight: 900; font-size: 20px; letter-spacing: -0.4px; }
.gate-name span, .crew-name span { color: var(--brand-soft); }
.gate-sub { font-size: 11px; color: var(--faint); }

.field { display: flex; flex-direction: column; gap: 6px; }
.field span { font-size: 11px; font-weight: 600; color: var(--dim); letter-spacing: 0.3px; }
.field input {
  background: rgba(255,255,255,0.04); border: 1px solid var(--line);
  border-radius: 11px; padding: 11px 13px; outline: none; transition: var(--speed);
}
.field input:focus { border-color: var(--brand); background: rgba(99,102,241,0.07); }

.gate-btn {
  margin-top: 4px; padding: 12px; border-radius: 11px; font-weight: 700; font-size: 14px;
  color: #fff; background: linear-gradient(120deg, var(--brand), var(--brand-2));
  display: flex; align-items: center; justify-content: center; gap: 9px;
  transition: var(--speed);
}
.gate-btn:hover { filter: brightness(1.12); }
.gate-btn:disabled { opacity: 0.55; }

.gate-error { color: var(--bad); font-size: 12px; min-height: 16px; }
.gate-note { margin: 0; font-size: 11px; color: var(--faint); text-align: center; }

/* ── Shell ───────────────────────────────────────────────────────────── */
.app { height: 100%; display: flex; flex-direction: column; }
.app[hidden] { display: none; }

/* ── The crew strip: the team, always in view, never a menu ──────────── */
.crew {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  background: rgba(6,6,11,0.82);
  backdrop-filter: blur(12px);
  position: sticky; top: 0; z-index: 20;
}

.crew-brand { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }
.crew-mark { width: 30px; height: 30px; font-size: 12px; }
.crew-name { font-family: 'Outfit'; font-weight: 900; font-size: 14px; letter-spacing: -0.3px; }

.crew-strip {
  flex: 1 1 auto; min-width: 0;
  display: flex; gap: 7px; overflow-x: auto;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  mask-image: linear-gradient(90deg, transparent, #000 12px, #000 calc(100% - 12px), transparent);
}
.crew-strip::-webkit-scrollbar { display: none; }

.crew-agent {
  flex: 0 0 auto; position: relative;
  display: flex; align-items: center; gap: 7px;
  padding: 7px 11px 7px 10px; border-radius: 11px;
  border: 1px solid var(--line); background: rgba(255,255,255,0.03);
  font-size: 12px; font-weight: 600; color: var(--dim);
  transition: var(--speed);
}
.crew-agent:hover { color: var(--ink); border-color: rgba(99,102,241,0.4); }
.crew-agent i { font-size: 11px; }

/* Health is a dot, not a word - the strip must stay scannable */
.crew-health { width: 6px; height: 6px; border-radius: 50%; background: var(--faint); }
.crew-agent[data-health="ready"]   .crew-health { background: var(--live); }
.crew-agent[data-health="working"] .crew-health { background: var(--live); animation: pulse 1.4s infinite; }
.crew-agent[data-health="down"]    .crew-health { background: var(--bad); }
/* Running, but not able to do its whole job - a Reviewer with no vision model
   is not "ready" and is not "down" either, and reporting it as ready is how you
   find out at the point it silently reviews nothing. */
.crew-agent[data-health="degraded"] .crew-health { background: var(--warn, #f59e0b); }
.crew-agent[data-health="planned"] { opacity: 0.5; }
.crew-agent[data-health="planned"] .crew-health { background: transparent; border: 1px dashed var(--faint); }

.crew-badge {
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--brand); color: #fff; font-size: 10px; font-weight: 800;
  display: grid; place-items: center;
}

@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ── Auto mode ───────────────────────────────────────────────────────────
   A switch that can start a render on its own is never a plain icon: off it
   is quiet, on it is lit and pulsing, because "is this thing armed" must be
   answerable from across the room. */
.auto-toggle {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 7px;
  padding: 7px 12px; border-radius: 99px;
  border: 1px solid var(--line); background: rgba(255,255,255,0.03);
  font-size: 11px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase;
  color: var(--faint); transition: var(--speed);
}
.auto-toggle:hover { color: var(--ink); border-color: rgba(99,102,241,0.45); }
.auto-toggle:disabled { opacity: 0.5; }

.auto-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: transparent; border: 1px solid var(--faint);
}
.auto-toggle[data-on="true"] {
  color: var(--live); border-color: rgba(52,211,153,0.45); background: rgba(52,211,153,0.09);
}
.auto-toggle[data-on="true"] .auto-dot {
  background: var(--live); border-color: var(--live);
  box-shadow: 0 0 8px rgba(52,211,153,0.75);
  animation: pulse 2s infinite;
}
@media (max-width: 620px) { .auto-label { display: none; } .auto-toggle { padding: 7px 9px; } }

/* ── The stream ──────────────────────────────────────────────────────── */
.stream {
  flex: 1 1 auto; min-height: 0; position: relative;
  overflow-y: auto; overflow-x: hidden;
  padding: 20px 14px 8px;
  scroll-behavior: smooth;
}

/* The spine: the pipeline, standing beside the whole conversation */
.spine {
  position: absolute; left: 22px; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, transparent, var(--line) 8%, var(--line) 92%, transparent);
  pointer-events: none;
}
.spine-nodes {
  position: sticky; top: 24px;
  display: flex; flex-direction: column; gap: 11px; align-items: flex-start;
  transform: translateX(-4px);
}
/* Six unlabelled dots are a puzzle. The stage names make the spine read as
   the pipeline it is - shown wherever there is room, dots alone when there
   is not. */
.spine-stage { display: flex; align-items: center; gap: 8px; }

.spine-node {
  flex: 0 0 auto;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--panel); border: 1.5px solid var(--line);
  transition: var(--speed);
}
.spine-stage[data-built="true"] .spine-node { border-color: rgba(165,180,252,0.45); }
.spine-stage[data-active="true"] .spine-node {
  background: var(--live); border-color: var(--live);
  box-shadow: 0 0 10px rgba(52,211,153,0.7);
}

.spine-label {
  font-size: 9px; font-weight: 800; letter-spacing: 0.7px; text-transform: uppercase;
  color: var(--faint); white-space: nowrap; transition: var(--speed);
}
.spine-stage[data-built="false"] .spine-label { opacity: 0.45; }
.spine-stage[data-active="true"] .spine-label { color: var(--live); }
@media (max-width: 1180px) { .spine-label { display: none; } }

.flow {
  max-width: 780px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 14px;
  padding-left: 26px;
}

/* Opening state - the composer is centred until the stream has something */
.opening { text-align: center; padding: 12vmin 4vmin 4vmin; }
.opening-mark { width: 52px; height: 52px; font-size: 20px; margin: 0 auto 16px; }
.opening h1 { font-family: 'Outfit'; font-size: 34px; font-weight: 900; margin: 0 0 6px; letter-spacing: -1px; }
.opening p { color: var(--dim); font-size: 14px; margin: 0; }

/* ── Entries ─────────────────────────────────────────────────────────── */
.entry { opacity: 0; transform: translateY(8px); transition: opacity 0.3s ease, transform 0.3s ease; }
.entry.in { opacity: 1; transform: none; }

/* Troy speaks as prose, not in a bubble - a chief of staff writes you a note */
.said.troy .entry-body { font-size: 14.5px; line-height: 1.62; color: var(--ink); }
.said.troy .entry-body p { margin: 0 0 10px; }
.said.troy .entry-body p:last-child { margin: 0; }
.said.troy .entry-body ul { margin: 0 0 10px; padding-left: 18px; }
.said.troy .entry-body li { margin: 3px 0; }
.said.troy .entry-meta {
  margin-top: 7px; font-size: 10px; color: var(--faint);
  text-transform: uppercase; letter-spacing: 0.6px; font-weight: 700;
}

/* You are quoted, tight and right - visually subordinate to the answer */
.said.me { align-self: flex-end; max-width: min(85%, 560px); }
.said.me .entry-body {
  background: rgba(99,102,241,0.14); border: 1px solid rgba(99,102,241,0.26);
  border-radius: 16px 16px 4px 16px; padding: 9px 13px;
  font-size: 13.5px; line-height: 1.5;
}

.failed { color: var(--bad); }

.typing { display: inline-flex; gap: 4px; padding: 4px 0; }
.typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--brand-soft);
            animation: bounce 1.1s infinite; }
.typing i:nth-child(2) { animation-delay: 0.15s; }
.typing i:nth-child(3) { animation-delay: 0.3s; }
@keyframes bounce { 0%,60%,100% { opacity: 0.3; transform: translateY(0); }
                    30% { opacity: 1; transform: translateY(-4px); } }

/* ── Notices: something happened, and neither of us said it ──────────────
   Deliberately lighter than a work card and quieter than Troy's prose. It is
   punctuation in the timeline, not another voice competing with him. */
.entry.notice {
  display: flex; gap: 10px; align-items: flex-start; margin-left: -26px;
  font-size: 12.5px; line-height: 1.5; color: var(--dim);
}
.notice-mark {
  flex: 0 0 26px; position: relative; height: 18px;
}
.notice-mark::before {
  content: ''; position: absolute; left: 50%; top: 6px;
  width: 6px; height: 6px; margin-left: -3px; border-radius: 50%;
  background: var(--brand-soft); box-shadow: 0 0 0 3px var(--bg);
}
.notice-body { flex: 1 1 auto; min-width: 0; padding-top: 1px; }
.notice-body strong { color: var(--ink); font-weight: 700; }
.notice-body code {
  font-family: ui-monospace, Menlo, monospace; font-size: 11px;
  color: var(--brand-soft); background: rgba(99,102,241,0.12);
  padding: 1px 5px; border-radius: 5px;
}

.entry.notice[data-tone="auto"] .notice-mark::before { background: var(--live); }
.entry.notice[data-tone="auto"] .notice-body { color: var(--dim); }
.entry.notice[data-tone="bad"] .notice-mark::before { background: var(--bad); }
.entry.notice[data-tone="bad"] .notice-body { color: var(--bad); }

/* ── Work, living in the stream ──────────────────────────────────────── */
.entry.work { display: flex; gap: 10px; align-items: flex-start; margin-left: -26px; }

.work-rail { flex: 0 0 26px; display: grid; place-items: center; padding-top: 15px; }
.work-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--faint); box-shadow: 0 0 0 3px var(--bg);
}
.entry.work[data-state="running"] .work-dot { background: var(--live); animation: pulse 1.4s infinite; }
.entry.work[data-state="done"]    .work-dot { background: var(--brand-soft); }
.entry.work[data-state="failed"]  .work-dot { background: var(--bad); }

.work-card {
  flex: 1 1 auto; min-width: 0;
  background: rgba(255,255,255,0.028);
  border: 1px solid var(--line);
  border-left: 2px solid var(--faint);
  border-radius: 12px; padding: 11px 13px;
}
.entry.work[data-state="running"] .work-card { border-left-color: var(--live); background: rgba(52,211,153,0.05); }
.entry.work[data-state="failed"]  .work-card { border-left-color: var(--bad); }

.work-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; }
.work-head i { color: var(--brand-soft); font-size: 11px; }
.work-agent { font-weight: 700; }
.work-kind { color: var(--faint); text-transform: uppercase; font-size: 9.5px;
             letter-spacing: 0.6px; font-weight: 800; }
.work-title { color: var(--dim); text-transform: capitalize; }
.work-state { margin-left: auto; font-family: ui-monospace, Menlo, monospace;
              font-size: 11px; font-weight: 700; color: var(--live); }
.entry.work[data-state="done"]   .work-state { color: var(--brand-soft); }
.entry.work[data-state="failed"] .work-state { color: var(--bad); }

.work-bar { height: 3px; border-radius: 99px; background: rgba(255,255,255,0.07); margin: 9px 0 7px; overflow: hidden; }
.work-bar span { display: block; height: 100%; background: var(--live); border-radius: 99px;
                 transition: width 0.6s cubic-bezier(0.32,0.72,0,1); }

.work-note { font-size: 11px; color: var(--faint); margin-top: 5px; }
.work-model { font-family: ui-monospace, Menlo, monospace; color: var(--brand-soft); }

.work-open {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 9px;
  font-size: 11px; font-weight: 700; color: var(--brand-soft); text-decoration: none;
}
.work-open:hover { color: #fff; }

/* Try again, on a card that failed. Present only where it can actually do
   something, which is why it is drawn from the task rather than always there. */
.work-retry {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 9px;
  padding: 5px 11px; border-radius: 99px;
  border: 1px solid rgba(248,113,113,0.4); background: rgba(248,113,113,0.1);
  font-size: 11px; font-weight: 700; color: var(--bad); transition: var(--speed);
}
.work-retry:hover:not(:disabled) { color: #fff; background: rgba(248,113,113,0.25); }
.work-retry:disabled { opacity: 0.6; }

/* ── Composer ────────────────────────────────────────────────────────────
   Centred while the stream is empty, docked once it is not. The same element
   moves rather than being replaced, so focus survives the transition. */
.composer {
  flex: 0 0 auto;
  padding: 10px 14px calc(12px + env(safe-area-inset-bottom));
  transition: var(--speed);
}
body.started .composer { border-top: 1px solid var(--line); background: rgba(6,6,11,0.9); }
body:not(.started) .composer { margin-bottom: 12vh; }

.composer-shell {
  max-width: 780px; margin: 0 auto;
  display: flex; align-items: flex-end; gap: 9px;
  padding: 8px 8px 8px 12px;
  background: rgba(255,255,255,0.045);
  border: 1px solid var(--line); border-radius: 18px;
  transition: var(--speed);
}
.composer-shell:focus-within { border-color: rgba(99,102,241,0.55); background: rgba(99,102,241,0.07); }
.composer-mark { width: 24px; height: 24px; font-size: 10px; flex: 0 0 auto; margin-bottom: 5px; }

.composer textarea {
  flex: 1 1 auto; min-width: 0; resize: none; border: none; background: none; outline: none;
  font-size: 14px; line-height: 1.5; padding: 6px 0; max-height: 150px;
}
.composer textarea::placeholder { color: var(--faint); }

.send-btn {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 12px;
  background: linear-gradient(120deg, var(--brand), var(--brand-2)); color: #fff;
  display: grid; place-items: center; transition: var(--speed);
}
.send-btn:hover { filter: brightness(1.15); }

.suggestions {
  max-width: 780px; margin: 10px auto 0;
  display: flex; gap: 7px; flex-wrap: wrap; justify-content: center;
}
body.started .suggestions { display: none; }

/* ── What the request is about ───────────────────────────────────────────
   Above the composer, not in a sidebar: it is part of writing the message,
   and a subject you have to go and look for is one you forget to set. */
.pick-btn {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: 9px;
  display: grid; place-items: center; margin-bottom: 3px;
  color: var(--faint); font-size: 12px; transition: var(--speed);
}
.pick-btn:hover { color: var(--brand-soft); background: rgba(99,102,241,0.12); }
body.has-context .pick-btn { color: var(--brand-soft); }

.context-bar {
  max-width: 780px; margin: 0 auto 8px;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; border-radius: 10px;
  background: rgba(99,102,241,0.1); border: 1px solid rgba(99,102,241,0.28);
  font-size: 12px; color: var(--dim);
}
.context-bar[hidden] { display: none; }
.context-bar i { color: var(--brand-soft); font-size: 11px; }
.context-bar strong { color: var(--ink); font-weight: 700; }
.context-clear {
  margin-left: auto; color: var(--faint); font-size: 11px; padding: 2px 4px;
}
.context-clear:hover { color: var(--bad); }

.picker {
  position: fixed; z-index: 30; bottom: 88px; left: 50%; transform: translateX(-50%);
  width: min(560px, calc(100vw - 28px)); max-height: min(60vh, 480px);
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.55);
}
.picker[hidden] { display: none; }
.picker-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px; border-bottom: 1px solid var(--line);
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.7px; color: var(--faint);
}
.picker-list { overflow-y: auto; padding: 6px; }

.picker-project { border-radius: 10px; }
.picker-project[data-on="true"] { background: rgba(99,102,241,0.08); }

.picker-pick {
  width: 100%; display: flex; align-items: center; gap: 9px;
  padding: 9px 10px; border-radius: 10px; text-align: left;
  font-size: 13px; color: var(--dim); transition: var(--speed);
}
.picker-pick:hover { color: var(--ink); background: rgba(255,255,255,0.04); }
.picker-pick i { color: var(--brand-soft); font-size: 12px; flex: 0 0 auto; }
.picker-name { font-weight: 600; text-transform: capitalize; }
.picker-meta { margin-left: auto; font-size: 10.5px; color: var(--faint); }
.picker-project[data-on="true"] .picker-pick { color: var(--ink); }

/* Units of a campaign, only once the campaign is the one you picked */
.picker-units { padding: 0 10px 10px 30px; display: flex; flex-direction: column; gap: 2px; }
.picker-unit {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 8px; font-size: 12.5px; color: var(--dim);
  cursor: pointer; transition: var(--speed);
}
.picker-unit:hover { background: rgba(255,255,255,0.04); color: var(--ink); }
.picker-unit input { accent-color: var(--brand); }
.picker-unit-name { text-transform: capitalize; }
.picker-unit-meta { margin-left: auto; font-size: 10.5px; color: var(--faint); }
.picker-hint { padding: 6px 8px 0; font-size: 10.5px; color: var(--faint); }

.chip {
  padding: 7px 13px; border-radius: 99px; font-size: 12px; color: var(--dim);
  border: 1px solid var(--line); background: rgba(255,255,255,0.03); transition: var(--speed);
}
.chip:hover { color: var(--ink); border-color: rgba(99,102,241,0.45); background: rgba(99,102,241,0.08); }

/* ── An agent's work, over the stream ────────────────────────────────── */
.agent-panel {
  position: fixed; z-index: 30;
  right: 14px; left: auto; top: 64px; width: min(430px, calc(100vw - 28px));
  max-height: min(70vh, 620px);
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: 18px;
  box-shadow: 0 30px 70px rgba(0,0,0,0.6);
  animation: rise var(--speed);
}
.agent-panel[hidden] { display: none; }
@keyframes rise { from { opacity: 0; transform: translateY(-8px); } }

.agent-panel-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 14px 14px 12px; border-bottom: 1px solid var(--line);
}
.agent-panel-name { font-family: 'Outfit'; font-weight: 800; font-size: 15px; }
.agent-panel-role { font-size: 11px; color: var(--faint); margin-top: 2px; }
.agent-panel-actions { display: flex; align-items: center; gap: 6px; }

/* Any rule that sets `display` outranks the browser's own
   `[hidden] { display: none }`, so `el.hidden = true` silently does nothing on
   a styled element. That is how the workbench button stayed on screen for
   agents that have no workbench - and, being a link with a stale href, sent
   people to the previous agent's view.

   One global rule instead of remembering it per component. `!important`
   because the whole point is to beat whatever a component declares. */
[hidden] { display: none !important; }

.ghost-btn {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 6px 10px; border-radius: 9px; font-size: 11px; font-weight: 700;
  color: var(--brand-soft); border: 1px solid rgba(99,102,241,0.3); text-decoration: none;
}
.ghost-btn:hover { background: rgba(99,102,241,0.12); color: #fff; }

.agent-panel-body { overflow-y: auto; padding: 10px 12px 14px; }

/* What this agent's view is for, above its work.
 *
 * The panel used to be a job list and nothing else, which read as broken on any
 * agent that had done nothing today. Every agent now has a screen, and the
 * argument for that screen's shape is the useful thing to say next to it - the
 * shape IS the argument in all six cases. */
.panel-view {
  display: grid; gap: 3px; margin-bottom: 12px;
  padding: 11px 12px; border-radius: 12px;
  border: 1px solid rgba(99,102,241,0.3); background: rgba(99,102,241,0.07);
  text-decoration: none; color: inherit; transition: var(--speed);
}
.panel-view:hover { border-color: var(--brand); background: rgba(99,102,241,0.13); }
.panel-view-name { font-size: 12.5px; font-weight: 700; }
.panel-view-name i { color: var(--brand-soft); margin-right: 7px; }
.panel-view-name em { color: var(--warn); font-style: normal; font-weight: 500; font-size: 11px; }
.panel-view-why { font-size: 11.5px; color: var(--dim); line-height: 1.5; }
.panel-view-spec { font-size: 10px; color: var(--faint);
                   font-family: ui-monospace, Menlo, monospace; }

.history { display: flex; flex-direction: column; gap: 6px; }
.history-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: 8px; align-items: baseline;
  padding: 9px 10px; border-radius: 10px; font-size: 12px;
  background: rgba(255,255,255,0.03); border-left: 2px solid var(--faint);
}
.history-row[data-state="running"] { border-left-color: var(--live); }
.history-row[data-state="done"]    { border-left-color: var(--brand-soft); }
.history-row[data-state="failed"]  { border-left-color: var(--bad); }
.history-kind { font-size: 9.5px; font-weight: 800; letter-spacing: 0.5px;
                text-transform: uppercase; color: var(--faint); }
.history-title { font-weight: 600; text-transform: capitalize; }
.history-state { font-family: ui-monospace, Menlo, monospace; font-size: 11px; color: var(--dim); }
.history-note { grid-column: 1 / -1; font-size: 10.5px; color: var(--faint); }

.empty {
  display: flex; flex-direction: column; gap: 5px;
  padding: 22px 14px; text-align: center; font-size: 12px; color: var(--faint);
}
.empty strong { color: var(--dim); font-size: 13px; }

/* ── Small screens ────────────────────────────────────────────────────────
   Nothing is removed - the spine narrows, the panel becomes a sheet. */
@media (max-width: 720px) {
  .stream { padding: 14px 10px 6px; }
  .spine { left: 15px; }
  .flow { padding-left: 20px; }
  .entry.work,
  .entry.notice { margin-left: -20px; }
  .work-rail,
  .notice-mark { flex-basis: 20px; }
  .crew-name { display: none; }
  .opening { padding-top: 8vmin; }
  .opening h1 { font-size: 27px; }

  .agent-panel {
    top: auto; bottom: 0; left: 0; right: 0; width: 100%;
    max-height: 76vh; border-radius: 20px 20px 0 0;
    animation: sheet var(--speed);
  }
  @keyframes sheet { from { transform: translateY(100%); } }
}

@media (max-width: 420px) {
  .crew-agent-name { display: none; }
  .crew-agent { padding: 7px 9px; }
}

/* A tool, not an agent: it is somewhere you go, not something that works for you */
.crew-tool { text-decoration: none; border-style: dashed; }
.crew-tool:hover { border-style: solid; }
.crew-out { font-size: 8px; opacity: 0.6; }

/* The password field, with a way to see what is actually in it.
   This origin also serves Postiz, so a password manager will offer the wrong
   saved credential here - being able to look is the difference between fixing
   it in a second and typing the right password four times. */
.field-input { position: relative; display: block; }
.field-input input { width: 100%; padding-right: 40px; }

.reveal {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; border-radius: 8px;
  color: var(--faint); display: grid; place-items: center;
  transition: var(--speed);
}
.reveal:hover { color: var(--ink); background: rgba(255,255,255,0.06); }

.gate-error .hint { color: var(--faint); font-size: 11px; line-height: 1.45; display: block; margin-top: 4px; }
.gate-error { min-height: 16px; line-height: 1.4; }

/* ── The library ──────────────────────────────────────────────────────────
   A rail on the right edge, not a page and not a modal. It is consulted while
   you are mid-sentence to Troy - "have I picked any music for this?" - so
   opening it must not take the conversation off screen.

   The circle under each icon fills when that kind has favourites, which makes
   the whole question answerable from the edge of the screen without opening
   anything. That is the only state the rail carries, and it is the state the
   build actually acts on. */
.library-rail {
  position: fixed; z-index: 29; right: 0; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 4px; padding: 6px 5px;
  background: var(--panel); border: 1px solid var(--line); border-right: none;
  border-radius: 14px 0 0 14px; box-shadow: -8px 0 30px rgba(0,0,0,0.4);
}

.rail-btn {
  position: relative; width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center; color: var(--faint);
  font-size: 13px; transition: var(--speed);
}
.rail-btn:hover { color: var(--ink); background: rgba(255,255,255,0.06); }
.rail-btn[data-open="true"] { color: #fff; background: rgba(99,102,241,0.18); }

.rail-dot {
  position: absolute; bottom: 4px; right: 4px;
  width: 6px; height: 6px; border-radius: 50%;
  border: 1px solid var(--faint); background: transparent;
}
.rail-btn[data-picked="true"] .rail-dot { background: var(--live); border-color: var(--live); }
.rail-btn[data-picked="true"] { color: var(--brand-soft); }

.library {
  position: fixed; z-index: 30; right: 52px; top: 64px;
  width: min(420px, calc(100vw - 70px)); max-height: min(76vh, 700px);
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: 18px;
  box-shadow: 0 30px 70px rgba(0,0,0,0.6);
  animation: rise var(--speed);
}
.library-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 14px 14px 12px; border-bottom: 1px solid var(--line);
}
.library-title { font-family: 'Outfit'; font-weight: 800; font-size: 15px; }
.library-sub { font-size: 10.5px; color: var(--faint); margin-top: 2px; line-height: 1.4; }

.library-search {
  display: flex; align-items: center; gap: 6px;
  padding: 10px 12px; border-bottom: 1px solid var(--line);
}
.library-search input[type="text"] {
  flex: 1; min-width: 0; padding: 8px 10px; border-radius: 9px;
  border: 1px solid var(--line); background: rgba(255,255,255,0.03);
  font-size: 12.5px; outline: none;
}
.library-search input[type="text"]:focus { border-color: var(--brand); }
.library-search .ghost-btn { cursor: pointer; padding: 7px 9px; }

.library-body { overflow-y: auto; padding: 8px 10px 14px; }

/* What a build will actually do with what is in here, said where the choice is
   made. A panel of files that does not say what happens if you leave it empty
   is a panel you have to remember the rules for. */
.library-rule {
  padding: 8px 10px; margin-bottom: 8px; border-radius: 9px;
  font-size: 11px; line-height: 1.5; color: var(--dim);
  background: rgba(99,102,241,0.07); border-left: 2px solid var(--brand);
}

.library-section {
  padding: 10px 2px 6px; font-size: 9.5px; font-weight: 800;
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--faint);
}

.media-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: 9px;
  padding: 9px 10px; margin-bottom: 6px; border-radius: 11px;
  background: rgba(255,255,255,0.03); border: 1px solid transparent;
}
.media-row[data-picked="true"] {
  background: rgba(52,211,153,0.07); border-color: rgba(52,211,153,0.25);
}
.media-row.found { border-style: dashed; border-color: var(--line); }

.media-pick {
  width: 30px; height: 30px; border-radius: 9px; color: var(--faint);
  display: grid; place-items: center; font-size: 12px; transition: var(--speed);
}
.media-pick:hover { color: var(--ink); background: rgba(255,255,255,0.06); }
.media-pick[data-on="true"] { color: var(--live); }
.media-pick:disabled { opacity: 0.5; }

.media-main { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.media-name {
  font-size: 12.5px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.media-meta { font-size: 10.5px; color: var(--faint); }
/* The licence is on the row, not behind a tooltip: "may we use this in a paid
   advert" is asked long after the download, and it has to be visible at the
   moment of choosing. */
.media-licence {
  font-size: 10px; color: var(--dim); line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.media-main audio { width: 100%; height: 30px; margin-top: 4px; }
.media-thumb {
  width: 100%; max-height: 130px; object-fit: cover;
  border-radius: 8px; margin-top: 4px; background: rgba(255,255,255,0.04);
}
.media-drop { color: var(--faint); font-size: 11px; align-self: start; padding: 4px; }
.media-drop:hover { color: var(--bad); }

@media (max-width: 720px) {
  .library-rail { top: auto; bottom: 96px; transform: none; flex-direction: row;
                  right: 10px; border-radius: 14px; border-right: 1px solid var(--line); }
  .library {
    top: auto; bottom: 0; left: 0; right: 0; width: 100%;
    max-height: 78vh; border-radius: 20px 20px 0 0;
    animation: sheet var(--speed);
  }
}
