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

/* The page's own type: Instrument Sans for everything, running text at 14 px, and the display sizes
   with the tight leading the handoff draws them in. The body is the ground: square, under
   everything, and what shows wherever the page is cut. */
body {
  margin: 0;
  background: var(--color-ground);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1 {
  font-size: var(--text-display-4);
  font-weight: var(--weight-display);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  margin: 0 0 var(--space-4);
}

h2 {
  font-size: var(--text-display-5);
  font-weight: var(--weight-regular);
  line-height: var(--leading-section);
  letter-spacing: var(--tracking-section);
  margin: var(--space-8) 0 var(--space-3);
}

h3 {
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  margin: var(--space-4) 0 var(--space-2);
}

p { margin: 0 0 var(--space-3); max-width: var(--measure-text); }

/* Emphasis is the interface weight, as the snapshot writes an address in a sentence. */
strong, b { font-weight: var(--weight-medium); }

a { color: inherit; text-underline-offset: 0.15em; }

a:focus-visible {
  outline: var(--focus-width) solid var(--color-accent);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-chip);
}

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

/* Words for a screen reader only: in the accessibility tree, off the screen. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.error { color: var(--color-danger); }

code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--color-surface);
  border: var(--hairline) solid var(--color-line);
  border-radius: var(--radius-chip);
  padding: 1px 5px;
}

pre {
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  background: var(--color-surface);
  border: var(--hairline) solid var(--color-line);
  border-radius: var(--radius);
  padding: var(--space-3);
  overflow-x: auto;
}

button {
  font: inherit;
  color: var(--color-ink);
  background: var(--color-surface);
  border: var(--hairline) solid var(--color-line);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
}

::selection {
  background: var(--color-ink);
  color: var(--color-bg);
}

/* ---- On the ground ----

   Whatever sits on the ground rather than on the shell: the frame's top line and footer, a well's
   lip, the tray. The ground is the same in both themes, so on it the inks every component reads are
   turned to the ones written on the ground, and a component drawn there (the mark, the theme word,
   who is here, a quiet button, a primary one) needs no variant to be legible: the ink is white, the
   muted words grey, a hairline the tray's grey, and a primary control white with the ground's
   colour on it. `--color-shell-ink` (tokens.css) keeps the page's own ink for the one thing on the
   ground drawn in the shell's colours, the current wing's pill. */

.on-ground {
  --color-ink: var(--color-on-ground);
  --color-muted: var(--color-on-ground-muted);
  --color-line: var(--color-on-ground-kind);
  --color-accent: var(--color-on-ground);
  --color-accent-hover: var(--color-on-ground-hover);
  --color-accent-ink: var(--color-ground);
  color: var(--color-ink);
}

/* ---- The frame: the ground and the shell ----

   The top line, the page, the tray at its foot and, on the customer's site, the footer: `Frame`
   (frame.rs), the one frame both sites wear around their routes.

   The top line lives on the ground, so it stops competing with the page (the Design pass, "THE
   GROUND"); the page is the shell, white and rounded, inset from the ground on three sides, and it
   fills the window's height so the ground shows as a frame and not as a gap. The customer's site
   is drawn for a phone and wider where there is room (`frame-adapt`, frame-adapt.css); HQ's shell
   runs across the window and its pages up to the wide measure inside it (`frame-wide`). */
.frame {
  display: flex;
  flex-direction: column;
}

/* The top line: the mark and, on HQ, the wings at the start; the theme switch and who is here at
   the end, pushed there even when the start is empty. On the ground, at the nav's height. */
.frame-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-7);
  min-height: var(--nav-height);
  padding: var(--space-2) calc(var(--shell-inset) + var(--space-2));
}

.frame-start {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-7);
}

.frame-end {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-left: auto;
}

.frame-home {
  display: inline-flex;
  color: inherit;
  text-decoration: none;
}

/* The shell: the page, resting on the ground, and the scroller of everything in it (below), which
   keeps whatever a page paints past its own edges inside the rounded corners. Positioned, so it is
   the containing block of what a page positions absolutely: a screen reader's hidden words far down
   the page otherwise escaped the scroller and made the window scroll by their offset (the
   customer's order page at 390, 14 Oct 2026). */
.page {
  position: relative;
  flex: 1;
  width: auto;
  min-height: 0;
  margin: 0 var(--shell-inset);
  padding: var(--space-7) var(--space-5) var(--space-10);
  background: var(--color-shell);
  color: var(--color-ink);
  border-radius: var(--radius-shell);
  overflow: hidden auto;
}

/* HQ's pages run to the wide measure, centred in a shell that runs across the window. */
.frame-wide .page {
  padding-inline: max(var(--space-5), calc((100% - var(--measure-wide)) / 2));
}

/* **The frame is the window's height, and its foot is the tray** (docs/decisions.md, 14 Oct 2026,
   "The browser crates", (5) on HQ and (10) on the customer's site; Reed, 12 Oct: "the tray is
   ground, not a bar over the page"). The white
   shell takes the room the top line and the tray leave and scrolls inside itself, so it ends in its
   rounded corners above the tray and nothing runs under it; the tray (`.frame-tray`, which a page
   fills through `FrameTray`) is a box as tall as what is in it, on the ground, and never moves.
   Empty, the tray is the shell's inset of ground, so a page with nothing in it looks as it always
   did. Grid and flex alone: nothing is measured. Chosen over `position: fixed` with the shell padded
   by the tray's height, which wraps and would have to be measured, and over a page taking the
   shell's place with `:has` (the 12 Oct build), which put a second shell in one page's stylesheet. */
.frame {
  height: 100vh;
  height: 100dvh;
  min-height: 0;
}

.frame-tray {
  flex: none;
  min-height: var(--shell-inset);
}

/* Nobody signed in, on a page that is no way in: the shell stays, empty, while the browser is sent
   to sign in (`Frame`, `send_nobody_to_sign_in`). */
.page[data-leaving] > * {
  visibility: hidden;
}

@media (min-width: 48rem) {
  .frame-wide .page {
    padding-block: var(--space-8) var(--space-12);
    padding-inline: max(var(--space-10), calc((100% - var(--measure-wide)) / 2));
  }
}

/* On a phone the Spec draws the shell 6 px in from the ground, at 16 px corners. */
@media (max-width: 36rem) {
  .page {
    margin: 0 var(--shell-inset-narrow);
    border-radius: var(--radius-shell-narrow);
  }

  .frame-tray {
    min-height: var(--shell-inset-narrow);
  }
}

/* The customer's footer, on the ground under the shell and its tray: where this is and whose, in the
   mono face. One quiet line, since the frame is the window's height and the footer is always on
   screen. */
.frame-foot {
  flex: none;
  padding: 0 var(--space-5) var(--space-2);
  color: var(--color-on-ground-muted);
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  line-height: var(--leading-body);
}

/* Who is here, at the end of the top line: the first name in the ground's ink, a short hairline,
   and the way out, quiet. "Sign out" is a quiet button, which elsewhere is underlined; here it reads
   as the Spec draws it, plain until the pointer is on it. */
.whoami {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin: 0;
  color: var(--color-muted);
  font-size: var(--text-quiet);
  white-space: nowrap;
}

.whoami-name {
  color: var(--color-ink);
}

.whoami-rule {
  width: var(--hairline);
  height: var(--space-3);
  background: var(--color-line);
}

.whoami .button-quiet {
  font-size: var(--text-quiet);
  text-decoration-color: transparent;
}

.whoami .button-quiet:hover {
  text-decoration-color: currentColor;
}

/* A stored comment as a page shows it. */
.comment-body img { max-width: 100%; height: auto; }
.comment-body a { color: var(--color-accent); }

/* The loader over the app's own first load (`vendor/loading.js`). Each shell's `index.html` draws
   the top line and this empty shell in plain HTML, with the frame's own classes, so what a person
   sees first is the page they are about to read with the marks on it and nothing moves when the app
   replaces it. The loader's canvas is absolute inside the box, so the box is positioned; `done()`
   fades the whole frame and takes it away once the app has drawn its own. The marks take the page's
   ink, kept faint by the loader itself. */
.boot-frame {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--color-ground);
  transition: opacity 0.22s ease-out;
}

/* On its way out, so the app underneath is not swapped in on one frame. */
.boot-frame[data-gone] {
  opacity: 0;
  pointer-events: none;
}

/* Its colours are the tokens' (`--garment-loader-mark`, `--garment-loader-sea`), inherited. */
.app-loading {
  position: relative;
}
