/* ============================================================
   The primitives layer (ADR-144, plan V1.17). Linked first by every
   page: the product site (product.css), the family archive
   (archive.css, mht.css), the book (its two shells) and the console
   (admin.css). This file owns geometry and behaviour; each identity
   owns its colours and its type, so no colour and no font is named
   here (base_css.test.ts). Its selectors are no stronger than one
   class, so every identity rule after it wins.

   Breakpoints, everywhere: phone under 600px, tablet 600-899px,
   desktop 900px and up, wide 1200px and up. Logical properties only.
   ============================================================ */

:root {
  /* spacing, a 4/8 scale */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;
  --sp-8: 64px;
  /* radii */
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 14px;
  --r-pill: 999px;
  /* a control's height: 48px; the public sites, the resident's pages and
     the paper surface set 56px, the console 44px */
  --h-control: 48px;
  /* the focus ring's width and offset; its colour, --focus-ring, is each
     identity's (from DS2) */
  --focus-w: 3px;
  --focus-off: 3px;
}

/* Read by a screen reader, never seen. One rule under every name the
   pages use. */
.sr-only, .vh, .visually-hidden, .pp-sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Where the keyboard is: one ring on every page, in the colour each
   identity gives --focus-ring (and may change on a dark band with
   outline-color). A browser with no :focus-visible shows it on focus. */
:focus-visible {
  outline: var(--focus-w) solid var(--focus-ring, currentColor);
  outline-offset: var(--focus-off);
}
@supports not selector(:focus-visible) {
  a:focus, button:focus, input:focus, select:focus, textarea:focus, summary:focus {
    outline: var(--focus-w) solid var(--focus-ring, currentColor);
    outline-offset: var(--focus-off);
  }
}
/* main takes focus when the skip link is followed; nobody tabbed to it. */
main:focus { outline: none; }

/* The first thing the keyboard reaches: a jump past the bar to the page.
   Off-screen until focused. Its colours and type are the identity's. */
.skip-link, .skip {
  position: absolute;
  inset-inline-start: -9999px;
  inset-block-start: 0;
  z-index: 1000;
  display: inline-flex;
  align-items: center;
  min-height: var(--h-control);
  padding: var(--sp-3) var(--sp-5);
  text-decoration: none;
}
.skip-link:focus, .skip:focus {
  inset-inline-start: var(--sp-3);
  inset-block-start: var(--sp-3);
}
@media print { .skip-link, .skip { display: none; } }

/* Buttons: one family. .btn holds the mechanics; a variant sets only
   tokens, which an identity gives values (--primary, --on-primary,
   --danger, --on-danger); the identity's own button rule keeps its colours,
   padding and type. Unset, the tokens change nothing: no border, no
   background, the parent's ink. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--h-control);
  min-width: var(--h-control);
  padding-inline: var(--sp-5);
  border: var(--btn-border-w, 0) solid var(--btn-border, transparent);
  border-radius: var(--r-btn, var(--r-md));
  background: var(--btn-bg, transparent);
  color: var(--btn-ink, inherit);
  font-family: inherit;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.btn-primary { --btn-bg: var(--primary); --btn-ink: var(--on-primary); }
.btn-quiet, .btn-ghost { --btn-bg: transparent; --btn-ink: var(--primary); --btn-border: currentColor; --btn-border-w: 1px; }
.btn-danger { --btn-bg: var(--danger); --btn-ink: var(--on-danger); }
.btn-large { --h-control: 56px; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.6; cursor: default; }

/* A message: its words always there, its colour from the identity's
   status tokens (--ok, --ok-soft, --ok-line, and -warn, -danger, -info). */
.flash {
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--flash-line, transparent);
  border-radius: var(--r-sm);
  background: var(--flash-bg, transparent);
  color: var(--flash-ink, inherit);
}
.flash-ok { --flash-bg: var(--ok-soft); --flash-ink: var(--ok); --flash-line: var(--ok-line, transparent); }
.flash-warn { --flash-bg: var(--warn-soft); --flash-ink: var(--warn); --flash-line: var(--warn-line, transparent); }
.flash-danger { --flash-bg: var(--danger-soft); --flash-ink: var(--danger); --flash-line: var(--danger-line, transparent); }
.flash-info { --flash-bg: var(--info-soft); --flash-ink: var(--info); --flash-line: var(--info-line, transparent); }

/* An element marked hidden stays hidden, whatever its display rule. */
[hidden] { display: none !important; }

/* A long word or URL wraps rather than pushing the page wider than a phone
   (plan V1.17 X3). Text breaks a word only when nothing else fits. A name
   in a heading and a quote may break anywhere, so a long name or URL never
   sets a minimum width; nothing else does, since that lets a flex item
   squeeze: a name in a header row would break mid-word. */
body { overflow-wrap: break-word; }
h1 bdi, h2 bdi, blockquote { overflow-wrap: anywhere; }

/* Motion follows the reader's setting: smooth scrolling only for a reader
   who has not asked for less motion, and for one who has, no animation
   or transition at all. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
