/* ---- Listening Post (Lab 01) ----
   Scoped styles for the labs pages. Reuses design tokens (--ink, --line,
   --font-serif, etc.) defined globally in app/assets/tailwind/application.css. */

.lp-head {
  padding-block: clamp(56px, 9vw, 96px) clamp(28px, 4vw, 40px);
  text-align: center;
}

/* page title — serif "human voice" */
.lp-title {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(32px, 5.2vw, 54px);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin-top: 18px;
}
/* time-of-day greeting — subheading beneath the title, anchored by the static starburst */
.lp-greeting {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(21px, 2.9vw, 32px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin-top: 14px;
}
.lp-greeting-mark { display: inline-flex; color: var(--ink); }
.lp-greeting-mark svg {
  display: block;
  overflow: visible;
}
.lp-subtitle {
  font-family: var(--font-sans);
  color: var(--ink-muted);
  font-size: clamp(16px, 1.6vw, 18px);
  max-width: 56ch;
  margin: 18px auto 0;
}

.lp-body {
  padding-bottom: clamp(32px, 4vw, 48px);   /* footer is fixed; body reserves its height */
}

/* ---- conversation layout ----
   Initial state: greeting + composer sit near the top (as authored). Once the
   first question is asked, `.is-conversing` on the controller root hides the
   greeting, reveals the scrolling transcript, and docks the composer to the
   bottom of the viewport (sticky) so follow-ups read like a chat. */
.lp-transcript:empty { display: none; }

.lp-turn + .lp-turn { border-top: 1px solid var(--line-soft); }
.lp-transcript .lp-turn:first-child .lp-answer-block { margin-top: 0; }

/* Composer dock: normal flow initially; sticky to the screen bottom while conversing. */
.lp-composer-dock { margin-top: 28px; }

/* "Start over" lives inside the composer bar next to the segment menu; it uses the
   .lp-menu-trigger look and only appears once a conversation is underway. The
   two-class selector beats .lp-menu-trigger's own `display` so it stays hidden
   until `.is-conversing`. */
.lp-composer-menus .lp-startover { display: none; }

.is-conversing .lp-head { display: none; }
.is-conversing .lp-startover { display: inline-flex; }
.is-conversing .lp-transcript {
  padding-top: clamp(24px, 5vw, 48px);
  /* The answer reads top-down: it starts just under the header and grows downward,
     scrolling only once it fills the space above the composer (auto-follow in the JS
     controller keeps the newest line in view). We reserve just the composer's height
     here so the last line clears it — the footer is already reserved by
     `body { padding-bottom: var(--footer-h) }`; reserving it twice left a large gap. */
  padding-bottom: calc(var(--lp-dock-h, 168px) + 24px);
}
.is-conversing .lp-body { padding-bottom: 0; }

/* The composer and the global footer are both pinned to the bottom of the viewport
   while a conversation is underway, so neither drifts as the answer streams in. The
   class lives on <body> because the footer is outside the controller's element; the
   controller keeps --lp-dock-h / --lp-footer-h up to date. */
body.lp-conversing .lp-composer-dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: var(--lp-footer-h, 84px);
  z-index: 30;
  padding: 16px var(--gutter) 20px;
  /* opaque base with a short top fade so transcript text scrolls cleanly under it */
  background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, var(--bg) 22px, var(--bg) 100%);
}
body.lp-conversing footer.cx-footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  background: var(--bg);
  box-shadow: 0 1px 0 1px var(--bg);   /* cover any sub-pixel transcript sliver at the very edge */
}

/* ---- composer (chat-style input) ----
   A single large input surface: a growing textarea over a toolbar carrying the
   two dropdown menus and the send control. Monochrome, hairline-bordered — the
   only concession to the "chat input" idiom is a soft corner radius. */
.lp-composer {
  max-width: 760px;
  margin: 0 auto;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 16px;
  transition: border-color 0.2s;
}
.lp-composer:focus-within { border-color: var(--ink); }

.lp-composer-input {
  display: block;
  width: 100%;
  border: none;
  background: transparent;
  resize: none;
  overflow-y: auto;
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
  padding: 20px 20px 6px;
  min-height: 58px;
  max-height: 200px;
}
.lp-composer-input::placeholder { color: var(--ink-faint); }
.lp-composer-input:focus { outline: none; }

.lp-composer-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px 10px;
}
.lp-composer-menus { display: flex; flex-wrap: wrap; gap: 8px; }

.lp-composer-send {
  margin-left: auto;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: #0B0B0C;
  color: #FFFFFF;
  border: none;
  border-radius: 9999px;
  cursor: pointer;
  transition: opacity 0.2s;
}
.lp-composer-send:hover { opacity: 0.8; }
.lp-composer-send:disabled,
.lp-composer-send.is-busy { opacity: 0.4; cursor: default; }

/* ---- composer dropdown menus ---- */
.lp-menu { position: relative; }
.lp-menu-trigger {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink-muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 8px 13px;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.lp-menu-trigger:hover { border-color: var(--ink); }
.lp-menu-trigger[aria-expanded="true"] {
  border-color: var(--ink);
  background: rgba(0, 0, 0, 0.03);
}
.lp-menu-ico { flex: 0 0 auto; color: var(--ink-faint); }

.lp-menu-panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 30;
  width: max-content;
  min-width: min(360px, 84vw);
  max-width: min(560px, 92vw);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
}
.lp-menu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.lp-menu-close {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  color: var(--ink-faint);
  padding: 0 2px;
  transition: color 0.2s;
}
.lp-menu-close:hover { color: var(--ink); }
.lp-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-top: 1px solid var(--line-soft);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.4;
  color: var(--ink);
  padding: 13px 16px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s;
}
.lp-menu-item:first-of-type { border-top: none; }
.lp-menu-item:hover { background: rgba(0, 0, 0, 0.04); }

@media (max-width: 680px) {
  .lp-menu-panel { width: auto; min-width: min(320px, 84vw); max-width: 92vw; }
  .lp-menu-item { white-space: normal; }
}

/* ---- mobile suggestion chips (empty state, replaces the "Ask a question" menu) ----
   Rendered on the demo page only; the row is hidden on desktop and once conversing. */
.lp-chips { display: none; }
.lp-chip {
  flex: 0 0 auto;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink-muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 9px 13px;
  min-height: 40px;
  cursor: pointer;
  transition: border-color 0.2s;
}
.lp-chip:hover { border-color: var(--ink); }

/* ============================================================
   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 fixed site footer, no launcher on this page. */
  body.lp-demo { padding-bottom: 0; }
  body.lp-demo footer.cx-footer { 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; }

  /* Compress the pre-conversation hero so the empty state fits ~one viewport. */
  body.lp-demo .lp-head { padding-block: 26px 14px; }
  body.lp-demo .lp-title { margin-top: 10px; }
  body.lp-demo .lp-greeting { margin-top: 8px; }
  body.lp-demo .lp-subtitle { margin-top: 10px; }

  /* 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 {
    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 {
    display: flex;
    gap: 8px;
    flex-wrap: nowrap;
    overflow-x: auto;
    margin-bottom: 10px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  body.lp-demo .lp-chips::-webkit-scrollbar { display: none; }
  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; }
  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-serif);
  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: 22px; margin: 28px 0 12px; }
.lp-answer-card h2 { font-size: 19px; margin: 26px 0 10px; }
.lp-answer-card h3 { font-size: 16.5px; 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: 12.5px;
  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: 11px;
  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: rgba(0, 0, 0, 0.018); }
.lp-answer-card .lp-table tbody tr:hover td { background: rgba(0, 0, 0, 0.045); }

/* 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: 11.5px;
  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);
}
.lp-steps-live-label.is-out { opacity: 0; }            /* crossfade: out, swap text, in */

/* 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: 12.5px;
  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: 13.5px;
  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: 10.5px;
  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: 11px;
  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;
}

/* ============================================================
   Raw dataset view (Labs · /labs/data)
   A spreadsheet-like grid rendered in the house type system —
   monospace, hairline rules, no colour. It should read, at a
   glance, as data.
   ============================================================ */

.dt-stats {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--ink-faint);
  margin-top: 22px;
  display: flex;
  gap: 12px;
  align-items: baseline;
}
.dt-stat b { color: var(--ink); font-weight: 500; }
.dt-stat-sep { color: var(--ink-faint); }

.dt-block { margin-top: 56px; }
.dt-block:first-of-type { margin-top: 40px; }

/* caption row above each table */
.dt-caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-bottom: 10px;
}
.dt-caption-name { color: var(--ink); }

/* scroll frame — clips the grid and gives it a bounded, viewport-like feel */
.dt-scroll {
  border: 1px solid var(--line);
  overflow: auto;
  max-height: 72vh;
}

.dt-table {
  border-collapse: collapse;
  width: 100%;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink);
}
.dt-table th,
.dt-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;
  white-space: nowrap;
}

/* sticky column headers */
.dt-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

/* row-number gutter, pinned left */
.dt-gutter {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bg);
  color: var(--ink-faint);
  text-align: right;
  width: 1%;
  font-size: 11px;
  user-select: none;
  border-right: 1px solid var(--line);
}
.dt-table thead .dt-gutter { z-index: 3; }

/* zebra + hover for scanability (kept strictly monochrome) */
.dt-table tbody tr:nth-child(even) td { background: rgba(0,0,0,0.018); }
.dt-table tbody tr:nth-child(even) .dt-gutter { background: #FAFAFA; }
.dt-table tbody tr:hover td { background: rgba(0,0,0,0.045); }
.dt-table tbody tr:hover .dt-gutter { background: #F2F2F2; }

.dt-mono { color: var(--ink-muted); }
.dt-nowrap { white-space: nowrap; }
.dt-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.dt-neg { font-weight: 500; }

/* segment pill */
.dt-tag {
  display: inline-block;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border: 1px solid var(--line-soft);
  border-radius: 2px;
  padding: 2px 7px;
}

/* sentiment — signalled by a monochrome glyph, not colour */
.dt-sent {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 11px;
  color: var(--ink-faint);
  white-space: nowrap;
}
.dt-sent::before {
  content: "\25CF"; /* ● */
  font-size: 8px;
  margin-right: 7px;
  vertical-align: 1px;
  color: var(--ink-faint);
}
.dt-sent--negative { color: var(--ink); }
.dt-sent--negative::before { color: var(--ink); }
.dt-sent--positive::before { content: "\25CB"; } /* ○ */
.dt-sent--neutral::before  { content: "\2013"; } /* – */

/* body verbatim — the human voice; readable sans, allowed to wrap.
   Table auto-layout ignores max-width on the <td>, so the width is
   pinned on an inner <div> to force wrapping instead of column bleed. */
.dt-body-col { white-space: normal; }
.dt-body {
  width: 480px;
  white-space: normal;
  overflow-wrap: break-word;
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-muted);
}
@media (max-width: 680px) {
  .dt-body { width: 260px; }
}

.dt-link { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.dt-link:hover { color: var(--ink-faint); }

@media (max-width: 680px) {
  .dt-scroll { max-height: 68vh; }
  .dt-body-col { min-width: 240px; }
}

/* ---- meta footer ---- */
.lp-meta-footer {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--line-soft);
}

/* ============================================================
   Labs index (/labs) — a short catalogue of the prototypes.
   Number-rail + content layout, monochrome, hairline rules.
   ============================================================ */
.lab-list { margin-top: clamp(24px, 4vw, 40px); }
.lab-entry {
  display: grid;
  grid-template-columns: 88px 1fr;
  gap: 0 28px;
  padding: clamp(28px, 4vw, 44px) 0;
  border-top: 1px solid var(--line);
}
.lab-entry:first-child { border-top: none; padding-top: 0; }
@media (max-width: 680px) {
  .lab-entry { grid-template-columns: 1fr; gap: 12px; }
}
.lab-num {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  padding-top: 6px;
}
.lab-main .eyebrow { display: block; margin-bottom: 12px; }
.lab-name {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(26px, 3.4vw, 38px);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0;
}
.lab-name a { color: var(--ink); border-bottom: 1px solid transparent; transition: border-color 0.2s; }
.lab-name a:hover { border-bottom-color: var(--ink); }

.lab-block { margin-top: 22px; }
.lab-block-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.lab-block p {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink-muted);
  max-width: 64ch;
  margin: 0;
}
.lab-block p.lab-stack {          /* more specific than .lab-block p */
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.7;
  max-width: none;
}
.lab-block p.lab-wide { max-width: none; }   /* span the full column, like the stack block */

.lab-open {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 26px;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.03em;
  color: var(--bg);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 9999px;
  padding: 11px 18px;
  transition: gap 0.2s, opacity 0.2s;
}
.lab-open:hover { gap: 12px; opacity: 0.85; }
.lab-open svg { flex: 0 0 auto; }

/* Same three swatch colours used on the homepage's Labs cards and Proof,
   carried across to this page — one quiet background wash per entry,
   bled slightly past the text for a soft "band" rather than a hard box.
   Scoped no-gradients exception (see CLAUDE.md): a soft single-corner
   "aurora" bloom in the bottom-right, fading to the page background. */
.lab-entry-yellow { --accent-b: #FF6F5E; --accent-ink: #9A3412; }
.lab-entry-green   { --accent-b: #22B8CF; --accent-ink: #0F766E; }
.lab-entry-blue    { --accent-b: #8B5CF6; --accent-ink: #4338CA; }
.lab-entry-pink    { --accent-b: #EC4899; --accent-ink: #9D174D; }
.lab-entry-emerald { --accent-b: #34D399; --accent-ink: #047857; }
.lab-entry-yellow, .lab-entry-green, .lab-entry-blue, .lab-entry-pink, .lab-entry-emerald {
  background:
    radial-gradient(120% 130% at 100% 100%, color-mix(in srgb, var(--accent-b) 22%, transparent) 0%, transparent 45%),
    var(--bg);
  margin-inline: -24px;
  padding-inline: 24px;
  border-radius: 3px;
}
/* The :first-child rule above zeroes padding-top for a flush start against a plain
   background — restore it here so a tinted first card gets the same breathing
   room above its eyebrow as every other (non-first) tinted card. */
.lab-entry-yellow:first-child,
.lab-entry-green:first-child,
.lab-entry-blue:first-child,
.lab-entry-pink:first-child,
.lab-entry-emerald:first-child {
  padding-top: clamp(28px, 4vw, 44px);
}
.lab-entry-yellow .eyebrow,
.lab-entry-green .eyebrow,
.lab-entry-blue .eyebrow,
.lab-entry-pink .eyebrow,
.lab-entry-emerald .eyebrow {
  color: var(--accent-ink);
}
.lab-entry-yellow .lab-open,
.lab-entry-green .lab-open,
.lab-entry-blue .lab-open,
.lab-entry-pink .lab-open,
.lab-entry-emerald .lab-open {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
}
@media (max-width: 680px) {
  .lab-entry-yellow, .lab-entry-green, .lab-entry-blue, .lab-entry-pink, .lab-entry-emerald { margin-inline: -16px; padding-inline: 16px; }
}

.lab-block p strong { color: var(--ink); font-weight: 500; }
.lab-block p code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  color: var(--ink);
  word-break: break-word;
}

/* The dataset reuses the .lab-entry / .lab-block treatment; its rail carries a small
   "records" glyph instead of a lab number. */
.lab-num svg { display: block; }

/* ============================================================
   Signal Line (/labs/signal-line) — MCP server landing page.
   Reuses .lab-entry/.lab-block/.eyebrow for the page's section
   rhythm and .dt-table for the recent-calls feed; only genuinely
   new components (cards, video placeholder, connect block) get
   their own .sl- classes.
   ============================================================ */

/* ---- tool/resource/prompt cards ---- */
.sl-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  margin-top: 4px;
  border-top: 1px solid var(--line-soft);
  border-left: 1px solid var(--line-soft);
}
.sl-card {
  background: var(--bg);
  border-right: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sl-card-kind {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.sl-card-name {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.sl-card .sl-card-desc {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: none;
  min-height: calc(1.55em * 3);   /* fixed reservation (not flex-grow) so .sl-card-foot starts at the same Y on every card, independent of row-stretch from taller siblings */
}
.sl-card-uri {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  word-break: break-all;
}
/* Anchors params/URI/empty-state to a common baseline across cards in the same
   grid row, regardless of how much description text sits above it. */
.sl-card-foot {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
}
.sl-params { display: flex; flex-direction: column; gap: 10px; }
.sl-param {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12.5px;
  line-height: 1.5;
  padding-top: 10px;
}
.sl-param:first-child { padding-top: 0; }
.sl-param + .sl-param { border-top: 1px solid var(--line-soft); }
.sl-param-head {
  display: grid;
  grid-template-columns: minmax(88px, auto) minmax(56px, auto) auto;
  align-items: baseline;
  column-gap: 10px;
}
.sl-param-name {
  font-family: var(--font-mono);
  color: var(--ink);
  font-size: 12.5px;
}
.sl-param-type {
  font-family: var(--font-mono);
  color: var(--ink-faint);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.sl-param-req {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 1px 6px;
  justify-self: start;
}
.sl-param-enum,
.sl-param-desc {
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--ink-muted);
}
.sl-param-none {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink-faint);
  font-style: italic;
}
.sl-empty {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--ink-faint);
  font-style: italic;
}

/* ---- connection block ---- */
.sl-connect {
  border: 1px solid var(--line);
  display: flex;
  flex-direction: column;
}
.sl-connect-row {
  display: flex;
  gap: 16px;
  align-items: baseline;
  padding: 12px 16px;
  font-family: var(--font-mono);
  font-size: 13px;
}
.sl-connect-row + .sl-connect-row { border-top: 1px solid var(--line-soft); }
.sl-connect-label {
  flex: 0 0 84px;
  color: var(--ink-faint);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-top: 2px;
}
.sl-connect-row code {
  color: var(--ink);
  word-break: break-all;
}
.sl-code {
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink);
  background: #FAFAFA;
  border: 1px solid var(--line-soft);
  padding: 16px 18px;
  margin-top: 12px;
  overflow-x: auto;
  white-space: pre;
}
.sl-demo-token {
  border: 1px solid var(--line);
  padding: 16px 18px;
}
.sl-demo-token p {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-muted);
  max-width: none;
}
.lab-block p.sl-auth-note {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-faint);
  max-width: none;
}

/* ---- recent-calls feed ---- */
.sl-feed-scroll { max-height: 50vh; }
/* The recent-calls feed renders tool-call arguments — the same thing the Proving
   Ground's bout transcript shows — so it reuses .pg-chat-action-json (and the shared
   .pg-json-key/.pg-json-string colouring) rather than defining a second JSON block
   that would then have to be kept in visual sync. Restyle that one, and this follows.
   Only the context differs: there's no right-aligned chat bubble to hang off here, so
   drop the shrink-to-fit and the chat margins, and hold the table column to a fixed
   width instead. */
.sl-feed-json {
  display: block;
  width: 320px;
  margin: 0;
}
@media (max-width: 680px) {
  .sl-feed-json { width: 220px; }
}

/* ============================================================
   Monday Brief (/labs/monday-brief) — agentic brief generation.
   ============================================================ */
.mb-form {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}
/* Segment picker grows to fill the row; Generate stays a fixed-size button
   at the end, so the two together read as one full-width control. */
.mb-form .lp-menu { flex: 1 1 auto; min-width: 220px; }
.mb-form .lp-menu-trigger { width: 100%; justify-content: space-between; }
.mb-form .lp-menu-panel { width: 100%; min-width: 0; max-width: none; }
.mb-trigger-label { display: inline-flex; align-items: center; gap: 7px; }
.mb-form .lp-menu-trigger .lp-step-chevron {
  flex: 0 0 auto;
  color: var(--ink-faint);
  transform: rotate(90deg);
  transition: transform 0.2s;
}
.mb-form .lp-menu-trigger[aria-expanded="true"] .lp-step-chevron { transform: rotate(-90deg); }

.mb-submit {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: 0.03em;
  color: var(--bg);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 9999px;
  padding: 10px 16px;
  cursor: pointer;
  transition: opacity 0.2s;
}
.mb-submit:hover { opacity: 0.85; }

.mb-run-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
/* .lp-answer-star's margin-top: 20px assumes it sits below a block of content
   (its usual context) — reset it here so it sits inline, vertically centered
   next to the status badge instead. */
.mb-run-meta .lp-answer-star { margin-top: 0; }
.mb-run-focus,
.mb-run-usage {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
}
/* Rate-limit / daily-budget notice, shown in place of starting a run. Deliberately
   quiet — a visitor who hits a limit is usually interested rather than hostile, so this
   reads as a note, not an error banner (no red, no icon, no alarm). */
.mb-notice {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-faint);
  border-left: 2px solid var(--line);
  padding: 4px 0 4px 16px;
  margin-bottom: clamp(20px, 3vw, 32px);
  max-width: 62ch;
}

/* Rendered brief output (Redcarpet HTML) — typography ported from Listening Post's
   .lp-answer-card so the two AI-generated report surfaces on the site read consistently. */
.mb-brief {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink);
  border: 1px solid var(--line-soft);
  background: #FAFAFA;
  padding: 18px 20px;
  margin: 0 0 20px;
}
.mb-brief p { margin: 0; max-width: none; }
.mb-brief p + *,
.mb-brief ul + *,
.mb-brief ol + *,
.mb-brief table + * { margin-top: 16px; }
.mb-brief h1,
.mb-brief h2,
.mb-brief h3 {
  font-family: var(--font-sans);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.mb-brief h1 { font-size: 19px; margin: 22px 0 10px; }
.mb-brief h2 { font-size: 16.5px; margin: 20px 0 8px; }
.mb-brief h3 { font-size: 14.5px; margin: 18px 0 6px; }
.mb-brief > :first-child { margin-top: 0; }
.mb-brief strong { font-weight: 600; }
.mb-brief em { font-style: italic; }
.mb-brief hr {
  border: none;
  border-top: 1px solid var(--line);
  margin: 20px 0;
}
.mb-brief ul,
.mb-brief ol { margin: 12px 0; padding-left: 22px; }
.mb-brief ul { list-style: disc; }
.mb-brief ol { list-style: decimal; }
.mb-brief li { margin: 5px 0; padding-left: 4px; }
.mb-brief li::marker { color: var(--ink-faint); }

/* markdown tables — monochrome, mono type, hairline cell rules, matching .dt-table.
   No wrapper div (Redcarpet emits a bare <table>), so the table itself scrolls. */
.mb-brief table {
  display: block;
  overflow-x: auto;
  border-collapse: collapse;
  width: 100%;
  margin: 18px 0;
  border: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink);
}
.mb-brief th,
.mb-brief td {
  border-right: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  padding: 8px 12px;
  text-align: left;
  vertical-align: top;
}
.mb-brief th:last-child,
.mb-brief td:last-child { border-right: none; }
.mb-brief tbody tr:last-child td { border-bottom: none; }
.mb-brief thead th {
  font-weight: 500;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.mb-brief tbody tr:nth-child(even) td { background: rgba(0, 0, 0, 0.018); }

/* live trace — one row per tool call, appended in real time via Turbo Streams */
.mb-trace-event {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  font-size: 12.5px;
  padding: 8px 0;
}
.mb-trace-event + .mb-trace-event,
.mb-trace-observation + .mb-trace-event { border-top: 1px solid var(--line-soft); }
.mb-trace-tool {
  font-family: var(--font-mono);
  color: var(--ink);
  flex: 0 0 auto;
}
.mb-trace-input {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-faint);
  word-break: break-word;
}
.mb-trace-thought {
  display: block;
  font-family: var(--font-sans);
  font-style: italic;
  color: var(--ink-muted);
}
/* action rows double as the disclosure trigger for their observation row —
   reset button chrome so it reads identically to the old plain div */
.mb-trace-action {
  width: 100%;
  border: none;
  background: none;
  padding: 8px 0;
  margin: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  font-weight: 500;
  transition: color 0.2s;
}
.mb-trace-action:hover { color: var(--ink); }
.mb-trace-action .lp-step-chevron { margin-left: auto; }
.mb-trace-action[aria-expanded="true"] .lp-step-chevron { transform: rotate(90deg); }

/* collapsed by default — max-height transition, not `hidden`, so it animates.
   This element carries no padding of its own (unlike the old .mb-trace-event-based
   version) so max-height: 0 actually clips to zero height; visual padding lives on
   .mb-trace-observation-inner instead. */
.mb-trace-observation {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.mb-trace-observation-inner {
  display: block;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-faint);
  padding: 8px 0 8px 18px;
}

/* archive — past runs, scheduled or on-demand */
.mb-archive { display: flex; flex-direction: column; }
.mb-archive-item + .mb-archive-item { border-top: 1px solid var(--line-soft); }
.mb-archive-link {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 4px;
  text-decoration: none;
  transition: background 0.15s;
}
.mb-archive-link:hover { background: rgba(0, 0, 0, 0.03); }
.mb-archive-focus {
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: var(--ink);
}
.mb-archive-meta {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-faint);
  margin-left: auto;
  white-space: nowrap;
}
@media (max-width: 680px) {
  .mb-archive-link { row-gap: 4px; }
  .mb-archive-meta { margin-left: 0; flex-basis: 100%; }
}
/* filled treatment for statuses that need a second look — weight, not colour */
.dt-tag--alert {
  color: var(--bg);
  background: var(--ink);
  border-color: var(--ink);
}

/* ============================================================
   Observatory — an instrument-panel treatment (bordered cards,
   one shared sticky toolbar driving both the WebGL map and the
   cluster-explorer lanes), inspired by product analytics UIs
   like Intercom's Topics Explorer, adapted to this site's own
   restraint. All white — the toolbar/legend strip pins under
   the site header (62px + 1px border = 63px) as you scroll.
   ============================================================ */
.obs-toolbar-sticky {
  /* Same pink accent already assigned to this page's /labs and homepage
     cards (see .lab-entry-pink / .labs-cell-pink) — declared here (and on
     .obs-card / .obs-drawer) since those classes aren't in this markup. */
  --accent-b: #EC4899;
  --accent-ink: #9D174D;
  position: sticky;
  top: 63px;              /* directly under header.cx-header (z-index 50) */
  z-index: 40;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.obs-card {
  --accent-b: #EC4899;
  --accent-ink: #9D174D;
  position: relative;
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
}
.obs-hint {
  margin-top: 6px;
  margin-bottom: 18px;
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: var(--ink-faint);
}
.obs-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
  padding: 14px 0 10px;
}
.obs-control { display: flex; flex-direction: column; gap: 6px; }
.obs-control-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.obs-select {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 8px 12px;
  cursor: pointer;
}
.obs-slider-row { display: flex; align-items: center; gap: 12px; }
.obs-slider { width: 200px; accent-color: var(--accent-ink, var(--ink)); }
.obs-slider-label {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink-muted);
  white-space: nowrap;
  min-width: 9ch;
}
.obs-toolbar-count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink-faint);
  white-space: nowrap;
}
.obs-toolbar-count span { color: var(--ink); font-weight: 500; }

/* ── the cluster map: clusters positioned by semantic proximity (their
   UMAP centroid), reusing the exact box visual language from the Cluster
   Explorer below (.obs-box: same shading system, same shape, same type)
   rather than a separate visual system — a WebGL point-cloud scatterplot
   used to render here (colourful, ~300 individual points) but read as
   visually disconnected from the rest of the monochrome-pink page. Plain
   absolutely-positioned DOM nodes; no WebGL, no canvas. ── */
.obs-constellation {
  position: relative;
  width: 100%;
  height: clamp(480px, 52vw, 640px);
  background: var(--line-soft);
  overflow: hidden;
}
.obs-box.obs-node {
  position: absolute;
  transform: translate(-50%, -50%);
  padding: 8px 10px;
  gap: 0;
}
/* A smaller, distinct size scale from the box grid's: ~19 nodes scattered
   freely across one canvas (rather than flowing in a wrapped grid) need to
   stay compact to leave room for UMAP's actual spacing to read — the grid's
   up-to-336px boxes packed this densely would overlap regardless of how
   much separation the layout pass applies. Higher specificity (two classes)
   wins over the shared `.obs-box[data-box-size]` grid rules. */
.obs-box.obs-node[data-box-size="xl"] { width: 210px; min-height: 30px; }
.obs-box.obs-node[data-box-size="l"]  { width: 170px; min-height: 30px; }
.obs-box.obs-node[data-box-size="m"]  { width: 140px; min-height: 30px; }
.obs-box.obs-node[data-box-size="s"]  { width: 118px; min-height: 30px; }
.obs-box.obs-node[data-box-size="xs"] { width: 96px; min-height: 30px; }
/* Overrides the grid's 44px name reservation — nodes are far more compact
   (see widths above) and don't need it; their own name text is already
   pre-truncated to fit by truncateNames() in JS. */
.obs-box.obs-node .obs-box-name { min-height: 0; }

/* One drawer for both visualizations — fixed to the viewport's right edge,
   under the sticky header (63px) and above the sticky toolbar (z 40) but
   below the site header (z 50). Lives as a direct child of <main>: inside a
   card it would be clipped by overflow: hidden, and any transformed or
   filtered ancestor would re-anchor the fixed positioning. */
.obs-drawer {
  --accent-b: #EC4899;
  --accent-ink: #9D174D;
  position: fixed;
  top: 63px;
  right: 0;
  /* Stop above the fixed site footer (its measured height lands in --footer-h
     on body, set by application.js) instead of covering it. */
  bottom: var(--footer-h, 92px);
  z-index: 45;
  width: min(380px, 90vw);
  background: var(--bg);
  border-left: 1px solid var(--line);
  padding: 22px 22px 20px;
  transform: translateX(100%);
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  overflow-y: auto;
}
.obs-drawer.is-open { transform: translateX(0); }
.obs-drawer-close {
  position: absolute;
  top: 12px;
  right: 14px;
  font-size: 20px;
  line-height: 1;
  color: var(--ink-faint);
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
}
.obs-drawer-close:hover { color: var(--ink); }
.obs-drawer-eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-ink, var(--ink));
  margin-top: 4px;
}
.obs-drawer-title {
  font-family: var(--font-sans);
  font-size: 18px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
  margin-top: 8px;
  padding-right: 18px;
}
.obs-panel-customer {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.03em;
  color: var(--accent-ink, var(--ink));
  padding-right: 18px;
}
.obs-panel-customer[hidden] { display: none; }
.obs-panel-body {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
  margin-top: 8px;
  padding-right: 18px;
}
.obs-panel-meta {
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
}
/* Verbatim detail meta — one labelled pill per field (segment/theme/
   sentiment/source/date) instead of a flat "·"-joined sentence, so each
   value's meaning is legible at a glance rather than inferred from position. */
.obs-meta-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 8px;
  margin-top: 10px;
}
.obs-meta-pill {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px 10px;
}
.obs-meta-pill-label {
  font-size: 9.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.obs-panel-ask { margin-top: 16px; }

/* Lives inside the sticky strip (which carries the background and bottom
   border) — swatches only, kept compact so the pinned bar stays slim. */
.obs-legend-swatches {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  padding: 0 0 12px;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink-muted);
}
.obs-swatch { display: inline-flex; align-items: center; gap: 6px; }
.obs-swatch i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

/* This entry collapses to a single column (number stacked above content,
   same technique already used at the mobile breakpoint) so the Cluster
   Explorer gets the whole .wrap width instead of just the content column. */
.lab-entry.obs-full-width { grid-template-columns: 1fr; gap: 12px; }

/* ---- Cluster Explorer: one full-width lane per cluster, real verbatim dots ---- */
/* Mirrors .obs-lane's own grid exactly (same fixed column width, same gap,
   same horizontal padding) so the tick positions and each lane's dot
   positions share one coordinate space — they used to be laid out in two
   differently-sized containers (this spanned the full card; each lane's
   strip only got the width left over after its label column), so "20 July"
   lined up with the card's edge while the actual rightmost dots fell well
   short of it. */
.obs-axis {
  display: grid;
  grid-template-columns: 460px 1fr 90px;
  gap: 20px;
  padding: 4px 20px 0;
  height: 20px;
}
.obs-axis-ticks { position: relative; }
.obs-axis-tick {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-faint);
  white-space: nowrap;
}

.obs-lanes { background: var(--bg); }
.obs-lane {
  display: grid;
  grid-template-columns: 460px 1fr 90px;
  align-items: stretch;
  gap: 20px;
  padding: 12px 20px;
  border-top: 1px solid var(--line-soft);
  cursor: pointer;
  transition: background 0.15s;
}
.obs-lane:hover { background: color-mix(in srgb, var(--ink) 3%, var(--bg)); }
/* The author display:grid above would beat the UA's [hidden] rule — make
   the empty-cluster hiding explicit. */
.obs-lane[hidden] { display: none; }
.obs-lane-label { display: flex; flex-direction: column; justify-content: center; gap: 4px; }
/* Coloured by the same size rank as its box in the Cluster Explorer's box
   grid above (--text-tint, set per-lane in JS by applySizeShading() — same
   function, same rank, a wider mix-with-ink range since this mixes into
   heading text rather than a background fill) — ties the two views'
   reading of "how big is this cluster" together at a glance. */
.obs-lane-name {
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.35;
  color: color-mix(in srgb, #9D174D var(--text-tint, 45%), var(--ink));
  white-space: nowrap;   /* the label column is sized to fit the longest real cluster name on one line */
}
.obs-lane-count {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
}
.obs-lane-dominant {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  margin-top: 2px;
}
.obs-lane-dominant[hidden] { display: none; }
/* Trend-in-words + a truncated pull from the cluster's existing AI summary —
   set via updateTrendLabels() in JS, empty (and so invisible, :empty above)
   until the controller connects. */
.obs-lane-summary {
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-faint);
  margin: 4px 0 0;
}
.obs-lane-summary:empty { display: none; }
.obs-lane-strip {
  position: relative;
  min-height: 56px;
}
/* The visible mark stays a small 8px dot, but the clickable/hoverable hit
   area is a larger 22px invisible box around it (skill floor: ~24px) — an
   8px-only hit target is unreliable to click precisely. */
.obs-dot {
  position: absolute;
  width: 22px;
  height: 22px;
  transform: translate(-50%, -50%);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.obs-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--dot-colour, #999);
  opacity: 0.85;
  transition: transform 0.12s, opacity 0.12s;
}
.obs-dot:hover::before { transform: scale(1.6); opacity: 1; }
.obs-lane-trend { display: flex; align-items: center; justify-content: flex-end; }
@media (max-width: 640px) {
  .obs-axis { grid-template-columns: 1fr; }
  .obs-axis-ticks { display: none; }   /* no fixed label column to align against once lanes stack */
  .obs-lane { grid-template-columns: 1fr; gap: 6px; }
  .obs-lane-name { white-space: normal; }   /* a 460px single-line name doesn't fit once the column drops to full-width-stacked */
  .obs-lane-strip { min-height: 44px; }
  .obs-lane-trend { justify-content: flex-start; }
}

/* ── cluster size boxes: an "at a glance" companion to the swimlanes below,
   area proportional to verbatim count (sqrt-scaled, not a packed treemap —
   see renderClusterBoxes()/boxSizeClass() in observatory_controller.js),
   shaded — one hue, the same pink used for this page's eyebrow — from
   darkest (the biggest cluster) to lightest (the smallest), a relative rank
   set per-box via the --box-tint custom property in JS rather than a fixed
   sentiment-coloured fill, so the boxes read as one size-ranked family
   rather than competing with the page's actual sentiment encoding
   (negative/neutral/positive, used everywhere else — map, legend, dots). ── */
.obs-boxes-hint { margin-top: 14px; margin-bottom: 0; padding: 0 20px; }
.obs-boxes {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 4px;
  padding: 20px;
  background: var(--line-soft);
}
.obs-box {
  --box-hue: #9D174D;   /* matches .eyebrow-pink */
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 10px;
  background: color-mix(in srgb, var(--box-hue) var(--box-tint, 10%), var(--bg));
  border: none;
  border-radius: 0;
  padding: 14px 16px;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  transition: filter 0.12s;
}
.obs-box:hover { filter: brightness(0.97); }
.obs-box[hidden] { display: none; }
/* Fixed to exactly 2 lines' worth of height so the stats row below always
   lands at the same vertical offset across every box, regardless of bucket
   — a 1-line name and a 2-line name otherwise pushed the count/negative%/
   trend chip to different heights. The text itself is pre-truncated to fit
   in JS (truncateNames() in the controller, per-bucket character budgets) —
   CSS -webkit-line-clamp was tried here first but proved unreliable at
   narrow bucket widths (a long name would still render a 3rd line instead
   of clipping, growing that one box taller than same-bucket siblings —
   exactly this misalignment bug). overflow:hidden stays only as a safety
   net. A fixed pixel value (not em) deliberately, sized for the largest
   bucket's font (xl, 16px: 16 × 1.35 × 2 ≈ 43px) — an em value scales with
   each bucket's own font-size, so two *different*-size boxes sharing a
   flex-wrap row (common: boxes pack by width, not by bucket) would still
   end up with different-height name blocks. */
.obs-box-name {
  font-family: var(--font-sans);
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
  min-height: 44px;
  overflow: hidden;
}
/* Always three stacked lines (count, negative%, trend pill) rather than a
   flex-wrap row — at narrower bucket widths the row wrapped inconsistently
   (sometimes the pill shared a line with "X% negative", sometimes it wrapped
   onto its own 3rd line), so the pill landed at a different vertical offset
   in different boxes even within the same visual row. A fixed one-item-per-
   line structure makes that offset identical for every box regardless of
   its bucket. */
.obs-box-stats { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.obs-box-count, .obs-box-neg {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  white-space: nowrap;
}
/* width communicates rank/size; min-height (not height) gives longer names
   or a wrapped stats row room to grow rather than clipping — a fixed height
   here previously cut off the negative% and trend chip on smaller boxes. */
.obs-box[data-box-size="xl"] { width: 336px; min-height: 136px; }
.obs-box[data-box-size="l"]  { width: 232px; min-height: 130px; }
.obs-box[data-box-size="m"]  { width: 180px; min-height: 116px; }
.obs-box[data-box-size="s"]  { width: 148px; min-height: 100px; }
.obs-box[data-box-size="xs"] { width: 116px; min-height: 84px; }
.obs-box[data-box-size="xl"] .obs-box-name { font-size: 16px; }
.obs-box[data-box-size="l"]  .obs-box-name { font-size: 15px; }
.obs-box[data-box-size="m"]  .obs-box-name { font-size: 13.5px; }
.obs-box[data-box-size="s"]  .obs-box-name { font-size: 12.5px; }
.obs-box[data-box-size="xs"] .obs-box-name { font-size: 11.5px; }
.obs-box[data-box-size="xs"] .obs-box-stats { display: none; }
@media (max-width: 640px) {
  .obs-boxes { gap: 3px; padding: 14px; }
  .obs-box[data-box-size] { width: calc(50% - 2px) !important; }
}

/* ── trend chip: shared by boxes, lanes, and the drawer. Volume direction,
   not sentiment — deliberately neutral ink tones rather than red/green so
   it never reads as a second, competing sentiment encoding. ── */
.obs-trend {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  padding: 1px 7px;
  border-radius: 10px;
  border: 1px solid var(--line);
  white-space: nowrap;
  color: var(--ink-faint);
}
/* visibility (not display: none) — an empty chip still reserves its line's
   height, so a cluster with no computable trend doesn't end up one line
   shorter than its row siblings and throw off the same alignment this
   whole trend-chip/stats layout exists to guarantee. */
.obs-trend:empty { visibility: hidden; }
.obs-trend[data-direction="up"] { color: var(--ink); border-color: var(--ink-faint); }
.obs-trend[data-direction="new"] { font-style: italic; }


/* ============================================================
   The Proving Ground (/labs/proving-ground) — agent-eval matrix
   + bout detail. Reuses .lp-page/.lp-head/.lp-title/.lp-subtitle,
   .eyebrow, .lab-block-label, .dt-table/.dt-scroll, and .sl-empty
   for section rhythm and tables; only genuinely new components
   (verdict cells/chips, transcript turns, persona card) get their
   own .pg- classes.
   ============================================================ */

/* Screen-reader-only. Scoped to pg- rather than claiming a generic utility name
   in a stylesheet every page of the site loads. */
.pg-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Section rhythm — a hairline rule and generous top space per section, matching
   the Observatory's and Monday Brief's treatment of the same shape. */
.pg-sec {
  margin-top: clamp(56px, 6vw, 72px);
  border-top: 1px solid var(--line);
  padding-top: clamp(24px, 3vw, 32px);
}
.pg-sec-lead { margin-top: 0; border-top: none; padding-top: 0; }

/* In-page anchor nav — plain mono links, same wayfinding tone as the
   eyebrow/lab-block-label mono voice elsewhere on the page. No sticky
   positioning, consistent with the site's minimal chrome. */
.pg-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px clamp(16px, 2.5vw, 28px);
  margin: clamp(24px, 3vw, 32px) 0 clamp(40px, 5vw, 56px);
  padding-top: 18px;
  border-top: 1px solid var(--line-soft);
}
.pg-nav a {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-decoration: none;
}
.pg-nav a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* ---- 01 · explanatory prose ---- */
/* Runs the full width of the wrap rather than sitting in a narrow measure —
   the section heading and hint above it already span the container, and a
   short column under them read as unfinished. */
.pg-plain p {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.72;
  color: var(--ink-muted);
  margin: 16px 0 0;
}
.pg-plain p:first-child { margin-top: 4px; }
.pg-plain code { font-family: var(--font-mono); font-size: 0.86em; color: var(--ink); }

/* The five steps. Numbered markers are used here and nowhere else on the page,
   because this is the one part of the content that genuinely is a sequence —
   five things that happen in that order, every time. */
/* auto-fit rather than a hardcoded column count, so adding or removing a step
   doesn't mean editing the grid and three media queries to match. */
.pg-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  list-style: none;
  margin: 0;
  padding: 0;
}
.pg-steps-label { margin-top: clamp(30px, 4vw, 40px); }

/* The agent's three tools, as a numbered list — <ol> supplies the numerals, so
   they can't drift out of step with the prose the way hand-typed ones do.
   list-style has to be set back explicitly: Tailwind's Preflight strips it from
   every ol/ul, so a bare <ol> renders unnumbered. */
.pg-tool-list {
  list-style: decimal;
  margin: 12px 0 0;
  padding-left: 26px;
  max-width: 70ch;
}
.pg-tool-list::marker { color: var(--ink-faint); }
.pg-tool-list li {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.72;
  color: var(--ink-muted);
}

/* Full width, matching .pg-plain and the table it introduces — a short column
   under a full-width label reads as unfinished. */
.pg-sees-lead {
  font-family: var(--font-sans);
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--ink-muted);
  margin: 0 0 16px;
}
.pg-sees-lead code { font-family: var(--font-mono); font-size: 0.87em; color: var(--ink); }
.pg-step { background: var(--bg); padding: 18px 18px 20px; }
.pg-step-n {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  padding-bottom: 10px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--line-soft);
}
.pg-step h3 {
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 400;
  color: var(--ink);
  line-height: 1.4;
  margin: 0 0 8px;
}
.pg-step p { font-family: var(--font-sans); font-size: 13.5px; line-height: 1.6; color: var(--ink-faint); }
.pg-step p b { color: var(--ink); font-weight: 500; }
.pg-steps-foot {
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--ink-faint);
  margin: 14px 0 0;
}
/* The hand-off down to §07. Needs to read as a door at this size and weight —
   inheriting the muted grey made it invisible against the sentence around it. */
.pg-steps-foot a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line);
}
.pg-steps-foot a:hover { text-decoration-color: var(--ink); }

/* Who-can-see-what. The asymmetry is the single fact the rest of the page
   depends on, so it gets a table rather than a paragraph — the agent's column
   is the only one with gaps in it, and that reads in about two seconds. */
.pg-sees-wrap { overflow-x: auto; margin-top: 12px; }
.pg-sees { border-collapse: collapse; width: 100%; min-width: 560px; }
.pg-sees th,
.pg-sees td {
  border-bottom: 1px solid var(--line-soft);
  padding: 12px 14px;
  text-align: center;
}
.pg-sees thead th {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  font-weight: 400;
  color: var(--ink);
  border-bottom: 1px solid var(--line);
  vertical-align: bottom;
}
.pg-sees thead th small {
  display: block;
  font-family: var(--font-sans);
  font-size: 11.5px;
  letter-spacing: 0;
  color: var(--ink-faint);
  margin-top: 3px;
}
.pg-sees th.rowh {
  text-align: left;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 400;
  color: var(--ink-muted);
  width: 34%;
}
.pg-sees tbody tr:last-child th,
.pg-sees tbody tr:last-child td { border-bottom: 0; }
/* Same pill component as .pg-cell — a yes/no here is the same kind of fact as a
   pass/fail, so it gets the same shape and palette. */
.pg-mk {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 3px 11px;
  border-radius: 9999px;
  white-space: nowrap;
}
.pg-mk-y { background: #DCFFDC; color: #207C36; }
.pg-mk-n { background: #FFDCDC; color: #D3686D; }

/* The asymmetry callout — same emerald-tinted treatment as the bout page's
   hidden-card panel (.pg-persona-hidden), because it's making the same point. */
.pg-asym {
  margin-top: 20px;
  padding: 16px 18px;
  border-radius: 10px;
  border: 1px solid color-mix(in srgb, #047857 30%, var(--line-soft));
  background: color-mix(in srgb, #047857 4%, var(--bg));
}
.pg-asym-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #047857;
  margin-bottom: 8px;
}
.pg-asym p { font-family: var(--font-sans); font-size: 14.5px; line-height: 1.6; color: var(--ink); margin: 0; }

/* Amber variant, for the judge's verbatim instructions. A true yellow-gold rather
   than the site's #9A3412 "yellow" ink, which is dark enough to read as burnt
   orange in a large tinted panel. Kept at 700-level so the label still clears
   contrast on the pale wash behind it. */
.pg-asym-amber {
  border-color: color-mix(in srgb, #A16207 28%, var(--line-soft));
  background: color-mix(in srgb, #EAB308 8%, var(--bg));
}
.pg-asym-amber .pg-asym-label { color: #A16207; }
/* The prompt is quoted source, so it keeps its mono voice inside the callout. */
.pg-asym-amber .pg-system-prompt { margin-top: 0; }

/* Glossary */
.pg-terms {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px clamp(24px, 3vw, 40px);
  margin: 4px 0 0;
}
.pg-term { border-top: 1px solid var(--line-soft); padding-top: 11px; }
.pg-term dt { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink); }
.pg-term dd { font-family: var(--font-sans); font-size: 13.5px; color: var(--ink-faint); line-height: 1.55; margin: 4px 0 0; }

/* ---- 02 · the exhibit ---- */
.pg-exhibit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: clamp(24px, 3vw, 44px);
  margin-top: clamp(26px, 3vw, 34px);
}
.pg-exhibit-main { min-width: 0; }
.pg-exhibit-head {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line-soft);
}
.pg-verdicts { align-self: start; min-width: 0; }
.pg-verdict-note { border-top: 1px solid var(--line); padding-top: 10px; margin-top: 18px; }
/* The first note sits directly under .pg-exhibit-head, which already draws a rule —
   its own top border would stack a second line right beneath that one. */
.pg-exhibit-head + .pg-verdict-note { border-top: 0; padding-top: 0; }
.pg-verdict-note-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
.pg-verdict-note p { font-family: var(--font-sans); font-size: 13px; line-height: 1.55; color: var(--ink-faint); }
.pg-verdict-crit { font-family: var(--font-mono); font-size: 11px; color: var(--ink); }
.pg-verdict-aside {
  border-top: 1px solid var(--line);
  padding-top: 10px;
  margin-top: 20px;
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-muted);
}
.pg-verdict-aside b {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #047857;
  margin-bottom: 6px;
}

/* Verdict marks — "PASS"/"FAIL" text on a pill: pale wash background, deep accent
   text, fully-rounded. One consistent "status pill" component used everywhere a
   pass/fail-shaped fact appears on this page and the bout page. */
.pg-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 9999px;
  text-align: center;
  white-space: nowrap;
}
a.pg-cell { text-decoration: none; }
.pg-cell-pass { background: #DCFFDC; color: #207C36; }
.pg-cell-fail { background: #FFDCDC; color: #D3686D; }

/* ---- doors into a bout ----
   A bout is the page's deepest content and used to be reachable only through two
   near-invisible links. These are the affordances that say so out loud. */

/* The standing invitation under the exhibit: a bordered block, not a faint line of
   mono, because it is the one place a reader is already primed to want the rest. */
.pg-open-cta {
  display: block;
  margin-top: 20px;
  padding: 14px 18px;
  border: 1px solid var(--line);
  border-radius: 8px;
  text-decoration: none;
  transition: border-color 0.15s, background 0.15s;
}
.pg-open-cta:hover { border-color: var(--ink); background: rgba(0,0,0,0.02); }
.pg-open-cta-main {
  display: block;
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink);
}
.pg-open-cta-sub {
  display: block;
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--ink-faint);
  margin-top: 3px;
}

/* The repeated door: one per grid row, one per failed verdict. Underlined at rest —
   these have to read as links at a glance, in a dense table. */
.pg-open-link {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}
.pg-open-link:hover { color: var(--ink); }
.pg-stream-item .pg-open-link { display: inline-block; margin-top: 8px; }

/* ---- 03 · what's being tested ---- */
.pg-method-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(24px, 3vw, 40px);
  margin-top: 6px;
}
.pg-method-grid p {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink-muted);
  margin: 12px 0 0;
}
.pg-method-grid p.pg-caveat { font-size: 13.5px; color: var(--ink-faint); }

.pg-cast-sub { margin-top: clamp(32px, 4vw, 44px); }
.pg-cast-block-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 14px;
}
.pg-cast-item-name {
  display: block;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink);
}
.pg-cast-item-desc {
  display: block;
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: var(--ink-faint);
  margin-top: 3px;
  line-height: 1.5;
}

/* Personas and tools: wrapping card rosters, not tall single-column lists — a
   fixed cast of short entries reads better scanned across than down. */
.pg-persona-grid,
.pg-tool-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  list-style: none;
  margin: 0;
  padding: 0;
}
/* A class, not an inline style: an inline grid-template-columns would outrank the
   media queries below and never collapse on a narrow screen. */
.pg-tool-cards-4 { grid-template-columns: repeat(4, 1fr); }
.pg-persona-card,
.pg-tool-card { background: var(--bg); padding: 16px 18px; }
.pg-persona-card .pg-persona-emoji { display: block; margin-bottom: 6px; font-size: 18px; }
.pg-tool-kb-detail {
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--ink-faint);
  line-height: 1.55;
  margin: 10px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}

.pg-criteria-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px clamp(24px, 3vw, 40px);
  margin: 0;
}
.pg-criteria-item { border-top: 1px solid var(--line-soft); padding-top: 12px; }
.pg-criteria-item dt { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink); }
.pg-criteria-item dd {
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: var(--ink-faint);
  line-height: 1.55;
  margin: 4px 0 0;
}

/* ---- 01 · the result ---- */

/* The one sentence a reader who never scrolls should leave with. Serif, because
   this is the page's anchor statement and the serif is its human voice; the
   emphasis takes the same green .pg-arc-to.is-better already uses for a movement
   in the right direction, so no new colour enters the page. */
.pg-verdict-line {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(24px, 3.2vw, 34px);
  line-height: 1.22;
  letter-spacing: -0.01em;
  margin: 6px 0 0;
}
/* One sentence per line, each wide enough not to wrap on its own — the measure
   has to fit the longer of the two, not the paragraph as a whole. Below that
   width each clause still wraps independently rather than reflowing into one
   run-on block. */
.pg-verdict-line span { display: block; max-width: 42ch; }
.pg-verdict-line b { font-weight: 400; color: #207C36; }
/* Full width of the wrap, not a narrow measure — same reasoning as .pg-plain:
   the stats grid directly below it spans the container, and a short column
   floating above them reads as unfinished. */
.pg-verdict-sub {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-faint);
  margin: 14px 0 clamp(24px, 3vw, 32px);
}

/* ---- 04 · the results ---- */

/* Headline movements. The starting figure is small and grey, the current one is
   large and set in the serif — the page's "human voice" face, used here because
   this is the number a person is meant to take away. */
.pg-arc {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  margin-top: 4px;
}
.pg-arc-stat { background: var(--bg); padding: 18px 20px 20px; }
.pg-arc-label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 12px;
}
.pg-arc-move { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.pg-arc-from {
  font-family: var(--font-mono);
  font-size: 17px;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.pg-arc-arrow { color: var(--ink-faint); font-size: 13px; }
.pg-arc-to {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 34px;
  line-height: 1;
  letter-spacing: -0.015em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.pg-arc-to.is-better { color: #207C36; }
.pg-arc-caption {
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-faint);
  margin: 10px 0 0;
}
.pg-arc-caption b { color: var(--ink); font-weight: 600; }

/* The strip: one row per version, every verdict from its latest run, grouped six
   to a persona so a column position means the same rule in every row. Passes are
   held to a half-strength tint — 144 cells at full wash reads as a field of green
   and buries the thing the chart is about, which is the failures thinning out. */
.pg-strip { margin-top: clamp(30px, 4vw, 40px); }
.pg-strip-head,
.pg-strip-row {
  display: grid;
  grid-template-columns: 132px 1fr 96px;
  gap: 14px;
  align-items: center;
}
.pg-strip-head { padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.pg-strip-row { padding: 9px 0; border-bottom: 1px solid var(--line-soft); }
.pg-strip-cap {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.pg-strip-cap-r { text-align: right; }
.pg-strip-personas,
.pg-strip-groups { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
.pg-strip-personas span { text-align: center; font-size: 13px; line-height: 1; }
/* Each block is a link to that customer's conversation. The hover/focus ring sits on
   the block rather than the square, so it reads as "open this conversation" rather
   than "open this verdict" — and it's a ring, not a colour change, because the fills
   already encode pass/fail and a second colour signal would fight them. */
.pg-strip-group {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 2px;
  padding: 3px;
  margin: -3px;
  border-radius: 6px;
  text-decoration: none;
  transition: background 0.12s, box-shadow 0.12s;
}
a.pg-strip-group:hover {
  background: rgba(0,0,0,0.05);
  box-shadow: 0 0 0 1px var(--line);
}
a.pg-strip-group:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
/* 24px clears the WCAG 2.2 AA minimum target size; the blocks are wide, it was only
   the height that fell short. */
.pg-strip-cell { height: 24px; border-radius: 3px; }
.pg-strip-cell-pass { background: color-mix(in srgb, #DCFFDC 52%, #FFFFFF); }
.pg-strip-cell-fail { background: #FFDCDC; }
.pg-strip-cell-missing { background: repeating-linear-gradient(45deg, var(--line-soft) 0 2px, transparent 2px 4px); }
.pg-strip-name { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink); }
.pg-strip-count {
  font-family: var(--font-mono);
  font-size: 11.5px;
  text-align: right;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.pg-strip-count b { color: #D3686D; font-weight: 500; }
.pg-strip-note {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink-faint);
  margin: 14px 0 0;
  line-height: 1.6;
  max-width: 78ch;
}

/* Per-version panels — a vertical numbered timeline, because these are an ordinal
   history (v1 -> v2 -> v3) with long-form rationale each, and a connecting line
   communicates "iteration" directly. */
.pg-acts { list-style: none; margin: clamp(44px, 5vw, 60px) 0 0; padding: 0; }
.pg-act {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 18px;
  position: relative;
  padding-bottom: clamp(34px, 4vw, 46px);
}
.pg-act:last-child { padding-bottom: 0; }
.pg-act::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 34px;
  bottom: 0;
  width: 1px;
  background: var(--line-soft);
}
.pg-act:last-child::before { display: none; }
.pg-act-marker {
  width: 32px;
  height: 32px;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  background: var(--bg);
  z-index: 1;
}
.pg-act.is-current .pg-act-marker { border-color: var(--ink); color: var(--ink); }
.pg-act-body { min-width: 0; }
.pg-act-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; padding-top: 5px; }
.pg-act-name { font-family: var(--font-mono); font-size: 13.5px; font-weight: 400; color: var(--ink); margin: 0; }
.pg-act-tag {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 9999px;
  padding: 2px 8px;
}
.pg-perf-stats { display: flex; flex-wrap: wrap; gap: 6px 22px; margin-top: 12px; }
.pg-perf-stat { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-faint); }
.pg-perf-stat b { color: var(--ink); font-weight: 500; }
.pg-perf-move { font-weight: 500; }
.pg-perf-move.is-better { color: #207C36; }
.pg-perf-move.is-worse { color: #D3686D; }

/* Full width, matching the rest of the page — a short column inside an otherwise
   full-width panel reads as unfinished. */
.pg-act-rule {
  background: rgba(0,0,0,0.03);
  border-left: 2px solid var(--line);
  padding: 13px 16px;
  margin-top: 16px;
  border-radius: 0 8px 8px 0;
}
.pg-act-rule-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
/* The legend sits inline in the box's label, which is uppercase and letter-spaced —
   both have to be reset or "added / removed" shouts alongside it. */
.pg-act-rule-label .pg-diff-legend {
  margin: 0 0 0 14px;
  text-transform: none;
  letter-spacing: 0.02em;
}

.pg-act-notes { margin-top: 16px; }
.pg-act-notes p {
  font-family: var(--font-sans);
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ink-muted);
  margin: 0;
}
.pg-act-notes p + p,
.pg-act-notes p + ul,
.pg-act-notes ul + p { margin-top: 10px; }
/* list-style has to be set back explicitly — Tailwind's Preflight strips it from
   every ol/ul, so these rendered as unmarked indented lines. Items that carry an
   emoji use it as their marker instead of doubling up with a disc. */
.pg-notes-list { list-style: disc; margin: 10px 0 0; padding: 0 0 0 20px; }
.pg-notes-list li {
  font-family: var(--font-sans);
  font-size: 14.5px;
  color: var(--ink-muted);
  margin: 7px 0;
  line-height: 1.55;
}
.pg-notes-list li::marker { color: var(--ink-faint); }
.pg-notes-list li.has-icon { list-style: none; margin-left: -20px; }
.pg-note-icon { display: inline-block; width: 20px; }
.pg-notes-list li b { color: var(--ink); font-weight: 600; }

/* System-prompt diff — git-style added/removed highlighting versus the previous
   version. Two tones per color: pale for the line background, deep only for
   something sitting ON TOP of that same-hue background (the +/- marker, the
   strikethrough rule). Color is never the only signal — the +/- marker carries the
   same information. */
.pg-diff-legend {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.02em;
  color: var(--ink-faint);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 14px 0 6px;
}
.pg-diff-swatch {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-left: 4px;
}
.pg-diff-swatch-added { background: #207C36; }
.pg-diff-swatch-removed { background: #D3686D; }
.pg-diff-added {
  background: #DCFFDC;
  padding: 4px 6px;
  margin-left: -6px;
  margin-right: -6px;
  border-radius: 3px;
}
.pg-diff-removed {
  background: #FFDCDC;
  color: var(--ink-faint);
  text-decoration: line-through;
  text-decoration-color: #D3686D;
  padding: 4px 6px;
  margin-left: -6px;
  margin-right: -6px;
  border-radius: 3px;
}
.pg-diff-marker { font-weight: 700; text-decoration: none; margin-right: 4px; display: inline-block; }
.pg-diff-added .pg-diff-marker { color: #207C36; }
.pg-diff-removed .pg-diff-marker { color: #D3686D; }

.pg-system-prompt { margin: 8px 0 0; }
.pg-system-prompt p {
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--ink-muted);
  word-break: break-word;
  margin: 0;
}
.pg-system-prompt p + p { margin-top: 12px; }

/* <details> disclosure for reference-only content (full prompts) — same label look
   as everywhere else, just made a focusable/clickable summary. */
.pg-details { margin-top: 24px; }
.pg-details summary { cursor: pointer; list-style: none; }
.pg-details summary::-webkit-details-marker { display: none; }
.pg-details summary::before {
  content: "+";
  display: inline-block;
  width: 1em;
  color: var(--ink-faint);
}
.pg-details[open] summary::before { content: "\2212"; }

/* Criterion lanes. The plot is wide and short and the SVG stretches to fill it
   (preserveAspectRatio="none"), so every stroke uses non-scaling-stroke and the
   point markers are round-capped zero-length lines — a <circle> would render as an
   ellipse. Axis is truncated; LabsHelper#lane_domain guarantees no line can bottom
   out, and the caption prints the range. */
.pg-lanes { margin-top: clamp(30px, 4vw, 40px); }
.pg-lane-axis,
.pg-lane {
  display: grid;
  grid-template-columns: 152px 1fr 168px;
  align-items: center;
  gap: 0 4px;
}
.pg-lane-axis { padding-bottom: 7px; border-bottom: 1px solid var(--line); }
.pg-lane { padding: 4px 0; border-bottom: 1px solid var(--line-soft); }
.pg-lane-cap {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.pg-lane-cap-r { text-align: right; }
.pg-lane-ticks {
  display: flex;
  justify-content: space-between;
  padding: 0 12px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
}
/* overflow-wrap: anywhere because criterion names are single unbroken tokens —
   "no_hallucination" is wider than this column on a phone and would otherwise
   spill over the trend line rather than wrapping. */
.pg-lane-name {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink);
  overflow-wrap: anywhere;
}
/* Clamped to two lines so every lane is the same height and the trend lines stay
   on a common grid — the full rubric text is a couple of sections up, and the
   title attribute carries it here. */
.pg-lane-name span {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--ink-faint);
  margin-top: 2px;
  line-height: 1.4;
}
.pg-lane-plot svg { display: block; width: 100%; height: 46px; }
.pg-lane-area { fill: #207C36; opacity: 0.10; }
.pg-lane-base {
  stroke: rgba(0,0,0,0.22);
  stroke-width: 1;
  stroke-dasharray: 4 4;
  vector-effect: non-scaling-stroke;
}
.pg-lane-line {
  fill: none;
  stroke: #207C36;
  stroke-width: 1.8;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.pg-lane-dot {
  stroke: #207C36;
  stroke-width: 4.5;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  opacity: 0.7;
}
.pg-lane-dot.is-last { stroke-width: 7; opacity: 1; }
.pg-lane.is-down .pg-lane-area { fill: #D3686D; }
.pg-lane.is-down .pg-lane-line,
.pg-lane.is-down .pg-lane-dot { stroke: #D3686D; }
.pg-lane-read { display: flex; align-items: baseline; justify-content: flex-end; gap: 10px; }
.pg-lane-pct { font-family: var(--font-mono); font-size: 15px; font-variant-numeric: tabular-nums; }
.pg-lane.is-down .pg-lane-pct { color: #D3686D; }
.pg-lane-delta {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 9999px;
  white-space: nowrap;
}
.pg-lane-delta-up { background: #DCFFDC; color: #207C36; }
.pg-lane-delta-down { background: #FFDCDC; color: #D3686D; }
.pg-lane-delta-flat { background: rgba(0,0,0,0.05); color: var(--ink-faint); }
.pg-lane-note {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink-faint);
  margin: 14px 0 0;
  line-height: 1.6;
  max-width: 78ch;
}

/* ---- 05 · every verdict ---- */
.pg-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 22px;
  border-bottom: 1px solid var(--line);
  margin-top: 4px;
}
.pg-tabs button {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  padding: 0 0 9px;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  background: none;
  cursor: pointer;
}
.pg-tabs button:hover { color: var(--ink); }
.pg-tabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--ink); }
.pg-tabs button i { font-style: normal; color: var(--ink-faint); }

.pg-grid-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: clamp(24px, 3vw, 40px);
  margin-top: 20px;
}
.pg-matrix-wrap { overflow-x: auto; }
.pg-matrix { border-collapse: collapse; width: 100%; min-width: 520px; }
.pg-matrix thead th {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  font-weight: 400;
  color: var(--ink-faint);
  text-align: center;
  padding: 0 4px 9px;
  white-space: nowrap;
}
.pg-matrix thead th.l { text-align: left; padding-left: 0; }
.pg-matrix tbody th {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  text-align: left;
  color: var(--ink);
  white-space: nowrap;
  padding: 4px 14px 4px 0;
}
.pg-matrix tbody th .pg-persona-emoji { margin-right: 8px; }
/* Underlined at rest, not a hairline: a persona name is a door to that whole
   conversation, and nothing else on the row says so. */
.pg-matrix-link {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 3px;
}
.pg-matrix-link:hover { text-decoration-color: var(--ink); }
.pg-matrix th.pg-matrix-open,
.pg-matrix td.pg-matrix-open { text-align: right; padding-left: 14px; white-space: nowrap; }
.pg-matrix td { padding: 3px 2px; text-align: center; }
/* Each cell links to that row's bout — the same destination as the persona name and the
   trailing "Read →", so these carry tabindex="-1" in the markup rather than adding six
   redundant tab stops per row. */
.pg-matrix-cell { display: block; width: 100%; height: 26px; border-radius: 5px; }
a.pg-matrix-cell { cursor: pointer; transition: box-shadow 0.12s; }
a.pg-matrix-cell:hover { box-shadow: 0 0 0 1px var(--ink); }
.pg-matrix-cell-pass { background: #DCFFDC; }
.pg-matrix-cell-fail { background: #FFDCDC; }
.pg-matrix-cell-missing { background: repeating-linear-gradient(45deg, var(--line-soft) 0 2px, transparent 2px 4px); }
.pg-matrix-legend {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-faint);
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line-soft);
}
.pg-matrix-legend i {
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: 3px;
  vertical-align: -1px;
  margin-right: 6px;
}

.pg-stream { align-self: start; min-width: 0; }
.pg-stream-h {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line);
}
.pg-stream-item { padding: 13px 0; border-bottom: 1px solid var(--line-soft); }
.pg-stream-item-h { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 5px; }
.pg-stream-persona { font-family: var(--font-sans); font-size: 12.5px; color: var(--ink-faint); }
.pg-stream-item p { font-family: var(--font-sans); font-size: 13px; line-height: 1.55; color: var(--ink-muted); }
.pg-stream-empty { font-family: var(--font-sans); font-size: 13px; color: var(--ink-faint); padding: 20px 0; }

/* ---- 06 · still open ---- */
.pg-open { border-top: 1px solid var(--line-soft); margin-top: 6px; }
.pg-open-item {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 18px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line-soft);
  align-items: baseline;
}
.pg-open-item .pg-cell { justify-self: start; }
.pg-open-item p { font-family: var(--font-sans); font-size: 15px; line-height: 1.65; color: var(--ink-muted); }
.pg-open-item p b { color: var(--ink); font-weight: 600; }
/* Full width, matching every other block on the page. */
.pg-closing {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.7;
  font-style: italic;
  color: var(--ink);
  margin-top: 26px;
}

/* ---- responsive ---- */
@media (max-width: 1080px) {
  .pg-grid-split { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1000px) {
  /* .pg-steps is auto-fit and reflows on its own — no override needed */
  .pg-terms { grid-template-columns: repeat(2, 1fr); }
  .pg-arc { grid-template-columns: repeat(2, 1fr); }
  .pg-tool-cards-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 900px) {
  .pg-exhibit,
  .pg-method-grid { grid-template-columns: minmax(0, 1fr); }
  .pg-persona-grid,
  .pg-tool-cards { grid-template-columns: repeat(2, 1fr); }
  .pg-lane-axis,
  .pg-lane { grid-template-columns: 118px 1fr 128px; }
}
@media (max-width: 760px) {
  .pg-strip-head,
  .pg-strip-row { grid-template-columns: 96px 1fr 62px; gap: 10px; }
  .pg-strip-personas { display: none; }
  .pg-strip-groups { gap: 4px; }
}
@media (max-width: 640px) {
  .pg-terms,
  .pg-arc,
  .pg-criteria-grid,
  .pg-persona-grid,
  .pg-tool-cards,
  .pg-tool-cards-4 { grid-template-columns: 1fr; }
  .pg-open-item { grid-template-columns: 1fr; gap: 8px; }
  .pg-lane-axis,
  .pg-lane { grid-template-columns: 96px 1fr 104px; }
  .pg-lane-name span { display: none; }
}


/* ---- bout detail page ---- */
.pg-breadcrumb {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  margin: 0 0 18px;
}
.pg-breadcrumb a { color: var(--ink-faint); text-decoration: underline; text-underline-offset: 2px; }
.pg-breadcrumb a:hover { color: var(--ink); }

/* Same customer, every version — the improvement arc at bout level, and the only
   place on the site that exposes it. Each chip carries that version's failure count
   for this persona, so the trend is legible before you click anything. */
.pg-siblings {
  display: flex;
  align-items: baseline;
  gap: 8px 18px;
  flex-wrap: wrap;
  padding-bottom: 18px;
  margin-bottom: clamp(28px, 3.5vw, 40px);
  border-bottom: 1px solid var(--line-soft);
}
.pg-siblings-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.pg-siblings ul { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.pg-sibling {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-faint);
  text-decoration: none;
  padding: 5px 11px;
  border: 1px solid var(--line-soft);
  border-radius: 9999px;
}
.pg-sibling i { font-style: normal; font-size: 10px; color: var(--ink-faint); }
.pg-sibling:hover { color: var(--ink); border-color: var(--line); }
.pg-sibling.is-current { color: var(--ink); border-color: var(--ink); }

.pg-bout-back {
  margin-top: clamp(28px, 3vw, 36px);
  padding-top: 16px;
  border-top: 1px solid var(--line-soft);
}
.pg-bout-back a {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.pg-bout-back a:hover { color: var(--ink); }
.pg-vs { color: var(--ink-faint); font-style: italic; }

/* ---- persona intro — sets the scene before the verdict/transcript, so a
   reader gets the persona's motive, the hidden facts the agent couldn't see,
   and what a good outcome looks like, before judging the transcript
   themselves. Two-column blocks reuse the same pattern as the show page's
   own two-column blocks, for consistency. */
.pg-persona-intro { margin-top: clamp(24px, 3vw, 32px); margin-bottom: clamp(40px, 5vw, 56px); }
.pg-persona-intro-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 2.5vw, 32px);
  margin-top: 10px;
}
@media (max-width: 680px) {
  .pg-persona-intro-grid { grid-template-columns: 1fr; }
}
.pg-persona-intro-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 6px;
}
.pg-persona-intro-block p,
.pg-persona-hidden li {
  font-family: var(--font-sans);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-muted);
}
.pg-persona-resolves { margin-top: 20px; }

/* the eval's whole asymmetry lives here — the judge sees this, the agent
   never does — so it gets a callout, not a plain paragraph in a sidebar. */
.pg-persona-hidden {
  margin-top: 20px;
  padding: 16px 18px;
  border: 1px solid color-mix(in srgb, #047857 30%, var(--line-soft));
  background: color-mix(in srgb, #047857 4%, var(--bg));
  border-radius: 10px;
}
.pg-persona-hidden-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #047857;
  margin-bottom: 10px;
}
.pg-persona-hidden ul { margin: 0; padding-left: 20px; }
.pg-persona-hidden li { color: var(--ink); margin: 4px 0; }


/* ============================================================
   Shared chat transcript — used by BOTH the bout page and the
   show page's exhibit (section 02). Rendered by the reusable
   _chat_exchange partial (customer_message/tool_calls/agent_reply
   locals, no Proving Ground literals in that file). Bubbles carry
   a "tail" corner sharp on the side nearest the speaker; tool
   calls are borderless icon+text rows, not cards, so they read as
   quiet log lines above the reply.
   ============================================================ */
.pg-chat { display: flex; flex-direction: column; gap: 18px; margin-top: 12px; }
.pg-chat-row { display: flex; flex-direction: column; gap: 6px; max-width: 78%; min-width: 0; }
.pg-chat-row-customer { align-items: flex-start; margin-right: auto; }
.pg-chat-row-agent { align-items: flex-end; margin-left: auto; }
@media (max-width: 680px) {
  .pg-chat-row { max-width: 92%; }
}
.pg-chat-speaker {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 4px;
}
.pg-chat-bubble {
  padding: 14px 16px;
  font-size: 14.5px;
  line-height: 1.6;
  border-radius: 14px;
  border: 1px solid var(--line);
  overflow-wrap: break-word;
  min-width: 0;
}
.pg-chat-bubble-customer {
  background: var(--bg);
  color: var(--ink);
  border-bottom-left-radius: 3px;
  font-family: var(--font-sans);
}
.pg-chat-bubble-agent {
  background: #F4F9FF;
  border-color: #DCE9FB;
  color: var(--ink);
  border-bottom-right-radius: 3px;
  font-family: var(--font-sans);
}
/* Nested markdown (render_markdown) inside the agent bubble — compact version of .mb-brief's rules */
.pg-chat-bubble-agent p { margin: 0; }
.pg-chat-bubble-agent p + p { margin-top: 10px; }
.pg-chat-bubble-agent strong { font-weight: 600; }
.pg-chat-bubble-agent em { font-style: italic; }
.pg-chat-bubble-agent ul,
.pg-chat-bubble-agent ol { margin: 8px 0 0; padding-left: 20px; }
.pg-chat-bubble-agent li { margin: 3px 0; }
.pg-chat-bubble-agent a { color: var(--ink); text-decoration: underline; }

/* Tool-call rows — collapsed-by-default disclosures (same expand pattern as
   Monday Brief's action/observation trace, .mb-trace-action), but borderless:
   icon + muted-gray description + chevron, no card. Stacked right-aligned
   above the reply bubble, under the turn's single "Agent" speaker label. */
.pg-chat-actions { display: flex; flex-direction: column; gap: 2px; width: 100%; min-width: 0; }
/* text-align: right (not flex + justify-content) — .pg-chat-action-item wraps
   both the trigger button AND its collapsed detail panel; making the item a
   flex row put those two side by side, and the detail's hidden-but-still
   horizontally-laid-out width (max-height only collapses the vertical axis)
   ate space and pushed the button left. text-align only affects inline-level
   boxes (the inline-flex button), so the block-level detail panel underneath
   is unaffected and still stacks/expands downward as normal. */
.pg-chat-action-item { text-align: right; width: 100%; min-width: 0; }
.pg-chat-action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 5px 4px;
  border: none;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.pg-action-icon-svg { display: block; color: var(--ink-faint); }
.pg-chat-action-label {
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-faint);
}
.pg-chat-action:hover .pg-chat-action-label,
.pg-chat-action:hover .pg-action-icon-svg { color: var(--ink-muted); }
.pg-chat-action .lp-step-chevron { color: var(--ink-faint); flex: 0 0 auto; transition: transform 0.15s; }
.pg-chat-action[aria-expanded="true"] .lp-step-chevron { transform: rotate(90deg); }

.pg-chat-action-detail {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.pg-chat-action-json {
  /* inline-block (not the <pre> default of block) so the box shrinks to fit
     its own content instead of always stretching the row's full width — a
     one-line {"tool": "check_account"} call shouldn't render as wide as a
     multi-field search query. text-align:right on the ancestor .pg-chat-
     action-item then positions this shrunk box at the right edge, matching
     the trigger button above it. */
  display: inline-block;
  max-width: 100%;
  margin: 4px 4px 6px;
  padding: 10px 12px;
  background: rgba(0,0,0,0.03);
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink-muted);
  text-align: left;
  white-space: pre-wrap;
  word-break: break-word;
  overflow-x: auto;
}
.pg-json-key { color: #1D4ED8; }
.pg-json-string { color: #047857; }

.pg-bout-meta {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line-soft);
}
