/* ==========================================================================
   RUBY FREMON — DESIGN TOKENS
   World: The Plate. Engraved precision, hairline rules, numbered callouts,
   the bordered plate as a formal object.

   Colour: true black and white. A pure neutral ramp with NO cast — not blue,
   not plum, not warm. There is no chromatic accent anywhere in this system.
   Contrast itself is the accent: a white plate on a black ground, a white
   button with black type. Introducing a hue is a change to the system.

   Three layers, in order. Never reach past a layer.
     1. PRIMITIVE  — raw values. Never used directly in components.
     2. SEMANTIC   — role-named. What components consume.
     3. COMPONENT  — per-component overrides, defined in components.css.
   ========================================================================== */

/* ==========================================================================
   1. PRIMITIVES
   ========================================================================== */

:root {
  /* --- Neutral ---------------------------------------------------------
     Pure greys, R=G=B at every stop. A cast is what made the last two
     palettes read as period pieces; there is none here by construction. */
  --p-black: #000000;
  --p-n-950: #0A0A0A;
  --p-n-900: #121212;
  --p-n-850: #171717;
  --p-n-870: #141414;  /* the ground's lift — see --surface-raised */
  --p-n-800: #1F1F1F;
  --p-n-700: #2B2B2B;
  --p-n-600: #3D3D3D;
  --p-n-500: #5C5C5C;
  --p-n-400: #8A8A8A;
  --p-n-300: #B0B0B0;
  --p-n-200: #D4D4D4;
  --p-n-100: #EBEBEB;
  --p-n-050: #F7F7F7;
  --p-white: #FFFFFF;

  /* --- Brand secondaries -----------------------------------------------
     Four client-specified tones. All desaturated and earth-derived, which is
     why they sit with the photography instead of fighting it — these are the
     colours already in the pictures: slate shadow, saddle leather, dry grass,
     bleached bone.

     Black and white still carries the structure. These carry warmth, and each
     has exactly ONE job, assigned by what it can legibly do rather than by
     taste. Measured ratios are on the semantic tokens below. */
  --p-slate-600: #38454A;  /* the lifted slate — surface only; white on it = 9.91:1 */
  --p-slate-700: #2C3639;  /* surface only — 1.60:1 on the ground, unreadable as text */
  --p-taupe-500: #78685E;  /* rules and large text; 3.71:1 on ground, 5.33:1 on white */
  --p-taupe-700: #665A50;  /* derived: the readable taupe — 6.68:1 on white, 5.06:1 on sheet */
  --p-olive-500: #86805D;  /* the dark-side accent — 4.96:1 on the ground */
  --p-sand-050:  #F0EBE3;  /* the lifted sheet — surface only; taupe-700 on it = 5.63:1 */
  --p-sand-100:  #E7DFD4;  /* warm sheet surface, or text at 14.99:1 on the ground */

  /* --- Type families ---------------------------------------------------
     Archivo carries display, text, and interface. A grotesque set very large
     and very tight is the modern elegant register, and — unlike the didone it
     replaces — its stems hold their weight at heading sizes on a black
     ground, which is the whole reason for the change.

     Times New Roman MT Condensed appears ONLY where Ruby's voice speaks:
     pull quotes, testimony, and the wordmark. One serif against one grotesque
     is the entire pairing; a third family would be decoration.

     NOT A WEBFONT. This is a licensed Monotype desktop face, not a Google
     font, and it is not installed on the build machine. Everyone without it
     locally gets the Times New Roman fallback below, which is a different
     width and will set noticeably wider. To ship it, license it for web use
     and self-host a woff2 with an @font-face rule; until then the fallback
     is what visitors actually see. */
  --p-font-display: Archivo, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --p-font-text: Archivo, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --p-font-voice: "Times New Roman MT Condensed", "TimesNewRomanMTStd-Cond", "Times New Roman", Times, Georgia, serif;

  /* --- Type scale ------------------------------------------------------
     Ratio 1.333 through the text range, then a deliberate jump at display.
     Enormous titles against microscopic keys; the middle is where nothing
     interesting happens. */
  --p-size-3xs: 0.6875rem; /* 11px — figure numbers, plate marks */
  --p-size-2xs: 0.75rem;   /* 12px — keys, captions */
  --p-size-xs: 0.8125rem;  /* 13px — labels, meta */
  --p-size-sm: 0.9375rem;  /* 15px — UI, dense text */
  --p-size-md: 1.0625rem;  /* 17px — body */
  --p-size-lg: 1.25rem;    /* 20px — lead paragraph */
  --p-size-xl: 1.625rem;   /* 26px */
  --p-size-2xl: 2.25rem;   /* 36px */
  --p-size-3xl: 3.25rem;   /* 52px */
  --p-size-4xl: 4.75rem;   /* 76px */
  --p-size-5xl: 7rem;      /* 112px — plate titles */

  --p-weight-regular: 400;
  --p-weight-medium: 500;
  --p-weight-semibold: 600;
  --p-weight-bold: 700;

  --p-leading-tight: 0.92;
  --p-leading-snug: 1.08;
  --p-leading-normal: 1.5;
  --p-leading-relaxed: 1.65;

  /* A grotesque at display scale must be tracked in, hard. Untracked large
     type is the single clearest tell of an unconsidered system. Small caps go
     the other way and open right up. */
  /* The voice face is tracked in tight, per the brand direction. Specified as
     -58 in design-tool units, which are 1/1000 em — so -0.058em here. */
  --p-tracking-voice: -0.058em;
  --p-tracking-display: -0.035em;
  --p-tracking-display-tight: -0.05em;
  --p-tracking-normal: 0;
  --p-tracking-wide: 0.08em;
  --p-tracking-key: 0.18em;

  /* --- Space -----------------------------------------------------------
     One rhythm throughout, 4px base. More space above a heading than below. */
  --p-space-0: 0;
  --p-space-1: 0.25rem;
  --p-space-2: 0.5rem;
  --p-space-3: 0.75rem;
  --p-space-4: 1rem;
  --p-space-5: 1.5rem;
  --p-space-6: 2rem;
  --p-space-7: 3rem;
  --p-space-8: 4rem;
  --p-space-9: 6rem;
  --p-space-10: 8rem;
  --p-space-11: 12rem;

  /* --- Line ------------------------------------------------------------
     The engraved line is the system's signature, and in a monochrome system
     it does most of the work colour would otherwise do. */
  --p-line-hair: 0.5px;
  --p-line-thin: 1px;
  --p-line-medium: 2px;
  --p-line-thick: 4px;

  /* --- Radius ----------------------------------------------------------
     A plate mark is square. Nothing in this world rounds. */
  --p-radius-none: 0;

  /* --- Motion ----------------------------------------------------------
     The world's native motion is the press: a plate meets paper, the
     impression settles. Nothing bounces. */
  --p-ease-press: cubic-bezier(0.16, 0.84, 0.44, 1);
  --p-ease-ink: cubic-bezier(0.4, 0, 0.2, 1);
  --p-dur-instant: 90ms;
  --p-dur-fast: 180ms;
  --p-dur-base: 320ms;
  --p-dur-slow: 640ms;
  --p-dur-draw: 1200ms; /* leader lines drawing themselves */

  --p-measure: 68ch;
  --p-measure-tight: 54ch;
}

/* ==========================================================================
   2. SEMANTIC
   Role-named. This is the only layer components are allowed to read.
   Every text pair below clears WCAG 2.2 AA against the surface it names.
   ========================================================================== */

:root {
  /* --- Surface ---------------------------------------------------------- */
  --surface-base: var(--p-n-950);
  --surface-sunken: var(--p-black);
  /* n-870, not n-850. The dark-side accent (olive) has almost no headroom:
     4.96:1 on the ground at rest. Lifting to n-850 dropped the small uppercase
     type that uses it — .figure-no and .tag inside a hovering .offering — to
     4.49:1, measured, which is under the floor. n-870 holds 4.61:1 and the
     lift is still a 1.075:1 area shift, which is what n-850 gave anyway. */
  --surface-raised: var(--p-n-870);
  --surface-inset: var(--p-n-900);

  /* The plate inverts to white. This is the black-and-white move: not a
     tinted panel, not paper — the other pole. */
  --surface-plate: var(--p-white);
  --surface-plate-bright: var(--p-white);
  --surface-plate-shade: var(--p-n-100);

  /* --- Text -------------------------------------------------------------
     Ratios measured against the surface each token is named for. */
  --text-primary: var(--p-white);            /* 19.8:1 on base */
  --text-secondary: var(--p-n-300);          /*  9.1:1 on base */
  --text-muted: var(--p-n-400);              /*  5.7:1 on base */
  --text-on-plate: var(--p-n-950);           /* 19.8:1 on plate */
  --text-on-plate-secondary: var(--p-n-600); /* 10.9:1 on plate */
  --text-on-plate-muted: var(--p-n-500);     /*  6.6:1 on plate */
  --text-inverse: var(--p-n-950);            /* on a white fill */

  /* --- Rule -------------------------------------------------------------
     In a monochrome system the hairline carries the structure colour would.
     Light rules on the ground, dark rules on the plate. */
  --rule-hair: rgba(255, 255, 255, 0.16);
  --rule-hair-strong: rgba(255, 255, 255, 0.34);
  --rule-on-plate: rgba(0, 0, 0, 0.16);
  --rule-on-plate-strong: rgba(0, 0, 0, 0.38);

  /* --- Accent -----------------------------------------------------------
     There is no chromatic accent. Emphasis is pure value: white against the
     ground, black against the plate. Components read --accent and get the
     right pole because .plate reassigns it. */
  --accent: var(--p-white);
  --accent-hover: var(--p-white);
  --accent-deep: var(--p-n-300);
  --accent-quiet: rgba(255, 255, 255, 0.1);

  --accent-fill: var(--p-white);
  --accent-fill-hover: var(--p-n-100);
  --accent-fill-press: var(--p-n-200);

  --marker: var(--p-white);
  --marker-quiet: rgba(255, 255, 255, 0.08);

  /* --- Brand secondaries, by role ---------------------------------------
     Each token names the surface it was measured against. Using one off its
     named surface is how a verified palette quietly stops being accessible:
     --accent-warm reads 4.96:1 on the ground and only 3.99:1 on a white
     plate, and --surface-slate is a surface precisely because it cannot be
     text (1.60:1 on the ground). */
  --surface-slate: var(--p-slate-700);   /* panel; white on it = 12.40:1 */
  --surface-sheet: var(--p-sand-100);    /* warm plate; near-black on it = 14.99:1 */

  /* Raised means LIFTED, and on every pole that means lighter, not darker:
     --surface-raised is n-850 against an n-950 ground for exactly that reason.
     A band that flips the ground must flip this too, or a hover written once
     against the dark pole paints near-black behind taupe text on the sheet —
     2.68:1, measured. The two below are the sheet and slate equivalents. */
  --surface-raised-sheet: var(--p-sand-050);
  --surface-raised-slate: var(--p-slate-600);

  --accent-warm: var(--p-olive-500);         /* on the ground only — 4.96:1 */
  --accent-warm-on-light: var(--p-taupe-700);/* on white — 6.68:1; on sheet — 5.06:1 */
  --text-warm: var(--p-sand-100);            /* on the ground — 14.99:1 */
  --rule-warm: var(--p-taupe-500);           /* rules and borders, never body text */

  /* --- Focus ------------------------------------------------------------
     Must survive on both poles, so it flips with the surface. Never removed. */
  --focus-ring: var(--p-white);
  --focus-ring-width: var(--p-line-medium);
  --focus-ring-offset: 3px;

  /* --- Feedback ---------------------------------------------------------
     Monochrome too. Validation is carried by weight, a heavy rule, and an
     explicit written message — never by hue, which also means it survives
     every form of colour blindness by construction. */
  --status-error: var(--p-white);
  --status-error-rule: var(--p-white);
  --status-success: var(--p-n-300);

  /* --- Impression -------------------------------------------------------
     A white plate on a black ground needs no border to separate; the shadow
     only seats it. */
  --impression-sm: 0 2px 10px rgba(0, 0, 0, 0.6);
  --impression-md: 0 10px 34px rgba(0, 0, 0, 0.65);
  --impression-lg: 0 24px 70px rgba(0, 0, 0, 0.75);

  /* --- Layout ------------------------------------------------------------ */
  --container-max: 78rem;
  /* The content edge of a .container, available to full-bleed sections that
     have to align with one. */
  --page-inset: max(var(--gutter), calc((100vw - var(--container-max)) / 2 + var(--gutter)));
  --container-text: 42rem;
  --gutter: var(--p-space-5);
}

@media (min-width: 48rem) {
  :root { --gutter: var(--p-space-7); }
}

@media (min-width: 75rem) {
  :root { --gutter: var(--p-space-8); }
}

/* ==========================================================================
   BASE
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background-color: var(--surface-base);
  color: var(--text-primary);
  font-family: var(--p-font-text);
  font-size: var(--p-size-md);
  line-height: var(--p-leading-relaxed);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: var(--p-weight-regular); }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
img, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}

::selection {
  background: var(--p-white);
  color: var(--p-black);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
