You are currently signed in with
.
Pro ");',
597 | };
598 |
599 | let modified = content;
600 | for (const [pattern, replacement] of Object.entries(patterns)) {
601 | modified = modified.replace(new RegExp(pattern, 'g'), replacement);
602 | }
603 |
604 | await fs.writeFile(workbenchPath, modified);
605 | logs.push("✅ Workbench file modified for Pro UI");
606 | } else {
607 | logs.push(`⚠️ Workbench file not found at: ${workbenchPath}`);
608 | }
609 |
610 | logs.push("✅ Pro conversion completed successfully");
611 | return await ld(logs, "Pro Conversion + Custom UI");
612 | } catch (err) {
613 | logs.push(`❌ Pro conversion error: ${err.message}`);
614 | return await ld(logs, "Pro Conversion + Custom UI");
615 | }
616 | };
617 |
618 | const ld = async (logs, toolName) => {
619 | const hd = "==================================================";
620 | const t1 = `🔄 Cursor ${toolName} Tool`;
621 |
622 | let lg = [];
623 | lg.push(hd);
624 | lg.push(t1);
625 | lg.push(hd);
626 |
627 | logs.forEach(l => {
628 | lg.push(l);
629 | });
630 |
631 | return lg.join('\n');
632 | };
633 |
634 | rt.get('/reset', async (req, res) => {
635 | try {
636 | const result = await rm();
637 | res.json({ success: true, log: result });
638 | } catch (err) {
639 | res.status(500).json({ success: false, error: err.message });
640 | }
641 | });
642 |
643 | rt.get('/patch', async (req, res) => {
644 | try {
645 | const action = req.query.action || 'bypass';
646 | let result;
647 |
648 | if (action === 'bypass') {
649 | result = await bt();
650 | } else if (action === 'disable') {
651 | result = await du();
652 | } else if (action === 'pro') {
653 | result = await pc();
654 | } else {
655 | result = await bt();
656 | }
657 |
658 | res.json({ success: true, log: result });
659 | } catch (err) {
660 | res.status(500).json({ success: false, error: err.message });
661 | }
662 | });
663 |
664 | rt.get('/paths', async (req, res) => {
665 | try {
666 | const { mp, sp, dp, ap, cp, up, pt, dc } = gp();
667 |
668 | let isRunning = false;
669 | try {
670 | if (pt === 'win32') {
671 | const { stdout } = await execPromise('tasklist /FI "IMAGENAME eq Cursor.exe" /NH');
672 | isRunning = stdout.includes('Cursor.exe');
673 | } else {
674 | const { stdout } = await execPromise('ps aux | grep -i Cursor | grep -v grep');
675 | isRunning = stdout.trim().length > 0;
676 | }
677 | } catch (e) {
678 | isRunning = false;
679 | }
680 |
681 | const info = {
682 | platform: pt,
683 | osVersion: os.release(),
684 | arch: os.arch(),
685 | homedir: os.homedir(),
686 | machinePath: mp,
687 | storagePath: sp,
688 | dbPath: dp,
689 | appPath: ap,
690 | cursorPath: cp,
691 | updatePath: up,
692 | isRunning,
693 | exists: {
694 | machineId: fs.existsSync(mp),
695 | storage: fs.existsSync(sp),
696 | database: fs.existsSync(dp),
697 | app: fs.existsSync(ap),
698 | cursor: fs.existsSync(cp),
699 | update: fs.existsSync(up)
700 | }
701 | };
702 |
703 | if (fs.existsSync(sp)) {
704 | try {
705 | const data = await fs.readFile(sp, 'utf8');
706 | const json = JSON.parse(data);
707 | info.storage = {
708 | machineId: json['telemetry.machineId'] || json['serviceMachineId'],
709 | devDeviceId: json['telemetry.devDeviceId'],
710 | tier: json['cursor.tier'] || 'unknown'
711 | };
712 | } catch (e) {}
713 | }
714 |
715 | if (fs.existsSync(dp)) {
716 | try {
717 | const db = await open({
718 | filename: dp,
719 | driver: sqlite3.Database
720 | });
721 | const rows = await db.all('SELECT key, value FROM ItemTable WHERE key LIKE "%cursor%" OR key LIKE "%telemetry%" LIMIT 10');
722 | info.database = rows.reduce((acc, row) => {
723 | try {
724 | acc[row.key] = JSON.parse(row.value);
725 | } catch (e) {
726 | acc[row.key] = row.value;
727 | }
728 | return acc;
729 | }, {});
730 | await db.close();
731 | } catch (e) {}
732 | }
733 |
734 | res.json(info);
735 | } catch (err) {
736 | res.status(500).json({ error: err.message });
737 | }
738 | });
739 |
740 | export default rt;
--------------------------------------------------------------------------------
/views/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Sazumi Cloud - Cursor Reset Tool
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
23 |
24 | Warning: Excessive use of this tool may violate Cursor's terms of service.
25 |
26 |
By using this tool, you acknowledge that:
27 |
28 | All actions performed are at your own risk
29 | Sazumi Cloud developers are not responsible for any consequences
30 | This tool should not be abused frequently
31 | This is provided for educational and research purposes only
32 |
33 |
Please use responsibly and consider supporting Cursor by purchasing a legitimate license if you find their product valuable.
34 |
35 |
38 |
39 |
40 |
41 |
42 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
56 | Recommended: For best compatibility, use Cursor version 0.49.x .
57 |
58 |
Sazumi Cloud is a powerful tool designed to reset the Machine ID of Cursor IDE. This helps to bypass trial limits, convert free trials to Pro, bypass token limitations, and prevent automatic updates to unleash the full potential of Cursor AI capabilities.
59 |
60 |
61 |
62 |
63 |
Token Limit Bypass
64 |
Remove restrictions on token usage for AI completions
65 |
66 |
67 |
68 |
69 |
70 |
Pro Conversion
71 |
Access Pro features without purchasing a subscription and customize the UI
72 |
73 |
74 |
75 |
76 |
77 |
Machine ID Reset
78 |
Bypass the "Too many free trial accounts" limitation
79 |
80 |
81 |
82 |
83 |
84 |
Auto Update Prevention
85 |
Stop Cursor from automatically updating to versions that could patch these bypasses
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
98 |
99 |
100 |
Loading system information
101 |
102 |
103 |
104 |
105 |
106 |
109 |
110 |
111 |
Loading cursor information
112 |
113 |
114 |
115 |
116 |
117 |
120 |
121 |
122 |
123 | Important: Make sure Cursor is closed before resetting the machine ID.
124 |
125 |
126 | Reset Machine ID
127 | Bypass Token Limit
128 | Disable Auto-Update
129 | Pro Conversion + Custom UI
130 |
131 |
132 |
133 |
134 |
135 |
136 |
139 |
140 |
141 |
142 | Note: When you encounter "too many requests" errors, you MUST change your IP address by toggling your mobile data OFF and ON.
143 |
144 |
145 |
Email generator feature has been removed in this version.
146 |
Please use an external email service for verification needs.
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
157 |
158 |
159 | Admin privileges are required for file operations
160 | Cursor must be completely closed when resetting
161 | Internet connection for API calls
162 | Compatible with Windows, macOS, and Linux
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
173 |
174 |
175 |
176 |
180 |
181 |
Cursor identifies your machine using a unique ID stored in specific locations of your system. This tool works by:
182 |
183 | Machine ID Reset: Generates a new unique identifier using secure cryptographic methods to bypass device restrictions and Cursor's telemetry tracking
184 | Token Limits: Modifies system files and SQLite database to remove AI completion token restrictions with improved patching methods
185 | Pro Features: Modifies authentication data to enable premium features without a paid subscription (Note: This only changes the UI appearance, not actual Pro functionality as Pro features work in the cloud, not locally)
186 | Update Prevention: Implements multiple layers of protection to block Cursor from automatically updating, including app-update.yml modification, blocker files, and URL endpoint removal
187 | Storage Clearance: Removes cached data that tracks your usage history and limits
188 | Cross-Platform: Works across Windows, macOS and Linux with dedicated optimizations for each platform
189 |
190 |
These modifications allow Cursor to treat your machine as a new device with full Pro capabilities.
191 |
192 |
193 |
194 |
198 |
199 |
200 | Close all instances of Cursor before resetting
201 | Administrator privileges may be required
202 | Restart Cursor after reset for changes to take effect
203 | Recommended Version: For optimal results, use Cursor version 0.49.x
204 |
205 |
206 |
207 |
208 |
212 |
213 |
214 | If reset fails, try running the application with administrator privileges
215 | Ensure Cursor is completely closed (check task manager)
216 | If problems persist, manual deletion of files may be required
217 |
218 |
219 |
220 |
221 |
225 |
226 |
For best results when creating new Cursor accounts:
227 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
242 |
243 |
244 |
245 | Important: Do not run or edit this code using Cursor IDE. Use VS Code or another code editor instead.
246 |
247 |
248 |
249 |
250 |
1
251 |
252 |
Clone Repository
253 |
git clone https://github.com/sazumivicky/cursor-reset-tools.git
254 | cd cursor-reset-tools
255 |
256 |
257 |
258 |
259 |
2
260 |
261 |
Install Dependencies
262 |
npm install
263 |
264 |
265 |
266 |
267 |
3
268 |
269 |
Start the Application
270 |
npm start
271 |
The server will start on http://localhost:3000
272 |
273 |
274 |
275 |
276 |
277 |
278 |
282 |
283 |
On Windows, use Command Prompt as Administrator:
284 |
cd path\to\cursor-reset-tools
285 | npm start
286 |
On macOS/Linux, use sudo:
287 |
cd path/to/cursor-reset-tools
288 | sudo npm start
289 |
290 |
291 |
292 |
296 |
297 |
To run in development mode with automatic restart:
298 |
npm run dev
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
311 |
312 |
313 |
314 |
315 |
316 |
320 |
321 |
322 | Fixed Major improvements to reset machine ID for all platforms
323 | Fixed More robust bypass token limit patching for new Cursor versions
324 | Fixed Disable auto-update now blocks all update channels and URLs
325 | Fixed Pro Conversion + Custom UI now works with latest UI changes
326 | Improved Cross-platform support and error handling
327 | Improved UI/UX for system and Cursor status detection
328 | Improved All features tested and optimized for Cursor 0.49.x
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
341 |
342 |
343 | Fixed Complete machine ID reset to properly bypass device limits
344 | Added Enhanced registry updates for Windows with both HKCU and HKLM keys
345 | Added macOS keychain credential clearing for complete reset
346 | Added Improved Linux support with additional identity file handling
347 | Enhanced SQLite database modifications with trial-related entry deletion
348 | Fixed More robust getMachineId function patching with direct UUID injection
349 | Improved Better error handling and file existence checks
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
362 |
363 |
364 | Added Windows registry update implementation for complete machine ID reset
365 | Added macOS platform UUID update support using plutil
366 | Improved Cross-platform machine ID reset with OS-specific optimizations
367 | Fixed Silent error handling for registry and platform UUID updates
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
380 |
381 |
382 | Enhanced Machine ID reset with improved cryptographic generation
383 | Added Windows registry support for more complete reset
384 | Improved Main.js patching to bypass machine ID checks on Cursor 0.49+
385 | Enhanced Disable auto-update functionality with multiple protection layers
386 | Fixed ES modules compatibility issues with clean native methods
387 | Improved Cross-platform file path handling for Windows/macOS/Linux
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
400 |
401 |
402 | Removed Atomic Mail functionality completely
403 | Fixed Cross-platform compatibility for Windows, macOS, and Linux features
404 | Improved Modern JavaScript with cleaner code patterns
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
417 |
418 |
419 | Improved Enhanced SQLite database handling for more reliable resets
420 | Added Proper backup of all files before modification
421 | Improved Windows registry updates for complete system ID refresh
422 | Fixed Better handling of telemetry IDs across all platforms
423 | Improved getMachineId patching in Cursor 0.49+ versions
424 | Fixed Token limit bypass with multiple pattern detection methods
425 | Fixed Auto-update disabling with proper permissions handling
426 | Added Fallback mechanisms for all core functions when primary methods fail
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
439 |
440 |
441 | Added Bypass token limit feature (experimental - still finding workarounds)
442 | Added Disable auto-update feature to prevent automatic updates
443 | Added Pro conversion tool for enabling premium features
444 | Fixed MacOS functionality issues across all features
445 | Improved Overall stability and compatibility with latest Cursor versions
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
458 |
459 |
460 | Fixed MacOS reset issue for "Too many free trial accounts" error
461 | Improved MacOS keychain handling for stored credentials removal
462 | Added Enhanced cleaning of additional ID files on MacOS
463 | Fixed MacOS defaults reset for Cursor application
464 | Improved Compatibility with Cursor version 0.48.x
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
477 |
478 |
479 | Fixed Improved machine ID reset method to match cursor-free-vip
480 | Fixed Files are now modified instead of deleted to preserve login status
481 | Added Detailed logs in UI showing each step of the reset process
482 | Fixed Added automatic cursor process termination if running
483 | Improved Patching for newer Cursor versions (≥0.45.0)
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
496 |
497 |
498 | Improved Enhanced UI with modern design
499 | Improved Better cross-platform compatibility
500 | Added Comprehensive documentation
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
513 |
514 |
515 | New Initial release of Sazumi Cloud
516 | New Support for Windows, macOS and Linux
517 | New Machine ID reset functionality
518 | New System information display
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
540 |
541 |
545 |
546 |
547 |
548 |
551 |
552 |
--------------------------------------------------------------------------------
/public/css/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --primary-color: #333333;
3 | --secondary-color: #f8f9fa;
4 | --accent-color: #757575;
5 | --accent-dark: #424242;
6 | --text-color: #212121;
7 | --success-color: #4caf50;
8 | --error-color: #f44336;
9 | --light-bg: #f1f3f4;
10 | --border-color: #e0e0e0;
11 | --border-radius: 6px;
12 | }
13 |
14 | * {
15 | margin: 0;
16 | padding: 0;
17 | box-sizing: border-box;
18 | }
19 |
20 | body {
21 | font-family: 'Google Sans', -apple-system, sans-serif;
22 | background-color: var(--secondary-color);
23 | color: var(--text-color);
24 | line-height: 1.6;
25 | overflow-x: hidden;
26 | }
27 |
28 | .container {
29 | max-width: 900px;
30 | margin: 0 auto;
31 | padding: 2rem 1rem;
32 | }
33 |
34 | header {
35 | text-align: center;
36 | margin-bottom: 2.5rem;
37 | padding: 1.5rem 0;
38 | position: relative;
39 | }
40 |
41 | header::after {
42 | content: '';
43 | position: absolute;
44 | bottom: 0;
45 | left: 50%;
46 | transform: translateX(-50%);
47 | width: 60px;
48 | height: 3px;
49 | background: var(--accent-color);
50 | border-radius: 3px;
51 | }
52 |
53 | header h1 {
54 | font-size: 2.5rem;
55 | margin-bottom: 0.5rem;
56 | letter-spacing: -0.5px;
57 | font-weight: 700;
58 | text-transform: uppercase;
59 | background: linear-gradient(45deg, var(--accent-color), var(--accent-dark));
60 | -webkit-background-clip: text;
61 | background-clip: text;
62 | color: transparent;
63 | position: relative;
64 | display: inline-block;
65 | }
66 |
67 | header h1::before {
68 | content: attr(data-text);
69 | position: absolute;
70 | left: 0;
71 | top: 0;
72 | z-index: -1;
73 | background: linear-gradient(45deg, var(--accent-color), var(--accent-dark));
74 | -webkit-background-clip: text;
75 | background-clip: text;
76 | color: transparent;
77 | filter: blur(8px);
78 | opacity: 0.5;
79 | }
80 |
81 | header p {
82 | color: var(--primary-color);
83 | font-size: 1.1rem;
84 | opacity: 0.8;
85 | }
86 |
87 | main, #intro, #docs, #changelog, #requirements {
88 | display: grid;
89 | grid-template-columns: 1fr;
90 | gap: 1.5rem;
91 | margin-bottom: 2rem;
92 | }
93 |
94 | @media (min-width: 768px) {
95 | main {
96 | grid-template-columns: repeat(2, 1fr);
97 | }
98 |
99 | main .card:last-child {
100 | grid-column: span 2;
101 | }
102 | }
103 |
104 | .card {
105 | background: white;
106 | border-radius: var(--border-radius);
107 | overflow: hidden;
108 | border: 1px solid var(--border-color);
109 | transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), border-color 0.3s ease;
110 | }
111 |
112 | .card:hover {
113 | transform: translateY(-5px);
114 | border-color: var(--accent-color);
115 | }
116 |
117 | .card-header {
118 | background: white;
119 | padding: 1.25rem 1.5rem;
120 | border-bottom: 1px solid var(--border-color);
121 | position: relative;
122 | }
123 |
124 | .card-header h2 {
125 | color: var(--text-color);
126 | font-size: 1.25rem;
127 | font-weight: 500;
128 | display: flex;
129 | align-items: center;
130 | gap: 10px;
131 | }
132 |
133 | .card-header h2 i {
134 | color: var(--accent-color);
135 | transition: transform 0.3s ease;
136 | font-size: 20px;
137 | }
138 |
139 | .card:hover .card-header h2 i {
140 | transform: scale(1.2);
141 | }
142 |
143 | .card-body {
144 | padding: 1.5rem;
145 | }
146 |
147 | .features {
148 | display: grid;
149 | grid-template-columns: 1fr;
150 | gap: 1.5rem;
151 | margin-top: 1.5rem;
152 | }
153 |
154 | @media (min-width: 768px) {
155 | .features {
156 | grid-template-columns: repeat(3, 1fr);
157 | }
158 | }
159 |
160 | .feature {
161 | display: flex;
162 | align-items: flex-start;
163 | gap: 15px;
164 | padding: 1rem;
165 | background: var(--light-bg);
166 | border-radius: var(--border-radius);
167 | transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
168 | border: 1px solid transparent;
169 | }
170 |
171 | .feature:hover {
172 | transform: translateY(-3px) scale(1.02);
173 | border-color: var(--accent-color);
174 | background: white;
175 | }
176 |
177 | .feature i {
178 | color: var(--accent-color);
179 | font-size: 24px;
180 | transition: transform 0.3s ease;
181 | }
182 |
183 | .feature:hover i {
184 | transform: scale(1.2);
185 | }
186 |
187 | .feature h3 {
188 | font-size: 1rem;
189 | margin-bottom: 0.5rem;
190 | font-weight: 500;
191 | }
192 |
193 | .feature p {
194 | font-size: 0.9rem;
195 | color: var(--primary-color);
196 | opacity: 0.8;
197 | }
198 |
199 | .btn {
200 | display: inline-flex;
201 | align-items: center;
202 | justify-content: center;
203 | background: linear-gradient(45deg, var(--accent-color), var(--accent-dark));
204 | color: white;
205 | border: none;
206 | border-radius: 50px;
207 | padding: 0.75rem 1.75rem;
208 | font-size: 0.9rem;
209 | font-weight: 500;
210 | cursor: pointer;
211 | transition: all 0.3s;
212 | letter-spacing: 0.25px;
213 | gap: 8px;
214 | position: relative;
215 | overflow: hidden;
216 | }
217 |
218 | .btn::after {
219 | content: '';
220 | position: absolute;
221 | top: 50%;
222 | left: 50%;
223 | width: 100%;
224 | height: 100%;
225 | background: rgba(255, 255, 255, 0.2);
226 | border-radius: 50%;
227 | transform: scale(0) translate(-50%, -50%);
228 | transform-origin: top left;
229 | transition: transform 0.6s;
230 | }
231 |
232 | .btn:hover {
233 | transform: translateY(-2px);
234 | }
235 |
236 | .btn:hover::after {
237 | transform: scale(2.5) translate(-50%, -50%);
238 | }
239 |
240 | .btn:active {
241 | transform: translateY(1px);
242 | }
243 |
244 | .btn:disabled {
245 | background: #e0e0e0;
246 | color: #9e9e9e;
247 | cursor: not-allowed;
248 | }
249 |
250 | .btn:disabled::after {
251 | display: none;
252 | }
253 |
254 | .btn i {
255 | font-size: 18px;
256 | transition: transform 0.3s ease;
257 | }
258 |
259 | .btn:hover i {
260 | transform: rotate(180deg);
261 | }
262 |
263 | .alert {
264 | padding: 1rem;
265 | border-radius: var(--border-radius);
266 | margin: 1rem 0;
267 | font-size: 0.9rem;
268 | display: flex;
269 | align-items: flex-start;
270 | gap: 10px;
271 | background-color: var(--light-bg);
272 | }
273 |
274 | .alert-warning {
275 | background-color: #fff8e1;
276 | color: #bf360c;
277 | }
278 |
279 | .alert-info {
280 | background-color: #e8f5e9;
281 | color: #1b5e20;
282 | }
283 |
284 | .alert i {
285 | font-size: 20px;
286 | color: var(--accent-color);
287 | }
288 |
289 | #reset-result {
290 | margin-top: 1.5rem;
291 | border-radius: var(--border-radius);
292 | font-size: 0.95rem;
293 | }
294 |
295 | .success, .error, .processing {
296 | padding: 1rem;
297 | border-radius: var(--border-radius);
298 | display: flex;
299 | flex-direction: column;
300 | gap: 8px;
301 | }
302 |
303 | .success {
304 | background-color: #e8f5e9;
305 | color: #1b5e20;
306 | }
307 |
308 | .error {
309 | background-color: #ffebee;
310 | color: #b71c1c;
311 | }
312 |
313 | .processing {
314 | background-color: #ede7f6;
315 | color: #311b92;
316 | }
317 |
318 | .success p, .error p, .processing p {
319 | display: flex;
320 | align-items: center;
321 | gap: 8px;
322 | }
323 |
324 | footer {
325 | text-align: center;
326 | margin-top: 3rem;
327 | padding-top: 1.5rem;
328 | border-top: 1px solid var(--border-color);
329 | font-size: 0.9rem;
330 | color: var(--primary-color);
331 | }
332 |
333 | footer a {
334 | color: var(--accent-color);
335 | text-decoration: none;
336 | transition: color 0.3s ease;
337 | }
338 |
339 | footer a:hover {
340 | text-decoration: underline;
341 | }
342 |
343 | table {
344 | width: 100%;
345 | border-collapse: collapse;
346 | margin-bottom: 1rem;
347 | font-size: 0.9rem;
348 | border-radius: var(--border-radius);
349 | overflow: hidden;
350 | }
351 |
352 | table, th, td {
353 | border: 1px solid var(--border-color);
354 | }
355 |
356 | th, td {
357 | padding: 0.75rem;
358 | text-align: left;
359 | }
360 |
361 | th {
362 | background-color: var(--light-bg);
363 | font-weight: 500;
364 | color: var(--primary-color);
365 | }
366 |
367 | tr:nth-child(even) {
368 | background-color: var(--light-bg);
369 | }
370 |
371 | .code-block {
372 | max-width: 100%;
373 | overflow-x: hidden;
374 | background: #1e1e1e;
375 | padding: 0.75rem;
376 | border-radius: var(--border-radius);
377 | font-family: 'Consolas', 'Monaco', monospace;
378 | font-size: 0.85rem;
379 | color: #d4d4d4;
380 | border: none;
381 | white-space: pre-wrap;
382 | word-wrap: break-word;
383 | word-break: break-all;
384 | scrollbar-width: thin;
385 | scrollbar-color: var(--accent-color) #1e1e1e;
386 | position: relative;
387 | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
388 | margin: 0;
389 | }
390 |
391 | .code-block::-webkit-scrollbar {
392 | height: 6px;
393 | }
394 |
395 | .code-block::-webkit-scrollbar-track {
396 | background: #2d2d2d;
397 | border-radius: 3px;
398 | }
399 |
400 | .code-block::-webkit-scrollbar-thumb {
401 | background-color: var(--accent-color);
402 | border-radius: 3px;
403 | }
404 |
405 | .code-block::before, .code-block::after {
406 | content: '';
407 | position: absolute;
408 | top: 0;
409 | height: 100%;
410 | width: 20px;
411 | pointer-events: none;
412 | z-index: 1;
413 | opacity: 0.7;
414 | }
415 |
416 | .code-block::before {
417 | left: 0;
418 | background: linear-gradient(to right, #1e1e1e, rgba(30, 30, 30, 0));
419 | }
420 |
421 | .code-block::after {
422 | right: 0;
423 | background: linear-gradient(to left, #1e1e1e, rgba(30, 30, 30, 0));
424 | }
425 |
426 | .status-indicator {
427 | display: inline-block;
428 | width: 10px;
429 | height: 10px;
430 | border-radius: 50%;
431 | margin-right: 8px;
432 | }
433 |
434 | .status-running {
435 | background-color: var(--success-color);
436 | box-shadow: 0 0 5px var(--success-color);
437 | animation: pulse 1.5s infinite;
438 | }
439 |
440 | .status-stopped {
441 | background-color: var(--error-color);
442 | }
443 |
444 | @keyframes pulse {
445 | 0% {
446 | box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.7);
447 | }
448 | 70% {
449 | box-shadow: 0 0 0 5px rgba(76, 175, 80, 0);
450 | }
451 | 100% {
452 | box-shadow: 0 0 0 0 rgba(76, 175, 80, 0);
453 | }
454 | }
455 |
456 | .loading {
457 | display: flex;
458 | justify-content: center;
459 | align-items: center;
460 | min-height: 100px;
461 | color: var(--primary-color);
462 | }
463 |
464 | .loading::before {
465 | content: "";
466 | width: 40px;
467 | height: 40px;
468 | border-radius: 50%;
469 | border: 3px solid transparent;
470 | border-top-color: var(--accent-color);
471 | border-right-color: var(--accent-color);
472 | animation: sp 1s cubic-bezier(0.5, 0, 0.5, 1) infinite;
473 | margin-right: 10px;
474 | }
475 |
476 | @keyframes sp {
477 | 0% {
478 | transform: rotate(0deg);
479 | }
480 | 100% {
481 | transform: rotate(360deg);
482 | }
483 | }
484 |
485 | .accordion {
486 | display: flex;
487 | flex-direction: column;
488 | gap: 0.5rem;
489 | }
490 |
491 | .accordion-item {
492 | border: 1px solid var(--border-color);
493 | border-radius: var(--border-radius);
494 | overflow: hidden;
495 | transition: all 0.3s ease;
496 | }
497 |
498 | .accordion-item:hover {
499 | border-color: var(--accent-color);
500 | }
501 |
502 | .accordion-header {
503 | padding: 1rem;
504 | display: flex;
505 | align-items: center;
506 | gap: 10px;
507 | background: var(--light-bg);
508 | cursor: pointer;
509 | user-select: none;
510 | }
511 |
512 | .accordion-header i {
513 | transition: transform 0.3s ease;
514 | color: var(--accent-color);
515 | font-size: 18px;
516 | }
517 |
518 | .accordion-item.active .accordion-header i {
519 | transform: rotate(90deg);
520 | }
521 |
522 | .accordion-header h3 {
523 | font-size: 1rem;
524 | font-weight: 500;
525 | margin: 0;
526 | }
527 |
528 | .accordion-content {
529 | padding: 0;
530 | max-height: 0;
531 | overflow: hidden;
532 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
533 | opacity: 0;
534 | }
535 |
536 | .accordion-item.active .accordion-content {
537 | padding: 1rem;
538 | max-height: 300px;
539 | overflow-y: auto;
540 | opacity: 1;
541 | }
542 |
543 | .accordion-content p {
544 | margin-bottom: 1rem;
545 | }
546 |
547 | .accordion-content ul {
548 | padding-left: 1.5rem;
549 | }
550 |
551 | .accordion-content li {
552 | margin-bottom: 0.5rem;
553 | }
554 |
555 | .version {
556 | margin-bottom: 1.5rem;
557 | padding-bottom: 1.5rem;
558 | border-bottom: 1px solid var(--border-color);
559 | transition: transform 0.3s ease;
560 | }
561 |
562 | .version:hover {
563 | transform: translateX(5px);
564 | }
565 |
566 | .version:last-child {
567 | margin-bottom: 0;
568 | padding-bottom: 0;
569 | border-bottom: none;
570 | }
571 |
572 | .version-header {
573 | display: flex;
574 | align-items: center;
575 | margin-bottom: 15px;
576 | }
577 |
578 | .version-tag {
579 | font-weight: 600;
580 | color: var(--accent-color);
581 | font-size: 1.1rem;
582 | transition: color 0.3s ease;
583 | }
584 |
585 | .version:hover .version-tag {
586 | color: var(--accent-dark);
587 | }
588 |
589 | .version-date {
590 | font-size: 0.9rem;
591 | font-weight: 500;
592 | color: var(--accent-dark);
593 | transition: all 0.3s ease;
594 | margin-left: 10px;
595 | opacity: 0.8;
596 | }
597 |
598 | .version-changes {
599 | list-style-type: none;
600 | }
601 |
602 | .version-changes li {
603 | margin-bottom: 0.5rem;
604 | display: flex;
605 | align-items: flex-start;
606 | gap: 8px;
607 | transition: transform 0.3s ease;
608 | }
609 |
610 | .version-changes li:hover {
611 | transform: translateX(5px);
612 | }
613 |
614 | .change-type {
615 | display: inline-block;
616 | padding: 0.1rem 0.5rem;
617 | border-radius: 20px;
618 | font-size: 0.7rem;
619 | font-weight: 600;
620 | text-transform: uppercase;
621 | min-width: 60px;
622 | text-align: center;
623 | }
624 |
625 | .new {
626 | background-color: #f1f3f4;
627 | color: #424242;
628 | }
629 |
630 | .improved {
631 | background-color: #e8f5e9;
632 | color: #388e3c;
633 | }
634 |
635 | .fixed {
636 | background-color: #ffebee;
637 | color: #d32f2f;
638 | }
639 |
640 | .added {
641 | background-color: #f5f5f5;
642 | color: #616161;
643 | }
644 |
645 | .removed {
646 | background-color: #e53935;
647 | color: white;
648 | }
649 |
650 | .req-list {
651 | list-style: none;
652 | display: grid;
653 | grid-template-columns: 1fr;
654 | gap: 1rem;
655 | }
656 |
657 | @media (min-width: 768px) {
658 | .req-list {
659 | grid-template-columns: repeat(2, 1fr);
660 | }
661 | }
662 |
663 | .req-list li {
664 | display: flex;
665 | align-items: center;
666 | gap: 10px;
667 | padding: 0.75rem;
668 | background: var(--light-bg);
669 | border-radius: var(--border-radius);
670 | transition: transform 0.3s ease;
671 | }
672 |
673 | .req-list li:hover {
674 | transform: translateY(-3px);
675 | background: white;
676 | border: 1px solid var(--accent-color);
677 | }
678 |
679 | .req-list i {
680 | color: var(--accent-color);
681 | font-size: 20px;
682 | }
683 |
684 | .action-buttons {
685 | display: flex;
686 | flex-direction: column;
687 | gap: 1rem;
688 | margin: 2rem 0;
689 | }
690 |
691 | @media (min-width: 500px) {
692 | .action-buttons {
693 | flex-direction: row;
694 | justify-content: center;
695 | }
696 | }
697 |
698 | .action-btn {
699 | display: inline-flex;
700 | align-items: center;
701 | justify-content: center;
702 | padding: 0.75rem 1.5rem;
703 | border-radius: 50px;
704 | font-weight: 500;
705 | text-decoration: none;
706 | transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
707 | gap: 8px;
708 | width: 100%;
709 | }
710 |
711 | @media (min-width: 500px) {
712 | .action-btn {
713 | width: auto;
714 | min-width: 150px;
715 | }
716 | }
717 |
718 | .github-btn {
719 | background: #24292e;
720 | color: white;
721 | }
722 |
723 | .github-btn:hover {
724 | transform: translateY(-5px);
725 | box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
726 | }
727 |
728 | .donate-btn {
729 | background: linear-gradient(45deg, #9c27b0, #673ab7);
730 | color: white;
731 | }
732 |
733 | .donate-btn:hover {
734 | transform: translateY(-5px);
735 | box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
736 | }
737 |
738 | .action-btn i {
739 | font-size: 18px;
740 | }
741 |
742 | @media (max-width: 480px) {
743 | header h1 {
744 | font-size: 1.8rem;
745 | }
746 |
747 | .card-body {
748 | padding: 1rem;
749 | }
750 |
751 | .features {
752 | grid-template-columns: 1fr;
753 | }
754 |
755 | .version-header {
756 | flex-direction: column;
757 | align-items: flex-start;
758 | gap: 5px;
759 | }
760 | }
761 |
762 | .highlight {
763 | background-color: #f1f8e9;
764 | color: #558b2f;
765 | padding: 2px 6px;
766 | border-radius: 4px;
767 | font-weight: 500;
768 | }
769 |
770 | .installation-steps {
771 | display: grid;
772 | grid-template-columns: 1fr;
773 | gap: 1.5rem;
774 | margin-bottom: 1.5rem;
775 | }
776 |
777 | .step {
778 | display: flex;
779 | gap: 15px;
780 | align-items: flex-start;
781 | }
782 |
783 | .step-number {
784 | background: linear-gradient(45deg, var(--accent-color), var(--accent-dark));
785 | color: white;
786 | width: 30px;
787 | height: 30px;
788 | border-radius: 50%;
789 | display: flex;
790 | align-items: center;
791 | justify-content: center;
792 | font-weight: 600;
793 | flex-shrink: 0;
794 | }
795 |
796 | .step-content {
797 | flex: 1;
798 | }
799 |
800 | .step-content h3 {
801 | font-size: 1.1rem;
802 | margin-bottom: 0.75rem;
803 | font-weight: 500;
804 | }
805 |
806 | .step-content p {
807 | margin-top: 0.5rem;
808 | }
809 |
810 | #installation {
811 | margin-bottom: 3rem;
812 | }
813 |
814 | .modal {
815 | display: none;
816 | position: fixed;
817 | top: 0;
818 | left: 0;
819 | width: 100%;
820 | height: 100%;
821 | background-color: rgba(0, 0, 0, 0.6);
822 | z-index: 1000;
823 | overflow: auto;
824 | backdrop-filter: blur(5px);
825 | }
826 |
827 | .modal-content {
828 | background-color: white;
829 | margin: 5vh auto;
830 | width: 90%;
831 | max-width: 600px;
832 | border-radius: var(--border-radius);
833 | box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
834 | animation: modalFadeIn 0.3s;
835 | max-height: 90vh;
836 | display: flex;
837 | flex-direction: column;
838 | }
839 |
840 | @keyframes modalFadeIn {
841 | from {opacity: 0; transform: translateY(-30px);}
842 | to {opacity: 1; transform: translateY(0);}
843 | }
844 |
845 | .modal-header {
846 | display: flex;
847 | justify-content: space-between;
848 | align-items: center;
849 | padding: 1.25rem 1.5rem;
850 | border-bottom: 1px solid var(--border-color);
851 | }
852 |
853 | .modal-header h2 {
854 | font-size: 1.25rem;
855 | font-weight: 500;
856 | display: flex;
857 | align-items: center;
858 | gap: 10px;
859 | color: var(--accent-dark);
860 | margin: 0;
861 | }
862 |
863 | .modal-header h2 i {
864 | color: #f44336;
865 | }
866 |
867 | .modal-close {
868 | font-size: 1.5rem;
869 | font-weight: 700;
870 | color: var(--accent-color);
871 | cursor: pointer;
872 | transition: all 0.2s;
873 | }
874 |
875 | .modal-close:hover {
876 | color: #f44336;
877 | transform: scale(1.1);
878 | }
879 |
880 | .modal-body {
881 | padding: 1.5rem;
882 | overflow-y: auto;
883 | }
884 |
885 | .modal-body p {
886 | margin-bottom: 1rem;
887 | line-height: 1.6;
888 | }
889 |
890 | .modal-body ul {
891 | margin: 1rem 0;
892 | padding-left: 1.5rem;
893 | }
894 |
895 | .modal-body li {
896 | margin-bottom: 0.5rem;
897 | position: relative;
898 | padding-left: 0.5rem;
899 | }
900 |
901 | .modal-body li::before {
902 | content: "•";
903 | color: var(--accent-color);
904 | font-weight: bold;
905 | position: absolute;
906 | left: -1rem;
907 | }
908 |
909 | .modal-footer {
910 | padding: 1rem 1.5rem;
911 | border-top: 1px solid var(--border-color);
912 | display: flex;
913 | justify-content: flex-end;
914 | }
915 |
916 | .timeline {
917 | position: relative;
918 | margin: 0 0 0 20px;
919 | padding-left: 20px;
920 | }
921 |
922 | .timeline-item {
923 | position: relative;
924 | margin-bottom: 30px;
925 | padding-bottom: 15px;
926 | }
927 |
928 | .timeline-item:last-child {
929 | margin-bottom: 0;
930 | padding-bottom: 0;
931 | }
932 |
933 | .timeline-dot {
934 | position: absolute;
935 | left: -31px;
936 | top: 0;
937 | width: 20px;
938 | height: 20px;
939 | border-radius: 50%;
940 | background: white;
941 | border: 3px solid var(--accent-color);
942 | z-index: 1;
943 | transition: all 0.3s ease;
944 | }
945 |
946 | .timeline-item:hover .timeline-dot {
947 | transform: scale(1.2);
948 | background: var(--accent-color);
949 | }
950 |
951 | .timeline-date {
952 | font-size: 0.9rem;
953 | font-weight: 500;
954 | color: var(--accent-dark);
955 | transition: all 0.3s ease;
956 | margin-left: 10px;
957 | opacity: 0.8;
958 | }
959 |
960 | .timeline-item:hover .timeline-date {
961 | color: var(--accent-color);
962 | font-weight: 600;
963 | }
964 |
965 | @media (max-width: 768px) {
966 | .timeline {
967 | margin-left: 0;
968 | }
969 |
970 | .timeline-date {
971 | font-size: 0.8rem;
972 | }
973 |
974 | .version-header {
975 | flex-direction: column;
976 | align-items: flex-start;
977 | gap: 5px;
978 | }
979 |
980 | .timeline-date {
981 | margin-left: 0;
982 | }
983 | }
984 |
985 | .timeline-content {
986 | position: relative;
987 | margin-left: 15px;
988 | }
989 |
990 | .timeline-card {
991 | background: white;
992 | border-radius: var(--border-radius);
993 | padding: 20px;
994 | margin-top: 15px;
995 | transition: all 0.3s ease;
996 | border: 1px solid var(--border-color);
997 | }
998 |
999 | .timeline-item:hover .timeline-card {
1000 | transform: translateY(-3px);
1001 | border-color: var(--accent-color);
1002 | }
1003 |
1004 | .version-tag {
1005 | font-weight: 600;
1006 | color: var(--accent-color);
1007 | font-size: 1.1rem;
1008 | transition: color 0.3s ease;
1009 | background: rgba(117, 117, 117, 0.1);
1010 | padding: 5px 12px;
1011 | border-radius: 50px;
1012 | display: inline-block;
1013 | }
1014 |
1015 | .timeline-item:hover .version-tag {
1016 | color: white;
1017 | background: var(--accent-color);
1018 | }
1019 |
1020 | .version-changes {
1021 | list-style-type: none;
1022 | padding: 0;
1023 | margin: 0;
1024 | }
1025 |
1026 | .version-changes li {
1027 | margin-bottom: 0.75rem;
1028 | padding-left: 0;
1029 | position: relative;
1030 | display: flex;
1031 | align-items: flex-start;
1032 | gap: 10px;
1033 | transition: transform 0.3s ease;
1034 | }
1035 |
1036 | .version-changes li:last-child {
1037 | margin-bottom: 0;
1038 | }
1039 |
1040 | .version-changes li:hover {
1041 | transform: translateX(5px);
1042 | }
1043 |
1044 | .change-type {
1045 | display: inline-block;
1046 | padding: 0.1rem 0.5rem;
1047 | border-radius: 20px;
1048 | font-size: 0.7rem;
1049 | font-weight: 600;
1050 | text-transform: uppercase;
1051 | min-width: 60px;
1052 | text-align: center;
1053 | flex-shrink: 0;
1054 | }
1055 |
1056 | @media (max-width: 768px) {
1057 | .timeline {
1058 | margin-left: 0;
1059 | }
1060 |
1061 | .timeline-date {
1062 | position: relative;
1063 | left: 0;
1064 | top: auto;
1065 | margin-bottom: 10px;
1066 | text-align: left;
1067 | width: auto;
1068 | font-size: 0.8rem;
1069 | color: var(--accent-color);
1070 | }
1071 | }
1072 |
1073 | .log-output {
1074 | background-color: #1e1e1e;
1075 | color: #f0f0f0;
1076 | font-family: "Consolas", "Monaco", monospace;
1077 | padding: 15px;
1078 | border-radius: 5px;
1079 | white-space: pre-wrap;
1080 | word-break: break-word;
1081 | max-height: 400px;
1082 | overflow-y: auto;
1083 | margin-top: 15px;
1084 | border: 1px solid #333;
1085 | font-size: 13px;
1086 | line-height: 1.5;
1087 | scrollbar-width: thin;
1088 | scrollbar-color: #555 #1e1e1e;
1089 | }
1090 |
1091 | .log-output::-webkit-scrollbar {
1092 | width: 8px;
1093 | height: 8px;
1094 | }
1095 |
1096 | .log-output::-webkit-scrollbar-track {
1097 | background: #1e1e1e;
1098 | border-radius: 4px;
1099 | }
1100 |
1101 | .log-output::-webkit-scrollbar-thumb {
1102 | background: #555;
1103 | border-radius: 4px;
1104 | }
1105 |
1106 | .log-output::-webkit-scrollbar-thumb:hover {
1107 | background: #777;
1108 | }
1109 |
1110 | .result-table {
1111 | width: 100%;
1112 | margin-top: 1rem;
1113 | border-collapse: collapse;
1114 | font-family: 'Consolas', 'Monaco', monospace;
1115 | font-size: 0.9rem;
1116 | }
1117 |
1118 | .result-table th {
1119 | text-align: left;
1120 | background-color: #f5f5f5;
1121 | padding: 0.5rem 1rem;
1122 | border: 1px solid var(--border-color);
1123 | font-weight: 600;
1124 | }
1125 |
1126 | .result-table td {
1127 | padding: 0.5rem 1rem;
1128 | border: 1px solid var(--border-color);
1129 | word-break: break-all;
1130 | }
1131 |
1132 | .result-table tr:nth-child(even) {
1133 | background-color: #fafafa;
1134 | }
1135 |
1136 | .action-grid {
1137 | display: grid;
1138 | grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
1139 | gap: 15px;
1140 | margin-bottom: 20px;
1141 | }
1142 |
1143 | .action-grid .btn {
1144 | width: 100%;
1145 | text-align: left;
1146 | display: flex;
1147 | align-items: center;
1148 | gap: 8px;
1149 | padding: 12px 16px;
1150 | font-weight: 500;
1151 | transition: all 0.2s ease;
1152 | }
1153 |
1154 | .action-grid .btn:hover {
1155 | transform: translateY(-2px);
1156 | }
1157 |
1158 | .btn-warning {
1159 | background: #ff9800;
1160 | color: #fff;
1161 | }
1162 |
1163 | .btn-info {
1164 | background: #03a9f4;
1165 | color: #fff;
1166 | }
1167 |
1168 | .btn-success {
1169 | background: #4caf50;
1170 | color: #fff;
1171 | }
1172 |
1173 | .atomic-email-container {
1174 | margin-top: 1rem;
1175 | }
1176 |
1177 | .email-details {
1178 | background-color: #f8f9fa;
1179 | border-radius: 8px;
1180 | padding: 1rem;
1181 | margin-top: 1rem;
1182 | border: 1px solid #e9ecef;
1183 | box-shadow: none;
1184 | }
1185 |
1186 | .detail-item {
1187 | display: flex;
1188 | align-items: center;
1189 | margin-bottom: 0.75rem;
1190 | padding: 0.75rem 1rem;
1191 | background-color: #fff;
1192 | border-radius: 4px;
1193 | box-shadow: none;
1194 | border: 1px solid #f1f3f5;
1195 | }
1196 |
1197 | .detail-label {
1198 | font-weight: 500;
1199 | min-width: 120px;
1200 | color: #333;
1201 | font-family: 'Google Sans', -apple-system, sans-serif;
1202 | }
1203 |
1204 | .detail-value {
1205 | flex: 1;
1206 | font-family: 'Google Sans', -apple-system, sans-serif;
1207 | word-break: break-all;
1208 | padding: 0.25rem 0.5rem;
1209 | background-color: #f1f3f5;
1210 | border-radius: 4px;
1211 | font-size: 0.9rem;
1212 | }
1213 |
1214 | .copy-btn {
1215 | background: none;
1216 | border: none;
1217 | color: #0066cc;
1218 | cursor: pointer;
1219 | padding: 0.25rem 0.5rem;
1220 | border-radius: 4px;
1221 | transition: all 0.2s;
1222 | margin-left: 0.5rem;
1223 | }
1224 |
1225 | .copy-btn:hover {
1226 | background-color: #e9ecef;
1227 | }
1228 |
1229 | .verification-status {
1230 | display: flex;
1231 | align-items: center;
1232 | gap: 1rem;
1233 | padding: 1rem;
1234 | background-color: #fff8e1;
1235 | border-radius: 8px;
1236 | margin-top: 1rem;
1237 | }
1238 |
1239 | .loading-spinner {
1240 | width: 20px;
1241 | height: 20px;
1242 | border: 3px solid rgba(255, 202, 40, 0.3);
1243 | border-radius: 50%;
1244 | border-top-color: #ffca28;
1245 | animation: spin 1s ease-in-out infinite;
1246 | }
1247 |
1248 | @keyframes spin {
1249 | to { transform: rotate(360deg); }
1250 | }
1251 |
1252 | .hidden {
1253 | display: none;
1254 | }
1255 |
1256 | .mt-4 {
1257 | margin-top: 1rem;
1258 | }
1259 |
1260 | .verification-code-container {
1261 | border-top: 1px solid #e9ecef;
1262 | padding-top: 0.75rem;
1263 | margin-top: 0.75rem;
1264 | background-color: #e8f5e9;
1265 | box-shadow: none;
1266 | }
1267 |
1268 | #verification-code {
1269 | font-size: 1.1rem;
1270 | letter-spacing: 0.5px;
1271 | font-weight: 500;
1272 | color: #1b5e20;
1273 | background-color: #c8e6c9;
1274 | font-family: 'Google Sans', -apple-system, sans-serif;
1275 | }
1276 |
1277 | .copied {
1278 | animation: copy-animation 1.5s ease;
1279 | }
1280 |
1281 | @keyframes copy-animation {
1282 | 0% { background-color: #c8e6c9; }
1283 | 70% { background-color: #c8e6c9; }
1284 | 100% { background-color: transparent; }
1285 | }
1286 |
1287 | .toast-container {
1288 | position: fixed;
1289 | bottom: 20px;
1290 | right: 20px;
1291 | z-index: 9999;
1292 | display: flex;
1293 | flex-direction: column;
1294 | gap: 10px;
1295 | max-width: 350px;
1296 | }
1297 |
1298 | .toast {
1299 | background-color: #fff;
1300 | border-radius: 8px;
1301 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1302 | overflow: hidden;
1303 | display: flex;
1304 | align-items: center;
1305 | justify-content: space-between;
1306 | animation: toast-in 0.3s ease forwards;
1307 | opacity: 0;
1308 | transform: translateY(20px);
1309 | }
1310 |
1311 | .toast-content {
1312 | display: flex;
1313 | align-items: flex-start;
1314 | gap: 10px;
1315 | padding: 12px 15px;
1316 | flex: 1;
1317 | }
1318 |
1319 | .toast-content i {
1320 | margin-top: 3px;
1321 | }
1322 |
1323 | .toast-content span {
1324 | font-size: 14px;
1325 | color: #333;
1326 | }
1327 |
1328 | .toast-close {
1329 | background: none;
1330 | border: none;
1331 | color: #777;
1332 | cursor: pointer;
1333 | padding: 8px 12px;
1334 | transition: all 0.2s;
1335 | }
1336 |
1337 | .toast-close:hover {
1338 | color: #333;
1339 | }
1340 |
1341 | .toast-error i {
1342 | color: #f44336;
1343 | }
1344 |
1345 | .toast-success i {
1346 | color: #4caf50;
1347 | }
1348 |
1349 | .toast-info i {
1350 | color: #2196f3;
1351 | }
1352 |
1353 | .toast-warning i {
1354 | color: #ff9800;
1355 | }
1356 |
1357 | .toast-closing {
1358 | animation: toast-out 0.3s ease forwards;
1359 | }
1360 |
1361 | @keyframes toast-in {
1362 | from {
1363 | opacity: 0;
1364 | transform: translateY(20px);
1365 | }
1366 | to {
1367 | opacity: 1;
1368 | transform: translateY(0);
1369 | }
1370 | }
1371 |
1372 | @keyframes toast-out {
1373 | from {
1374 | opacity: 1;
1375 | transform: translateY(0);
1376 | }
1377 | to {
1378 | opacity: 0;
1379 | transform: translateY(20px);
1380 | }
1381 | }
1382 |
1383 | .rotating {
1384 | display: flex;
1385 | align-items: center;
1386 | justify-content: center;
1387 | width: 20px;
1388 | height: 20px;
1389 | position: relative;
1390 | }
1391 |
1392 | .rotating i {
1393 | position: absolute;
1394 | animation: spin 1s linear infinite;
1395 | transform-origin: center;
1396 | top: 0;
1397 | left: 0;
1398 | width: 100%;
1399 | height: 100%;
1400 | display: flex;
1401 | align-items: center;
1402 | justify-content: center;
1403 | }
1404 |
1405 | @keyframes spin {
1406 | 0% { transform: rotate(0deg); }
1407 | 100% { transform: rotate(360deg); }
1408 | }
1409 |
1410 | .btn-content {
1411 | display: flex;
1412 | align-items: center;
1413 | justify-content: center;
1414 | gap: 8px;
1415 | width: 100%;
1416 | }
1417 |
1418 | .email-generator-container {
1419 | margin-top: 1rem;
1420 | padding: 1rem;
1421 | background: var(--light-bg);
1422 | border-radius: var(--border-radius);
1423 | text-align: center;
1424 | }
1425 |
1426 | .email-generator-container p {
1427 | margin-bottom: 0.5rem;
1428 | color: var(--text-color);
1429 | }
1430 |
1431 | .email-generator-container p:last-child {
1432 | margin-bottom: 0;
1433 | font-size: 0.9rem;
1434 | opacity: 0.8;
1435 | }
1436 |
--------------------------------------------------------------------------------