--- a/styles.css +++ b/styles.css @@ -1,116 +1,913 @@ -/* doany.ai onboarding styles — current production */ - -* { +/* doany.ai — Premium Design System + Tokens from design-tokens.json applied as CSS custom properties */ + +/* ============================================ + DESIGN TOKENS (CSS Custom Properties) + ============================================ */ + +:root { + /* Brand */ + --color-primary: #1A1A2E; + --color-primary-hover: #2D2D44; + --color-accent: #6366F1; + --color-accent-hover: #4F46E5; + --color-accent-light: #EEF2FF; + --color-surface: #FAFAFA; + --color-surface-elevated: #FFFFFF; + + /* Semantic */ + --color-success: #059669; + --color-success-light: #ECFDF5; + --color-success-border: #A7F3D0; + --color-error: #DC2626; + --color-error-light: #FEF2F2; + --color-error-border: #FECACA; + + /* Neutral */ + --color-neutral-900: #111827; + --color-neutral-800: #1F2937; + --color-neutral-700: #374151; + --color-neutral-600: #4B5563; + --color-neutral-500: #6B7280; + --color-neutral-400: #9CA3AF; + --color-neutral-300: #D1D5DB; + --color-neutral-200: #E5E7EB; + --color-neutral-100: #F3F4F6; + --color-neutral-50: #F9FAFB; + + /* Typography */ + --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace; + + /* Spacing */ + --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; + + /* Radius */ + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 14px; + --radius-xl: 20px; + --radius-full: 9999px; + + /* Shadows */ + --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.05); + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04); + --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08), 0 1px 4px rgba(0, 0, 0, 0.04); + --shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.1), 0 4px 12px rgba(0, 0, 0, 0.04); + --shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.14), 0 8px 20px rgba(0, 0, 0, 0.06); + --shadow-focus: 0 0 0 3px rgba(99, 102, 241, 0.25); + + /* Motion */ + --duration-instant: 100ms; + --duration-fast: 150ms; + --duration-normal: 250ms; + --duration-slow: 400ms; + --duration-entrance: 500ms; + --ease-default: cubic-bezier(0.4, 0, 0.2, 1); + --ease-out: cubic-bezier(0, 0, 0.2, 1); + --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); +} + +/* ============================================ + RESET & BASE + ============================================ */ + +*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } +html { + font-size: 16px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; +} + body { - font-family: Arial, sans-serif; - background: #f5f5f5; + font-family: var(--font-sans); + color: var(--color-neutral-900); + background: var(--color-surface); min-height: 100vh; -} + line-height: 1.6; +} + +/* ============================================ + SKIP LINK (Accessibility) + ============================================ */ + +.skip-link { + position: absolute; + top: -100%; + left: var(--space-4); + padding: var(--space-2) var(--space-4); + background: var(--color-accent); + color: white; + border-radius: var(--radius-sm); + font-size: 13px; + font-weight: 500; + text-decoration: none; + z-index: 1000; + transition: top var(--duration-fast) var(--ease-out); +} + +.skip-link:focus { + top: var(--space-4); +} + +/* ============================================ + HEADER + ============================================ */ .header { display: flex; align-items: center; - gap: 8px; - padding: 12px 20px; - background: white; - border-bottom: 1px solid #eee; -} + gap: var(--space-3); + padding: var(--space-4) var(--space-6); + background: var(--color-surface-elevated); + border-bottom: 1px solid var(--color-neutral-200); +} + +.header-logo { + display: flex; + align-items: center; + gap: var(--space-3); + text-decoration: none; +} + +.header-wordmark { + font-size: 18px; + font-weight: 700; + color: var(--color-primary); + letter-spacing: -0.03em; +} + +.header-logo-icon { + width: 28px; + height: 28px; + background: var(--color-accent); + border-radius: var(--radius-sm); + display: flex; + align-items: center; + justify-content: center; + color: white; + font-weight: 700; + font-size: 14px; +} + +/* ============================================ + LAYOUT — Centered content area + ============================================ */ + +.onboarding-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + min-height: calc(100vh - 57px); + padding: var(--space-12) var(--space-6) var(--space-16); +} + +/* ============================================ + PROGRESS BAR + ============================================ */ + +.progress-bar { + display: flex; + align-items: center; + gap: 0; + margin-bottom: var(--space-10); + width: 100%; + max-width: 320px; +} + +.progress-step { + display: flex; + align-items: center; + flex: 1; +} + +.progress-step:last-child { + flex: 0; +} + +.progress-dot { + width: 32px; + height: 32px; + border-radius: var(--radius-full); + border: 2px solid var(--color-neutral-300); + background: var(--color-surface-elevated); + display: flex; + align-items: center; + justify-content: center; + font-size: 13px; + font-weight: 600; + color: var(--color-neutral-400); + transition: all var(--duration-normal) var(--ease-default); + flex-shrink: 0; + position: relative; +} + +.progress-line { + flex: 1; + height: 2px; + background: var(--color-neutral-200); + transition: background var(--duration-normal) var(--ease-default); +} + +.progress-step.active .progress-dot { + border-color: var(--color-accent); + background: var(--color-accent); + color: white; +} + +.progress-step.completed .progress-dot { + border-color: var(--color-success); + background: var(--color-success); + color: white; +} + +.progress-step.completed .progress-line { + background: var(--color-success); +} + +.progress-dot .check-icon { + display: none; +} + +.progress-step.completed .progress-dot .step-number { + display: none; +} + +.progress-step.completed .progress-dot .check-icon { + display: block; +} + +/* ============================================ + CARD (Step container) + ============================================ */ .onboarding-step { display: none; - max-width: 480px; - margin: 30px auto; - background: white; - padding: 24px; - border-radius: 4px; - box-shadow: 0 1px 3px rgba(0,0,0,0.08); + width: 100%; + max-width: 440px; + background: var(--color-surface-elevated); + padding: var(--space-10); + border-radius: var(--radius-xl); + box-shadow: var(--shadow-lg); + animation: cardEnter var(--duration-entrance) var(--ease-out); } .onboarding-step.active { display: block; } -/* No progress indicator styles */ - -.form-row { - margin-bottom: 10px; -} - -.form-row label { +@keyframes cardEnter { + from { + opacity: 0; + transform: translateY(12px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ============================================ + TYPOGRAPHY + ============================================ */ + +.step-heading { + font-size: 24px; + font-weight: 700; + color: var(--color-neutral-900); + letter-spacing: -0.025em; + line-height: 1.25; + margin-bottom: var(--space-2); +} + +.step-subheading { + font-size: 15px; + color: var(--color-neutral-500); + line-height: 1.5; + margin-bottom: var(--space-8); +} + +/* ============================================ + FORM ELEMENTS + ============================================ */ + +.form-group { + margin-bottom: var(--space-5); +} + +.form-label { display: block; - font-size: 12px; - color: #999; - margin-bottom: 3px; -} - -.form-row input, -.form-row select { + font-size: 13px; + font-weight: 600; + color: var(--color-neutral-700); + margin-bottom: var(--space-2); + letter-spacing: 0.01em; +} + +.form-input, +.form-select, +.form-textarea { width: 100%; - padding: 7px 10px; - border: 1px solid #ddd; - border-radius: 3px; + padding: var(--space-3) var(--space-4); + border: 1.5px solid var(--color-neutral-200); + border-radius: var(--radius-md); + font-size: 15px; + font-family: var(--font-sans); + color: var(--color-neutral-900); + background: var(--color-surface-elevated); + transition: border-color var(--duration-fast) var(--ease-default), + box-shadow var(--duration-fast) var(--ease-default); + min-height: 48px; +} + +.form-input::placeholder, +.form-textarea::placeholder { + color: var(--color-neutral-400); +} + +.form-input:hover, +.form-select:hover, +.form-textarea:hover { + border-color: var(--color-neutral-300); +} + +.form-input:focus, +.form-select:focus, +.form-textarea:focus { + outline: none; + border-color: var(--color-accent); + box-shadow: var(--shadow-focus); +} + +/* Error state */ +.form-input.error, +.form-select.error, +.form-textarea.error { + border-color: var(--color-error); + background: var(--color-error-light); +} + +.form-input.error:focus, +.form-select.error:focus { + box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15); +} + +/* Success state */ +.form-input.valid { + border-color: var(--color-success); +} + +.form-error { + display: none; font-size: 13px; - color: #333; -} - -.form-row input:focus, -.form-row select:focus { + color: var(--color-error); + margin-top: var(--space-1); + padding-left: var(--space-1); + line-height: 1.4; +} + +.form-error.visible { + display: block; + animation: errorEnter var(--duration-fast) var(--ease-out); +} + +@keyframes errorEnter { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } +} + +/* Password field with toggle */ +.password-wrapper { + position: relative; +} + +.password-wrapper .form-input { + padding-right: var(--space-12); +} + +.password-toggle { + position: absolute; + right: var(--space-3); + top: 50%; + transform: translateY(-50%); + background: none; + border: none; + color: var(--color-neutral-400); + cursor: pointer; + padding: var(--space-1); + border-radius: var(--radius-sm); + font-size: 13px; + font-weight: 500; + font-family: var(--font-sans); + transition: color var(--duration-fast) var(--ease-default); +} + +.password-toggle:hover { + color: var(--color-neutral-600); +} + +.password-toggle:focus-visible { outline: none; - border-color: #007bff; -} - -/* Primary button — inconsistent across steps */ + box-shadow: var(--shadow-focus); +} + +/* Workspace URL prefix */ +.url-input-group { + display: flex; + align-items: center; + border: 1.5px solid var(--color-neutral-200); + border-radius: var(--radius-md); + overflow: hidden; + transition: border-color var(--duration-fast) var(--ease-default), + box-shadow var(--duration-fast) var(--ease-default); + min-height: 48px; +} + +.url-input-group:hover { + border-color: var(--color-neutral-300); +} + +.url-input-group:focus-within { + border-color: var(--color-accent); + box-shadow: var(--shadow-focus); +} + +.url-prefix { + padding: var(--space-3) 0 var(--space-3) var(--space-4); + font-size: 15px; + color: var(--color-neutral-400); + white-space: nowrap; + user-select: none; +} + +.url-input-group .form-input { + border: none; + min-height: auto; + padding-left: var(--space-1); +} + +.url-input-group .form-input:focus { + box-shadow: none; +} + +/* Checkbox */ +.checkbox-group { + display: flex; + align-items: flex-start; + gap: var(--space-3); + margin-top: var(--space-6); +} + +.checkbox-input { + appearance: none; + width: 20px; + height: 20px; + border: 1.5px solid var(--color-neutral-300); + border-radius: var(--radius-sm); + flex-shrink: 0; + cursor: pointer; + position: relative; + transition: all var(--duration-fast) var(--ease-default); + margin-top: 1px; +} + +.checkbox-input:hover { + border-color: var(--color-accent); +} + +.checkbox-input:checked { + background: var(--color-accent); + border-color: var(--color-accent); +} + +.checkbox-input:checked::after { + content: ''; + position: absolute; + left: 6px; + top: 2px; + width: 5px; + height: 10px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.checkbox-input:focus-visible { + outline: none; + box-shadow: var(--shadow-focus); +} + +.checkbox-label { + font-size: 13px; + color: var(--color-neutral-600); + line-height: 1.5; + cursor: pointer; +} + +.checkbox-label a { + color: var(--color-accent); + text-decoration: none; + font-weight: 500; +} + +.checkbox-label a:hover { + text-decoration: underline; +} + +/* Textarea */ +.form-textarea { + resize: vertical; + min-height: 100px; + line-height: 1.5; +} + +/* ============================================ + BUTTONS + ============================================ */ + .btn-primary { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + width: 100%; + padding: var(--space-3) var(--space-6); + min-height: 48px; + background: var(--color-primary); + color: white; + font-size: 15px; + font-weight: 600; + font-family: var(--font-sans); + border: none; + border-radius: var(--radius-md); + cursor: pointer; + transition: all var(--duration-fast) var(--ease-default); + letter-spacing: -0.01em; + position: relative; +} + +.btn-primary:hover { + background: var(--color-primary-hover); + transform: translateY(-1px); + box-shadow: var(--shadow-md); +} + +.btn-primary:active { + transform: translateY(0); + box-shadow: var(--shadow-sm); +} + +.btn-primary:focus-visible { + outline: none; + box-shadow: var(--shadow-focus); +} + +.btn-primary:disabled, +.btn-primary.loading { + opacity: 0.6; + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +.btn-secondary { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-6); + min-height: 48px; + background: transparent; + color: var(--color-neutral-600); + font-size: 15px; + font-weight: 500; + font-family: var(--font-sans); + border: 1.5px solid var(--color-neutral-200); + border-radius: var(--radius-md); + cursor: pointer; + transition: all var(--duration-fast) var(--ease-default); +} + +.btn-secondary:hover { + border-color: var(--color-neutral-300); + background: var(--color-neutral-50); +} + +.btn-secondary:focus-visible { + outline: none; + box-shadow: var(--shadow-focus); +} + +.btn-row { + display: flex; + gap: var(--space-3); + margin-top: var(--space-8); +} + +.btn-row .btn-secondary { + flex-shrink: 0; +} + +.btn-row .btn-primary { + flex: 1; +} + +.btn-text { + background: none; + border: none; + color: var(--color-neutral-500); + font-size: 14px; + font-weight: 500; + font-family: var(--font-sans); + cursor: pointer; + padding: var(--space-3); + border-radius: var(--radius-sm); + transition: color var(--duration-fast) var(--ease-default); + display: block; + margin: var(--space-3) auto 0; +} + +.btn-text:hover { + color: var(--color-neutral-700); +} + +.btn-text:focus-visible { + outline: none; + box-shadow: var(--shadow-focus); +} + +/* ============================================ + LOADING SPINNER + ============================================ */ + +.spinner { display: inline-block; - padding: 8px 20px; - background: #ff6633; - color: white; + width: 18px; + height: 18px; + border: 2px solid rgba(255, 255, 255, 0.3); + border-top-color: white; + border-radius: var(--radius-full); + animation: spin 0.6s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +.btn-primary .btn-label, +.btn-primary .spinner { + transition: opacity var(--duration-fast) var(--ease-default); +} + +.btn-primary.loading .btn-label { + opacity: 0; +} + +.btn-primary:not(.loading) .spinner { + display: none; +} + +.btn-primary.loading .spinner { + position: absolute; +} + +/* ============================================ + ERROR BANNER (network errors) + ============================================ */ + +.error-banner { + display: none; + align-items: center; + gap: var(--space-3); + padding: var(--space-3) var(--space-4); + background: var(--color-error-light); + border: 1px solid var(--color-error-border); + border-radius: var(--radius-md); + margin-bottom: var(--space-6); + font-size: 14px; + color: var(--color-error); + animation: errorEnter var(--duration-fast) var(--ease-out); +} + +.error-banner.visible { + display: flex; +} + +.error-banner-icon { + flex-shrink: 0; + font-size: 16px; +} + +.error-banner-text { + flex: 1; +} + +.error-banner-dismiss { + background: none; + border: none; + color: var(--color-error); + cursor: pointer; + padding: var(--space-1); + font-size: 18px; + line-height: 1; + opacity: 0.6; +} + +.error-banner-dismiss:hover { + opacity: 1; +} + +/* ============================================ + SUCCESS STATE (Step 3 completion) + ============================================ */ + +.success-content { + text-align: center; + padding: var(--space-6) 0; +} + +.success-icon { + width: 64px; + height: 64px; + background: var(--color-success-light); + border-radius: var(--radius-full); + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto var(--space-6); + animation: successPop var(--duration-slow) var(--ease-spring); +} + +.success-icon svg { + width: 28px; + height: 28px; + color: var(--color-success); +} + +@keyframes successPop { + 0% { transform: scale(0); opacity: 0; } + 60% { transform: scale(1.15); } + 100% { transform: scale(1); opacity: 1; } +} + +.success-heading { + font-size: 24px; + font-weight: 700; + color: var(--color-neutral-900); + letter-spacing: -0.025em; + margin-bottom: var(--space-2); +} + +.success-text { + font-size: 15px; + color: var(--color-neutral-500); + margin-bottom: var(--space-8); +} + +/* ============================================ + EMPTY STATE (Dashboard) + ============================================ */ + +.empty-state { + text-align: center; + padding: var(--space-16) var(--space-6); + max-width: 400px; + margin: 0 auto; +} + +.empty-illustration { + width: 180px; + height: 140px; + margin: 0 auto var(--space-8); + opacity: 0.9; +} + +.empty-heading { + font-size: 20px; + font-weight: 700; + color: var(--color-neutral-900); + margin-bottom: var(--space-2); + letter-spacing: -0.02em; +} + +.empty-text { + font-size: 15px; + color: var(--color-neutral-500); + margin-bottom: var(--space-8); + line-height: 1.6; +} + +.empty-state .btn-primary { + width: auto; + display: inline-flex; + padding: var(--space-3) var(--space-8); +} + +.empty-hint { font-size: 13px; - font-weight: bold; - border: none; - border-radius: 3px; - cursor: pointer; - text-align: center; - text-transform: uppercase; - letter-spacing: 1px; -} - -.btn-primary:hover { - opacity: 0.85; -} - -.btn-secondary { - display: inline-block; - padding: 8px 20px; - background: transparent; - color: #999; - font-size: 13px; - border: 1px solid #ddd; - border-radius: 3px; - cursor: pointer; - text-align: center; -} - -/* No focus-visible styles for keyboard navigation */ -/* No disabled button styles */ -/* No loading spinner styles */ -/* No error message styles */ -/* No skeleton/placeholder styles */ -/* No transition or motion styles */ -/* No responsive breakpoints */ - -textarea { - resize: vertical; - border-radius: 3px; - font-family: Arial, sans-serif; -} - -/* Checkbox is unstyled, tiny default browser checkbox */ -input[type="checkbox"] { - margin-right: 4px; -} + color: var(--color-neutral-400); + margin-top: var(--space-4); +} + +/* ============================================ + ARIA LIVE REGION (Screen reader) + ============================================ */ + +.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; +} + +/* ============================================ + FOCUS-VISIBLE (Keyboard users only) + ============================================ */ + +*:focus { + outline: none; +} + +*:focus-visible { + outline: none; + box-shadow: var(--shadow-focus); + border-radius: var(--radius-sm); +} + +/* ============================================ + RESPONSIVE + ============================================ */ + +@media (max-width: 480px) { + .onboarding-container { + padding: var(--space-8) var(--space-4) var(--space-12); + } + + .onboarding-step { + padding: var(--space-6); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + } + + .step-heading { + font-size: 22px; + } + + .progress-bar { + max-width: 260px; + } + + .btn-row { + flex-direction: column-reverse; + } + + .btn-row .btn-secondary { + width: 100%; + } + + .header { + padding: var(--space-3) var(--space-4); + } +} + +@media (max-width: 360px) { + .onboarding-step { + padding: var(--space-5); + } + + .step-heading { + font-size: 20px; + } +} + +/* ============================================ + REDUCED MOTION + ============================================ */ + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + transition-duration: 0.01ms !important; + } +}