/* SpriteMaker.ai - Global Styles */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* ----------------------------------------------------------------------
 * Accessibility primitives (SPRITE-496, sweep complete in SPRITE-498)
 *
 * Tokens for the a11y palette live at :root so values aren't repeated
 * inline. These are scoped to a11y primitives, not a backdoor token
 * set for the rest of the app.
 *
 * Conventions enforced here so individual components don't have to
 * re-derive them:
 *   - Visible :focus-visible ring on every interactive element. The
 *     foundation PR (SPRITE-496) had to mark this `!important` because
 *     Tailwind's `.focus\:outline-none:focus` (0,2,0) was sprinkled
 *     across dozens of inputs and outranked the bare `:focus-visible`
 *     (0,1,0) selector. SPRITE-498 swept those `focus:outline-none`
 *     usages out of every component (the <main> skip-link target is
 *     the documented exception — see App.tsx), so the global rule no
 *     longer needs to win the cascade by force. `!important` removed.
 *   - .sr-only utility (Tailwind ships one, but this static stylesheet
 *     can load before Vite injects the compiled Tailwind CSS, so we
 *     keep a local copy as a safety net).
 *   - .skip-link — visually hidden until focused, lands focus on
 *     #main-content. Uses CSS variable tokens (no hardcoded hex).
 *   - prefers-reduced-motion: kill non-essential animation. We strip
 *     transitions/animations broadly because the platform leans on
 *     animate-spin, animate-pulse, gradient transitions, and modal
 *     fades — all decorative.
 * -------------------------------------------------------------------- */

:root {
  /* a11y palette tokens — kept here until the design-system has a real
     CSS-vars surface (SPRITE-453). Values match Tailwind's `cyan-500`,
     `slate-900`, and `white` so the tokens stay in sync with the rest
     of the visual language. */
  --a11y-focus-color: #06b6d4;
  --a11y-skip-link-bg: var(--a11y-focus-color);
  --a11y-skip-link-fg: #0f172a;
  --a11y-skip-link-focus-outline: #ffffff;
}

:focus-visible {
  outline: 2px solid var(--a11y-focus-color);
  outline-offset: 2px;
  border-radius: 2px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  padding: 0.75rem 1rem;
  background: var(--a11y-skip-link-bg);
  color: var(--a11y-skip-link-fg);
  font-weight: 600;
  border-radius: 0 0 0.5rem 0;
  transform: translateY(-100%);
  transition: transform 150ms ease-out;
}

.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--a11y-skip-link-focus-outline);
  outline-offset: 2px;
}

@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;
  }
}

/* ── Brand mascot (Pip) motion ───────────────────────────────────────
   The signature idle hop is a deliberately hard, 2-frame stepped motion —
   it must read as pixel / 8-bit, never a smooth ease. Amplitude is passed
   per-instance via --pip-bob-amp (≈5% of the rendered height); the Pip
   component omits the class below ~24px. The eye-blink hides the .pip-eye
   cells on a long interval. Both are gated behind no-preference (and the
   rule above also neutralises them under reduce). */
@media (prefers-reduced-motion: no-preference) {
  .pip-bob {
    animation: pip-bob var(--pip-bob-dur, 1s) steps(1) infinite;
    will-change: transform;
  }

  @keyframes pip-bob {
    0%,
    49% {
      transform: translateY(0);
    }
    50%,
    100% {
      transform: translateY(calc(-1 * var(--pip-bob-amp, 6px)));
    }
  }

  .pip-blinkAnim .pip-eye {
    animation: pip-eyeblink 3.4s steps(1) infinite;
  }

  @keyframes pip-eyeblink {
    0%,
    94% {
      opacity: 1;
    }
    95%,
    100% {
      opacity: 0;
    }
  }
}

html,
body {
  height: 100%;
  width: 100%;
}

body {
  font-family:
    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
    'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#root {
  height: 100%;
  width: 100%;
}

code {
  font-family:
    source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
}

/* SPRITE-501: .tab-scroll-strip — hides the WebKit scrollbar track on the
 * horizontal tab strip. `scrollbar-width: none` and `-ms-overflow-style: none`
 * live on the component via Tailwind arbitrary properties; this rule handles
 * the pseudo-element that Tailwind can't express. */
.tab-scroll-strip::-webkit-scrollbar {
  display: none;
}

/* Custom scrollbar — themed via the slate ramp so light themes get light
 * tracks instead of a hardcoded dark gutter. */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: var(--slate-800);
}

::-webkit-scrollbar-thumb {
  background: var(--slate-600);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--slate-500);
}

/* ======================================================================
 * Design Token Theme System (SPRITE-Theme)
 * ====================================================================== */

:root {
  /* Default Theme (Sleek Dark Mode) Variables */
  --white: #e9eef5; /* soft near-white — eases glare vs pure #fff (~15:1, was ~18:1) */
  --slate-50: #f8fafc;
  --slate-100: #f1f5f9;
  --slate-200: #e2e8f0;
  --slate-300: #cbd5e1;
  --slate-400: #94a3b8;
  --slate-500: #7e8da3; /* Secondary text — lifted from #64748b (3.7:1) to ~5:1 on #0f172a */
  --slate-600: #475569;
  --slate-700: #334155;
  --slate-800: #1e293b;
  --slate-900: #0f172a;
  --slate-950: #020617;
  --cyan-400: #22d3ee;
  --cyan-500: #06b6d4;
  --cyan-600: #0891b2;
  --cyan-700: #0e7490;
  --gray-900: #111827;

  /* SPRITE-835: the full red/green ramps are backed by vars (like slate/cyan
     above) so themes can retune them. Defaults are the exact Tailwind v3 hex,
     so every non-colourblind theme is pixel-identical; only the colourblind
     themes remap red→orange / green→blue (see the shared theme block below).
     The whole 50–950 ramp is listed — not just the shades used today — so a
     future bg-red-400 / text-green-800 can't escape the remap (PR #840). */
  --red-50: #fef2f2;
  --red-100: #fee2e2;
  --red-200: #fecaca;
  --red-300: #fca5a5;
  --red-400: #f87171;
  --red-500: #ef4444;
  --red-600: #dc2626;
  --red-700: #b91c1c;
  --red-800: #991b1b;
  --red-900: #7f1d1d;
  --red-950: #450a0a;
  --green-50: #f0fdf4;
  --green-100: #dcfce7;
  --green-200: #bbf7d0;
  --green-300: #86efac;
  --green-400: #4ade80;
  --green-500: #22c55e;
  --green-600: #16a34a;
  --green-700: #15803d;
  --green-800: #166534;
  --green-900: #14532d;
  --green-950: #052e16;

  --a11y-focus-color: #06b6d4;
}

/* ----------------------------------------------------------------------
 * Workbench design tokens (design_handoff_hybrid_theme — "D3 workbench
 * layout × D1 slate/cyan finish"). Consumed through the `wb` Tailwind
 * color namespace configured in index.html. The :root block carries the
 * exact spec values; each theme class remaps the vars onto its own
 * palette so the theme switcher keeps working. Accent alpha steps derive
 * from --wb-accent via color-mix so themes only override the base accent.
 * -------------------------------------------------------------------- */

:root {
  --wb-bg: #0f172a;
  --wb-deep: #020617;
  --wb-panel: #111c30;
  --wb-card: #1e293b;
  --wb-line: #27354b;
  --wb-line-soft: #1c2940;
  --wb-text: #e9eef5;
  --wb-sub: #94a3b8;
  --wb-faint: #7e8da3;
  --wb-accent: #22d3ee;
  --wb-accent-deep: #06313c;
  --wb-accent-10: color-mix(in srgb, var(--wb-accent) 10%, transparent);
  --wb-accent-30: color-mix(in srgb, var(--wb-accent) 30%, transparent);
  --wb-accent-45: color-mix(in srgb, var(--wb-accent) 45%, transparent);
  --wb-ok: #34d399;
  --wb-warn: #fbbf24;
  --wb-err: #f87171;
  --wb-translating: #a78bfa;
  --wb-grad-from: #06b6d4;
  --wb-grad-to: #2563eb;
  --wb-checker-a: #16223a;
  --wb-checker-b: #101a2e;
}

/* NOTE: this grouped block does NOT flatten the themes to one palette.
 * Each --wb-* token points at the theme's OWN --slate-* / --cyan-* ramp,
 * and var() resolves at use time against the active theme class. E.g.
 * under .theme-sepia, --wb-bg → --slate-900 → #f4efe6 (warm paper) and
 * --wb-accent → --cyan-400 → #c27803 (amber); under .theme-synthwave the
 * same lines yield #0d061c (obsidian violet) and #f472b6 (hot pink). */
.theme-oled,
.theme-sepia,
.theme-daylight,
.theme-colorblind-dark,
.theme-colorblind-light,
.theme-synthwave {
  --wb-bg: var(--slate-900);
  --wb-deep: var(--slate-950);
  --wb-panel: var(--slate-800);
  --wb-card: var(--slate-700);
  --wb-line: var(--slate-600);
  --wb-line-soft: var(--slate-700);
  --wb-text: var(--white);
  --wb-sub: var(--slate-400);
  --wb-faint: var(--slate-500);
  --wb-accent: var(--cyan-400);
  --wb-accent-deep: var(--slate-950);
  --wb-grad-from: var(--cyan-500);
  --wb-grad-to: var(--cyan-600);
  --wb-checker-a: var(--slate-800);
  --wb-checker-b: var(--slate-900);
}

/* Checkerboard well behind transparent previews (28px tiles per spec). */
.wb-checker {
  background-image: repeating-conic-gradient(
    var(--wb-checker-a) 0% 25%,
    var(--wb-checker-b) 0% 50%
  );
  background-size: 28px 28px;
}

.wb-checker-sm {
  background-image: repeating-conic-gradient(
    var(--wb-checker-a) 0% 25%,
    var(--wb-checker-b) 0% 50%
  );
  background-size: 20px 20px;
}

/* ----------------------------------------------------------------------
 * Docs prose (SPRITE-654)
 * Inline elements rendered from trusted authored HTML inside the docs
 * block renderer (links, inline code, emphasis). Block-level layout and
 * typography are Tailwind utilities on the renderer; only these inline
 * bits need styling that reaches inside dangerouslySetInnerHTML.
 * -------------------------------------------------------------------- */
.docs-prose a {
  color: var(--wb-accent);
  cursor: pointer;
  text-decoration: none;
  border-bottom: 1px solid var(--wb-accent-30);
  transition: border-color 0.15s;
}
.docs-prose a:hover {
  border-bottom-color: var(--wb-accent);
}
.docs-prose code {
  font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
  font-size: 0.86em;
  color: var(--wb-text);
  background: var(--wb-accent-10);
  border: 1px solid var(--wb-line);
  border-radius: 5px;
  padding: 1px 6px;
}
.docs-prose strong {
  color: var(--wb-text);
  font-weight: 650;
}

/* 📜 Sepia Paper Light Theme */
.theme-sepia {
  --white: #1c150c; /* Invert text-white to dark sepia! */
  --slate-50: #1c150c;
  --slate-100: #2d2415;
  --slate-200: #3b301c;
  --slate-300: #4e4027;
  --slate-400: #63512e; /* Muted text — ~6.7:1 on paper */
  --slate-500: #71603e; /* Secondary text — ~5.3:1 on paper */
  --slate-600: #cab894; /* Light borders */
  --slate-700: #dccfb2; /* Active/Hover borders */
  --slate-800: #e8dfcb; /* Card background */
  --slate-900: #f4efe6; /* Main background */
  --slate-950: #faf8f5; /* Deep main background */

  --cyan-400: #c27803; /* Warm amber accents */
  --cyan-500: #b45309;
  --cyan-600: #92400e;
  --cyan-700: #78350f;
  --gray-900: #f4efe6;

  --a11y-focus-color: #b45309;
}

/* ☀️ Daylight Studio Light Theme */
.theme-daylight {
  --white: #0f172a; /* Invert text-white to dark slate ink */
  --slate-50: #0f172a;
  --slate-100: #1e293b;
  --slate-200: #334155;
  --slate-300: #475569;
  --slate-400: #4e5c72; /* Muted text — ~6.5:1 on #f8fafc */
  --slate-500: #5c6b81; /* Secondary text — ~5.2:1 on #f8fafc */
  --slate-600: #cbd5e1; /* Light borders */
  --slate-700: #e2e8f0; /* Active/Hover borders */
  --slate-800: #eef2f7; /* Card background */
  --slate-900: #f8fafc; /* Main background */
  --slate-950: #ffffff; /* Deep main background */

  --cyan-400: #0e7490; /* Deep ocean cyan accents */
  --cyan-500: #0891b2;
  --cyan-600: #155e75;
  --cyan-700: #164e63;
  --gray-900: #f8fafc;

  --a11y-focus-color: #0e7490;
}

/* 👁️ Colorblind Safe Dark Theme */
.theme-colorblind-dark {
  --white: #e9eef5; /* soft near-white — eases glare */
  --slate-50: #f8fafc;
  --slate-100: #f1f5f9;
  --slate-200: #cbd5e1;
  --slate-300: #94a3b8;
  --slate-400: #7c8aa2; /* Muted text — lifted from #64748b (3.7:1) to ~5.5:1 */
  --slate-500: #697590; /* Secondary text — lifted from #475569 (2.5:1) to ~4.1:1 */
  --slate-600: #334155;
  --slate-700: #1e293b;
  --slate-800: #101626; /* Darker navy card */
  --slate-900: #0a0e1a; /* Main navy background */
  --slate-950: #03050a;

  --cyan-400: #60a5fa; /* Distinct sky blue accents */
  --cyan-500: #3b82f6;
  --cyan-600: #2563eb;
  --cyan-700: #1d4ed8;
  --gray-900: #0a0e1a;

  --a11y-focus-color: #f59e0b; /* Distinct amber focus ring */

  /* SPRITE-835: green (--wb-ok) vs red (--wb-err) is exactly the pair
     red-green colour vision deficiency cannot separate. Retune the
     semantic success/danger tokens onto the blue↔orange axis this theme
     is built around — ok = blue, err = orange — so state stays legible
     without relying on the red/green distinction. */
  --wb-ok: #38bdf8;
  --wb-err: #fb923c;
}

/* 👁️ Colorblind Safe Light Theme */
.theme-colorblind-light {
  --white: #101828; /* Invert text-white to dark ink */
  --slate-50: #101828;
  --slate-100: #1d2939;
  --slate-200: #344054;
  --slate-300: #475467;
  --slate-400: #4c596f; /* Muted text — ~6.8:1 on #f9fafb */
  --slate-500: #5a6377; /* Secondary text — ~5.6:1 on #f9fafb */
  --slate-600: #d0d5dd; /* Light borders */
  --slate-700: #e4e7ec; /* Active/Hover borders */
  --slate-800: #f2f4f7; /* Card background */
  --slate-900: #f9fafb; /* Main background */
  --slate-950: #ffffff; /* Deep main background */

  --cyan-400: #1d4ed8; /* Distinct deep blue accents */
  --cyan-500: #2563eb;
  --cyan-600: #1e40af;
  --cyan-700: #1e3a8a;
  --gray-900: #f9fafb;

  --a11y-focus-color: #b45309; /* Distinct amber focus ring */
}

/* ----------------------------------------------------------------------
 * Shared light-theme polish (sepia, daylight, colorblind-light)
 * -------------------------------------------------------------------- */

/* Status hues tuned down for light surfaces — the dark-theme defaults
 * (#34d399 etc.) wash out on paper backgrounds. */
.theme-sepia,
.theme-daylight,
.theme-colorblind-light {
  --wb-ok: #047857;
  --wb-warn: #b45309;
  --wb-err: #dc2626;
  --wb-translating: #7c3aed;
}

/* SPRITE-835: the shared light block above darkens --wb-ok/--wb-err to a
   deep green/red for paper backgrounds — but that's still the green-vs-red
   pair colour-blind users can't tell apart. For the colourblind light
   theme specifically, re-point them onto the blue↔orange axis (deep enough
   for AA contrast on the near-white surface). Placed after the shared block
   so it wins the cascade at equal specificity. */
.theme-colorblind-light {
  --wb-ok: #0369a1;
  --wb-err: #c2410c;
}

/* SPRITE-835 (PR #840): the full semantic red/green ramps, remapped onto the
   blue↔orange axis for BOTH colourblind themes. Shared because the fills carry
   white labels in either theme, so the same deep orange/blue works on the dark
   and near-white surfaces alike. Mapping the whole 50→950 ramp (not just the
   shades used today) means a future bg-red-400 / text-green-800 can't silently
   escape the remap. Tints (50–400) stay light; fills (500+) are deep enough
   for AA white-label contrast. Ordering preserved so hover shade-pairs read as
   hovers. */
.theme-colorblind-dark,
.theme-colorblind-light {
  --red-50: #fff7ed;
  --red-100: #ffedd5;
  --red-200: #fed7aa;
  --red-300: #fdba74;
  --red-400: #f97316;
  --red-500: #c2410c;
  --red-600: #9a3412;
  --red-700: #7c2d12;
  --red-800: #671e0b;
  --red-900: #571908;
  --red-950: #431407;
  --green-50: #f0f9ff;
  --green-100: #e0f2fe;
  --green-200: #bae6fd;
  --green-300: #7dd3fc;
  --green-400: #38bdf8;
  --green-500: #0ea5e9;
  --green-600: #0284c7;
  --green-700: #0369a1;
  --green-800: #075985;
  --green-900: #0c4a6e;
  --green-950: #082f49;
}

/* Light themes remap `text-white` to dark ink for body copy, but solid
 * accent / danger / success / gradient surfaces keep saturated fills —
 * restore true white there so button labels stay legible. Green is included
 * (SPRITE-835): its solid buttons carry white labels too, and under the
 * colourblind-light theme green is remapped to a deep blue where dark ink
 * would be unreadable. */
:is(.theme-sepia, .theme-daylight, .theme-colorblind-light)
  :is(
    .bg-cyan-500,
    .bg-cyan-600,
    .bg-cyan-700,
    .bg-red-500,
    .bg-red-600,
    .bg-red-700,
    .bg-green-500,
    .bg-green-600,
    .bg-green-700,
    .bg-wb-gradient
  ),
:is(.theme-sepia, .theme-daylight, .theme-colorblind-light)
  :is(
    .bg-cyan-500,
    .bg-cyan-600,
    .bg-cyan-700,
    .bg-red-500,
    .bg-red-600,
    .bg-red-700,
    .bg-green-500,
    .bg-green-600,
    .bg-green-700,
    .bg-wb-gradient
  )
  .text-white {
  color: #ffffff;
}

/* 🌌 Synthwave Neon Theme */
.theme-synthwave {
  --white: #f4ecff; /* soft violet-white — eases glare, keeps the neon tint */
  --slate-50: #faf5ff;
  --slate-100: #f3e8ff;
  --slate-200: #e9d5ff;
  --slate-300: #d8b4fe;
  --slate-400: #c084fc; /* Neon purple text */
  --slate-500: #a855f7;
  --slate-600: #3e1f75;
  --slate-700: #2c1654;
  --slate-800: #160c2d; /* Violet card background */
  --slate-900: #0d061c; /* Obsidian background */
  --slate-950: #06020c;

  --cyan-400: #f472b6; /* Vaporwave hot pink accents! */
  --cyan-500: #ec4899;
  --cyan-600: #db2777;
  --cyan-700: #be185d;
  --gray-900: #0d061c;

  --a11y-focus-color: #ec4899;
}

/* Synthwave Glowing Effects */
.theme-synthwave .bg-slate-800 {
  box-shadow: 0 0 15px rgba(236, 72, 153, 0.08);
  border: 1px solid rgba(236, 72, 153, 0.25) !important;
}

.theme-synthwave button.bg-cyan-600 {
  background: linear-gradient(135deg, #ec4899 0%, #8b5cf6 100%) !important;
  box-shadow: 0 0 15px rgba(236, 72, 153, 0.4) !important;
  border: 1px solid rgba(255, 255, 255, 0.2) !important;
  transition: all 0.2s ease-out !important;
}

.theme-synthwave button.bg-cyan-600:hover:not(:disabled) {
  box-shadow: 0 0 25px rgba(236, 72, 153, 0.6) !important;
  filter: brightness(1.1);
}

.theme-synthwave .text-cyan-400 {
  color: #f472b6 !important;
  text-shadow: 0 0 8px rgba(244, 114, 182, 0.3);
}

/* ⚫ OLED True Black Theme
 * Pure #000000 primary backgrounds to save power on OLED panels and offer a
 * higher-contrast dark option. Backgrounds (slate-900/950) are true black;
 * surfaces step up via subtly elevated slate-tinted grays (slate-800/700) and
 * a divider (slate-600) tuned to ~2.4:1 on black — matching the default dark
 * theme's border visibility so panels and dividers stay legible. Text, icons,
 * and the cyan accent clear WCAG AA on pure black (≈7:1 secondary text up to
 * ≈19:1 primary; ≈11.6:1 accent). --wb-* tokens derive from this ramp via the
 * shared remap block above. */
.theme-oled {
  --white: #f2f5fb; /* Primary text — bright near-white, ~19:1 on black */
  --slate-50: #f8fafc;
  --slate-100: #f1f5f9;
  --slate-200: #e2e8f0;
  --slate-300: #cbd5e1;
  --slate-400: #aab4c4; /* Muted text — ~10:1 on pure black */
  --slate-500: #8b97a8; /* Secondary text — ~7:1 on pure black */
  --slate-600: #424b5c; /* Borders / dividers — ~2.4:1, matches default dark */
  --slate-700: #232a34; /* Card / hover border — first elevation above panel */
  --slate-800: #15191f; /* Panel — subtly elevated above true black */
  --slate-900: #000000; /* Main background — true black */
  --slate-950: #000000; /* Deep background — true black */

  --cyan-400: #22d3ee; /* Cyan accents — ~11.6:1 on black */
  --cyan-500: #06b6d4;
  --cyan-600: #0891b2;
  --cyan-700: #0e7490;
  --gray-900: #000000;

  --a11y-focus-color: #22d3ee;
}
