/* ==========================================================================
   Patch design tokens

   Every value here was measured off the 1440-wide mockup exports rather than
   invented; spec-public-site-visual.md records how, and holds the element-box
   tables these tokens are meant to reproduce.

   Naming is by role, not by value. `--ink-lede` is the subtitle's colour
   wherever a subtitle appears; it is not "the grey one".

   Two deliberate departures from the mockup, both recorded in the spec:
     · `--ink-status` is darkened from the mockup's #7C83A1, which measured
       3.74:1 on white. See the token itself for where it landed, and for why
       one surface is not enough to tune a colour against.
     · The supporting typeface is Hubot Sans. The mockup set those roles in a
       third, unbriefed face, so support-layer sizes here are cap-height
       matched to the mockup rather than copied from it — the same optical
       size, different line widths.
   ========================================================================== */

:root {
  /* ---- Brand ---------------------------------------------------------- */
  /* Both blues are lifted straight from the logo: the back plate and the
     front plate. Nothing in the palette is a tint of a tint. */
  --brand-900: #222d7c; /* logo back plate; headline accent word */
  --brand-600: #3245a9; /* logo front plate; primary button; progress fill */
  --brand-050: #e8ebfb; /* email-bar underline */
  --brand-track: #e8ecf1; /* progress track */
  --brand-hand: #ffd87e; /* logo hand — held for illustration, not UI */

  /* ---- Ink ------------------------------------------------------------ */
  --ink-display: #1b1c21; /* headlines */
  --ink-strong: #0e0d40; /* inbox address, card titles */
  --ink-title: #1a1f36; /* filenames, job-card headings */
  --ink-body: #3d3d62; /* card body copy */
  --ink-lede: #5c606f; /* hero subtitle */
  --ink-eyebrow: #56586b; /* "Introducing" */
  --ink-nav: #626060; /* header links, chip labels */
  --ink-numeral: #1c1c1c; /* step numbers */
  /* 4.97:1 on the canvas and 5.23:1 on white. The previous #6B7291 was tuned
     against white alone and measured 4.49:1 on #F9F9FA — a token that only
     passes on one of the two surfaces it is used on is not passing. */
  --ink-status: #646b8a;
  --ink-meta: #73648e; /* duration, download glyph */
  --ink-on-brand: #ffffff;

  /* The only non-brand hue in the system. A run that stopped must not be able
     to render in the same colour as one that succeeded. */
  --danger: #8c2f39;
  --danger-surface: #fbeced;

  /* ---- Surfaces ------------------------------------------------------- */
  --surface-page: #ffffff; /* the sheet behind the canvas */
  --surface-canvas: #f9f9fa; /* the inset rounded panel */
  --surface-raised: #ffffff; /* cards, the address bar */
  --surface-chip: #ededed; /* Agent + Sign In pills */
  --surface-tile: #f7f8fb; /* file-icon tile */

  --line-strong: #d5d4e0; /* secondary button border */
  --line-soft: #f0f0f0; /* icon button border */

  /* ---- Type ----------------------------------------------------------- */
  --font-display: "Archivo", "Archivo Fallback", system-ui, sans-serif;
  --font-support: "Hubot Sans", "Hubot Sans Fallback", system-ui, sans-serif;

  /* Archivo has no true bold master boundary that matters here — the mockup's
     headline sits at 650 on the weight axis, between SemiBold and Bold, and a
     pixel diff against the export confirmed it (IoU 0.961). Do not round it
     to 600 or 700. */
  --weight-display: 650;
  --weight-emphasis: 700;
  --weight-support: 400;
  --weight-support-medium: 500;
  --weight-numeral: 300;

  /* Sizes. Display roles are exact; support roles are cap-height matched. */
  --size-display-1: 56px; /* hero headline — cap 38.67 */
  --size-display-2: 50px; /* job headline — cap 34.67 */
  --size-eyebrow: 24px; /* "Introducing Patch" — cap 16.67 */
  --size-address: 24px; /* patch@getcaboo.com — cap 16.67 */
  --size-numeral: 24px; /* 01 / 02 / 03 — figure 16.67, set in Archivo */
  --size-card-title: 17.5px; /* cap 12.0 */
  --size-filename: 17px; /* cap 12.67 */
  --size-lede: 18px; /* cap 13.33 */
  --size-button: 16px; /* cap 10.67 */
  --size-status: 16px; /* cap 12.0 */
  --size-meta: 15px; /* figure 10.67 */
  --size-body: 14px; /* cap 10.0 */
  --size-nav: 13px; /* cap 9.33 */

  /* The headline tracking is the one value that must not drift. */
  --track-display: -0.04em;
  --track-eyebrow: -0.02em;
  --track-normal: 0;

  --leading-display: 1;
  --leading-tight: 1.2;
  --leading-body: 1.43; /* 20px pitch at 14px — measured off the step cards */

  /* ---- Geometry ------------------------------------------------------- */
  --radius-canvas: 24px;
  --radius-card: 16px;
  --radius-bar: 16px;
  --radius-button: 10px;
  --radius-tile: 12px;
  --radius-pill: 999px;

  --inset-page: 12px; /* white margin around the canvas */
  --gap-cards: 61.3px; /* measured; not a rounded 60 */
  --pad-card: 28px;
  --pad-bar: 16px;

  /* ---- Elevation ------------------------------------------------------ */
  /* The step cards cast almost nothing: no shadow above them at all, a peak
     delta of 3/255 below. Anything heavier is wrong. */
  --shadow-card: 0 4px 20px rgba(16, 16, 40, 0.035);

  /* Depth is the visible "side" of a raised object — a heavier bottom edge
     read as the thickness of a physical key rather than as a shadow.

     The rule it implies: things you press have depth, things you read do not.
     Controls and the address bar get an edge; cards and panels keep the flat
     near-invisible shadow above. Mixing the two makes everything look
     pressable and nothing look meant. */
  --depth-bar: 5px; /* the address bar's own thickness */
  --depth-control: 4px; /* buttons — also how far they travel when pressed */
  --depth-control-sm: 3px; /* secondary and icon buttons */

  /* ---- Motion ---------------------------------------------------------
     Four tiers, assigned by what the movement is *for*. Motion that carries
     no information does not get a tier; it gets deleted.

       chrome  a control acknowledging the pointer
       info    something changed and you should notice
       move    something travelled from one place to another
       beat    the one moment on the screen worth a beat of its own

     Curves: entrances decelerate, moves ease evenly, and anything that lands
     on a target settles slightly past it — a stage advancing should feel like
     it arrived rather than drifted. */
  --motion-chrome: 120ms;
  --motion-info: 200ms;
  --motion-move: 320ms;
  --motion-beat: 480ms;

  --ease-out: cubic-bezier(0.2, 0, 0, 1);
  --ease-move: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-settle: cubic-bezier(0.34, 1.28, 0.64, 1);
}

/* Reduced motion is handled by scoping transform- and size-based movement into
   `no-preference` blocks rather than by zeroing these durations. Zeroing makes
   every state change instantaneous, and an instant swap is often *more*
   disorienting than a short fade — colour and opacity transitions are not what
   vestibular sensitivity is about. What goes away is travel, not feedback. */
