/* ============================================================
   OPEN API — a Carbon band between #whats-it-worth and #cta.
   Section-scoped; every selector prefixed .api-.

   Two sentences and the payload. The section used to carry a headline and
   three capability rows; the client cut it to the claim and the evidence,
   which is the stronger shape — a developer reads the payload, and everyone
   else reads two sentences and moves on.

   It also carries the page's ground alternation: this band being Carbon is
   what puts #cta on Bone, so the run stays Bone, Carbon, Bone, Carbon down
   to the footer.
   ============================================================ */
.api{padding:96px 0;background:var(--nv-carbon,#171918);color:var(--nv-bone,#F2F0E9);
  border-top:1px solid rgba(242,240,233,.10)}
.api *,.api *::before,.api *::after{box-sizing:border-box}

.api-k{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;font-size:.6875rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--nv-signal,#D7E84A);
  margin-bottom:20px}
.api-lede{margin:0;font-size:1.25rem;line-height:1.55;letter-spacing:-.006em;
  color:var(--nv-bone,#F2F0E9);max-width:64ch;text-wrap:pretty}
.api-lede b{color:var(--nv-bone,#F2F0E9);font-weight:600}
/* the two phrases the sentence turns on. Signal on the Carbon default,
   Signal Moss where the band is light — the accent follows the ground, it
   does not stay one colour and hope. */
.api-lede .pop{color:var(--nv-signal,#D7E84A);font-weight:600}

/* ---- the payload panel --------------------------------------------------- */
.api-code{margin-top:40px;max-width:820px;
  border:1px solid rgba(242,240,233,.12);border-radius:var(--nv-radius,4px);
  background:var(--nv-graphite,#222523);overflow:hidden}
.api-code-hd{display:flex;justify-content:space-between;align-items:center;gap:16px;
  padding:11px 16px;border-bottom:1px solid rgba(242,240,233,.10);
  font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.6875rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--nv-signal,#D7E84A)}
.api-code-hd .q{color:var(--nv-steel,#9EA29F)}

/* the window is the mask; the pre inside it is what moves */
.api-win{position:relative;height:430px;overflow:hidden}
.api-win::after{content:"";position:absolute;left:0;right:0;bottom:0;height:52px;
  background:linear-gradient(to bottom,rgba(34,37,35,0),var(--nv-graphite,#222523));
  pointer-events:none}
.api-win pre{margin:0;padding:18px 18px 40px;
  font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.75rem;line-height:1.8;
  color:var(--nv-steel,#9EA29F);white-space:pre;tab-size:2}

/* Keyframe stops cannot be computed from a custom property, so they are fixed
   and the JS tunes only the distance and the duration — the hold at each end
   is baked into the percentages below. */
@keyframes api-scroll{
  0%   {transform:translateY(0);            opacity:0}
  4%   {transform:translateY(0);            opacity:1}
  14%  {transform:translateY(0);            opacity:1}
  88%  {transform:translateY(var(--api-shift,0));opacity:1}
  96%  {transform:translateY(var(--api-shift,0));opacity:1}
  100% {transform:translateY(var(--api-shift,0));opacity:0}
}
.api-win.is-running pre{animation:api-scroll var(--api-dur,26s) linear infinite}
.api-win.is-running:hover pre,
.api-win.is-running:focus-within pre,
.api-win.is-paused pre{animation-play-state:paused}

/* no motion: the panel becomes an ordinary scroll region so the same content
   is still reachable, which a stopped animation on its own would not be */
.api-win.is-static{overflow-y:auto}
.api-win.is-static pre{animation:none;transform:none;opacity:1}
.api-win.is-static::after{display:none}
@media(prefers-reduced-motion:reduce){
  .api-win pre{animation:none !important;transform:none !important;opacity:1 !important}
  .api-win{overflow-y:auto}
  .api-win::after{display:none}
}

/* ---- payload syntax ------------------------------------------------------ */
/* var(--nv-ash,#5F6461) is the project hairline value and is 3.17:1 on Graphite — below AA
   for text. var(--nv-steel,#9EA29F) is 4.70:1 and still reads a step quieter than Steel. */
.api-win .cm{color:var(--nv-steel,#9EA29F)}                              /* comment          */
.api-win .ky{color:var(--nv-bone,#F2F0E9)}               /* key              */
.api-win .st{color:var(--nv-steel,#9EA29F)}              /* string           */
.api-win .nu{color:var(--nv-signal,#D7E84A)}             /* number / boolean */
.api-win .vb{color:var(--nv-bone,#F2F0E9);font-weight:500}

.api-note{margin:22px 0 0;font-size:.875rem;line-height:1.6;
  color:var(--nv-steel,#9EA29F);max-width:82ch}

@media(max-width:768px){
  .api{padding:64px 0}
  .api-lede{font-size:1.0625rem}
  .api-win{height:360px}
  .api-win pre{font-size:.6875rem}
}

/* ============================================================
   REVISION — the claim reads as a header, and the payload sits beside it.

   Two changes, both the client's: the lede is set at header scale rather
   than body scale, and the code panel moves from under the text to the
   right of it. Below 1080 the grid collapses back to one column and the
   panel returns to sitting under the sentence, because a 600px payload in
   a 340px column is unreadable at any type size.

   The two columns are centred against each other rather than top-aligned.
   The text block cannot be made to equal the panel's height without either
   padding the copy or shrinking the payload, and a centred pair reads as
   deliberate where a top-aligned pair with 90px of dead space under the
   text reads as a bug.
   ============================================================ */
.api-cols{display:grid;grid-template-columns:1fr;gap:26px}
.api-say{min-width:0;display:flex;flex-direction:column}
.api-cols .api-code{margin-top:0;max-width:none;min-width:0}

/* Stacked again, at the client's call: the claim across the top, the payload
   under it. Sized so the sentence sets on two lines at full container width
   — the largest step that still does, measured rather than chosen — and the
   window shows seven rows, which is enough to see that it is real JSON and
   short enough that the band stays a band. */
.api-lede{font-size:1.4375rem;line-height:1.35;letter-spacing:-.016em;
  font-weight:500;max-width:34ch;text-wrap:balance}
@media(min-width:769px){  .api-lede{font-size:1.625rem;max-width:none} }
@media(min-width:1080px){ .api-lede{font-size:1.75rem} }
/* 2.125rem is the ceiling: 34px sets on two lines across the full container
   and 35px tips to three. Swept at 1240, 1280 and 1440 before it was set. */
@media(min-width:1240px){ .api-lede{font-size:2.125rem} }
.api-k{margin-bottom:16px}

/* Seven rows: 18px of top padding plus 7 x 21.6px of set line. The bottom
   fade shrinks with the window — a 52px veil over a 170px pane would cover
   two and a half of the seven. */
.api-win{height:170px}
.api-win::after{height:26px}
/* the phone step has to be restated here: the block that set it sits earlier
   in the file than these rules, so an unmediated size above would win. */
@media(max-width:768px){ .api-lede{font-size:1.25rem;line-height:1.45} }

/* ---- the band on Bone --------------------------------------------------
   #software arriving above #whats-it-worth pushed every ground below it one
   step along, so this band is now the light one and #cta is Carbon. The code
   panel stays dark on purpose: a payload is a terminal, and a terminal on a
   light page is a well, not an inconsistency. */
.api-bone{background:var(--nv-bone,#F2F0E9);color:var(--nv-carbon,#171918);
  border-top:1px solid var(--nv-border-alt,#C8C6BE)}
.api-bone .api-k{color:var(--signal-ink-bone,#41630F)}
.api-bone .api-lede{color:var(--nv-carbon,#171918)}
.api-bone .api-lede b{color:var(--nv-carbon,#171918)}
.api-bone .api-lede .pop{color:var(--signal-ink-bone,#41630F)}
.api-bone .api-code{border-color:var(--nv-border-alt,#C8C6BE);
  box-shadow:0 18px 44px -28px rgba(23,25,24,.55)}

/* The panel's closing line. It sits OUTSIDE the scrolling window on purpose:
   the payload is a loop, so anything inside it would slide away and come back,
   and this is the one line that has to be readable at every moment. Signal on
   Graphite is 13.07:1 — legal here, and the only Signal on a Bone band. */
.api-code-ft{padding:12px 16px 13px;border-top:1px solid rgba(242,240,233,.10);
  background:var(--nv-graphite,#222523);
  font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;line-height:1.5;letter-spacing:.04em;
  color:var(--nv-signal,#D7E84A)}

/* Single-column widths: the payload is wider than a phone, so the window
   becomes a horizontal scroll region rather than clipping the right-hand
   side of every line. Vertical stays hidden — that axis is the animation. */
@media(max-width:1079px){
  .api-win{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}
}
