/* Self-hosted display + body fonts (Outfit, Nunito — SIL Open Font License). */
@font-face { font-family: "Outfit"; font-weight: 700; font-display: swap; src: url("/assets/fonts/outfit-700.woff2") format("woff2"); }
@font-face { font-family: "Outfit"; font-weight: 800; font-display: swap; src: url("/assets/fonts/outfit-800.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-weight: 600; font-display: swap; src: url("/assets/fonts/nunito-600.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-weight: 700; font-display: swap; src: url("/assets/fonts/nunito-700.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-weight: 800; font-display: swap; src: url("/assets/fonts/nunito-800.woff2") format("woff2"); }

/* Game-scale root: UI is a constant fraction of window height (clamped).
   Deck 800p → 18px, 1080p → ~24.3px, ≥1440p → 30px, floor 14.4px.
   Only this rule may set the root font-size. */
html { font-size: clamp(14.4px, 2.25vh, 30px); }

/* Pattern Pop tokens — single source of truth for UI color/geometry/patterns.
   src/shared/theme.ts mirrors the color tokens; test/theme-parity.test.ts
   asserts they never drift. Meadow = :root, Ink = html[data-theme="dark"]. */
:root {
  color-scheme: light;
  --pp-bg: #f4f8f7;
  --pp-surface: #ffffff;
  --pp-well: #e9efee;
  --pp-hairline: #eef3f2;
  --pp-ink: #22343c;
  --pp-muted: #7d919b;
  --pp-label: #9ab0ba;
  --pp-primary: #ff5c47;
  --pp-primary-deep: #d9412e;
  --pp-secondary: #2fd0c4;
  --pp-secondary-deep: #1ba99e;
  --pp-secondary-well: #d9f5f2;
  --pp-secondary-text: #0f8c82;
  --pp-danger: #e8484d;
  --pp-danger-deep: #c23438;
  --pp-disabled: #dde4e3;
  --pp-disabled-text: #96a5a3;
  --pp-toast-bg: #22343c;
  --pp-toast-text: #ffffff;
  --pp-gold: #ffc233;
  --pp-focus: #1ba99e;
  --pp-on-accent: #ffffff;
  --pp-on-secondary: #063c37;
  --pp-lift: 0 2px 6px rgba(18, 42, 54, 0.10);
  /* dark-text-on-mint emboss; Ink disables it (white halo under bright text) */
  --pp-press-up: 0 0.0625rem 0 rgba(255, 255, 255, 0.45);
  --pp-pat-on-primary: rgba(255, 255, 255, 0.16);
  --pp-pat-on-secondary: rgba(255, 255, 255, 0.30);
  --pp-pat-faint: rgba(34, 52, 60, 0.035);
  --pp-pat-soft: rgba(34, 52, 60, 0.10);
  --pp-pat-mid: rgba(34, 52, 60, 0.16);
  --pp-scroll-thumb: rgba(34, 52, 60, 0.30);
  --pp-chevron: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='8'%3E%3Cpath%20d='M1%201l5%205%205-5'%20fill='none'%20stroke='%2322343c'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E");
  --pp-page-pattern: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='64'%20height='64'%3E%3Cg%20fill='%2322343c'%20fill-opacity='.035'%3E%3Ccircle%20cx='15'%20cy='14'%20r='4.5'/%3E%3Ccircle%20cx='22'%20cy='14'%20r='4.5'/%3E%3Ccircle%20cx='18.5'%20cy='8.5'%20r='4.5'/%3E%3Cellipse%20cx='46'%20cy='44'%20rx='6'%20ry='7.5'/%3E%3Cpath%20d='M46%2051l-2%204h4z'/%3E%3C/g%3E%3C/svg%3E");
  --pp-radius-sm: 0.625rem;
  --pp-radius-icon: 0.75rem;
  --pp-radius-md: 0.875rem;
  --pp-radius-lg: 1.125rem;
  --pp-radius-pill: 999px;
  --pp-font-display: "Outfit", system-ui, sans-serif;
  --pp-font-body: "Nunito", system-ui, sans-serif;
}
html[data-theme="dark"] {
  color-scheme: dark;
  --pp-bg: #151f2b;
  --pp-surface: #202d3c;
  --pp-well: #2b3a4b;
  --pp-hairline: #2b3a4b;
  --pp-ink: #eef5f7;
  --pp-muted: #8fa4b4;
  --pp-label: #6d8496;
  --pp-primary: #ff5c47;
  --pp-primary-deep: #b93825;
  --pp-secondary: #35e0c8;
  --pp-secondary-deep: #17ab97;
  --pp-secondary-well: #163f44;
  --pp-secondary-text: #4fe3d0;
  --pp-danger: #ff5f66;
  --pp-danger-deep: #c73b42;
  --pp-disabled: #2b3a4b;
  --pp-disabled-text: #64798c;
  --pp-toast-bg: #0d141d;
  --pp-toast-text: #eef5f7;
  --pp-gold: #ffc233;
  --pp-focus: #4fe3d0;
  --pp-on-accent: #ffffff;
  --pp-on-secondary: #063c37;
  --pp-lift: 0 3px 8px rgba(0, 0, 0, 0.35);
  --pp-press-up: none;
  --pp-pat-on-primary: rgba(255, 255, 255, 0.22);
  --pp-pat-on-secondary: rgba(0, 0, 0, 0.18);
  --pp-pat-faint: rgba(255, 255, 255, 0.035);
  --pp-pat-soft: rgba(255, 255, 255, 0.07);
  --pp-pat-mid: rgba(255, 255, 255, 0.14);
  --pp-scroll-thumb: rgba(255, 255, 255, 0.25);
  --pp-chevron: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='8'%3E%3Cpath%20d='M1%201l5%205%205-5'%20fill='none'%20stroke='%23eef5f7'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E");
  --pp-page-pattern: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%3E%3Ccircle%20cx='2'%20cy='2'%20r='1.2'%20fill='%23ffffff'%20fill-opacity='.035'/%3E%3C/svg%3E");
}

/* Game-scale sizing tokens + pattern recipes (consume theme-aware alphas above) */
:root {
  --pp-text-label: 0.75rem;
  --pp-text-sm: 0.875rem;
  --pp-text-body: 1rem;
  --pp-text-xl: 1.125rem;
  --pp-text-hero: 1.25rem;
  --pp-text-title: 1.5rem;
  --pp-ctl-chip: 1.75rem;
  --pp-ctl-icon: 2.25rem;
  --pp-ctl-input: 2.25rem;
  --pp-ctl-md: 2.5rem;
  --pp-ctl-row: 2.75rem;
  --pp-ctl-xl: 3.25rem;
  --pp-space-1: 0.25rem;
  --pp-space-2: 0.5rem;
  --pp-space-3: 0.75rem;
  --pp-space-4: 1rem;
  --pp-space-5: 1.5rem;
  --pp-rail-left: 14rem;
  --pp-rail-right: 12.5rem;
  --pp-edge: 0.22rem;
  --pp-edge-pressed: 0.09rem;
  --pp-stripe: repeating-linear-gradient(45deg, var(--pp-pat-on-primary) 0 0.5rem, transparent 0.5rem 1.25rem);
  /* One horizontal period of the 45deg/1.25rem stripe (1.25 * sqrt2). Every
     --pp-stripe surface MUST set background-size to this square tile so tile
     edges are period-aligned, and pp-stripe-move shifts exactly one tile —
     otherwise the element-box tile shows a moving vertical seam when
     background-position animates. */
  --pp-stripe-tile: 1.7678rem;
  --pp-stripe-faint: repeating-linear-gradient(45deg, var(--pp-pat-faint) 0 0.375rem, transparent 0.375rem 1rem);
  --pp-halftone: radial-gradient(var(--pp-pat-soft) 0.08rem, transparent 0.11rem);
  --pp-halftone-on-secondary: radial-gradient(var(--pp-pat-on-secondary) 0.07rem, transparent 0.1rem);
  /* Candy gloss (2026-07-06 round-9 pick, level S2): a hard-stop glass band
     layered OVER pattern fills — never instead of them — plus hairline
     top-light/bottom-bite insets and letterpress on accent text. Saturated
     interactive fills only; wells, surfaces, and neutral chips stay flat.
     Glossed stripe surfaces need the two-layer background-size (see
     test/scale-tokens.test.ts). */
  --pp-gloss: linear-gradient(180deg, rgba(255, 255, 255, 0.50) 0%, rgba(255, 255, 255, 0.16) 46%, rgba(255, 255, 255, 0) 54%);
  --pp-gloss-soft: linear-gradient(180deg, rgba(255, 255, 255, 0.38) 0%, rgba(255, 255, 255, 0.12) 46%, rgba(255, 255, 255, 0) 54%);
  --pp-gloss-inset: inset 0 0.0625rem 0 rgba(255, 255, 255, 0.55), inset 0 -0.0625rem 0 rgba(0, 0, 0, 0.10);
  --pp-press: 0 -0.0625rem 0 rgba(0, 0, 0, 0.22);
}

@keyframes pp-stripe-move { to { background-position: var(--pp-stripe-tile) 0; } }
@keyframes pp-drift { to { background-position: 640px 384px; } }
/* balloon grammar: UI inflates in, deflates out */
@keyframes pp-inflate { from { transform: scale(0.94); opacity: 0; } 60% { transform: scale(1.02); } to { transform: scale(1); opacity: 1; } }
@keyframes pp-deflate { from { transform: scale(1); opacity: 1; } to { transform: scale(0.94); opacity: 0; } }

.pp-stripe-anim { background-size: var(--pp-stripe-tile) var(--pp-stripe-tile); animation: pp-stripe-move 1.1s linear infinite; }

@media (prefers-reduced-motion: reduce) {
  .pp-stripe-anim { animation: none; }
  body { animation: none !important; }
}
