/* ---------------------------------------------------------------------------
   demo.css: the guided demo narration panel.
   ---------------------------------------------------------------------------
   The panel sits between the stage rail and the workspace on the run screen and
   is the one element on that screen written for somebody who has never seen the
   pipeline before. Everything else is an operations console; this is a
   commentary track laid over it.

   Two things it must never do, both of which drove the rules below.

   1. Never take the screen off the operator. The run screen is a fixed height
      console on desktop and its panes own their own scrollbars. So this panel
      is capped near 320px and the step rail scrolls INSIDE itself. A panel that
      grew with the step count would push the workspace off the bottom of the
      viewport halfway through the demo.

   2. Never imply a hang. The live indicator is a slow pulse on a dot, not a
      spinner. A spinner on a step that legitimately takes forty seconds reads
      as "this is stuck", which is the opposite of what a demo is for.

   Colour is never the only signal: each step outcome also has its own mark
   shape and a label read out to assistive tech.
--------------------------------------------------------------------------- */

/* The run screen is a four row grid on desktop (rail, banners, workspace, log)
   and this panel is a fifth child. Without this the workspace inherits the
   panel's auto row, the panel inherits the workspace's 1fr and the console
   layout inverts. A hidden panel is display:none so it creates no track at all
   and the original four row template is still correct. */
/* WHY THE PANEL FLEXES RATHER THAN TAKING ITS CONTENT HEIGHT.
   The console is a fixed height box: whatever this panel takes, the leads pane
   loses. Left to size itself the panel ran past 400px on a 940px viewport and
   the workspace collapsed to 23 pixels. A leads pane that thin is not a
   smaller pane, it is a missing one, and the demo exists to show it.
   So the panel and the workspace SHARE the slack and each scrolls inside
   itself. The panel is weighted slightly heavier because during a demo the
   narration is the thing being read, and the minimums stop either one from
   being squeezed out of existence on a short screen.
   layout.css owns the run screen's flex column; this only says what this one
   child does inside it. */
@media (min-width: 1024px) {
  .screen--run > .demo {
    flex: 1.1 1 0;
    min-height: 140px;
    overflow-y: auto;
  }
}

.demo {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  min-height: 0;
  padding: var(--s-3);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
}
.demo[hidden] { display: none; }

/* ---- head ---------------------------------------------------------------- */
.demo__head {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  min-width: 0;
}

.demo__heading {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  min-width: 0;
  flex-wrap: wrap;
}

.demo__eyebrow {
  font-size: var(--t-xs);
  font-weight: var(--fw-semi);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--c-accent);
}

.demo__counter {
  margin: 0;
  font-size: var(--t-lg);
  font-weight: var(--fw-semi);
  line-height: var(--lh-tight);
  color: var(--c-fg);
  font-variant-numeric: tabular-nums;
}

.demo__pill {
  margin-left: auto;
  flex: none;
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-pill);
  border: 1px solid var(--c-border);
  background: var(--c-surface-2);
  color: var(--c-fg-muted);
  font-size: var(--t-xs);
  font-weight: var(--fw-semi);
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.demo__pill--running {
  border-color: var(--c-accent);
  background: var(--c-accent-soft);
  color: var(--c-ok-ink);
}
.demo__pill--done {
  border-color: var(--c-ok-soft);
  background: var(--c-ok-soft);
  color: var(--c-ok-ink);
}
/* The deliberate beat between one step finishing and the next starting. It is
   not idle and it is not the end of the run, so it gets its own quiet tone
   rather than borrowing either. */
.demo__pill--held {
  border-color: var(--c-border-strong);
  background: var(--c-surface-2);
  color: var(--c-fg-muted);
}

/* ---- progress ------------------------------------------------------------ */
.demo__progress {
  position: relative;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--c-idle-soft);
  overflow: hidden;
}
/* Two layers, painted back to front. The pale layer reaches the END of the
   running step so the bar moves the instant a step starts; the solid layer is
   only what genuinely settled, so the bar never claims a step finished. */
.demo__progressnow,
.demo__progressfill {
  position: absolute;
  inset: 0 auto 0 0;
  display: block;
  width: 0;
  border-radius: var(--r-pill);
  transition: width var(--m-slow) var(--m-ease);
}
.demo__progressnow {
  background: var(--c-accent-soft);
  z-index: 0;
}
.demo__progressfill {
  background: var(--c-accent);
  z-index: 1;
}
.demo__progressnow[hidden] { display: none; }

/* ---- the "what this is" strip -------------------------------------------- */
.demo__about {
  margin: 0;
  font-size: var(--t-xs);
  line-height: var(--lh-body);
  color: var(--c-fg-muted);
}
.demo__about strong {
  font-weight: var(--fw-bold);
  letter-spacing: .04em;
  color: var(--c-fg);
}
.demo__aboutsep { padding: 0 var(--s-2); color: var(--c-border-strong); }
.demo__about--live { color: var(--c-warn-ink); }
.demo__about--live strong { color: var(--c-warn-ink); }

/* ---- body: the current step beside the rail ------------------------------ */
.demo__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 15rem;
  gap: var(--s-4);
  min-height: 0;
  flex: 1 1 auto;
}

/* ---- current step -------------------------------------------------------- */
.demo__current {
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  padding-right: var(--s-1);
}

.demo__curhead {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

.demo__curmark {
  flex: none;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  color: var(--c-ok);
}
.demo__curmark svg { width: 18px; height: 18px; }

/* The live indicator. A slow pulse on a dot, deliberately NOT a spinner: a
   spinner on a forty second scrape reads as a hang. */
.demo--running .demo__curmark::before {
  content: '';
  width: 9px;
  height: 9px;
  border-radius: var(--r-pill);
  background: var(--c-accent);
  box-shadow: 0 0 0 0 var(--c-accent-soft);
  animation: demo-pulse 1.8s var(--m-ease) infinite;
}
@keyframes demo-pulse {
  0%   { box-shadow: 0 0 0 0 var(--c-accent-soft); opacity: 1; }
  70%  { box-shadow: 0 0 0 7px rgba(21, 128, 61, 0); opacity: .65; }
  100% { box-shadow: 0 0 0 0 rgba(21, 128, 61, 0); opacity: 1; }
}

.demo[data-status="failed"] .demo__curmark { color: var(--c-danger); }
.demo[data-status="skipped"] .demo__curmark { color: var(--c-drop); }

.demo__curtitle {
  margin: 0;
  min-width: 0;
  font-size: var(--t-xl);
  font-weight: var(--fw-semi);
  line-height: var(--lh-tight);
  color: var(--c-fg);
}

/* Body copy, not console text. This is the one block on the run screen a
   stranger is expected to READ rather than scan. */
.demo__what {
  margin: var(--s-2) 0 0;
  font-size: var(--t-md);
  line-height: var(--lh-body);
  color: var(--c-fg);
}

/* The reason the step exists. Quieter than the what, with its own rule down
   the side, so the eye can take the narration and skip the rationale or the
   other way round. */
.demo__why {
  margin: var(--s-2) 0 0;
  padding-left: var(--s-3);
  border-left: 2px solid var(--c-accent-soft);
  font-size: var(--t-base);
  line-height: var(--lh-body);
  color: var(--c-fg-muted);
}

/* What the step actually LEARNED while it ran: the seller's real quota, the
   capture date, the real Claude latency. The script copy above is written in
   advance and is identical on every demo, so this line is the only part of the
   narration that proves the run in front of you is real. Mono and boxed, to
   read as a measurement rather than as more prose. */
.demo__detail {
  margin: var(--s-2) 0 0;
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-sm);
  background: var(--c-surface-2);
  border: 1px solid var(--c-border);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  line-height: var(--lh-body);
  color: var(--c-fg);
  overflow-wrap: anywhere;
}

.demo__watch {
  margin: var(--s-2) 0 0;
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  color: var(--c-fg-faint);
}

.demo__what[hidden],
.demo__why[hidden],
.demo__detail[hidden],
.demo__watch[hidden] { display: none; }

/* ---- the step rail ------------------------------------------------------- */
.demo__steps {
  margin: 0;
  padding: 0 var(--s-1) 0 0;
  list-style: none;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  border-left: 1px solid var(--c-border);
  padding-left: var(--s-3);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.demo__step { min-width: 0; }

/* position:relative is load-bearing, not decoration. The chip holds an
   .sr-only status word and that utility is position:absolute. Without a
   positioned ancestor its containing block is the page, so below 1024px, where
   the rail is a horizontal scroller 2000px wide, those 1px spans sit at their
   static x OUTSIDE the scroller's clip and drag the whole document's scrollable
   width out with them. The page gained 198px of horizontal scroll from eleven
   invisible spans. Containing them in the chip lets the rail clip them. */
.demo__chip {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: 100%;
  min-width: 0;
  padding: var(--s-1) var(--s-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--c-fg-muted);
  font: inherit;
  font-size: var(--t-sm);
  text-align: left;
  transition: background var(--m-fast) var(--m-ease),
              border-color var(--m-fast) var(--m-ease),
              color var(--m-fast) var(--m-ease);
}
button.demo__chip { cursor: pointer; }
button.demo__chip:disabled { cursor: default; }
button.demo__chip:not(:disabled):hover {
  background: var(--c-surface-2);
  border-color: var(--c-border);
  color: var(--c-fg);
}

.demo__chipmark {
  flex: none;
  display: grid;
  place-items: center;
  width: 14px;
  height: 14px;
  color: var(--c-idle);
}
.demo__chipmark svg { width: 14px; height: 14px; }

.demo__chipn {
  flex: none;
  width: 2ch;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--c-fg-faint);
  text-align: right;
}

.demo__chiptitle {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- rail states --------------------------------------------------------- */
.demo__step[data-status="done"] .demo__chipmark { color: var(--c-ok); }
.demo__step[data-status="done"] .demo__chiptitle { color: var(--c-fg-muted); }
.demo__step[data-status="failed"] .demo__chipmark { color: var(--c-danger); }
.demo__step[data-status="failed"] .demo__chiptitle { color: var(--c-danger-ink); }
.demo__step[data-status="skipped"] .demo__chipmark { color: var(--c-drop); }
.demo__step[data-status="skipped"] .demo__chiptitle { color: var(--c-drop); }

/* The running step. Highlighted, and its dot pulses in step with the big one
   above so the two read as the same thing in two places. */
.demo__step.is-current .demo__chip {
  background: var(--c-accent-soft);
  border-color: var(--c-accent);
  color: var(--c-ok-ink);
  font-weight: var(--fw-semi);
}
.demo__step.is-current .demo__chipn { color: var(--c-ok-ink); }
.demo__step[data-status="start"] .demo__chipmark::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--c-accent);
  animation: demo-blink 1.8s var(--m-ease) infinite;
}
@keyframes demo-blink {
  0%, 100% { opacity: 1; }
  55%      { opacity: .35; }
}

/* Not started yet. Dimmed, no copy, no control: there is nothing to open. */
.demo__step[data-status="future"] .demo__chip { opacity: .45; }
.demo__step[data-status="future"] .demo__chipmark::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: var(--r-pill);
  border: 1px solid var(--c-border-strong);
}

.demo__step.is-open .demo__chip {
  border-color: var(--c-primary);
  background: var(--c-primary-soft);
  color: var(--c-primary);
}

/* ---- the replay block ---------------------------------------------------- */
/* An earlier step reopened. It lives below the body rather than inside the rail
   chip, because below 1024px that chip is 150px wide in a horizontal scroller
   and a paragraph would be unreadable in it. */
.demo__recall {
  /* Never the part that gives way. .demo__body flexes and everything inside it
     has its own scrollbar, so when the panel is capped the body is what should
     shrink. Left shrinkable, the replay lost most of its height to the body and
     arrived as a 70px slot with its own scrollbar, which is exactly what the
     viewer clicked to get away from. */
  flex: 0 0 auto;
  min-height: 0;
  max-height: 7rem;
  overflow-y: auto;
  padding: var(--s-2) var(--s-3);
  border: 1px dashed var(--c-border-strong);
  border-radius: var(--r-md);
  background: var(--c-surface-2);
}
.demo__recall[hidden] { display: none; }

.demo__recallhead {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  min-width: 0;
}
.demo__recalltag {
  flex: none;
  font-size: var(--t-xs);
  font-weight: var(--fw-semi);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--c-fg-faint);
}
.demo__recalltitle {
  margin: 0;
  min-width: 0;
  font-size: var(--t-md);
  font-weight: var(--fw-semi);
  line-height: var(--lh-tight);
  color: var(--c-fg);
}
.demo__recall .demo__what { margin-top: var(--s-1); font-size: var(--t-base); }
.demo__recall .demo__why { margin-top: var(--s-1); }

/* ---- desktop height cap -------------------------------------------------- */
/* The console is one viewport tall and the workspace below has to keep its own
   scrollbars, so the panel is capped rather than allowed to grow with the step
   count. Everything inside it scrolls in its own box. */
@media (min-width: 1024px) {
  .demo { max-height: 320px; }

  /* Reopening an earlier step is the one time the panel is allowed past its
     budget. At 320px the replay gets about 70px and both it and the live step
     end up scrolled, which turns a deliberate "let me read that again" into
     two clipped boxes. Growing here is safe in a way growing with the step
     count is not: it happens only on a click, the workspace row below is
     minmax(0, 1fr) so it simply gives up the space, and the page itself still
     never scrolls. */
  .demo:has(> .demo__recall:not([hidden])) { max-height: 440px; }
  .demo:has(> .demo__recall:not([hidden])) .demo__recall { max-height: 11rem; }
}

/* ---- narrow: stack the body and scroll the rail sideways ----------------- */
@media (max-width: 1023px) {
  .demo__body {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
  }
  .demo__current { overflow: visible; }

  .demo__steps {
    flex-direction: row;
    align-items: stretch;
    gap: var(--s-2);
    padding: var(--s-1) 0 var(--s-2);
    border-left: 0;
    border-top: 1px solid var(--c-border);
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
  }
  /* Fixed width chips, so the row scrolls instead of squeezing every title into
     an ellipsis. min-width:0 on the flex item is what keeps this off the page
     axis: without it the row cannot shrink and the whole document gains a
     horizontal scrollbar. */
  .demo__step {
    flex: 0 0 auto;
    width: 11rem;
    scroll-snap-align: start;
  }
  .demo__chip {
    border: 1px solid var(--c-border);
    background: var(--c-surface-2);
    height: 100%;
  }
  .demo__curtitle { font-size: var(--t-lg); }
  .demo__recall { max-height: none; }
}

@media (max-width: 700px) {
  .demo { padding: var(--s-2) var(--s-3); }
  .demo__pill { margin-left: 0; }
  .demo__head { flex-wrap: wrap; }
}

/* ---- reduced motion ------------------------------------------------------ */
/* No pulse and no travel. The state itself still changes, it simply arrives
   rather than animating in. */
@media (prefers-reduced-motion: reduce) {
  .demo--running .demo__curmark::before,
  .demo__step[data-status="start"] .demo__chipmark::before {
    animation: none;
    box-shadow: none;
    opacity: 1;
  }
  .demo__progressnow,
  .demo__progressfill,
  .demo__chip {
    transition: none;
  }
  .demo__steps { scroll-behavior: auto; }
}

/* ---------------------------------------------------------------------------
   The runtime detail line.
   ---------------------------------------------------------------------------
   `what` and `why` are the fixed script. THIS is what the engine learned while
   the step actually ran: the seller's real remaining quota, the capture date,
   the address the fallback harvest recovered, the real Claude latency, the
   address the email was rerouted to. It is the half of the narration that
   proves the run is real rather than a slideshow, so it is given its own
   treatment instead of being folded in with the script copy.
--------------------------------------------------------------------------- */
.demo__detail {
  margin: var(--s-3) 0 0;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  background: var(--c-surface-2);
  border: 1px solid var(--c-border);
  font-family: var(--f-mono);
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  color: var(--c-fg);
  overflow-wrap: anywhere;
}

.demo__detail[hidden] {
  display: none;
}
