/* ============================================================================
 * Design tokens — the one place colour, spacing and type are named.
 * ============================================================================
 *
 * Why this exists
 * ---------------
 * There were 13,000+ hardcoded hex colours across ~490 templates and exactly one
 * global CSS custom property in the whole project (`--site-nav-h`, in
 * project.css). Every page invented its own palette inline.
 *
 * The useful discovery: those hex values are already Tailwind's slate / blue /
 * red / amber / emerald / violet ramps, applied by hand. There is no Tailwind in
 * this project — someone just used its numbers. That means replacing a hex with
 * the matching token below renders BYTE-IDENTICALLY.
 *
 * Protect that property. It is what lets the migration ship continuously instead
 * of as one big risky rewrite. The moment a substitution changes a rendered
 * colour, it stops being a mechanical refactor and starts needing design review.
 *
 * How to migrate (two passes, and the order matters)
 * -------------------------------------------------
 *   Pass A   #e2e8f0  ->  var(--slate-200)      mechanical, always safe
 *   Pass B   var(--slate-200)  ->  var(--border) needs a human to confirm INTENT
 *
 * Do not collapse these into one step. #e2e8f0 is a border in most places here
 * but a background in others; guessing bakes in the wrong intent and blocks dark
 * mode later.
 *
 * `make lint-tokens` ratchets Pass A on changed files only.
 *
 * Where NOT to use these
 * ----------------------
 *   - notifications/**  — email clients strip custom properties. A token in an
 *     email renders as nothing, which means black-on-black or invisible text.
 *   - the exports directories and the _pdf.html templates — WeasyPrint. It
 *     does support custom
 *     properties, but PDFs are the highest-consequence, lowest-observability
 *     surface here: a regression is found by a customer, not by CI.
 * Both are excluded in the lint target.
 *
 * NOTE: never write a glob like double-star-slash in a CSS comment. The
 * slash-star pair inside it terminates the comment early, and the remaining
 * words leak into the stylesheet where they attach to the next selector —
 * turning `:root` into `exports :root`, which matches nothing. That silently
 * dropped every primitive token and left the whole site unstyled.
 * ========================================================================== */

/* ---------------------------------------------------------------------------
 * LAYER 1 — PRIMITIVES
 * The literal ramps already in use. Named, not chosen: every value below was
 * already in the codebase. Never reference a raw hex outside this block.
 * ------------------------------------------------------------------------ */
:root {
  /* Slate — the dominant neutral. 6 of the 10 most-used colours are from here. */
  --slate-50:  #f8fafc;
  --slate-100: #f1f5f9;
  --slate-200: #e2e8f0;
  --slate-300: #cbd5e1;
  --slate-400: #94a3b8;
  --slate-500: #64748b;
  --slate-600: #475569;
  --slate-700: #334155;
  --slate-800: #1e293b;
  --slate-900: #0f172a;

  /* Gray — a second neutral ramp that crept in alongside slate. Kept so Pass A
     stays lossless; prefer slate for new work. */
  --gray-700: #374151;
  --gray-900: #111827;

  --blue-50:  #eff6ff;
  --blue-100: #dbeafe;
  --blue-600: #2563eb;
  --blue-700: #1d4ed8;

  --indigo-500: #6366f1;
  --violet-600: #7c3aed;

  --red-100: #fee2e2;
  --red-400: #f87171;
  --red-600: #dc2626;
  --red-800: #991b1b;

  --amber-100: #fef3c7;
  --amber-500: #f59e0b;
  --amber-600: #d97706;

  --emerald-100: #d1fae5;
  --emerald-500: #10b981;
  --emerald-600: #059669;

  --white: #ffffff;
  --black: #000000;

  /* Spacing — a 4px base scale. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-8: 3rem;
  --space-10: 4rem;

  --radius-sm: 0.25rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;
  --radius-pill: 9999px;

  --shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);
  --shadow-md: 0 4px 12px rgba(15, 23, 42, .08);
  --shadow-lg: 0 12px 32px rgba(15, 23, 42, .12);

  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --dur-fast: 120ms;
  --dur-base: 200ms;

  --z-sticky: 1020;
  --z-drawer: 1045;
  --z-modal: 1055;
  --z-toast: 1090;
}

/* Marketing palette for the .lp-page shell. Named here rather than inlined in
 * ui.css so `make lint-tokens` stays clean and the palette has one home — the
 * same rule every other colour on the platform follows.
 *
 * The LAYOUT is still ShineM5 (Mobirise), measured in a browser: 30px cards,
 * 16px pill buttons with an arrow badge, 80px section rhythm, headings at
 * weight 400. The COLOUR is no longer ShineM5's acid lime — it is lifted from
 * the account pages (templates/account/login.html), so a visitor who clicks
 * "Start free" does not walk from a lime page onto a blue one.
 *
 * Values are that page's, not approximations of it: #3b82f6 -> #2563eb is its
 * Sign In gradient, #1d4ed8 its link hover, #101a3a the visual panel behind
 * the form, #3d4468 / #6c7293 its body and muted type. The neutrals are its
 * neumorphic ground (#e0e5ec family) lightened to survive at full-section
 * width, which is the "bluish tint" the rest of this palette hangs off.
 *
 * The `--shine-` prefix is kept because it names the theme, not the hue, and
 * renaming it would touch every rule in the .lp-page block for no gain. */
:root {
  --shine-accent:        #3b82f6;
  --shine-accent-deep:   #2563eb;
  --shine-accent-subtle: #e8eefb;
  /* The accent as an INK — 6.3:1 on white, so it can be read as type rather
   * than only used as a fill. */
  --shine-accent-ink:    #1d4ed8;
  /* And the accent on a dark ground, where #3b82f6 goes muddy. */
  --shine-accent-lift:   #93c5fd;

  --shine-ink:         #101a3a;
  --shine-paper:       #eef1f7;
  --shine-nav:         #e6eaf2;
  --shine-line:        #dee3ee;
  --shine-line-strong: #c7cfdf;
  --shine-muted:       #3d4468;
  --shine-subtle:      #6c7293;

  /* Type ON the accent fill. Lime was light enough to take black; #3b82f6 is
   * not — this is the pairing that has to flip, and missing it is how a
   * palette swap ends up with black text on a mid-blue button. */
  --shine-on-accent:        #ffffff;
  --shine-on-accent-muted:  #dbe6fb;

  --shine-footer-link: #c7d2e8;
}

/* Dawn — the soft sky-blue -> lavender -> blush ground used by the AI
 * Strategy Builder workspace (.sb-page). Only the opaque values live here;
 * every card fill, hairline and hover wash in that stylesheet is an rgba()
 * of white or near-black over this ground, so the whole surface is driven
 * by these five stops.
 *
 * The ramp runs blue -> lavender -> blush across the diagonal, which is what
 * keeps a full-bleed section from reading as a flat wash of one hue. Type on
 * it is --slate-900 for headings, --sbx-body for prose and --sbx-subtle for
 * meta; anything lighter than --sbx-subtle stops clearing 4.5:1 against
 * --sbx-bg-mid. (This ground was midnight navy/indigo before; kept the same
 * variable names so the light-on-dark -> dark-on-light flip in
 * my_strategies.css stayed a value swap, not a rewrite.) */
:root {
  --sbx-bg-deep:   #dbeafe;
  --sbx-bg-mid:    #ede9fe;
  --sbx-bg-violet: #fce7f3;
  --sbx-body:      #475569;
  --sbx-subtle:    #64748b;
}

/* Spectrum — the emerald -> blue -> violet ground used by the Enterprise AI
 * Strategy journey (.sbj-page). Same discipline as the midnight ramp above:
 * only the opaque stops live here, and every card fill, hairline and hover
 * wash in journey.css is an rgba() of white or black over them, so the whole
 * journey is re-tintable from these values.
 *
 * The ramp runs left-to-right rather than diagonally because the journey's
 * hero is a wide band, and a diagonal on a short band shows only two of the
 * three hues. --sbj-ink is the type colour for the white pill CTA and the
 * dark closing band; --sbj-body / --sbj-subtle are prose and meta ON the
 * gradient, both of which clear 4.5:1 against --sbj-blue, the lightest stop. */
:root {
  --sbj-green:  #0e9f6e;
  --sbj-teal:   #0b8fbf;
  --sbj-blue:   #1d4fd8;
  --sbj-violet: #6d28d9;
  --sbj-purple: #8b2fd0;

  --sbj-ink:    #0b1020;
  --sbj-body:   #e4ecff;
  --sbj-subtle: #bcc9f0;
}

/* ---------------------------------------------------------------------------
 * LAYER 2 — SEMANTICS
 * What a colour MEANS. These are the only tokens page CSS should reference:
 * they are what makes dark mode and per-product theming a token swap rather
 * than a find-and-replace.
 * ------------------------------------------------------------------------ */
:root {
  --surface:         var(--white);
  --surface-sunken:  var(--slate-50);
  --surface-raised:  var(--white);
  --surface-inverse: var(--slate-900);

  --border:        var(--slate-200);
  --border-strong: var(--slate-300);

  --text:         var(--slate-900);
  --text-muted:   var(--slate-500);
  --text-subtle:  var(--slate-400);
  --text-inverse: var(--white);

  --brand:          var(--blue-600);
  --brand-hover:    var(--blue-700);
  --brand-contrast: var(--white);
  --brand-subtle:   var(--blue-50);

  --accent: var(--amber-500);

  --danger:         var(--red-600);
  --danger-subtle:  var(--red-100);
  --warning:        var(--amber-500);
  --warning-subtle: var(--amber-100);
  --success:        var(--emerald-600);
  --success-subtle: var(--emerald-100);

  --focus-ring: 0 0 0 0.25rem rgba(37, 99, 235, .25);
}

/* Per-product identity. Each product landing page currently ships its own fonts
 * and palette in an 800–1,500 line standalone template; these overrides are the
 * replacement for that (see the masterplan's product_landing layout).
 * Applied via a body class, so they cascade to everything on the page. */
.product-house    { --brand: #1a3c5e; --accent: #c89020; }
.product-solar    { --brand: var(--amber-500); --accent: var(--amber-600); }
.product-strategy { --brand: var(--violet-600); --accent: var(--amber-500); }
.product-sme      { --brand: var(--blue-600); --accent: var(--indigo-500); }

/* The four secondary ("More tools") products — each needs its own color so
 * the row of chips reads as distinct tools rather than five repeats of the
 * same outline button. Matches each product's own `primary_color` in
 * product_registry.py so the identity agrees wherever it shows up. */
.product-wai      { --brand: #0d9488; --accent: #14b8a6; }  /* teal — Home Build wAI */
.product-sizer    { --brand: #0ea5e9; --accent: #38bdf8; }  /* sky blue — Solar Sizer AI */
.product-career   { --brand: #10b981; --accent: #34d399; }  /* emerald — Career Builder */
.product-startup  { --brand: #f97316; --accent: #fb923c; }  /* orange — SME Startup Review */

/* ---------------------------------------------------------------------------
 * LAYER 3 — BOOTSTRAP BRIDGE
 *
 * Only meaningful where Bootstrap 5.3.x is loaded, i.e. base_app.html
 * (static/vendor/iai/bootstrap 5.3.2) and its ~169 descendants. base.html and
 * base_marketing.html still load the digalu 5.1.3 build, which has no runtime
 * custom properties — these declarations are inert there, not harmful.
 *
 * IMPORTANT, and contrary to the obvious guess: overriding `--bs-primary` does
 * NOT restyle `.btn-primary`. In 5.3 the button rule hardcodes its own
 * component vars:
 *     .btn-primary{--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;...}
 * `--bs-primary` is only consumed by utilities like `.text-primary`. So the
 * component vars have to be overridden directly, which is what the block below
 * does. Verified against static/vendor/iai/bootstrap/css/bootstrap.min.css.
 * ------------------------------------------------------------------------ */
:root {
  /* These ARE read at runtime by Bootstrap's base styles. */
  --bs-body-color:      var(--text);
  --bs-body-bg:         var(--surface);
  --bs-border-color:    var(--border);
  --bs-secondary-color: var(--text-muted);
  --bs-emphasis-color:  var(--text);
  --bs-link-color:      var(--brand);
  --bs-link-hover-color: var(--brand-hover);

  /* Consumed by .text-primary / .bg-primary utilities. */
  --bs-primary: var(--brand);
  --bs-danger:  var(--danger);
  --bs-warning: var(--warning);
  --bs-success: var(--success);

  --bs-border-radius:    var(--radius-md);
  --bs-border-radius-lg: var(--radius-lg);
  --bs-body-font-family: var(--font-sans);
}

/* Component-level overrides — the part that actually restyles buttons. */
.btn-primary {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-color: var(--brand-contrast);
  --bs-btn-hover-bg: var(--brand-hover);
  --bs-btn-hover-border-color: var(--brand-hover);
  --bs-btn-hover-color: var(--brand-contrast);
  --bs-btn-active-bg: var(--brand-hover);
  --bs-btn-active-border-color: var(--brand-hover);
  --bs-btn-disabled-bg: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
}

.btn-outline-primary {
  --bs-btn-color: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand);
  --bs-btn-hover-border-color: var(--brand);
  --bs-btn-hover-color: var(--brand-contrast);
  --bs-btn-active-bg: var(--brand);
  --bs-btn-active-border-color: var(--brand);
}

/* The five competing button namespaces (.sme-btn-*, .bp-btn-*, .sbl .btn.primary,
 * .btn-unlock, plain Bootstrap) are aliased here rather than replaced with an
 * include partial. A `ui/button.html` would be longer than the HTML it replaces,
 * cannot take icon children ({% include %} has no slots), and would be routed
 * around. Aliasing works on all templates the day it ships and lets each app's
 * local definition be deleted one at a time. */
.sme-btn-primary,
.bp-btn-primary,
.btn-unlock,
.sbl .btn.primary {
  background-color: var(--brand);
  border-color: var(--brand);
  color: var(--brand-contrast);
}

.sme-btn-primary:hover,
.bp-btn-primary:hover,
.btn-unlock:hover,
.sbl .btn.primary:hover {
  background-color: var(--brand-hover);
  border-color: var(--brand-hover);
  color: var(--brand-contrast);
}

/* ---------------------------------------------------------------------------
 * RECENT WORK — /app/ hub
 * A fixed-size thumbnail per row (a vertical topic photo, or a tinted icon
 * tile when none applies) so the list reads as a body of work rather than a
 * bare file listing. Sizing needs a real class rather than a Bootstrap
 * utility — nothing in the framework does fixed 56px tiles — but everything
 * else here is existing tokens, so no per-product variants are needed.
 * ------------------------------------------------------------------------ */
.recent-work-row {
  transition: background-color .15s ease;
}
.recent-work-row:hover {
  background-color: var(--surface-sunken);
}
.recent-work-thumb,
.recent-work-thumb-fallback {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-md);
  flex: 0 0 auto;
}
.recent-work-thumb {
  object-fit: cover;
}
.recent-work-thumb-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-sunken);
  color: var(--text-muted);
  font-size: 1.35rem;
}

/* ---------------------------------------------------------------------------
 * PRODUCT DEMOS — /app/ hub
 * A photo card (image, name, one-line pitch, call to action) per product
 * instead of a bare icon tile, so "see a sample" reads as an actual body of
 * work rather than a directory listing. Locked/"coming soon" products reuse
 * the exact same card with the photo desaturated, so the row stays one
 * consistent grid instead of two different layouts.
 * ------------------------------------------------------------------------ */
.demo-card {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-raised);
  box-shadow: var(--shadow-sm);
  color: var(--text);
  transition: transform .15s ease, box-shadow .15s ease;
}
a.demo-card:hover,
a.demo-card:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  color: var(--text);
}
.demo-card__media {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--surface-sunken);
  flex: 0 0 auto;
}
.demo-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.demo-card__img-fallback {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  color: var(--text-muted);
}
.demo-card__body {
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}
.demo-card__eyebrow {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--brand);
  margin-bottom: var(--space-1);
}
.demo-card__title {
  font-size: .9rem;
  font-weight: 700;
  line-height: 1.3;
  margin-bottom: var(--space-2);
  flex-grow: 1;
}
.demo-card__cta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: .78rem;
  font-weight: 600;
  color: var(--text-muted);
  margin: 0;
}
.demo-card--disabled {
  pointer-events: none;
}
.demo-card--disabled .demo-card__media {
  filter: grayscale(1);
  opacity: .65;
}
.demo-card--disabled .demo-card__title,
.demo-card--disabled .demo-card__eyebrow {
  color: var(--text-muted);
}

/* ---------------------------------------------------------------------------
 * DARK MODE
 * Only Layer 2 is redefined — that is the payoff for keeping primitives and
 * semantics separate. Bootstrap 5.3's own `data-bs-theme` switch drives it, so
 * this composes with the framework instead of fighting it.
 *
 * This replaces the two bespoke toggles that shipped inside product templates
 * (SME's localStorage('sme_theme'), strategy's body.sbl-dark), which theme only
 * their own page and know nothing about each other.
 * ------------------------------------------------------------------------ */
[data-bs-theme="dark"] {
  --surface:         var(--slate-900);
  --surface-sunken:  #060b16;
  --surface-raised:  var(--slate-800);
  --surface-inverse: var(--white);

  --border:        var(--slate-700);
  --border-strong: var(--slate-600);

  --text:         var(--slate-100);
  --text-muted:   var(--slate-400);
  --text-subtle:  var(--slate-500);
  --text-inverse: var(--slate-900);

  --brand:        #60a5fa;   /* blue-400 — blue-600 fails contrast on dark */
  --brand-hover:  #93c5fd;   /* blue-300 */
  --brand-subtle: var(--slate-800);
  --brand-contrast: var(--slate-900);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, .5);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, .6);
}

/* Respect the OS preference only when the page has not made an explicit choice,
 * so a user's in-app toggle always wins over the system setting. */
@media (prefers-reduced-motion: reduce) {
  :root { --dur-fast: 0ms; --dur-base: 0ms; }
}
