/*
 * developers.biklo.com
 *
 * Brand accent #04a9b5, the same one the admin uses. Light and dark both defined on
 * tokens so the palette is stated once; the reference page opts out of the sidebar
 * via `body.wide` because Scalar brings its own.
 */
:root {
	--bg: #ffffff;
	--panel: #f7fafa;
	--ink: #0c1517;
	--ink-2: #48605f;
	--ink-3: #7d9391;
	--rule: #e2eaea;
	--brand: #04a9b5;
	--brand-deep: #026f78;
	--brand-wash: #e6f7f8;
	/* Semantic, and deliberately NOT the accent: these mark sandbox vs live, and a
	   teal "LIVE" would be indistinguishable from every other brand-coloured thing
	   on the page. */
	--good: #16a34a;
	--bad: #dc2626;
	--code-bg: #f3f7f7;
	--tree: #d3e0e0;
	--max: 46rem;
	--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
	:root {
		--bg: #0b1416;
		--panel: #101c1f;
		--ink: #e8f1f1;
		--ink-2: #a9c0c2;
		--ink-3: #7b9497;
		--rule: #1e3034;
		--brand: #2ac6d1;
		--brand-deep: #7fe0e7;
		--brand-wash: #0d2c30;
		--good: #4ade80;
		--bad: #f87171;
		--code-bg: #0f1d20;
		--tree: #27403f;
	}
}

* { box-sizing: border-box; }

/*
 * The filter sets `hidden` on rows it wants gone. The nav rows are `display: flex`
 * for the method badge, and an author rule beats the browser's own `[hidden]`
 * rule — so every row stayed on screen and the filter looked broken while working
 * perfectly. Author-level and !important, once, for the whole page.
 */
[hidden] { display: none !important; }

body {
	margin: 0;
	background: var(--bg);
	color: var(--ink);
	font-family: var(--font);
	font-size: 16px;
	line-height: 1.65;
	-webkit-font-smoothing: antialiased;
}

a { color: var(--brand-deep); }
a:hover { color: var(--brand); }

/* ---------- chrome ---------- */

.top {
	display: flex;
	align-items: center;
	gap: 28px;
	flex-wrap: wrap;
	padding: 14px 28px;
	border-bottom: 1px solid var(--rule);
	background: var(--bg);
	position: sticky;
	top: 0;
	z-index: 10;
}
/*
 * The logo is a 574x276 lockup carrying both the wordmark and "for developers".
 * Height is what is fixed; width follows, and the intrinsic width/height on the
 * <img> reserves the right box so the header does not jump while it loads.
 */
.brand { display: inline-flex; align-items: center; text-decoration: none; }
.brand img {
	/* 38px, not 30: the lockup carries "for developers" as a second line, and below
	   this it renders under 10px and stops being readable. */
	height: 38px;
	width: auto;
	display: block;
}
@media (max-width: 520px) { .brand img { height: 30px; } }
.top nav { display: flex; gap: 22px; flex-wrap: wrap; }
.top nav a {
	color: var(--ink-2);
	text-decoration: none;
	font-size: 14.5px;
	font-weight: 500;
	padding: 4px 0;
	border-bottom: 2px solid transparent;
}
.top nav a:hover { color: var(--ink); }
.top nav a.active { color: var(--brand-deep); border-bottom-color: var(--brand); }

.shell {
	display: grid;
	grid-template-columns: 250px minmax(0, 1fr);
	gap: 48px;
	max-width: 1180px;
	margin: 0 auto;
	padding: 32px 28px 80px;
}
body.wide .shell { grid-template-columns: 1fr; max-width: none; padding: 0; }

/*
 * The rail scrolls ITSELF, not the page.
 *
 * With several groups open the nav is taller than the viewport — 82 endpoints in
 * 14 sections gets there quickly — and without this you had to scroll the whole
 * page to reach the bottom of it, which scrolls away the very content you were
 * navigating from.
 *
 * Only the list scrolls: the title and the filter box stay pinned, because a
 * filter you have to scroll back up to reach is a filter nobody uses.
 */
aside {
	position: sticky;
	top: 78px;
	align-self: start;
	display: flex;
	flex-direction: column;
	max-height: calc(100vh - 78px - 24px);
}

#nav-list {
	flex: 1;
	/* Without min-height:0 a flex child refuses to shrink below its content and
	   the overflow never engages — the rail just grows again. */
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding-bottom: 8px;
	scrollbar-width: thin;
	scrollbar-color: var(--rule) transparent;
}
#nav-list::-webkit-scrollbar { width: 9px; }
#nav-list::-webkit-scrollbar-track { background: transparent; }
#nav-list::-webkit-scrollbar-thumb {
	background: var(--rule);
	border-radius: 5px;
	border: 2px solid var(--bg);
}
#nav-list::-webkit-scrollbar-thumb:hover { background: var(--ink-3); }
.rail-title {
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--ink-3);
	margin: 0 0 12px;
}
aside ul { list-style: none; margin: 0; padding: 0; }
aside li { margin: 0; }

/* The whole ROW is the target, not the text inside it: a 4px-tall hit area on a
   two-word link is the difference between a sidebar that feels responsive and one
   that feels broken. The active state paints the row for the same reason. */
aside li > a {
	display: flex;
	align-items: baseline;
	gap: 8px;
	padding: 6px 10px 6px 12px;
	border-left: 2px solid transparent;
	border-radius: 0 6px 6px 0;
	color: var(--ink-2);
	text-decoration: none;
	font-size: 14.5px;
	line-height: 1.35;
}
aside li > a:hover { color: var(--ink); background: var(--panel); }
aside li.active > a {
	color: var(--brand-deep);
	font-weight: 600;
	background: var(--brand-wash);
	border-left-color: var(--brand);
}
aside li.active .verb { box-shadow: 0 0 0 2px var(--brand-wash), 0 0 0 3px var(--brand); }
.nav-label { flex: 1; min-width: 0; }

/* Collapsible groups */
.nav-group > details > summary {
	display: flex;
	align-items: center;
	gap: 7px;
	cursor: pointer;
	list-style: none;
	padding: 7px 10px 7px 12px;
	border-radius: 6px;
	font-family: var(--mono);
	font-size: 10.5px;
	letter-spacing: 0.11em;
	text-transform: uppercase;
	color: var(--ink-3);
	user-select: none;
}
.nav-group > details > summary::-webkit-details-marker { display: none; }
.nav-group > details > summary::before {
	content: '';
	width: 0;
	height: 0;
	border-left: 5px solid currentColor;
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	transition: transform 0.15s ease;
	flex: none;
}
.nav-group > details[open] > summary::before { transform: rotate(90deg); }
.nav-group > details > summary:hover { color: var(--ink); background: var(--panel); }
.nav-group > details > summary.current { color: var(--brand-deep); }
.nav-group > details > summary .count {
	margin-left: auto;
	font-size: 10px;
	color: var(--ink-3);
	background: var(--panel);
	border: 1px solid var(--rule);
	border-radius: 999px;
	padding: 1px 6px;
}
.nav-group > details > ul { border-left: 1px solid var(--rule); margin-left: 17px; }
.nav-group + .nav-group { margin-top: 2px; }

main { min-width: 0; }
main > *:first-child { margin-top: 0; }

/* ---------- prose ---------- */

h1 { font-size: 33px; line-height: 1.15; letter-spacing: -0.022em; margin: 0 0 18px; text-wrap: balance; }
h2 { font-size: 23px; letter-spacing: -0.015em; margin: 42px 0 12px; text-wrap: balance; }
h3 { font-size: 17.5px; margin: 30px 0 10px; }
p, ul, ol { max-width: var(--max); }
li { margin-bottom: 6px; }
.lead { font-size: 17.5px; color: var(--ink-2); }
.meta { color: var(--ink-3); font-size: 13.5px; }

code {
	font-family: var(--mono);
	font-size: 0.875em;
	background: var(--code-bg);
	border: 1px solid var(--rule);
	border-radius: 3px;
	padding: 0.08em 0.34em;
	word-break: break-word;
}
pre {
	background: var(--code-bg);
	border: 1px solid var(--rule);
	border-left: 3px solid var(--brand);
	border-radius: 5px;
	padding: 15px 17px;
	overflow-x: auto;
	font-size: 13.5px;
	line-height: 1.6;
}
pre code { background: none; border: 0; padding: 0; font-size: inherit; }

/* A real table on desktop so the columns share the width properly; `display: block`
   made every column shrink to its content and squeezed descriptions into a
   40-character ribbon. Narrow screens get the scroller instead (see the media
   query at the end). */
table { border-collapse: collapse; width: 100%; font-size: 14.5px; margin-bottom: 20px; table-layout: fixed; }
th, td { text-align: left; padding: 9px 14px 9px 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
th { font-size: 11.5px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-3); font-weight: 600; white-space: nowrap; }

blockquote {
	margin: 0 0 18px;
	padding: 2px 0 2px 18px;
	border-left: 3px solid var(--brand);
	color: var(--ink-2);
}

/* ---------- changelog ---------- */

.entry { padding: 20px 0; border-bottom: 1px solid var(--rule); }
.entry h2 { margin: 0 0 6px; font-size: 20px; }
.entry h2 a { text-decoration: none; }
.tag {
	display: inline-block;
	font-family: var(--mono);
	font-size: 11px;
	padding: 2px 8px;
	margin-left: 6px;
	border-radius: 999px;
	background: var(--brand-wash);
	color: var(--brand-deep);
	border: 1px solid color-mix(in srgb, var(--brand) 30%, transparent);
}

footer {
	border-top: 1px solid var(--rule);
	padding: 20px 28px;
	color: var(--ink-3);
	font-size: 13px;
	font-family: var(--mono);
}
body.wide footer { display: none; }

/* ---------- API reference ---------- */

/*
 * Three columns on an endpoint page: navigation, prose, code. The samples column
 * is sticky so the call stays on screen while the reader scrolls the parameters —
 * that pairing is the whole point of an endpoint page.
 */
.shell.three {
	grid-template-columns: 250px minmax(0, 1fr) 400px;
	gap: 36px;
	max-width: 1480px;
}

.sidepanel { position: sticky; top: 78px; align-self: start; }

#filter {
	width: 100%;
	margin: 0 0 12px;
	padding: 6px 10px;
	font: inherit;
	font-size: 13.5px;
	color: var(--ink);
	background: var(--bg);
	border: 1px solid var(--rule);
	border-radius: 7px;
}
#filter:focus {
	outline: none;
	border-color: var(--brand);
	box-shadow: 0 0 0 3px var(--brand-wash);
}

/* Method badges. Colour carries meaning here: read vs write vs destroy. */
.verb {
	font-family: var(--mono);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.04em;
	padding: 2px 0;
	border-radius: 4px;
	text-transform: uppercase;
	white-space: nowrap;
	color: #fff;
	background: var(--ink-3);
	/* Fixed width and centred. GET, PATCH and DELETE are different lengths, so
	   badges sized to their text left the sidebar labels on a ragged edge. */
	display: inline-block;
	width: 52px;
	text-align: center;
	flex: none;
}
.verb.get { background: #0f8b96; }
.verb.post { background: #2f8f4e; }
.verb.put, .verb.patch { background: #b9762a; }
.verb.delete { background: #c4443c; }

.endpoint { display: flex; align-items: center; gap: 10px; margin: 0 0 18px; }
.endpoint code {
	font-size: 14.5px;
	padding: 4px 9px;
	background: var(--code-bg);
	border: 1px solid var(--rule);
	border-radius: 6px;
}

.badges { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 26px; }
.badge {
	font-size: 12.5px;
	color: var(--ink-2);
	background: var(--panel);
	border: 1px solid var(--rule);
	border-radius: 999px;
	padding: 3px 11px;
}
.badge code { background: none; border: 0; padding: 0; font-size: 12px; color: var(--ink); }
.badge.sandbox { background: var(--brand-wash); border-color: var(--brand); color: var(--brand-deep); }
.badge.deprecated { text-decoration: none; opacity: .8; border-style: dashed; }

/* Reference index: one card per section, endpoints listed inside it. */
.api-group {
	border: 1px solid var(--rule);
	border-radius: 12px;
	padding: 18px 22px 8px;
	margin: 0 0 18px;
	background: var(--panel);
}
.api-group h2 { margin: 0 0 4px; font-size: 17px; }
.api-group .meta { margin: 0 0 10px; font-size: 14px; color: var(--ink-2); }
.ep-list { list-style: none; margin: 0; padding: 0; }
.ep-list li {
	display: flex;
	align-items: baseline;
	gap: 10px;
	padding: 7px 0;
	border-top: 1px solid var(--rule);
}
.ep-list a { text-decoration: none; }
.ep-list a:hover { text-decoration: underline; }
.ep-list code { font-size: 12.5px; color: var(--ink-3); }

.see-also {
	margin-top: 28px;
	padding: 11px 15px;
	border-left: 3px solid var(--brand);
	background: var(--panel);
	border-radius: 0 8px 8px 0;
	font-size: 14px;
}

/* Field reference tables */
.fields { margin-bottom: 14px; }
.fields td { padding: 11px 16px 11px 0; }
/* The description is the column that carries the meaning, so it gets what is left
   after the three narrow ones. */
.fields th:nth-child(1), .fields td:nth-child(1) { width: 30%; }
.fields th:nth-child(2), .fields td:nth-child(2) { width: 78px; }
.fields th:nth-child(3), .fields td:nth-child(3) { width: 92px; }
/* Break at the <wbr> the renderer puts after each dot, not inside a segment. */
.fields td:first-child { word-break: normal; overflow-wrap: break-word; }
.fields.response th:nth-child(1), .fields.response td:nth-child(1) { width: 38%; }
.fields code { font-size: 12.5px; }
.fields .type { color: var(--ink-3); font-family: var(--mono); font-size: 12.5px; white-space: nowrap; }
/*
 * Nesting, shown as a tree.
 *
 * The dotted key already states the depth, but a wall of `rate_limits.per_minute`
 * rows does not READ as belonging to anything — the guide lines are what make a
 * nested object look like one object instead of a flat list with long names.
 *
 * They are painted as backgrounds on the cell rather than borders on a wrapper so
 * the line runs the full height of the row and joins the row above it: cells touch,
 * padding does not break the line.
 */
.fields td:first-child {
	background-repeat: no-repeat;
	background-image: linear-gradient(var(--tree), var(--tree));
	background-size: 0 100%;
}
.fields .depth-1 td:first-child {
	padding-left: 22px;
	background-size: 1px 100%;
	background-position: 7px 0;
}
.fields .depth-2 td:first-child {
	padding-left: 40px;
	background-image: linear-gradient(var(--tree), var(--tree)), linear-gradient(var(--tree), var(--tree));
	background-size: 1px 100%, 1px 100%;
	background-position: 7px 0, 25px 0;
}
.fields .depth-3 td:first-child {
	padding-left: 58px;
	background-image: linear-gradient(var(--tree), var(--tree)), linear-gradient(var(--tree), var(--tree)), linear-gradient(var(--tree), var(--tree));
	background-size: 1px 100%, 1px 100%, 1px 100%;
	background-position: 7px 0, 25px 0, 43px 0;
}

/* Fold control. Only rows that own children get one. */
.fold {
	appearance: none;
	width: 15px;
	height: 15px;
	padding: 0;
	margin-right: 5px;
	vertical-align: middle;
	background: none;
	border: 0;
	cursor: pointer;
	position: relative;
}
.fold::before {
	content: '';
	position: absolute;
	top: 50%;
	left: 3px;
	width: 0;
	height: 0;
	border-left: 5px solid var(--ink-3);
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	transform: translateY(-50%) rotate(90deg);
	transition: transform 0.14s ease;
}
.fields tr.folded .fold::before { transform: translateY(-50%) rotate(0deg); }
.fold:hover::before { border-left-color: var(--brand); }
/* A folded parent says so, rather than just losing its rows silently. */
.fields tr.folded > td:first-child > code::after {
	content: '…';
	margin-left: 6px;
	color: var(--ink-3);
	font-family: var(--font);
}
.fields tr.has-children > td:first-child > code { font-weight: 600; }
.req, .opt {
	font-family: var(--mono);
	font-size: 11px;
	padding: 2px 7px;
	border-radius: 999px;
	white-space: nowrap;
}
.req { color: #fff; background: #c4443c; }
.opt { color: var(--ink-3); background: var(--panel); border: 1px solid var(--rule); }
.values { margin: 6px 0 0; font-size: 13.5px; color: var(--ink-2); }
.values strong { color: var(--ink); font-weight: 600; }
.unsupported { color: #b9762a; }
.unsupported strong { color: #b9762a; }
.example-label {
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--ink-3);
	margin: 18px 0 7px;
}

/* ---------- syntax highlighting ---------- */

/*
 * Generated at BUILD time by SyntaxHighlighter, so this is the whole cost of
 * highlighted code on the site — no library, no runtime pass, nothing to fetch.
 * Tuned for contrast on both grounds rather than for matching any editor theme.
 */
.hl .t-key { color: #b5476e; }
.hl .t-str { color: #297a4b; }
.hl .t-num { color: #9a5b1e; }
.hl .t-lit { color: #7a4fbf; }
.hl .t-kw  { color: #b5476e; font-weight: 600; }
.hl .t-var { color: #0b6f8a; }
.hl .t-com { color: var(--ink-3); font-style: italic; }
.hl .t-punc { color: var(--ink-3); }

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .hl .t-key { color: #ff8fb3; }
	:root:not([data-theme="light"]) .hl .t-str { color: #7fd6a0; }
	:root:not([data-theme="light"]) .hl .t-num { color: #ffc07a; }
	:root:not([data-theme="light"]) .hl .t-lit { color: #c5a6ff; }
	:root:not([data-theme="light"]) .hl .t-kw  { color: #ff8fb3; }
	:root:not([data-theme="light"]) .hl .t-var { color: #7fdcf0; }
}

/* ---------- heading anchors ---------- */

h2, h3 { position: relative; scroll-margin-top: 84px; }
.anchor {
	margin-left: 8px;
	color: var(--ink-3);
	text-decoration: none;
	font-weight: 400;
	opacity: 0;
	transition: opacity 0.12s ease;
}
h2:hover .anchor, h3:hover .anchor, .anchor:focus { opacity: 1; }
.anchor:hover { color: var(--brand); }

/*
 * The shared link landed people at the right scroll position and then left them to
 * work out which paragraph was meant. The highlight says "this bit", then fades so
 * it does not become permanent page furniture.
 */
:target { animation: flash 2.2s ease-out 1; }
@keyframes flash {
	0%, 55% { background: var(--brand-wash); box-shadow: -10px 0 0 var(--brand-wash), 10px 0 0 var(--brand-wash); }
	100% { background: transparent; box-shadow: none; }
}
@media (prefers-reduced-motion: reduce) {
	:target { animation: none; background: var(--brand-wash); }
}

/* ---------- inline URLs and paths ---------- */

/*
 * A path is the single most scanned thing on these pages. Plain inline code made
 * `/v1/orders/{id}` read as ordinary prose, so it got the brand tint and a border.
 */
:not(pre) > code {
	font-family: var(--mono);
	font-size: 0.875em;
	padding: 1.5px 5px;
	border-radius: 5px;
	background: var(--brand-wash);
	border: 1px solid color-mix(in srgb, var(--brand) 22%, transparent);
	color: var(--brand-deep);
	word-break: break-word;
}
/* Inside a coloured pill the tint fights the pill; keep those plain. */
.badge :not(pre) > code, .tag code, aside code { background: none; border: 0; color: inherit; padding: 0; }
a code { color: inherit; }

.top nav a.download::after {
	content: '\2193';
	margin-left: 5px;
	font-size: 12px;
	opacity: 0.65;
}

/* Copy buttons — injected by portal.js into every <pre>. */
pre { position: relative; }
.copy {
	position: absolute;
	top: 8px;
	right: 8px;
	font: inherit;
	font-family: var(--font);
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1;
	padding: 5px 9px;
	color: var(--ink-2);
	background: var(--bg);
	border: 1px solid var(--rule);
	border-radius: 6px;
	cursor: pointer;
	/* Out of the way until wanted, but never fully invisible: a control nobody can
	   see is a control nobody uses. Always visible on touch, which has no hover. */
	opacity: 0.45;
	transition: opacity 0.12s ease, color 0.12s ease;
}
pre:hover .copy, .copy:focus { opacity: 1; }
.copy:hover { color: var(--brand-deep); border-color: var(--brand); }
.copy.done { color: #fff; background: var(--brand-deep); border-color: var(--brand-deep); opacity: 1; }
@media (hover: none) { .copy { opacity: 1; } }

/* Code samples */
.samples {
	border: 1px solid var(--rule);
	border-radius: 12px;
	overflow: hidden;
	background: var(--code-bg);
}
.lang-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
	padding: 6px;
	border-bottom: 1px solid var(--rule);
	background: var(--panel);
}
.lang {
	font: inherit;
	font-size: 12.5px;
	font-family: var(--mono);
	color: var(--ink-2);
	background: none;
	border: 0;
	border-radius: 6px;
	padding: 4px 9px;
	cursor: pointer;
}
.lang:hover { color: var(--ink); background: var(--bg); }
.lang.active { color: #fff; background: var(--brand-deep); }
/* Every sample is in the DOM; exactly one is shown. No sample is "active" until
   the page loads, so default to hidden and let .active reveal. */
.sample { display: none; margin: 0; border: 0; border-radius: 0; max-height: 72vh; }
.sample.active { display: block; }

/*
 * ONBOARDING
 *
 * "How to start" and the three-step block on the front page.
 *
 * The screens below are DRAWN, not screenshotted. A screenshot of a dashboard goes
 * stale the week someone changes a button, and nobody notices until an integrator
 * says the docs do not match what they are looking at — so these are built from the
 * same tokens as the rest of the site, and a redesign makes them look wrong here in
 * a way that is obvious rather than silent. They are illustrations of the SHAPE of
 * each screen; the words on them are the words on the real one.
 */

.steps {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 22px;
	margin: 28px 0 8px;
	padding: 0;
	list-style: none;
}
.steps li {
	position: relative;
	padding: 22px 20px 20px;
	border: 1px solid var(--rule);
	border-radius: 12px;
	background: var(--panel);
	margin: 0;
}
.steps .n {
	display: block;
	font-size: 30px;
	font-weight: 800;
	line-height: 1;
	color: var(--brand);
	opacity: .35;
	margin-bottom: 10px;
	font-variant-numeric: tabular-nums;
}
.steps strong { display: block; font-size: 15px; margin-bottom: 6px; }
.steps p { margin: 0; font-size: 13.5px; color: var(--ink-2); }

/* One numbered step on the How to start page: the instruction, then the screen. */
.howto { counter-reset: howto; }
.howto-step { margin: 40px 0; }
.howto-step > h3 { display: flex; align-items: center; gap: 12px; }
.howto-step > h3::before {
	counter-increment: howto;
	content: counter(howto);
	flex: none;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	background: var(--brand);
	color: #fff;
	font-size: 15px;
	font-weight: 700;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-variant-numeric: tabular-nums;
}

/* A browser window around a drawn screen, so it reads as "this is a page". */
.mock {
	margin: 18px 0 8px;
	border: 1px solid var(--rule);
	border-radius: 10px;
	overflow: hidden;
	background: var(--bg);
	font-size: 13px;
}
.mock-bar {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 9px 12px;
	background: var(--panel);
	border-bottom: 1px solid var(--rule);
}
.mock-bar i { width: 9px; height: 9px; border-radius: 50%; background: var(--tree); }
.mock-url {
	margin-left: 8px;
	padding: 3px 10px;
	border-radius: 20px;
	background: var(--bg);
	border: 1px solid var(--rule);
	color: var(--ink-3);
	font-family: var(--mono);
	font-size: 11.5px;
}
.mock-body { padding: 18px; }
.mock h4 { margin: 0 0 4px; font-size: 15px; }
.mock .sub { margin: 0 0 14px; font-size: 12.5px; color: var(--ink-2); }

.mock-row {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	padding: 10px 12px;
	border-radius: 8px;
	background: var(--panel);
	margin-bottom: 8px;
}
.mock-row .grow { flex: 1; min-width: 90px; }

.mock-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.mock-card {
	border: 1px solid var(--rule);
	border-radius: 10px;
	padding: 14px;
	background: var(--bg);
}
.mock-card.on { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-wash); }
.mock-card b { display: block; margin-bottom: 4px; }
.mock-card span { font-size: 12px; color: var(--ink-2); }

.mock-field {
	border: 1px solid var(--rule);
	border-radius: 7px;
	padding: 8px 11px;
	margin-bottom: 10px;
	color: var(--ink-3);
	background: var(--bg);
}
.mock-field.filled { color: var(--ink); }
.mock-label { display: block; font-size: 11.5px; font-weight: 600; color: var(--ink-2); margin-bottom: 4px; }

.mock-btn {
	display: inline-block;
	padding: 7px 14px;
	border-radius: 8px;
	background: var(--brand);
	color: #fff;
	font-size: 12.5px;
	font-weight: 600;
}
.mock-btn.ghost { background: transparent; color: var(--ink-2); border: 1px solid var(--rule); }

.mock-pill {
	display: inline-block;
	padding: 2px 9px;
	border-radius: 20px;
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .03em;
}
.mock-pill.test { background: #e8f7ee; color: #166534; }
.mock-pill.live { background: #fdecec; color: #991b1b; }
@media (prefers-color-scheme: dark) {
	.mock-pill.test { background: #0f2e1c; color: #7ee2a8; }
	.mock-pill.live { background: #331414; color: #f3a3a3; }
}

.mock code, .mock .mono { font-family: var(--mono); font-size: 12px; }

/* The one-time secret. Orange on purpose — it is the only thing on these screens
   that cannot be recovered if it is missed. */
.mock-warn {
	border: 2px solid #e08b2f;
	background: #fff6ea;
	border-radius: 10px;
	padding: 14px;
}
.mock-warn b { color: #92400e; }
.mock-warn p { margin: 4px 0 10px; font-size: 12.5px; color: #7c4310; }
@media (prefers-color-scheme: dark) {
	.mock-warn { background: #2a1c09; border-color: #a8702a; }
	.mock-warn b { color: #f6c98b; }
	.mock-warn p { color: #e2b482; }
}

.mock-caption {
	margin: 0 0 24px;
	font-size: 12.5px;
	color: var(--ink-3);
}

/*
 * GUIDE SCREENSHOTS, AND THE LIGHTBOX
 *
 * A screenshot of a dashboard is unreadable at prose width — the whole point of one is
 * the small thing an arrow is pointing at. So it renders bounded and clickable, and a
 * click shows it at full size over a dimmed page.
 *
 * Separate from `.mock` above, which are the DRAWN screens. These are real captures and
 * therefore go stale when the UI changes; that is the trade for showing exactly what a
 * seller will see.
 */
.howto-step img,
.shot {
	display: block;
	width: 100%;
	margin: 18px 0 8px;
	border: 1px solid var(--rule);
	border-radius: 10px;
	background: var(--bg);
	cursor: zoom-in;
	transition: border-color .15s, box-shadow .15s;
}
.howto-step img:hover {
	border-color: var(--brand);
	box-shadow: 0 2px 14px rgba(4, 169, 181, .18);
}

/* The caption markdown produces from the alt text, when CommonMark emits a figure. */
.howto-step img + em {
	display: block;
	margin-top: -2px;
	font-size: 12.5px;
	color: var(--ink-3);
}

#lightbox {
	position: fixed;
	inset: 0;
	z-index: 100;
	display: none;
	align-items: center;
	justify-content: center;
	padding: 28px;
	/* Nearly opaque, not translucent: the page behind is a wall of text and it
	   competes with the thing you opened the image to look at. */
	background: rgba(8, 20, 22, .92);
	cursor: zoom-out;
}
#lightbox.open { display: flex; }
#lightbox img {
	max-width: 100%;
	max-height: 100%;
	border-radius: 8px;
	box-shadow: 0 18px 60px rgba(0, 0, 0, .5);
}
#lightbox .close {
	position: absolute;
	top: 18px;
	right: 22px;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, .35);
	background: rgba(255, 255, 255, .08);
	color: #fff;
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
}
#lightbox .close:hover { background: rgba(255, 255, 255, .18); }

/* Scrolling the page under an open overlay is disorienting, and on a phone it is how
   you end up scrolled somewhere unexpected when it closes. */
body.lightbox-open { overflow: hidden; }

/*
 * ENVIRONMENT PICKER
 *
 * Two cards, deliberately large: choosing the wrong base URL is the single commonest
 * way a first integration wastes an afternoon, and the error it produces (401) looks
 * like a bad key rather than a wrong host.
 *
 * The choice is remembered and rewrites every fenced example on the site, so it has to
 * look like a control rather than a note.
 */
.envpick {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: 14px;
	margin: 20px 0 26px;
}
.envpick button {
	display: block;
	text-align: left;
	padding: 16px 18px;
	border: 2px solid var(--rule);
	border-radius: 12px;
	background: var(--bg);
	color: var(--ink);
	font: inherit;
	cursor: pointer;
	transition: border-color .15s, background .15s, box-shadow .15s;
}
.envpick button:hover { border-color: var(--brand); }
.envpick button[aria-pressed="true"] {
	border-color: var(--brand);
	background: var(--brand-wash);
	box-shadow: 0 0 0 3px var(--brand-wash);
}

.envpick .tag {
	display: inline-block;
	padding: 2px 10px;
	border-radius: 20px;
	background: #e8f7ee;
	color: #166534;
	font-size: 11px;
	font-weight: 800;
	letter-spacing: .06em;
}
.envpick .tag.live { background: #fdecec; color: #991b1b; }
@media (prefers-color-scheme: dark) {
	.envpick .tag { background: #0f2e1c; color: #7ee2a8; }
	.envpick .tag.live { background: #331414; color: #f3a3a3; }
}

.envpick .url {
	display: block;
	margin: 9px 0 6px;
	font-family: var(--mono);
	font-size: 13.5px;
	font-weight: 600;
	color: var(--ink);
	word-break: break-all;
}
.envpick .note { display: block; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.envpick .note code { font-size: 11.5px; }

/*
 * The header badge — the far-right anchor of the header, not a nav link.
 *
 * It was an outlined grey pill sitting fourth in the nav, and it read as another
 * menu item: people did not see it at all. It is now filled, tinted by mode, and
 * pushed to the opposite end of the header from the logo, where nothing competes
 * with it. It states the host too, because "TEST" on its own does not answer the
 * question a reader actually has — which base URL am I looking at?
 */
.envbadge {
	margin-left: auto;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 7px 8px 7px 14px;
	border-radius: 22px;
	border: 1px solid var(--good);
	/* colour-mix would be tidier, but this file supports browsers without it. */
	background: rgba(22, 163, 74, .10);
	color: var(--ink);
	font-size: 13px;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	transition: box-shadow .15s ease, transform .15s ease;
}
.envbadge:hover {
	color: var(--ink);
	box-shadow: 0 0 0 3px rgba(22, 163, 74, .16);
}
.envbadge .dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--good);
	/* A ring rather than a bare dot, so the state reads at a glance from across
	   the header without relying on an 8px circle alone. */
	box-shadow: 0 0 0 3px rgba(22, 163, 74, .22);
	flex: none;
}
.envbadge .label {
	font-size: 11.5px;
	font-weight: 800;
	letter-spacing: .08em;
	color: var(--good);
}
.envbadge .host {
	font-family: var(--mono);
	font-size: 12px;
	font-weight: 600;
	color: var(--ink);
}
/* The affordance. Without it the pill looks like a status readout, not a control. */
.envbadge .swap {
	padding: 3px 9px;
	border-radius: 14px;
	background: var(--bg);
	border: 1px solid var(--rule);
	font-size: 11px;
	font-weight: 600;
	color: var(--ink-2);
}
.envbadge:hover .swap { border-color: var(--good); color: var(--good); }

.envbadge.live {
	border-color: var(--bad);
	background: rgba(220, 38, 38, .10);
}
.envbadge.live:hover { box-shadow: 0 0 0 3px rgba(220, 38, 38, .16); }
.envbadge.live .label { color: var(--bad); }
.envbadge.live .dot { background: var(--bad); box-shadow: 0 0 0 3px rgba(220, 38, 38, .22); }
.envbadge.live:hover .swap { border-color: var(--bad); color: var(--bad); }

/*
 * Narrow: the header wraps, so `margin-left: auto` no longer pushes the badge
 * anywhere. Drop the host and the hint and keep the mode, which is the part that
 * has to survive.
 */
@media (max-width: 860px) {
	.envbadge { margin-left: 0; padding: 5px 12px; }
	.envbadge .host, .envbadge .swap { display: none; }
}

@media (max-width: 1200px) {
	/* The samples drop under the prose before the navigation does — losing the
	   endpoint list costs more than reading the sample a screen lower. */
	.shell.three { grid-template-columns: 250px minmax(0, 1fr); }
	.shell.three .sidepanel { grid-column: 1 / -1; position: static; }
}

@media (max-width: 860px) {
	/* Below this width a fixed table cannot fit; let it scroll on its own rather
	   than push the page sideways. */
	table { display: block; overflow-x: auto; table-layout: auto; }
	.fields th, .fields td { width: auto !important; }

	/* minmax(0, …), not 1fr: a bare `1fr` floors the column at the widest child's
	   min-content, and a stacked code sample is ~600px wide — the whole page then
	   scrolled sideways on a phone. */
	.shell, .shell.three { grid-template-columns: minmax(0, 1fr); gap: 24px; padding-top: 24px; }
	aside { position: static; }
	aside ul { display: flex; flex-wrap: wrap; gap: 6px; border-left: 0; }
	aside a { border: 1px solid var(--rule); border-radius: 4px; padding: 4px 10px; margin: 0; }
	/* The endpoint rail is 82 items — a wrapped chip cloud is unusable, so it stays
	   a list and simply scrolls to a bounded height. */
	/* Stacked: the rail is no longer sticky, so cap the LIST instead of the aside. */
	aside { display: block; max-height: none; }
	aside #nav-list { display: block; max-height: 320px; overflow-y: auto; border-left: 1px solid var(--rule); }
	aside #nav-list a { border: 0; border-radius: 0; padding: 6px 0; }
}
