/*
 * One stylesheet for both pages.
 *
 * The palette is the one godrop.sh already had, so the hosted service looks
 * like the project it belongs to rather than a second product with the same
 * name. Sans for prose, mono for anything a machine reads or a person copies.
 */

/* Light only, whatever the system is set to. One palette to get right, and
 * screenshots of the site look the same on every machine they are taken on. */
:root {
	color-scheme: light;
	--bg: #fbfbfa;
	--fg: #1a1a19;
	--muted: #6b6b66;
	--line: #e4e4e0;
	--accent: #0a7d55;
	--code-bg: #f2f2ef;
	--card: #ffffff;
	--danger: #a3311f;
	/* Two hues for a JSON answer, and neutrals for everything structural.
	   The values are what a reader came for, so the values are what carries
	   colour; braces and keys stay out of the way. */
	--json-string: #0a7d55;
	--json-number: #9a5f14;
	/* A solid button is near-black. Brand colour is for identity, not for
	   every call to action. */
	--solid: #1a1a19;
	--solid-fg: #fbfbfa;
	--solid-hover: #333330;

	/* Three corners and no others.
	 *
	 * There were twenty one, from 4px to 14px by way of every number in
	 * between, which is what a stylesheet looks like when each rule picked a
	 * corner on its own. Swiss has nothing to say about how round a button
	 * is; it has a great deal to say about a measurement that came from
	 * nowhere, and that is what those were. The proportions come from the
	 * mark, whose own corner is 9 of its 64 units, so the interface and the
	 * thing it belongs to round by the same rule.
	 *
	 * --r-1 is for what sits inside something else, --r-2 for a working
	 * surface (a button, a panel, a code block, a field), --r-3 for the
	 * outermost container. 999px stays where it is a shape rather than a
	 * corner, which is the pills and nothing else.
	 *
	 * The drawing of the Mac keeps its own, in em so that they scale with it:
	 * its corners are its subject's, not ours. */
	--r-1: 6px;
	--r-2: 10px;
	--r-3: 14px;
}

* {
	box-sizing: border-box;
}

/*
 * Where a jump to an anchor stops.
 *
 * The bar is sticky, so an anchor followed from an index put its heading at
 * the very top of the viewport, which is underneath the bar: the section you
 * asked for opened with its first line covered. This is the height of the bar
 * and a little air, and it is set on the scroll container so that it applies
 * to every anchor on the site rather than to the ones somebody remembered.
 */
html {
	scroll-padding-top: 5.5rem;

	/* No rubber band at either end. Pulling past the top or the bottom used
	   to bounce the whole page and show what is behind it, which on a page
	   whose first and last elements are a sticky bar and a ruled footer reads
	   as the layout coming apart rather than as a scroll gesture.
	   
	   It costs pull to refresh on Android, which is a real gesture somebody
	   may want back; it is one line either way. */
	overscroll-behavior-y: none;
}

/*
 * One grotesque, served from here rather than from a font host.
 *
 * The page read as a template for as long as it used the system sans, because
 * that is what a page looks like when nobody chose anything. A single face
 * carries the whole identity, which is the Swiss argument for it, and 46 KB
 * of variable woff2 covering Latin is the entire cost. It is preloaded in the
 * head so the swap window is short, and the system stack behind it is close
 * enough in width that nothing moves far while it lands.
 */
@font-face {
	font-family: "Schibsted Grotesk";
	src: url("/schibsted-grotesk.woff2") format("woff2");
	font-weight: 400 900;
	font-style: normal;
	font-display: swap;
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--fg);
	font: 16px/1.6 "Schibsted Grotesk", ui-sans-serif, -apple-system, "Segoe UI", system-ui,
		sans-serif;
	-webkit-font-smoothing: antialiased;
}

code,
pre,
.mono {
	font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
}

/* --------------------------------------------------------------- top bar */

.bar {
	border-bottom: 1px solid var(--line);
	background: var(--bg);
	position: sticky;
	top: 0;
	z-index: 10;
}

.bar-inner {
	max-width: 52rem;
	margin: 0 auto;
	padding: 0.85rem 1.5rem;
	display: flex;
	align-items: center;
	gap: 0.7rem;
}

.brand {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	font-weight: 650;
	letter-spacing: -0.015em;
	color: var(--fg);
	text-decoration: none;
	font-size: 1.02rem;
}

.brand img {
	width: 22px;
	height: 22px;
	display: block;
}

/* The face on the account button, sized to the text beside it. */
.account-mark {
	width: 1.05em;
	height: 1.05em;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.6;
	stroke-linecap: round;
	flex: none;
}

.bar .spacer {
	flex: 1;
}

/* An icon on its own, with no button around it: it goes somewhere rather than
   doing something, and the bar has one call to action already. */
.icon-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.1rem;
	height: 2.1rem;
	margin-right: -0.35rem;
	border-radius: var(--r-2);
	/* The mark itself, dimmed rather than greyed: a logo in the wrong colour
	   stops looking like the logo. */
	color: var(--fg);
	opacity: 0.72;
	text-decoration: none;
	transition: opacity 0.12s ease, background 0.12s ease;
}

.icon-link:hover {
	opacity: 1;
	background: var(--code-bg);
}

.icon-link svg {
	display: block;
}

/* ---------------------------------------------------------------- layout */

main {
	max-width: 52rem;
	margin: 0 auto;
	padding: 3.5rem 1.5rem 6rem;
}

h1 {
	font-size: clamp(2rem, 6vw, 2.9rem);
	line-height: 1.08;
	letter-spacing: -0.03em;
	margin: 0 0 0.7rem;
	text-wrap: balance;
}

.lede {
	font-size: 1.12rem;
	color: var(--muted);
	margin: 0 0 2rem;
	max-width: 34rem;
	text-wrap: pretty;
}

h2 {
	font-size: 0.78rem;
	text-transform: uppercase;
	letter-spacing: 0.11em;
	color: var(--muted);
	margin: 3.2rem 0 1rem;
	font-weight: 620;
}

h3 {
	font-size: 1rem;
	font-weight: 620;
	margin: 0 0 0.4rem;
}

p {
	text-wrap: pretty;
}

a {
	color: var(--accent);
}

/* ----------------------------------------------------------------- code */

pre {
	background: var(--code-bg);
	border: 1px solid var(--line);
	border-radius: var(--r-2);
	padding: 1rem 1.1rem;
	overflow-x: auto;
	margin: 0 0 1rem;
	font-size: 13.5px;
	line-height: 1.7;
	position: relative;
}

p code,
li code,
td code {
	background: var(--code-bg);
	border: 1px solid var(--line);
	border-radius: var(--r-1);
	padding: 0.1em 0.35em;
	font-size: 0.9em;
}

.cmt {
	color: var(--muted);
}

/* copy.js wraps each code block in one of these and puts the button here
   rather than inside the <pre>, which scrolls. */
.code-block {
	position: relative;
	margin-bottom: 1rem;
}

.code-block pre {
	margin-bottom: 0;
}

/*
 * A labelled block: a strip above it saying what it is, with the copy button
 * living in that strip. Somewhere to put the button that is never over the
 * code beats hiding it until hover, which a phone cannot do anyway.
 */
.code-head {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.4rem 0.5rem 0.4rem 1.1rem;
	background: var(--card);
	border: 1px solid var(--line);
	border-bottom: none;
	border-radius: var(--r-2) var(--r-2) 0 0;
	font-size: 0.7rem;
	font-weight: 620;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--muted);
}

.code-head .spacer {
	flex: 1;
}

/* The status the server answered with. Not a label: it is what came back. */
.code-head .status {
	font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
	text-transform: none;
	letter-spacing: 0;
	color: var(--accent);
	padding-right: 0.6rem;
}

/* A refusal should not be the same colour as a success. */
.code-head .status.bad {
	color: var(--danger);
}

.code-block.labelled pre {
	border-radius: 0 0 var(--r-2) var(--r-2);
}

/*
 * One request and what came back from it, read as a single thing. Without
 * this a response is just a second code block, which is exactly how it does
 * not look on any terminal anybody has used.
 */
.exchange {
	border: 1px solid var(--line);
	border-radius: var(--r-2);
	overflow: hidden;
	margin-bottom: 1rem;
}

.exchange .code-block {
	margin-bottom: 0;
}

.exchange .code-head,
.exchange pre {
	border-radius: 0;
	border-left: none;
	border-right: none;
}

.exchange .code-block:first-child .code-head {
	border-top: none;
}

.exchange .code-block:last-child pre {
	border-bottom: none;
}

/* What the server said, which nobody types and nobody copies. */
.exchange pre[data-output] {
	color: var(--muted);
	/* Wrapped rather than scrolled: the URL is the point of the answer, and a
	   URL that runs off the edge is one the reader cannot see or click. */
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

/* The copy button on a code block is added by copy.js, so it is never there
   without one, and it stays out of the way until the block is hovered. */
.copy {
	position: absolute;
	top: 0.5rem;
	right: 0.5rem;
	padding: 0.25rem 0.6rem;
	border: 1px solid var(--line);
	border-radius: var(--r-1);
	background: var(--card);
	color: var(--muted);
	font: 600 11px/1.6 ui-sans-serif, system-ui, sans-serif;
	letter-spacing: 0.03em;
	cursor: pointer;
	opacity: 0;
	transition: opacity 0.12s ease, color 0.12s ease;
}

.code-block:hover .copy,
.copy:focus-visible {
	opacity: 1;
}

.copy:hover {
	color: var(--fg);
}

/* In a strip of its own there is nothing to hide from, so it stays. */
.code-head .copy {
	position: static;
	opacity: 1;
}

/* The button that actually sends the request above it. Solid, because it is
   the one thing on this page that does something rather than copying it. */
.code-head .run {
	padding: 0.25rem 0.7rem;
	border-radius: var(--r-1);
	border: 1px solid var(--solid);
	background: var(--solid);
	color: var(--solid-fg);
	font: 600 11px/1.6 ui-sans-serif, system-ui, sans-serif;
	letter-spacing: 0.03em;
	cursor: pointer;
	transition: opacity 0.12s ease;
}

.code-head .run:hover {
	background: var(--solid-hover);
	border-color: var(--solid-hover);
}

.code-head .run:disabled {
	opacity: 0.55;
	cursor: default;
}

/* A link inside an answer: the URL that came back is worth clicking. */
.exchange pre[data-output] a {
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
}

/*
 * Touch has no hover, so the button is always there, and a button that is
 * always there cannot sit on top of the code it belongs to. On a phone it
 * drops below the block instead, where it covers nothing. A labelled block
 * already has somewhere better to put it.
 */
@media (hover: none) {
	/* A finger is not a cursor: give it something worth aiming at. */
	.copy,
	.code-head .run {
		padding: 0.55rem 0.85rem;
	}

	.code-block:not(.labelled) {
		display: flex;
		flex-direction: column;
		align-items: flex-end;
	}

	.code-block:not(.labelled) pre {
		width: 100%;
	}

	.code-block:not(.labelled) .copy {
		position: static;
		opacity: 1;
		margin-top: 0.4rem;
	}
}

/* --------------------------------------------------------------- buttons */

/* Every button here is display: inline-flex, and an author rule beats the
   browser's own [hidden] { display: none }. So a button the JavaScript hides
   renders anyway, as an empty pill with no label, which is exactly what the
   plan card shipped. This has to come before the rule that causes it, and it
   applies to every element on the page rather than only that one. */
[hidden] {
	display: none !important;
}

button,
.btn {
	font: inherit;
	font-size: 0.92rem;
	font-weight: 560;
	border-radius: var(--r-2);
	border: 1px solid var(--line);
	background: var(--card);
	color: var(--fg);
	padding: 0.5rem 0.9rem;
	cursor: pointer;
	text-decoration: none;
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	transition: border-color 0.12s ease, background 0.12s ease, opacity 0.12s ease;
}

button:hover,
.btn:hover {
	border-color: var(--muted);
}

button:disabled {
	opacity: 0.55;
	cursor: default;
}

.btn-primary,
button.primary {
	background: var(--solid);
	border-color: var(--solid);
	color: var(--solid-fg);
}

.btn-primary:hover,
button.primary:hover {
	background: var(--solid-hover);
	border-color: var(--solid-hover);
}

.btn-quiet {
	background: none;
	border-color: transparent;
	color: var(--muted);
	padding: 0.35rem 0.5rem;
}

.btn-quiet:hover {
	color: var(--fg);
	border-color: var(--line);
}

.btn-danger:hover {
	color: var(--danger);
	border-color: var(--danger);
}

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

/* The one button the page is built around. */
.agent-copy {
	font-size: 0.97rem;
	padding: 0.7rem 1.15rem;
}

/* The instructions are long on purpose, but they should not push the rest of
   the page out of reach when they appear. */
#instructions {
	max-height: 22rem;
	overflow: auto;
	white-space: pre-wrap;
	margin-top: 1rem;
}

/* ----------------------------------------------------------------- cards */

.card {
	background: var(--card);
	border: 1px solid var(--line);
	border-radius: var(--r-3);
	padding: 1rem 1.15rem;
}

/* Two by two rather than three and a lonely fourth: the column floor is set
   so that four cards never try to fit across this measure. */
.grid {
	display: grid;
	/* min() rather than a bare 18rem: on a narrow phone the track would
	   otherwise hold its minimum and push the card past the screen. */
	grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
	gap: 0.8rem;
}

.grid .card b {
	display: block;
	font-size: 0.95rem;
	margin-bottom: 0.2rem;
}

.grid .card span {
	color: var(--muted);
	font-size: 0.9rem;
}

.muted {
	color: var(--muted);
}

.small {
	font-size: 0.9rem;
}

.note {
	border-left: 2px solid var(--line);
	padding-left: 1rem;
	color: var(--muted);
	font-size: 0.93rem;
}

/* ---------------------------------------------------------------- tables */

/* Wide content scrolls inside its own box rather than taking the page
   sideways with it. */
.scroll {
	overflow-x: auto;
	margin-bottom: 1rem;
}

table {
	border-collapse: collapse;
	width: 100%;
	font-size: 0.94rem;
}

th,
td {
	text-align: left;
	padding: 0.55rem 0.9rem 0.55rem 0;
	border-bottom: 1px solid var(--line);
	vertical-align: top;
}

thead th {
	font-size: 0.76rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--muted);
	font-weight: 620;
}

tbody th {
	font-weight: 550;
	white-space: nowrap;
	padding-right: 1.6rem;
}

tbody tr:last-child th,
tbody tr:last-child td {
	border-bottom: none;
}

/* ----------------------------------------------------------------- lists */

.rows {
	border: 1px solid var(--line);
	border-radius: var(--r-3);
	background: var(--card);
	overflow: hidden;
}

.row {
	display: flex;
	align-items: center;
	gap: 0.8rem;
	padding: 0.75rem 1rem;
	border-bottom: 1px solid var(--line);
}

.row:last-child {
	border-bottom: none;
}

.row .grow {
	flex: 1;
	min-width: 0;
}

.row .name {
	font-weight: 550;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.row .meta {
	color: var(--muted);
	font-size: 0.85rem;
	display: flex;
	gap: 0.55rem;
	flex-wrap: wrap;
	font-variant-numeric: tabular-nums;
}

.row .actions {
	display: flex;
	gap: 0.2rem;
	flex-shrink: 0;
}

/*
 * The rest of a list, when there is more of it.
 *
 * Reads as the last row rather than as a control beside the list, and takes no
 * top border of its own: the row above it already drew that line, and two
 * would be a two pixel seam.
 */
.rows-more {
	display: block;
	width: 100%;
	font: inherit;
	font-size: 0.88rem;
	font-weight: 550;
	color: var(--muted);
	background: none;
	border: 0;
	padding: 0.75rem 1rem;
	text-align: center;
	cursor: pointer;
}

.rows-more:hover {
	color: var(--fg);
	background: var(--code-bg);
}

.empty {
	padding: 2.2rem 1rem;
	text-align: center;
	color: var(--muted);
	font-size: 0.95rem;
}

.section-head {
	display: flex;
	align-items: baseline;
	gap: 0.8rem;
	margin: 3.2rem 0 1rem;
}

.section-head h2 {
	margin: 0;
}

.section-head .spacer {
	flex: 1;
}

.mcp-head {
	font-size: 0.9rem;
	font-weight: 560;
	color: var(--muted);
	margin: 1.1rem 0 0.4rem;
}

/* --------------------------------------------------------------- footer */

footer {
	margin-top: 4.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--line);
	color: var(--muted);
	font-size: 0.9rem;
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	justify-content: space-between;
}

/* -------------------------------------------------------------- waiting */

/*
 * Two kinds of waiting, because there are two kinds of not knowing yet.
 *
 * Before Clerk answers, the page cannot tell whether a sign-in card or a
 * dashboard is coming, so a spinner says "wait" without promising a shape.
 * Once the shape is known, skeleton rows say what is arriving and stop the
 * layout jumping when it does.
 */
.spinner {
	width: 1.4rem;
	height: 1.4rem;
	margin: 5rem auto;
	border: 2px solid var(--line);
	border-top-color: var(--muted);
	border-radius: 50%;
	animation: spin 0.7s linear infinite;
}

@keyframes spin {
	to {
		transform: rotate(360deg);
	}
}

.skeleton {
	background: linear-gradient(90deg, var(--line) 25%, var(--code-bg) 50%, var(--line) 75%);
	background-size: 200% 100%;
	border-radius: var(--r-1);
	animation: sheen 1.4s ease-in-out infinite;
}

@keyframes sheen {
	to {
		background-position: -200% 0;
	}
}

.skeleton-name {
	height: 0.95rem;
	width: 42%;
	margin-bottom: 0.45rem;
}

.skeleton-meta {
	height: 0.75rem;
	width: 22%;
}

/* Motion off means a plain resting state, not a frozen half-animation. */
@media (prefers-reduced-motion: reduce) {
	.spinner {
		animation: none;
		border-top-color: var(--line);
	}

	.skeleton {
		animation: none;
		background: var(--line);
	}
}

/* ----------------------------------------------------------------- modal */

dialog {
	border: 1px solid var(--line);
	border-radius: var(--r-3);
	background: var(--card);
	color: var(--fg);
	padding: 0;
	width: min(30rem, calc(100vw - 2rem));
	box-shadow: 0 18px 48px rgb(0 0 0 / 18%);
}

dialog::backdrop {
	background: rgb(0 0 0 / 38%);
	backdrop-filter: blur(2px);
}

.modal-body {
	padding: 1.4rem 1.5rem 1.2rem;
	display: grid;
	gap: 0.9rem;
}

.modal-body h3 {
	margin: 0;
	font-size: 1.05rem;
}

.modal-body label {
	font-size: 0.85rem;
	font-weight: 560;
	display: block;
	margin-bottom: 0.35rem;
}

.modal-body input {
	font: inherit;
	font-size: 0.95rem;
	width: 100%;
	padding: 0.55rem 0.7rem;
	border: 1px solid var(--line);
	border-radius: var(--r-2);
	background: var(--bg);
	color: var(--fg);
}

.modal-actions {
	display: flex;
	justify-content: flex-end;
	gap: 0.5rem;
	margin-top: 0.2rem;
}

/* The secret, on the one screen it will ever appear on. */
.secret-row {
	display: flex;
	align-items: stretch;
	gap: 0.4rem;
}

.secret-row .secret {
	flex: 1;
	min-width: 0;
}

.secret-row button {
	flex-shrink: 0;
	align-self: stretch;
}

.secret {
	font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
	font-size: 0.85rem;
	background: var(--code-bg);
	border: 1px solid var(--line);
	border-radius: var(--r-2);
	padding: 0.7rem 0.8rem;
	word-break: break-all;
	user-select: all;
}

.warn {
	font-size: 0.87rem;
	color: var(--muted);
	border-left: 2px solid var(--danger);
	padding-left: 0.8rem;
}

/* ---------------------------------------------------------------- toasts */

.toast {
	position: fixed;
	left: 50%;
	bottom: 1.5rem;
	transform: translateX(-50%) translateY(0.5rem);
	background: var(--fg);
	color: var(--bg);
	padding: 0.55rem 1rem;
	border-radius: var(--r-2);
	font-size: 0.9rem;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.15s ease, transform 0.15s ease;
	z-index: 50;
}

.toast.show {
	opacity: 1;
	transform: translateX(-50%) translateY(0);
}

@media (prefers-reduced-motion: reduce) {
	* {
		transition: none !important;
		animation: none !important;
	}
}

.hidden {
	display: none !important;
}

/* Signed out, the page is one card and nothing else. Anything written above
   it is read once and in the way forever after. */
.centered {
	display: grid;
	place-items: center;
	min-height: 70vh;
}

/* ----------------------------------------------------------------- phones */

/*
 * A row that is a name beside its buttons needs room for both. On a phone
 * there is room for one, and squeezing them together truncates the file name
 * to nothing while the buttons keep their full width. So the row stacks: the
 * file first, what to do with it underneath.
 */
@media (max-width: 34rem) {
	.row {
		flex-direction: column;
		align-items: stretch;
		gap: 0.5rem;
	}

	.row .actions {
		/* Pull the first button's label back into line with the name above
		   it, past its own padding. */
		margin-left: -0.5rem;
	}

	.row .actions .btn,
	.row .actions button {
		/* Comfortably hittable with a thumb. */
		padding: 0.5rem 0.6rem;
	}

	.bar-inner,
	main {
		padding-left: 1.1rem;
		padding-right: 1.1rem;
	}

	.section-head {
		margin-top: 2.4rem;
	}
}


/* ---------------------------------------------------------------- the drop */

/*
 * The hero does the thing the page describes rather than describing it. A
 * visitor with a file in their hand should not have to read a curl line first,
 * and somebody who has just taken a screenshot should be able to paste it into
 * the page they are already looking at.
 */
.hero {
	display: grid;
	/* minmax(0, 1fr) rather than 1fr: a bare 1fr is minmax(auto, 1fr), and that
	 * auto minimum refuses to shrink below the widest thing inside. One result
	 * row holds an eighty character URL, so the column grew past the page and
	 * took the whole layout with it. */
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: 2.4rem;
	align-items: center;
	margin-bottom: 1rem;
}

.hero .lede {
	margin-bottom: 0;
}

.drop {
	min-width: 0;
	border: 2px dashed var(--line);
	border-radius: var(--r-3);
	background: var(--card);
	padding: 2.2rem 1.4rem;
	text-align: center;
	transition: border-color 0.15s, background 0.15s;
}

/* Dragging anywhere over the page lights it up: the target is easy to miss
 * and a drop that lands on the document is a drop that goes nowhere. */
.drop.over {
	border-color: var(--accent);
	background: var(--code-bg);
}

/* The input is what the keyboard and the screen reader use; the label is what
 * everybody else clicks. Hiding it with display:none would take it out of the
 * tab order, so it is only made invisible. */
.drop input[type="file"] {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

/* The input comes first in the markup so that the ring can land on the label,
 * which is the thing anybody can see. */
.drop input[type="file"]:focus-visible + label {
	outline: 2px solid var(--accent);
	outline-offset: 3px;
}

.drop label {
	cursor: pointer;
}

.drop-hint {
	margin: 0.9rem 0 0;
	font-size: 0.92rem;
	color: var(--muted);
}

.paste-hint {
	font-size: 0.85rem;
	opacity: 0.85;
}

.drop-bar {
	height: 4px;
	border-radius: 999px;
	background: var(--line);
	margin-top: 1rem;
	overflow: hidden;
}

.drop-bar div {
	height: 100%;
	width: 0;
	background: var(--accent);
	transition: width 0.12s linear;
}

.drop-out {
	margin-top: 1rem;
	font-size: 0.9rem;
	text-align: left;
}

.drop-out:empty {
	display: none;
}

.drop-file {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.5rem 0;
	border-top: 1px solid var(--line);
}

.drop-file:first-child {
	border-top: 0;
}

.drop-file img {
	width: 34px;
	height: 34px;
	object-fit: cover;
	border-radius: var(--r-1);
	flex: none;
	background: var(--code-bg);
}

.drop-file .grow {
	min-width: 0;
	flex: 1;
}

.drop-file a {
	display: block;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: 550;
	font-size: 0.88rem;
}

.drop-file .when {
	color: var(--muted);
	font-size: 0.78rem;
}

.drop-error {
	color: var(--danger);
	text-align: center;
}

@media (max-width: 44rem) {
	.hero {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.5rem;
	}

}

/* Whether paste is worth mentioning is a question about the input device, not
 * about how wide the window is: a narrow window on a laptop still has a
 * keyboard, and a wide tablet still has no Cmd+V. */
@media (hover: none) {
	.paste-hint {
		display: none;
	}
}

/* -------------------------------------------------------------- composer */

/* The dashboard's upload box. The same drop as the hero, shorter, because on
 * this page it sits above a list somebody came to read. */
.composer {
	margin-bottom: 0.9rem;
}

.composer-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: 0.8rem;
}

.composer-head .spacer,
.text-foot .spacer {
	flex: 1;
}

.tabs {
	display: inline-flex;
	padding: 2px;
	border: 1px solid var(--line);
	border-radius: var(--r-2);
	background: var(--code-bg);
}

.tabs button {
	border: 0;
	background: none;
	color: var(--muted);
	padding: 0.3rem 0.8rem;
	border-radius: var(--r-1);
}

.tabs button[aria-selected="true"] {
	background: var(--card);
	color: var(--fg);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

.composer select,
.composer textarea,
.composer input[type="text"] {
	font: inherit;
	font-size: 0.9rem;
	border: 1px solid var(--line);
	border-radius: var(--r-2);
	background: var(--bg);
	color: var(--fg);
	padding: 0.4rem 0.6rem;
	min-width: 0;
}

.composer .drop {
	padding: 1.4rem 1rem;
}

.composer textarea {
	display: block;
	width: 100%;
	resize: vertical;
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 0.85rem;
	line-height: 1.5;
	padding: 0.6rem 0.7rem;
}

.text-foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-top: 0.6rem;
}

.text-foot input[type="text"] {
	flex: 0 1 16rem;
}

/* --------------------------------------------------------------- mac app */

/* A section heading is set in small caps with wide tracking, so the pill
 * undoes both rather than inheriting a label that shouts. */
.beta {
	display: inline-block;
	margin-left: 0.4rem;
	padding: 0.05rem 0.45rem;
	border: 1px solid var(--line);
	border-radius: 999px;
	font-size: 0.7rem;
	font-weight: 560;
	letter-spacing: 0;
	text-transform: none;
	color: var(--muted);
	vertical-align: middle;
}

kbd {
	font: 0.8rem ui-monospace, SFMono-Regular, Menlo, monospace;
	padding: 0.05rem 0.35rem;
	border: 1px solid var(--line);
	border-bottom-width: 2px;
	border-radius: var(--r-1);
	background: var(--card);
}

/* ------------------------------------------------------------------ demo */

/*
 * The Mac app, shown working: right click, Services, Upload to GoDrop, the
 * notification, the paste. Every size inside is in em and every em is a
 * fraction of the box's own width, so the scene scales as one picture instead
 * of reflowing like a page. Every animation runs on the same ten seconds and
 * the percentages below are that clock.
 *
 * The resting styles are the last frame. With reduced motion the animations
 * are removed and what is left is a still of the link already pasted.
 */
.demo {
	container-type: inline-size;
	margin-top: 1rem;
	border: 1px solid var(--line);
	border-radius: var(--r-3);
	overflow: hidden;
	background: linear-gradient(160deg, #f3f3f0, #e9e9e4);
}

.demo-stage {
	position: relative;
	aspect-ratio: 16 / 9;
	font: 1.45cqw/1.6 -apple-system, "Segoe UI", Inter, system-ui, sans-serif;
	color: #1a1a19;
	user-select: none;
}

.demo-stage > * {
	position: absolute;
}

.demo-menubar {
	top: 0;
	left: 0;
	right: 0;
	height: 6%;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 1.2em;
	padding: 0 2%;
	font-size: 0.85em;
	background: rgba(255, 255, 255, 0.6);
}

.demo-status {
	position: relative;
	width: 1.35em;
	height: 1.35em;
}

.demo-status svg {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
}

.demo-status-icon circle {
	fill: #1a1a19;
}

.demo-status-icon path {
	fill: none;
	stroke: #fff;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.demo-ring {
	opacity: 0;
	transform: rotate(-90deg);
}

.demo-ring circle {
	fill: none;
	stroke: #1a1a19;
	stroke-width: 2.4;
	stroke-dasharray: 50.3;
}

.demo-window {
	left: 5%;
	top: 14%;
	width: 50%;
	height: 72%;
	background: #fff;
	border-radius: 0.8em;
	box-shadow: 0 1.2em 3em rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.06);
	overflow: hidden;
}

.demo-titlebar {
	display: flex;
	align-items: center;
	gap: 0.45em;
	height: 13%;
	padding: 0 3%;
	border-bottom: 1px solid #ececea;
	font-size: 0.9em;
	font-weight: 600;
}

.demo-titlebar i {
	width: 0.8em;
	height: 0.8em;
	border-radius: 50%;
	background: #ff5f57;
}

.demo-titlebar i:nth-child(2) {
	background: #febc2e;
}

.demo-titlebar i:nth-child(3) {
	background: #28c840;
}

.demo-titlebar span {
	flex: 1;
	text-align: center;
	margin-right: 2.4em;
}

.demo-row {
	display: flex;
	align-items: center;
	gap: 0.7em;
	height: 12%;
	margin: 0 2%;
	padding: 0 2%;
	border-radius: 0.4em;
	font-size: 0.95em;
}

.demo-row em {
	margin-left: auto;
	font-style: normal;
	font-size: 0.85em;
	opacity: 0.55;
}

.demo-thumb {
	width: 1.3em;
	height: 1.6em;
	border-radius: 0.2em;
	background: #dfe3e8;
}

.demo-thumb.demo-image {
	background: linear-gradient(135deg, #cfd6d2, #9aa8a0);
}

.demo-menu,
.demo-submenu {
	padding: 0.35em;
	font-size: 0.9em;
	background: rgba(250, 250, 250, 0.97);
	border-radius: 0.6em;
	box-shadow: 0 0.8em 2.4em rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
	opacity: 0;
}

.demo-menu {
	left: 22%;
	top: 29%;
	width: 19%;
}

.demo-submenu {
	left: 40.5%;
	top: 45%;
	width: 18%;
}

.demo-menu div,
.demo-submenu div {
	display: flex;
	padding: 0.25em 0.7em;
	border-radius: 0.35em;
}

.demo-menu b {
	margin-left: auto;
	font-weight: 400;
}

.demo-menu hr {
	margin: 0.3em 0.5em;
	border: 0;
	border-top: 1px solid #dddddb;
}

.demo-toast {
	right: 3%;
	top: 9%;
	width: 33%;
	display: flex;
	align-items: center;
	gap: 0.8em;
	padding: 0.8em 1em;
	background: rgba(255, 255, 255, 0.94);
	border-radius: 1em;
	box-shadow: 0 0.8em 2.4em rgba(0, 0, 0, 0.14), 0 0 0 1px rgba(0, 0, 0, 0.06);
}

.demo-toast img {
	width: 2.4em;
	height: 2.4em;
}

.demo-toast strong {
	display: block;
	font-size: 0.95em;
}

.demo-toast span {
	font-size: 0.85em;
	color: #6b6b66;
}

.demo-comment {
	right: 3%;
	top: 42%;
	width: 37%;
	height: 44%;
	background: #fff;
	border: 1px solid #d0d7de;
	border-radius: 0.7em;
	overflow: hidden;
	opacity: 0;
}

.demo-comment-head {
	padding: 0.55em 0.9em;
	font-size: 0.85em;
	font-weight: 600;
	background: #f6f8fa;
	border-bottom: 1px solid #d8dee4;
}

.demo-comment-body {
	padding: 0.8em 0.9em;
	font: 0.8em/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
	word-break: break-all;
}

.demo-link {
	color: var(--accent);
	/* Given no size rather than faded, because an invisible element still
	   occupies its two wrapped lines and the caret was landing after them,
	   blinking in the middle of a comment box nobody had typed in yet.
	   Stepped rather than eased, so the URL arrives whole, which is what
	   pressing Cmd+V does. Size rather than display: display is a discrete
	   property and animating it in a keyframe does not hold across engines,
	   which left the URL missing for the whole loop. */
	font-size: 0;
}

.demo-caret {
	display: inline-block;
	width: 1px;
	height: 1.1em;
	margin-left: 1px;
	vertical-align: text-bottom;
	background: #1a1a19;
	animation: demo-blink 1s steps(1) infinite;
}

.demo-paste {
	position: absolute;
	right: 0.9em;
	bottom: 0.9em;
	font-size: 0.9em;
	opacity: 0;
}

.demo-cursor {
	left: 78%;
	top: 62%;
	width: 1.5em;
	opacity: 0;
	fill: #111;
	stroke: #fff;
	stroke-width: 1.2;
	stroke-linejoin: round;
	filter: drop-shadow(0 0.1em 0.15em rgba(0, 0, 0, 0.25));
}

.demo-cursor,
.demo-comment,
.demo-target,
.demo-menu,
.demo-submenu,
.demo-services,
.demo-upload,
.demo-ring,
.demo-status-icon,
.demo-toast,
.demo-link,
.demo-paste {
	animation-duration: 10s;
	animation-iteration-count: infinite;
	animation-timing-function: ease-in-out;
}

.demo-cursor { animation-name: demo-cursor; }
.demo-comment { animation-name: demo-comment; animation-timing-function: ease-out; }
.demo-target { animation-name: demo-select; animation-timing-function: steps(1); }
.demo-menu { animation-name: demo-menu; animation-timing-function: ease-out; }
.demo-submenu { animation-name: demo-submenu; animation-timing-function: steps(1); }
.demo-services { animation-name: demo-highlight-services; animation-timing-function: steps(1); }
.demo-upload { animation-name: demo-highlight-upload; animation-timing-function: steps(1); }
.demo-ring { animation-name: demo-ring; animation-timing-function: linear; }
.demo-status-icon { animation-name: demo-status-icon; animation-timing-function: steps(1); }
.demo-toast { animation-name: demo-toast; animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1); }
.demo-link { animation-name: demo-link; animation-timing-function: steps(1); }
.demo-paste { animation-name: demo-paste; animation-timing-function: ease-out; }

@keyframes demo-cursor {
	0% { left: 38%; top: 92%; opacity: 0; }
	4% { left: 38%; top: 92%; opacity: 1; }
	13%, 17% { left: 21%; top: 26%; }
	25% { left: 30%; top: 47%; }
	31%, 39% { left: 55%; top: 48%; }
	52% { left: 70%; top: 62%; }
	60%, 94% { left: 78%; top: 64%; opacity: 1; }
	100% { left: 78%; top: 64%; opacity: 0; }
}

@keyframes demo-select {
	0% { background: transparent; color: inherit; }
	15% { background: #1a1a19; color: #fbfbfa; }
	95% { background: transparent; color: inherit; }
}

@keyframes demo-menu {
	0%, 16% { opacity: 0; transform: scale(0.96); transform-origin: top left; }
	17.5%, 38% { opacity: 1; transform: none; }
	40%, 100% { opacity: 0; }
}

@keyframes demo-submenu {
	0% { opacity: 0; }
	28% { opacity: 1; }
	39% { opacity: 0; }
}

@keyframes demo-highlight-services {
	0% { background: transparent; color: inherit; }
	25% { background: #1a1a19; color: #fbfbfa; }
	39% { background: transparent; color: inherit; }
}

@keyframes demo-highlight-upload {
	0% { background: transparent; color: inherit; }
	32% { background: #1a1a19; color: #fbfbfa; }
	39% { background: transparent; color: inherit; }
}

@keyframes demo-status-icon {
	0% { opacity: 1; }
	40% { opacity: 0; }
	50% { opacity: 1; }
}

@keyframes demo-ring {
	0%, 40% { opacity: 0; stroke-dashoffset: 50.3; }
	40.5% { opacity: 1; stroke-dashoffset: 50.3; }
	49% { opacity: 1; stroke-dashoffset: 0; }
	50%, 100% { opacity: 0; stroke-dashoffset: 0; }
}

/* The dashoffset lives on the circle, so the ring's animation reaches it. */
.demo-ring circle {
	animation: inherit;
	animation-name: demo-ring-stroke;
}

@keyframes demo-ring-stroke {
	0%, 40.5% { stroke-dashoffset: 50.3; }
	49%, 100% { stroke-dashoffset: 0; }
}

@keyframes demo-toast {
	0%, 50% { opacity: 0; transform: translateX(18%) scale(0.98); }
	54%, 82% { opacity: 1; transform: none; }
	88%, 100% { opacity: 0; transform: translateY(-12%) scale(0.98); }
}

@keyframes demo-comment {
	0%, 55% { opacity: 0; transform: translateY(4%); }
	62%, 96% { opacity: 1; transform: none; }
	100% { opacity: 0; }
}

@keyframes demo-link {
	0% { font-size: 0; opacity: 0; }
	68% { font-size: 1em; opacity: 1; }
	96% { font-size: 0; opacity: 0; }
}

@keyframes demo-paste {
	0%, 64% { opacity: 0; transform: scale(0.8); }
	66%, 72% { opacity: 1; transform: none; }
	76%, 100% { opacity: 0; }
}

@keyframes demo-blink {
	50% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
	.demo *,
	.demo *::before {
		animation: none !important;
	}
}

/* ------------------------------------------------------------------ plan */

.plan {
	margin-bottom: 0.9rem;
}

.plan-head {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin-bottom: 0.6rem;
}

.plan-head .spacer {
	flex: 1;
}

/* A bar rather than a percentage on its own. Nobody has a feel for what 4%
   of a quota looks like, and everybody can see a nearly full one. */
.meter {
	background: var(--line);
	border-radius: 999px;
	height: 6px;
	overflow: hidden;
	margin-bottom: 0.55rem;
}

.meter span {
	background: var(--accent);
	border-radius: 999px;
	display: block;
	height: 100%;
	transition: width 0.3s ease;
}

/* Past four fifths it stops being information and starts being a warning. */
.meter span.full {
	background: var(--danger, #c0392b);
}

.plan p {
	margin: 0;
}

/* The plan card while it waits for Stripe.
 *
 * A webhook is a separate message travelling separately, so pressing a billing
 * button leaves the card describing a state that may be about to change. It
 * says so rather than sitting still, and it stops taking clicks: a second
 * press during those few seconds opens a second Stripe session for something
 * that is already happening.
 */
.plan.settling .meter span {
	background: linear-gradient(90deg, var(--line) 25%, var(--muted) 50%, var(--line) 75%);
	background-size: 200% 100%;
	animation: sheen 1.4s ease-in-out infinite;
	width: 100% !important;
}

.plan.settling button {
	opacity: 0.55;
	pointer-events: none;
}

.plan.settling #plan-name {
	color: var(--muted);
}

/* ------------------------------------------------- the landing page's field
 *
 * Only the front page. The dashboard and the legal pages are documents and
 * keep the single measured column above; this one is a page somebody is
 * deciding something on, and a centred column of prose is what it looked like
 * before: a blog post with a product in it.
 *
 * Swiss structure rather than Swiss decoration. The grid is not drawn, it is
 * hung from: a numbered mark in the left margin, the argument in the middle,
 * and the aside that qualifies it out on the right where it can be skipped.
 * Nothing is centred, because centring is what a layout does when it has not
 * decided which edge matters.
 */
main.field {
	max-width: 74rem;
	/* No padding under the footer: the footer is the end of the page, and
	   ninety six pixels of nothing after it is scroll with nothing in it. Its
	   own padding is the breathing room. */
	padding: 0 1.5rem;
}

.band {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	column-gap: 1.5rem;
	border-top: 1px solid var(--line);
	padding: 3.2rem 0;
}

/* The first band has nothing above it to be ruled off from. */
.band-hero {
	border-top: 0;
	padding-top: 4.5rem;
}

.band > .mark {
	grid-column: 1 / span 2;
	margin: 0.35rem 0 0;
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--muted);
}

.band > .body {
	grid-column: 3 / span 7;
	/* minmax(0, ...) above is what lets this shrink; without it an eighty
	 * character URL in a pre would push the column past the page. */
	min-width: 0;
}

.band > .aside {
	grid-column: 11 / span 2;
	font-size: 0.83rem;
	line-height: 1.55;
	color: var(--muted);
	border-left: 1px solid var(--line);
	padding-left: 1rem;
	margin: 0.3rem 0 0;
}

.band > .aside p {
	margin: 0 0 0.8rem;
}

.band > .aside p:last-child {
	margin-bottom: 0;
}

/* The scale contrast is where the identity is. A grotesque at display size
 * wants to be set tighter than it is at reading size, so the tracking closes
 * as the size grows rather than staying where a paragraph left it. */
.field h1 {
	font-size: clamp(2.6rem, 7.2vw, 4.6rem);
	line-height: 0.98;
	letter-spacing: -0.04em;
	font-weight: 500;
	margin: 0 0 1.4rem;
	max-width: 14ch;
}

.field .band-hero .lede {
	font-size: 1.22rem;
	line-height: 1.5;
	color: var(--fg);
	max-width: 38ch;
	margin-bottom: 2rem;
}

.field h2 {
	margin-top: 0;
}

.field h3 {
	margin: 2.4rem 0 0.5rem;
}

/* The install line is the one thing the page is asking for, so it is set as
 * a block rather than a button: it is a command, and a button that cannot be
 * pasted would be lying about what happens next. copy.js puts the strip and
 * the copy button on it like any other labelled block. */
.field pre.cta {
	/* The one block on the page that has to fit whole on a phone: a command
	   the reader has to scroll sideways to finish reading is a command they
	   do not believe is one line. */
	font-size: clamp(0.72rem, 3.4vw, 1.02rem);
	border-color: var(--fg);
}

.field pre.cta code {
	font-weight: 500;
}

/* Sections below the hero keep the drop box from filling the column. */
.field .drop {
	max-width: 32rem;
}

.field footer {
	border-top: 1px solid var(--line);
	margin-top: 0;
	padding-bottom: 2.5rem;
}

/* One column, and the mark becomes a heading rather than a margin note. The
 * aside goes under what it qualifies, which is where it reads on a phone. */
@media (max-width: 62rem) {
	main.field {
		max-width: 40rem;
	}

	.band {
		grid-template-columns: minmax(0, 1fr);
		padding: 2.6rem 0;
	}

	.band > .mark,
	.band > .body,
	.band > .aside {
		grid-column: 1;
	}

	.band > .mark {
		margin-bottom: 1rem;
	}

	.band > .aside {
		margin-top: 1.8rem;
		padding-left: 0.9rem;
	}

	.field h1 {
		max-width: none;
	}
}

/* The bar is shared with the document pages, which keep the narrow measure.
 * On the landing page it has to sit on the same edge as the field below it,
 * or the brand floats inward of the first column and the whole grid reads as
 * an accident. */
body:has(main.field) .bar-inner {
	max-width: 74rem;
}

@media (max-width: 62rem) {
	body:has(main.field) .bar-inner {
		max-width: 40rem;
	}
}

/* ----------------------------------------------- the field, drawn faintly
 *
 * A grid you can see, at a contrast where you cannot quite. The page was
 * already hung off twelve columns; this is the columns admitting it, which is
 * the difference between a layout that is aligned and a layout that says so.
 * It is one gradient and no elements, so it costs nothing and a phone never
 * sees it.
 *
 * The numbering is a counter rather than five typed strings, because a band
 * moved or removed used to leave a number behind that no longer counted
 * anything.
 */
main.field {
	counter-reset: band;
	position: relative;
}

.band {
	counter-increment: band;
	position: relative;
}

.band > .mark::before {
	content: counter(band, decimal-leading-zero) " · ";
	color: var(--line);
}

/* The ruler, out in the margin where the page ends and the paper begins. It
 * is furniture, not content, so it is hidden from anything that reads aloud
 * and it goes away as soon as the margin does. */
.band::before {
	content: "SEC 0." counter(band, decimal-leading-zero);
	position: absolute;
	right: calc(100% + 2.2rem);
	top: 3.4rem;
	font: 0.62rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
	letter-spacing: 0.1em;
	color: var(--line);
	white-space: nowrap;
	pointer-events: none;
}

.band-hero::before {
	top: 4.7rem;
}

@media (max-width: 86rem) {
	.band::before {
		display: none;
	}
}

/* Column rules, at the same twelve column rhythm the content sits on. The
 * colour is the hairline the rest of the page already uses, carried down to
 * where it reads as paper rather than as a line. */
@media (min-width: 62.01rem) {
	.band {
		background-image: repeating-linear-gradient(
			to right,
			color-mix(in srgb, var(--line) 55%, transparent) 0 1px,
			transparent 1px calc(100% / 12)
		);
	}
}

/* ------------------------------------------------------------ the hero pair
 *
 * The claim on the left and the thing itself on the right. The proof used to
 * be a section further down, which meant the page asserted for a screen and a
 * half before it showed anything.
 */
.band-hero > .body {
	grid-column: 3 / span 5;
}

.band-hero > .aside-wide {
	grid-column: 8 / span 5;
	font-size: 0.9rem;
	border-left: 0;
	padding-left: 0;
	margin-top: 0.4rem;
}

.band-hero > .aside-wide .exchange {
	margin-bottom: 1rem;
}

@media (max-width: 62rem) {
	.band-hero > .body,
	.band-hero > .aside-wide {
		grid-column: 1;
	}

	.band-hero > .aside-wide {
		margin-top: 2rem;
	}
}

/* ----------------------------------------------------------------- pills
 *
 * What the four cards under the old hero were trying to say, in the space a
 * line of prose takes. A card is for something with a sentence in it; these
 * have three words each and were padding a grid to look substantial.
 */
.pills {
	display: flex;
	flex-wrap: wrap;
	gap: 0.45rem;
	margin: 1.4rem 0 0;
}

.pills span {
	font: 0.72rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
	letter-spacing: 0.02em;
	color: var(--muted);
	border: 1px solid var(--line);
	border-radius: 999px;
	padding: 0.42rem 0.65rem;
	background: var(--card);
}

/* ------------------------------------------------------------------- URLs
 *
 * The accent belongs to the one thing the service exists to hand back. It was
 * spent on nothing in particular before, which is the same as not having one.
 */
.url {
	color: var(--accent);
}

a.url {
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
}

/* The headline sits in five columns now rather than nine, so the size that
 * fitted beside nothing does not fit beside the proof. */
.band-hero .body h1 {
	font-size: clamp(2.4rem, 4.4vw, 3.5rem);
}

/* The panel holds a command with a URL in it and cannot scroll sideways
 * without the command looking like it was cut off mid-thought. */
.band-hero .exchange pre {
	font-size: 0.8rem;
}

/* ------------------------------------------------------------ on a phone
 *
 * The measured problems, not the guessed ones: the install line was cut off
 * at "skill.m" behind a horizontal scrollbar, and the opening paragraph ran
 * to five lines of thirty five characters.
 */
@media (max-width: 34rem) {
	/* Every command on the page wraps rather than scrolls. A block with a
	   scrollbar under it is a block whose second half nobody reads, and the
	   install line was ending at "skill.m" on a phone. Shrinking the type
	   instead is a fight a narrower phone always wins, and the Copy button
	   sends the whole thing whichever way it is laid out. */
	.field pre code {
		white-space: pre-wrap;
		overflow-wrap: anywhere;
	}

	.field pre.cta {
		font-size: 0.82rem;
	}

	/* Large enough to open the page, small enough to hold a sentence on
	   fewer than five lines. */
	.field .band-hero .lede {
		font-size: 1.06rem;
	}
}

/* The index at the top of a document somebody arrived at with one errand.
 * A page of eight legal sections that opens with the first of them makes
 * whoever came to file a copyright notice read about everything else first. */
.index {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.4rem;
	margin: 1.6rem 0 0;
	font-size: 0.9rem;
}

/* A legal document's own sections are longer than a narrative's, so the mark
 * wraps rather than being cut, and it is set to read as a heading in the
 * margin instead of a label. */
.band > .mark {
	text-wrap: balance;
}

/* The two things on this page that qualify rather than state. They sit in
 * the margin, where something that changes what you just read belongs. */
.aside .note,
.aside .warn {
	margin: 0;
}

/* ------------------------------------------- a document with numbered parts
 *
 * Terms and Privacy are cited rather than read through: somebody wants the
 * clause about deletion, not the whole of it. Numbering the sections is what
 * lets them be referred to at all, and each one is its own anchor, so a
 * number can be linked as well as spoken.
 *
 * The ruler out in the margin goes here. It earns its place on a page with
 * five parts and becomes noise on one with twelve, where the mark beside the
 * text already carries the number.
 */
.field.numbered .band::before {
	content: none;
}

.field.numbered .band > .mark {
	font-size: 0.75rem;
}

/* The section heading is the mark now, so the prose starts at the top of its
 * column rather than under a heading that is no longer there. */
.field.numbered .band > .body > :first-child {
	margin-top: 0;
}

.field.numbered .band > .body > h3:first-child {
	margin-top: 0;
}

/* The drawing needs a certain width to be a drawing at all.
 *
 * Its type is a fraction of its own container, so on a phone the Finder
 * window's file names come out at under five pixels: an illustration nobody
 * can read is not an illustration, it is a grey rectangle that costs a
 * screenful of scrolling. The paragraph above it says the same thing in
 * words, which is what a screen reader was getting from it anyway.
 */
@media (max-width: 44rem) {
	.demo {
		display: none;
	}
}
