/* Perigee palette — instrument black, chalk, and one redline.
 *
 * Dark throughout. There is no light theme: this is an R&D and flight-test
 * tool, read on a laptop in a van at a dune site as often as at a desk, and a
 * near-black instrument surface suits that better than a document.
 *
 * The interface carries **one hue**, and it always means the same thing. Red is
 * the limit mark: the thing to act on, the thing not to do, the thing that
 * needs a person, the claim still to be proven. Everything else — every surface, every rule, every state that
 * is merely fine — is achromatic. That is the whole discipline, and it is what
 * keeps a near-black page minimal rather than merely dark: with no second
 * accent to compete, a single red mark is read before anything else on screen.
 *
 * Consequences worth stating, because they are easy to undo one rule at a time:
 *
 *   - **A primary action is chalk, not red.** A white fill on near-black is the
 *     strongest affordance available here, and it leaves red free to mean
 *     consequence. It is also what stops a destructive button reading as a
 *     slightly-off primary one — the two are now different colours, not two
 *     shades of the same one.
 *   - **A positive state is achromatic.** No green. A confirmation says what it
 *     is in words; it does not need a hue, and adding one would put a second
 *     accent back on the page for the least important message on it.
 *   - **Do not add a hue for a new state.** Weight, tint and border carry that.
 *
 *   redline   the one hue. Links, eyebrows, focus rings, admin chrome, the
 *             destructive fill, the search mark, the removed line in a diff.
 *   chalk     text and primary fills.
 *   void      the page. surface-1 and surface-2 raise off it.
 *
 * The --light-color-* / --dark-color-* names are inherited and read backwards:
 * --light-color-N is foreground text, --dark-color-N is a surface. They are
 * referenced across every component, so they keep their names and take new
 * values here. New work should prefer the semantic names below.
 */

/* Registered so the theme transition below can interpolate them. */
@property --light-color-1 {
    syntax: '<color>';
    inherits: true;
    initial-value: #F4F4F5;
}

@property --light-color-2 {
    syntax: '<color>';
    inherits: true;
    initial-value: #F4F4F5;
}

@property --light-color-3 {
    syntax: '<color>';
    inherits: true;
    initial-value: #B3B3B8;
}

:root {
    /* --- Palette ------------------------------------------------------- */

    /* Neutral, not blue-cast or warm. The greys carry no hue of their own, so
       the red is the only chromatic thing on the page and reads as a mark
       rather than as part of a scheme. */
    --void: #0A0A0B;
    --surface-1: #131315;
    --surface-2: #1B1B1E;
    --scrim: rgba(10, 10, 11, 0.96);

    /* Hue 0 — pure red, no drift. Warmer than about 4° starts reading as safety
       orange; cooler than about 355° heads back toward the magenta this palette
       replaced, and loses contrast doing it.
       Light enough to be a foreground: 5.6:1 on --surface-1, and --void on it
       is 6.0:1, which is what lets the same value also be a fill under a dark
       label. A deeper, more saturated red would pass as a fill and fail as
       text, and this palette needs one red to be both.
       It is lighter than a pure red wants to be, and the reason is that this is
       the only hue in the interface — every state that is not fine is stated in
       it. Simulated for protanopia it falls to 3.8:1, which is thin; at the
       full-saturation #FF2E2E it was 3.15:1, which is not usable. Nothing here
       is distinguished by hue alone, so red losing its luminance costs emphasis
       rather than meaning, but a red carrying this much load is worth the two
       steps of lightness. Do not darken it back for saturation. */
    --redline: #FF4A4A;
    --redline-hi: #FF6E6E;
    /* Rules and outlines only — 2.7:1, so nothing that has to be read. */
    --redline-dim: #B01C1C;
    --redline-tint: rgba(255, 74, 74, 0.12);

    --chalk: #F4F4F5;
    /* A chalk fill cannot brighten on hover, so it steps down instead. */
    --chalk-dim: #DADADF;
    --chalk-tint: rgba(244, 244, 245, 0.10);

    /* Borders are light at very low alpha rather than dark: on a near-black
       surface a darker line is invisible. */
    --hairline: rgba(244, 244, 245, 0.10);
    --hairline-strong: rgba(244, 244, 245, 0.20);

    /* --- Semantic roles ------------------------------------------------ */
    --signal-color: var(--redline);
    --signal-color-lighter: var(--redline-hi);

    /* Destructive and error. The same red as the signal colour, deliberately:
       a link and a delete button are told apart by shape here, and inventing a
       second red to distinguish them would put two nearly-identical hues on the
       page — the fault the old palette had between its accent and its alarm. */
    --alarm: var(--redline);
    --alarm-tint: var(--redline-tint);
    --carmine: var(--redline);

    /* Positive, available, resolved. Achromatic on purpose — see the header. */
    --ok: var(--chalk);
    --ok-tint: var(--chalk-tint);

    /* Surfaces. Named "dark-color" for historical reasons — see the header. */
    --dark-color-1: var(--surface-1);
    --dark-color-2: var(--surface-2);

    /* Foreground tiers. --light-color-4 is body copy in page.css, so it is held
       at ~5.5:1 on --surface-1 rather than being dimmed to taste. */
    --light-color-1: #F4F4F5;
    --light-color-2: #F4F4F5;
    --light-color-3: #B3B3B8;
    --light-color-4: #8D8D94;

    /* For content sitting on an accent or on the deepest surface. */
    --on-dark-1: #F4F4F5;
    --on-dark-2: rgba(244, 244, 245, 0.72);
    --on-dark-muted: rgba(244, 244, 245, 0.45);

    /* Inset fills for form rows and pills. */
    --lighten-color-1: rgba(244, 244, 245, 0.05);
    --lighten-color-2: rgba(244, 244, 245, 0.10);

    /* And "darken" recesses: input wells, and the dropdown's opaque panel. */
    --darken-color-1: rgba(0, 0, 0, 0.32);
    --darken-color-2: #0D0D0F;

    /* --- Code --------------------------------------------------------------
     *
     * The five classes svc/docs/highlight.go and svc/markdown/highlight.go
     * emit, kept here rather than in public.css and docs.css because both files
     * style the same renderer's output and two copies drift.
     *
     * Near-monochrome, with the red where it already means something: a diff
     * fence reuses these three, so a removed line lands on --code-keyword and
     * an added one on --code-type — red out, white in. */
    --code-comment: #7F7F87;
    --code-string: #C4C4CA;
    --code-number: #FF9A93;
    --code-keyword: var(--redline);
    --code-type: #ECECEF;
}

body {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-height: 100vh;
    font-family: sans-serif;
    font-size: 16px;
    color: var(--light-color-1);
    background: var(--void);
    transition: background 0.4s ease, --light-color-1 0.15s ease-in, --light-color-2 0.15s ease-in, --light-color-3 0.15s ease-in;
    font-synthesis: none;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    -webkit-text-size-adjust: 100%;
}

html,
body {
    margin: 0;
}

::selection {
    background: var(--redline);
    color: var(--void);
}

/* One visible focus treatment for the whole site. Components that set their
   own :focus styles override this; everything else inherits something you can
   actually see on a dark surface. */
:focus-visible {
    outline: 2px solid var(--redline);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    body {
        transition: none;
    }
}

/* Above the nav bar rather than under it. The bar carries a blurred, darkened
   scrim now, and a progress bar showing through it reads as a rendering
   artefact rather than as progress — on the front page it is also the one
   moving thing on a photograph. */
pg-loader {
    top: 0;
    position: fixed;
    display: flex;
    z-index: 600;
    max-width: 900px;
    width: 100vw;
    box-sizing: border-box;
}

pg-router {
    display: flex;
    flex: 1;
    width: 100vw;
    box-sizing: border-box;
    justify-content: center;
}

/* Full-bleed. The 900px column and the padding are inside the component now,
   because its scrim has to reach both edges of the window; see nav/bar.js. */
pg-nav-bar {
    width: 100%;
    box-sizing: border-box;
}

/* A page with a full-bleed hero takes the bar out of the flow and floats it
   over the photograph, so the image starts at the top of the window instead of
   below a strip of --void. The bar's own scrim is what keeps it legible there.

   Keyed on the hero rather than on the page component, so the front page keeps
   this when it is server-rendered in Go — that shell will emit the same
   `.header.hero` markup and nothing about the front page. It is deliberately not `position:
   fixed`: the bar scrolls away with the picture it belongs to, which is what it
   does on every other page.

   :has() rather than a class toggled in JS, which would have to be undone in
   disconnectedCallback and would be a second place for the front page to
   declare what it is. */
body:has(.hero) pg-nav-bar {
    position: absolute;
    top: 0;
    left: 0;
    /* Turns on the bar's blurred scrim; see nav/bar.js. It travels as a custom
       property because it crosses a shadow boundary, and it is set here rather
       than always-on because over --void it is invisible and over the top of an
       ordinary .header band it is not. */
    --nav-scrim: block;
}
