/* playful.css - Playful Design System
 * Loaded before user styles.css. Provides Playful design tokens.
 */

/* Declare the cascade-layer order up front so it matches Tailwind v4's own
 * `@layer theme, base, components, utilities`. Generated apps load Tailwind v4
 * (@tailwindcss/browser@4), which puts every utility in `@layer utilities`.
 * The base resets below therefore live in `@layer base`, so app-authored
 * Tailwind spacing utilities (p-*, m-*, …) still win. An UNLAYERED reset would
 * beat every layered utility regardless of specificity and silently zero them
 * out — see the padding/margin collapse this replaced. */
@layer theme, base, components, utilities;

/* ============================================
 * 0. Base reset
 * ============================================
 * 83/99 recent prod projects re-wrote this verbatim. Centralizing here lets
 * apps skip the boilerplate without sacrificing Tailwind compatibility
 * (Tailwind Preflight does its own reset, but it does NOT zero margin/padding
 * on every element — apps still had to).
 */
@layer base {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
  }
}

/* ============================================
 * 1. Typography
 * ============================================
 * Inter is loaded via Google Fonts in the preamble.
 */
:root {
  /* Safe-area insets — non-zero when viewport-fit=cover is active (iOS Safari).
   * Use these to offset fixed/absolute elements away from the notch, home
   * indicator, or address-bar overlap zone. */
  --playful-safe-top: env(safe-area-inset-top, 0px);
  --playful-safe-right: env(safe-area-inset-right, 0px);
  --playful-safe-bottom: env(safe-area-inset-bottom, 0px);
  --playful-safe-left: env(safe-area-inset-left, 0px);

  /* Font stacks */
  --playful-font-sans: 'Inter', system-ui, -apple-system, sans-serif;
  --playful-font-mono: ui-monospace, 'Cascadia Code', 'Fira Code', monospace;

  /* Type scale (~1.25 ratio) */
  --playful-text-xs: 0.75rem; /* 12px */
  --playful-text-sm: 0.875rem; /* 14px */
  --playful-text-base: 1rem; /* 16px */
  --playful-text-lg: 1.125rem; /* 18px */
  --playful-text-xl: 1.25rem; /* 20px */
  --playful-text-2xl: 1.5rem; /* 24px */
  --playful-text-3xl: 1.875rem; /* 30px */
  --playful-text-4xl: 2.25rem; /* 36px */
  --playful-text-5xl: 3rem; /* 48px */

  /* Line heights */
  --playful-leading-none: 1;
  --playful-leading-tight: 1.25;
  --playful-leading-snug: 1.375;
  --playful-leading-normal: 1.5;
  --playful-leading-relaxed: 1.625;

  /* Font weights */
  --playful-font-light: 300;
  --playful-font-normal: 400;
  --playful-font-medium: 500;
  --playful-font-semibold: 600;
  --playful-font-bold: 700;
}

@layer base {
  html,
  body {
    /* Disable both scroll-chaining and the iOS elastic "rubber-band" bounce.
       Without this, tapping and dragging on a non-scrollable spot inside the
       iframe causes the host viewport to rubber-band on iOS. */
    overscroll-behavior: none;
  }

  body {
    font-family: var(--playful-font-sans);
    /* Subpixel font rendering on macOS / iOS (46/99 apps set this manually). */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* Keep normal-flow content above the iOS home indicator / address-bar
       overlap zone when viewport-fit=cover is active. Fixed-position
       elements must handle their own offset via --playful-safe-bottom. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  /* Interactive controls: avoid the 300ms tap delay and accidental pinch-zoom
     on mobile. 40/99 prod apps set this manually on individual buttons. */
  button {
    touch-action: manipulation;
  }
}

/* ============================================
 * 2. Shadow / Elevation
 * ============================================ */
:root {
  --playful-shadow-xs: 0 1px 2px oklch(0% 0 0 / 0.05);
  --playful-shadow-sm: 0 1px 3px oklch(0% 0 0 / 0.1), 0 1px 2px oklch(0% 0 0 / 0.06);
  --playful-shadow-md: 0 4px 6px oklch(0% 0 0 / 0.1), 0 2px 4px oklch(0% 0 0 / 0.06);
  --playful-shadow-lg: 0 10px 15px oklch(0% 0 0 / 0.1), 0 4px 6px oklch(0% 0 0 / 0.05);
  --playful-shadow-xl: 0 20px 25px oklch(0% 0 0 / 0.1), 0 8px 10px oklch(0% 0 0 / 0.04);
  --playful-shadow-2xl: 0 25px 50px oklch(0% 0 0 / 0.25);
}

/* ============================================
 * 3. Surface Utilities
 * ============================================
 * Hue-neutral utilities for overlays, scrims, glassmorphic cards.
 * Safe to use regardless of the app's palette.
 */
:root {
  --playful-surface-overlay: oklch(0% 0 0 / 0.5);
  --playful-surface-glass: oklch(100% 0 0 / 0.8);
  --playful-surface-scrim: oklch(0% 0 0 / 0.3);
}

/* ============================================
 * 4. Dialog primitive
 * ============================================
 * Native <dialog> positioning is fragile: the UA stylesheet centers
 * via `margin: auto`, but Tailwind Preflight and utility classes can
 * neutralize that and pin the dialog to the top-left. This class
 * locks in a safe centered layout plus a default backdrop.
 *
 * Usage: <dialog class="playful-dialog"> ... </dialog>
 * Open with dialog.showModal(); close with dialog.close().
 */
.playful-dialog {
  margin: auto;
  padding: 0.5rem;
  border: none;
  background: white;
  border-radius: 1rem;
  max-width: min(92vw, 560px);
  max-height: 90vh;
  overflow: visible;
}
.playful-dialog::backdrop {
  background: var(--playful-surface-overlay);
}

/* ============================================
 * 5. Toast animation keyframes
 * ============================================
 * Reusable slide-in / slide-out for transient toast messages.
 * Apply to the toast element; style everything else (color, size,
 * position) with Tailwind utilities or your own app styles.
 *
 * Usage: animation: playful-toast-in 0.3s ease forwards;
 */
@keyframes playful-toast-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes playful-toast-out {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(12px);
  }
}

/* ============================================
 * 6. Animation keyframes
 * ============================================
 * Common entrance / loop animations. Reuse via
 * `animation: playful-X <duration> <timing> ...;`.
 *
 * - `playful-spin`     — full rotation (loading indicators)
 * - `playful-fade-in`  — simple opacity 0 → 1
 * - `playful-rise-in`  — fade in while sliding up 16px (cards, lists)
 * - `playful-pulse`    — opacity 1 ⇄ 0.5 (live indicators, skeleton)
 */
@keyframes playful-spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes playful-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes playful-rise-in {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes playful-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

/* ============================================
 * 7. Utility classes
 * ============================================ */

/* Single-line ellipsis. Tailwind's `truncate` does the same thing; this is
   for apps that prefer a semantic class on a CSS-styled component. */
.playful-truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Visually hidden, still accessible to screen readers. Standard a11y pattern.
   Use for icon-only buttons that need a text label:
   `<button>Save<span class="playful-sr-only"> document</span></button>`. */
.playful-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;
}

/* Prevent text selection (drag-game pieces, custom controls). */
.playful-no-select {
  -webkit-user-select: none;
  user-select: none;
}

/* ============================================
 * 8. Spinner component
 * ============================================
 * Tiny CSS spinner. Size via `--playful-spinner-size` (default 24px); color
 * inherits via `currentColor`, so set `color: var(--primary)` on the parent.
 *
 * Usage: <div class="playful-spinner" aria-label="Loading"></div>
 */
.playful-spinner {
  width: var(--playful-spinner-size, 24px);
  height: var(--playful-spinner-size, 24px);
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: playful-spin 0.8s linear infinite;
  /* Dim the ring so the spinning gap reads clearly. */
  opacity: 0.6;
}

/* ============================================
 * 9. Scrollbar utilities
 * ============================================ */
.playful-scrollbar-hidden {
  scrollbar-width: none;
}
.playful-scrollbar-hidden::-webkit-scrollbar {
  display: none;
}

.playful-scrollbar-thin {
  scrollbar-width: thin;
  scrollbar-color: currentColor transparent;
}
.playful-scrollbar-thin::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.playful-scrollbar-thin::-webkit-scrollbar-thumb {
  background: currentColor;
  border-radius: 3px;
  opacity: 0.4;
}

/* ============================================
 * 10. Toast component
 * ============================================
 * Container is appended to <body> by playful.js when `playful.ui.toast()`
 * is first called. Individual toasts inherit app palette via `currentColor`
 * and the `--playful-surface-*` neutrals.
 *
 * 75/99 recent prod apps hand-rolled this triple (HTML + CSS + JS); use
 * `playful.ui.toast(msg)` instead.
 */
.playful-toast-container {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 24px);
  transform: translateX(-50%);
  z-index: 2147483000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  max-width: calc(100vw - 32px);
}
.playful-toast {
  pointer-events: auto;
  background: #1a1a1a;
  color: #ffffff;
  padding: 10px 18px;
  border-radius: 999px;
  font-family: var(--playful-font-sans);
  font-size: var(--playful-text-sm);
  font-weight: var(--playful-font-medium);
  line-height: var(--playful-leading-snug);
  box-shadow: var(--playful-shadow-lg);
  max-width: 100%;
  text-align: center;
  word-wrap: break-word;
  animation: playful-toast-in 0.25s ease forwards;
}
.playful-toast[data-variant='success'] {
  background: #1f7a4f;
}
.playful-toast[data-variant='error'] {
  background: #b8332f;
}
.playful-toast[data-variant='warning'] {
  background: #b76d0a;
}
.playful-toast[data-closing] {
  animation: playful-toast-out 0.25s ease forwards;
}
