/* ============================================ DESIGN TOKENS — Make Post Sell Single source of truth for the design system. CSS custom properties, consumed everywhere. ============================================ */ :root { /* ---- Color: Brand ---- */ --color-green: #a3c765; --color-green-dark: #8ab34e; --color-green-light: #e8f5d4; --color-blue: #98b6fa; --color-blue-dark: #7a9de8; --color-navy: #5871ad; --color-navy-light: #82A8FF; --color-purple: #9B59B6; --color-purple-dark: #7B2D8E; --color-danger: #CC6958; --color-danger-dark: #b5503f; --color-check: #678731; --color-cross: #c77765; --color-gold: #d4a843; /* ---- Color: Surface ---- */ --surface-base: #FFFFFF; --surface-dim: #F9F9FA; --surface-container: #F4F4F5; --surface-container-high: #EEEEEF; --surface-inverse: #0b0b0b; /* ---- Color: Text ---- */ --text-primary: #0b0b0b; --text-body: #515151; --text-secondary: #666666; --text-muted: #777777; --text-faint: #999999; --text-disabled: #BBBBBB; --text-inverse: #FFFFFF; --text-on-green: #FFFFFF; --text-on-navy: #FFFFFF; /* ---- Color: Border ---- */ --border-default: #e0e0e0; --border-light: #eeeeee; --border-focus: #5871ad; --border-error: #CC6958; /* ---- Color: State overlays ---- */ --state-hover: rgba(0, 0, 0, 0.04); --state-focus: rgba(88, 113, 173, 0.12); --state-pressed: rgba(0, 0, 0, 0.08); --state-dragged: rgba(0, 0, 0, 0.12); --state-disabled-bg: rgba(0, 0, 0, 0.04); --state-disabled-text: rgba(0, 0, 0, 0.26); /* ---- Color: Alerts ---- */ --alert-success-bg: #e8f5d4; --alert-success-text: #155724; --alert-success-border: #c3e6cb; --alert-info-bg: #dce8ff; --alert-info-text: #0c5460; --alert-info-border: #bee5eb; --alert-warning-bg: #fff3cd; --alert-warning-text: #856404; --alert-warning-border: #ffeeba; --alert-danger-bg: #f8d7da; --alert-danger-text: #721c24; --alert-danger-border: #f5c6cb; /* ---- Typography ---- */ --font-family: helvetica, arial, sans-serif; --font-mono: 'SF Mono', 'Menlo', 'Consolas', monospace; /* Type scale — major third (1.250) */ --text-xs: 0.75rem; /* 12px */ --text-sm: 0.875rem; /* 14px */ --text-base: 1rem; /* 16px */ --text-md: 1.125rem; /* 18px */ --text-lg: 1.25rem; /* 20px */ --text-xl: 1.5rem; /* 24px */ --text-2xl: 1.875rem; /* 30px */ --text-3xl: 2.25rem; /* 36px */ --text-4xl: 3rem; /* 48px */ --text-5xl: 3.75rem; /* 60px */ /* Line heights */ --leading-none: 1; --leading-tight: 1.15; --leading-snug: 1.3; --leading-normal: 1.5; --leading-relaxed: 1.65; --leading-loose: 1.8; /* Font weights */ --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700; /* Letter spacing */ --tracking-tight: -0.02em; --tracking-normal: 0; --tracking-wide: 0.02em; --tracking-wider: 0.05em; --tracking-widest: 0.08em; /* ---- Spacing scale (4px base) ---- */ --space-0: 0; --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px; --space-12: 48px; --space-16: 64px; --space-20: 80px; --space-24: 96px; /* ---- Shape (border radius) ---- */ --radius-none: 0; --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-xl: 16px; --radius-2xl: 24px; --radius-full: 9999px; /* ---- Elevation (box-shadow) ---- */ --elevation-0: none; --elevation-1: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04); --elevation-2: 0 2px 6px rgba(0,0,0,0.06), 0 2px 4px rgba(0,0,0,0.04); --elevation-3: 0 4px 12px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.04); --elevation-4: 0 8px 24px rgba(0,0,0,0.08), 0 2px 6px rgba(0,0,0,0.04); --elevation-5: 0 16px 48px rgba(0,0,0,0.10), 0 4px 12px rgba(0,0,0,0.05); /* ---- Motion ---- */ /* Durations */ --duration-instant: 50ms; --duration-fast: 100ms; --duration-normal: 200ms; --duration-slow: 300ms; --duration-slower: 400ms; --duration-entrance: 250ms; --duration-exit: 200ms; /* Easing — based on material curves */ --ease-standard: cubic-bezier(0.2, 0, 0, 1); --ease-decelerate: cubic-bezier(0, 0, 0, 1); --ease-accelerate: cubic-bezier(0.3, 0, 1, 1); --ease-emphasize: cubic-bezier(0.2, 0, 0, 1); --ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* ---- Z-index scale ---- */ --z-base: 0; --z-dropdown: 100; --z-sticky: 200; --z-overlay: 300; --z-modal: 400; --z-toast: 500; --z-ribbon: 600; /* ---- Layout ---- */ --content-width: 800px; --content-narrow: 400px; --content-wide: 1200px; --bp-tablet: 800px; --bp-desktop: 1200px; } /* ============================================ BASE RESETS & DEFAULTS ============================================ */ *, *::before, *::after { box-sizing: border-box; } html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; font-size: 16px; scroll-behavior: smooth; } body { font-family: var(--font-family); font-size: var(--text-base); font-weight: var(--weight-regular); line-height: var(--leading-normal); color: var(--text-body); background-color: var(--surface-dim); margin: 0; } /* ============================================ FOCUS — Accessible, visible, consistent ============================================ */ :focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; } :focus:not(:focus-visible) { outline: none; } /* ============================================ SELECTION ============================================ */ ::selection { background: var(--color-navy-light); color: var(--text-inverse); } /* ============================================ TYPOGRAPHY UTILITIES ============================================ */ .type-display { font-size: clamp(var(--text-3xl), 5vw, var(--text-5xl)); font-weight: var(--weight-bold); line-height: var(--leading-tight); letter-spacing: var(--tracking-tight); color: var(--text-primary); } .type-headline-1 { font-size: var(--text-4xl); font-weight: var(--weight-bold); line-height: var(--leading-tight); letter-spacing: var(--tracking-tight); color: var(--text-primary); } .type-headline-2 { font-size: var(--text-3xl); font-weight: var(--weight-bold); line-height: var(--leading-tight); letter-spacing: var(--tracking-tight); color: var(--text-primary); } .type-headline-3 { font-size: var(--text-2xl); font-weight: var(--weight-bold); line-height: var(--leading-snug); color: var(--text-primary); } .type-title-lg { font-size: var(--text-xl); font-weight: var(--weight-semibold); line-height: var(--leading-snug); color: var(--text-primary); } .type-title { font-size: var(--text-lg); font-weight: var(--weight-semibold); line-height: var(--leading-snug); color: var(--text-primary); } .type-title-sm { font-size: var(--text-base); font-weight: var(--weight-semibold); line-height: var(--leading-normal); color: var(--text-primary); } .type-body-lg { font-size: var(--text-md); font-weight: var(--weight-regular); line-height: var(--leading-relaxed); color: var(--text-body); } .type-body { font-size: var(--text-base); font-weight: var(--weight-regular); line-height: var(--leading-relaxed); color: var(--text-body); } .type-body-sm { font-size: var(--text-sm); font-weight: var(--weight-regular); line-height: var(--leading-relaxed); color: var(--text-body); } .type-label-lg { font-size: var(--text-sm); font-weight: var(--weight-semibold); line-height: var(--leading-normal); letter-spacing: var(--tracking-wide); color: var(--text-primary); } .type-label { font-size: var(--text-xs); font-weight: var(--weight-semibold); line-height: var(--leading-normal); letter-spacing: var(--tracking-wider); text-transform: uppercase; color: var(--text-muted); } .type-caption { font-size: var(--text-xs); font-weight: var(--weight-regular); line-height: var(--leading-normal); color: var(--text-faint); } .type-overline { font-size: 11px; font-weight: var(--weight-bold); line-height: var(--leading-normal); letter-spacing: var(--tracking-widest); text-transform: uppercase; color: var(--text-muted); } .type-code { font-family: var(--font-mono); font-size: 0.9em; background: var(--surface-container); padding: 2px 6px; border-radius: var(--radius-sm); } /* ============================================ ELEVATION UTILITIES ============================================ */ .elevation-0 { box-shadow: var(--elevation-0); } .elevation-1 { box-shadow: var(--elevation-1); } .elevation-2 { box-shadow: var(--elevation-2); } .elevation-3 { box-shadow: var(--elevation-3); } .elevation-4 { box-shadow: var(--elevation-4); } .elevation-5 { box-shadow: var(--elevation-5); } /* ============================================ SURFACE UTILITIES ============================================ */ .surface-base { background-color: var(--surface-base); } .surface-dim { background-color: var(--surface-dim); } .surface-container { background-color: var(--surface-container); } .surface-inverse { background-color: var(--surface-inverse); color: var(--text-inverse); } /* ============================================ INTERACTIVE STATE LAYER Overlay that reacts to hover/focus/press. Apply to any interactive element. ============================================ */ .state-layer { position: relative; overflow: hidden; } .state-layer::after { content: ''; position: absolute; inset: 0; background: currentColor; opacity: 0; transition: opacity var(--duration-fast) var(--ease-standard); pointer-events: none; border-radius: inherit; } .state-layer:hover::after { opacity: 0.04; } .state-layer:focus-visible::after { opacity: 0.08; } .state-layer:active::after { opacity: 0.10; } /* ============================================ RIPPLE EFFECT Add .ripple to any interactive element. Requires JS initialization (see styleguide). ============================================ */ .ripple { position: relative; overflow: hidden; } .ripple-wave { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.35); transform: scale(0); animation: ripple-expand var(--duration-slower) var(--ease-decelerate) forwards; pointer-events: none; } @keyframes ripple-expand { to { transform: scale(2.5); opacity: 0; } } /* Dark ripple for light backgrounds */ .ripple-dark .ripple-wave { background: rgba(0, 0, 0, 0.12); } /* ============================================ TRANSITION UTILITIES ============================================ */ .transition-all { transition: all var(--duration-normal) var(--ease-standard); } .transition-colors { transition: color var(--duration-normal) var(--ease-standard), background-color var(--duration-normal) var(--ease-standard), border-color var(--duration-normal) var(--ease-standard); } .transition-shadow { transition: box-shadow var(--duration-normal) var(--ease-standard); } .transition-transform { transition: transform var(--duration-normal) var(--ease-standard); } /* ============================================ ENTRANCE ANIMATIONS ============================================ */ @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes fade-in-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } } @keyframes fade-in-down { from { opacity: 0; transform: translateY(-16px); } to { opacity: 1; transform: translateY(0); } } @keyframes fade-in-scale { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } @keyframes slide-in-right { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: translateX(0); } } @keyframes slide-in-left { from { opacity: 0; transform: translateX(-24px); } to { opacity: 1; transform: translateX(0); } } @keyframes scale-in { from { transform: scale(0); } to { transform: scale(1); } } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } @keyframes spin { to { transform: rotate(360deg); } } @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } .animate-fade-in { animation: fade-in var(--duration-entrance) var(--ease-decelerate) both; } .animate-fade-in-up { animation: fade-in-up var(--duration-entrance) var(--ease-decelerate) both; } .animate-fade-in-down { animation: fade-in-down var(--duration-entrance) var(--ease-decelerate) both; } .animate-fade-in-scale { animation: fade-in-scale var(--duration-entrance) var(--ease-decelerate) both; } .animate-slide-in-right { animation: slide-in-right var(--duration-slow) var(--ease-decelerate) both; } .animate-slide-in-left { animation: slide-in-left var(--duration-slow) var(--ease-decelerate) both; } .animate-pulse { animation: pulse 2s var(--ease-standard) infinite; } .animate-spin { animation: spin 1s linear infinite; } /* Staggered delays for lists */ .stagger-1 { animation-delay: 50ms; } .stagger-2 { animation-delay: 100ms; } .stagger-3 { animation-delay: 150ms; } .stagger-4 { animation-delay: 200ms; } .stagger-5 { animation-delay: 250ms; } .stagger-6 { animation-delay: 300ms; } /* Respect reduced motion */ @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; } } /* ============================================ SKELETON LOADING ============================================ */ .skeleton { background: linear-gradient(90deg, var(--surface-container) 25%, var(--surface-container-high) 50%, var(--surface-container) 75% ); background-size: 200% 100%; animation: shimmer 1.5s infinite; border-radius: var(--radius-md); color: transparent !important; } .skeleton-text { height: 1em; margin-bottom: 0.5em; border-radius: var(--radius-sm); } .skeleton-circle { border-radius: var(--radius-full); } /* ============================================ SPINNER ============================================ */ .spinner { display: inline-block; width: 20px; height: 20px; border: 2px solid var(--border-default); border-top-color: var(--color-navy); border-radius: var(--radius-full); animation: spin 0.6s linear infinite; } .spinner-sm { width: 14px; height: 14px; } .spinner-lg { width: 32px; height: 32px; border-width: 3px; } /* ============================================ DISABLED STATE ============================================ */ [disabled], .disabled { opacity: 0.38; pointer-events: none; cursor: not-allowed; } /* ============================================ SCROLL-TRIGGERED REVEAL Elements start hidden, JS adds .revealed ============================================ */ .reveal { opacity: 0; transform: translateY(20px); transition: opacity var(--duration-slow) var(--ease-decelerate), transform var(--duration-slow) var(--ease-decelerate); } .reveal.revealed { opacity: 1; transform: translateY(0); } .reveal-scale { opacity: 0; transform: scale(0.96); transition: opacity var(--duration-slow) var(--ease-decelerate), transform var(--duration-slow) var(--ease-decelerate); } .reveal-scale.revealed { opacity: 1; transform: scale(1); } /* ============================================ SPACING UTILITIES ============================================ */ .mt-0 { margin-top: var(--space-0); } .mt-1 { margin-top: var(--space-1); } .mt-2 { margin-top: var(--space-2); } .mt-3 { margin-top: var(--space-3); } .mt-4 { margin-top: var(--space-4); } .mt-6 { margin-top: var(--space-6); } .mt-8 { margin-top: var(--space-8); } .mt-10 { margin-top: var(--space-10); } .mb-0 { margin-bottom: var(--space-0); } .mb-1 { margin-bottom: var(--space-1); } .mb-2 { margin-bottom: var(--space-2); } .mb-3 { margin-bottom: var(--space-3); } .mb-4 { margin-bottom: var(--space-4); } .mb-6 { margin-bottom: var(--space-6); } .mb-8 { margin-bottom: var(--space-8); } .mb-10 { margin-bottom: var(--space-10); } .p-0 { padding: var(--space-0); } .p-2 { padding: var(--space-2); } .p-4 { padding: var(--space-4); } .p-6 { padding: var(--space-6); } .p-8 { padding: var(--space-8); } .gap-2 { gap: var(--space-2); } .gap-3 { gap: var(--space-3); } .gap-4 { gap: var(--space-4); } .gap-6 { gap: var(--space-6); } .gap-8 { gap: var(--space-8); } /* ============================================ RESPONSIVE CONTAINER ============================================ */ .container { width: 100%; max-width: var(--content-width); margin-left: auto; margin-right: auto; padding-left: var(--space-6); padding-right: var(--space-6); } .container-narrow { max-width: var(--content-narrow); } .container-wide { max-width: var(--content-wide); }