# ThrillWiki Design System Last Updated: 2025-01-15 ## Overview A comprehensive design system for ThrillWiki that combines modern aesthetics with exceptional user experience. Built on Tailwind CSS, HTMX, and AlpineJS to create a cohesive, accessible, and performant interface. ## Design Philosophy ### Core Principles 1. **Thrill-Focused**: Every design element should evoke excitement and adventure 2. **Data-Rich**: Present complex theme park information in digestible, beautiful ways 3. **Progressive Enhancement**: Works beautifully without JavaScript, enhanced with it 4. **Accessibility First**: WCAG 2.1 AA compliance throughout 5. **Performance Obsessed**: Sub-2s load times, smooth 60fps animations ### Visual Identity - **Theme**: Modern theme park adventure with premium feel - **Mood**: Exciting, trustworthy, sophisticated, fun - **Target**: Theme park enthusiasts, families, travel planners ## Color System ### Primary Palette ```css /* Thrill Colors - Excitement & Adventure */ --thrill-primary: #6366f1; /* Indigo 500 - Primary brand */ --thrill-primary-dark: #4f46e5; /* Indigo 600 - Hover states */ --thrill-primary-light: #818cf8; /* Indigo 400 - Light accents */ /* Adventure Colors - Energy & Fun */ --thrill-secondary: #f59e0b; /* Amber 500 - Secondary actions */ --thrill-secondary-dark: #d97706; /* Amber 600 - Hover states */ --thrill-secondary-light: #fbbf24; /* Amber 400 - Light accents */ /* Status Colors - Clear Communication */ --thrill-success: #10b981; /* Emerald 500 - Operating parks */ --thrill-warning: #f59e0b; /* Amber 500 - Construction */ --thrill-danger: #ef4444; /* Red 500 - Closed permanently */ --thrill-info: #3b82f6; /* Blue 500 - Information */ ``` ### Neutral Palette ```css /* Light Mode */ --neutral-50: #f8fafc; --neutral-100: #f1f5f9; --neutral-200: #e2e8f0; --neutral-300: #cbd5e1; --neutral-400: #94a3b8; --neutral-500: #64748b; --neutral-600: #475569; --neutral-700: #334155; --neutral-800: #1e293b; --neutral-900: #0f172a; /* Dark Mode */ --dark-50: #0f172a; --dark-100: #1e293b; --dark-200: #334155; --dark-300: #475569; --dark-400: #64748b; --dark-500: #94a3b8; --dark-600: #cbd5e1; --dark-700: #e2e8f0; --dark-800: #f1f5f9; --dark-900: #f8fafc; ``` ### Gradient System ```css /* Hero Gradients */ --gradient-hero: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%); --gradient-hero-dark: linear-gradient(135deg, #4338ca 0%, #7c3aed 50%, #db2777 100%); /* Background Gradients */ --gradient-bg-light: linear-gradient(135deg, #f8fafc 0%, #e0e7ff 50%, #ede9fe 100%); --gradient-bg-dark: linear-gradient(135deg, #0f172a 0%, #1e1b4b 50%, #581c87 100%); /* Card Gradients */ --gradient-card: linear-gradient(145deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%); --gradient-card-hover: linear-gradient(145deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.08) 100%); ``` ## Typography ### Font Stack ```css /* Primary Font - Poppins */ --font-primary: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; /* Weights */ --font-light: 300; --font-regular: 400; --font-medium: 500; --font-semibold: 600; --font-bold: 700; --font-extrabold: 800; ``` ### Type Scale ```css /* Display - Hero sections */ --text-display-xl: 4.5rem; /* 72px */ --text-display-lg: 3.75rem; /* 60px */ --text-display-md: 3rem; /* 48px */ --text-display-sm: 2.25rem; /* 36px */ /* Headings */ --text-h1: 2rem; /* 32px */ --text-h2: 1.75rem; /* 28px */ --text-h3: 1.5rem; /* 24px */ --text-h4: 1.25rem; /* 20px */ --text-h5: 1.125rem; /* 18px */ --text-h6: 1rem; /* 16px */ /* Body */ --text-lg: 1.125rem; /* 18px */ --text-base: 1rem; /* 16px */ --text-sm: 0.875rem; /* 14px */ --text-xs: 0.75rem; /* 12px */ ``` ## Spacing System ### Base Scale (4px grid) ```css --space-0: 0; --space-1: 0.25rem; /* 4px */ --space-2: 0.5rem; /* 8px */ --space-3: 0.75rem; /* 12px */ --space-4: 1rem; /* 16px */ --space-5: 1.25rem; /* 20px */ --space-6: 1.5rem; /* 24px */ --space-8: 2rem; /* 32px */ --space-10: 2.5rem; /* 40px */ --space-12: 3rem; /* 48px */ --space-16: 4rem; /* 64px */ --space-20: 5rem; /* 80px */ --space-24: 6rem; /* 96px */ --space-32: 8rem; /* 128px */ ``` ## Component Library ### Buttons #### Primary Button ```css .btn-primary { @apply px-6 py-3 bg-gradient-to-r from-thrill-primary to-thrill-primary-dark; @apply text-white font-semibold rounded-xl shadow-lg; @apply hover:shadow-xl hover:scale-105 active:scale-95; @apply transition-all duration-200 ease-out; @apply focus:outline-none focus:ring-4 focus:ring-thrill-primary/30; } ``` #### Secondary Button ```css .btn-secondary { @apply px-6 py-3 bg-white dark:bg-neutral-800; @apply text-thrill-primary dark:text-thrill-primary-light; @apply font-semibold rounded-xl shadow-md border border-thrill-primary/20; @apply hover:bg-thrill-primary/5 hover:shadow-lg hover:scale-105; @apply active:scale-95 transition-all duration-200 ease-out; @apply focus:outline-none focus:ring-4 focus:ring-thrill-primary/30; } ``` #### Ghost Button ```css .btn-ghost { @apply px-4 py-2 text-neutral-600 dark:text-neutral-400; @apply font-medium rounded-lg hover:bg-neutral-100 dark:hover:bg-neutral-800; @apply hover:text-neutral-900 dark:hover:text-neutral-100; @apply transition-all duration-150 ease-out; @apply focus:outline-none focus:ring-2 focus:ring-neutral-300 dark:focus:ring-neutral-600; } ``` ### Cards #### Base Card ```css .card { @apply bg-white/80 dark:bg-neutral-800/80 backdrop-blur-lg; @apply border border-neutral-200/50 dark:border-neutral-700/50; @apply rounded-2xl shadow-lg hover:shadow-xl; @apply transition-all duration-300 ease-out; @apply hover:scale-[1.02] hover:-translate-y-1; } ``` #### Feature Card ```css .card-feature { @apply card p-8 relative overflow-hidden; @apply before:absolute before:inset-0 before:bg-gradient-card; @apply hover:before:bg-gradient-card-hover; @apply before:transition-all before:duration-300; } ``` #### Park Card ```css .card-park { @apply card group cursor-pointer; @apply hover:ring-2 hover:ring-thrill-primary/30; } .card-park-image { @apply aspect-video w-full object-cover rounded-t-2xl; @apply group-hover:scale-105 transition-transform duration-500 ease-out; } .card-park-content { @apply p-6 space-y-4; } ``` ### Forms #### Input Fields ```css .form-input { @apply w-full px-4 py-3 bg-white dark:bg-neutral-800; @apply border border-neutral-300 dark:border-neutral-600; @apply rounded-xl shadow-sm focus:shadow-md; @apply text-neutral-900 dark:text-neutral-100; @apply placeholder-neutral-500 dark:placeholder-neutral-400; @apply focus:outline-none focus:ring-2 focus:ring-thrill-primary/50; @apply focus:border-thrill-primary dark:focus:border-thrill-primary-light; @apply transition-all duration-200 ease-out; } ``` #### Labels ```css .form-label { @apply block text-sm font-semibold text-neutral-700 dark:text-neutral-300; @apply mb-2; } ``` #### Error States ```css .form-error { @apply text-sm text-thrill-danger mt-1; } .form-input-error { @apply border-thrill-danger focus:ring-thrill-danger/50; @apply focus:border-thrill-danger; } ``` ### Status Badges #### Operating ```css .badge-operating { @apply inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold; @apply bg-thrill-success/10 text-thrill-success; @apply border border-thrill-success/20; } ``` #### Construction ```css .badge-construction { @apply inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold; @apply bg-thrill-warning/10 text-thrill-warning; @apply border border-thrill-warning/20; } ``` #### Closed ```css .badge-closed { @apply inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold; @apply bg-thrill-danger/10 text-thrill-danger; @apply border border-thrill-danger/20; } ``` ## Animation System ### Micro-Interactions ```css /* Hover Lift */ .hover-lift { @apply transition-all duration-300 ease-out; @apply hover:scale-105 hover:-translate-y-1 hover:shadow-xl; } /* Pulse Animation */ .pulse-glow { @apply animate-pulse; animation: pulse-glow 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } @keyframes pulse-glow { 0%, 100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4); } 50% { box-shadow: 0 0 0 10px rgba(99, 102, 241, 0); } } /* Slide In Animations */ .slide-in-up { animation: slideInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards; } @keyframes slideInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } ``` ### HTMX Transitions ```css /* View Transitions for HTMX */ .htmx-transition { view-transition-name: main-content; } ::view-transition-old(main-content) { animation: 300ms cubic-bezier(0.4, 0, 1, 1) both fade-out, 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left; } ::view-transition-new(main-content) { animation: 400ms cubic-bezier(0, 0, 0.2, 1) 100ms both fade-in, 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right; } @keyframes fade-in { from { opacity: 0; } } @keyframes fade-out { to { opacity: 0; } } @keyframes slide-from-right { from { transform: translateX(30px); } } @keyframes slide-to-left { to { transform: translateX(-30px); } } ``` ## Layout System ### Container Sizes ```css .container-xs { max-width: 480px; } .container-sm { max-width: 640px; } .container-md { max-width: 768px; } .container-lg { max-width: 1024px; } .container-xl { max-width: 1280px; } .container-2xl { max-width: 1536px; } ``` ### Grid System ```css /* Auto-fit grids for responsive cards */ .grid-auto-fit-xs { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } .grid-auto-fit-sm { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); } .grid-auto-fit-md { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); } .grid-auto-fit-lg { grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); } ``` ## Responsive Design ### Breakpoints ```css /* Mobile First Approach */ sm: 640px /* Small devices */ md: 768px /* Medium devices */ lg: 1024px /* Large devices */ xl: 1280px /* Extra large devices */ 2xl: 1536px /* 2X Extra large devices */ ``` ### Container Queries ```css /* Component-based responsive design */ @container (min-width: 320px) { /* Small container */ } @container (min-width: 480px) { /* Medium container */ } @container (min-width: 640px) { /* Large container */ } ``` ## Accessibility ### Focus States ```css .focus-visible { @apply focus:outline-none focus-visible:ring-2 focus-visible:ring-thrill-primary; @apply focus-visible:ring-offset-2 focus-visible:ring-offset-white; @apply dark:focus-visible:ring-offset-neutral-900; } ``` ### Screen Reader Support ```css .sr-only { @apply absolute w-px h-px p-0 -m-px overflow-hidden; @apply whitespace-nowrap border-0; clip: rect(0, 0, 0, 0); } .sr-only-focusable:focus { @apply static w-auto h-auto p-1 m-0 overflow-visible; @apply whitespace-normal; clip: auto; } ``` ## Performance Guidelines ### Critical CSS - Inline critical styles for above-the-fold content - Defer non-critical CSS loading - Use CSS containment for performance isolation ### Animation Performance - Prefer `transform` and `opacity` for animations - Use `will-change` sparingly and remove after animation - Implement `prefers-reduced-motion` support ### Loading States ```css .loading-skeleton { @apply bg-gradient-to-r from-neutral-200 via-neutral-100 to-neutral-200; @apply dark:from-neutral-700 dark:via-neutral-600 dark:to-neutral-700; @apply animate-pulse; background-size: 200% 100%; animation: shimmer 1.5s infinite; } @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } ``` ## Implementation Notes ### CSS Custom Properties - Use CSS custom properties for theme values - Implement proper fallbacks for older browsers - Leverage cascade for theme switching ### Component Architecture - Build components with composition in mind - Use CSS classes for styling, not inline styles - Implement proper component variants ### Testing Strategy - Test across all supported browsers - Validate accessibility with screen readers - Performance test on low-end devices - Verify responsive behavior at all breakpoints