/* /api: the drop-in card, the SSE sample, the price block and the reference
   tables. Tokens: site.css only. Every length is a --sp-* / --fs-* / --lh-* /
   --r-* / --target / --measure token, every colour a named surface (--bg,
   --card, --line, --raised, --fg, --secondary, --muted) or the one accent
   (--accent). No hex literal lives here. Two radii are in use: --r-control
   (tabs, code boxes, controls) and --r-surface (the card). The only lengths
   not drawn from a token are hairline border widths. Everything is scoped
   under .api so no rule below can move /benchmarks or /relay. */

/* ---- the hero: picked mockup v3 "Key card" (.tmp/mockups/api-page-hero-20261021-2033) ----
   Look plan (design/SKILL.md step 5):
   - Palette: the site.css ladder only. --bg the page, --fg the headline and the key, --muted the second ink, --card the
     key card and the drop-in card, --line the hairline.
   - Accent: the one existing CTA (--cta-*, the .sb-btn fill) on exactly one control, "Get an API key". Links and the
     focus ring wear --accent; the copied check is --accent.
   - Type: --font-ui for the headline and the copy (the h1's display tracking is --tracking-tight, below 0), --font-mono for
     the key and the command rows. Two families.
   - Radius: two. --r-surface on the key card and the drop-in card, --r-control on the key field, the buttons, the tabs, the
     command rows and the skeleton bars.
   - The one bold thing: the key card top right, which fills with the minted sbc_ key.
   Entrance: the page's own sb-reveal, staggered over the three blocks (one orchestrated entrance). */
/* bench.css sizes its h1 as a flex row for the pill badge; this page has no
   badge, so the h1 is a plain block and the site's own text-wrap: balance
   applies to the display line */
.api h1 { display: block; font-size: var(--fs-h1); line-height: 1.1; max-width: var(--measure); }
.api .api-cta { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-6); }
.api .api-cta .sb-btn { font-size: var(--fs-sm); }
/* the press is held while the mint is in flight: the button's own press scale stays down and takes no second press */
.api .api-cta .sb-btn[aria-busy="true"] { transform: scale(var(--press-scale)); pointer-events: none; }

/* two columns from a tablet up: the headline, the buttons and the fine print on the left, the key card above the drop-in
   card on the right (which spans both left rows). One column under it, in reading order: headline and buttons, the cards,
   the fine print. */
.api .api-hero {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  grid-template-rows: auto 1fr;
  grid-template-areas: "copy side" "fine side";
  column-gap: var(--sp-12);
  row-gap: var(--sp-12);
  align-items: start;
}
.api .api-hero-copy { grid-area: copy; min-width: 0; }
.api .api-hero-side { grid-area: side; display: grid; gap: var(--sp-4); min-width: 0; }
.api .api-hero .api-fine { grid-area: fine; margin-top: 0; min-width: 0; }
.api .api-hero .api-drop { margin-top: 0; }
@media (max-width: 900px) {
  .api .api-hero { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; grid-template-areas: "copy" "side" "fine"; row-gap: var(--sp-8); }
}

/* ---- the key card: the page's one bold thing ----
   One card, four states (data-state, set by api-key.js): empty is one sentence (the "Get an API key" button beside it is
   the one action), wait is a skeleton in the shape of the key row and the line under it, done holds the key with one
   copy control and one consequence line, error holds the server's own message and a link to sign up. The card keeps one
   height through all four, so nothing under it moves when it fills. Signed-in visitors get no card: the server draws a
   signed-in viewer's phone tab bar with an account tab at /account/menu (site-nav.ts tabBar), and the button stays the
   link to the console for them. */
.api .api-key {
  display: grid; gap: var(--sp-3); align-content: start;
  min-width: 0;
  min-height: calc(var(--sp-5) * 2 + var(--control-h) + var(--sp-3) + var(--target-sm));
  padding: var(--sp-5) var(--sp-4);
  background: var(--card); border: var(--hairline) solid var(--line); border-radius: var(--r-surface);
}
body:has(a[href$="/account/menu"]) .api .api-key { display: none; }
.api .api-key [hidden] { display: none; }
.api .api-key-field {
  display: flex; align-items: center; gap: var(--sp-2); min-width: 0;
  min-height: var(--control-h); padding: var(--sp-1) var(--sp-2) var(--sp-1) var(--sp-4);
  border: var(--hairline) solid var(--line); border-radius: var(--r-control);
}
.api .api-key[data-state="error"] .api-key-field { border-color: var(--danger-line); }
/* empty: the one sentence sits in a field that fills the card where the key row and its line will be */
.api .api-key[data-state="empty"] .api-key-field { min-height: calc(var(--control-h) + var(--sp-3) + var(--target-sm)); }
.api .api-key[data-state="empty"] .api-key-line { display: none; }
.api .api-key-hint, .api .api-key-err { margin: 0; min-width: 0; font-size: var(--fs-sm); line-height: var(--lh-sm); }
.api .api-key-hint { color: var(--muted); }
.api .api-key-err { color: var(--fg); }
.api .api-key-value {
  flex: 1; min-width: 0; padding: 0; background: none; border: 0;
  font-family: var(--font-mono); font-size: var(--fs-base); line-height: var(--lh-base); color: var(--fg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.api .api-key-copy {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: var(--target); height: var(--target); padding: 0;
  background: none; border: 0; border-radius: var(--r-control);
  color: var(--muted); cursor: pointer;
  transition: color var(--dur-2) var(--ease-std), background-color var(--dur-2) var(--ease-std);
}
.api .api-key-copy:active { color: var(--fg); background: var(--raised); }
@media (hover: hover) {
  .api .api-key-copy:hover { color: var(--fg); background: var(--raised); }
}
.api .api-key-copy.copied { color: var(--accent); }
.api .api-key-copy.blocked { color: var(--fg); }
.api .api-key-ico { width: var(--sp-5); height: var(--sp-5); flex: none; }
.api .api-key-ico .api-key-g-ok, .api .api-key-ico .api-key-g-no { display: none; }
.api .api-key-copy.copied .api-key-g-ok, .api .api-key-copy.blocked .api-key-g-no { display: inline; }
.api .api-key-copy.copied .api-key-g-copy, .api .api-key-copy.blocked .api-key-g-copy { display: none; }
/* the line under the key: the credits, no account, and the way to more. The credits read in the muted ink with the figure in
   --fg; the link is the one accent text link in the card */
.api .api-key-line { display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--sp-4); row-gap: var(--sp-1); min-height: var(--target-sm); min-width: 0; font-size: var(--fs-base); line-height: var(--lh-base); }
.api .api-key-credits { color: var(--muted); }
.api .api-key-credits b { color: var(--fg); font-weight: 500; }
.api .api-key-up { display: inline-flex; align-items: center; min-height: var(--target-sm); color: var(--accent); text-decoration: underline; text-underline-offset: 0.15em; }
/* the wait state: flat bars in the key row's and the line's own boxes, pulsing between two surfaces of the ladder */
.api .api-key-skel {
  display: block; width: calc(var(--sp-16) * 3); max-width: 100%; height: var(--lh-base);
  background: var(--line); border-radius: var(--r-control);
  animation: api-key-wait var(--dur-5) var(--ease-std) infinite alternate; /* deliberate */
}
.api .api-key-skel-line { width: calc(var(--sp-16) * 2); height: var(--lh-sm); }
@keyframes api-key-wait { from { background-color: var(--line); } to { background-color: var(--raised); } }

/* ---- section rhythm ---- */
.api .api-sec { margin-top: var(--sp-section); }
.api h2 { font-size: var(--fs-h2); line-height: var(--lh-lg); margin-bottom: var(--sp-3); }
.api .api-sub { font-size: var(--fs-base); line-height: var(--lh-base); color: var(--secondary); margin-top: var(--sp-6); margin-bottom: var(--sp-1); }
.api .api-p { color: var(--secondary); max-width: var(--measure); margin-top: var(--sp-3); }
.api .api-cap { color: var(--muted); font-size: var(--fs-sm); line-height: var(--lh-sm); max-width: var(--measure); margin-top: var(--sp-3); }
.api .api-p code, .api .api-cap code { font-family: var(--font-mono); color: var(--fg); }
/* the free-in-beta and own-account terms under the rate card: one sentence per line */
.api .api-callout {
  max-width: var(--measure); margin-top: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: var(--card); border: 1px solid var(--line); border-left: 2px solid var(--accent);
  border-radius: var(--r-control); color: var(--secondary); font-size: var(--fs-sm); line-height: var(--lh-sm);
}
.api .api-callout code { font-family: var(--font-mono); color: var(--fg); }
.api .api-handoff a { color: var(--accent); }

/* ---- the drop-in card: the page's one bold thing ---- */
.api .api-drop {
  margin-top: var(--sp-section);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-surface);
  padding: var(--sp-5) var(--sp-4);
  min-width: 0;
}
.api .api-tabs { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-bottom: var(--sp-4); }
.api .api-tabs button {
  min-height: var(--target); padding: 0 var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--r-control);
  background: var(--raised); color: var(--muted); cursor: pointer;
  font-size: var(--fs-sm); white-space: nowrap;
  transition: color var(--dur-2) var(--ease-std), background-color var(--dur-2) var(--ease-std), border-color var(--dur-2) var(--ease-std);
}
.api .api-tabs button:hover { color: var(--fg); }
.api .api-tabs button[aria-selected="true"] { color: var(--fg); border-color: var(--accent); background: var(--card); }
.api .api-panel { display: grid; gap: var(--sp-2); min-width: 0; }
.api .api-panel[hidden] { display: none; }
.api .api-panel > * { min-width: 0; }
/* the command rows are the widget's own .sb-oneliner, which centers itself in
   the --content column; inside the card it fills the card. The box is the
   widget's (install-snippet.js): one clipped line that fades at its end, the
   whole box one copy button, in the control radius, with no scroll bar, so a
   long command (the curl samples) can never make the page scroll at a narrow
   width and this page restyles none of it. */
.api .api-snippet { margin-top: var(--sp-4); min-width: 0; }
.api .sb-oneliner { max-width: none; }

/* ---- the SSE sample: the wire, not a command. It draws its own box in the
   mounted rows' look (card fill, hairline, control radius) but is not the
   widget's one-line .sb-cmd (that family clips, fades and never scrolls): it
   has no copy button and no row label, and each line is its own code line that
   scrolls on its own axis when a phone cannot show it whole, so it is a
   focusable region (api.html). ---- */
.api .api-sse {
  display: grid; gap: var(--sp-1);
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: var(--sp-3) var(--sp-4);
  min-width: 0; overflow-x: auto;
}
.api .api-sse code {
  display: block; width: max-content; min-width: 100%;
  font-family: var(--font-mono); font-size: var(--fs-xs); line-height: var(--lh-xs);
  color: var(--muted); white-space: pre;
}

/* ---- the three stat cards: caption + one big value, no chart bars ---- */
.api .fig .api-stat {
  font-family: var(--font-mono); color: var(--fg);
  font-size: var(--fs-h2); line-height: var(--lh-xl);
  font-weight: 500; letter-spacing: var(--tracking-tight);
  font-variant-numeric: tabular-nums;
}

/* ---- the weight ladder under the price table: one mono data line, never
   wrapped, scrollable on its own axis if a phone cannot show it whole ---- */
.api .api-weights {
  font-family: var(--font-mono); color: var(--muted);
  white-space: nowrap; overflow-x: auto; max-width: none;
}

/* ---- tables: the price legs, the model list, the route tables. Rows, never
   cards. Cells wrap so no figure is ever clipped at 320; a figure's digits
   ride in a .api-fig span that never breaks mid-number, and the wrapper stays
   a scroll box (mobile-web-design.mdc's own table pattern) as the last resort
   for a long model id. The model row's second cell is .api-role: one short
   phrase on what the id does. ---- */
.api .api-tablewrap { overflow-x: auto; margin-top: var(--sp-3); }
/* a scroller that is a tab stop (the SSE sample below, and every table wrapper: edge/src/focus-scrollers.ts) draws its ring inside
   its own box, where an ancestor that clips cannot cut it */
.api .api-tablewrap:focus-visible, .api .api-sse:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.api .api-table { width: 100%; min-width: 0; border-collapse: collapse; font-size: var(--fs-sm); line-height: var(--lh-sm); }
.api .api-table th, .api .api-table td {
  text-align: left; padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--line); vertical-align: top;
  white-space: normal; overflow-wrap: anywhere;
}
.api .api-table th { color: var(--muted); font-weight: 500; }
.api .api-table .api-id { font-family: var(--font-mono); color: var(--fg); }
.api .api-table .api-role { color: var(--muted); }
.api .api-table .api-context { color: var(--muted); white-space: nowrap; overflow-wrap: normal; font-variant-numeric: tabular-nums; }
.api .api-table .api-num { font-family: var(--font-mono); color: var(--fg); text-align: right; font-variant-numeric: tabular-nums; }
/* a number and its unit stay together; the unit word may wrap to the next
   line, the figure never breaks */
.api .api-fig { white-space: nowrap; }

/* ---- the status contract ---- */
.api .api-status { list-style: none; padding: 0; margin-top: var(--sp-3); display: grid; gap: var(--sp-3); max-width: var(--measure); }
.api .api-status li { color: var(--secondary); display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.api .api-status code { font-family: var(--font-mono); color: var(--fg); border: 1px solid var(--line); border-radius: var(--r-control); padding: 0 var(--sp-2); }

/* the stat row stacks on a phone: bench.css's two-column .figs makes each
   card ~136px wide at 320, and the third caption ("requests a minute per key")
   then wraps. One column at phone widths keeps every caption to one line. */
@media (max-width: 560px) { .api .figs { grid-template-columns: minmax(0, 1fr); } }
/* phone (≤560px): the drop-in card and the tables at 288px.
   - The dialect tabs drop the word "dialect" so the three sit on one row.
   - The command rows stay one line at 288px: the widget's box fades the curl
     at its end and its copy control is the glyph alone under 480px, so the
     row needs no stacking rule of its own.
   - Table headers never break inside a word ("inp/ut"), and the outer cells
     lose their inset so the figures have the room; a model id breaks only at
     its hyphen. The wrapper still scrolls if a table cannot fit. */
@media (max-width: 560px) {
  .api .api-tab-more { display: none; }
  .api .api-table th, .api .api-table td { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  .api .api-table :is(th, td):first-child { padding-left: 0; }
  .api .api-table :is(th, td):last-child { padding-right: 0; }
  .api .api-table th { white-space: nowrap; overflow-wrap: normal; }
  .api .api-table .api-rate { overflow-wrap: normal; }
}
/* ---- the any-model, keys and routes sections: inline links wear the accent
   like the handoff lines; the route tables are the same rows as every other
   table here, with the verb in mono and the path linked to its reference. At
   a phone width the wrapper scrolls on its own axis, the table pattern the
   rest of the page already uses. ---- */
.api .api-p a, .api .api-cap a { color: var(--accent); }
.api .api-table .api-verb { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 600; color: var(--muted); white-space: nowrap; }
.api .api-table .api-verb[data-verb="post"] { color: var(--fg); }
.api .api-table .api-path a { color: var(--fg); text-decoration: none; display: inline-flex; align-items: center; min-height: var(--target-sm); }
.api .api-routes td { vertical-align: middle; }
.api .api-table .api-path a:hover code { color: var(--accent); }
.api .api-table .api-path code, .api .api-table .api-scopecell code { font-family: var(--font-mono); overflow-wrap: anywhere; }
.api .api-table .api-scopecell code { color: var(--muted); font-size: var(--fs-xs); white-space: nowrap; }
.api .api-table .api-scope { white-space: nowrap; }

/* one column grid across every route table, so the six tables line up */
.api .api-routes { table-layout: fixed; }
.api .api-routes th:nth-child(1) { width: 5.5em; }
.api .api-routes th:nth-child(2) { width: 42%; }
.api .api-routes th:nth-child(4) { width: 9.5em; }
/* on a phone each route is a two-line row, not a table: the verb and the
   path on the first line, the purpose and the scope under the path, so no
   column is squeezed and nothing scrolls sideways */
@media (max-width: 640px) {
  .api .api-routes, .api .api-routes tbody { display: block; }
  .api .api-routes thead { display: none; }
  .api .api-routes tr { display: grid; grid-template-columns: 4.5em minmax(0, 1fr); column-gap: var(--sp-2); border-top: 1px solid var(--line); padding: var(--sp-2) 0; }
  .api .api-routes td { border-top: 0; padding: 0; }
  .api .api-routes .api-verb { align-self: center; }
  .api .api-routes .api-role, .api .api-routes .api-scopecell { grid-column: 2; }
}

