/* preflight.sh
   Set like a printed sheet, after cronwatch.dev: soleil for everything a
   person reads, Auger Mono for everything a machine printed, and a small
   label down the left of each section instead of headlines shouting at you.
   Neutral greys, with Preflight's blue as the one accent (buttons, the chosen
   tab, the page you are on) and three colours for what a scan reports. Dark
   by default; the toggle turns the sheet over to light. Both faces come from
   Adobe Fonts, the one other origin the page loads from, allowed in the CSP.
   preflightsh-app keeps a copy of this sheet; change one, change the other. */

:root {
  --paper: #f4f4f5;
  --sheet: #ffffff;
  --sunk: #fafafa;
  --rule: #e4e4e7;
  --rule-2: #d4d4d8;
  --tick: #909098;
  --ink: #000000;
  --body: #18181b;
  --muted: #71717a;
  --ok: #15803d;
  --warn: #a16207;
  --bad: #b91c1c;
  /* The brand blue, darkened on light paper so text on it and text in it
     both pass 4.5:1. */
  --accent: #1d7ac9;
  --accent-ink: #ffffff;
  --accent-soft: rgba(36, 152, 244, .12);
  --sans: "soleil", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "auger-mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color-scheme: light;
}
:root[data-theme="dark"] {
  --paper: #09090b;
  --sheet: #111113;
  --sunk: #18181b;
  --rule: #27272a;
  --rule-2: #3f3f46;
  --tick: #66666f;
  --ink: #ffffff;
  --body: #e4e4e7;
  --muted: #a1a1aa;
  --ok: #4ade80;
  --warn: #fbbf24;
  --bad: #f87171;
  --accent: #2498f4;
  --accent-ink: #050b12;
  --accent-soft: rgba(36, 152, 244, .16);
  color-scheme: dark;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--paper); color: var(--ink); font: 400 17px/1.62 var(--sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
a { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .16em; text-decoration-color: var(--rule-2); }
a:hover { text-decoration-color: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
::selection { background: var(--accent); color: var(--accent-ink); }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
code, pre, kbd, .mono { font-family: var(--mono); }
h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.012em; }
p, figure { margin: 0; }
pre { margin: 0; font: 400 13px/1.62 var(--mono); color: var(--body); overflow-x: auto; tab-size: 4; }
pre .k { color: var(--ink); font-weight: 500; } pre .s { color: var(--ok); } pre .c { color: var(--muted); }
pre b { font-weight: 500; color: var(--ink); }
pre b.bad, pre .bad { color: var(--bad); } pre b.warn, pre .warn { color: var(--warn); } pre b.ok, pre .ok { color: var(--ok); }
.skip { position: absolute; left: -999px; top: 8px; background: var(--ink); color: var(--sheet); padding: 8px 12px; }
.skip:focus { left: 8px; z-index: 30; }
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
.label, .for, .foot-head { font: 500 11.5px/1.5 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }

/* The sheet. */
.page { max-width: 1180px; min-height: 100vh; margin: 0 auto; background: var(--sheet); border-left: 1px solid var(--rule); border-right: 1px solid var(--rule); padding: 0 clamp(20px, 4vw, 56px); display: flex; flex-direction: column; }
.page > main { flex: 1 0 auto; }

/* Top: links left, the mark right, the way a masthead sits. */
.top { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 24px 0 0; }
.links { display: flex; flex-wrap: wrap; align-items: center; gap: 22px; font-size: 16px; }
.links a { color: var(--ink); text-decoration-color: var(--rule-2); }
.links a:hover, .links a.here { text-decoration-color: var(--accent); }
.links button { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .16em; text-decoration-color: var(--rule-2); }
.links button:hover { text-decoration-color: var(--accent); }
.links form { display: contents; }
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; font-weight: 700; font-size: 17px; color: var(--ink); letter-spacing: -0.01em; white-space: nowrap; }
.brand img { height: 30px; width: auto; display: block; }
.brand .tld { color: var(--muted); font-weight: 500; }
.brand:hover .tld { color: var(--accent); }
.menu { display: none; }

/* Buttons: the blue one does the thing; the outlined one goes elsewhere. */
.btn, .ghost-btn { display: inline-flex; align-items: center; justify-content: center; gap: 9px; font: 500 14px/1 var(--mono); border-radius: 3px; padding: 11px 14px; text-decoration: none; white-space: nowrap; }
.btn { color: var(--accent-ink); background: var(--accent); border: 1px solid var(--accent); }
.btn:hover { filter: brightness(1.08); }
.ghost-btn { color: var(--ink); border: 1px solid var(--rule-2); background: none; }
.ghost-btn:hover { border-color: var(--ink); }
.btn.danger { background: var(--bad); border-color: var(--bad); color: var(--sheet); }
.ghost-btn.danger { color: var(--bad); }
.ghost-btn.danger:hover { border-color: var(--bad); }
.btn.small, .ghost-btn.small { font-size: 12.5px; padding: 8px 10px; }
.btn[disabled], .ghost-btn[disabled] { opacity: .5; cursor: not-allowed; }

/* The opening: the first paragraph does the work a slogan usually does. */
.opening { padding: 64px 0 52px; }
/* The mark, big, on its way out of the sheet: it sits in the empty right of
   the opening and its nose crosses the sheet's edge. Behind the words, and
   gone on narrow screens where there is no empty right to fill. */
html, body { overflow-x: clip; }
.opening { position: relative; }
.opening > :not(.flyby) { position: relative; z-index: 1; }
.flyby { position: absolute; z-index: 0; top: 115px; right: calc(-1 * clamp(20px, 4vw, 56px) - 112px); width: 640px; height: auto; pointer-events: none; user-select: none; transform: rotate(-14deg); }
@media (prefers-reduced-motion: no-preference) {
  .flyby { animation: flyby-in 1.1s cubic-bezier(.2, .7, .2, 1) both, flyby-drift 6s ease-in-out 1.1s infinite alternate; }
  @keyframes flyby-in { from { transform: translate(-220px, 160px) rotate(-14deg); opacity: 0; } }
  @keyframes flyby-drift { to { transform: translate(14px, -10px) rotate(-15deg); } }
}
@media (max-width: 1100px) { .flyby { display: none; } }
.opening .say { font-weight: 400; font-size: clamp(1.6rem, 3.3vw, 2.5rem); line-height: 1.24; letter-spacing: -0.02em; max-width: 21em; text-wrap: pretty; }
.opening .say b { font-weight: 700; }
.opening .then { margin-top: 24px; color: var(--ink); max-width: 56ch; text-wrap: pretty; }
.install { cursor: pointer; display: inline-flex; align-items: center; gap: 14px; margin-top: 26px; background: var(--sunk); border: 1px solid var(--rule); border-radius: 3px; padding: 10px 10px 10px 14px; font: 400 14px/1.4 var(--mono); max-width: 100%; }
.install code { min-width: 0; overflow-wrap: anywhere; }
.install code::before { content: "$ "; color: var(--muted); }
.installs { display: flex; flex-wrap: wrap; gap: 14px 18px; margin-top: 30px; }
.installs .for { margin: 0 0 7px; }
.installs .install { margin-top: 0; }
.installs.tabbed { display: block; max-width: 760px; }
.doc > .installs { margin-top: 18px; }
.installs.tabbed .for { display: none; }
.installs.tabbed .install { display: flex; justify-content: space-between; width: 100%; }
.tabs { display: flex; flex-wrap: wrap; gap: 2px 4px; margin: 0 0 14px; border-bottom: 1px solid var(--rule); }
.tabs[hidden] { display: none; }
.tab { display: inline-flex; align-items: center; gap: 8px; margin: 0 0 -1px; padding: 8px 10px 9px; border-bottom: 2px solid transparent; color: var(--muted); font: 500 11.5px/1.5 var(--mono); letter-spacing: .12em; text-transform: uppercase; }
.tab:hover { color: var(--body); }
.tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }
.tab:focus-visible { outline-offset: -2px; }
.tab .logo { width: 16px; height: 16px; fill: currentColor; flex: none; }
/* Each logo in its own colour once hovered or chosen, grey until then. */
.tab-npm:hover .logo, .tab-npm[aria-selected="true"] .logo { fill: #cb3837; }
.tab-brew:hover .logo, .tab-brew[aria-selected="true"] .logo { fill: #be862d; }
.tab-go:hover .logo, .tab-go[aria-selected="true"] .logo { fill: #00add8; }
.tab-docker:hover .logo, .tab-docker[aria-selected="true"] .logo { fill: #1d63ed; }
:root[data-theme="dark"] .tab-docker:hover .logo, :root[data-theme="dark"] .tab-docker[aria-selected="true"] .logo { fill: #4d8af0; }
.tab-curl:hover .logo, .tab-curl[aria-selected="true"] .logo { fill: var(--ok); }
/* Bun's logo keeps its own colours, grey until hovered or chosen. */
.tab-bun .logo { filter: grayscale(1); opacity: .7; }
.tab-bun:hover .logo, .tab-bun[aria-selected="true"] .logo { filter: none; opacity: 1; }
.then-run { margin-top: 18px; font-size: 15px; color: var(--muted); }
.then-run code { color: var(--ink); font-size: .9em; }
.actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 24px; }
.actions .note { font-size: 15px; color: var(--ink); }
details.peek { margin-top: 18px; }
details.peek > summary { list-style: none; cursor: pointer; font: 400 13px/1.5 var(--mono); color: var(--muted); }
details.peek > summary::-webkit-details-marker { display: none; }
details.peek > summary::after { content: " +"; }
details.peek[open] > summary::after { content: " \2212"; }
details.peek > summary:hover { color: var(--ink); }
details.peek .out { margin-top: 12px; }
.copy { flex: none; font: 500 11px/1 var(--mono); letter-spacing: .07em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--rule-2); border-radius: 2px; padding: 6px 8px; }
.copy:hover { color: var(--ink); border-color: var(--muted); }

/* Rows: a small label down the left, the thing itself on the right. */
.row { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 40px; row-gap: 40px; align-items: start; padding: clamp(64px, 8vw, 96px) 0; border-top: 1px solid var(--rule); }
.row > .label { padding-top: 7px; }
.row .body > h2 { font-size: 1.62rem; line-height: 1.22; max-width: 40ch; text-wrap: pretty; }
@media (min-width: 1100px) { .row .body > h2 { max-width: none; } }
.row .body > p { color: var(--ink); max-width: 60ch; margin-top: 18px; text-wrap: pretty; }
.row .body > p.small { font-size: 15.5px; }
.row .body > p code, .stacks code, .catches code { font-size: .86em; }
.row .body > * + .out, .row .body > * + .install, .row .body > * + .installs, .row .body > * + .catches, .row .body > * + .browser { margin-top: 30px; }
.row .body > * + p.small, .row .body > * + details.peek, .row .body > * + .actions { margin-top: 24px; }
.row .body > details.peek + details.peek { margin-top: 12px; }
.row .body > p.small + p.small { margin-top: 12px; }
.row > .span { grid-column: 1 / -1; min-width: 0; }
.row .caption { margin-top: 14px; font-size: 15px; color: var(--muted); }

/* A list with a mono label down the left of each line, ruled like a table. */
.stacks { margin: 22px 0 0; max-width: 68ch; border-top: 1px solid var(--rule); }
.stacks > div { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: 18px; padding: 11px 0 12px; border-bottom: 1px solid var(--rule); }
.stacks dt { font: 500 11.5px/1.5 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); padding-top: 4px; }
.stacks dd { margin: 0; font-size: 16px; line-height: 1.5; color: var(--ink); text-wrap: pretty; }
@media (max-width: 560px) { .stacks > div { grid-template-columns: minmax(0, 1fr); gap: 2px; } }
/* Each service or framework with its logo, in its own colours: the one place
   the page shows other people's marks. A dark mark turns light on dark paper
   (.inv); Remix has a drawing for each (.on-light, .on-dark). */
.stacks.chips { max-width: 76ch; }
.stacks.chips > div { grid-template-columns: 150px minmax(0, 1fr); }
.stacks.chips dd { display: flex; flex-wrap: wrap; gap: 6px; }
.chip { display: inline-flex; align-items: center; gap: 7px; padding: 3px 9px 3px 7px; border: 1px solid var(--rule); border-radius: 3px; font-size: 14px; line-height: 1.5; color: var(--ink); white-space: nowrap; }
.chip img { height: 14px; width: auto; max-width: 18px; object-fit: contain; flex: none; }
.chip img.r { border-radius: 2px; }
.chip code { font: 400 11.5px/1 var(--mono); color: var(--muted); }
.chip .sq { width: 12px; height: 12px; margin: 0; color: #c80100; }
.chip img.on-dark { display: none; }
:root[data-theme="dark"] .chip img.on-dark { display: block; }
:root[data-theme="dark"] .chip img.on-light { display: none; }
:root[data-theme="dark"] .chip img.inv { filter: invert(1); }
@media (max-width: 560px) { .stacks.chips > div { grid-template-columns: minmax(0, 1fr); gap: 8px; } }

/* Printed things: what the CLI actually put on a screen. */
.out { background: var(--sunk); border: 1px solid var(--rule); border-radius: 3px; min-width: 0; }
.out + .out { margin-top: 12px; }
.out .from { display: flex; justify-content: space-between; gap: 12px; padding: 8px 14px; border-bottom: 1px solid var(--rule); font: 400 11.5px/1.5 var(--mono); color: var(--muted); }
.out .from .dots { display: flex; align-items: center; gap: 5px; }
.out .from .dots i { width: 8px; height: 8px; border-radius: 50%; border: 1px solid var(--rule-2); }
.out pre { padding: 13px 15px 15px; }
.out.wrap pre { white-space: pre-wrap; word-break: break-word; }
.out.tall pre { max-height: 520px; overflow-y: auto; }
.out .prompt { color: var(--ink); }
.out .prompt::before { content: "$ "; color: var(--muted); }
.out .head { color: var(--ink); font-weight: 500; }
.out .dim { color: var(--tick); }

/* The six-rule list, set as a glossary: an id down the left, what it means. */
.catches { list-style: none; margin: 0; padding: 0; max-width: 72ch; }
.catches li { display: grid; grid-template-columns: 170px minmax(0, 1fr); gap: 20px; padding: 10px 0; border-top: 1px solid var(--rule); align-items: baseline; }
.catches li:first-child { border-top: 0; padding-top: 0; }
.catches li > code { font: 500 13px/1.5 var(--mono); }
.catches li > code.bad { color: var(--bad); } .catches li > code.warn { color: var(--warn); } .catches li > code.ok { color: var(--ok); }
.catches li span { color: var(--ink); font-size: 16px; }
.catches li span small { color: var(--muted); font: 400 11px/1 var(--mono); letter-spacing: .06em; text-transform: uppercase; margin-left: 6px; }

/* A flat browser window: a thin frame, three dots and the address. */
.browser { margin: 0; border: 1px solid var(--rule-2); border-radius: 6px; background: var(--sheet); overflow: hidden; }
.browser .chrome { display: grid; grid-template-columns: 64px minmax(0, 1fr) 64px; align-items: center; gap: 12px; padding: 9px 12px; background: var(--sunk); border-bottom: 1px solid var(--rule); }
.browser .dots { display: flex; gap: 6px; }
.browser .dots i { width: 9px; height: 9px; border-radius: 50%; border: 1px solid var(--rule-2); }
.browser .url { justify-self: center; width: min(100%, 380px); padding: 5px 12px; background: var(--sheet); border: 1px solid var(--rule); border-radius: 3px; font: 400 12px/1.4 var(--mono); color: var(--muted); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.browser .screen { padding: 4px clamp(16px, 3vw, 32px) 12px; }

/* The app's run page inside the frame: its masthead and page as the app
   draws them, in a window that scrolls like the real one. */
.browser .screen.app { max-height: 760px; overflow-y: auto; overscroll-behavior: contain; padding-bottom: 28px; }
.browser .screen.app .top { padding-top: 18px; }
.browser .screen.app .links span { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .16em; text-decoration-color: var(--rule-2); font-size: 15px; }
.browser .screen.app .apphead { padding-top: 32px; }
.browser .screen.app .btn, .browser .screen.app .ghost-btn, .browser .screen.app .copy { cursor: default; }

/* A run's figures: how many passed, warned and failed. Shared with the app. */
.figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); margin: 18px 0 0; border-top: 1px solid var(--rule); }
.figures > div { display: flex; flex-direction: column-reverse; justify-content: flex-end; gap: 4px; padding: 14px 16px 2px 0; }
.figures dt { display: flex; align-items: center; font: 500 11px/1.4 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.figures dd { margin: 0; font: 300 32px/1.1 var(--sans); font-variant-numeric: tabular-nums; color: var(--ink); }
.figures .zero dd { color: var(--rule-2); }
.figures .bad dd { color: var(--bad); } .figures .warn dd { color: var(--warn); }
.sq { display: inline-block; width: 8px; height: 8px; border-radius: 1.5px; background: currentColor; margin-right: 7px; vertical-align: 1px; flex: none; }
.sq.ok, .state.ok { color: var(--ok); } .sq.warn, .state.warn { color: var(--warn); } .sq.bad, .state.bad { color: var(--bad); } .sq.muted, .state.muted { color: var(--muted); }
.state { font: 500 12.5px/1.4 var(--mono); white-space: nowrap; }
.headline { font: 400 clamp(21px, 2.4vw, 26px)/1.25 var(--sans); letter-spacing: -0.015em; }
.headline b { font-weight: 700; }

/* A state or a count as a coloured pill: the state's colour on a wash of
   itself. Shared with the app (its runs list and run page). A zero stays in
   place, faded, so rows of pills line up. */
.count-pill { display: inline-block; padding: 3px 10px; border-radius: 999px; font: 500 11.5px/1.4 var(--mono); letter-spacing: .04em; white-space: nowrap; color: var(--c); background: color-mix(in srgb, var(--c) 14%, transparent); border: 1px solid color-mix(in srgb, var(--c) 30%, transparent); }
.count-pill.bad { --c: var(--bad); } .count-pill.warn { --c: var(--warn); } .count-pill.ok { --c: var(--ok); }
.count-pill.zero { --c: var(--muted); opacity: .55; }
.pills { display: flex; flex-wrap: wrap; gap: 6px; }
.pills.big { gap: 8px; margin-top: 16px; }
.pills.big .count-pill { padding: 6px 14px; font-size: 13px; }

/* A table of checks or runs, as the dashboard sets it. Shared with the app. */
table.board { width: 100%; border-collapse: collapse; }
.board th { text-align: left; font: 500 10.5px/1.2 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding: 0 14px 10px 0; border-bottom: 1px solid var(--rule); white-space: nowrap; }
.board td { padding: 11px 14px 11px 0; border-bottom: 1px solid var(--rule); vertical-align: top; font-size: 15px; line-height: 1.45; color: var(--body); }
.board tbody tr:last-child td { border-bottom: 0; }
.board td.id { font: 500 13px/1.5 var(--mono); color: var(--ink); white-space: nowrap; }
.board td .sub { display: block; color: var(--muted); font: 400 13.5px/1.4 var(--sans); }
.board td.num { font: 400 13px/1.5 var(--mono); white-space: nowrap; text-align: right; }
.board th.num { text-align: right; }
.board .nowrap { white-space: nowrap; }
.board a { text-decoration-color: transparent; }
.board a:hover { text-decoration-color: var(--accent); }


/* The dashboard's run page. The app serves it; the home page draws it in a
   browser frame with the same markup, so they cannot drift apart. */
/* A page's head: a mono label, the heading, then anything that sums it up. */
.apphead { padding: 48px 0 8px; }
.apphead .label { margin-bottom: 10px; }
.apphead h1 { font-size: clamp(1.7rem, 3vw, 2.2rem); line-height: 1.15; letter-spacing: -0.02em; }
.apphead .back { display: inline-block; margin-bottom: 18px; font: 400 13px/1.5 var(--mono); color: var(--muted); text-decoration: none; }
.apphead .back:hover { color: var(--ink); }
.apphead .actions { margin-top: 22px; }
.apphead .notice { margin-top: 24px; max-width: 46rem; }
.appbody { padding: 24px 0 40px; }
.notice + .notice { margin-top: 14px; }
.notice p + p { margin-top: 4px; }
.notice .muted { font-size: 15px; }

/* A finding on the run page: what failed, and the fix beneath it. */
.appbody h2.section { display: flex; align-items: center; margin-top: 52px; font: 500 11.5px/1.5 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.appbody h2.section:first-child { margin-top: 0; }
.findings { margin-top: 14px; }
.finding { border-top: 1px solid var(--rule); padding: 22px 0 26px; }
.finding:last-child { border-bottom: 1px solid var(--rule); }
.finding-head { display: grid; grid-template-columns: 70px minmax(0, 1fr) auto; gap: 6px 18px; align-items: baseline; }
/* The state pill sits at its own width at the start of its column, rather
   than stretching to fill it as a grid item would. */
.finding-head .state-pill { justify-self: start; align-self: start; margin-top: 2px; }
.finding-head h3 { font-size: 1.08rem; line-height: 1.35; }
.finding-head .id { display: block; margin-top: 2px; font: 400 12.5px/1.4 var(--mono); color: var(--muted); }
.finding-head .msg { grid-column: 2; color: var(--ink); white-space: pre-line; font-size: 15.5px; }
.finding-head .copy-btn { grid-column: 3; grid-row: 1; }
.finding .fix { margin: 18px 0 0 88px; }
.passed { list-style: none; margin: 14px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 0 32px; }
.passed li { display: flex; align-items: baseline; gap: 4px; padding: 7px 0; border-bottom: 1px solid var(--rule); font-size: 15px; color: var(--body); }
.passed li .sq { color: var(--ok); }
@media (max-width: 700px) {
  .finding-head { grid-template-columns: minmax(0, 1fr) auto; }
  .finding-head .state-pill { grid-column: 1 / -1; }
  .finding-head .msg { grid-column: 1 / -1; }
  .finding-head .copy-btn { grid-row: auto; grid-column: 2; }
  .finding .fix { margin-left: 0; }
}

/* The AI suggestion, as the server renders it (internal/web/suggest.go). */
.ai-suggestion { background: var(--sunk); border: 1px solid var(--rule); border-left: 2px solid var(--accent); border-radius: 3px; padding: 14px 16px; font-size: 15.5px; line-height: 1.6; color: var(--ink); }
.ai-suggestion > .label { margin-bottom: 8px; }
.ai-suggestion > * + * { margin-top: 10px; }
.ai-suggestion ul { padding-left: 1.2em; margin-bottom: 0; }
.ai-suggestion li + li { margin-top: 4px; }
.ai-suggestion :not(pre) > code, .msg code, h3 code { font-size: .84em; background: var(--sheet); border: 1px solid var(--rule); padding: 1px 4px; border-radius: 2px; overflow-wrap: anywhere; }
.ai-suggestion pre { background: var(--sheet); border: 1px solid var(--rule); border-radius: 3px; padding: 12px 14px; font-size: 12.5px; }
.fix > .muted { font-size: 14.5px; }

/* While a fix is written: the box it will fill, with lines that shimmer
   where the text will be. Still for readers who asked for less motion. */
.fix-loading { background: var(--sunk); border: 1px solid var(--rule); border-left: 2px solid var(--accent); border-radius: 3px; padding: 14px 16px; }
.fix-loading .label { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.fix-loading .label .dots { display: inline-flex; gap: 3px; }
.fix-loading .label .dots i { width: 4px; height: 4px; border-radius: 50%; background: var(--accent); }
.fix-loading .line { display: block; height: 10px; margin-top: 10px; border-radius: 2px; background: linear-gradient(90deg, var(--rule) 0%, var(--rule-2) 40%, var(--rule) 80%); background-size: 300% 100%; }
.fix-loading .line:nth-of-type(1) { width: 92%; } .fix-loading .line:nth-of-type(2) { width: 78%; } .fix-loading .line:nth-of-type(3) { width: 54%; }
.fix-loading .note { margin-top: 14px; font-size: 14px; color: var(--muted); }
@media (prefers-reduced-motion: no-preference) {
  .fix-loading .line { animation: pf-shimmer 1.6s ease-in-out infinite; }
  .fix-loading .line:nth-of-type(2) { animation-delay: .15s; } .fix-loading .line:nth-of-type(3) { animation-delay: .3s; }
  .fix-loading .label .dots i { animation: pf-blink 1.2s ease-in-out infinite; }
  .fix-loading .label .dots i:nth-child(2) { animation-delay: .2s; } .fix-loading .label .dots i:nth-child(3) { animation-delay: .4s; }
}
@keyframes pf-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
@keyframes pf-blink { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }

/* Not found and server error: one centred block, nothing else. */
.lost { display: grid; justify-items: center; text-align: center; padding: clamp(64px, 14vh, 150px) 0 clamp(72px, 16vh, 170px); }
.lost .code { font: 200 clamp(5rem, 13vw, 8.5rem)/1 var(--sans); letter-spacing: -0.04em; color: var(--rule-2); }
.lost h1 { margin-top: 10px; font-size: clamp(1.8rem, 4vw, 2.5rem); line-height: 1.15; letter-spacing: -0.02em; }
.lost .line { margin-top: 14px; color: var(--ink); max-width: 40ch; }
.lost .actions { justify-content: center; margin-top: 28px; }
.lost .note { margin-top: 26px; font-size: 15px; color: var(--muted); max-width: 44ch; }

/* The close. */
.end { padding: clamp(64px, 8vw, 96px) 0 24px; border-top: 1px solid var(--rule); }
.end p { font-size: clamp(1.35rem, 2.4vw, 1.85rem); line-height: 1.3; max-width: 24ch; letter-spacing: -0.015em; }
.end .go { margin-top: 24px; display: flex; flex-wrap: wrap; gap: 24px; align-items: center; font-size: 17px; max-width: none; }

/* Footer: the mark and a line about the project beside columns of links,
   then the copyright with the theme switch at the far end. */
footer { padding: 48px 0 44px; border-top: 1px solid var(--rule); margin-top: 40px; font-size: 15px; color: var(--muted); }
footer a { color: var(--muted); text-decoration: none; }
footer a:hover { color: var(--ink); }
footer .foot-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2.4fr); gap: 40px 48px; }
footer .foot-about p { margin-top: 14px; max-width: 30ch; line-height: 1.5; }
footer .foot-about .brand { color: var(--ink); }
footer .foot-cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px 24px; }
footer .foot-head { margin-bottom: 12px; }
footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
footer .foot-end { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 44px; padding-top: 20px; border-top: 1px solid var(--rule); }
footer .foot-end a { text-decoration: underline; text-decoration-color: var(--rule-2); text-underline-offset: .16em; }
footer.slim { padding-top: 0; }
footer.slim .foot-end { margin-top: 0; }
.theme { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; color: var(--muted); }
.theme:hover { color: var(--ink); }
.theme svg { width: 20px; height: 20px; }
.theme .sun { display: none; }
:root[data-theme="dark"] .theme .sun { display: block; }
:root[data-theme="dark"] .theme .moon { display: none; }
@media (max-width: 860px) { footer .foot-top { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 560px) { footer .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* About, terms, privacy and contact: a label down the left, the text beside it. */
.solo { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 48px; align-items: start; padding: 40px 0 24px; }
.solo > .label { padding-top: 16px; }
.solo .updated { font: 400 13px/1.5 var(--mono); color: var(--muted); }
.notice { border-left: 2px solid var(--rule-2); padding: 2px 0 2px 16px; }
.notice.ok { border-left-color: var(--ok); }
.notice.bad { border-left-color: var(--bad); }
.notice.warn { border-left-color: var(--warn); }
.notice.accent { border-left-color: var(--accent); }

/* Forms: labels in mono capitals, fields drawn as thin boxes. Shared with the app. */
.form { display: grid; gap: 20px; max-width: 34rem; }
.doc > .form, .solo .form { margin-top: 30px; }
.form label, .field-label { display: block; font: 500 11.5px/1.5 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin-bottom: 6px; }
.form .hint { margin-top: 6px; font-size: 14px; color: var(--muted); }
input[type="text"], input[type="email"], input[type="password"], input[type="url"], input[type="search"], input[type="number"], select, textarea {
  display: block; width: 100%; font: 400 16px/1.5 var(--sans); color: var(--ink); background: var(--sheet); border: 1px solid var(--rule-2); border-radius: 3px; padding: 9px 12px; margin: 0;
}
input.mono, textarea.mono { font-family: var(--mono); font-size: 14px; }
textarea { min-height: 11em; resize: vertical; }
input:hover, select:hover, textarea:hover { border-color: var(--tick); }
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--accent); outline: 1px solid var(--accent); outline-offset: 0; }
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); width: 16px; height: 16px; }
.check { display: flex; align-items: center; gap: 10px; font-size: 16px; color: var(--ink); text-transform: none; letter-spacing: 0; font-family: var(--sans); }

/* Docs */
.docs { display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: 48px; align-items: start; padding: 40px 0; }
.docs-side { position: sticky; top: 24px; display: flex; flex-direction: column; max-height: var(--side-room, calc(100vh - 150px)); }
.docs-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-bottom: 20px; scrollbar-width: thin; }
.docs-side p.label, .docs-menu p.label { margin: 0 0 10px; }
.docs-side ol, .docs-menu ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.docs-side ol a, .docs-menu ol a { display: grid; grid-template-columns: 22px 1fr; gap: 8px; align-items: baseline; padding: 4px 0; text-decoration: none; font-size: 16px; color: var(--body); }
.docs-side ol a span:first-child, .docs-menu ol a span:first-child { font: 400 11px/1 var(--mono); color: var(--muted); }
.docs-side ol a:hover, .docs-menu ol a:hover { color: var(--ink); }
.docs-side ol a.here, .docs-menu ol a.here { color: var(--ink); font-weight: 600; }
.docs-side ol a.here span:first-child, .docs-menu ol a.here span:first-child { color: var(--accent); }
.docs-menu { display: none; }

/* Search: the entry looks like a flat, empty field; the dialog is a sheet
   with a field on top and the results beneath. */
.search-open { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex: none; margin: 0 0 20px; padding: 6px 8px 6px 10px; background: var(--sunk); border: 1px solid var(--rule-2); border-radius: 3px; font-size: 15px; line-height: 1.4; color: var(--muted); text-decoration: none; }
.search-open:hover { color: var(--ink); border-color: var(--tick); }
.search-open kbd { font: 400 11px/1.5 var(--mono); color: var(--muted); border: 1px solid var(--rule-2); border-radius: 2px; padding: 0 5px; }
.search-open kbd:empty { display: none; }
@media (hover: none) { .search-open kbd { display: none; } }
html.searching { overflow: hidden; }
dialog.search { width: min(640px, calc(100vw - 24px)); max-width: none; max-height: min(600px, calc(100dvh - 24px)); margin: 12vh auto auto; padding: 0; border: 1px solid var(--rule-2); border-radius: 4px; background: var(--sheet); color: var(--ink); overflow: hidden; }
dialog.search[open] { display: flex; flex-direction: column; }
dialog::backdrop { background: rgba(9, 9, 11, .42); }
:root[data-theme="dark"] dialog::backdrop { background: rgba(0, 0, 0, .66); }
.search-box { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.search-field { display: flex; align-items: center; gap: 10px; flex: none; padding-right: 12px; border-bottom: 1px solid var(--rule); }
.search-field:focus-within { border-bottom-color: var(--accent); }
.search-field input { flex: 1 1 auto; min-width: 0; margin: 0; padding: 15px 16px; border: 0; background: none; font: 400 19px/1.3 var(--sans); color: var(--ink); -webkit-appearance: none; appearance: none; }
.search-field input::placeholder { color: var(--muted); }
.search-field input:focus-visible { outline: none; }
.search-field input::-webkit-search-cancel-button { display: none; }
.search-close { flex: none; font: 500 11px/1 var(--mono); letter-spacing: .06em; color: var(--muted); border: 1px solid var(--rule-2); border-radius: 2px; padding: 5px 7px; }
.search-close:hover { color: var(--ink); border-color: var(--muted); }
.search-status { padding: 14px 16px; font-size: 15px; color: var(--muted); }
.search-status:empty { padding: 0; }
.search-results { list-style: none; margin: 0; padding: 6px 0; overflow-y: auto; overscroll-behavior: contain; flex: 1 1 auto; min-height: 0; }
.search-results:empty { display: none; }
.search-results li { display: grid; gap: 1px; padding: 9px 16px 10px 14px; border-left: 2px solid transparent; cursor: pointer; }
.search-results li[aria-selected="true"] { background: var(--sunk); border-left-color: var(--accent); }
.sr-page { font: 500 11px/1.5 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.sr-head { font-size: 16px; line-height: 1.35; font-weight: 600; color: var(--ink); }
.sr-text { font-size: 14px; line-height: 1.45; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.search-results mark { background: var(--accent-soft); color: var(--ink); border-radius: 1px; }
.search-hint { flex: none; display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: baseline; padding: 8px 16px; border-top: 1px solid var(--rule); font: 400 11px/1.6 var(--mono); color: var(--muted); }
.search-hint kbd { font: inherit; border: 1px solid var(--rule-2); border-radius: 2px; padding: 0 4px; }
.search-hint kbd:not(:first-child) { margin-left: 10px; }

/* A page of prose: docs, terms, privacy, about. */
.doc { min-width: 0; max-width: 68ch; }
.doc > * + * { margin-top: 16px; }
.doc > .label { margin: 0 0 12px; }
.doc h1 { font-size: clamp(1.8rem, 3.2vw, 2.4rem); line-height: 1.16; letter-spacing: -0.02em; }
.doc h1 + p { margin-top: 18px; }
.doc h2 { font-size: 1.4rem; line-height: 1.25; margin-top: 40px; scroll-margin-top: 24px; }
.doc h3 { font-size: 1.1rem; margin-top: 28px; scroll-margin-top: 24px; }
.doc .anchor { text-decoration: none; color: inherit; }
.doc h2 .anchor:hover::after, .doc h3 .anchor:hover::after { content: " #"; color: var(--accent); }
.doc p, .doc li { color: var(--ink); }
.doc p > code, .doc li > code, .doc td > code, .doc h2 code, .doc h3 code, .inline-code { font-size: .84em; background: var(--sunk); border: 1px solid var(--rule); padding: 1px 4px; border-radius: 2px; color: var(--ink); overflow-wrap: anywhere; }
.doc ul, .doc ol { padding-left: 1.2em; margin-bottom: 0; }
.doc li + li { margin-top: 5px; }
.doc .table { overflow-x: auto; }
.doc table { width: 100%; border-collapse: collapse; font-size: 15px; }
.doc th, .doc td { text-align: left; padding: 8px 10px 8px 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
.doc th { font: 500 11px/1.5 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.doc td:first-child { white-space: nowrap; }
.doc blockquote { margin: 0; border-left: 2px solid var(--accent); padding: 2px 16px; color: var(--ink); }
.doc hr { border: 0; border-top: 1px solid var(--rule); }
.code pre { background: var(--sunk); border: 1px solid var(--rule); border-radius: 3px; padding: 14px 16px; }
.pager { display: flex; justify-content: space-between; gap: 16px; margin-top: 48px; padding-top: 20px; border-top: 1px solid var(--rule); font-size: 16px; }
.pager a { text-decoration: none; display: grid; color: var(--ink); }
.pager a:hover { color: var(--accent); }
.pager a small { color: var(--muted); font: 400 11.5px/1.6 var(--mono); letter-spacing: .08em; text-transform: uppercase; }
.pager .next { text-align: right; margin-left: auto; }

@media (max-width: 900px) {
  .row { grid-template-columns: minmax(0, 1fr); gap: 14px; row-gap: 14px; }
  .row > .label { padding-top: 0; }
  .row > .span { margin-top: 18px; }
  .solo { grid-template-columns: minmax(0, 1fr); gap: 8px; padding-top: 24px; }
  .solo > .label { padding-top: 0; }
  .docs { grid-template-columns: minmax(0, 1fr); gap: 0; padding-top: 24px; }
  .docs-side { display: none; }
  .docs-menu { display: block; margin-bottom: 22px; }
  .docs-menu summary { list-style: none; cursor: pointer; font: 500 11.5px/1.5 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); padding: 8px 0; border-bottom: 1px solid var(--rule); }
  .docs-menu summary::-webkit-details-marker { display: none; }
  .docs-menu summary::after { content: " +"; }
  .docs-menu[open] summary::after { content: " \2212"; }
  .docs-menu ol { padding: 10px 0; }
  .docs-menu .search-open { margin: 12px 0 2px; }
}
@media (max-width: 760px) {
  body { font-size: 16.5px; }
  .page { border-left: 0; border-right: 0; }
  .links { display: none; }
  .menu { display: block; position: relative; }
  .menu summary { list-style: none; cursor: pointer; font-size: 16px; color: var(--ink); }
  .menu summary::-webkit-details-marker { display: none; }
  .menu ol { position: absolute; left: 0; top: calc(100% + 10px); min-width: 190px; background: var(--sheet); border: 1px solid var(--rule); border-radius: 3px; padding: 10px 12px; list-style: none; margin: 0; z-index: 5; display: grid; gap: 8px; }
  .menu a, .menu button { color: var(--ink); text-decoration: underline; text-decoration-color: var(--rule-2); text-underline-offset: .16em; }
  .menu form { margin: 0; }
  .top { padding-top: 20px; }
  .opening { padding: 40px 0 36px; }
  .install { display: flex; width: 100%; justify-content: space-between; }
  .installs { display: grid; }
  .tabs { flex-wrap: nowrap; gap: 0; }
  .tab { position: relative; flex: 1 1 0; justify-content: center; padding: 11px 0 12px; }
  .tab .logo { width: 18px; height: 18px; }
  .tab .name { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
  .catches li { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .row { padding: 56px 0; }
  .browser .chrome { grid-template-columns: auto minmax(0, 1fr); }
  .browser .chrome > span:last-child { display: none; }
  .browser .screen { padding: 0 14px 8px; }
  .figures { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .figures dd { font-size: 26px; }
  .board .hide-sm { display: none; }
  dialog.search { margin-top: 12px; max-height: calc(100dvh - 24px); }
  .search-hint { display: none; }
}
