/*
  PHARMA OBSERVATORY DESIGN TOKENS

  The single source of every colour, type size, space, radius, shadow and motion value in explore.
  Component CSS reads ONLY the semantic tokens below (the `--color-*`, `--text-*`, `--space-*`,
  `--radius-*`, `--shadow-*` names). The primitive ramps exist so the semantic layer has something
  to point at; nothing outside this file should name a primitive.

  Family: a sibling of the Scientist.com product, measured from its live stylesheet on 2026-10-02:
  primary navy #1F346F, teal #138EA0 (its focus ring), dark surfaces #080F26 / #0D1A3F / #22315A,
  Source Sans 3 body. Where we depart on purpose:
    - the single ACTION colour is bright blue #3065F4 (the redesign brief). The reference uses
      #3065F4 for "info" and fills its buttons navy; swapping --color-action to --navy-700 restores
      the reference's choice in one line.
    - headings use Lexend (OFL) in place of the reference's commercial Parabolica.
    - buttons are 8px-rounded rectangles, not pills; pills are kept for chips and filters.

  Theming: light is the default. Dark applies when the OS asks for it and the viewer has not
  chosen light, or when the viewer chose dark (html[data-theme="dark"]). The theme controller
  writes data-theme; the pre-paint script in the layouts applies a stored choice before first paint.

  Contrast: every text and UI pairing the system relies on is listed in lib/design_tokens.rb and
  measured from this file by bin/check_contrast (and by spec/assets/design_tokens_spec.rb, so a
  token edit that breaks WCAG 2.1 AA fails the suite). Ratios are deliberately not copied into
  comments here, where they would go stale.
*/

@font-face {
  font-family: "Source Sans 3";
  src: url("/assets/source-sans-3-latin-9da25ef2.woff2") format("woff2");
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Source Sans 3";
  src: url("/assets/source-sans-3-italic-latin-27715ecd.woff2") format("woff2");
  font-weight: 200 900;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "Lexend";
  src: url("/assets/lexend-latin-80258e9a.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ---------- Primitive ramps (do not use outside this file) ---------- */
  --navy-50: #eef1f8;
  --navy-100: #dde3f1;
  --navy-200: #c6d0e6;
  --navy-300: #8ba3d4;
  --navy-500: #3a4f8c;
  --navy-700: #1f346f;
  --navy-800: #15244c;
  --navy-900: #0d1a3f;
  --navy-950: #080f26;

  --teal-50: #e7f4f5;
  --teal-100: #c5e5e9;
  --teal-300: #5caeb9;
  --teal-400: #2e9dab;
  --teal-500: #138ea0;
  --teal-700: #0d5c69;

  --blue-50: #eef3ff;
  --blue-100: #dbe5fe;
  --blue-300: #8aaeff;
  --blue-400: #5b87f8;
  --blue-500: #3065f4;
  --blue-600: #264fea;
  --blue-700: #1d3fc4;

  --gray-0: #ffffff;
  --gray-25: #fafbfc;
  --gray-50: #f5f6f9;
  --gray-100: #eceef3;
  --gray-200: #dde1e8;
  --gray-300: #c6ccd8;
  --gray-500: #626c86;
  --gray-600: #545e78;
  --gray-700: #35405d;
  --gray-900: #1a2238;

  --dk-bg: #080f26;
  --dk-surface: #0d1a3f;
  --dk-surface-2: #11203f;
  --dk-sunken: #0a1430;
  --dk-border: #22315a;
  --dk-border-strong: #2f4070;
  --dk-text: #dde5f2;
  --dk-text-muted: #a3b1cc;
  --dk-text-subtle: #8796b6;

  /* ---------- Typography ---------- */
  --font-sans: "Source Sans 3", "Source Sans Pro", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: "Lexend", var(--font-sans);
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;

  /* A compact scale for a data tool: 14px is the working size for tables and controls, 16px for
     reading prose. Headings step up on a ~1.25 ratio and tighten their tracking as they grow. */
  --text-2xs: 0.6875rem; /* 11px: overline labels only, always uppercase + tracked */
  --text-xs: 0.75rem;    /* 12px: meta, captions, badges */
  --text-sm: 0.8125rem;  /* 13px: secondary table text, helper text */
  --text-md: 0.875rem;   /* 14px: tables, controls, nav */
  --text-base: 1rem;     /* 16px: body prose */
  --text-lg: 1.125rem;   /* 18px: section titles */
  --text-xl: 1.375rem;   /* 22px: card/page sub-titles */
  --text-2xl: 1.75rem;   /* 28px: page titles */
  --text-3xl: 2.25rem;   /* 36px: home greeting, hero figures */
  --text-4xl: 3rem;      /* 48px: landing hero */

  --leading-tight: 1.2;
  --leading-snug: 1.35;
  --leading-normal: 1.5;

  --tracking-tight: -0.02em;
  --tracking-wide: 0.06em;

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

  /* ---------- Space (4px base) ---------- */
  --space-0: 0;
  --space-px: 1px;
  --space-0-5: 0.125rem; /* 2 */
  --space-1: 0.25rem;    /* 4 */
  --space-1-5: 0.375rem; /* 6 */
  --space-2: 0.5rem;     /* 8 */
  --space-2-5: 0.625rem; /* 10 */
  --space-3: 0.75rem;    /* 12 */
  --space-4: 1rem;       /* 16 */
  --space-5: 1.25rem;    /* 20 */
  --space-6: 1.5rem;     /* 24 */
  --space-8: 2rem;       /* 32 */
  --space-10: 2.5rem;    /* 40 */
  --space-12: 3rem;      /* 48 */
  --space-16: 4rem;      /* 64 */
  --space-20: 5rem;      /* 80 */

  /* ---------- Layout ---------- */
  --container-max: 90rem;     /* 1440 */
  --container-prose: 45rem;   /* 720 */
  --gutter: var(--space-8);
  --topbar-height: 3.5rem;    /* 56 */
  --section-nav-height: 3.25rem; /* the sticky entity-page section nav (components/_section_nav) */
  --control-height-sm: 1.75rem;
  --control-height: 2.25rem;
  --control-height-lg: 2.75rem;

  /* ---------- Radius: rounded, not bubbly ---------- */
  --radius-xs: 3px;
  --radius-sm: 5px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 14px;
  --radius-pill: 999px;

  /* ---------- Blur: the Row preview tail's placeholder rows (empty bars, never real data) ---------- */
  --blur-preview: 4px;

  /* ---------- Motion ---------- */
  --duration-fast: 120ms;
  --duration-base: 180ms;
  --duration-slow: 260ms;
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  /* Delight layer (delight.css). An arrival is slower than a state change and decelerates hard.
     Two bands: SMALL motion (a menu, a flash, a copy confirmation: --duration-enter, --motion-rise)
     and AUTHORED motion (the public hero, scroll reveals, chart columns), which the owner asked
     (2026-10-11) to be unmistakable rather than subtle, so it travels further and takes longer. The
     authored band is --duration-arrive / -reveal / -focal / -grow, --motion-arrive-* and
     --motion-reveal-*. Only transform and opacity move. */
  --duration-enter: 420ms;
  --duration-arrive: 680ms;
  --duration-reveal: 640ms;
  --duration-focal: 720ms;
  --duration-grow: 800ms;
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --motion-rise: 0.625rem;
  --motion-arrive-rise: 1.75rem;
  --motion-arrive-scale: 0.98;
  --motion-arrive-stagger: 100ms;
  --motion-reveal-rise: 1.5rem;
  --motion-reveal-stagger: 70ms;
  /* The whole left-to-right spread of a chart's columns: the last column starts this long after the first. */
  --motion-grow-span: 600ms;
  --motion-lift: -4px;
  --motion-lift-button: -2px;
  --motion-nudge: 4px;
  --motion-icon-scale: 1.12;
  --motion-icon-lift: -2px;
  --motion-underline-offset: 0.32em;
  --motion-press: 0.98;

  /* ---------- Z layers ---------- */
  --z-sticky: 10;
  --z-topbar: 40;
  --z-popover: 50;
  --z-dialog: 60;
  --z-toast: 70;

  /* =========================================================================================
     SEMANTIC TOKENS, LIGHT
     ========================================================================================= */
  color-scheme: light;

  /* Surfaces. The page canvas is a cool off-white so white cards read without a heavy shadow. */
  --color-bg: var(--gray-50);
  --color-surface: var(--gray-0);
  --color-surface-raised: var(--gray-0);
  --color-surface-sunken: var(--gray-100);
  --color-surface-hover: var(--gray-25);
  --color-surface-selected: var(--blue-50);
  --color-surface-brand: var(--navy-700);   /* the navy band (landing, mark tile) */
  --color-surface-accent: var(--teal-50);   /* the active nav item, informative callouts */
  --color-overlay: rgb(8 15 38 / 0.48);

  /* The header brand mark INVERTS with the theme (owner decision 2026-10-10): white telescope on a navy
     tile in light, navy telescope on a white tile in dark (both dark blocks below). The favicon, PWA
     icons and Open Graph card stay fixed navy (bin/generate_app_icon reads the LIGHT value): they render
     where the site theme cannot be followed. */
  --color-brand-tile: var(--navy-700);
  --color-brand-core: var(--gray-0);

  /* The Contract Research Map wordmark (CrmLogoHelper). Navy lettering flips to white in dark; the
     teal and green are the brand values and hold in both themes. */
  --color-crm-ink: var(--navy-700);
  --color-crm-teal: #77cbbc;
  --color-crm-green: #9acb3d;

  /* Borders. Subtle by default; strong for inputs and dividers that must hold at 3:1. */
  --color-border: var(--gray-200);
  --color-border-strong: var(--gray-300);
  --color-border-input: #8a93a8;

  /* Text */
  --color-text: var(--gray-700);
  --color-text-strong: var(--navy-700);
  --color-text-muted: var(--gray-600);
  --color-text-subtle: var(--gray-500);
  --color-text-inverse: var(--gray-0);
  --color-text-on-brand: var(--gray-0);
  --color-text-accent: var(--teal-700);

  /* Action: the ONE colour that means "you can do something here". */
  --color-action: var(--blue-500);
  --color-action-hover: var(--blue-600);
  --color-action-active: var(--blue-700);
  --color-action-text: var(--gray-0);
  --color-action-subtle: var(--blue-50);    /* secondary-button hover wash */
  --color-link: #2552d6;
  --color-link-hover: var(--blue-700);
  --color-focus: var(--teal-500);
  --focus-ring: 0 0 0 2px var(--color-surface), 0 0 0 4px var(--color-focus);

  /* Status. Text tokens are AA on their own -bg token AND on surface. */
  --color-success-text: #17663f;
  --color-success-bg: #e6f4ec;
  --color-success-border: #9fd3b6;
  --color-success-solid: #1f8a54;
  --color-warning-text: #8a4b06;
  --color-warning-bg: #fdf2df;
  --color-warning-border: #f0c98a;
  --color-warning-solid: #c47a10;
  --color-danger-text: #a3170f;
  --color-danger-bg: #fdecea;
  --color-danger-border: #f2b0aa;
  --color-danger-solid: #c11b14;
  --color-info-text: #1d3fc4;
  --color-info-bg: var(--blue-50);
  --color-info-border: var(--blue-100);
  --color-neutral-text: var(--gray-700);
  --color-neutral-bg: var(--gray-100);
  --color-neutral-border: var(--gray-200);

  /* Licence tiers (house rule: red = prohibited, amber = licensable). Never reused for anything
     else, so a red or amber chip on this platform always means a licence obligation. */
  --color-tier-prohibited-text: var(--color-danger-text);
  --color-tier-prohibited-bg: var(--color-danger-bg);
  --color-tier-prohibited-border: var(--color-danger-border);
  --color-tier-licensable-text: var(--color-warning-text);
  --color-tier-licensable-bg: var(--color-warning-bg);
  --color-tier-licensable-border: var(--color-warning-border);
  --color-tier-internal-text: var(--navy-700);
  --color-tier-internal-bg: var(--navy-50);
  --color-tier-internal-border: var(--navy-200);

  /* Search-term highlight */
  --color-mark-bg: #fff1b8;
  --color-mark-text: var(--gray-900);

  /* Chart palette: one categorical order used by every chart, map and legend. DRASTICALLY
     DIFFERENT HUES ON PURPOSE (owner direction, 2026-10-02): an all-blue brand palette looked
     calm but made stacked series hard to tell apart, so series take blue, orange, teal, gold,
     magenta, green, violet, red, in that fixed order, never cycled. A 9th series folds into
     --chart-other.
     The ORDER is the colour-blind safety mechanism. Validated 2026-10-02 with the dataviz skill's
     validate_palette.js (adjacent pairs, light on #ffffff, dark on --dk-surface): every hard gate
     passes in both modes; light worst adjacent CVD dE 9.9, dark 10.6; slot 4 (gold) is under 3:1
     on white, so a chart that uses it carries a legend plus direct labels or a table view.
     Scatter, map and other all-pairs forms cap at the first THREE slots (validated all-pairs).
     Series red and orange are NOT licence-tier signals: a tier is always a chip with a lock icon
     and the words "Restricted" or "Licensable", never a bare colour. */
  --chart-1: #2a64e0;
  --chart-2: #eb6834;
  --chart-3: #0097a7;
  --chart-4: #d99a00;
  --chart-5: #d6569a;
  --chart-6: #2f9e44;
  --chart-7: #6a4fc9;
  --chart-8: #d93f3f;
  --chart-other: #a7afc0;
  /* The "no data / unknown" band: lighter than --chart-other so both can share a stack. */
  --chart-unknown: #d5dae4;
  --chart-grid: var(--gray-200);
  --chart-axis: var(--gray-500);
  --chart-label: var(--gray-600);
  /* Sequential ramp (pale to saturated) for heatmaps and choropleths. */
  --chart-seq-1: #e7f4f5;
  --chart-seq-2: #b6dfe4;
  --chart-seq-3: #6fbfca;
  --chart-seq-4: #2e9dab;
  --chart-seq-5: #137585;
  --chart-seq-6: #0d4d5a;

  /* Elevation. Borders carry structure; shadows only lift things that float. */
  --shadow-xs: 0 1px 2px rgb(16 27 60 / 0.05);
  --shadow-sm: 0 1px 3px rgb(16 27 60 / 0.07), 0 1px 2px rgb(16 27 60 / 0.04);
  --shadow-md: 0 6px 16px -4px rgb(16 27 60 / 0.12), 0 2px 4px rgb(16 27 60 / 0.05);
  --shadow-lg: 0 18px 40px -8px rgb(16 27 60 / 0.22), 0 4px 10px rgb(16 27 60 / 0.06);
}

/* =========================================================================================
   SEMANTIC TOKENS, DARK
   The block is written twice: once for "the OS prefers dark and the viewer has not chosen light",
   once for "the viewer chose dark". Keep the two identical; spec/assets/design_tokens_spec.rb
   fails if they drift.
   ========================================================================================= */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --color-bg: var(--dk-bg);
    --color-surface: var(--dk-surface);
    --color-surface-raised: var(--dk-surface-2);
    --color-surface-sunken: var(--dk-sunken);
    --color-surface-hover: #12224a;
    --color-surface-selected: #16295c;
    --color-surface-brand: var(--navy-800);
    --color-brand-tile: var(--gray-0);
    --color-brand-core: var(--navy-700);
  --color-crm-ink: var(--gray-0);
    --color-surface-accent: #0a3a44;
    --color-overlay: rgb(2 6 18 / 0.66);
    --color-border: var(--dk-border);
    --color-border-strong: var(--dk-border-strong);
    --color-border-input: #5a6b94;
    --color-text: var(--dk-text);
    --color-text-strong: #f2f5fb;
    --color-text-muted: var(--dk-text-muted);
    --color-text-subtle: var(--dk-text-subtle);
    --color-text-inverse: var(--navy-950);
    --color-text-on-brand: var(--gray-0);
    --color-text-accent: #9ad6de;
    --color-action: var(--blue-500);
    --color-action-hover: var(--blue-600);
    --color-action-active: var(--blue-700);
    --color-action-text: var(--gray-0);
    --color-action-subtle: #15265a;
    --color-link: var(--blue-300);
    --color-link-hover: #b3caff;
    --color-focus: var(--teal-400);
    --color-success-text: #86d9a9;
    --color-success-bg: #0d2f22;
    --color-success-border: #1e5a3e;
    --color-success-solid: #3cb371;
    --color-warning-text: #f3c57a;
    --color-warning-bg: #33230a;
    --color-warning-border: #6b4a14;
    --color-warning-solid: #e3a43a;
    --color-danger-text: #ff9c95;
    --color-danger-bg: #3a1214;
    --color-danger-border: #7a2a26;
    --color-danger-solid: #ff706a;
    --color-info-text: var(--blue-300);
    --color-info-bg: #142450;
    --color-info-border: #26408a;
    --color-neutral-text: var(--dk-text);
    --color-neutral-bg: #17264f;
    --color-neutral-border: var(--dk-border-strong);
    --color-tier-internal-text: #c6d0e6;
    --color-tier-internal-bg: #17264f;
    --color-tier-internal-border: var(--dk-border-strong);
    --color-mark-bg: #5a4a10;
    --color-mark-text: #fff6d6;
    --chart-1: #4a7df0;
    --chart-2: #dd6430;
    --chart-3: #0f9caa;
    --chart-4: #bf8a00;
    --chart-5: #cf5f9d;
    --chart-6: #259446;
    --chart-7: #8a78e6;
    --chart-8: #e05252;
    --chart-other: #5f6b8a;
    --chart-unknown: #3f4a72;
    --chart-grid: var(--dk-border);
    --chart-axis: var(--dk-text-subtle);
    --chart-label: var(--dk-text-muted);
    --chart-seq-1: #0f2a3a;
    --chart-seq-2: #0f4452;
    --chart-seq-3: #12606f;
    --chart-seq-4: #1f8796;
    --chart-seq-5: #4fb3c0;
    --chart-seq-6: #9ad6de;
    --shadow-xs: 0 1px 2px rgb(0 0 0 / 0.3);
    --shadow-sm: 0 1px 3px rgb(0 0 0 / 0.36);
    --shadow-md: 0 8px 20px -6px rgb(0 0 0 / 0.5);
    --shadow-lg: 0 20px 44px -10px rgb(0 0 0 / 0.6);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --color-bg: var(--dk-bg);
  --color-surface: var(--dk-surface);
  --color-surface-raised: var(--dk-surface-2);
  --color-surface-sunken: var(--dk-sunken);
  --color-surface-hover: #12224a;
  --color-surface-selected: #16295c;
  --color-surface-brand: var(--navy-800);
  --color-brand-tile: var(--gray-0);
  --color-brand-core: var(--navy-700);
  --color-crm-ink: var(--gray-0);
  --color-surface-accent: #0a3a44;
  --color-overlay: rgb(2 6 18 / 0.66);
  --color-border: var(--dk-border);
  --color-border-strong: var(--dk-border-strong);
  --color-border-input: #5a6b94;
  --color-text: var(--dk-text);
  --color-text-strong: #f2f5fb;
  --color-text-muted: var(--dk-text-muted);
  --color-text-subtle: var(--dk-text-subtle);
  --color-text-inverse: var(--navy-950);
  --color-text-on-brand: var(--gray-0);
  --color-text-accent: #9ad6de;
  --color-action: var(--blue-500);
  --color-action-hover: var(--blue-600);
  --color-action-active: var(--blue-700);
  --color-action-text: var(--gray-0);
  --color-action-subtle: #15265a;
  --color-link: var(--blue-300);
  --color-link-hover: #b3caff;
  --color-focus: var(--teal-400);
  --color-success-text: #86d9a9;
  --color-success-bg: #0d2f22;
  --color-success-border: #1e5a3e;
  --color-success-solid: #3cb371;
  --color-warning-text: #f3c57a;
  --color-warning-bg: #33230a;
  --color-warning-border: #6b4a14;
  --color-warning-solid: #e3a43a;
  --color-danger-text: #ff9c95;
  --color-danger-bg: #3a1214;
  --color-danger-border: #7a2a26;
  --color-danger-solid: #ff706a;
  --color-info-text: var(--blue-300);
  --color-info-bg: #142450;
  --color-info-border: #26408a;
  --color-neutral-text: var(--dk-text);
  --color-neutral-bg: #17264f;
  --color-neutral-border: var(--dk-border-strong);
  --color-tier-internal-text: #c6d0e6;
  --color-tier-internal-bg: #17264f;
  --color-tier-internal-border: var(--dk-border-strong);
  --color-mark-bg: #5a4a10;
  --color-mark-text: #fff6d6;
  --chart-1: #4a7df0;
  --chart-2: #dd6430;
  --chart-3: #0f9caa;
  --chart-4: #bf8a00;
  --chart-5: #cf5f9d;
  --chart-6: #259446;
  --chart-7: #8a78e6;
  --chart-8: #e05252;
  --chart-other: #5f6b8a;
  --chart-unknown: #3f4a72;
  --chart-grid: var(--dk-border);
  --chart-axis: var(--dk-text-subtle);
  --chart-label: var(--dk-text-muted);
  --chart-seq-1: #0f2a3a;
  --chart-seq-2: #0f4452;
  --chart-seq-3: #12606f;
  --chart-seq-4: #1f8796;
  --chart-seq-5: #4fb3c0;
  --chart-seq-6: #9ad6de;
  --shadow-xs: 0 1px 2px rgb(0 0 0 / 0.3);
  --shadow-sm: 0 1px 3px rgb(0 0 0 / 0.36);
  --shadow-md: 0 8px 20px -6px rgb(0 0 0 / 0.5);
  --shadow-lg: 0 20px 44px -10px rgb(0 0 0 / 0.6);
}
