Girish Jeswani commited on
Commit
01db13e
·
1 Parent(s): 1a19944

add signup page

Browse files
phd-advisor-frontend/src/components/Signup.js ADDED
@@ -0,0 +1,407 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState } from 'react';
2
+ import { Eye, EyeOff, Mail, Lock, User, ArrowRight, BookOpen, Phone, GraduationCap } from 'lucide-react';
3
+ import '../styles/Signup.css';
4
+
5
+ const Signup = ({ onNavigateToLogin, onNavigateToHome }) => {
6
+ const [showPassword, setShowPassword] = useState(false);
7
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false);
8
+ const [formData, setFormData] = useState({
9
+ firstName: '',
10
+ lastName: '',
11
+ email: '',
12
+ password: '',
13
+ confirmPassword: '',
14
+ academicStage: '',
15
+ researchArea: ''
16
+ });
17
+ const [isLoading, setIsLoading] = useState(false);
18
+ const [errors, setErrors] = useState({});
19
+
20
+ const academicStages = [
21
+ { value: '', label: 'Select your stage' },
22
+ { value: 'prospective', label: 'Prospective PhD Student' },
23
+ { value: 'first-year', label: 'First Year PhD' },
24
+ { value: 'coursework', label: 'Coursework Phase' },
25
+ { value: 'qualifying', label: 'Qualifying Exams' },
26
+ { value: 'dissertation', label: 'Dissertation Phase' },
27
+ { value: 'writing', label: 'Writing & Defense' },
28
+ { value: 'postdoc', label: 'Postdoc' },
29
+ { value: 'faculty', label: 'Faculty/Researcher' }
30
+ ];
31
+
32
+ const handleInputChange = (e) => {
33
+ const { name, value } = e.target;
34
+ setFormData(prev => ({
35
+ ...prev,
36
+ [name]: value
37
+ }));
38
+ // Clear error when user starts typing
39
+ if (errors[name]) {
40
+ setErrors(prev => ({
41
+ ...prev,
42
+ [name]: ''
43
+ }));
44
+ }
45
+ };
46
+
47
+ const validateForm = () => {
48
+ const newErrors = {};
49
+
50
+ if (!formData.firstName.trim()) {
51
+ newErrors.firstName = 'First name is required';
52
+ }
53
+
54
+ if (!formData.lastName.trim()) {
55
+ newErrors.lastName = 'Last name is required';
56
+ }
57
+
58
+ if (!formData.email) {
59
+ newErrors.email = 'Email is required';
60
+ } else if (!/\S+@\S+\.\S+/.test(formData.email)) {
61
+ newErrors.email = 'Please enter a valid email address';
62
+ }
63
+
64
+ if (!formData.password) {
65
+ newErrors.password = 'Password is required';
66
+ } else if (formData.password.length < 8) {
67
+ newErrors.password = 'Password must be at least 8 characters';
68
+ } else if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(formData.password)) {
69
+ newErrors.password = 'Password must contain uppercase, lowercase, and number';
70
+ }
71
+
72
+ if (!formData.confirmPassword) {
73
+ newErrors.confirmPassword = 'Please confirm your password';
74
+ } else if (formData.password !== formData.confirmPassword) {
75
+ newErrors.confirmPassword = 'Passwords do not match';
76
+ }
77
+
78
+ if (!formData.academicStage) {
79
+ newErrors.academicStage = 'Please select your academic stage';
80
+ }
81
+
82
+ setErrors(newErrors);
83
+ return Object.keys(newErrors).length === 0;
84
+ };
85
+
86
+ const handleSubmit = async (e) => {
87
+ e.preventDefault();
88
+
89
+ if (!validateForm()) return;
90
+
91
+ setIsLoading(true);
92
+
93
+ try {
94
+ // Simulate API call
95
+ await new Promise(resolve => setTimeout(resolve, 2000));
96
+
97
+ // For demo purposes, we'll just navigate to home
98
+ // In real implementation, handle user registration here
99
+ console.log('Signup attempt:', formData);
100
+ onNavigateToHome?.();
101
+
102
+ } catch (error) {
103
+ console.error('Signup error:', error);
104
+ setErrors({ submit: 'Registration failed. Please try again.' });
105
+ } finally {
106
+ setIsLoading(false);
107
+ }
108
+ };
109
+
110
+ const handleGoogleSignUp = () => {
111
+ console.log('Google Sign Up clicked');
112
+ // Future Google Auth integration will go here
113
+ };
114
+
115
+ const handlePhoneSignUp = () => {
116
+ console.log('Phone Sign Up clicked');
117
+ // Future Phone Auth integration will go here
118
+ };
119
+
120
+ return (
121
+ <div className="signup-page">
122
+ <div className="signup-container">
123
+ {/* Header */}
124
+ <div className="signup-header">
125
+ <div className="logo-container">
126
+ <BookOpen className="logo-icon" />
127
+ </div>
128
+ <h1 className="signup-title">Join Our Community</h1>
129
+ <p className="signup-subtitle">
130
+ Create your account to get personalized PhD guidance from expert advisors
131
+ </p>
132
+ </div>
133
+
134
+ {/* Main Signup Form */}
135
+ <div className="signup-form-container">
136
+ <form onSubmit={handleSubmit} className="signup-form">
137
+
138
+ {/* Name Fields Row */}
139
+ <div className="form-row">
140
+ <div className="form-group">
141
+ <label htmlFor="firstName" className="form-label">
142
+ First Name
143
+ </label>
144
+ <div className="input-container">
145
+ <User className="input-icon" />
146
+ <input
147
+ type="text"
148
+ id="firstName"
149
+ name="firstName"
150
+ value={formData.firstName}
151
+ onChange={handleInputChange}
152
+ className={`form-input ${errors.firstName ? 'error' : ''}`}
153
+ placeholder="First name"
154
+ disabled={isLoading}
155
+ />
156
+ </div>
157
+ {errors.firstName && (
158
+ <span className="error-message">{errors.firstName}</span>
159
+ )}
160
+ </div>
161
+
162
+ <div className="form-group">
163
+ <label htmlFor="lastName" className="form-label">
164
+ Last Name
165
+ </label>
166
+ <div className="input-container">
167
+ <User className="input-icon" />
168
+ <input
169
+ type="text"
170
+ id="lastName"
171
+ name="lastName"
172
+ value={formData.lastName}
173
+ onChange={handleInputChange}
174
+ className={`form-input ${errors.lastName ? 'error' : ''}`}
175
+ placeholder="Last name"
176
+ disabled={isLoading}
177
+ />
178
+ </div>
179
+ {errors.lastName && (
180
+ <span className="error-message">{errors.lastName}</span>
181
+ )}
182
+ </div>
183
+ </div>
184
+
185
+ {/* Email Field */}
186
+ <div className="form-group">
187
+ <label htmlFor="email" className="form-label">
188
+ Email Address
189
+ </label>
190
+ <div className="input-container">
191
+ <Mail className="input-icon" />
192
+ <input
193
+ type="email"
194
+ id="email"
195
+ name="email"
196
+ value={formData.email}
197
+ onChange={handleInputChange}
198
+ className={`form-input ${errors.email ? 'error' : ''}`}
199
+ placeholder="Enter your email"
200
+ disabled={isLoading}
201
+ />
202
+ </div>
203
+ {errors.email && (
204
+ <span className="error-message">{errors.email}</span>
205
+ )}
206
+ </div>
207
+
208
+ {/* Password Fields Row */}
209
+ <div className="form-row">
210
+ <div className="form-group">
211
+ <label htmlFor="password" className="form-label">
212
+ Password
213
+ </label>
214
+ <div className="input-container">
215
+ <Lock className="input-icon" />
216
+ <input
217
+ type={showPassword ? 'text' : 'password'}
218
+ id="password"
219
+ name="password"
220
+ value={formData.password}
221
+ onChange={handleInputChange}
222
+ className={`form-input ${errors.password ? 'error' : ''}`}
223
+ placeholder="Create password"
224
+ disabled={isLoading}
225
+ />
226
+ <button
227
+ type="button"
228
+ onClick={() => setShowPassword(!showPassword)}
229
+ className="password-toggle"
230
+ disabled={isLoading}
231
+ >
232
+ {showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
233
+ </button>
234
+ </div>
235
+ {errors.password && (
236
+ <span className="error-message">{errors.password}</span>
237
+ )}
238
+ </div>
239
+
240
+ <div className="form-group">
241
+ <label htmlFor="confirmPassword" className="form-label">
242
+ Confirm Password
243
+ </label>
244
+ <div className="input-container">
245
+ <Lock className="input-icon" />
246
+ <input
247
+ type={showConfirmPassword ? 'text' : 'password'}
248
+ id="confirmPassword"
249
+ name="confirmPassword"
250
+ value={formData.confirmPassword}
251
+ onChange={handleInputChange}
252
+ className={`form-input ${errors.confirmPassword ? 'error' : ''}`}
253
+ placeholder="Confirm password"
254
+ disabled={isLoading}
255
+ />
256
+ <button
257
+ type="button"
258
+ onClick={() => setShowConfirmPassword(!showConfirmPassword)}
259
+ className="password-toggle"
260
+ disabled={isLoading}
261
+ >
262
+ {showConfirmPassword ? <EyeOff size={16} /> : <Eye size={16} />}
263
+ </button>
264
+ </div>
265
+ {errors.confirmPassword && (
266
+ <span className="error-message">{errors.confirmPassword}</span>
267
+ )}
268
+ </div>
269
+ </div>
270
+
271
+ {/* Academic Stage */}
272
+ <div className="form-group">
273
+ <label htmlFor="academicStage" className="form-label">
274
+ Academic Stage
275
+ </label>
276
+ <div className="input-container">
277
+ <GraduationCap className="input-icon" />
278
+ <select
279
+ id="academicStage"
280
+ name="academicStage"
281
+ value={formData.academicStage}
282
+ onChange={handleInputChange}
283
+ className={`form-select ${errors.academicStage ? 'error' : ''}`}
284
+ disabled={isLoading}
285
+ >
286
+ {academicStages.map(stage => (
287
+ <option key={stage.value} value={stage.value}>
288
+ {stage.label}
289
+ </option>
290
+ ))}
291
+ </select>
292
+ </div>
293
+ {errors.academicStage && (
294
+ <span className="error-message">{errors.academicStage}</span>
295
+ )}
296
+ </div>
297
+
298
+ {/* Research Area (Optional) */}
299
+ <div className="form-group">
300
+ <label htmlFor="researchArea" className="form-label">
301
+ Research Area <span className="optional">(Optional)</span>
302
+ </label>
303
+ <div className="input-container">
304
+ <BookOpen className="input-icon" />
305
+ <input
306
+ type="text"
307
+ id="researchArea"
308
+ name="researchArea"
309
+ value={formData.researchArea}
310
+ onChange={handleInputChange}
311
+ className="form-input"
312
+ placeholder="e.g., Computer Science, Biology, Psychology..."
313
+ disabled={isLoading}
314
+ />
315
+ </div>
316
+ </div>
317
+
318
+ {/* Terms and Privacy */}
319
+ <div className="terms-section">
320
+ <p className="terms-text">
321
+ By creating an account, you agree to our{' '}
322
+ <button type="button" className="link-btn">Terms of Service</button>
323
+ {' '}and{' '}
324
+ <button type="button" className="link-btn">Privacy Policy</button>
325
+ </p>
326
+ </div>
327
+
328
+ {/* Submit Error */}
329
+ {errors.submit && (
330
+ <div className="submit-error">
331
+ {errors.submit}
332
+ </div>
333
+ )}
334
+
335
+ {/* Submit Button */}
336
+ <button
337
+ type="submit"
338
+ className={`submit-btn ${isLoading ? 'loading' : ''}`}
339
+ disabled={isLoading}
340
+ >
341
+ {isLoading ? (
342
+ <>
343
+ <div className="loading-spinner"></div>
344
+ Creating Account...
345
+ </>
346
+ ) : (
347
+ <>
348
+ Create Account
349
+ <ArrowRight size={16} />
350
+ </>
351
+ )}
352
+ </button>
353
+ </form>
354
+
355
+ {/* Divider */}
356
+ <div className="divider">
357
+ <span>or sign up with</span>
358
+ </div>
359
+
360
+ {/* Social Signup Options */}
361
+ <div className="social-signup">
362
+ <button
363
+ type="button"
364
+ className="google-btn"
365
+ onClick={handleGoogleSignUp}
366
+ disabled={isLoading}
367
+ >
368
+ <svg className="google-icon" viewBox="0 0 24 24">
369
+ <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
370
+ <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
371
+ <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
372
+ <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
373
+ </svg>
374
+ Continue with Google
375
+ </button>
376
+
377
+ <button
378
+ type="button"
379
+ className="phone-btn"
380
+ onClick={handlePhoneSignUp}
381
+ disabled={isLoading}
382
+ >
383
+ <Phone size={16} />
384
+ Continue with Phone
385
+ </button>
386
+ </div>
387
+ </div>
388
+
389
+ {/* Footer */}
390
+ <div className="signup-footer">
391
+ <p>
392
+ Already have an account?{' '}
393
+ <button
394
+ type="button"
395
+ className="link-btn"
396
+ onClick={onNavigateToLogin}
397
+ >
398
+ Sign in here
399
+ </button>
400
+ </p>
401
+ </div>
402
+ </div>
403
+ </div>
404
+ );
405
+ };
406
+
407
+ export default Signup;
phd-advisor-frontend/src/styles/Signup.css ADDED
@@ -0,0 +1,594 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Signup.css */
2
+
3
+ .signup-page {
4
+ min-height: 100vh;
5
+ background: var(--bg-gradient);
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ padding: 24px 16px;
10
+ }
11
+
12
+ .signup-container {
13
+ width: 100%;
14
+ max-width: 520px;
15
+ background: var(--bg-primary);
16
+ border: 1px solid var(--border-primary);
17
+ border-radius: 20px;
18
+ box-shadow: var(--shadow-xl);
19
+ backdrop-filter: blur(20px);
20
+ -webkit-backdrop-filter: blur(20px);
21
+ overflow: hidden;
22
+ animation: fadeInUp 0.6s ease-out;
23
+ }
24
+
25
+ [data-theme="dark"] .signup-container {
26
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.6);
27
+ }
28
+
29
+ /* Header Section */
30
+ .signup-header {
31
+ text-align: center;
32
+ padding: 40px 32px 32px 32px;
33
+ background: var(--bg-secondary);
34
+ border-bottom: 1px solid var(--border-primary);
35
+ }
36
+
37
+ .logo-container {
38
+ width: 56px;
39
+ height: 56px;
40
+ background: var(--accent-gradient);
41
+ border-radius: 16px;
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ margin: 0 auto 20px auto;
46
+ box-shadow: var(--shadow-md);
47
+ }
48
+
49
+ .logo-icon {
50
+ width: 28px;
51
+ height: 28px;
52
+ color: #FFFFFF;
53
+ }
54
+
55
+ .signup-title {
56
+ font-size: 28px;
57
+ font-weight: 700;
58
+ color: var(--text-primary);
59
+ margin: 0 0 8px 0;
60
+ line-height: 1.2;
61
+ }
62
+
63
+ .signup-subtitle {
64
+ font-size: 16px;
65
+ color: var(--text-secondary);
66
+ margin: 0;
67
+ line-height: 1.5;
68
+ }
69
+
70
+ /* Form Container */
71
+ .signup-form-container {
72
+ padding: 32px;
73
+ }
74
+
75
+ .signup-form {
76
+ margin-bottom: 24px;
77
+ }
78
+
79
+ /* Form Groups and Rows */
80
+ .form-group {
81
+ margin-bottom: 20px;
82
+ }
83
+
84
+ .form-row {
85
+ display: grid;
86
+ grid-template-columns: 1fr 1fr;
87
+ gap: 16px;
88
+ margin-bottom: 20px;
89
+ }
90
+
91
+ .form-row .form-group {
92
+ margin-bottom: 0;
93
+ }
94
+
95
+ .form-label {
96
+ display: block;
97
+ font-size: 14px;
98
+ font-weight: 600;
99
+ color: var(--text-primary);
100
+ margin-bottom: 8px;
101
+ }
102
+
103
+ .optional {
104
+ font-weight: 400;
105
+ color: var(--text-tertiary);
106
+ font-size: 13px;
107
+ }
108
+
109
+ /* Input Container */
110
+ .input-container {
111
+ position: relative;
112
+ display: flex;
113
+ align-items: center;
114
+ }
115
+
116
+ .input-icon {
117
+ position: absolute;
118
+ left: 16px;
119
+ width: 16px;
120
+ height: 16px;
121
+ color: var(--text-tertiary);
122
+ z-index: 1;
123
+ transition: color 0.2s ease;
124
+ }
125
+
126
+ .form-input,
127
+ .form-select {
128
+ width: 100%;
129
+ padding: 16px 16px 16px 48px;
130
+ border: 1px solid var(--border-secondary);
131
+ border-radius: 12px;
132
+ background: var(--input-bg);
133
+ color: var(--text-primary);
134
+ font-size: 16px;
135
+ transition: all 0.2s ease;
136
+ outline: none;
137
+ }
138
+
139
+ .form-input::placeholder {
140
+ color: var(--text-tertiary);
141
+ }
142
+
143
+ .form-select {
144
+ cursor: pointer;
145
+ appearance: none;
146
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
147
+ background-position: right 12px center;
148
+ background-repeat: no-repeat;
149
+ background-size: 16px;
150
+ padding-right: 48px;
151
+ }
152
+
153
+ [data-theme="dark"] .form-select {
154
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%9ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
155
+ }
156
+
157
+ .form-input:focus,
158
+ .form-select:focus {
159
+ border-color: var(--accent-primary);
160
+ box-shadow: var(--input-focus-shadow);
161
+ }
162
+
163
+ .form-input:focus + .input-icon,
164
+ .form-select:focus + .input-icon,
165
+ .input-container:focus-within .input-icon {
166
+ color: var(--accent-primary);
167
+ }
168
+
169
+ .form-input.error,
170
+ .form-select.error {
171
+ border-color: var(--error-text);
172
+ background: var(--error-bg);
173
+ }
174
+
175
+ /* Password Toggle */
176
+ .password-toggle {
177
+ position: absolute;
178
+ right: 16px;
179
+ background: none;
180
+ border: none;
181
+ color: var(--text-tertiary);
182
+ cursor: pointer;
183
+ padding: 4px;
184
+ border-radius: 6px;
185
+ transition: all 0.2s ease;
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
189
+ z-index: 2;
190
+ }
191
+
192
+ .password-toggle:hover {
193
+ color: var(--text-primary);
194
+ background: var(--bg-secondary);
195
+ }
196
+
197
+ /* Terms Section */
198
+ .terms-section {
199
+ margin-bottom: 24px;
200
+ padding: 16px;
201
+ background: var(--bg-secondary);
202
+ border: 1px solid var(--border-primary);
203
+ border-radius: 12px;
204
+ }
205
+
206
+ .terms-text {
207
+ font-size: 14px;
208
+ color: var(--text-secondary);
209
+ margin: 0;
210
+ line-height: 1.5;
211
+ text-align: center;
212
+ }
213
+
214
+ /* Error Messages */
215
+ .error-message {
216
+ display: block;
217
+ color: var(--error-text);
218
+ font-size: 13px;
219
+ margin-top: 6px;
220
+ font-weight: 500;
221
+ }
222
+
223
+ .submit-error {
224
+ background: var(--error-bg);
225
+ border: 1px solid var(--error-border);
226
+ border-radius: 8px;
227
+ padding: 12px 16px;
228
+ margin-bottom: 20px;
229
+ color: var(--error-text);
230
+ font-size: 14px;
231
+ font-weight: 500;
232
+ text-align: center;
233
+ }
234
+
235
+ /* Submit Button */
236
+ .submit-btn {
237
+ width: 100%;
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ gap: 8px;
242
+ background: var(--accent-gradient);
243
+ color: #FFFFFF;
244
+ border: none;
245
+ padding: 16px 24px;
246
+ border-radius: 12px;
247
+ font-size: 16px;
248
+ font-weight: 600;
249
+ cursor: pointer;
250
+ transition: all 0.3s ease;
251
+ box-shadow: var(--shadow-md);
252
+ margin-bottom: 24px;
253
+ }
254
+
255
+ .submit-btn:hover:not(:disabled) {
256
+ transform: translateY(-2px);
257
+ box-shadow: var(--shadow-lg);
258
+ }
259
+
260
+ .submit-btn:active:not(:disabled) {
261
+ transform: translateY(0);
262
+ }
263
+
264
+ .submit-btn:disabled {
265
+ opacity: 0.7;
266
+ cursor: not-allowed;
267
+ transform: none;
268
+ }
269
+
270
+ .submit-btn.loading {
271
+ pointer-events: none;
272
+ }
273
+
274
+ /* Loading Spinner */
275
+ .loading-spinner {
276
+ width: 16px;
277
+ height: 16px;
278
+ border: 2px solid rgba(255, 255, 255, 0.3);
279
+ border-top: 2px solid #FFFFFF;
280
+ border-radius: 50%;
281
+ animation: spin 1s linear infinite;
282
+ }
283
+
284
+ @keyframes spin {
285
+ 0% { transform: rotate(0deg); }
286
+ 100% { transform: rotate(360deg); }
287
+ }
288
+
289
+ /* Divider */
290
+ .divider {
291
+ position: relative;
292
+ text-align: center;
293
+ margin: 24px 0;
294
+ }
295
+
296
+ .divider::before {
297
+ content: '';
298
+ position: absolute;
299
+ top: 50%;
300
+ left: 0;
301
+ right: 0;
302
+ height: 1px;
303
+ background: var(--border-secondary);
304
+ }
305
+
306
+ .divider span {
307
+ background: var(--bg-primary);
308
+ color: var(--text-tertiary);
309
+ font-size: 13px;
310
+ font-weight: 500;
311
+ padding: 0 16px;
312
+ position: relative;
313
+ z-index: 1;
314
+ }
315
+
316
+ /* Social Signup */
317
+ .social-signup {
318
+ display: flex;
319
+ flex-direction: column;
320
+ gap: 12px;
321
+ margin-bottom: 24px;
322
+ }
323
+
324
+ .google-btn,
325
+ .phone-btn {
326
+ width: 100%;
327
+ display: flex;
328
+ align-items: center;
329
+ justify-content: center;
330
+ gap: 12px;
331
+ padding: 14px 20px;
332
+ border: 1px solid var(--border-secondary);
333
+ border-radius: 12px;
334
+ background: var(--bg-primary);
335
+ color: var(--text-primary);
336
+ font-size: 15px;
337
+ font-weight: 500;
338
+ cursor: pointer;
339
+ transition: all 0.2s ease;
340
+ }
341
+
342
+ .google-btn:hover:not(:disabled),
343
+ .phone-btn:hover:not(:disabled) {
344
+ border-color: var(--border-primary);
345
+ background: var(--bg-secondary);
346
+ transform: translateY(-1px);
347
+ box-shadow: var(--shadow-sm);
348
+ }
349
+
350
+ .google-btn:disabled,
351
+ .phone-btn:disabled {
352
+ opacity: 0.6;
353
+ cursor: not-allowed;
354
+ transform: none;
355
+ }
356
+
357
+ .google-icon {
358
+ width: 18px;
359
+ height: 18px;
360
+ flex-shrink: 0;
361
+ }
362
+
363
+ /* Footer */
364
+ .signup-footer {
365
+ text-align: center;
366
+ padding: 24px 32px 32px 32px;
367
+ border-top: 1px solid var(--border-primary);
368
+ background: var(--bg-secondary);
369
+ }
370
+
371
+ .signup-footer p {
372
+ color: var(--text-secondary);
373
+ font-size: 14px;
374
+ margin: 0;
375
+ }
376
+
377
+ .link-btn {
378
+ background: none;
379
+ border: none;
380
+ color: var(--accent-primary);
381
+ font-size: 14px;
382
+ font-weight: 600;
383
+ cursor: pointer;
384
+ padding: 0;
385
+ text-decoration: underline;
386
+ text-underline-offset: 2px;
387
+ transition: color 0.2s ease;
388
+ }
389
+
390
+ .link-btn:hover {
391
+ color: var(--accent-secondary);
392
+ }
393
+
394
+ /* Animations */
395
+ @keyframes fadeInUp {
396
+ from {
397
+ opacity: 0;
398
+ transform: translateY(20px);
399
+ }
400
+ to {
401
+ opacity: 1;
402
+ transform: translateY(0);
403
+ }
404
+ }
405
+
406
+ /* Mobile Responsive */
407
+ @media (max-width: 640px) {
408
+ .signup-page {
409
+ padding: 16px 12px;
410
+ }
411
+
412
+ .signup-container {
413
+ max-width: 100%;
414
+ border-radius: 16px;
415
+ }
416
+
417
+ .signup-header {
418
+ padding: 32px 24px 24px 24px;
419
+ }
420
+
421
+ .signup-title {
422
+ font-size: 24px;
423
+ }
424
+
425
+ .signup-subtitle {
426
+ font-size: 15px;
427
+ }
428
+
429
+ .signup-form-container {
430
+ padding: 24px;
431
+ }
432
+
433
+ /* Stack form rows on mobile */
434
+ .form-row {
435
+ grid-template-columns: 1fr;
436
+ gap: 20px;
437
+ }
438
+
439
+ .form-row .form-group {
440
+ margin-bottom: 0;
441
+ }
442
+
443
+ .form-input,
444
+ .form-select {
445
+ font-size: 16px; /* Prevents zoom on iOS */
446
+ padding: 14px 14px 14px 44px;
447
+ }
448
+
449
+ .submit-btn {
450
+ padding: 14px 20px;
451
+ font-size: 15px;
452
+ }
453
+
454
+ .google-btn,
455
+ .phone-btn {
456
+ padding: 12px 16px;
457
+ font-size: 14px;
458
+ }
459
+
460
+ .signup-footer {
461
+ padding: 20px 24px 24px 24px;
462
+ }
463
+
464
+ .terms-section {
465
+ padding: 14px;
466
+ }
467
+
468
+ .terms-text {
469
+ font-size: 13px;
470
+ }
471
+ }
472
+
473
+ @media (max-width: 480px) {
474
+ .signup-container {
475
+ max-width: 100%;
476
+ }
477
+
478
+ .form-row {
479
+ gap: 16px;
480
+ }
481
+
482
+ .form-input,
483
+ .form-select {
484
+ padding: 12px 12px 12px 40px;
485
+ }
486
+
487
+ .input-icon {
488
+ left: 14px;
489
+ width: 14px;
490
+ height: 14px;
491
+ }
492
+
493
+ .password-toggle {
494
+ right: 14px;
495
+ }
496
+ }
497
+
498
+ /* Focus and Accessibility */
499
+ .submit-btn:focus-visible,
500
+ .google-btn:focus-visible,
501
+ .phone-btn:focus-visible,
502
+ .link-btn:focus-visible,
503
+ .password-toggle:focus-visible {
504
+ outline: 2px solid var(--accent-primary);
505
+ outline-offset: 2px;
506
+ }
507
+
508
+ .form-input:focus-visible,
509
+ .form-select:focus-visible {
510
+ outline: none; /* Handled by border and shadow */
511
+ }
512
+
513
+ /* High Contrast Mode */
514
+ @media (prefers-contrast: high) {
515
+ .signup-container {
516
+ border-width: 2px;
517
+ }
518
+
519
+ .form-input,
520
+ .form-select {
521
+ border-width: 2px;
522
+ }
523
+
524
+ .submit-btn {
525
+ border: 2px solid var(--accent-primary);
526
+ }
527
+ }
528
+
529
+ /* Reduced Motion */
530
+ @media (prefers-reduced-motion: reduce) {
531
+ .signup-container,
532
+ .submit-btn,
533
+ .google-btn,
534
+ .phone-btn,
535
+ .form-input,
536
+ .form-select,
537
+ .password-toggle,
538
+ .link-btn {
539
+ transition: none;
540
+ }
541
+
542
+ .loading-spinner {
543
+ animation: none;
544
+ }
545
+
546
+ .fadeInUp {
547
+ animation: none;
548
+ }
549
+ }
550
+
551
+ /* Password Strength Indicator (Optional Enhancement) */
552
+ .password-strength {
553
+ margin-top: 8px;
554
+ display: flex;
555
+ gap: 4px;
556
+ }
557
+
558
+ .strength-bar {
559
+ height: 3px;
560
+ flex: 1;
561
+ background: var(--border-tertiary);
562
+ border-radius: 2px;
563
+ transition: background-color 0.2s ease;
564
+ }
565
+
566
+ .strength-bar.weak {
567
+ background: #EF4444;
568
+ }
569
+
570
+ .strength-bar.medium {
571
+ background: #F59E0B;
572
+ }
573
+
574
+ .strength-bar.strong {
575
+ background: #10B981;
576
+ }
577
+
578
+ .strength-text {
579
+ font-size: 12px;
580
+ margin-top: 4px;
581
+ font-weight: 500;
582
+ }
583
+
584
+ .strength-text.weak {
585
+ color: #EF4444;
586
+ }
587
+
588
+ .strength-text.medium {
589
+ color: #F59E0B;
590
+ }
591
+
592
+ .strength-text.strong {
593
+ color: #10B981;
594
+ }