/* Chrome and palette shared by every page on the site.
 *
 * These rules lived in three copies until 2026-09-06, one per page, with
 * a note in faq.html saying to extract them when a third page arrived.
 * /docs was the third page.
 *
 * What belongs here is what must be identical everywhere: the palette,
 * the reset, the header, the footer and the focus ring. What does not is
 * anything a page is entitled to decide for itself. "main" is the clear
 * case, sized to an input box on the home page and to a paragraph on the
 * other two, and it stays in each page's own <style>.
 *
 * The three copies had not drifted in value when they were merged, which
 * is luck rather than process, and is the argument for this file.
 */

:root {
    --bg: #0f1115;
    --panel: #191c22;
    --ink: #eef1f6;
    --muted: #a2abba;
    --brand: #4aa8ff;
    --brand-hover: #7cc2ff;
    --brand-solid: #0b6fc4;
    --brand-solid-hover: #0a5ea6;
    --border: #2a2f38;
    --hl-bg: #ffd54f;
    --hl-ink: #1a1a1a;
    --font-body: "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-head: "Space Grotesk", "Inter", "Segoe UI", sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

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

/* line-height is deliberately absent. The home page has never set one on
   body and the other two set 1.6, so putting a value here would change
   how one of them renders. A refactor that moves text on the page is not
   a refactor. Each page states its own. */
body {
    color-scheme: dark;
    font-family: var(--font-body);
    background: var(--bg);
    color: var(--ink);
    margin: 0;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

header,
footer {
    background: var(--panel);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
    text-align: center;
}

header {
    padding: 1.25rem 2rem;
}

/* The logo is a link on every page except the home page, where there is
   nowhere to go back to. */
header a {
    display: inline-block;
    line-height: 0;
    border-radius: 4px;
}

footer {
    font-size: 0.85rem;
    color: var(--muted);
    padding: 1.1rem 1rem;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}

footer .copyright {
    margin-top: 0.75rem;
}

.links {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.6rem 1.4rem;
}

.links a {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--brand);
    font-weight: 500;
    text-decoration: none;
}

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

/* The highlight carries its own ink. It inherits the body color
   otherwise, which on a dark page means near-white text on pale yellow:
   the one thing that would make the demo unreadable, and the highlights
   are the demo. */
.hl {
    background: var(--hl-bg);
    color: var(--hl-ink);
    padding: 0 2px;
    border-radius: 3px;
}

code {
    font-family: var(--font-mono);
    font-size: 0.86em;
    color: var(--ink);
    background: var(--panel);
    border: 1px solid var(--border);
    padding: 0.05em 0.35em;
    border-radius: 3px;
    white-space: nowrap;
}

/* index.html had no rule for this and picked up the browser default.
   It gets the brand ring now, which is the point of a shared sheet:
   keyboard focus should not look like a different site per page. That is
   one of exactly two rendering differences this extraction makes, it is
   visible only to a keyboard, and it is an improvement. */
a:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
    border-radius: 3px;
}

/* The other one. index.html had no reduced-motion rule, so its
   transitions ran for everybody, including people whose system asks them
   not to. Now they do not. */
@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
    }
}

/* ---- scroll to top ------------------------------------------------
   Only the two long pages carry one. Measured at 1100x800: the FAQ is
   27.4 screens and the API docs 11.2, where the home page is 1.8 and
   contact is 1.0. A control that saves nothing on a short page is
   clutter, so those two do not get it.

   An anchor rather than a button, so it inherits the focus ring above
   instead of needing its own, and so it still means something to a
   screen reader. It is hidden until there is something to scroll back
   from, which is the only state where it is useful. */
.to-top {
    position: fixed;
    right: max(1.1rem, env(safe-area-inset-right));
    bottom: max(1.1rem, env(safe-area-inset-bottom));
    width: 2.75rem;
    height: 2.75rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--brand-solid);
    border: 1px solid var(--brand);
    color: #fff;
    text-decoration: none;
    /* On a wide screen this sits in the gutter beside a centred column and
       touches nothing. On a phone the column is the full width, so it
       necessarily floats over the text. The shadow and the ring are what
       make that read as layered rather than as a collision: without them
       a flat disc dropped on a line of prose just looks like a mistake. */
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55), 0 0 0 4px rgba(15, 17, 21, 0.55);
    opacity: 0;
    visibility: hidden;
    transform: translateY(0.4rem);
    transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
    z-index: 50;
}

.to-top.is-visible {
    opacity: 1;
    visibility: visible;
    transform: none;
}

.to-top:hover {
    background: var(--brand-solid-hover);
}

.to-top svg {
    width: 1.15rem;
    height: 1.15rem;
    display: block;
}

/* The control rests over the footer at the end of a long page. On a wide
   screen it lands in the gutter beside a centred footer and touches
   nothing. A phone footer is full width, so it would sit on the copyright
   line instead. Make room, and the button floats in empty space at both
   sizes, which is the only thing that differed. */
@media (max-width: 600px) {
    body:has(.to-top) footer {
        padding-bottom: 4.75rem;
    }
}
