/*
 * GrAndMA / Forge — component CSS.
 * Semantic classes that replace the most duplicated Tailwind utility soups.
 * Values mirror Tailwind tokens so they compose with existing utilities.
 * Prefix: .gm-*  (grandma)
 */

/* ──────────────────────────────────────────────────────────────
 * Global tweaks to lift the app out of all-flat-white.
 * Kept minimal and token-driven so dark mode can invert cleanly.
 * ────────────────────────────────────────────────────────────── */
body {
  background:
    radial-gradient(ellipse 1200px 600px at 80% -200px, rgba(124,58,237,0.07) 0%, transparent 60%),
    radial-gradient(ellipse 900px 500px at -10% 300px, rgba(2,132,199,0.08) 0%, transparent 55%),
    linear-gradient(180deg, #f9fafb 0%, #eef2f6 100%) !important;
  background-attachment: fixed;
}
html.dark body {
  background:
    radial-gradient(ellipse 1200px 600px at 80% -200px, rgba(124,58,237,0.14) 0%, transparent 60%),
    radial-gradient(ellipse 900px 500px at -10% 300px, rgba(2,132,199,0.12) 0%, transparent 55%),
    linear-gradient(180deg, #0b1220 0%, #0f172a 100%) !important;
}

/* Selection highlight that matches the brand. */
::selection { background: rgba(2,132,199,0.25); color: inherit; }

/* Focus ring polish — the 3-px brand ring with a white offset. */
.gm-input:focus,
.gm-select:focus,
.gm-textarea:focus {
  border-color: var(--gm-brand) !important;
  box-shadow: 0 0 0 2px var(--gm-surface), 0 0 0 4px var(--gm-brand-ring) !important;
}

/* ──────────────────────────────────────────────────────────────
 * Tokens (CSS variables — single source of truth)
 * ────────────────────────────────────────────────────────────── */
:root {
  --gm-surface:        #ffffff;
  --gm-surface-muted:  #f9fafb;   /* gray-50 */
  --gm-surface-sunken: #f3f4f6;   /* gray-100 */
  --gm-border:         #e5e7eb;   /* gray-200 */
  --gm-border-strong:  #d1d5db;   /* gray-300 */
  --gm-hairline:       #f3f4f6;   /* gray-100, for divide-y */

  --gm-text:           #1f2937;   /* gray-800 */
  --gm-text-muted:     #6b7280;   /* gray-500 */
  --gm-text-subtle:    #9ca3af;   /* gray-400 */
  --gm-text-strong:    #111827;   /* gray-900 */

  /* ── Brand (petrol) — matches insilijo.science ink ── */
  --gm-brand:          #0c4a6e;   /* brand-600 */
  --gm-brand-hover:    #0a3d5a;   /* brand-700 */
  --gm-brand-ring:     rgba(12, 74, 110, 0.30);

  /* ── Signal (rust) — reserved for the single most important CTA on a
     page; matches the landing's --signal. Use bg-signal-600 / text-white. */
  --gm-signal:         #b45309;   /* signal-600 */
  --gm-signal-hover:   #92400e;   /* signal-700 */
  --gm-signal-ring:    rgba(180, 83, 9, 0.30);

  --gm-danger-bg:      #fef2f2;
  --gm-danger-border:  #fecaca;
  --gm-danger-text:    #b91c1c;

  --gm-warning-bg:     #fffbeb;
  --gm-warning-border: #fde68a;
  --gm-warning-text:   #b45309;

  --gm-success-bg:     #ecfdf5;
  --gm-success-border: #a7f3d0;
  --gm-success-text:   #047857;

  --gm-info-bg:        #eff6ff;
  --gm-info-border:    #bfdbfe;
  --gm-info-text:      #1d4ed8;

  --gm-radius-sm:      0.5rem;
  --gm-radius:         0.75rem;
  --gm-radius-lg:      0.875rem;
  --gm-radius-xl:      1rem;

  --gm-shadow-card:    0 1px 3px 0 rgb(0 0 0 / 0.06);
  --gm-shadow-card-hover: 0 6px 16px -4px rgb(12 74 110 / 0.10), 0 2px 4px -1px rgb(0 0 0 / 0.06);
  --gm-shadow-pop:     0 8px 24px -6px rgb(0 0 0 / 0.12);
  --gm-shadow-glow:    0 0 0 1px rgb(12 74 110 / 0.14), 0 4px 14px -2px rgb(12 74 110 / 0.16);

  /* Accent palette — use sparingly for variety in hero tiles, stat cards,
     pipeline arms, etc. Named by hue to keep intent obvious at call sites. */
  --gm-violet:         #7c3aed;        /* violet-600  — drug-discovery pipeline arm */
  --gm-violet-soft:    #ede9fe;        /* violet-100  */
  --gm-violet-ink:     #5b21b6;        /* violet-800  */
  --gm-emerald:        #059669;        /* emerald-600 — preprocessed / success ops */
  --gm-emerald-soft:   #d1fae5;
  --gm-emerald-ink:    #065f46;
  --gm-coral:          #f43f5e;        /* rose-500    — highlight / call-out */
  --gm-coral-soft:     #ffe4e6;
  --gm-coral-ink:      #9f1239;
  --gm-amber:          #d97706;        /* amber-600   — warning / pending */
  --gm-amber-soft:     #fef3c7;
  --gm-amber-ink:      #92400e;
  --gm-cyan:           #0891b2;        /* cyan-600    — secondary analyses */
  --gm-cyan-soft:      #cffafe;
  --gm-cyan-ink:       #155e75;

  /* Gradients — reference in `background:` on heroes, icon tiles, hero buttons.
     Retuned toward the landing's petrol+rust palette; swap in `flat` values
     (solid fills) when you want the Swiss-influenced landing look. */
  --gm-gradient-brand:   linear-gradient(135deg, #0c4a6e 0%, #0a3d5a 100%);
  --gm-gradient-twilight:linear-gradient(135deg, #0c4a6e 0%, #5b21b6 100%);
  --gm-gradient-accent:  linear-gradient(135deg, #b45309 0%, #c76810 100%);   /* rust CTA tile */
  --gm-gradient-warm:    linear-gradient(135deg, #b45309 0%, #d88220 100%);
  --gm-gradient-mint:    linear-gradient(135deg, #0c4a6e 0%, #059669 100%);
  --gm-gradient-surface: linear-gradient(180deg, #ffffff 0%, #f7f8fa 100%);

  /* Flat alternatives — when you want the landing's exact look, use these
     (no gradient) on CTA / hero surfaces. */
  --gm-flat-brand:       #0c4a6e;
  --gm-flat-signal:      #b45309;
  --gm-flat-paper:       #ffffff;
  --gm-flat-panel:       #f7f8fa;
  --gm-flat-rule:        #e3e7ef;
}

/* Dark mode (opt-in via `class="dark"` on <html>) */
html.dark {
  --gm-surface:        #0f172a;   /* slate-900 */
  --gm-surface-muted:  #111827;
  --gm-surface-sunken: #1f2937;
  --gm-border:         #1f2937;
  --gm-border-strong:  #334155;
  --gm-hairline:       #1f2937;

  --gm-text:           #e5e7eb;
  --gm-text-muted:     #9ca3af;
  --gm-text-subtle:    #6b7280;
  --gm-text-strong:    #f9fafb;

  --gm-danger-bg:      #3f1d1d;
  --gm-danger-border:  #7f1d1d;
  --gm-danger-text:    #fca5a5;
  --gm-warning-bg:     #3a2a0a;
  --gm-warning-border: #78350f;
  --gm-warning-text:   #fcd34d;
  --gm-success-bg:     #0f2f23;
  --gm-success-border: #065f46;
  --gm-success-text:   #6ee7b7;
  --gm-info-bg:        #0f1f3a;
  --gm-info-border:    #1e3a8a;
  --gm-info-text:      #93c5fd;
}

/* ──────────────────────────────────────────────────────────────
 * Typography helpers
 * ────────────────────────────────────────────────────────────── */
.gm-eyebrow {
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--gm-brand-hover);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
/* Muted variant when a coloured eyebrow would be too loud (e.g. inside
   tinted/hero cards). */
.gm-eyebrow--muted { color: var(--gm-text-subtle); font-weight: 600; }

.gm-page-title {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--gm-text-strong);
  letter-spacing: -0.01em;
  position: relative;
  display: inline-block;
}
.gm-page-title::after {
  content: "";
  display: block;
  height: 3px;
  width: 2.5rem;
  margin-top: 0.375rem;
  border-radius: 3px;
  background: var(--gm-gradient-brand);
}

/* ──────────────────────────────────────────────────────────────
 * Forms
 * Replaces the 172 copies of:
 *   w-full border border-gray-300 rounded-lg px-3 py-2 text-sm
 *   focus:ring-2 focus:ring-brand-600 focus:outline-none
 * ────────────────────────────────────────────────────────────── */
.gm-field          { display: block; }
.gm-field + .gm-field { margin-top: 0.75rem; }

.gm-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--gm-text-muted);
  margin-bottom: 0.25rem;
}
.gm-label__hint {
  font-weight: 400;
  color: var(--gm-text-subtle);
  margin-left: 0.25rem;
}
.gm-help-text {
  font-size: 0.75rem;
  color: var(--gm-text-subtle);
  margin-top: 0.25rem;
}

.gm-input,
.gm-select,
.gm-textarea {
  width: 100%;
  background: var(--gm-surface);
  color: var(--gm-text);
  border: 1px solid var(--gm-border-strong);
  border-radius: var(--gm-radius-sm);
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.gm-input--sm,
.gm-select--sm { padding: 0.375rem 0.5rem; font-size: 0.75rem; }

.gm-input:focus,
.gm-select:focus,
.gm-textarea:focus {
  outline: none;
  border-color: var(--gm-brand);
  box-shadow: 0 0 0 3px var(--gm-brand-ring);
}
.gm-input:disabled,
.gm-select:disabled { background: var(--gm-surface-sunken); color: var(--gm-text-subtle); cursor: not-allowed; }

/* Segmented radio group — replaces the has-[:checked] pattern */
.gm-segment {
  display: flex;
  border: 1px solid var(--gm-border-strong);
  border-radius: var(--gm-radius-sm);
  overflow: hidden;
  font-size: 0.875rem;
}
.gm-segment > label {
  flex: 1;
  text-align: center;
  padding: 0.375rem 0.5rem;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
  color: var(--gm-text-muted);
}
.gm-segment > label + label { border-left: 1px solid var(--gm-border-strong); }
.gm-segment > label:has(input:checked) { background: var(--gm-brand); color: #fff; }
.gm-segment input { position: absolute; opacity: 0; pointer-events: none; }

/* ──────────────────────────────────────────────────────────────
 * Buttons
 * ────────────────────────────────────────────────────────────── */
.gm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  font-weight: 600;
  font-size: 0.875rem;
  padding: 0.5rem 1rem;
  border-radius: var(--gm-radius);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease, box-shadow 120ms ease, transform 60ms ease;
  user-select: none;
  line-height: 1.25rem;
}
.gm-btn:focus-visible {
  outline: 2px solid var(--gm-brand);
  outline-offset: 2px;
}
.gm-btn:disabled,
.gm-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Primary — flat petrol, the everyday confirm/submit button. */
.gm-btn--primary   {
  background: var(--gm-flat-brand);
  color: #fff;
  box-shadow: 0 1px 2px rgb(12 74 110 / 0.18), inset 0 1px 0 rgb(255 255 255 / 0.10);
}
.gm-btn--primary:hover:not(:disabled)   {
  background: var(--gm-brand-hover);
  box-shadow: 0 4px 10px -2px rgb(12 74 110 / 0.28), inset 0 1px 0 rgb(255 255 255 / 0.10);
  transform: translateY(-1px);
}
.gm-btn--primary:active:not(:disabled)  { transform: translateY(0); }

/* Signal — rust CTA. Reserved for the single highest-leverage action on
   a page (Run analysis, Publish, Save permanently). Scarce by design:
   every screen should have at most one of these. Matches the landing's
   primary CTA colour. */
.gm-btn--signal    {
  background: var(--gm-flat-signal);
  color: #fff;
  box-shadow: 0 1px 2px rgb(180 83 9 / 0.22), inset 0 1px 0 rgb(255 255 255 / 0.12);
}
.gm-btn--signal:hover:not(:disabled)    {
  background: var(--gm-signal-hover);
  box-shadow: 0 4px 12px -2px rgb(180 83 9 / 0.32);
  transform: translateY(-1px);
}

/* Accent — gradient pipeline tile (violet → rust). Kept for callout
   cards where you *want* warmth, not for routine buttons. */
.gm-btn--accent    {
  background: var(--gm-gradient-accent);
  color: #fff;
  box-shadow: 0 1px 2px rgb(180 83 9 / 0.22), inset 0 1px 0 rgb(255 255 255 / 0.12);
}
.gm-btn--accent:hover:not(:disabled)    {
  filter: brightness(1.05);
  box-shadow: 0 4px 12px -2px rgb(180 83 9 / 0.32);
  transform: translateY(-1px);
}

.gm-btn--secondary { background: var(--gm-surface); color: var(--gm-text); border-color: var(--gm-border-strong); }
.gm-btn--secondary:hover:not(:disabled) { background: var(--gm-surface-sunken); }

.gm-btn--ghost     { background: transparent; color: var(--gm-text-muted); }
.gm-btn--ghost:hover:not(:disabled)     { background: var(--gm-surface-sunken); color: var(--gm-text); }

.gm-btn--danger    { background: #dc2626; color: #fff; }
.gm-btn--danger:hover:not(:disabled)    { background: #b91c1c; }

.gm-btn--sm  { padding: 0.375rem 0.75rem; font-size: 0.75rem; }
.gm-btn--lg  { padding: 0.625rem 1.25rem; font-size: 0.875rem; border-radius: var(--gm-radius-xl); }
.gm-btn--block { width: 100%; }

/* Icon-only button (requires aria-label on the element) */
.gm-btn--icon {
  padding: 0.5rem;
  border-radius: var(--gm-radius-sm);
  background: transparent;
  color: var(--gm-text-subtle);
}
.gm-btn--icon:hover:not(:disabled) { background: var(--gm-surface-sunken); color: var(--gm-text); }

/* Circular "?" help button */
.gm-help-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 9999px;
  background: var(--gm-info-bg);
  color: var(--gm-info-text);
  font-weight: 700;
  font-size: 0.75rem;
  border: 1px solid var(--gm-info-border);
  cursor: pointer;
  transition: background 120ms ease;
}
.gm-help-btn:hover { background: #dbeafe; }

/* ──────────────────────────────────────────────────────────────
 * Cards
 * ────────────────────────────────────────────────────────────── */
.gm-card {
  background: var(--gm-surface);
  border: 1px solid var(--gm-border);
  border-radius: var(--gm-radius-lg);
  box-shadow: var(--gm-shadow-card);
  overflow: hidden;
  transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease;
}
/* Interactive card (links that wrap a card) — subtle lift on hover. */
a.gm-card:hover,
.gm-card--interactive:hover {
  border-color: var(--gm-brand-ring);
  box-shadow: var(--gm-shadow-card-hover);
  transform: translateY(-1px);
}

/* Tinted cards — pastel fills for variety. */
.gm-card--tint-brand   { background: var(--gm-info-bg); border-color: var(--gm-info-border); }
.gm-card--tint-violet  { background: var(--gm-violet-soft); border-color: #c4b5fd; }
.gm-card--tint-emerald { background: var(--gm-emerald-soft); border-color: #6ee7b7; }
.gm-card--tint-coral   { background: var(--gm-coral-soft); border-color: #fecdd3; }
.gm-card--tint-amber   { background: var(--gm-amber-soft); border-color: #fcd34d; }
.gm-card--tint-cyan    { background: var(--gm-cyan-soft); border-color: #67e8f9; }

/* Card header strip with a warm gradient — great for case-study-style cards. */
.gm-card__hero {
  padding: 1rem 1.25rem;
  color: #fff;
  background: var(--gm-gradient-brand);
}
.gm-card__hero--twilight { background: var(--gm-gradient-twilight); }
.gm-card__hero--accent   { background: var(--gm-gradient-accent); }
.gm-card__hero--warm     { background: var(--gm-gradient-warm); }
.gm-card__hero--mint     { background: var(--gm-gradient-mint); }

.gm-card__header {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--gm-hairline);
  min-height: 2.75rem;
  background: linear-gradient(180deg, rgba(2,132,199,0.03) 0%, transparent 100%);
}
/* Slim coloured accent strip on the top edge. Apply a --gm-accent-gradient
   inline on the card (or use a variant class) to switch hues. */
.gm-card__header::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: var(--gm-card-accent, var(--gm-gradient-brand));
  opacity: 0.75;
}
.gm-card--accent-violet  { --gm-card-accent: var(--gm-gradient-accent); }
.gm-card--accent-emerald { --gm-card-accent: var(--gm-gradient-mint); }
.gm-card--accent-warm    { --gm-card-accent: var(--gm-gradient-warm); }
.gm-card--accent-twilight{ --gm-card-accent: var(--gm-gradient-twilight); }
.gm-card__header--toggle {
  cursor: pointer;
  user-select: none;
}
.gm-card__header--toggle:hover { background: var(--gm-surface-muted); }

.gm-card__body {
  padding: 1rem 1.25rem 1.25rem;
}

/* Chevron used by collapsible card headers */
.gm-chevron {
  width: 1rem; height: 1rem;
  color: var(--gm-text-subtle);
  transition: transform 180ms ease;
}
.gm-chevron--open { transform: rotate(180deg); }

/* Pulse utility — used on status dots for datasets waiting on preprocessing. */
@keyframes gm-pulse {
  0%   { box-shadow: 0 0 0 0   rgba(217,119,6, 0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(217,119,6, 0);    }
  100% { box-shadow: 0 0 0 0   rgba(217,119,6, 0);    }
}
.gm-pulse { animation: gm-pulse 1.8s ease-out infinite; }
.gm-pulse--emerald { animation: gm-pulse-em 1.8s ease-out infinite; }
@keyframes gm-pulse-em {
  0%   { box-shadow: 0 0 0 0   rgba(5,150,105, 0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(5,150,105, 0);    }
  100% { box-shadow: 0 0 0 0   rgba(5,150,105, 0);    }
}

/* Interactive row — used on dataset-hub and list cards. The CTA arrow slides
   right on hover. */
.gm-row-arrow { transition: transform 180ms ease; }
.gm-card--interactive:hover .gm-row-arrow,
a.gm-card:hover .gm-row-arrow { transform: translateX(3px); }

/* ──────────────────────────────────────────────────────────────
 * Stats (metric tile)
 * Replaces per-app duplicates in discomarker/chips/ducky/clustering.
 * ────────────────────────────────────────────────────────────── */
.gm-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
}
@media (min-width: 640px) {
  .gm-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.gm-stat {
  background: var(--gm-surface);
  border: 1px solid var(--gm-border);
  border-radius: var(--gm-radius-lg);
  padding: 1rem;
  text-align: center;
  transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease;
}
.gm-stat:hover { border-color: var(--gm-brand-ring); box-shadow: var(--gm-shadow-card-hover); transform: translateY(-1px); }

.gm-stat__value {
  font-size: 1.5rem;
  line-height: 2rem;
  font-weight: 700;
  color: var(--gm-brand-hover);
}
.gm-stat__label {
  font-size: 0.75rem;
  color: var(--gm-text-muted);
  margin-top: 0.125rem;
}
/* Tonal stat variants — use when stats sit side-by-side to break monotony. */
.gm-stat--brand   .gm-stat__value { color: var(--gm-brand-hover); }
.gm-stat--violet  .gm-stat__value { color: var(--gm-violet-ink); }
.gm-stat--emerald .gm-stat__value { color: var(--gm-emerald-ink); }
.gm-stat--coral   .gm-stat__value { color: var(--gm-coral-ink); }
.gm-stat--amber   .gm-stat__value { color: var(--gm-amber-ink); }
.gm-stat--cyan    .gm-stat__value { color: var(--gm-cyan-ink); }

/* Icon tile — a colored rounded square for section headers. */
.gm-icon-tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--gm-radius-sm);
  color: #fff;
  background: var(--gm-gradient-brand);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.08), inset 0 1px 0 rgb(255 255 255 / 0.15);
  flex: none;
}
.gm-icon-tile--lg { width: 2.5rem; height: 2.5rem; border-radius: var(--gm-radius); }
.gm-icon-tile--violet  { background: var(--gm-gradient-accent); }
.gm-icon-tile--warm    { background: var(--gm-gradient-warm); }
.gm-icon-tile--mint    { background: var(--gm-gradient-mint); }
.gm-icon-tile--twilight{ background: var(--gm-gradient-twilight); }

/* Hero banner — reshaped to match insilijo.science. White canvas,
   petrol ink, Source Serif 4 for the display title. Use on list /
   dataset / module-portal pages; pair with an optional CTA row. For
   the old colour-fill gradient hero, add `.gm-hero--colour`. */
.gm-hero {
  position: relative;
  overflow: hidden;
  border-radius: var(--gm-radius);
  padding: 1.25rem 1.5rem;
  color: var(--gm-text);
  background: var(--gm-flat-paper);
  border: 1px solid var(--gm-border);
  box-shadow: var(--gm-shadow-card);
}
.gm-hero__title {
  font-family: "Source Serif 4", "Source Serif Pro", Georgia, serif;
  font-size: 1.875rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--gm-text);
  position: relative;
}
.gm-hero__subtitle {
  font-size: 0.9375rem;
  color: var(--gm-text-muted);
  margin-top: 0.3rem;
  max-width: 42rem;
  position: relative;
}

/* Optional gradient variant — the old colour-fill hero, now tuned to the
   landing's petrol→rust accents. Drop `.gm-hero--colour` on pages where
   you want a deliberately high-emphasis banner (case-study guide, big
   "what is this" intros). */
.gm-hero--colour {
  color: #fff;
  background: var(--gm-gradient-twilight);
  border: 0;
  box-shadow: 0 10px 30px -12px rgb(12 74 110 / 0.35);
}
.gm-hero--colour .gm-hero__title    { color: #fff; }
.gm-hero--colour .gm-hero__subtitle { color: rgb(255 255 255 / 0.82); }
.gm-hero--colour::after {
  content: "";
  position: absolute;
  top: -40%;
  right: -10%;
  width: 60%;
  height: 180%;
  background: radial-gradient(ellipse at center, rgb(255 255 255 / 0.16) 0%, transparent 60%);
  pointer-events: none;
}

/* ──────────────────────────────────────────────────────────────
 * Alerts / banners
 * ────────────────────────────────────────────────────────────── */
.gm-alert {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border-radius: var(--gm-radius);
  border: 1px solid;
  font-size: 0.875rem;
}
.gm-alert__icon { flex: none; width: 1rem; height: 1rem; margin-top: 0.125rem; }

.gm-alert--info    { background: var(--gm-info-bg);    border-color: var(--gm-info-border);    color: var(--gm-info-text); }
.gm-alert--success { background: var(--gm-success-bg); border-color: var(--gm-success-border); color: var(--gm-success-text); }
.gm-alert--warning { background: var(--gm-warning-bg); border-color: var(--gm-warning-border); color: var(--gm-warning-text); }
.gm-alert--danger  { background: var(--gm-danger-bg);  border-color: var(--gm-danger-border);  color: var(--gm-danger-text); }

/* Compact inline tip (used next to form fields) */
.gm-tip {
  background: var(--gm-info-bg);
  border: 1px solid var(--gm-info-border);
  color: var(--gm-info-text);
  border-radius: var(--gm-radius-sm);
  padding: 0.625rem 0.75rem;
  font-size: 0.75rem;
  line-height: 1.1rem;
}

/* ──────────────────────────────────────────────────────────────
 * Plot loading spinner — painted into any [data-plotly-json-id]
 * container before Plotly renders. Plotly wipes the container on
 * render, so no teardown is needed. See apps/core/static/core/js/
 * plotly_panels.js paintPlotSpinner().
 * ────────────────────────────────────────────────────────────── */
.gm-plot-spinner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 140px;
  height: 100%;
  width: 100%;
  padding: 1.5rem 1rem;
  color: var(--gm-text-subtle);
  font-size: 0.75rem;
  letter-spacing: 0.02em;
}
.gm-plot-spinner svg {
  width: 2.25rem;
  height: 2.25rem;
  color: var(--gm-brand);
}
.gm-plot-spinner__track {
  stroke: var(--gm-info-border);
  opacity: 0.5;
}
.gm-plot-spinner__head {
  stroke: currentColor;
  stroke-dasharray: 80;
  stroke-dashoffset: 60;
  transform-origin: 25px 25px;
  animation: gm-plot-spin 0.9s linear infinite;
}
@keyframes gm-plot-spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.gm-plot-spinner__label {
  font-weight: 500;
  color: var(--gm-text-muted);
}

/* ──────────────────────────────────────────────────────────────
 * Empty states (the "Configure and click Run." boxes)
 * ────────────────────────────────────────────────────────────── */
.gm-empty {
  background:
    radial-gradient(ellipse 220px 110px at 50% 0%, rgba(2,132,199,0.08) 0%, transparent 70%),
    var(--gm-surface);
  border: 1px dashed var(--gm-border-strong);
  border-radius: var(--gm-radius-lg);
  padding: 2.5rem 1.5rem;
  text-align: center;
  color: var(--gm-text-muted);
  font-size: 0.875rem;
}

/* ──────────────────────────────────────────────────────────────
 * Analysis shell — the canonical 2-column layout used across 8+ pages
 * ────────────────────────────────────────────────────────────── */
.gm-analysis-shell {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  align-items: start;
  min-width: 0;
}
@media (min-width: 1024px) {
  .gm-analysis-shell {
    grid-template-columns: 300px minmax(0, 1fr);
  }
  .gm-analysis-shell--wide    { grid-template-columns: 360px minmax(0, 1fr); }
  .gm-analysis-shell--narrow  { grid-template-columns: 260px minmax(0, 1fr); }
}

.gm-analysis-shell__sidebar  { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.gm-analysis-shell__results  { min-width: 0; }

/* ──────────────────────────────────────────────────────────────
 * Tables (shared base — apps may still add headers)
 * ────────────────────────────────────────────────────────────── */
.gm-table {
  width: 100%;
  font-size: 0.75rem;
  border-collapse: separate;
  border-spacing: 0;
}
.gm-table thead th {
  background: var(--gm-surface-muted);
  color: var(--gm-text-muted);
  font-weight: 600;
  text-align: left;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--gm-border);
}
.gm-table tbody td {
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--gm-hairline);
  color: var(--gm-text);
}
.gm-table tbody tr:nth-child(odd)  td { background: transparent; }
.gm-table tbody tr:nth-child(even) td { background: rgba(240, 249, 255, 0.45); }   /* brand-50 @ 45% */
.gm-table tbody tr:hover td { background: rgba(186, 230, 253, 0.35); }              /* brand-200 @ 35% */
.gm-table td.gm-table__num,
.gm-table th.gm-table__num { text-align: right; font-variant-numeric: tabular-nums; }

/* ──────────────────────────────────────────────────────────────
 * GIZMO-style analysis tabs — the JS applies `border-brand-600`
 * + `text-brand-700` to the active tab; we use that as the hook to
 * upgrade the underline to a gradient and tint the whole tab.
 * ────────────────────────────────────────────────────────────── */
.gizmo-tab { position: relative; color: var(--gm-text-muted); }
.gizmo-tab:hover { color: var(--gm-text); background: var(--gm-surface-muted); }
.gizmo-tab.border-brand-600 {
  color: var(--gm-brand-hover) !important;
  background: linear-gradient(180deg, rgba(2,132,199,0.06) 0%, transparent 100%);
  border-bottom-color: transparent !important;
}
.gizmo-tab.border-brand-600::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 3px;
  background: var(--gm-gradient-brand);
  border-radius: 3px 3px 0 0;
}

/* ──────────────────────────────────────────────────────────────
 * Badge / pill
 * ────────────────────────────────────────────────────────────── */
.gm-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.125rem 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  border-radius: 9999px;
  background: var(--gm-surface-sunken);
  color: var(--gm-text-muted);
  border: 1px solid var(--gm-border);
}
.gm-badge--brand   { background: var(--gm-info-bg); color: var(--gm-brand-hover); border-color: var(--gm-info-border); }
.gm-badge--success { background: var(--gm-success-bg); color: var(--gm-success-text); border-color: var(--gm-success-border); }
.gm-badge--warning { background: var(--gm-warning-bg); color: var(--gm-warning-text); border-color: var(--gm-warning-border); }
.gm-badge--danger  { background: var(--gm-danger-bg); color: var(--gm-danger-text); border-color: var(--gm-danger-border); }

/* ──────────────────────────────────────────────────────────────
 * Top-nav link (.gm-navlink) — used in the primary navbar.
 * Each link sets its own --nav-accent via inline style; the
 * accent tints the hover background and drives the active pill
 * so the nav has section-colored personality without being loud.
 * ────────────────────────────────────────────────────────────── */
.gm-navlink {
  --nav-accent: #0c4a6e;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.4375rem 0.875rem;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  color: #334155;
  background: #ffffff;
  border: 1px solid #cbd5e1;
  border-radius: 0.5rem;
  font-family: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  box-shadow: 0 1px 2px 0 rgba(15,23,42,0.05);
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease;
}
button.gm-navlink { margin: 0; }
.gm-navlink:hover {
  color: var(--nav-accent);
  background: #f8fafc;
  border-color: color-mix(in srgb, var(--nav-accent) 50%, #cbd5e1);
  box-shadow: 0 2px 4px 0 color-mix(in srgb, var(--nav-accent) 15%, rgba(15,23,42,0.06));
}
.gm-navlink:active { transform: translateY(1px); }
.gm-navlink.is-active {
  color: #ffffff;
  background: var(--nav-accent);
  border-color: var(--nav-accent);
  box-shadow: 0 2px 6px -1px color-mix(in srgb, var(--nav-accent) 45%, transparent),
              inset 0 1px 0 0 rgba(255,255,255,0.15);
}
.gm-navlink.is-active:hover {
  color: #ffffff;
  background: color-mix(in srgb, var(--nav-accent) 92%, #000000);
  border-color: color-mix(in srgb, var(--nav-accent) 92%, #000000);
}
.gm-navlink.is-disabled {
  color: #94a3b8;
  background: #f1f5f9;
  border-color: #e2e8f0;
  box-shadow: none;
  cursor: not-allowed;
}
.gm-navlink.is-disabled:hover {
  color: #94a3b8;
  background: #f1f5f9;
  border-color: #e2e8f0;
  box-shadow: none;
}
.gm-navlink__divider {
  display: inline-block;
  width: 1px;
  height: 1.25rem;
  background: #cbd5e1;
  margin: 0 0.25rem;
  align-self: center;
}
