/** * ThrillWiki Design Tokens * * This is the single source of truth for all design tokens in the application. * All CSS files should reference these variables instead of hardcoding values. * * Token Naming Convention: * - Color scales: --color-{name}-{shade} (e.g., --color-primary-500) * - Semantic colors: --color-{semantic} (e.g., --color-background, --color-foreground) * - Typography: --font-{property}-{value} (e.g., --font-size-lg) * - Spacing: --spacing-{size} (e.g., --spacing-4) * - Shadows: --shadow-{size} (e.g., --shadow-md) * - Radius: --radius-{size} (e.g., --radius-lg) * - Transitions: --transition-{type} (e.g., --transition-all) * - Z-index: --z-{level} (e.g., --z-50) * * Responsive Breakpoints (Tailwind defaults): * - sm: 640px - Small devices (landscape phones) * - md: 768px - Medium devices (tablets) * - lg: 1024px - Large devices (desktops) * - xl: 1280px - Extra large devices * - 2xl: 1536px - 2X Extra large devices */ @layer tokens, base, components, utilities, overrides; @layer tokens { :root { /* ================================================================= Color Scales - Base Palette ================================================================= */ /* Primary Colors - Blue */ --color-primary-50: #eff6ff; --color-primary-100: #dbeafe; --color-primary-200: #bfdbfe; --color-primary-300: #93c5fd; --color-primary-400: #60a5fa; --color-primary-500: #3b82f6; --color-primary-600: #2563eb; --color-primary-700: #1d4ed8; --color-primary-800: #1e40af; --color-primary-900: #1e3a8a; --color-primary-950: #172554; /* Secondary Colors - Slate */ --color-secondary-50: #f8fafc; --color-secondary-100: #f1f5f9; --color-secondary-200: #e2e8f0; --color-secondary-300: #cbd5e1; --color-secondary-400: #94a3b8; --color-secondary-500: #64748b; --color-secondary-600: #475569; --color-secondary-700: #334155; --color-secondary-800: #1e293b; --color-secondary-900: #0f172a; --color-secondary-950: #020617; /* Accent Colors - Red */ --color-accent-50: #fef2f2; --color-accent-100: #fee2e2; --color-accent-200: #fecaca; --color-accent-300: #fca5a5; --color-accent-400: #f87171; --color-accent-500: #ef4444; --color-accent-600: #dc2626; --color-accent-700: #b91c1c; --color-accent-800: #991b1b; --color-accent-900: #7f1d1d; --color-accent-950: #450a0a; /* Success Colors - Green */ --color-success-50: #f0fdf4; --color-success-100: #dcfce7; --color-success-200: #bbf7d0; --color-success-300: #86efac; --color-success-400: #4ade80; --color-success-500: #22c55e; --color-success-600: #16a34a; --color-success-700: #15803d; --color-success-800: #166534; --color-success-900: #14532d; --color-success-950: #052e16; /* Warning Colors - Amber */ --color-warning-50: #fffbeb; --color-warning-100: #fef3c7; --color-warning-200: #fde68a; --color-warning-300: #fcd34d; --color-warning-400: #fbbf24; --color-warning-500: #f59e0b; --color-warning-600: #d97706; --color-warning-700: #b45309; --color-warning-800: #92400e; --color-warning-900: #78350f; --color-warning-950: #451a03; /* Error Colors - Red */ --color-error-50: #fef2f2; --color-error-100: #fee2e2; --color-error-200: #fecaca; --color-error-300: #fca5a5; --color-error-400: #f87171; --color-error-500: #ef4444; --color-error-600: #dc2626; --color-error-700: #b91c1c; --color-error-800: #991b1b; --color-error-900: #7f1d1d; --color-error-950: #450a0a; /* Info Colors - Sky */ --color-info-50: #f0f9ff; --color-info-100: #e0f2fe; --color-info-200: #bae6fd; --color-info-300: #7dd3fc; --color-info-400: #38bdf8; --color-info-500: #0ea5e9; --color-info-600: #0284c7; --color-info-700: #0369a1; --color-info-800: #075985; --color-info-900: #0c4a6e; --color-info-950: #082f49; /* ================================================================= Typography ================================================================= */ /* Font Families */ --font-family-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; --font-family-serif: 'Playfair Display', Georgia, Cambria, 'Times New Roman', Times, serif; --font-family-mono: 'JetBrains Mono', 'Fira Code', Consolas, 'Liberation Mono', Menlo, Courier, monospace; /* Font Sizes */ --font-size-xs: 0.75rem; /* 12px */ --font-size-sm: 0.875rem; /* 14px */ --font-size-base: 1rem; /* 16px */ --font-size-lg: 1.125rem; /* 18px */ --font-size-xl: 1.25rem; /* 20px */ --font-size-2xl: 1.5rem; /* 24px */ --font-size-3xl: 1.875rem; /* 30px */ --font-size-4xl: 2.25rem; /* 36px */ --font-size-5xl: 3rem; /* 48px */ --font-size-6xl: 3.75rem; /* 60px */ --font-size-7xl: 4.5rem; /* 72px */ --font-size-8xl: 6rem; /* 96px */ --font-size-9xl: 8rem; /* 128px */ /* Font Weights */ --font-weight-thin: 100; --font-weight-extralight: 200; --font-weight-light: 300; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; --font-weight-extrabold: 800; --font-weight-black: 900; /* Line Heights */ --line-height-none: 1; --line-height-tight: 1.25; --line-height-snug: 1.375; --line-height-normal: 1.5; --line-height-relaxed: 1.625; --line-height-loose: 2; /* Letter Spacing */ --letter-spacing-tighter: -0.05em; --letter-spacing-tight: -0.025em; --letter-spacing-normal: 0em; --letter-spacing-wide: 0.025em; --letter-spacing-wider: 0.05em; --letter-spacing-widest: 0.1em; /* ================================================================= Spacing Scale ================================================================= */ --spacing-px: 1px; --spacing-0: 0; --spacing-0-5: 0.125rem; /* 2px */ --spacing-1: 0.25rem; /* 4px */ --spacing-1-5: 0.375rem; /* 6px */ --spacing-2: 0.5rem; /* 8px */ --spacing-2-5: 0.625rem; /* 10px */ --spacing-3: 0.75rem; /* 12px */ --spacing-3-5: 0.875rem; /* 14px */ --spacing-4: 1rem; /* 16px */ --spacing-5: 1.25rem; /* 20px */ --spacing-6: 1.5rem; /* 24px */ --spacing-7: 1.75rem; /* 28px */ --spacing-8: 2rem; /* 32px */ --spacing-9: 2.25rem; /* 36px */ --spacing-10: 2.5rem; /* 40px */ --spacing-11: 2.75rem; /* 44px */ --spacing-12: 3rem; /* 48px */ --spacing-14: 3.5rem; /* 56px */ --spacing-16: 4rem; /* 64px */ --spacing-20: 5rem; /* 80px */ --spacing-24: 6rem; /* 96px */ --spacing-28: 7rem; /* 112px */ --spacing-32: 8rem; /* 128px */ --spacing-36: 9rem; /* 144px */ --spacing-40: 10rem; /* 160px */ --spacing-44: 11rem; /* 176px */ --spacing-48: 12rem; /* 192px */ --spacing-52: 13rem; /* 208px */ --spacing-56: 14rem; /* 224px */ --spacing-60: 15rem; /* 240px */ --spacing-64: 16rem; /* 256px */ --spacing-72: 18rem; /* 288px */ --spacing-80: 20rem; /* 320px */ --spacing-96: 24rem; /* 384px */ /* ================================================================= Shadows ================================================================= */ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-base: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); --shadow-none: 0 0 #0000; /* ================================================================= Border Radius ================================================================= */ --radius-none: 0; --radius-sm: 0.125rem; /* 2px */ --radius-base: 0.25rem; /* 4px */ --radius-md: 0.375rem; /* 6px */ --radius-lg: 0.5rem; /* 8px */ --radius-xl: 0.75rem; /* 12px */ --radius-2xl: 1rem; /* 16px */ --radius-3xl: 1.5rem; /* 24px */ --radius-full: 9999px; /* ================================================================= Transitions & Animations ================================================================= */ /* Transition Durations */ --duration-75: 75ms; --duration-100: 100ms; --duration-150: 150ms; --duration-200: 200ms; --duration-300: 300ms; --duration-500: 500ms; --duration-700: 700ms; --duration-1000: 1000ms; /* Transition Timing Functions */ --ease-linear: linear; --ease-in: cubic-bezier(0.4, 0, 1, 1); --ease-out: cubic-bezier(0, 0, 0.2, 1); --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* Transition Presets */ --transition-none: none; --transition-all: all 150ms cubic-bezier(0.4, 0, 0.2, 1); --transition-colors: color 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), border-color 150ms cubic-bezier(0.4, 0, 0.2, 1), text-decoration-color 150ms cubic-bezier(0.4, 0, 0.2, 1), fill 150ms cubic-bezier(0.4, 0, 0.2, 1), stroke 150ms cubic-bezier(0.4, 0, 0.2, 1); --transition-opacity: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1); --transition-shadow: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1); --transition-transform: transform 150ms cubic-bezier(0.4, 0, 0.2, 1); /* ================================================================= Responsive Breakpoints Use with CSS media queries: @media (min-width: var(--breakpoint-sm)) Note: CSS custom properties in media queries require JavaScript workarounds These are documented here for reference; use Tailwind classes for responsive design ================================================================= */ --breakpoint-sm: 640px; /* Small devices (landscape phones) */ --breakpoint-md: 768px; /* Medium devices (tablets) */ --breakpoint-lg: 1024px; /* Large devices (desktops) */ --breakpoint-xl: 1280px; /* Extra large devices */ --breakpoint-2xl: 1536px; /* 2X Extra large devices */ /* Container Max-Widths at Breakpoints */ --container-sm: 640px; --container-md: 768px; --container-lg: 1024px; --container-xl: 1280px; --container-2xl: 1536px; /* ================================================================= Z-Index Scale ================================================================= */ --z-0: 0; --z-10: 10; --z-20: 20; --z-30: 30; --z-40: 40; --z-50: 50; --z-auto: auto; --z-dropdown: 100; --z-sticky: 200; --z-fixed: 300; --z-modal-backdrop: 400; --z-modal: 500; --z-popover: 600; --z-tooltip: 700; --z-toast: 800; /* ================================================================= Semantic Colors - Light Mode ================================================================= */ /* Background & Foreground */ --color-background: var(--color-secondary-50); --color-foreground: var(--color-secondary-900); /* Muted */ --color-muted: var(--color-secondary-100); --color-muted-foreground: var(--color-secondary-500); /* Border & Input */ --color-border: var(--color-secondary-200); --color-input: var(--color-secondary-50); /* Card */ --color-card: var(--color-secondary-50); --color-card-foreground: var(--color-secondary-900); /* Popover */ --color-popover: var(--color-secondary-50); --color-popover-foreground: var(--color-secondary-900); /* Primary */ --color-primary: var(--color-primary-600); --color-primary-foreground: var(--color-primary-50); /* Secondary */ --color-secondary: var(--color-secondary-100); --color-secondary-foreground: var(--color-secondary-900); /* Accent */ --color-accent: var(--color-accent-100); --color-accent-foreground: var(--color-accent-900); /* Destructive */ --color-destructive: var(--color-error-600); --color-destructive-foreground: var(--color-error-50); /* Default Border Radius */ --radius: var(--radius-md); } /* ================================================================= Dark Mode Override ================================================================= */ .dark { /* Background & Foreground */ --color-background: var(--color-secondary-900); --color-foreground: var(--color-secondary-50); /* Muted */ --color-muted: var(--color-secondary-800); --color-muted-foreground: var(--color-secondary-400); /* Border & Input */ --color-border: var(--color-secondary-700); --color-input: var(--color-secondary-800); /* Card */ --color-card: var(--color-secondary-800); --color-card-foreground: var(--color-secondary-50); /* Popover */ --color-popover: var(--color-secondary-800); --color-popover-foreground: var(--color-secondary-50); /* Primary */ --color-primary: var(--color-primary-500); --color-primary-foreground: var(--color-primary-950); /* Secondary */ --color-secondary: var(--color-secondary-800); --color-secondary-foreground: var(--color-secondary-50); /* Accent */ --color-accent: var(--color-accent-900); --color-accent-foreground: var(--color-accent-100); /* Destructive */ --color-destructive: var(--color-error-900); --color-destructive-foreground: var(--color-error-200); /* Dark mode shadow adjustments */ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.2); --shadow-base: 0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.2); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.3), 0 2px 4px -2px rgb(0 0 0 / 0.2); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.3), 0 4px 6px -4px rgb(0 0 0 / 0.2); --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.3), 0 8px 10px -6px rgb(0 0 0 / 0.2); --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.5); } } @layer base { /* ================================================================= Base Element Styles ================================================================= */ * { @apply border-border; } body { @apply font-sans antialiased bg-background text-foreground; font-feature-settings: "rlig" 1, "calt" 1; } /* Typography */ h1, h2, h3, h4, h5, h6 { @apply font-semibold tracking-tight; } h1 { @apply text-4xl lg:text-5xl; } h2 { @apply text-3xl lg:text-4xl; } h3 { @apply text-2xl lg:text-3xl; } h4 { @apply text-xl lg:text-2xl; } h5 { @apply text-lg lg:text-xl; } h6 { @apply text-base lg:text-lg; } /* Links */ a { color: var(--color-primary); text-decoration: none; } a:hover { text-decoration: underline; } /* ================================================================= Accessibility - Focus Indicators (WCAG 2.1 AA Compliant) ================================================================= */ /* Default focus-visible style for all interactive elements */ :focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; } /* Enhanced focus for buttons and interactive elements */ button:focus-visible, [role="button"]:focus-visible, input[type="submit"]:focus-visible, input[type="button"]:focus-visible, input[type="reset"]:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.2); } /* Form field focus states */ input:focus-visible, textarea:focus-visible, select:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 0; border-color: var(--color-primary); } /* Link focus state */ a:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: var(--radius-sm); } /* Focus within for composite components */ [tabindex]:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; } /* ================================================================= Accessibility - Reduced Motion Support ================================================================= */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } /* ================================================================= Accessibility - High Contrast Support ================================================================= */ @media (prefers-contrast: high) { :root { --color-border: var(--color-secondary-700); } .dark { --color-border: var(--color-secondary-300); } button, input, select, textarea { border-width: 2px; } } /* ================================================================= Accessibility - Screen Reader Utilities ================================================================= */ /* Visually hidden but accessible to screen readers */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } /* Make sr-only visible on focus (for skip links) */ .sr-only-focusable:focus, .sr-only-focusable:focus-within { position: static; width: auto; height: auto; padding: inherit; margin: inherit; overflow: visible; clip: auto; white-space: normal; } /* Not screen reader only - visible to all */ .not-sr-only { position: static; width: auto; height: auto; padding: 0; margin: 0; overflow: visible; clip: auto; white-space: normal; } } @layer components { /* ================================================================= HTMX Loading States ================================================================= */ .htmx-indicator { opacity: 0; transition: opacity 200ms ease-in; } .htmx-request .htmx-indicator { opacity: 1; } .htmx-request.htmx-indicator { opacity: 1; } /* ================================================================= Container ================================================================= */ .container { @apply px-4 mx-auto md:px-6 lg:px-8; max-width: 80rem; /* 1280px */ } .container-sm { @apply px-4 mx-auto md:px-6; max-width: 40rem; /* 640px */ } .container-md { @apply px-4 mx-auto md:px-6; max-width: 48rem; /* 768px */ } .container-lg { @apply px-4 mx-auto md:px-6 lg:px-8; max-width: 64rem; /* 1024px */ } .container-xl { @apply px-4 mx-auto md:px-6 lg:px-8; max-width: 80rem; /* 1280px */ } .container-2xl { @apply px-4 mx-auto md:px-6 lg:px-8; max-width: 96rem; /* 1536px */ } } @layer utilities { /* ================================================================= Spacing Utilities ================================================================= */ .p-token-1 { padding: var(--spacing-1); } .p-token-2 { padding: var(--spacing-2); } .p-token-3 { padding: var(--spacing-3); } .p-token-4 { padding: var(--spacing-4); } .p-token-6 { padding: var(--spacing-6); } .p-token-8 { padding: var(--spacing-8); } .m-token-1 { margin: var(--spacing-1); } .m-token-2 { margin: var(--spacing-2); } .m-token-3 { margin: var(--spacing-3); } .m-token-4 { margin: var(--spacing-4); } .m-token-6 { margin: var(--spacing-6); } .m-token-8 { margin: var(--spacing-8); } .gap-token-1 { gap: var(--spacing-1); } .gap-token-2 { gap: var(--spacing-2); } .gap-token-3 { gap: var(--spacing-3); } .gap-token-4 { gap: var(--spacing-4); } .gap-token-6 { gap: var(--spacing-6); } .gap-token-8 { gap: var(--spacing-8); } /* ================================================================= Transition Utilities ================================================================= */ .transition-token-all { transition: var(--transition-all); } .transition-token-colors { transition: var(--transition-colors); } .transition-token-opacity { transition: var(--transition-opacity); } .transition-token-shadow { transition: var(--transition-shadow); } .transition-token-transform { transition: var(--transition-transform); } .duration-token-75 { transition-duration: var(--duration-75); } .duration-token-100 { transition-duration: var(--duration-100); } .duration-token-150 { transition-duration: var(--duration-150); } .duration-token-200 { transition-duration: var(--duration-200); } .duration-token-300 { transition-duration: var(--duration-300); } .duration-token-500 { transition-duration: var(--duration-500); } .ease-token-linear { transition-timing-function: var(--ease-linear); } .ease-token-in { transition-timing-function: var(--ease-in); } .ease-token-out { transition-timing-function: var(--ease-out); } .ease-token-in-out { transition-timing-function: var(--ease-in-out); } .ease-token-bounce { transition-timing-function: var(--ease-bounce); } /* ================================================================= Z-Index Utilities ================================================================= */ .z-token-0 { z-index: var(--z-0); } .z-token-10 { z-index: var(--z-10); } .z-token-20 { z-index: var(--z-20); } .z-token-30 { z-index: var(--z-30); } .z-token-40 { z-index: var(--z-40); } .z-token-50 { z-index: var(--z-50); } .z-token-dropdown { z-index: var(--z-dropdown); } .z-token-sticky { z-index: var(--z-sticky); } .z-token-fixed { z-index: var(--z-fixed); } .z-token-modal-backdrop { z-index: var(--z-modal-backdrop); } .z-token-modal { z-index: var(--z-modal); } .z-token-popover { z-index: var(--z-popover); } .z-token-tooltip { z-index: var(--z-tooltip); } .z-token-toast { z-index: var(--z-toast); } /* ================================================================= Shadow Utilities ================================================================= */ .shadow-token-sm { box-shadow: var(--shadow-sm); } .shadow-token-base { box-shadow: var(--shadow-base); } .shadow-token-md { box-shadow: var(--shadow-md); } .shadow-token-lg { box-shadow: var(--shadow-lg); } .shadow-token-xl { box-shadow: var(--shadow-xl); } .shadow-token-2xl { box-shadow: var(--shadow-2xl); } .shadow-token-inner { box-shadow: var(--shadow-inner); } .shadow-token-none { box-shadow: var(--shadow-none); } /* ================================================================= Border Radius Utilities ================================================================= */ .rounded-token-none { border-radius: var(--radius-none); } .rounded-token-sm { border-radius: var(--radius-sm); } .rounded-token-base { border-radius: var(--radius-base); } .rounded-token-md { border-radius: var(--radius-md); } .rounded-token-lg { border-radius: var(--radius-lg); } .rounded-token-xl { border-radius: var(--radius-xl); } .rounded-token-2xl { border-radius: var(--radius-2xl); } .rounded-token-3xl { border-radius: var(--radius-3xl); } .rounded-token-full { border-radius: var(--radius-full); } /* ================================================================= Typography Utilities ================================================================= */ .font-token-sans { font-family: var(--font-family-sans); } .font-token-serif { font-family: var(--font-family-serif); } .font-token-mono { font-family: var(--font-family-mono); } .text-token-xs { font-size: var(--font-size-xs); } .text-token-sm { font-size: var(--font-size-sm); } .text-token-base { font-size: var(--font-size-base); } .text-token-lg { font-size: var(--font-size-lg); } .text-token-xl { font-size: var(--font-size-xl); } .text-token-2xl { font-size: var(--font-size-2xl); } .text-token-3xl { font-size: var(--font-size-3xl); } .text-token-4xl { font-size: var(--font-size-4xl); } /* ================================================================= Responsive Visibility Utilities ================================================================= */ /* Hide at specific breakpoints */ @media (max-width: 639px) { .hidden-mobile { display: none !important; } } @media (min-width: 640px) and (max-width: 767px) { .hidden-sm { display: none !important; } } @media (min-width: 768px) and (max-width: 1023px) { .hidden-md { display: none !important; } } @media (min-width: 1024px) and (max-width: 1279px) { .hidden-lg { display: none !important; } } @media (min-width: 1280px) { .hidden-xl { display: none !important; } } /* Show only at specific breakpoints */ .show-mobile { display: none !important; } .show-sm { display: none !important; } .show-md { display: none !important; } .show-lg { display: none !important; } .show-xl { display: none !important; } @media (max-width: 639px) { .show-mobile { display: block !important; } } @media (min-width: 640px) and (max-width: 767px) { .show-sm { display: block !important; } } @media (min-width: 768px) and (max-width: 1023px) { .show-md { display: block !important; } } @media (min-width: 1024px) and (max-width: 1279px) { .show-lg { display: block !important; } } @media (min-width: 1280px) { .show-xl { display: block !important; } } /* ================================================================= Responsive Stack/Flex Utilities ================================================================= */ /* Stack on mobile, row on larger screens */ .stack-to-row { display: flex; flex-direction: column; gap: var(--spacing-4); } @media (min-width: 640px) { .stack-to-row { flex-direction: row; } } /* Stack on mobile/tablet, row on desktop */ .stack-to-row-lg { display: flex; flex-direction: column; gap: var(--spacing-4); } @media (min-width: 1024px) { .stack-to-row-lg { flex-direction: row; } } /* ================================================================= Responsive Grid Utilities ================================================================= */ /* Auto-fit grid that adapts to content */ .grid-auto-fit { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: var(--spacing-6); } .grid-auto-fit-sm { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: var(--spacing-4); } .grid-auto-fit-lg { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr)); gap: var(--spacing-8); } /* Responsive column grids */ .grid-responsive-2 { display: grid; grid-template-columns: 1fr; gap: var(--spacing-4); } @media (min-width: 640px) { .grid-responsive-2 { grid-template-columns: repeat(2, 1fr); } } .grid-responsive-3 { display: grid; grid-template-columns: 1fr; gap: var(--spacing-4); } @media (min-width: 640px) { .grid-responsive-3 { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 1024px) { .grid-responsive-3 { grid-template-columns: repeat(3, 1fr); } } .grid-responsive-4 { display: grid; grid-template-columns: 1fr; gap: var(--spacing-4); } @media (min-width: 640px) { .grid-responsive-4 { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 1024px) { .grid-responsive-4 { grid-template-columns: repeat(4, 1fr); } } /* ================================================================= Responsive Text Size Utilities ================================================================= */ .text-responsive-sm { font-size: var(--font-size-sm); } @media (min-width: 1024px) { .text-responsive-sm { font-size: var(--font-size-base); } } .text-responsive-base { font-size: var(--font-size-base); } @media (min-width: 1024px) { .text-responsive-base { font-size: var(--font-size-lg); } } .text-responsive-lg { font-size: var(--font-size-lg); } @media (min-width: 1024px) { .text-responsive-lg { font-size: var(--font-size-xl); } } .text-responsive-xl { font-size: var(--font-size-xl); } @media (min-width: 1024px) { .text-responsive-xl { font-size: var(--font-size-2xl); } } .text-responsive-2xl { font-size: var(--font-size-2xl); } @media (min-width: 1024px) { .text-responsive-2xl { font-size: var(--font-size-3xl); } } /* ================================================================= Responsive Spacing Utilities ================================================================= */ .py-responsive { padding-top: var(--spacing-4); padding-bottom: var(--spacing-4); } @media (min-width: 640px) { .py-responsive { padding-top: var(--spacing-6); padding-bottom: var(--spacing-6); } } @media (min-width: 1024px) { .py-responsive { padding-top: var(--spacing-8); padding-bottom: var(--spacing-8); } } .px-responsive { padding-left: var(--spacing-4); padding-right: var(--spacing-4); } @media (min-width: 640px) { .px-responsive { padding-left: var(--spacing-6); padding-right: var(--spacing-6); } } @media (min-width: 1024px) { .px-responsive { padding-left: var(--spacing-8); padding-right: var(--spacing-8); } } .gap-responsive { gap: var(--spacing-4); } @media (min-width: 640px) { .gap-responsive { gap: var(--spacing-6); } } @media (min-width: 1024px) { .gap-responsive { gap: var(--spacing-8); } } /* ================================================================= Accessibility Utilities ================================================================= */ /* Focus ring utilities */ .focus-ring { outline: 2px solid transparent; outline-offset: 2px; } .focus-ring:focus-visible { outline: 2px solid var(--color-primary); } .focus-ring-inset:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; } /* Skip link styling */ .skip-link { position: absolute; top: -100%; left: 0; padding: var(--spacing-2) var(--spacing-4); background: var(--color-primary); color: var(--color-primary-foreground); z-index: var(--z-toast); transition: top 0.2s; border-radius: 0 0 var(--radius-md) 0; } .skip-link:focus { top: 0; outline: none; } /* Disable outline when not using keyboard */ [data-focus-visible-added] { outline: 2px solid var(--color-primary); outline-offset: 2px; } /* Improve touch target size for accessibility (minimum 44x44px) */ .touch-target { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; } /* Color contrast utilities */ .text-high-contrast { color: var(--color-foreground); } .bg-high-contrast { background-color: var(--color-background); } /* Announcement region for screen readers */ .aria-live-region { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } /* Make element focusable for keyboard users */ .focusable { tabindex: 0; } .focusable:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; } /* Interactive state indicators */ .interactive { cursor: pointer; user-select: none; } .interactive:hover { opacity: 0.9; } .interactive:active { transform: scale(0.98); } /* Disabled state */ .disabled, [disabled], [aria-disabled="true"] { opacity: 0.5; pointer-events: none; cursor: not-allowed; } /* Loading state - reduces motion for those who prefer it */ .loading { position: relative; pointer-events: none; } .loading::after { content: ''; position: absolute; inset: 0; background: rgba(255, 255, 255, 0.5); } @media (prefers-reduced-motion: no-preference) { .loading::after { animation: pulse 1.5s ease-in-out infinite; } } @keyframes pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 0.3; } } }