/* ============================================================================
   Framer design tokens - the single source of truth for colour.

   Every token is declared ONCE using light-dark(), which resolves against the
   element's used `color-scheme`. That means:
     * with `color-scheme: light dark` on :root, the app follows the OS with
       no JavaScript at all;
     * the entire manual override is the two [data-theme] rules below the
       palette.
   There is deliberately no duplicated @media block to drift out of sync.
   ============================================================================ */

:root {
  color-scheme: light dark;                    /* default: follow the OS */

  /* ---- Brand ramp: "Iris" ------------------------------------------------ */
  --iris-50:  #f4f1ff;  --iris-100: #e9e3ff;  --iris-200: #d5caff;
  --iris-300: #b8a4ff;  --iris-400: #9a78ff;  --iris-500: #7c4dff;
  --iris-600: #6a35f0;  --iris-700: #5827cc;  --iris-800: #4721a3;
  --iris-900: #351a78;

  /* ---- Neutral ramp: "Ink" ----------------------------------------------- */
  --ink-0:    #ffffff;  --ink-25:   #fbfbfd;  --ink-50:   #f6f6f9;
  --ink-100:  #eeeef4;  --ink-200:  #e0e0ea;  --ink-300:  #c8c8d6;
  --ink-400:  #9c9cb0;  --ink-500:  #74748c;  --ink-600:  #55556b;
  --ink-700:  #3d3d50;  --ink-800:  #2a2a39;  --ink-900:  #1c1c28;
  --ink-950:  #121219;  --ink-1000: #0a0a0f;

  /* ---- Surfaces ---------------------------------------------------------- */
  --surface-base:    light-dark(var(--ink-50),  var(--ink-950));
  --surface-raised:  light-dark(var(--ink-0),   var(--ink-900));
  --surface-sunken:  light-dark(var(--ink-100), var(--ink-1000));
  --surface-overlay: light-dark(var(--ink-0),   var(--ink-800));
  --surface-row-alt: light-dark(rgba(0, 0, 0, .025), rgba(255, 255, 255, .03));
  --surface-hover:   light-dark(rgba(0, 0, 0, .04),  rgba(255, 255, 255, .05));
  --surface-header:  light-dark(rgba(255, 255, 255, .82), rgba(18, 18, 25, .82));
  /* gradient stops - light-dark() cannot wrap a whole gradient */
  --grad-app-1:      light-dark(var(--ink-50),  var(--ink-950));
  --grad-app-2:      light-dark(var(--ink-100), var(--ink-900));

  /* ---- Borders ------------------------------------------------------------ */
  --border-subtle:  light-dark(var(--ink-200), var(--ink-800));
  --border-default: light-dark(var(--ink-300), var(--ink-700));
  --border-strong:  light-dark(var(--ink-400), var(--ink-600));

  /* ---- Text --------------------------------------------------------------- */
  --text-primary:   light-dark(var(--ink-900), var(--ink-50));
  --text-secondary: light-dark(var(--ink-600), var(--ink-300));
  --text-muted:     light-dark(var(--ink-600), var(--ink-400));
  --text-inverse:   light-dark(var(--ink-0),   var(--ink-950));
  --text-on-brand:  #ffffff;

  /* ---- Brand semantics ---------------------------------------------------- */
  /* --brand is body-text-sized link colour, so it must clear 4.5:1 against
     --surface-raised in BOTH themes. iris-400 measured 3.5:1 on the dark
     card, so dark steps up to iris-300. --brand-solid stays put: it is a
     fill colour behind white text, not text itself. */
  --brand:          light-dark(var(--iris-600), var(--iris-300));
  --brand-hover:    light-dark(var(--iris-700), var(--iris-200));
  --brand-solid:    var(--iris-500);            /* fills: identical both themes */
  --brand-solid-hi: var(--iris-600);
  --brand-subtle:   light-dark(var(--iris-50), color-mix(in srgb, var(--iris-500) 16%, transparent));
  --brand-wash:     light-dark(color-mix(in srgb, var(--iris-500)  7%, transparent),
                               color-mix(in srgb, var(--iris-500) 12%, transparent));
  --brand-contrast: #ffffff;
  --brand-rgb:      124, 77, 255;

  /* ---- Status ------------------------------------------------------------- */
  /* Base hues are theme-invariant, so a "pass" is the same green in both
     themes. Only the tint strength and the readable-on-tint text flip.

     NOTE: light-dark() accepts <color> ONLY. It cannot supply the percentage
     argument of color-mix() - doing so makes the whole function invalid and
     the token silently computes to transparent, which quietly removed every
     alert and status-pill background. So the tint percentage is written out
     per theme and light-dark() wraps the two finished colours.              */
  --status-pass:        #10b981;
  --status-pass-strong: light-dark(#047857, #6ee7b7);
  --status-pass-subtle: light-dark(color-mix(in srgb, #10b981 12%, transparent),
                                   color-mix(in srgb, #10b981 18%, transparent));
  --status-fail:        #ef4444;
  --status-fail-strong: light-dark(#b91c1c, #fca5a5);
  --status-fail-subtle: light-dark(color-mix(in srgb, #ef4444 12%, transparent),
                                   color-mix(in srgb, #ef4444 18%, transparent));
  --status-warn:        #f59e0b;
  --status-warn-strong: light-dark(#8a3d06, #fcd34d);
  --status-warn-subtle: light-dark(color-mix(in srgb, #f59e0b 12%, transparent),
                                   color-mix(in srgb, #f59e0b 18%, transparent));
  --status-info:        #0ea5e9;
  --status-info-strong: light-dark(#0369a1, #7dd3fc);
  --status-info-subtle: light-dark(color-mix(in srgb, #0ea5e9 12%, transparent),
                                   color-mix(in srgb, #0ea5e9 18%, transparent));
  --status-skip:        light-dark(var(--ink-500), var(--ink-400));
  --status-skip-strong: light-dark(var(--ink-600), var(--ink-300));
  --status-skip-subtle: light-dark(color-mix(in srgb, #74748c 12%, transparent),
                                   color-mix(in srgb, #74748c 18%, transparent));

  /* ---- Syntax highlighting (Python code modal) ---------------------------- */
  --syntax-comment:   light-dark(#565e69, #7c8798);
  --syntax-keyword:   light-dark(#6a35f0, #b8a4ff);
  --syntax-string:    light-dark(#0a7d3f, #86efac);
  --syntax-number:    light-dark(#b45309, #fbbf24);
  --syntax-decorator: light-dark(#a21caf, #f0abfc);
  --syntax-function:  light-dark(#0369a1, #7dd3fc);

  /* ---- Log viewer --------------------------------------------------------- */
  --log-debug:     light-dark(#0369a1, #9cdcfe);
  --log-info:      var(--status-info-strong);
  --log-warning:   var(--status-warn-strong);
  --log-error:     var(--status-fail-strong);
  --log-timestamp: var(--status-pass-strong);
  --log-test:      light-dark(#a21caf, #f0abfc);
  --log-site:      light-dark(#0a7d3f, #86efac);
  --log-rule:      light-dark(rgba(0, 0, 0, .06), rgba(255, 255, 255, .05));

  /* ---- Effects and metrics ------------------------------------------------ */
  --focus-ring:   0 0 0 3px color-mix(in srgb, var(--brand-solid) 32%, transparent);
  --shadow-sm:    0 1px 2px light-dark(rgba(16, 16, 26, .06), rgba(0, 0, 0, .40));
  --shadow-md:    0 4px 6px -1px light-dark(rgba(16, 16, 26, .10), rgba(0, 0, 0, .45));
  --shadow-lg:    0 10px 24px -6px light-dark(rgba(16, 16, 26, .14), rgba(0, 0, 0, .55));
  --shadow-brand: 0 4px 12px color-mix(in srgb, var(--brand-solid) 30%, transparent);

  --radius-sm: .375rem;  --radius-md: .5rem;
  --radius-lg: .75rem;   --radius-xl: 1rem;
  --sidebar-width: 260px; --header-height: 60px;
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Monaco', monospace;
}

/* The explicit user override. These two rules ARE the whole theme switch. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark;  }

/* ============================================================================
   Bootstrap 5.3 bridge.
   Set once here so every Bootstrap component themes correctly in BOTH modes
   with zero !important. This file loads AFTER bootstrap.min.css, so these
   equal-specificity declarations win over Bootstrap's own [data-bs-theme]
   values - while anything we do NOT list (the .form-select chevron data-URI,
   the .btn-close filter) still gets Bootstrap's correct per-theme treatment.
   ============================================================================ */
:root {
  --bs-body-bg:                  var(--surface-base);
  --bs-body-color:               var(--text-primary);
  --bs-emphasis-color:           var(--text-primary);
  --bs-secondary-color:          var(--text-secondary);
  --bs-secondary-bg:             var(--surface-sunken);
  --bs-tertiary-color:           var(--text-muted);
  --bs-tertiary-bg:              var(--surface-raised);
  --bs-heading-color:            var(--text-primary);
  --bs-border-color:             var(--border-subtle);
  --bs-border-color-translucent: var(--border-subtle);
  --bs-link-color:               var(--brand);
  --bs-link-hover-color:         var(--brand-hover);
  --bs-code-color:               var(--brand);
  --bs-focus-ring-color:         color-mix(in srgb, var(--brand-solid) 32%, transparent);
  --bs-font-sans-serif:          var(--font-sans);
  --bs-font-monospace:           var(--font-mono);

  --bs-primary:               var(--brand-solid);
  --bs-primary-rgb:           var(--brand-rgb);
  --bs-primary-text-emphasis: var(--brand);
  --bs-primary-bg-subtle:     var(--brand-subtle);
  --bs-primary-border-subtle: color-mix(in srgb, var(--brand-solid) 40%, transparent);

  --bs-success:               var(--status-pass);
  --bs-success-rgb:           16, 185, 129;
  --bs-success-text-emphasis: var(--status-pass-strong);
  --bs-success-bg-subtle:     var(--status-pass-subtle);
  --bs-success-border-subtle: color-mix(in srgb, var(--status-pass) 40%, transparent);

  --bs-danger:               var(--status-fail);
  --bs-danger-rgb:           239, 68, 68;
  --bs-danger-text-emphasis: var(--status-fail-strong);
  --bs-danger-bg-subtle:     var(--status-fail-subtle);
  --bs-danger-border-subtle: color-mix(in srgb, var(--status-fail) 40%, transparent);

  --bs-warning:               var(--status-warn);
  --bs-warning-rgb:           245, 158, 11;
  --bs-warning-text-emphasis: var(--status-warn-strong);
  --bs-warning-bg-subtle:     var(--status-warn-subtle);
  --bs-warning-border-subtle: color-mix(in srgb, var(--status-warn) 40%, transparent);

  --bs-info:               var(--status-info);
  --bs-info-rgb:           14, 165, 233;
  --bs-info-text-emphasis: var(--status-info-strong);
  --bs-info-bg-subtle:     var(--status-info-subtle);
  --bs-info-border-subtle: color-mix(in srgb, var(--status-info) 40%, transparent);

  --bs-secondary:               var(--status-skip);
  --bs-secondary-text-emphasis: var(--status-skip-strong);
  --bs-secondary-bg-subtle:     var(--status-skip-subtle);
  --bs-secondary-border-subtle: var(--border-default);
}

/* Tokens light-dark() cannot express: Bootstrap wants raw RGB triplets for
   rgba() composition, and light-dark() only accepts <color>.

   --bs-secondary-rgb matters more than it looks. Bootstrap 5.3 splits two
   similarly named things:
     .text-muted     -> var(--bs-secondary-color)          (a text colour)
     .text-secondary -> rgba(var(--bs-secondary-rgb), ...) (a THEME colour)
   Leaving --bs-secondary-rgb at the mid grey made .text-secondary measure
   3.7:1 on a dark card. It is pinned per-theme to the readable step instead;
   .badge.bg-secondary tints from it at .22 opacity, measured readable in both
   themes (see components.css). */
:root {
  --bs-body-bg-rgb:    246, 246, 249;
  --bs-body-color-rgb: 28, 28, 40;
  --bs-secondary-rgb:  85, 85, 107;      /* --ink-600 */
  --bs-link-color-rgb: 106, 53, 240;     /* --iris-600, matches --brand */
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bs-body-bg-rgb:    18, 18, 25;
    --bs-body-color-rgb: 246, 246, 249;
    --bs-secondary-rgb:  200, 200, 214;  /* --ink-300 */
    --bs-link-color-rgb: 184, 164, 255;  /* --iris-300, matches --brand */
  }
}
:root[data-theme="dark"] {
  --bs-body-bg-rgb:    18, 18, 25;
  --bs-body-color-rgb: 246, 246, 249;
  --bs-secondary-rgb:  200, 200, 214;
  --bs-link-color-rgb: 184, 164, 255;
}
