/* Signal Line (/labs/signal-line).
   Part of the /labs stylesheet, split out of one 3,400-line labs.css.

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

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

/* ============================================================
   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 (the catalogue list, the connect block and the
   config snippet) get their own .sl- classes.
   ============================================================ */

/* ---- tool/resource/prompt list ----
   ONE COLUMN, AND THE COLUMN COUNT IS THE WHOLE POINT. This was a
   `repeat(auto-fit, minmax(260px, 1fr))` card grid. Five tools do not fill
   three tracks, so the last row carried an empty cell with no right border and
   the ruled frame hung open; row-stretch gave the one-parameter cards 127px of
   dead space while the three-parameter card set the height; and `auto-fit`
   dropped to two fat tracks for the two resources, so one component rendered
   at three widths in a single section.

   `align-items: start` is the reflex fix and it is wrong here: shrinking each
   card to its content staggers the `border-right`/`border-bottom` rules that
   ARE the lattice, trading dead space for a stepped, broken frame. A single
   column removes all three faults by construction — rows are always full, each
   row is its own height, one width — and it scans better for a catalogue of
   callable functions, where every name should sit on one left edge.
   ============================================================ */
.sl-list {
  margin-top: 4px;
  border-top: 1px solid var(--line-soft);
}
.sl-item {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 0 28px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line-soft);
}
.sl-item-name {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 0;
  overflow-wrap: anywhere;
}
/* min-width:0 so a long unbroken URI or enum cannot push the track wider than
   its share and force the whole list into horizontal overflow. */
.sl-item-body { min-width: 0; }

/* TWO CLASSES, DELIBERATELY. `.lab-block p` (0,1,1) beats a single class
   (0,1,0) and would set this back to 16px/64ch — the same specificity trap that
   still renders `.sl-param-none` larger than the name above it. */
.sl-item .sl-item-desc {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-muted);
  max-width: 62ch;
  margin: 0;
}
.sl-item .sl-item-uri {
  margin: 10px 0 0;
  max-width: 62ch;
}
.sl-item-uri code {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  overflow-wrap: anywhere;
}

/* THE PARAMETER TRACKS ARE FIXED, NOT INTRINSIC. They were
   `minmax(88px, auto) minmax(56px, auto) auto` scoped to each parameter's own
   head, so the type label landed at a different x for every row — a 22px ragged
   column inside a single tool. Fixed tracks align every parameter of every tool
   on the page, not just the ones that happen to share a name length. */
.sl-params {
  display: grid;
  grid-template-columns: 160px 92px minmax(0, 1fr);
  column-gap: 18px;
  margin-top: 14px;
  padding-top: 4px;
  border-top: 1px solid var(--line-soft);
}
/* `display: contents` drops the li box so its three children become the grid's
   own items and inherit the shared tracks. The row rule therefore has to be
   drawn on the cells rather than on the li, which no longer generates a box. */
.sl-param { display: contents; }
.sl-param > * { padding: 8px 0; }
.sl-param + .sl-param > * { border-top: 1px solid var(--line-soft); }
.sl-param-name {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.sl-param-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  line-height: 1.5;
}
.sl-param-type {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* No border and no radius. It was a 10px outlined chip with `border-radius: 2px`
   — below the 12px floor, and a radius on something that is not an action or a
   photograph of a person. Weight and the mono face carry it instead. */
.sl-param-req {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
}
.sl-param-note {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  line-height: 1.5;
}
.sl-param-enum,
.sl-param-desc {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink-muted);
}
.sl-param-enum { color: var(--ink-faint); }

/* `.lab-block p` (0,1,1) wins over a lone `.sl-param-none`/`.sl-empty` (0,1,0)
   and was rendering "No parameters." at 16px — larger than the 13px tool name
   above it, and the most prominent text in its own row. The extra class is what
   takes the specificity back. */
.lab-block p.sl-param-none {
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-faint);
  font-style: italic;
  margin-top: 10px;
  max-width: 62ch;
}
.lab-block p.sl-empty,
.sl-empty {
  font-family: var(--font-sans);
  font-size: 15px;
  color: var(--ink-faint);
  font-style: italic;
  max-width: none;
}

/* Below the two-column split the name sits above its own body, and the
   parameter tracks stack: 160px + 92px of fixed columns cannot hold their
   labels once the content column is under about 260px. */
@media (max-width: 680px) {
  .sl-item {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .sl-params { grid-template-columns: 1fr; column-gap: 0; }
  .sl-param > * { padding: 4px 0; }
  .sl-param > .sl-param-name { padding-top: 10px; }
  .sl-param > .sl-param-note:last-child { padding-bottom: 10px; }
  .sl-param + .sl-param > * { border-top: none; }
  .sl-param + .sl-param > .sl-param-name { border-top: 1px solid var(--line-soft); }
}

/* Section 03's two short instructions. `.lab-block p` caps at 64ch already, so
   this only sets the smaller, quieter voice that separates an aside from the
   section's own prose. */
.lab-block p.lab-note {
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-muted);
  margin-top: 12px;
  max-width: 62ch;
}
.lab-note + .sl-code-wrap { margin-top: 12px; }

/* ---- connection block ----
   BOTH OF THESE ARE MEASURED OBJECTS, NOT FULL-WIDTH BANDS. `.sl-connect` ran
   the full 960px column to hold a 265px value, and `.sl-code` ran 958px to hold
   about 44 characters — roughly 700px of empty right side on the page's single
   most important artefact. A box three times wider than its own content reads
   as unfinished rather than as generous. 62ch is wide enough for the longest
   line either one holds. */
.sl-connect {
  border: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  max-width: 62ch;
}
.sl-connect-row {
  display: flex;
  gap: 16px;
  align-items: baseline;
  padding: 12px 16px;
  font-family: var(--font-mono);
  font-size: 13px;
  min-height: 44px;
}
.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: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-top: 2px;
}
.sl-connect-row code {
  color: var(--ink);
  word-break: break-all;
  flex: 1 1 auto;
  min-width: 0;
}

/* ---- copy controls ----
   Rendered `hidden` and unhidden by copy_controller.js only once it has
   confirmed a clipboard API, so an insecure origin or an old browser shows no
   dead control rather than a button that silently does nothing. A pill, because
   the design system reserves a radius for actions and this is one; 44px because
   that floor is unconditional. */
.sl-copy {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  background: transparent;
  border: 1px solid var(--line2);
  border-radius: 9999px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background-color 0.15s;
}
.sl-copy:hover { color: var(--ink); border-color: var(--ink); }
.sl-copy:focus-visible { outline: 2px solid var(--deep); outline-offset: 2px; }
.sl-copy[data-state="done"] {
  color: var(--pass);
  border-color: var(--pass-line);
  background: color-mix(in srgb, var(--pass) 8%, transparent);
}
/* The config block's control floats over the top-right of the snippet rather
   than sitting in the flow: the block is `white-space: pre` and scrolls on its
   own axis, so a sibling in normal flow would either widen it or scroll away. */
/* `ch` IS A PER-FONT UNIT, AND CAPPING TWICE IN TWO FONTS IS THE BUG. The
   wrapper and the `pre` inside it both carried `max-width: 62ch`, but the
   wrapper measures in 16px Inter and the pre in 12px mono — 662px against
   446px. So the config block rendered two-thirds the width of `.sl-connect`
   and `.sl-demo-token`, which are capped at the same 62ch in the same sans
   context and therefore agree with each other, and the float button anchored
   to the wrapper's right edge sat 145px clear of the code it copies.

   ONE CAP, ON THE WRAPPER, IN THE SANS CONTEXT. The pre fills it. That is what
   makes all three blocks in this section one width without any of them naming
   a pixel value or knowing about the others — and a font-size change inside
   the snippet can no longer resize the box around it. */
.sl-code-wrap { position: relative; max-width: 62ch; }
.sl-copy--float {
  position: absolute;
  top: 20px;
  right: 10px;
  z-index: 1;
  background: var(--bg2);
}
.sl-code {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink);
  /* A LITERAL HERE IS INVISIBLE TYPE IN DARK MODE. This was `#FAFAFA`, which
     never flips, while the `color` above it does — so in dark the block was
     near-white ink on a near-white slab at 1.10:1, and every brace, quote,
     colon and comma in the page's single most important artefact vanished. Only
     the coloured keys and strings survived. --bg2 is the themed surface and
     carries --ink at about 15:1 in both directions. */
  background: var(--bg2);
  border: 1px solid var(--line-soft);
  padding: 16px 18px;
  margin-top: 12px;
  /* 100%, not a second 62ch: the cap lives on .sl-code-wrap, which measures it
     in the same font as this section's other two blocks. */
  max-width: 100%;
  overflow-x: auto;
  white-space: pre;
}
.sl-demo-token {
  border: 1px solid var(--line);
  padding: 16px 18px;
  max-width: 62ch;
}
.sl-demo-token p {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-muted);
  max-width: 58ch;
  margin: 0 0 16px;
}
/* 62ch, not none. At `max-width: none` this measured 137 characters a line —
   the widest paragraph on the page, and the one doing the most careful work:
   it is the studio disclosing the limits of its own auth model. 15px rather
   than 14 puts it back on the type scale, and --ink-muted rather than
   --ink-faint stops the most honest paragraph here being the faintest. */
.lab-block p.sl-auth-note {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-muted);
  max-width: 62ch;
}

/* ---- recent-calls feed ----
   NO max-height. It was 50vh against 613px of content, so the frame clipped
   195px THROUGH the fourth row, behind a 2px scrollbar with no fade — which
   reads as a rendering fault rather than as more content, and it was the last
   thing on the page before the footer. Rather than tune the clip to land on a
   row boundary (a number that breaks the moment a row's height changes), the
   controller now returns a number of rows that fits, and the frame shows all of
   them. The horizontal scroller is untouched: the table is genuinely wider than
   a phone, which is what .dt-scroll is for. */
/* 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 {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink-muted);
  white-space: nowrap;
}
/* The age line is the section's actual claim, so it is set as copy rather than
   as a caption, and the flag only appears when the newest call is over a week
   old — a live feed says nothing, a quiet one says so plainly. */
.sl-feed-age {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-muted);
  max-width: 62ch;
  margin: 0 0 14px;
}
.sl-feed-age-flag {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--part);
  margin-right: 6px;
}
.sl-feed-caption {
  caption-side: top;
  text-align: left;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  padding: 10px 14px;
  border-bottom: 1px solid var(--line-soft);
}
/* FULL COLUMN, NOT THE PROSE MEASURE. This one sits under the table as its
   footnote, so it belongs to the table's width rather than to the 62ch measure
   the section's body copy uses — capped, it broke a single sentence over three
   short lines beneath a 958px object. */
.lab-block p.sl-feed-note {
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-faint);
  max-width: none;
  margin-top: 12px;
}
.sl-feed-note code {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-muted);
}
/* A focusable scroll region needs a visible focus ring, or the keyboard route
   that was just opened is invisible to the person using it. */
.sl-feed-scroll:focus-visible { outline: 2px solid var(--deep); outline-offset: 2px; }
