/* Rove — design tokens and primitives.
   Loaded by every page; page-specific layout lives alongside it. */

:root {
  color-scheme: light dark;

  --bg: #fbfaf8;
  --surface: #ffffff;
  --surface-sunken: #f4f2ee;
  --border: #e3dfd7;
  --border-strong: #cdc7ba;
  --text: #1c1a17;
  --text-muted: #6d675d;
  /* 5.38:1 on --surface, 4.81:1 on --surface-sunken. The previous #938c80 was
     3.33:1, which is the large-text threshold — but this token is only ever used
     at --step-0/--step-1, so it never qualified. */
  --text-faint: #6f6a60;
  /* Measured, not picked. Emphasis is carried by --accent, and in light mode
     the old #b4532a ran 4.16:1 on --accent-soft and 4.46:1 on --surface-sunken,
     both under the 4.5 floor for small text, while the dark palette's accent
     ran 5.6-6.8 on the same roles. Emphasis was measurably weaker in one theme
     than the other. Darkened until every accent pairing clears 5:1. */
  --accent: #a84d27;
  --accent-text: #ffffff;
  /* Lightened alongside it: this is the worst-case ground for accent text
     (the numbered step markers sit on it at 12px). */
  --accent-soft: #faf2ed;
  --danger: #a32f2f;
  --danger-soft: #fbeaea;
  /* Healthy, on the status page. 5.3:1 on --surface. */
  --ok: #2f7a45;
  --ok-soft: #e8f3eb;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  --radius: 8px;
  --radius-sm: 5px;

  /* Content width cap. The layout is left-aligned to the same gutter the
     full-bleed masthead uses, not centred — so the panels stay under the
     brand instead of drifting to the middle on a wide display. */
  --shell: 1280px;

  /* Type scale. Six steps, whole pixels. Sizes were previously tuned per rule,
     which produced fifteen sizes between 11 and 21px including half-pixel steps
     — the main reason the UI read as unsettled. Nothing outside this scale. */
  --step-0: 11px;   /* badges, brand mark, densest mono */
  --step-1: 12px;   /* form labels, meta rows, hints, timestamps */
  --step-2: 13px;   /* buttons, links, secondary prose, session body */
  --step-3: 14px;   /* inputs, topic names, session titles */
  --step-4: 15px;   /* body default */
  --step-5: 17px;   /* page and section headings */

  /* Spacing scale, 4px based. Replaces sixteen ad-hoc values (2,3,4,5,6,7,8,9,
     10,12,14,16,18,20,22,44) with one rhythm. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 40px;

  /* The site header's height, fixed so it is the same bar on every page. */
  --head-height: 60px;
}

/* Dark follows the system unless the page has been told otherwise: theme.js
   sets data-theme on <html> from the viewer's saved choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #17161a;
    --surface: #1f1e23;
    --surface-sunken: #26252b;
    --border: #322f38;
    --border-strong: #46424d;
    --text: #edeaf0;
    --text-muted: #a49eac;
    /* 5.19:1 on --surface, 4.76:1 on --surface-sunken; was #7b7583 at 3.72:1. */
    --text-faint: #948da0;
    --accent: #e08a5f;
    --accent-text: #1a1418;
    --accent-soft: #2f2620;
    --danger: #e98080;
    --danger-soft: #332123;
    --ok: #6cc489;
    --ok-soft: #1f2e24;
  }
}

:root[data-theme="light"] { color-scheme: light; }

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #17161a;
  --surface: #1f1e23;
  --surface-sunken: #26252b;
  --border: #322f38;
  --border-strong: #46424d;
  --text: #edeaf0;
  --text-muted: #a49eac;
  /* 5.19:1 on --surface, 4.76:1 on --surface-sunken; was #7b7583 at 3.72:1. */
  --text-faint: #948da0;
  --accent: #e08a5f;
  --accent-text: #1a1418;
  --accent-soft: #2f2620;
  --danger: #e98080;
  --danger-soft: #332123;
  --ok: #6cc489;
  --ok-soft: #1f2e24;
}

* { box-sizing: border-box; }

/* The UA stylesheet's [hidden] { display: none } is an author-beatable rule, and
   .btn, .form and .banner all set display — which silently defeated `hidden` on
   every button, form and banner that relies on it. State it as an author rule so
   toggling el.hidden actually hides. */
[hidden] { display: none !important; }

/* One focus ring for everything interactive. Only form controls used to have
   one, so tabbing through the console — whose primary navigation is a list of
   buttons — was invisible. :where() keeps specificity at zero so any component
   can still override it. */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--step-4)/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* Motion ------------------------------------------------------------------ */

/* In-page links glide rather than teleport, so you can see where you were taken
   from. Guarded on prefers-reduced-motion: a long smooth scroll is one of the
   reliable triggers for motion sickness, and the jump is the safe default. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* The theme cross-fade: theme.js swaps the theme inside a view transition, so
   the browser fades a picture of the old page into the new one. Not a
   transition on every element: scrollbars, form controls and anything with a
   transition of its own flip instantly instead, and for a moment the page is
   half of each, which reads as a flicker. Nothing here runs on first paint. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 200ms;
}

/* Brand ------------------------------------------------------------------- */

.brand { display: flex; align-items: center; gap: var(--space-3); }

/* The mark: three commits merging into one record, drawn like a git graph. The
   strands and commits take currentColor, so it reads as ink in either theme;
   only what comes out of the merge is accent, because that is the point.
   favicon.svg is the same drawing, and a test keeps the two identical. */
.logo {
  height: 26px;
  width: auto;
  display: block;
  flex: none;
  color: var(--text);
}

a.brand { text-decoration: none; color: inherit; }

/* Site header ------------------------------------------------------------- */
/* One bar for every page (product, docs, console, errors), so moving between
   them nothing jumps: a fixed height and the same padding, mark, wordmark and
   theme toggle in the same places. Each page fills in its own links. */

.site-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  height: var(--head-height);
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  position: sticky;
  top: 0;
  z-index: 2;
}
.site-head .brand { flex: none; }
.wordmark { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -0.02em; line-height: 1; }
.site-links { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }

/* Phones: still one row. The text links step aside (each page links to the
   others in its body); the mark, the main action and the theme stay. */
@media (max-width: 640px) {
  .site-head { padding: 0 var(--space-4); gap: var(--space-3); }
  .site-links { gap: var(--space-3); }
  .site-links > .link { display: none; }
}
/* The narrowest phones: the mark alone, on every page, so the console's
   workspace picker still fits beside it. */
@media (max-width: 360px) {
  .site-head .wordmark { display: none; }
}
a.brand:hover .logo { color: var(--accent); }

.mark {
  font: 600 var(--step-0)/1 var(--mono);
  letter-spacing: 0.14em;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-text);
}

.link {
  color: var(--text-muted);
  font-size: var(--step-1);
  text-decoration: none;
  border-bottom: 1px solid var(--border-strong);
}
.link:hover { color: var(--text); }

/* Buttons ---------------------------------------------------------------- */

.btn {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--step-2);
  font-weight: 500;
  cursor: pointer;
  background: none;
  color: var(--text);
  text-decoration: none;
  display: inline-block;
}

.btn-primary { background: var(--accent); color: var(--accent-text); }
.btn-primary:hover:not(:disabled) { filter: brightness(1.08); }

.btn-ghost { border-color: var(--border-strong); color: var(--text-muted); }
.btn-ghost:hover { color: var(--text); border-color: var(--text-faint); }

.btn-wide { width: 100%; margin-top: var(--space-3); }
.btn-lg { padding: var(--space-3) var(--space-4); font-size: var(--step-3); }

.btn:disabled { opacity: 0.55; cursor: progress; }

/* Badges ----------------------------------------------------------------- */

.badge {
  display: inline-block;
  padding: var(--space-1) var(--space-2);
  border-radius: 100px;
  font-family: var(--mono);
  font-size: var(--step-0);
  line-height: 1.3;
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
}

.badge-seq { background: var(--surface-sunken); font-variant-numeric: tabular-nums; }
.badge-quiet { border-style: dashed; color: var(--text-faint); }
.badge-tag { border-color: var(--border); color: var(--text-muted); }

/* Theme toggle ------------------------------------------------------------ */
/* Shared by every page. Shows what a click switches to: the sun in dark mode,
   the moon in light. */

.theme-toggle {
  flex: none;   /* never squeezed by a crowded header */
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-muted);
  cursor: pointer;
}
.theme-toggle:hover { color: var(--text); border-color: var(--text-faint); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Before theme.js labels the button, the stylesheet's own guess: the system's. */
.theme-toggle .icon-sun { display: none; }
@media (prefers-color-scheme: dark) {
  .theme-toggle:not([data-showing]) .icon-sun { display: block; }
  .theme-toggle:not([data-showing]) .icon-moon { display: none; }
}
.theme-toggle[data-showing="dark"] .icon-sun { display: block; }
.theme-toggle[data-showing="dark"] .icon-moon { display: none; }

/* Shared by the product page and the docs ---------------------------------- */

.eyebrow {
  margin: 0 0 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.lede {
  margin: 26px 0 0;
  max-width: 62ch;
  font-size: 16.5px;
  color: var(--text-muted);
}

.footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  max-width: 940px;
  margin: 0 auto;
  padding: 22px 28px 40px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  color: var(--text-faint);
}

.footer-links { display: flex; gap: 16px; }

@media (max-width: 720px) {
  .footer { padding: 20px 16px 32px; }
  /* Thumb-sized: the links were 20px tall. */
  .footer-links .link { padding: 10px 0; }
}
