/**
 * @bitbaum/design-tokens — the design SSOT for OrangeCat, FleetCrown and Solon.
 *
 * ┌──────────────────────────────────────────────────────────────────────────┐
 * │  TO RETHEME THE ENTIRE STACK, EDIT THE "KNOBS" BLOCK BELOW AND NOTHING   │
 * │  ELSE. Then tag a release and bump the dependency in the three apps.     │
 * └──────────────────────────────────────────────────────────────────────────┘
 *
 * Why this package exists: the same tokens used to be hand-copied into three
 * repos. They drifted — Solon's globals.css carried a comment claiming it
 * matched OrangeCat while sharing zero values with it, and the three products
 * looked like three companies. Copies drift; imports cannot.
 *
 * Rules for consumers:
 *   - Components use ROLES (.font-display, bg-surface-base, text-fg-secondary).
 *     They never name a typeface, a weight, or a hex value.
 *   - A face's required weight and tracking are declared HERE, next to the face,
 *     so swapping a single-weight display serif for a variable grotesque is one
 *     edit and zero component changes.
 *   - Colours are HSL channel triplets so Tailwind composes alpha:
 *     `hsl(var(--surface-raised) / 0.5)` via `bg-surface-raised/50`.
 */

/* ══════════════════════════════════════════════════════════════════════════
   FACES — self-hosted, latin + latin-ext. No external requests at runtime.
   ══════════════════════════════════════════════════════════════════════════ */

/* Instrument Serif — display. SINGLE WEIGHT (400): there is no bold. Asking for
   700 makes the browser synthesize a fake bold, which looks cheap; that is why
   --font-display-weight exists and why components must not set a weight. */
@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/instrument-serif-latin.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/instrument-serif-latin-ext.woff2) format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/instrument-serif-italic-latin.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Inter — UI/body. Variable 400–700. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/inter-latin.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/inter-latin-ext.woff2) format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}

/* IBM Plex Mono — load-bearing strings: Bitcoin addresses, signatures, hashes,
   tallies. A hash must look identical on all three sites. */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/plex-mono-400-latin.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/plex-mono-500-latin.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ════════════════════════════════════════════════════════════════════════
     ▼▼▼  THE KNOBS  ▼▼▼   Everything below this line is derived from these.
     ════════════════════════════════════════════════════════════════════════ */

  /* — Typeface roles. Swap a face here and the whole stack changes. ——————— */
  --font-display: 'Instrument Serif', Georgia, serif;
  --font-sans: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* The weight and tracking the DISPLAY FACE needs. These belong to the face,
     not to the component — that is what makes a face swap a one-line change.
     Instrument Serif has one weight (400) and, being a high-contrast serif,
     wants far less negative tracking than a grotesque does. */
  --font-display-weight: 400;
  --tracking-display: -0.015em;

  /* — The one action colour across all three products. Theme-independent. — */
  --public-accent: #ff5c00;

  /**
   * The label colour for text sitting ON --public-accent.
   *
   * White on #ff5c00 is 3.10:1 — below the 4.5 AA floor — so every primary
   * CTA in the fleet was failing at once: Solon's "Open the Dashboard",
   * OrangeCat's "Get Started", FleetCrown's "Launch agent". Measured, not
   * guessed. Near-black on the same orange is 6.10:1.
   *
   * The orange is deliberately NOT darkened to rescue white text: it would
   * have to reach #c74600 to clear the floor, and that is a duller, muddier
   * colour. The accent IS the brand; the label is what gives way.
   *
   * Theme-independent for the same reason --public-accent is. The accent does
   * not flip between themes, so a label that flipped with the theme would be
   * unreadable in one of them — which is exactly why no existing text token
   * could be reused here (--text-primary inverts, this must not).
   */
  --on-accent: 0 0% 8%;

  /**
   * — The marketing band ——————————————————————————————————————————————————
   * Always near-black, in BOTH themes, so a CTA reads the same regardless of
   * the surrounding app theme. Deliberately not part of the ramp below.
   */
  --surface-public: 0 0% 4%;

  /* ── LIGHT THEME ────────────────────────────────────────────────────────
     :root is light and `.dark` overrides it — the same mechanism OrangeCat
     uses, so an app can toggle themes without translating anything. An app
     that is dark-only (Solon, FleetCrown's public surface) pins it by putting
     `class="dark"` on <html> and never removing it. */

  /* Surfaces — page < base < raised < overlay < modal < drawer */
  --surface-page: 0 0% 97%;
  --surface-base: 0 0% 100%;
  --surface-raised: 0 0% 96%;
  --surface-overlay: 0 0% 94%;
  --surface-modal: 0 0% 100%;
  --surface-drawer: 0 0% 98%;
  --surface-hover: 0 0% 94%;

  /* Text ramp */
  --text-primary: 0 0% 10%;
  --text-secondary: 0 0% 40%;
  --text-tertiary: 0 0% 58%;
  --text-muted: 0 0% 72%;
  --text-inverted: 0 0% 98%;

  /* Borders */
  --border-subtle: 0 0% 94%;
  --border-default: 0 0% 82%;
  --border-strong: 0 0% 78%;
  --border-interactive: 0 0% 30%;

  /* Accent */
  --accent-primary: var(--public-accent);
  --accent-hover: #e44d00;
  --accent-muted: 0 0% 10%;
  --accent-text: 0 0% 10%;

  /* Status — the only chromatic colours permitted outside the accent */
  --status-positive: 145 60% 35%;
  --status-positive-subtle: 145 60% 35% / 0.08;
  --status-warning: 38 92% 50%;
  --status-warning-subtle: 38 92% 50% / 0.08;
  --status-negative: 0 65% 50%;
  --status-negative-subtle: 0 65% 50% / 0.08;
  --status-neutral: 0 0% 58%;

  /* — Geometry —————————————————————————————————————————————————————————— */
  --radius-control: 0.375rem;
  --radius-surface: 0.5rem;
  --radius-pill: 9999px;
  --shell-max: 80rem;
  --public-nav-height: 76px;

  /* — Secondary tracking roles —————————————————————————————————————————— */
  --tracking-label: 0.1em;
  --tracking-caps: 0.16em;

  /**
   * — Vertical rhythm ————————————————————————————————————————————————————
   * Pace is one decision, not a `py-20 sm:py-28` guess repeated on every
   * section — that is how a page ends up with six slightly different rhythms.
   * Fluid, so spacing that reads as generous at 1440 does not strand a phone
   * with half a screen of emptiness.
   */
  --section-py: clamp(5rem, 9vw, 9rem);
  --section-py-tight: clamp(3.5rem, 6vw, 6rem);

  /**
   * — Display scale ——————————————————————————————————————————————————————
   * Fluid for the same reason: one confident size that resolves itself per
   * viewport, rather than three breakpoint variants per heading. Note that
   * display-3 bottoms out at 1.5rem — exactly the display face's size floor,
   * so every step of this scale is safe to set in the display face.
   */
  --text-display-1: clamp(2.75rem, 5.4vw, 4.5rem);
  --text-display-2: clamp(2rem, 3.4vw, 3rem);
  --text-display-3: clamp(1.5rem, 2vw, 1.875rem);

  /**
   * — Measures for running text ——————————————————————————————————————————
   * Headlines take their width from the column they sit in; a hero h1 with its
   * own max-width as well ends up with two rules where only one ever binds.
   */
  --measure-lede: 46ch;
  --measure-copy: 68ch;

  /* ════════════════════════════════════════════════════════════════════════
     ▲▲▲  END KNOBS  ▲▲▲
     ════════════════════════════════════════════════════════════════════════ */

  /* Bitcoin's own orange. Not a brand colour — it means "this is Bitcoin", so
     it is deliberately NOT --public-accent and must not be used for actions. */
  --bitcoin-orange: #f7931a;
}

/* ══════════════════════════════════════════════════════════════════════════
   DARK THEME
   Only the values that actually differ. Faces, weights, tracking, geometry,
   rhythm, measures, --public-accent and --surface-public are theme-independent
   and are NOT repeated here — repeating them is how a theme drifts from its
   own light counterpart.
   ══════════════════════════════════════════════════════════════════════════ */

.dark {
  /* Surfaces */
  --surface-page: 0 0% 7%;
  --surface-base: 0 0% 11%;
  --surface-raised: 0 0% 14%;
  --surface-overlay: 0 0% 17%;
  --surface-modal: 0 0% 11%;
  --surface-drawer: 0 0% 9%;
  --surface-hover: 0 0% 13%;

  /* Text ramp */
  --text-primary: 0 0% 92%;
  --text-secondary: 0 0% 65%;
  --text-tertiary: 0 0% 48%;
  --text-muted: 0 0% 32%;
  --text-inverted: 0 0% 10%;

  /* Borders */
  --border-subtle: 0 0% 13%;
  --border-default: 0 0% 20%;
  --border-strong: 0 0% 24%;
  --border-interactive: 0 0% 60%;

  /* Accent */
  --accent-primary: var(--public-accent);
  --accent-hover: #ff7a33;
  --accent-muted: 0 0% 92% / 0.08;
  --accent-text: 0 0% 92%;

  /* Status */
  --status-positive: 145 55% 50%;
  --status-positive-subtle: 145 55% 50% / 0.12;
  --status-warning: 38 92% 60%;
  --status-warning-subtle: 38 92% 60% / 0.12;
  --status-negative: 0 75% 60%;
  --status-negative-subtle: 0 75% 60% / 0.12;
  --status-neutral: 0 0% 48%;
}

/* ══════════════════════════════════════════════════════════════════════════
   SHARED PRIMITIVES — the chrome all three products present.
   ══════════════════════════════════════════════════════════════════════════ */

body {
  color: hsl(var(--text-primary));
  background: hsl(var(--surface-page));
  font-family: var(--font-sans);
}

/**
 * The display treatment. Owns family + weight + tracking together so that a
 * component only ever declares INTENT ("this is display type"), never the
 * mechanics. Do not add font-bold/tracking-* alongside this class: the current
 * face has no bold, and a synthesized one looks cheap.
 */
.font-display {
  font-family: var(--font-display);
  font-weight: var(--font-display-weight);
  letter-spacing: var(--tracking-display);
  /* Balance the line lengths so a headline never strands its last word alone on
     a second line. Browsers cap this at a few lines, which is exactly the range
     a display heading occupies; longer running text is unaffected. */
  text-wrap: balance;
}

/**
 * SIZE FLOOR — the display face is for DISPLAY sizes only: 1.5rem (24px) and up.
 *
 * Instrument Serif is high-contrast: its thin strokes thin out further as the
 * type shrinks, so an 18px serif heading reads LIGHTER than the 16px sans
 * paragraph beneath it and the hierarchy silently inverts. Below the floor,
 * headings use the sans at 600. Each repo's design gate enforces this by
 * rejecting `font-display` next to text-xs/sm/base/lg/xl.
 */

/**
 * The wordmark. A high-contrast serif goes weak at small sizes in mixed case,
 * but holds up in uppercase with open tracking — which is exactly what a
 * wordmark is. This is the ONLY sanctioned use of the display face below the
 * size floor described above.
 */
.wordmark {
  font-family: var(--font-display);
  font-weight: var(--font-display-weight);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/**
 * Numbers that sit in columns or change in place — tallies, balances, counts.
 * Tabular figures stop the layout jittering as values update.
 */
.tabular {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/**
 * Section rhythm. Marketing sections are full-bleed and own their inner
 * container — a root layout must NOT wrap pages in one, or every hero renders
 * as a box floating in a gutter instead of reaching the edges of the screen.
 */
.section-shell {
  margin-inline: auto;
  width: 100%;
  max-width: var(--shell-max);
  padding-inline: 1rem;
}

@media (min-width: 640px) {
  .section-shell {
    padding-inline: 1.5rem;
  }
}

@media (min-width: 1024px) {
  .section-shell {
    padding-inline: 2rem;
  }
}

/** One accent glow and a masked grid over the near-black public surface. */
.public-backdrop {
  position: relative;
  isolation: isolate;
  background: hsl(var(--surface-public));
  --public-glow-accent: rgb(255 92 0 / 0.1);
  --public-grid-stroke: rgb(255 255 255 / 0.04);
  --public-grid-size: 80px;
}

.public-backdrop::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(60rem 30rem at 50% -10%, var(--public-glow-accent), transparent 70%);
}

.public-backdrop::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(to right, var(--public-grid-stroke) 1px, transparent 1px),
    linear-gradient(to bottom, var(--public-grid-stroke) 1px, transparent 1px);
  background-size: var(--public-grid-size) var(--public-grid-size);
  mask-image: radial-gradient(closest-side at 50% 35%, black, transparent);
}

/** The eyebrow pill that opens a marketing page on all three products. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: var(--radius-pill);
  border: 1px solid hsl(var(--border-default));
  background: hsl(var(--surface-base));
  padding: 0.375rem 0.875rem;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: hsl(var(--text-secondary));
}

.eyebrow::before {
  content: '';
  width: 0.375rem;
  height: 0.375rem;
  border-radius: var(--radius-pill);
  background: var(--public-accent);
}
