/* The Listening Post — mobile composer (max-width 680px).
   Part of the /labs stylesheet, split out of one 3,400-line labs.css.

   THE NUMBER IN THE FILENAME IS LOAD-BEARING. stylesheet_link_tag :app
   collects every stylesheet under app/assets and serves them sorted by
   path, so the ordinal prefix is the only thing holding the cascade order
   these rules were written in — and several classes are shared across labs
   (.lp-head, .lab-entry, .lab-block, .dt-table). Renaming a file without
   renumbering it, or inserting one out of sequence, reorders the cascade
   silently.

   Nothing in this comment may contain the two characters that close a CSS
   comment. The first version of it wrote a shell glob here, which closed
   the comment early; the leaked text then parsed as a selector and ate the
   first real rule in all nine files. There is a test for that now.
   ============================================================ */

/* ============================================================
   Mobile-first composer (≤680px, demo page) — Claude-app pattern.
   A compact, bottom-docked input bar with inline pill controls; the
   content area scrolls freely above it. Desktop (>680px) is untouched.
   Body-level concerns (footer, Intercom launcher, padding reserve) are
   scoped to body.lp-demo; in-page concerns to the controller root.
   ============================================================ */
@media (max-width: 680px) {
  /* Reclaim the whole viewport: no site footer, no launcher on this page. The
     body padding-bottom this used to zero out went with the fixed footer, and the
     footer selector was footer.cx-footer — dead since Prism II, which is why the
     footer had quietly been rendering here again. */
  body.lp-demo .ft-band { display: none; }
  body.lp-demo .intercom-lightweight-app-launcher,
  body.lp-demo .intercom-launcher-frame,
  body.lp-demo #intercom-container .intercom-launcher { display: none !important; }

  /* .lp-head / .lp-title / .lp-subtitle used to be compressed here so the empty
     state fit one viewport. This page has rendered the shared lab hero since
     2026-09-03 and has none of those elements, so the rules were doing nothing
     while a 454px hole did exactly what they were written to prevent. The classes
     survive for the Proving Ground's bout view, which is not this breakpoint's
     problem. Deleted rather than kept as a comfort. */

  /* The corpus line stays in flow under the band while the composer is pinned to
     the bottom, which is what gives the phone's empty state something between the
     two. It is the widest line on the page at this width, so it wraps rather than
     scrolls. */
  body.lp-demo .lp-corpus { margin-top: 22px; }

  /* The composer is pinned to the bottom of the screen here, so the Other labs row
     at the end of the page needs that much room under it or its last line sits
     behind the input. --lp-dock-h is measured by listening_post_controller.js. */
  body.lp-demo:has(.lp-composer-dock) .labs-rel {
    padding-bottom: calc(var(--lp-dock-h, 120px) + 32px);
  }
  body.lp-demo.lp-conversing .lp-corpus { display: none; }

  /* Composer docked to the bottom of the viewport at all times (not just while
     conversing). Flat — background matches the page, only a hairline top border.
     --lp-kb (set from visualViewport in JS) lifts it flush above the keyboard. */
  body.lp-demo .lp-composer-dock {
    /* A column so the chips can be ordered above the input without moving them in
       the markup, where they sit after the composer so a keyboard reaches the field
       first. At the bottom of a phone screen the suggestions belong above the thumb
       target, not below it. */
    display: flex;
    flex-direction: column;
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--lp-kb, 0px);
    z-index: 40;
    margin-top: 0;
    padding: 10px var(--gutter) calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--bg);
    border-top: 1px solid var(--line);
  }

  /* Suggestion chips: one horizontally-scrolling row just above the input. */
  body.lp-demo .lp-chips {
    order: -1;
    display: flex;
    gap: 8px;
    flex-wrap: nowrap;
    overflow-x: auto;
    max-width: none;
    margin: 0 0 10px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  body.lp-demo .lp-chips::-webkit-scrollbar { display: none; }
  /* 79% of this row is off-screen with the scrollbar hidden, and the only hint
     was a chip happening to be clipped by the viewport edge. The mask fades the
     last few pixels so the row reads as continuing rather than as ending. */
  body.lp-demo .lp-chips {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
  body.lp-demo.lp-conversing .lp-chips { display: none; }

  /* Drop the floating-card look — the composer becomes a plain two-row stack. */
  body.lp-demo .lp-composer {
    max-width: none;
    margin: 0;
    background: transparent;
    border: none;
    border-radius: 0;
  }

  /* Row 1 — textarea: single line at rest (~44px); JS caps growth at 2 lines. */
  body.lp-demo .lp-composer-input {
    min-height: 44px;
    padding: 12px 4px 6px;
    line-height: 1.4;
  }

  /* Row 2 — controls on one line. Hide the "Ask a question" dropdown (chips replace it).
     Tightened padding/gaps so segment pill + Start over + send all fit at 360px. */
  body.lp-demo .lp-composer-bar { gap: 8px; padding: 6px 0 2px; }
  body.lp-demo .lp-composer-menus { flex-wrap: nowrap; min-width: 0; gap: 8px; }
  body.lp-demo .lp-composer-menus .lp-menu-trigger { padding-inline: 11px; }
  body.lp-demo .lp-menu--ask { display: none; }

  /* The composer is pinned to the bottom, so its menus must open upward, not off-screen. */
  body.lp-demo .lp-menu-panel { top: auto; bottom: calc(100% + 8px); }

  /* ≥44px touch targets even where the control looks smaller. */
  body.lp-demo .lp-menu-trigger { min-height: 44px; }
  body.lp-demo .lp-startover { flex: 0 0 auto; white-space: nowrap; }
  /* The chips are a touch target at this width and measured 40px. Desktop leaves
     them at their authored height on purpose — see composer_touch_targets_test on
     why 44 is scoped to touch rather than applied everywhere. */
  body.lp-demo .lp-chip { min-height: 44px; }
  body.lp-demo .lp-composer-send { position: relative; }
  body.lp-demo .lp-composer-send::after { content: ""; position: absolute; inset: -3px -4px; }

  /* Scroll room: keep the last answer clear of the docked composer (footer is gone). */
  body.lp-demo.lp-conversing .lp-transcript {
    padding-bottom: calc(var(--lp-dock-h, 150px) + 16px);
  }
  body.lp-demo .lp-body { padding-bottom: 0; }
}

/* ---- empty state ---- */
.lp-empty {
  font-family: var(--font-sans);
  font-style: italic;
  font-weight: 300;
  color: var(--ink-muted);
  font-size: clamp(18px, 2vw, 22px);
  margin-top: 56px;
}

/* ---- answer ---- */
.lp-answer-block { margin-top: 56px; }
.lp-asked {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 16px;
}
/* The answer is boxless markdown (headings, bold, italics, lists) in the sans body
   voice. It fills the full content column — aligned to the same left/right margins
   as the header and footer (the .wrap gutters) — rather than a narrow sub-column. */
.lp-answer-card {
  margin-top: 28px;             /* breathing room between the process log and the answer */
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.75;
  color: var(--ink);
}
.lp-answer-card p { margin: 0; }
.lp-answer-card p + *,
.lp-answer-card ul + *,
.lp-answer-card ol + * { margin-top: 18px; }
.lp-answer-card h1,
.lp-answer-card h2,
.lp-answer-card h3 {
  font-family: var(--font-sans);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.lp-answer-card h1 { font-size: 21px; margin: 28px 0 12px; }
.lp-answer-card h2 { font-size: 19px; margin: 26px 0 10px; }
.lp-answer-card h3 { font-size: 17px; margin: 22px 0 8px; }
.lp-answer-card > :first-child { margin-top: 0; }
.lp-answer-card strong { font-weight: 600; }
.lp-answer-card em { font-style: italic; }
.lp-answer-card hr {
  border: none;
  border-top: 1px solid var(--line);
  margin: 26px 0;
}
.lp-answer-card ul,
.lp-answer-card ol { margin: 14px 0; padding-left: 24px; }
.lp-answer-card ul { list-style: disc; }
.lp-answer-card ol { list-style: decimal; }
.lp-answer-card li { margin: 6px 0; padding-left: 4px; }
.lp-answer-card li::marker { color: var(--ink-faint); }

/* ---- answer tables ----
   Markdown tables in a streamed answer, styled to match the /data grid (.dt-table):
   monochrome, mono type, hairline cell rules, a faint header row, zebra + hover, and
   a bordered frame that scrolls horizontally when the table is wider than the column. */
.lp-answer-card .lp-table-wrap {
  margin: 22px 0;
  border: 1px solid var(--line);
  overflow-x: auto;
}
.lp-answer-card .lp-table {
  border-collapse: collapse;
  width: 100%;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink);
}
.lp-answer-card .lp-table th,
.lp-answer-card .lp-table td {
  border-right: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  padding: 9px 14px;
  text-align: left;
  vertical-align: top;
}
.lp-answer-card .lp-table th:last-child,
.lp-answer-card .lp-table td:last-child { border-right: none; }
.lp-answer-card .lp-table tbody tr:last-child td { border-bottom: none; }
.lp-answer-card .lp-table thead th {
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.lp-answer-card .lp-table tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--ink) 2%, transparent); }
.lp-answer-card .lp-table tbody tr:hover td { background: color-mix(in srgb, var(--ink) 4%, transparent); }

/* Each word lands in its own span and eases from transparent to full ink — no blur,
   just a gentle opacity ramp. Because words arrive faster than the ~0.8s fade, several
   are always mid-fade at once, giving the soft trailing gradient of Claude's chat. */
.lp-word {
  opacity: 0;
  animation: lpChunkIn 0.8s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
@keyframes lpChunkIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Trailing star at the end of the answer: spins while the reveal is streaming,
   then freezes (static) once the answer is complete. */
.lp-answer-star {
  display: block;
  width: 18px;
  height: 18px;
  margin-top: 20px;
  color: var(--ink);
}
.lp-answer-star svg { display: block; overflow: visible; transform-origin: center; }

/* subtle commercial footer under the answer: model · tokens · cost · latency */
.lp-answer-meta {
  margin-top: 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}
.lp-answer-meta[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .lp-answer-star:not(.is-done) svg { animation: lpSpin 5.5s linear infinite; }
  .lp-answer-star:not(.is-done) .lp-ray {
    transform-origin: 12px 12px;
    animation: lpRay 1.4s ease-in-out infinite;
  }
  .lp-answer-star .lp-ray:nth-child(1) { animation-delay: 0s; }
  .lp-answer-star .lp-ray:nth-child(2) { animation-delay: 0.09s; }
  .lp-answer-star .lp-ray:nth-child(3) { animation-delay: 0.18s; }
  .lp-answer-star .lp-ray:nth-child(4) { animation-delay: 0.27s; }
  .lp-answer-star .lp-ray:nth-child(5) { animation-delay: 0.36s; }
  .lp-answer-star .lp-ray:nth-child(6) { animation-delay: 0.45s; }
  .lp-answer-star .lp-ray:nth-child(7) { animation-delay: 0.54s; }
  .lp-answer-star .lp-ray:nth-child(8) { animation-delay: 0.63s; }
}

/* ---- processing steps ----
   Two shells over one per-step state machine. While the pipeline runs, a single
   "live line" (spinning starburst + one label that crossfades between steps) is
   shown. Once the answer finishes, it hands off to a single "Thought for N steps"
   disclosure whose one chevron expands to reveal all four steps' captured detail
   at once. Both shells start hidden, so the no-JS fallback shows only the answer. */
.lp-steps {
  display: flex;
  flex-direction: column;
  margin-top: 22px;
}
.lp-steps-live[hidden],
.lp-steps-summary[hidden] { display: none; }

/* live line — mirrors a step-summary row; its star spins the whole time it shows */
.lp-steps-live {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 7px 0;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink);
  transition: opacity 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.lp-steps-live.is-fading { opacity: 0; }               /* fade out on handoff to the summary */
.lp-steps-live-label {
  flex: 0 1 auto;
  transition: opacity 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
/* .4, not 0. At 0 the swap left 200ms windows where the spinning star sat beside
   no text at all, which reads as a hung page rather than as a step changing. */
.lp-steps-live-label.is-out { opacity: .4; }

/* summary disclosure — one clickable head + a max-height collapsible region */
.lp-steps-summary { opacity: 1; transition: opacity 0.2s cubic-bezier(0.22, 1, 0.36, 1); }
.lp-steps-summary.is-in { opacity: 0; }                /* start transparent, JS clears it to fade in */
.lp-steps-summary-head {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 7px 0;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-muted);
  transition: color 0.2s;
}
.lp-steps-summary-head:hover { color: var(--ink); }
.lp-steps-summary-label { flex: 0 1 auto; }
.lp-steps-summary-head[aria-expanded="true"] .lp-step-chevron { transform: rotate(90deg); }
.lp-step-tick--static { display: block; }

.lp-steps-nested {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
/* nested steps are always laid out; the region's max-height governs visibility */
.lp-steps-nested .lp-step { display: block; }
.lp-steps-nested .lp-step-summary { cursor: default; }

/* a nested step's label row — non-interactive (the one disclosure is the head above) */
.lp-step-summary {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 7px 0;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-faint);
}
.lp-step.is-active > .lp-step-summary { color: var(--ink); }
.lp-step.is-done   > .lp-step-summary { color: var(--ink-muted); }

/* state icon: spinning star while active, check once done */
.lp-step-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  color: currentColor;
}
.lp-step-star { display: inline-flex; }
.lp-step-star svg { display: block; overflow: visible; transform-origin: center; }
.lp-step-tick { display: none; }
.lp-step.is-done > .lp-step-summary .lp-step-star { display: none; }
.lp-step.is-done > .lp-step-summary .lp-step-tick { display: block; }
.lp-ray {
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
}

.lp-step-label { flex: 0 1 auto; }

.lp-step-chevron {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--ink-faint);
  transition: transform 0.2s;
}

.lp-step-body { padding: 2px 0 14px 29px; }  /* indent under the label (icon 18 + gap 11) */
.lp-step-detail {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-muted);
  white-space: pre-wrap;
  word-break: break-word;
}
.lp-step-detail:empty { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .lp-step.is-active .lp-step-star svg,
  .lp-steps-live .lp-step-star svg { animation: lpSpin 5.5s linear infinite; }
  .lp-step.is-active .lp-step-star .lp-ray,
  .lp-steps-live .lp-step-star .lp-ray {
    transform-origin: 12px 12px;
    animation: lpRay 1.4s ease-in-out infinite;
  }
  .lp-step-star .lp-ray:nth-child(1) { animation-delay: 0s; }
  .lp-step-star .lp-ray:nth-child(2) { animation-delay: 0.09s; }
  .lp-step-star .lp-ray:nth-child(3) { animation-delay: 0.18s; }
  .lp-step-star .lp-ray:nth-child(4) { animation-delay: 0.27s; }
  .lp-step-star .lp-ray:nth-child(5) { animation-delay: 0.36s; }
  .lp-step-star .lp-ray:nth-child(6) { animation-delay: 0.45s; }
  .lp-step-star .lp-ray:nth-child(7) { animation-delay: 0.54s; }
  .lp-step-star .lp-ray:nth-child(8) { animation-delay: 0.63s; }
}
@keyframes lpSpin { to { transform: rotate(360deg); } }
@keyframes lpRay  { 0%, 100% { opacity: 0.22; } 50% { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .lp-word { animation: none; opacity: 1; filter: none; }
  .lp-step-star svg,
  .lp-step-star .lp-ray,
  .lp-answer-star svg,
  .lp-answer-star .lp-ray { animation: none; }
  /* instant label swap, handoff, and expand/collapse */
  .lp-steps-live,
  .lp-steps-live-label,
  .lp-steps-summary,
  .lp-steps-nested { transition: none; }
}

/* ---- citation hovers ----
   [n] tokens in the answer become hover targets that reveal the cited verbatim(s)
   in a tooltip (the source of truth now that "Behind the answer" is gone). */
.lp-cite {
  cursor: help;
  border-bottom: 1px dotted var(--ink-faint);
  transition: color 0.15s, border-color 0.15s;
}
.lp-cite:hover,
.lp-cite:focus-visible {
  color: var(--ink);
  border-bottom-color: var(--ink);
  outline: none;
}

.lp-tip {
  position: fixed;
  z-index: 60;
  max-width: min(380px, 90vw);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px 14px;
  box-shadow: 0 8px 28px rgba(11, 11, 12, 0.12);
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink);
  pointer-events: none;
}
.lp-tip[hidden] { display: none; }
.lp-tip-item + .lp-tip-item {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}
.lp-tip-meta {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 5px;
}
.lp-tip-body { color: var(--ink-muted); }

/* ---- sources ---- */
.lp-sources { margin-top: 40px; }
.lp-sources summary {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  cursor: pointer;
  list-style: none;
}
.lp-sources summary::-webkit-details-marker { display: none; }
.lp-sources summary::before { content: "+ "; color: var(--ink-faint); }
.lp-sources[open] summary::before { content: "\2013 "; }
.lp-source-list { margin-top: 20px; display: flex; flex-direction: column; }
.lp-source {
  padding: 18px 0 18px 18px;
  border-left: 2px solid var(--line-soft);
  border-top: 1px solid var(--line-soft);
}
.lp-source:first-child { border-top: none; }
.lp-source-meta {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.lp-source-id { color: var(--ink); }
.lp-source-body {
  font-family: var(--font-sans);
  font-size: 15px;
  color: var(--ink-muted);
  line-height: 1.6;
  margin-top: 8px;
}
