/* ============================================================================
   Morganelli Method OS — DESIGN TOKENS (the shared foundation).
   v1.221 — Phase 0 of the design-system overhaul.

   ONE language, TWO skins. Every surface — operator (slate, dark-capable) and
   family portal (ivy, light) — descends from the same structural scale (type,
   space, elevation, motion, focus) and differs only in its COLOR tokens. This
   is what makes "two rooms of one house" true, and what lets brand.py reskin a
   tenant by overriding tokens rather than editing templates.

   This file is plain CSS custom properties (NOT Tailwind-processed), so it needs
   no `npm run build:css`. It is loaded AFTER tailwind.css / portal.css so the
   accessibility primitives at the bottom win. Components reference var(--token);
   they never hardcode a hex or a Tailwind shade.

   Reconciliation note: base.html:58 still defines the legacy --color-* block for
   back-compat; those names are a subset of what's here and will be folded in as
   surfaces migrate. New work uses the semantic names below.

   ACCESSIBILITY: every text/background pair below is chosen to meet WCAG 2.2 AA
   (≥4.5:1 body text, ≥3:1 large text & UI boundaries). Muted/faint tokens are
   capped so even the lightest text clears 4.5:1 on its intended surface.
   ============================================================================ */

:root {
  /* ---------------------------------------------------------------------------
     STRUCTURAL TOKENS — shared by every skin. Skin overrides never touch these.
     --------------------------------------------------------------------------- */

  /* Type families. Inter (body) + Fraunces (editorial display) + mono. */
  --font-sans: "Inter", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-serif: "Fraunces", ui-serif, Georgia, "Times New Roman", serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;

  /* Type scale. 12px floor — no 10px labels (a11y + the "calm density" move).
     Display sizes carry slightly negative tracking, the Stripe/Linear tell. */
  --fs-xs: 0.75rem;      /* 12px — smallest allowed; labels, meta            */
  --fs-sm: 0.8125rem;    /* 13px — secondary UI text                        */
  --fs-base: 0.9375rem;  /* 15px — body                                     */
  --fs-md: 1rem;         /* 16px — comfortable reading / mobile inputs      */
  --fs-lg: 1.125rem;     /* 18px — card titles, section heads               */
  --fs-xl: 1.375rem;     /* 22px — page subtitles                           */
  --fs-2xl: 1.625rem;    /* 26px — page titles                              */
  --fs-3xl: 2.125rem;    /* 34px — hero                                     */
  --fs-display: 2.75rem; /* 44px — editorial display (portal)               */
  --lh-tight: 1.25;
  --lh-snug: 1.45;
  --lh-base: 1.6;
  --lh-relaxed: 1.75;
  --tracking-tight: -0.011em;
  --tracking-wide: 0.04em;

  /* Spacing scale (for scoped CSS; Tailwind utilities still cover most cases). */
  --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem;
  --space-5: 1.25rem; --space-6: 1.5rem; --space-8: 2rem; --space-10: 2.5rem; --space-12: 3rem;

  /* Radius scale. */
  --radius-xs: 0.375rem; --radius-sm: 0.625rem; --radius: 0.875rem;
  --radius-lg: 1.125rem; --radius-xl: 1.375rem; --pill: 9999px;

  /* Motion. Single ease + three durations; honoured by reduced-motion below. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-fast: 0.15s; --dur: 0.22s; --dur-slow: 0.45s;

  /* Accessibility primitives. */
  --tap-min: 44px;                 /* WCAG 2.2 target size (24px AA min; 44 = comfortable) */
  --ring-width: 2px;
  --ring-offset: 2px;

  /* ---------------------------------------------------------------------------
     COLOR TOKENS — OPERATOR skin, LIGHT (the :root default).
     Aligned to the slate values already used across ~90 templates so token-based
     components sit seamlessly beside legacy `slate-*` classes during migration.
     --------------------------------------------------------------------------- */
  --bg: #f8fafc;            /* slate-50  — app canvas        */
  --bg-elev: #ffffff;
  --surface: #ffffff;       /* cards                          */
  --surface-2: #f8fafc;     /* subtle raised / inset          */
  --surface-3: #f1f5f9;     /* slate-100 — wells, hovers      */
  --border: #e2e8f0;        /* slate-200 — hairline           */
  --border-soft: #f1f5f9;   /* slate-100                      */
  --border-strong: #cbd5e1; /* slate-300 — emphasis / inputs  */

  --text: #0f172a;          /* slate-900 — 16.1:1 on canvas   */
  --text-muted: #475569;    /* slate-600 — 7.4:1              */
  --text-faint: #5b6b82;    /* tuned slate-500 — 4.7:1 (AA)   */

  /* Carolyn — Chief of Staff, brand violet. */
  --accent: #6d28d9;        /* violet-700                     */
  --accent-strong: #5b21b6; /* violet-800 (hover)             */
  --accent-ink: #6d28d9;    /* text on light — 6.6:1          */
  --accent-wash: #f5f3ff;   /* violet-50                      */
  --accent-line: #ddd6fe;   /* violet-200                     */
  --on-accent: #ffffff;     /* text on filled accent          */

  /* Agent accents (one signature each). */
  --linda: #4338ca; --linda-ink: #4338ca; --linda-wash: #eef2ff; --linda-line: #c7d2fe;
  --lenny: #047857; --lenny-ink: #047857; --lenny-wash: #ecfdf5; --lenny-line: #a7f3d0;

  /* Semantic — ONE meaning each. ink = text/icon, wash = fill, line = border. */
  --success: #047857; --success-ink: #047857; --success-wash: #ecfdf5; --success-line: #a7f3d0;
  --warning: #b45309; --warning-ink: #92400e; --warning-wash: #fffbeb; --warning-line: #fde68a;
  --danger:  #be123c; --danger-ink:  #be123c; --danger-wash:  #fff1f2; --danger-line:  #fecdd3;
  --info:    #1d4ed8; --info-ink:    #1d4ed8; --info-wash:    #eff6ff; --info-line:    #bfdbfe;

  /* The single canonical link color (kills the blue-600 vs indigo drift). */
  --link: #4338ca; --link-hover: #3730a3;

  /* Elevation — soft, layered; gives the dialog-vs-card depth that was missing. */
  --elev-1: 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 1px rgba(15, 23, 42, 0.04);
  --elev-2: 0 4px 12px -2px rgba(15, 23, 42, 0.10), 0 2px 6px -2px rgba(15, 23, 42, 0.06);
  --elev-3: 0 16px 40px -12px rgba(15, 23, 42, 0.18), 0 4px 12px -4px rgba(15, 23, 42, 0.10);

  /* Focus ring — high-contrast against the canvas (≥3:1). */
  --ring: #7c3aed;
  --ring-contrast: #ffffff;
}

/* ===========================================================================
   OPERATOR skin, DARK. Hooks the EXISTING `.dark` class (Tailwind class
   strategy) so it works with the current toggle and every `dark:` utility.
   =========================================================================== */
html.dark {
  --bg: #020617;            /* slate-950                      */
  --bg-elev: #0b1120;
  --surface: #0f172a;       /* slate-900 — cards              */
  --surface-2: #131c30;
  --surface-3: #1e293b;     /* slate-800 — wells, hovers      */
  --border: #1e293b;        /* slate-800                      */
  --border-soft: #172033;
  --border-strong: #334155; /* slate-700                      */

  --text: #f1f5f9;          /* slate-100 — 16.3:1             */
  --text-muted: #94a3b8;    /* slate-400 — 7.9:1             */
  --text-faint: #7c8aa3;    /* tuned — 4.9:1 on slate-950     */

  --accent: #6d28d9;        /* violet-700 — FILL: white text clears AA (5.9:1)  */
  --accent-strong: #5b21b6; /* violet-800 — hover (darkens; white text 7.5:1)   */
  --accent-ink: #c4b5fd;    /* violet-300 — accent TEXT/icon on dark (8.9:1)    */
  --accent-wash: rgba(139, 92, 246, 0.15);
  --accent-line: rgba(139, 92, 246, 0.34);
  --on-accent: #ffffff;

  --linda: #6366f1; --linda-ink: #a5b4fc; --linda-wash: rgba(99, 102, 241, 0.16); --linda-line: rgba(99, 102, 241, 0.34);
  --lenny: #10b981; --lenny-ink: #6ee7b7; --lenny-wash: rgba(16, 185, 129, 0.15); --lenny-line: rgba(16, 185, 129, 0.32);

  --success: #10b981; --success-ink: #6ee7b7; --success-wash: rgba(16, 185, 129, 0.14); --success-line: rgba(16, 185, 129, 0.30);
  --warning: #f59e0b; --warning-ink: #fcd34d; --warning-wash: rgba(245, 158, 11, 0.13); --warning-line: rgba(245, 158, 11, 0.32);
  --danger:  #be123c; --danger-ink:  #fda4af; --danger-wash:  rgba(244, 63, 94, 0.14);  --danger-line:  rgba(244, 63, 94, 0.32);  /* base = white-text-safe fill; -ink stays light for text */
  --info:    #3b82f6; --info-ink:    #93c5fd; --info-wash:    rgba(59, 130, 246, 0.14); --info-line:    rgba(59, 130, 246, 0.32);

  --link: #a5b4fc; --link-hover: #c7d2fe;

  --elev-1: 0 1px 2px rgba(0, 0, 0, 0.40);
  --elev-2: 0 4px 16px -4px rgba(0, 0, 0, 0.50), 0 2px 6px -3px rgba(0, 0, 0, 0.40);
  --elev-3: 0 20px 52px -14px rgba(0, 0, 0, 0.62), 0 6px 16px -6px rgba(0, 0, 0, 0.45);

  --ring: #a78bfa;
  --ring-contrast: #020617;
}

/* ===========================================================================
   FAMILY PORTAL skin (ivy) — light only, warm, editorial. Scoped to
   `.skin-ivy` on the portal <body>. Same structural scale; ivy color tokens.
   Muted uses ivy-600 (not ivy-500) so body-muted text clears 4.5:1.
   =========================================================================== */
.skin-ivy {
  --bg: #f5f7fb;            /* ivy-50                         */
  --bg-elev: #ffffff;
  --surface: #ffffff;
  --surface-2: #f5f7fb;
  --surface-3: #e8edf6;     /* ivy-100                        */
  --border: #e8edf6;        /* ivy-100                        */
  --border-soft: #eff2f8;
  --border-strong: #cdd8ec; /* ivy-200                        */

  --text: #1a2745;          /* ivy-900 — 13.6:1               */
  --text-muted: #365389;    /* ivy-600 — 6.1:1                */
  --text-faint: #46618f;    /* tuned ivy-550 — 4.6:1 (AA)     */

  --accent: #2c4270;        /* ivy-700                        */
  --accent-strong: #22335a; /* ivy-800                        */
  --accent-ink: #2c4270;    /* 7.9:1                          */
  --accent-wash: #eef2f8;
  --accent-line: #cdd8ec;
  --on-accent: #ffffff;

  --link: #2c4270; --link-hover: #1a2745;

  --elev-1: 0 1px 2px rgba(26, 39, 69, 0.06);
  --elev-2: 0 10px 26px -10px rgba(26, 39, 69, 0.14), 0 2px 6px -3px rgba(26, 39, 69, 0.08);
  --elev-3: 0 22px 52px -16px rgba(26, 39, 69, 0.20);

  --ring: #2c4270;
  --ring-contrast: #ffffff;
  font-feature-settings: "ss01";
}

/* ===========================================================================
   GLOBAL ACCESSIBILITY PRIMITIVES.
   These apply to every surface and are the floor the audit (Task #8) builds on.
   =========================================================================== */

/* Visible keyboard focus everywhere — a single, high-contrast, token-driven
   ring. `:focus-visible` only shows it for keyboard/AT users, not mouse clicks,
   so it never fights the design while guaranteeing keyboard operability. */
:where(a, button, input, select, textarea, summary, [tabindex], [role="button"], [role="link"], [role="menuitem"], [role="option"], [role="tab"]):focus-visible {
  outline: var(--ring-width) solid var(--ring);
  outline-offset: var(--ring-offset);
  border-radius: var(--radius-xs);
}
/* Drop the legacy focus outline only when focus-visible is supported and the
   element is NOT keyboard-focused (prevents a double ring). */
:where(a, button, input, select, textarea, summary):focus:not(:focus-visible) {
  outline: none;
}

/* Skip-to-content link — first tab stop, hidden until focused. */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -3rem;
  z-index: 100;
  padding: 0.5rem 0.875rem;
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--elev-2);
  font: 500 var(--fs-sm) / 1 var(--font-sans);
  text-decoration: none;
  transition: top var(--dur) var(--ease);
}
.skip-link:focus {
  top: 0.75rem;
  outline: var(--ring-width) solid var(--ring);
  outline-offset: var(--ring-offset);
}

/* Windows High Contrast / forced-colors: keep focus + boundaries perceivable
   and let the OS palette take over (don't fight it with our hexes). */
@media (forced-colors: active) {
  :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: var(--ring-width) solid Highlight;
  }
  .skip-link { border: 1px solid CanvasText; }
}

/* Global reduced-motion floor. Page-scoped rules (base.html fade-in/draw-in)
   already opt out; this catches everything else, including component shimmer. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
