/*
  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 */
  /* The one measure for a section lede and an introductory paragraph on a marketing page (landing,
     agents, compare). 56rem (896px) is about 110 characters of body text at 16px: wider than a
     reading column on purpose, because a lede is one or two sentences and the owner wanted it to
     use the page rather than wrap at half the container. In rem, not ch, so it does not shrink
     with a smaller font; it never exceeds the container on a narrow screen. */
  --measure-lede: 56rem;
  --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);
}
