/* ---------------------------------------------------------------------------
   forbind — reset, primitives and the focus system
--------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  /* No font-size override here: the root size is the user's own preference and
     everything in tokens.css is relative to it. */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--t-13);
  line-height: var(--lh-body);
  /* Reflow, not horizontal scroll, is the rule (WCAG 2.2 AA 1.4.10). */
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6, p, ul, ol, dl, dd, figure, pre { margin: 0; }
ul, ol { padding: 0; list-style: none; }

img, svg { max-width: 100%; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  margin: 0;
}

a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}
a:hover { color: var(--accent-hover); text-decoration: underline; }

code, kbd, samp, pre { font-family: var(--font-mono); }

/* --- focus ---------------------------------------------------------------
   Every focusable thing gets a visible indicator and it is never removed: a
   2px accent outline, offset clear of the element.

   There was a `.focus-inset` class here for anything whose outer ring would be
   clipped by a pane or scroll boundary. Nothing ever wore it — rings were
   measured at every pane edge and the browser paints all of them — so it went
   rather than sit in the stylesheet looking load-bearing. The one inset ring
   left is on `.field`, which draws its own because the outline would sit
   outside the box the border already draws.
------------------------------------------------------------------------- */
:focus { outline: none; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Windows High Contrast / forced-colors: the system picks the colours, we only
   guarantee that a ring exists and that fills never carry meaning alone. */
@media (forced-colors: active) {
  :focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
  /* Wherever a ring is drawn with box-shadow — which forced colours discard —
     an outline stands in for it. */
  .field:focus-within { outline: 2px solid Highlight; outline-offset: -2px; }
}

/* --- screen-reader-only ------------------------------------------------- */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- skip links ----------------------------------------------------------
   Visually hidden until focused, then a real, visible control at the top of
   the page. They are the first thing in the tab order.
------------------------------------------------------------------------- */
.skip-links { position: absolute; top: 0; left: 0; z-index: 100; }

.skip-link {
  position: absolute;
  top: 0; left: 0;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link:focus-visible,
.skip-link:focus {
  position: fixed;
  top: var(--s-8);
  left: var(--s-8);
  width: auto; height: auto;
  clip-path: none;
  overflow: visible;
  display: inline-flex;
  align-items: center;
  height: var(--h-36);
  padding: 0 var(--s-14);
  background: var(--ink);
  color: var(--paper);
  font: 600 var(--t-12-5) / 1 var(--font-sans);
  text-decoration: none;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A focused landmark target should not draw a ring of its own — it is a
   scroll destination, not a control. */
[tabindex='-1']:focus { outline: none; }

/* --- shared primitives -------------------------------------------------- */

/* Small uppercase mono section label, used throughout the detail pane, the
   rail and the import report. */
.label {
  font: 600 var(--t-10) / 1 var(--font-mono);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ink-55);
}
.label--sm {
  font-size: var(--t-9-5);
  letter-spacing: var(--ls-label-sm);
}

.mono { font-family: var(--font-mono); }

/* Buttons ---------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-7);
  height: var(--h-30);
  padding: 0 var(--s-13);
  border: var(--rule-w) solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font: 600 var(--t-11-5) / 1 var(--font-sans);
  text-decoration: none;
  cursor: pointer;
  border-radius: 0;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn:hover { background: var(--hover-surface); color: var(--ink); text-decoration: none; }
.btn:active { background: var(--rule); }

.btn--filled {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.btn--filled:hover { background: var(--fill-hover); color: var(--paper); }
.btn--filled:active { background: var(--fill-active); color: var(--paper); }

/* Both places `aria-disabled` is used put *status* in the label — "Sending…"
   in try-it, "Testing…" in the auth sheet — so the button is saying something
   at the moment it is dimmed. An inactive control is exempt from 1.4.3, but a
   label nobody can read is not much of a status. Opacity composites the whole
   button against the page, so 0.55 landed the label at 4.21:1 on paper; 0.6
   takes it to 5.00:1 and still reads as stood down. */
.btn[aria-disabled='true'],
.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.btn[aria-disabled='true']:hover,
.btn:disabled:hover { background: var(--paper); }
.btn--filled[aria-disabled='true']:hover,
.btn--filled:disabled:hover { background: var(--ink); }

.btn--sm { height: var(--h-24); padding: 0 var(--s-9); font-size: var(--t-10-5); }
.btn--md { height: var(--h-28); padding: 0 var(--s-12); }
.btn--lg { height: var(--h-36); padding: 0 var(--s-16); font-size: var(--t-12-5); }

/* A link that behaves as a link but sits in a button row. */
.link-quiet {
  background: none;
  border: 0;
  padding: 0;
  color: var(--accent);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.link-quiet:hover { color: var(--accent-hover); }

/* Verb + status pills ---------------------------------------------------- */
.pill {
  display: inline-block;
  padding: var(--s-3) var(--s-5);
  border: var(--rule-w) solid currentColor;
  font: 600 var(--t-10) / 1.1 var(--font-mono);
  text-align: center;
  white-space: nowrap;
}
.pill--get     { color: var(--get-fg);     background: var(--get-bg); }
.pill--post    { color: var(--post-fg);    background: var(--post-bg); }
.pill--patch   { color: var(--patch-fg);   background: var(--patch-bg); }
.pill--put     { color: var(--patch-fg);   background: var(--patch-bg); }
.pill--delete  { color: var(--delete-fg);  background: var(--delete-bg); }
.pill--other   { color: var(--neutral-fg); background: var(--neutral-bg); border-color: var(--neutral-border); }
.pill--neutral { color: var(--neutral-fg); background: var(--neutral-bg); border-color: var(--neutral-border); }

.pill--success { color: var(--post-fg);   background: var(--post-bg); }
.pill--warn    { color: var(--patch-fg);  background: var(--patch-bg); }
.pill--error   { color: var(--delete-fg); background: var(--delete-bg); }
.pill--info    { color: var(--get-fg);    background: var(--get-bg); }

/* Chips ------------------------------------------------------------------ */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-5);
  padding: var(--s-4) var(--s-8);
  border: var(--rule-w) solid var(--border-quiet);
  background: transparent;
  color: var(--ink);
  font: 600 var(--t-10-5) / 1.1 var(--font-mono);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
.chip:hover { background: var(--hover-surface); }
.chip[aria-pressed='true'],
.chip[aria-current='true'] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.chip[aria-pressed='true']:hover,
.chip[aria-current='true']:hover { background: var(--fill-hover); }
.chip--dashed { border-style: dashed; color: var(--ink-55); }
.chip--dashed[aria-pressed='true'] { color: var(--paper); border-style: solid; }
.chip--static { cursor: default; }
.chip--static:hover { background: transparent; }

/* Fields ----------------------------------------------------------------- */
.field {
  display: flex;
  align-items: center;
  gap: var(--s-10);
  height: var(--h-32);
  padding: 0 var(--s-10);
  border: var(--rule-w) solid var(--ink);
  background: var(--field-bg);
}
.field:focus-within { box-shadow: inset 0 0 0 2px var(--accent); }

.field input,
.input-bare {
  flex: 1;
  min-width: 0;
  /* The field is 32px and the input's own content box is 18, so centring it
     leaves a 7px dead band top and bottom where the pointer hits the wrapping
     div and nothing happens. Stretching costs nothing visually and makes the
     whole control the target. */
  align-self: stretch;
  border: 0;
  background: transparent;
  font: 400 var(--t-12-5) / 1 var(--font-sans);
  color: var(--ink);
}
.field input:focus-visible,
.input-bare:focus-visible { outline: none; }
.field input::placeholder { color: var(--ink-55); opacity: 1; }

.kbd {
  font: 500 var(--t-10-5) / 1 var(--font-mono);
  padding: var(--s-3) var(--s-5);
  border: var(--rule-w) solid var(--divider-quiet);
  color: var(--ink-55);
  white-space: nowrap;
}

/* Code ------------------------------------------------------------------- */
.code-block {
  margin: 0;
  padding: var(--s-12) var(--s-14);
  background: var(--code-bg);
  color: var(--code-fg);
  border: var(--rule-w) solid var(--code-border);
  font: 400 var(--t-11-5) / var(--lh-code) var(--font-mono);
  white-space: pre-wrap;
  word-break: break-all;
  overflow-x: auto;
}

/* Syntax highlighting, applied to a response body whose `Content-Type` names a
   language this app can colour. The class names are highlight.js's own; the
   colours are ours, so the palette is a set of tokens checked against the code
   surface rather than a vendored theme stylesheet nobody here has read.

   Deliberately a short list. A grammar emits far more scopes than this, and
   everything unnamed falls through to `--code-fg` — which is the same legible
   block the reader had before any of this. Colour is never the message: the
   body reads identically with the stylesheet off, and forced colours hands the
   whole block to the system palette, which is correct and needs no help here.

   No bold, no italics, no background tints. This is a monospace block in a
   pane, not a code editor, and weight changes at 11.5px cost more in legibility
   than they return. */
.code-block .hljs-attr,
.code-block .hljs-attribute { color: var(--syntax-key); }
.code-block .hljs-string { color: var(--syntax-string); }
.code-block .hljs-number { color: var(--syntax-number); }
.code-block .hljs-literal,
.code-block .hljs-type,
.code-block .hljs-symbol { color: var(--syntax-literal); }
.code-block .hljs-tag,
.code-block .hljs-name { color: var(--syntax-tag); }
.code-block .hljs-comment,
.code-block .hljs-meta,
.code-block .hljs-bullet,
.code-block .hljs-punctuation { color: var(--syntax-muted); }

/* Word-led status rows (WARN / INFO / FAIL) — never an icon, never a colour
   on its own. */
.word {
  flex: none;
  /* Nudged off the top: the word is set in small caps-height mono next to
     sentence-case text, so its optical centre sits high without this. */
  margin-top: 2px;
  font: 600 var(--t-10) / 1.6 var(--font-mono);
  letter-spacing: var(--ls-label-sm);
}
.word--warn { color: var(--patch-fg); }
.word--info { color: var(--post-fg); }
.word--fail { color: var(--delete-fg); }

/* The base URL field ------------------------------------------------------
   One component, two homes: the parse report and the Try it panel. It is
   marked out with the dashed border the drop zone uses, because both are the
   same kind of thing — somewhere the reader has to supply what the document
   did not. */
fb-base-url { display: block; }

.baseurl {
  padding: var(--s-14);
  border: var(--rule-w-strong) dashed var(--ink);
  background: var(--paper-alt);
}
.baseurl--report { margin-top: var(--s-22); }
.baseurl--settings { margin-top: var(--s-16); }
.baseurl--inline { margin-bottom: var(--s-14); }

.baseurl__title {
  font: 600 var(--t-12) / 1.3 var(--font-sans);
  letter-spacing: var(--ls-label-sm);
}
.baseurl__lede {
  margin-top: var(--s-8);
  font: 400 var(--t-12) / 1.55 var(--font-sans);
  color: var(--ink-70);
}
/* Specific enough to settle the margin against `.urlrow`, which is declared
   in overlays.css and therefore later in the cascade. */
.baseurl .urlrow { margin-top: var(--s-10); background: var(--paper); }

.baseurl__error {
  display: flex;
  gap: var(--s-10);
  margin-top: var(--s-10);
  font: 400 var(--t-12) / 1.5 var(--font-sans);
}
/* The word carries the failure as well as the border, so a dashed edge in
   forced colours is a repeat of what is already written, not the only cue. */
.baseurl__input[aria-invalid='true'] { border: var(--rule-w-strong) solid var(--delete-fg); }
@media (forced-colors: active) {
  .baseurl__input[aria-invalid='true'] { border-style: dashed; }
}

.baseurl__clear {
  margin-top: var(--s-10);
  font: 400 var(--t-11-5) / 1.5 var(--font-sans);
}

/* Rendered descriptions ---------------------------------------------------
   `.md` wraps whatever a document's `description` turned out to be. The rules
   are deliberately few: prose spacing, lists that keep their markers, and code
   that reuses the block styling above. Headings inside a description are
   pushed down to h4–h6 by js/lib/markdown.js, so they are styled as the small
   labels they are rather than competing with the pane's own headings. */
.md > :first-child { margin-top: 0; }
.md > * + * { margin-top: var(--s-8); }
.md--inline { display: inline; }

.md ul, .md ol { margin-inline-start: var(--s-18); }
.md ul { list-style: disc; }
.md ol { list-style: decimal; }
.md li + li { margin-top: var(--s-4); }
.md li::marker { color: var(--ink-55); }

.md code {
  padding: 0 var(--s-3);
  border: var(--rule-w) solid var(--divider-quiet);
  font: 400 0.95em / 1.4 var(--font-mono);
  overflow-wrap: anywhere;
}
.md pre {
  padding: var(--s-10) var(--s-12);
  background: var(--code-bg);
  color: var(--code-fg);
  border: var(--rule-w) solid var(--code-border);
  font: 400 var(--t-11-5) / var(--lh-code) var(--font-mono);
  overflow-x: auto;
}
/* The border belongs to the block, not to every span inside it. */
.md pre code { padding: 0; border: 0; font-size: inherit; }

.md__h {
  font: 600 var(--t-12) / 1.3 var(--font-sans);
  letter-spacing: var(--ls-label-sm);
  color: var(--ink);
}
.md blockquote {
  padding-inline-start: var(--s-10);
  border-inline-start: var(--rule-w-strong) solid var(--rule);
  color: var(--ink-55);
}
/* Its own scroll container, so a wide table in a narrow column scrolls rather
   than crushing its cells. */
.md table { border-collapse: collapse; display: block; overflow-x: auto; }
/* Breaking `artist:elvis` across two lines to fit a column defeats the point
   of quoting it, so code in a table keeps its width and the table scrolls. */
.md table code { overflow-wrap: normal; white-space: nowrap; }
.md th, .md td {
  padding: var(--s-4) var(--s-8);
  border: var(--rule-w) solid var(--rule);
  text-align: start;
}
.md hr { border: 0; border-top: var(--rule-w) solid var(--rule); }
.md img { max-width: 100%; height: auto; }

/* Dividers --------------------------------------------------------------- */
.hr { border: 0; border-top: var(--rule-w) solid var(--rule); margin: 0; }
