FreeCall - Beautiful Video Calling Without Limits | Free Online Video Chat

Beautiful video calling without limits

Rated #1 Free Video Calling Platform

Beautiful Video Calling For Everyone

Connect instantly with friends, family, and colleagues in crystal-clear video calls. No downloads, no registration, just pure video calling magic powered by your browser.

2M+ Happy Users
15 Max Participants
100% Free Forever
Sarah
John
Alex

Why Choose FreeCall?

Experience the future of video calling with our beautiful, feature-rich platform

Instant Connection

Start video calls in seconds with no downloads required

Group Calling

Connect up to 15 people in crystal-clear video calls

Screen Sharing

Share your screen with beautiful transitions and controls

Private & Secure

End-to-end encrypted calls with no data storage

Mobile Friendly

Perfect experience on phones, tablets, and desktops

Real-time Chat

Send messages and emojis during your video calls

Loved by millions worldwide

"The most beautiful video calling app I've ever used!"

Sarah Chen Remote Team Lead

"Finally, a video calling platform that's actually fun to use."

Marcus Johnson Freelance Designer

Create a New Meeting Room

Set up your video call and share the link with participants

Camera Preview

Camera off

Join a Meeting

Enter the room ID to join an existing video call

Camera Preview

Camera off

Room:

00:00:00 1 participant Connected
You

Chat

Chat is ready. Send a message to start the conversation.

:root { /* Primitive Color Tokens */ --color-white: rgba(255, 255, 255, 1); --color-black: rgba(0, 0, 0, 1); --color-cream-50: rgba(252, 252, 249, 1); --color-cream-100: rgba(255, 255, 253, 1); --color-gray-200: rgba(245, 245, 245, 1); --color-gray-300: rgba(167, 169, 169, 1); --color-gray-400: rgba(119, 124, 124, 1); --color-slate-500: rgba(98, 108, 113, 1); --color-brown-600: rgba(94, 82, 64, 1); --color-charcoal-700: rgba(31, 33, 33, 1); --color-charcoal-800: rgba(38, 40, 40, 1); --color-slate-900: rgba(19, 52, 59, 1); --color-teal-300: rgba(50, 184, 198, 1); --color-teal-400: rgba(45, 166, 178, 1); --color-teal-500: rgba(33, 128, 141, 1); --color-teal-600: rgba(29, 116, 128, 1); --color-teal-700: rgba(26, 104, 115, 1); --color-teal-800: rgba(41, 150, 161, 1); --color-red-400: rgba(255, 84, 89, 1); --color-red-500: rgba(192, 21, 47, 1); --color-orange-400: rgba(230, 129, 97, 1); --color-orange-500: rgba(168, 75, 47, 1); /* RGB versions for opacity control */ --color-brown-600-rgb: 94, 82, 64; --color-teal-500-rgb: 33, 128, 141; --color-slate-900-rgb: 19, 52, 59; --color-slate-500-rgb: 98, 108, 113; --color-red-500-rgb: 192, 21, 47; --color-red-400-rgb: 255, 84, 89; --color-orange-500-rgb: 168, 75, 47; --color-orange-400-rgb: 230, 129, 97; /* Background color tokens (Light Mode) */ --color-bg-1: rgba(59, 130, 246, 0.08); /* Light blue */ --color-bg-2: rgba(245, 158, 11, 0.08); /* Light yellow */ --color-bg-3: rgba(34, 197, 94, 0.08); /* Light green */ --color-bg-4: rgba(239, 68, 68, 0.08); /* Light red */ --color-bg-5: rgba(147, 51, 234, 0.08); /* Light purple */ --color-bg-6: rgba(249, 115, 22, 0.08); /* Light orange */ --color-bg-7: rgba(236, 72, 153, 0.08); /* Light pink */ --color-bg-8: rgba(6, 182, 212, 0.08); /* Light cyan */ /* Semantic Color Tokens (Light Mode) */ --color-background: var(--color-cream-50); --color-surface: var(--color-cream-100); --color-text: var(--color-slate-900); --color-text-secondary: var(--color-slate-500); --color-primary: var(--color-teal-500); --color-primary-hover: var(--color-teal-600); --color-primary-active: var(--color-teal-700); --color-secondary: rgba(var(--color-brown-600-rgb), 0.12); --color-secondary-hover: rgba(var(--color-brown-600-rgb), 0.2); --color-secondary-active: rgba(var(--color-brown-600-rgb), 0.25); --color-border: rgba(var(--color-brown-600-rgb), 0.2); --color-btn-primary-text: var(--color-cream-50); --color-card-border: rgba(var(--color-brown-600-rgb), 0.12); --color-card-border-inner: rgba(var(--color-brown-600-rgb), 0.12); --color-error: var(--color-red-500); --color-success: var(--color-teal-500); --color-warning: var(--color-orange-500); --color-info: var(--color-slate-500); --color-focus-ring: rgba(var(--color-teal-500-rgb), 0.4); --color-select-caret: rgba(var(--color-slate-900-rgb), 0.8); /* Common style patterns */ --focus-ring: 0 0 0 3px var(--color-focus-ring); --focus-outline: 2px solid var(--color-primary); --status-bg-opacity: 0.15; --status-border-opacity: 0.25; --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); /* RGB versions for opacity control */ --color-success-rgb: 33, 128, 141; --color-error-rgb: 192, 21, 47; --color-warning-rgb: 168, 75, 47; --color-info-rgb: 98, 108, 113; /* Typography */ --font-family-base: "FKGroteskNeue", "Geist", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; --font-family-mono: "Berkeley Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; --font-size-xs: 11px; --font-size-sm: 12px; --font-size-base: 14px; --font-size-md: 14px; --font-size-lg: 16px; --font-size-xl: 18px; --font-size-2xl: 20px; --font-size-3xl: 24px; --font-size-4xl: 30px; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 550; --font-weight-bold: 600; --line-height-tight: 1.2; --line-height-normal: 1.5; --letter-spacing-tight: -0.01em; /* Spacing */ --space-0: 0; --space-1: 1px; --space-2: 2px; --space-4: 4px; --space-6: 6px; --space-8: 8px; --space-10: 10px; --space-12: 12px; --space-16: 16px; --space-20: 20px; --space-24: 24px; --space-32: 32px; /* Border Radius */ --radius-sm: 6px; --radius-base: 8px; --radius-md: 10px; --radius-lg: 12px; --radius-full: 9999px; /* Shadows */ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.02); --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.02); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.04), 0 2px 4px -1px rgba(0, 0, 0, 0.02); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.04), 0 4px 6px -2px rgba(0, 0, 0, 0.02); --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.03); /* Animation */ --duration-fast: 150ms; --duration-normal: 250ms; --ease-standard: cubic-bezier(0.16, 1, 0.3, 1); /* Layout */ --container-sm: 640px; --container-md: 768px; --container-lg: 1024px; --container-xl: 1280px; } /* Dark mode colors */ @media (prefers-color-scheme: dark) { :root { /* RGB versions for opacity control (Dark Mode) */ --color-gray-400-rgb: 119, 124, 124; --color-teal-300-rgb: 50, 184, 198; --color-gray-300-rgb: 167, 169, 169; --color-gray-200-rgb: 245, 245, 245; /* Background color tokens (Dark Mode) */ --color-bg-1: rgba(29, 78, 216, 0.15); /* Dark blue */ --color-bg-2: rgba(180, 83, 9, 0.15); /* Dark yellow */ --color-bg-3: rgba(21, 128, 61, 0.15); /* Dark green */ --color-bg-4: rgba(185, 28, 28, 0.15); /* Dark red */ --color-bg-5: rgba(107, 33, 168, 0.15); /* Dark purple */ --color-bg-6: rgba(194, 65, 12, 0.15); /* Dark orange */ --color-bg-7: rgba(190, 24, 93, 0.15); /* Dark pink */ --color-bg-8: rgba(8, 145, 178, 0.15); /* Dark cyan */ /* Semantic Color Tokens (Dark Mode) */ --color-background: var(--color-charcoal-700); --color-surface: var(--color-charcoal-800); --color-text: var(--color-gray-200); --color-text-secondary: rgba(var(--color-gray-300-rgb), 0.7); --color-primary: var(--color-teal-300); --color-primary-hover: var(--color-teal-400); --color-primary-active: var(--color-teal-800); --color-secondary: rgba(var(--color-gray-400-rgb), 0.15); --color-secondary-hover: rgba(var(--color-gray-400-rgb), 0.25); --color-secondary-active: rgba(var(--color-gray-400-rgb), 0.3); --color-border: rgba(var(--color-gray-400-rgb), 0.3); --color-error: var(--color-red-400); --color-success: var(--color-teal-300); --color-warning: var(--color-orange-400); --color-info: var(--color-gray-300); --color-focus-ring: rgba(var(--color-teal-300-rgb), 0.4); --color-btn-primary-text: var(--color-slate-900); --color-card-border: rgba(var(--color-gray-400-rgb), 0.2); --color-card-border-inner: rgba(var(--color-gray-400-rgb), 0.15); --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.15); --button-border-secondary: rgba(var(--color-gray-400-rgb), 0.2); --color-border-secondary: rgba(var(--color-gray-400-rgb), 0.2); --color-select-caret: rgba(var(--color-gray-200-rgb), 0.8); /* Common style patterns - updated for dark mode */ --focus-ring: 0 0 0 3px var(--color-focus-ring); --focus-outline: 2px solid var(--color-primary); --status-bg-opacity: 0.15; --status-border-opacity: 0.25; --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); /* RGB versions for dark mode */ --color-success-rgb: var(--color-teal-300-rgb); --color-error-rgb: var(--color-red-400-rgb); --color-warning-rgb: var(--color-orange-400-rgb); --color-info-rgb: var(--color-gray-300-rgb); } } /* Data attribute for manual theme switching */ [data-color-scheme="dark"] { /* RGB versions for opacity control (dark mode) */ --color-gray-400-rgb: 119, 124, 124; --color-teal-300-rgb: 50, 184, 198; --color-gray-300-rgb: 167, 169, 169; --color-gray-200-rgb: 245, 245, 245; /* Colorful background palette - Dark Mode */ --color-bg-1: rgba(29, 78, 216, 0.15); /* Dark blue */ --color-bg-2: rgba(180, 83, 9, 0.15); /* Dark yellow */ --color-bg-3: rgba(21, 128, 61, 0.15); /* Dark green */ --color-bg-4: rgba(185, 28, 28, 0.15); /* Dark red */ --color-bg-5: rgba(107, 33, 168, 0.15); /* Dark purple */ --color-bg-6: rgba(194, 65, 12, 0.15); /* Dark orange */ --color-bg-7: rgba(190, 24, 93, 0.15); /* Dark pink */ --color-bg-8: rgba(8, 145, 178, 0.15); /* Dark cyan */ /* Semantic Color Tokens (Dark Mode) */ --color-background: var(--color-charcoal-700); --color-surface: var(--color-charcoal-800); --color-text: var(--color-gray-200); --color-text-secondary: rgba(var(--color-gray-300-rgb), 0.7); --color-primary: var(--color-teal-300); --color-primary-hover: var(--color-teal-400); --color-primary-active: var(--color-teal-800); --color-secondary: rgba(var(--color-gray-400-rgb), 0.15); --color-secondary-hover: rgba(var(--color-gray-400-rgb), 0.25); --color-secondary-active: rgba(var(--color-gray-400-rgb), 0.3); --color-border: rgba(var(--color-gray-400-rgb), 0.3); --color-error: var(--color-red-400); --color-success: var(--color-teal-300); --color-warning: var(--color-orange-400); --color-info: var(--color-gray-300); --color-focus-ring: rgba(var(--color-teal-300-rgb), 0.4); --color-btn-primary-text: var(--color-slate-900); --color-card-border: rgba(var(--color-gray-400-rgb), 0.15); --color-card-border-inner: rgba(var(--color-gray-400-rgb), 0.15); --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.15); --color-border-secondary: rgba(var(--color-gray-400-rgb), 0.2); --color-select-caret: rgba(var(--color-gray-200-rgb), 0.8); /* Common style patterns - updated for dark mode */ --focus-ring: 0 0 0 3px var(--color-focus-ring); --focus-outline: 2px solid var(--color-primary); --status-bg-opacity: 0.15; --status-border-opacity: 0.25; --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); /* RGB versions for dark mode */ --color-success-rgb: var(--color-teal-300-rgb); --color-error-rgb: var(--color-red-400-rgb); --color-warning-rgb: var(--color-orange-400-rgb); --color-info-rgb: var(--color-gray-300-rgb); } [data-color-scheme="light"] { /* RGB versions for opacity control (light mode) */ --color-brown-600-rgb: 94, 82, 64; --color-teal-500-rgb: 33, 128, 141; --color-slate-900-rgb: 19, 52, 59; /* Semantic Color Tokens (Light Mode) */ --color-background: var(--color-cream-50); --color-surface: var(--color-cream-100); --color-text: var(--color-slate-900); --color-text-secondary: var(--color-slate-500); --color-primary: var(--color-teal-500); --color-primary-hover: var(--color-teal-600); --color-primary-active: var(--color-teal-700); --color-secondary: rgba(var(--color-brown-600-rgb), 0.12); --color-secondary-hover: rgba(var(--color-brown-600-rgb), 0.2); --color-secondary-active: rgba(var(--color-brown-600-rgb), 0.25); --color-border: rgba(var(--color-brown-600-rgb), 0.2); --color-btn-primary-text: var(--color-cream-50); --color-card-border: rgba(var(--color-brown-600-rgb), 0.12); --color-card-border-inner: rgba(var(--color-brown-600-rgb), 0.12); --color-error: var(--color-red-500); --color-success: var(--color-teal-500); --color-warning: var(--color-orange-500); --color-info: var(--color-slate-500); --color-focus-ring: rgba(var(--color-teal-500-rgb), 0.4); /* RGB versions for light mode */ --color-success-rgb: var(--color-teal-500-rgb); --color-error-rgb: var(--color-red-500-rgb); --color-warning-rgb: var(--color-orange-500-rgb); --color-info-rgb: var(--color-slate-500-rgb); } /* Base styles */ html { font-size: var(--font-size-base); font-family: var(--font-family-base); line-height: var(--line-height-normal); color: var(--color-text); background-color: var(--color-background); -webkit-font-smoothing: antialiased; box-sizing: border-box; } body { margin: 0; padding: 0; } *, *::before, *::after { box-sizing: inherit; } /* Typography */ h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: var(--font-weight-semibold); line-height: var(--line-height-tight); color: var(--color-text); letter-spacing: var(--letter-spacing-tight); } h1 { font-size: var(--font-size-4xl); } h2 { font-size: var(--font-size-3xl); } h3 { font-size: var(--font-size-2xl); } h4 { font-size: var(--font-size-xl); } h5 { font-size: var(--font-size-lg); } h6 { font-size: var(--font-size-md); } p { margin: 0 0 var(--space-16) 0; } a { color: var(--color-primary); text-decoration: none; transition: color var(--duration-fast) var(--ease-standard); } a:hover { color: var(--color-primary-hover); } code, pre { font-family: var(--font-family-mono); font-size: calc(var(--font-size-base) * 0.95); background-color: var(--color-secondary); border-radius: var(--radius-sm); } code { padding: var(--space-1) var(--space-4); } pre { padding: var(--space-16); margin: var(--space-16) 0; overflow: auto; border: 1px solid var(--color-border); } pre code { background: none; padding: 0; } /* Buttons */ .btn { display: inline-flex; align-items: center; justify-content: center; padding: var(--space-8) var(--space-16); border-radius: var(--radius-base); font-size: var(--font-size-base); font-weight: 500; line-height: 1.5; cursor: pointer; transition: all var(--duration-normal) var(--ease-standard); border: none; text-decoration: none; position: relative; } .btn:focus-visible { outline: none; box-shadow: var(--focus-ring); } .btn--primary { background: var(--color-primary); color: var(--color-btn-primary-text); } .btn--primary:hover { background: var(--color-primary-hover); } .btn--primary:active { background: var(--color-primary-active); } .btn--secondary { background: var(--color-secondary); color: var(--color-text); } .btn--secondary:hover { background: var(--color-secondary-hover); } .btn--secondary:active { background: var(--color-secondary-active); } .btn--outline { background: transparent; border: 1px solid var(--color-border); color: var(--color-text); } .btn--outline:hover { background: var(--color-secondary); } .btn--sm { padding: var(--space-4) var(--space-12); font-size: var(--font-size-sm); border-radius: var(--radius-sm); } .btn--lg { padding: var(--space-10) var(--space-20); font-size: var(--font-size-lg); border-radius: var(--radius-md); } .btn--full-width { width: 100%; } .btn:disabled { opacity: 0.5; cursor: not-allowed; } /* Form elements */ .form-control { display: block; width: 100%; padding: var(--space-8) var(--space-12); font-size: var(--font-size-md); line-height: 1.5; color: var(--color-text); background-color: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-base); transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); } textarea.form-control { font-family: var(--font-family-base); font-size: var(--font-size-base); } select.form-control { padding: var(--space-8) var(--space-12); -webkit-appearance: none; -moz-appearance: none; appearance: none; background-image: var(--select-caret-light); background-repeat: no-repeat; background-position: right var(--space-12) center; background-size: 16px; padding-right: var(--space-32); } /* Add a dark mode specific caret */ @media (prefers-color-scheme: dark) { select.form-control { background-image: var(--select-caret-dark); } } /* Also handle data-color-scheme */ [data-color-scheme="dark"] select.form-control { background-image: var(--select-caret-dark); } [data-color-scheme="light"] select.form-control { background-image: var(--select-caret-light); } .form-control:focus { border-color: var(--color-primary); outline: var(--focus-outline); } .form-label { display: block; margin-bottom: var(--space-8); font-weight: var(--font-weight-medium); font-size: var(--font-size-sm); } .form-group { margin-bottom: var(--space-16); } /* Card component */ .card { background-color: var(--color-surface); border-radius: var(--radius-lg); border: 1px solid var(--color-card-border); box-shadow: var(--shadow-sm); overflow: hidden; transition: box-shadow var(--duration-normal) var(--ease-standard); } .card:hover { box-shadow: var(--shadow-md); } .card__body { padding: var(--space-16); } .card__header, .card__footer { padding: var(--space-16); border-bottom: 1px solid var(--color-card-border-inner); } /* Status indicators - simplified with CSS variables */ .status { display: inline-flex; align-items: center; padding: var(--space-6) var(--space-12); border-radius: var(--radius-full); font-weight: var(--font-weight-medium); font-size: var(--font-size-sm); } .status--success { background-color: rgba( var(--color-success-rgb, 33, 128, 141), var(--status-bg-opacity) ); color: var(--color-success); border: 1px solid rgba(var(--color-success-rgb, 33, 128, 141), var(--status-border-opacity)); } .status--error { background-color: rgba( var(--color-error-rgb, 192, 21, 47), var(--status-bg-opacity) ); color: var(--color-error); border: 1px solid rgba(var(--color-error-rgb, 192, 21, 47), var(--status-border-opacity)); } .status--warning { background-color: rgba( var(--color-warning-rgb, 168, 75, 47), var(--status-bg-opacity) ); color: var(--color-warning); border: 1px solid rgba(var(--color-warning-rgb, 168, 75, 47), var(--status-border-opacity)); } .status--info { background-color: rgba( var(--color-info-rgb, 98, 108, 113), var(--status-bg-opacity) ); color: var(--color-info); border: 1px solid rgba(var(--color-info-rgb, 98, 108, 113), var(--status-border-opacity)); } /* Container layout */ .container { width: 100%; margin-right: auto; margin-left: auto; padding-right: var(--space-16); padding-left: var(--space-16); } @media (min-width: 640px) { .container { max-width: var(--container-sm); } } @media (min-width: 768px) { .container { max-width: var(--container-md); } } @media (min-width: 1024px) { .container { max-width: var(--container-lg); } } @media (min-width: 1280px) { .container { max-width: var(--container-xl); } } /* Utility classes */ .flex { display: flex; } .flex-col { flex-direction: column; } .items-center { align-items: center; } .justify-center { justify-content: center; } .justify-between { justify-content: space-between; } .gap-4 { gap: var(--space-4); } .gap-8 { gap: var(--space-8); } .gap-16 { gap: var(--space-16); } .m-0 { margin: 0; } .mt-8 { margin-top: var(--space-8); } .mb-8 { margin-bottom: var(--space-8); } .mx-8 { margin-left: var(--space-8); margin-right: var(--space-8); } .my-8 { margin-top: var(--space-8); margin-bottom: var(--space-8); } .p-0 { padding: 0; } .py-8 { padding-top: var(--space-8); padding-bottom: var(--space-8); } .px-8 { padding-left: var(--space-8); padding-right: var(--space-8); } .py-16 { padding-top: var(--space-16); padding-bottom: var(--space-16); } .px-16 { padding-left: var(--space-16); padding-right: var(--space-16); } .block { display: block; } .hidden { display: none; } /* Accessibility */ .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 { outline: var(--focus-outline); outline-offset: 2px; } /* Dark mode specifics */ [data-color-scheme="dark"] .btn--outline { border: 1px solid var(--color-border-secondary); } @font-face { font-family: 'FKGroteskNeue'; src: url('https://r2cdn.perplexity.ai/fonts/FKGroteskNeue.woff2') format('woff2'); } /* END PERPLEXITY DESIGN SYSTEM */ /* Modern glassmorphism and beautiful video calling styles */ /* Reset and base styles */ * { box-sizing: border-box; margin: 0; padding: 0; } /* CSS Variables for the modern theme */ :root { /* Modern gradient colors */ --gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%); --gradient-secondary: linear-gradient(135deg, #00D4FF 0%, #4ECDC4 100%); --gradient-accent: linear-gradient(135deg, #FF6B6B 0%, #FFD93D 100%); /* Glassmorphism colors */ --glass-bg: rgba(255, 255, 255, 0.1); --glass-border: rgba(255, 255, 255, 0.2); --glass-shadow: 0 8px 32px rgba(31, 38, 135, 0.37); --glass-blur: blur(12px); /* Accent colors */ --accent-cyan: #00D4FF; --accent-coral: #FF6B6B; --accent-mint: #4ECDC4; --accent-purple: #A8E6CF; --accent-gold: #FFD93D; /* Animation variables */ --animation-fast: 0.2s; --animation-normal: 0.3s; --animation-slow: 0.5s; --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55); --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1); /* Typography */ --font-primary: 'Poppins', system-ui, -apple-system, sans-serif; /* Shadows */ --shadow-soft: 0 10px 40px rgba(0, 0, 0, 0.1); --shadow-medium: 0 20px 60px rgba(0, 0, 0, 0.15); --shadow-strong: 0 30px 80px rgba(0, 0, 0, 0.2); /* Dark theme colors */ --dark-bg-primary: #0a0a0f; --dark-bg-secondary: #1a1a24; --dark-text-primary: #ffffff; --dark-text-secondary: #a0a0a0; } body { font-family: var(--font-primary); background: var(--gradient-primary); color: var(--color-text); line-height: 1.6; overflow-x: hidden; min-height: 100vh; position: relative; } body.dark-theme { background: linear-gradient(135deg, var(--dark-bg-primary) 0%, var(--dark-bg-secondary) 100%); color: var(--dark-text-primary); } /* Particle Background */ .particles-container { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: -1; opacity: 0.6; } .particle { position: absolute; background: var(--accent-cyan); border-radius: 50%; animation: float 6s ease-in-out infinite; } @keyframes float { 0%, 100% { transform: translateY(0) rotate(0deg); opacity: 0.3; } 50% { transform: translateY(-20px) rotate(180deg); opacity: 0.8; } } /* Header */ .header { position: fixed; top: 0; left: 0; right: 0; background: var(--glass-bg); backdrop-filter: var(--glass-blur); border-bottom: 1px solid var(--glass-border); z-index: 1000; transition: all var(--animation-normal) var(--ease-smooth); } .header-content { display: flex; align-items: center; justify-content: space-between; padding: var(--space-16) 0; max-width: 1200px; margin: 0 auto; padding-left: var(--space-20); padding-right: var(--space-20); } .brand { display: flex; align-items: center; gap: var(--space-16); } .brand-logo { display: flex; align-items: center; gap: var(--space-12); } .brand-icon { font-size: var(--font-size-2xl); background: var(--gradient-secondary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; animation: pulse 2s ease-in-out infinite; } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } } .brand-name { font-size: var(--font-size-2xl); font-weight: 800; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; margin: 0; } .brand-slogan { font-size: var(--font-size-sm); color: var(--color-text-secondary); margin: 0; opacity: 0.8; } .nav { display: flex; align-items: center; gap: var(--space-20); } .nav-toggle { display: none; background: none; border: none; font-size: var(--font-size-lg); color: var(--color-text); cursor: pointer; padding: var(--space-8); border-radius: var(--radius-base); transition: all var(--animation-fast) var(--ease-smooth); } .nav-toggle:hover { background: var(--glass-bg); } .nav-list { display: flex; list-style: none; margin: 0; padding: 0; gap: var(--space-8); } .nav-link { padding: var(--space-12) var(--space-20); border-radius: var(--radius-full); transition: all var(--animation-normal) var(--ease-smooth); font-weight: 500; text-decoration: none; color: var(--color-text); position: relative; overflow: hidden; } .nav-link::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: var(--gradient-secondary); transition: left var(--animation-normal) var(--ease-smooth); border-radius: var(--radius-full); z-index: -1; } .nav-link:hover::before, .nav-link.active::before { left: 0; } .nav-link:hover, .nav-link.active { color: white; transform: translateY(-2px); } .theme-toggle { background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--radius-full); width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all var(--animation-normal) var(--ease-smooth); color: var(--color-text); } .theme-toggle:hover { background: var(--glass-border); transform: scale(1.1); } /* Main content */ .main { min-height: 100vh; padding-top: 80px; } .page { display: none; min-height: calc(100vh - 80px); animation: fadeIn var(--animation-normal) var(--ease-smooth); } .page.active { display: block; } @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .container { max-width: 1200px; margin: 0 auto; padding: 0 var(--space-20); } /* Hero section */ .hero { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-32); align-items: center; min-height: 80vh; padding: var(--space-32) 0; } .hero-badge { display: inline-flex; align-items: center; gap: var(--space-8); background: var(--glass-bg); backdrop-filter: var(--glass-blur); padding: var(--space-8) var(--space-16); border-radius: var(--radius-full); border: 1px solid var(--glass-border); font-size: var(--font-size-sm); font-weight: 500; margin-bottom: var(--space-24); color: var(--accent-gold); animation: slideInLeft var(--animation-slow) var(--ease-bounce); } .hero-badge i { animation: sparkle 1.5s ease-in-out infinite; } @keyframes sparkle { 0%, 100% { transform: scale(1) rotate(0deg); } 50% { transform: scale(1.2) rotate(180deg); } } .hero-title { font-size: clamp(2.5rem, 5vw, 4rem); font-weight: 800; line-height: 1.1; margin-bottom: var(--space-24); animation: slideInLeft var(--animation-slow) var(--ease-bounce) 0.2s; } .gradient-text { background: var(--gradient-accent); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .hero-description { font-size: var(--font-size-lg); color: var(--color-text-secondary); margin-bottom: var(--space-32); line-height: 1.7; animation: slideInLeft var(--animation-slow) var(--ease-bounce) 0.4s; } .hero-actions { display: flex; gap: var(--space-20); margin-bottom: var(--space-32); flex-wrap: wrap; animation: slideInLeft var(--animation-slow) var(--ease-bounce) 0.6s; } .hero-stats { display: flex; gap: var(--space-32); animation: slideInLeft var(--animation-slow) var(--ease-bounce) 0.8s; } .stat-item { text-align: center; } .stat-number { display: block; font-size: var(--font-size-2xl); font-weight: 800; background: var(--gradient-secondary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .stat-label { font-size: var(--font-size-sm); color: var(--color-text-secondary); font-weight: 500; } /* Hero visual */ .hero-visual { position: relative; animation: slideInRight var(--animation-slow) var(--ease-bounce); } .hero-image { position: relative; height: 400px; display: flex; align-items: center; justify-content: center; } .floating-card { position: absolute; background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); border-radius: var(--radius-lg); padding: var(--space-16); box-shadow: var(--shadow-soft); animation: float 3s ease-in-out infinite; min-width: 120px; } .floating-card.card-1 { top: 20%; left: 10%; animation-delay: 0s; } .floating-card.card-2 { top: 60%; right: 20%; animation-delay: 1s; } .floating-card.card-3 { bottom: 20%; left: 20%; animation-delay: 2s; } .mock-video { width: 80px; height: 60px; background: var(--gradient-primary); border-radius: var(--radius-base); display: flex; align-items: center; justify-content: center; color: white; font-size: var(--font-size-lg); margin-bottom: var(--space-8); } .participant-name { font-size: var(--font-size-sm); font-weight: 500; text-align: center; color: var(--color-text); } .floating-elements { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .floating-icon { position: absolute; width: 40px; height: 40px; background: var(--gradient-accent); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-size: var(--font-size-base); animation: floatIcon 4s ease-in-out infinite; } .floating-icon.icon-1 { top: 10%; right: 10%; animation-delay: 0.5s; } .floating-icon.icon-2 { bottom: 30%; right: 5%; animation-delay: 1.5s; } .floating-icon.icon-3 { top: 50%; left: 5%; animation-delay: 2.5s; } @keyframes floatIcon { 0%, 100% { transform: translateY(0) rotate(0deg) scale(1); } 25% { transform: translateY(-10px) rotate(90deg) scale(1.1); } 50% { transform: translateY(5px) rotate(180deg) scale(0.9); } 75% { transform: translateY(-5px) rotate(270deg) scale(1.1); } } @keyframes slideInLeft { from { opacity: 0; transform: translateX(-50px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideInRight { from { opacity: 0; transform: translateX(50px); } to { opacity: 1; transform: translateX(0); } } /* Button styles */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-8); padding: var(--space-12) var(--space-24); border-radius: var(--radius-base); font-size: var(--font-size-base); font-weight: 600; font-family: var(--font-primary); cursor: pointer; transition: all var(--animation-normal) var(--ease-smooth); border: none; text-decoration: none; position: relative; overflow: hidden; user-select: none; min-height: 44px; } .btn--animated { position: relative; overflow: hidden; } .btn-ripple { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.3); transform: scale(0); animation: ripple 0.6s linear; pointer-events: none; } @keyframes ripple { to { transform: scale(4); opacity: 0; } } .btn--primary { background: var(--gradient-secondary); color: white; border: none; box-shadow: var(--shadow-soft); } .btn--primary:hover { transform: translateY(-3px); box-shadow: var(--shadow-medium); } .btn--primary:active { transform: translateY(-1px); } .btn--outline { background: var(--glass-bg); border: 1px solid var(--glass-border); color: var(--color-text); backdrop-filter: var(--glass-blur); } .btn--outline:hover { background: var(--glass-border); border-color: var(--accent-cyan); color: var(--accent-cyan); transform: translateY(-2px); } .btn--lg { padding: var(--space-16) var(--space-32); font-size: var(--font-size-lg); border-radius: var(--radius-lg); min-height: 56px; } .btn--sm { padding: var(--space-8) var(--space-16); font-size: var(--font-size-sm); min-height: 36px; } .btn--full-width { width: 100%; } .cta-button { background: var(--gradient-primary); transform: translateY(0); box-shadow: var(--shadow-medium); } .cta-button:hover { transform: translateY(-4px); box-shadow: var(--shadow-strong); } /* Features section */ .features-section { padding: var(--space-32) 0; margin-top: var(--space-32); } .section-header { text-align: center; margin-bottom: var(--space-32); } .section-title { font-size: var(--font-size-4xl); font-weight: 800; margin-bottom: var(--space-16); background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .section-description { font-size: var(--font-size-lg); color: var(--color-text-secondary); max-width: 600px; margin: 0 auto; } .features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--space-24); margin-top: var(--space-32); } .feature-card { position: relative; background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); border-radius: var(--radius-lg); padding: var(--space-32); text-align: center; transition: all var(--animation-normal) var(--ease-smooth); overflow: hidden; } .feature-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--gradient-secondary); transform: scaleX(0); transition: transform var(--animation-normal) var(--ease-smooth); } .feature-card:hover::before { transform: scaleX(1); } .feature-card:hover { transform: translateY(-8px); box-shadow: var(--shadow-medium); border-color: var(--accent-cyan); } .feature-icon { width: 80px; height: 80px; margin: 0 auto var(--space-20); background: var(--gradient-accent); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: var(--font-size-2xl); color: white; position: relative; overflow: hidden; } .feature-icon::after { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.3); transform: translate(-50%, -50%); transition: all var(--animation-normal) var(--ease-smooth); } .feature-card:hover .feature-icon::after { width: 100%; height: 100%; } .feature-title { font-size: var(--font-size-xl); font-weight: 700; margin-bottom: var(--space-12); color: var(--color-text); } .feature-description { color: var(--color-text-secondary); line-height: 1.6; margin: 0; } .feature-glow { position: absolute; top: 50%; left: 50%; width: 200px; height: 200px; background: radial-gradient(circle, rgba(102, 126, 234, 0.1) 0%, transparent 70%); border-radius: 50%; transform: translate(-50%, -50%); opacity: 0; transition: opacity var(--animation-normal) var(--ease-smooth); pointer-events: none; } .feature-card:hover .feature-glow { opacity: 1; } /* Testimonials */ .testimonials-section { padding: var(--space-32) 0; text-align: center; } .testimonials-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: var(--space-24); margin-top: var(--space-32); } .testimonial-card { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); border-radius: var(--radius-lg); padding: var(--space-32); transition: all var(--animation-normal) var(--ease-smooth); } .testimonial-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-medium); } .testimonial-content p { font-size: var(--font-size-lg); font-style: italic; color: var(--color-text); margin-bottom: var(--space-24); } .testimonial-author { display: flex; align-items: center; gap: var(--space-16); margin-bottom: var(--space-16); } .author-avatar { width: 50px; height: 50px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-size: var(--font-size-lg); } .author-info { text-align: left; } .author-name { display: block; font-weight: 600; color: var(--color-text); } .author-role { display: block; font-size: var(--font-size-sm); color: var(--color-text-secondary); } .testimonial-rating { color: var(--accent-gold); } /* Glass card styles */ .glass-card { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-soft); } /* Room setup */ .room-setup { max-width: 600px; margin: 0 auto; padding: var(--space-32) 0; } .setup-content { padding: var(--space-32); animation: slideInUp var(--animation-slow) var(--ease-bounce); } @keyframes slideInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } .setup-header { text-align: center; margin-bottom: var(--space-32); } .setup-icon { width: 80px; height: 80px; margin: 0 auto var(--space-20); background: var(--gradient-secondary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: var(--font-size-2xl); color: white; animation: bounce 2s ease-in-out infinite; } @keyframes bounce { 0%, 20%, 50%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-10px); } 60% { transform: translateY(-5px); } } .setup-header h2 { font-size: var(--font-size-3xl); font-weight: 700; margin-bottom: var(--space-12); color: var(--color-text); } .setup-header p { color: var(--color-text-secondary); font-size: var(--font-size-lg); } /* Form styles */ .form-group { margin-bottom: var(--space-24); } .form-label { display: flex; align-items: center; gap: var(--space-8); margin-bottom: var(--space-8); font-weight: 600; color: var(--color-text); font-size: var(--font-size-sm); } .form-control { width: 100%; padding: var(--space-16); border: 1px solid var(--glass-border); border-radius: var(--radius-base); font-size: var(--font-size-base); font-family: var(--font-primary); background: var(--glass-bg); backdrop-filter: var(--glass-blur); color: var(--color-text); transition: all var(--animation-fast) var(--ease-smooth); } .form-control:focus { outline: none; border-color: var(--accent-cyan); box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.1); background: var(--glass-border); } .form-control::placeholder { color: var(--color-text-secondary); } .input-group { display: flex; gap: var(--space-12); } .input-group .form-control { flex: 1; } /* Device preview */ .device-preview { margin: var(--space-32) 0; } .device-preview h3 { display: flex; align-items: center; gap: var(--space-8); margin-bottom: var(--space-20); text-align: center; justify-content: center; font-size: var(--font-size-lg); color: var(--color-text); } .preview-container { position: relative; width: 100%; height: 240px; background: linear-gradient(135deg, var(--dark-bg-primary), var(--dark-bg-secondary)); border-radius: var(--radius-lg); overflow: hidden; border: 2px solid var(--glass-border); box-shadow: var(--shadow-soft); } .preview-container video { width: 100%; height: 100%; object-fit: cover; } .preview-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.8); display: flex; flex-direction: column; align-items: center; justify-content: center; color: white; backdrop-filter: blur(10px); } .preview-overlay i { font-size: var(--font-size-4xl); margin-bottom: var(--space-16); opacity: 0.6; } .preview-overlay p { font-size: var(--font-size-lg); margin: 0; opacity: 0.8; } .preview-effects { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .effect-dot { position: absolute; width: 8px; height: 8px; background: var(--accent-cyan); border-radius: 50%; animation: pulse 2s ease-in-out infinite; } .effect-dot.dot-1 { top: 20%; left: 20%; animation-delay: 0s; } .effect-dot.dot-2 { top: 60%; right: 30%; animation-delay: 0.7s; } .effect-dot.dot-3 { bottom: 30%; left: 60%; animation-delay: 1.4s; } .preview-controls { display: flex; gap: var(--space-16); justify-content: center; margin-top: var(--space-20); } .preview-control { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); border-radius: var(--radius-base); padding: var(--space-12) var(--space-20); display: flex; align-items: center; gap: var(--space-8); color: var(--color-text); font-family: var(--font-primary); font-weight: 500; cursor: pointer; transition: all var(--animation-normal) var(--ease-smooth); } .preview-control:hover { background: var(--glass-border); border-color: var(--accent-cyan); color: var(--accent-cyan); transform: translateY(-2px); } .preview-control.muted { background: var(--accent-coral); border-color: var(--accent-coral); color: white; } /* Call interface */ .call-page { padding: 0; } .call-interface { height: 100vh; display: flex; flex-direction: column; background: var(--dark-bg-primary); color: var(--dark-text-primary); } .glass-header { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border-bottom: 1px solid var(--glass-border); } .call-header { padding: var(--space-20) var(--space-24); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; } .room-info h3 { margin: 0 0 var(--space-8) 0; font-size: var(--font-size-xl); color: var(--dark-text-primary); } .call-status { display: flex; align-items: center; gap: var(--space-12); font-size: var(--font-size-sm); color: var(--dark-text-secondary); } .timer { font-family: var(--font-family-mono); font-weight: 600; color: var(--accent-cyan); } .participant-count { color: var(--accent-mint); } .status { display: flex; align-items: center; gap: var(--space-4); font-weight: 500; } .status--success { color: var(--accent-mint); } .status i { animation: pulse 2s ease-in-out infinite; } .separator { color: var(--dark-text-secondary); opacity: 0.5; } .call-actions-top { display: flex; gap: var(--space-12); } /* Video container */ .video-container { flex: 1; position: relative; background: var(--dark-bg-secondary); overflow: hidden; } .video-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--space-16); padding: var(--space-20); height: 100%; align-content: center; } .video-tile { position: relative; background: var(--dark-bg-primary); border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 16/9; min-height: 200px; transition: all var(--animation-normal) var(--ease-smooth); } .glass-video { border: 1px solid var(--glass-border); box-shadow: var(--shadow-soft); } .video-tile:hover { transform: scale(1.02); box-shadow: var(--shadow-medium); } .video-tile video { width: 100%; height: 100%; object-fit: cover; } .video-overlay { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(transparent, rgba(0, 0, 0, 0.8)); padding: var(--space-16); display: flex; align-items: center; justify-content: space-between; backdrop-filter: blur(10px); } .video-overlay .participant-name { color: white; font-weight: 600; font-size: var(--font-size-sm); display: flex; align-items: center; gap: var(--space-8); } .video-controls-mini { display: flex; gap: var(--space-8); } .mute-indicator { background: var(--accent-coral); color: white; padding: var(--space-6); border-radius: var(--radius-sm); font-size: var(--font-size-xs); } .video-effects { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .pulse-ring { position: absolute; top: 50%; left: 50%; width: 100px; height: 100px; border: 2px solid var(--accent-cyan); border-radius: 50%; transform: translate(-50%, -50%); opacity: 0; animation: pulseRing 3s ease-in-out infinite; } @keyframes pulseRing { 0% { transform: translate(-50%, -50%) scale(0.5); opacity: 1; } 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.3; } 100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; } } /* Call controls */ .glass-controls { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border-top: 1px solid var(--glass-border); } .call-controls { padding: var(--space-24); flex-shrink: 0; } .controls-group { display: flex; align-items: center; justify-content: center; gap: var(--space-20); } .control-btn { width: 60px; height: 60px; border-radius: 50%; border: none; background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); color: var(--dark-text-primary); font-size: var(--font-size-lg); cursor: pointer; transition: all var(--animation-normal) var(--ease-smooth); display: flex; align-items: center; justify-content: center; position: relative; overflow: hidden; } .animated-btn { position: relative; overflow: hidden; } .control-btn:hover { background: var(--glass-border); transform: scale(1.1); box-shadow: var(--shadow-soft); } .control-btn.active { background: var(--accent-cyan); color: white; border-color: var(--accent-cyan); } .control-btn.muted { background: var(--accent-coral); color: white; border-color: var(--accent-coral); } .control-btn.end-call { background: var(--accent-coral); color: white; border-color: var(--accent-coral); } .control-btn.end-call:hover { background: #ff5252; transform: scale(1.1); } /* Reactions */ .reactions-container { position: fixed; top: 50%; left: 50%; width: 200px; height: 200px; transform: translate(-50%, -50%); pointer-events: none; z-index: 1000; } .reaction-emoji { position: absolute; font-size: var(--font-size-2xl); animation: floatReaction 3s ease-out forwards; pointer-events: none; } @keyframes floatReaction { 0% { transform: scale(0) rotate(0deg); opacity: 1; } 20% { transform: scale(1.5) rotate(180deg); opacity: 1; } 100% { transform: scale(0.5) rotate(360deg) translateY(-100px); opacity: 0; } } /* Chat panel */ .glass-panel { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border-left: 1px solid var(--glass-border); } .chat-panel { position: fixed; top: 0; right: -400px; width: 400px; height: 100vh; display: flex; flex-direction: column; transition: right var(--animation-normal) var(--ease-smooth); z-index: 1001; box-shadow: var(--shadow-strong); } .chat-panel.active { right: 0; } .chat-header { padding: var(--space-20); border-bottom: 1px solid var(--glass-border); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; } .chat-header h3 { margin: 0; color: var(--dark-text-primary); display: flex; align-items: center; gap: var(--space-8); } .chat-messages { flex: 1; padding: var(--space-20); overflow-y: auto; background: rgba(0, 0, 0, 0.2); } .system-message { text-align: center; color: var(--dark-text-secondary); font-size: var(--font-size-sm); margin-bottom: var(--space-20); display: flex; align-items: center; justify-content: center; gap: var(--space-8); background: var(--glass-bg); padding: var(--space-12); border-radius: var(--radius-base); backdrop-filter: var(--glass-blur); } .chat-message { margin-bottom: var(--space-16); padding: var(--space-12) var(--space-16); background: var(--glass-bg); border-radius: var(--radius-base); border-left: 3px solid var(--accent-cyan); backdrop-filter: var(--glass-blur); animation: slideInRight 0.3s var(--ease-smooth); } @keyframes slideInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } } .message-sender { font-weight: 600; font-size: var(--font-size-sm); color: var(--accent-cyan); margin-bottom: var(--space-4); } .message-content { margin: 0; color: var(--dark-text-primary); line-height: 1.5; } .message-time { font-size: var(--font-size-xs); color: var(--dark-text-secondary); margin-top: var(--space-8); } .chat-input { padding: var(--space-20); border-top: 1px solid var(--glass-border); display: flex; gap: var(--space-8); flex-shrink: 0; background: var(--glass-bg); } .chat-input input { flex: 1; background: rgba(0, 0, 0, 0.3); border: 1px solid var(--glass-border); color: var(--dark-text-primary); } .chat-input input::placeholder { color: var(--dark-text-secondary); } .emoji-btn { background: none; border: none; font-size: var(--font-size-lg); cursor: pointer; padding: var(--space-8); border-radius: var(--radius-base); transition: all var(--animation-fast) var(--ease-smooth); } .emoji-btn:hover { background: var(--glass-bg); transform: scale(1.1); } /* Modals */ .modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.8); display: flex; align-items: center; justify-content: center; z-index: 2000; padding: var(--space-20); backdrop-filter: blur(10px); animation: fadeIn var(--animation-normal) var(--ease-smooth); } .modal.hidden { display: none; } .modal-content { max-width: 600px; width: 100%; max-height: 80vh; overflow-y: auto; animation: scaleIn var(--animation-normal) var(--ease-bounce); } @keyframes scaleIn { from { transform: scale(0.9); opacity: 0; } to { transform: scale(1); opacity: 1; } } .modal-header { padding: var(--space-24); border-bottom: 1px solid var(--glass-border); display: flex; align-items: center; justify-content: space-between; } .modal-header h3 { margin: 0; color: var(--color-text); display: flex; align-items: center; gap: var(--space-8); } .modal-body { padding: var(--space-24); } /* Share modal */ .share-section { margin-bottom: var(--space-32); } .share-section h4 { margin-bottom: var(--space-16); color: var(--color-text); display: flex; align-items: center; gap: var(--space-8); } .share-link { display: flex; gap: var(--space-8); } .share-link input { flex: 1; } .qr-container { text-align: center; } .qr-code { background: white; padding: var(--space-16); border-radius: var(--radius-base); margin-bottom: var(--space-16); box-shadow: var(--shadow-soft); } .social-buttons { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: var(--space-12); } .social-btn { padding: var(--space-12) var(--space-16); border: none; border-radius: var(--radius-base); color: white; font-weight: 600; cursor: pointer; transition: all var(--animation-normal) var(--ease-smooth); display: flex; align-items: center; justify-content: center; gap: var(--space-8); font-family: var(--font-primary); } .social-btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-soft); } .social-btn.whatsapp { background: #25D366; } .social-btn.telegram { background: #0088cc; } .social-btn.twitter { background: #1DA1F2; } .social-btn.facebook { background: #4267B2; } .social-btn.linkedin { background: #0077b5; } /* Signaling modal */ .signaling-step { margin-bottom: var(--space-24); padding: var(--space-24); background: var(--glass-bg); border-radius: var(--radius-base); border: 1px solid var(--glass-border); backdrop-filter: var(--glass-blur); } .signaling-step h4 { margin: 0 0 var(--space-12) 0; color: var(--accent-cyan); display: flex; align-items: center; gap: var(--space-8); } .signaling-step p { margin-bottom: var(--space-16); color: var(--color-text-secondary); line-height: 1.6; } .signaling-step textarea { margin-bottom: var(--space-16); min-height: 80px; font-family: var(--font-family-mono); font-size: var(--font-size-sm); resize: vertical; } /* Loading overlay */ .loading-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.9); display: flex; align-items: center; justify-content: center; z-index: 3000; backdrop-filter: blur(10px); } .loading-overlay.hidden { display: none; } .loading-spinner { text-align: center; color: white; } .spinner-ring { display: inline-block; position: relative; width: 80px; height: 80px; margin-bottom: var(--space-24); } .spinner-ring div { box-sizing: border-box; display: block; position: absolute; width: 64px; height: 64px; margin: 8px; border: 8px solid var(--accent-cyan); border-radius: 50%; animation: spin 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; border-color: var(--accent-cyan) transparent transparent transparent; } .spinner-ring div:nth-child(1) { animation-delay: -0.45s; } .spinner-ring div:nth-child(2) { animation-delay: -0.3s; } .spinner-ring div:nth-child(3) { animation-delay: -0.15s; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading-text { margin: 0; font-size: var(--font-size-lg); font-weight: 500; color: var(--accent-cyan); } /* Toast notifications */ .toast-container { position: fixed; top: var(--space-20); right: var(--space-20); z-index: 4000; display: flex; flex-direction: column; gap: var(--space-8); } .toast { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); border-radius: var(--radius-base); padding: var(--space-16) var(--space-20); color: white; font-weight: 500; box-shadow: var(--shadow-medium); animation: slideInToast 0.3s var(--ease-bounce); max-width: 300px; position: relative; overflow: hidden; } .toast::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--gradient-secondary); } .toast.success::before { background: var(--accent-mint); } .toast.error::before { background: var(--accent-coral); } .toast.warning::before { background: var(--accent-gold); } @keyframes slideInToast { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } /* Achievement modal */ .achievement-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.8); display: flex; align-items: center; justify-content: center; z-index: 5000; backdrop-filter: blur(10px); animation: fadeIn var(--animation-normal) var(--ease-smooth); } .achievement-modal.hidden { display: none; } .achievement-content { background: var(--glass-bg); backdrop-filter: var(--glass-blur); border: 1px solid var(--glass-border); border-radius: var(--radius-lg); padding: var(--space-32); text-align: center; max-width: 400px; animation: bounceIn 0.6s var(--ease-bounce); position: relative; overflow: hidden; } .achievement-content::before { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: conic-gradient(var(--accent-gold), var(--accent-cyan), var(--accent-coral), var(--accent-mint), var(--accent-gold)); animation: rotate 3s linear infinite; z-index: -1; } .achievement-content::after { content: ''; position: absolute; top: 3px; left: 3px; right: 3px; bottom: 3px; background: var(--glass-bg); backdrop-filter: var(--glass-blur); border-radius: calc(var(--radius-lg) - 3px); z-index: -1; } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes bounceIn { 0% { transform: scale(0); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .achievement-icon { width: 80px; height: 80px; margin: 0 auto var(--space-20); background: var(--gradient-accent); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: var(--font-size-2xl); color: white; animation: spin 1s ease-in-out; } .achievement-title { font-size: var(--font-size-xl); font-weight: 700; margin-bottom: var(--space-12); background: var(--gradient-accent); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .achievement-description { color: var(--color-text-secondary); margin-bottom: var(--space-24); } /* Responsive design */ @media (max-width: 1024px) { .hero { grid-template-columns: 1fr; text-align: center; gap: var(--space-24); } .features-grid { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); } .testimonials-grid { grid-template-columns: 1fr; } } @media (max-width: 768px) { .nav-toggle { display: block; } .nav-list { position: absolute; top: 100%; left: 0; right: 0; background: var(--glass-bg); backdrop-filter: var(--glass-blur); border-top: 1px solid var(--glass-border); flex-direction: column; padding: var(--space-20); gap: var(--space-8); display: none; box-shadow: var(--shadow-medium); } .nav-list.active { display: flex; } .theme-toggle { order: -1; } .hero-actions { flex-direction: column; align-items: center; } .hero-actions .btn { width: 100%; max-width: 300px; } .hero-stats { flex-direction: column; gap: var(--space-16); } .features-grid { grid-template-columns: 1fr; } .setup-content { margin: var(--space-16); padding: var(--space-24); } .input-group { flex-direction: column; } .call-header { flex-direction: column; gap: var(--space-16); text-align: center; } .call-actions-top { justify-content: center; } .video-grid { grid-template-columns: 1fr; gap: var(--space-12); padding: var(--space-12); } .controls-group { gap: var(--space-16); flex-wrap: wrap; justify-content: center; } .control-btn { width: 52px; height: 52px; } .chat-panel { width: 100%; right: -100%; } .modal-content { margin: var(--space-16); max-height: calc(100vh - 32px); } .social-buttons { grid-template-columns: 1fr; } } @media (max-width: 480px) { .container { padding: 0 var(--space-16); } .hero { padding: var(--space-20) 0; min-height: 60vh; } .hero-title { font-size: clamp(1.8rem, 8vw, 2.5rem); } .hero-actions .btn { width: 100%; } .feature-card { padding: var(--space-24); } .setup-content { padding: var(--space-20); } .preview-container { height: 180px; } .preview-controls { flex-direction: column; gap: var(--space-8); } .preview-control { justify-content: center; } .video-tile { min-height: 160px; } .controls-group { gap: var(--space-12); } .control-btn { width: 48px; height: 48px; font-size: var(--font-size-base); } .toast { margin: var(--space-8); max-width: calc(100% - var(--space-32)); } .achievement-content { margin: var(--space-16); padding: var(--space-24); } } /* Print styles */ @media print { .header, .call-controls, .chat-panel, .modal, .loading-overlay, .particles-container { display: none !important; } } /* Reduced motion */ @media (prefers-reduced-motion: reduce) { *, ::before, ::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } // Enhanced FreeCall Video Calling App - Fixed Navigation & Functionality class FreeCallApp { constructor() { this.localStream = null; this.remoteStreams = new Map(); this.peerConnections = new Map(); this.dataChannels = new Map(); this.currentPage = 'home'; this.roomId = ''; this.participantName = ''; this.isAudioEnabled = true; this.isVideoEnabled = true; this.isScreenSharing = false; this.isChatOpen = false; this.callStartTime = null; this.callTimer = null; this.participants = new Set(['You']); this.achievements = new Set(); this.isDarkTheme = false; // Social sharing platforms this.socialPlatforms = { whatsapp: { url: 'https://wa.me/?text=', color: '#25D366' }, telegram: { url: 'https://t.me/share/url?url=', color: '#0088cc' }, twitter: { url: 'https://twitter.com/intent/tweet?text=', color: '#1DA1F2' }, facebook: { url: 'https://www.facebook.com/sharer/sharer.php?u=', color: '#4267B2' }, linkedin: { url: 'https://www.linkedin.com/sharing/share-offsite/?url=', color: '#0077b5' } }; // Reaction emojis this.reactions = ['❤️', '😂', '😮', '👏', '👍', '👎', '😢', '😡']; console.log('🎥 FreeCall App initializing...'); this.init(); } init() { // Ensure DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.setupApp()); } else { this.setupApp(); } } setupApp() { console.log('📱 Setting up FreeCall application...'); // Generate initial room ID this.generateRoomId(); // Setup core functionality this.initParticles(); this.initTheme(); this.handleURLParams(); // Setup event listeners with explicit timing setTimeout(() => { this.setupAllEventListeners(); this.initScrollAnimations(); console.log('✅ FreeCall app ready!'); }, 100); } setupAllEventListeners() { console.log('🔧 Setting up all event listeners...'); // Theme toggle this.setupThemeToggle(); // Navigation - using more specific selectors this.setupNavigation(); // Action buttons this.setupActionButtons(); // Room functionality this.setupRoomControls(); // Call controls this.setupCallControls(); // Chat functionality this.setupChatControls(); // Modal controls this.setupModalControls(); // Sharing this.setupSharingControls(); // Utility events this.setupUtilityEvents(); console.log('✅ All event listeners configured'); } setupThemeToggle() { const themeToggle = document.getElementById('themeToggle'); if (themeToggle) { themeToggle.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); this.toggleTheme(); console.log('🌓 Theme toggled'); }); console.log('✓ Theme toggle configured'); } else { console.warn('⚠️ Theme toggle button not found'); } } setupNavigation() { // Nav toggle for mobile const navToggle = document.getElementById('navToggle'); if (navToggle) { navToggle.addEventListener('click', (e) => { e.preventDefault(); this.toggleMobileNav(); }); } // Navigation links with explicit selection const navLinks = document.querySelectorAll('a[data-page]'); console.log(`📍 Found ${navLinks.length} navigation links`); navLinks.forEach((link, index) => { const pageId = link.getAttribute('data-page'); console.log(`📌 Setting up nav link ${index}: ${pageId}`); link.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); console.log(`🔀 Navigation clicked: ${pageId}`); this.navigateToPage(pageId); }); }); } setupActionButtons() { // Main CTA buttons const ctaButtons = document.querySelectorAll('.cta-button, button[data-page]'); console.log(`🎯 Found ${ctaButtons.length} action buttons`); ctaButtons.forEach((button, index) => { const pageId = button.getAttribute('data-page'); console.log(`🎯 Setting up action button ${index}: ${pageId}`); button.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); console.log(`🚀 Action button clicked: ${pageId}`); this.navigateToPage(pageId); }); }); } setupRoomControls() { // Generate room ID const generateBtn = document.getElementById('generateRoomBtn'); if (generateBtn) { generateBtn.addEventListener('click', (e) => { e.preventDefault(); this.generateRoomId(); this.showToast('New room ID generated!', 'success'); }); } // Create room const createBtn = document.getElementById('createRoomBtn'); if (createBtn) { createBtn.addEventListener('click', (e) => { e.preventDefault(); this.createRoom(); }); } // Join room const joinBtn = document.getElementById('joinRoomBtn'); if (joinBtn) { joinBtn.addEventListener('click', (e) => { e.preventDefault(); this.joinRoom(); }); } // Preview controls this.setupPreviewControls(); } setupCallControls() { const controlButtons = [ { id: 'muteBtn', action: () => this.toggleMute() }, { id: 'cameraBtn', action: () => this.toggleCamera() }, { id: 'screenShareBtn', action: () => this.toggleScreenShare() }, { id: 'chatBtn', action: () => this.toggleChat() }, { id: 'reactionsBtn', action: () => this.showReactions() }, { id: 'endCallBtn', action: () => this.endCall() }, { id: 'copyLinkBtn', action: () => this.copyRoomLink() }, { id: 'showSignalingBtn', action: () => this.showSignaling() } ]; controlButtons.forEach(({ id, action }) => { const element = document.getElementById(id); if (element) { element.addEventListener('click', (e) => { e.preventDefault(); action(); }); } }); } setupChatControls() { const chatInput = document.getElementById('chatInput'); if (chatInput) { chatInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { this.sendMessage(); } }); } const sendBtn = document.getElementById('sendMessageBtn'); if (sendBtn) { sendBtn.addEventListener('click', (e) => { e.preventDefault(); this.sendMessage(); }); } const closeChatBtn = document.getElementById('closeChatBtn'); if (closeChatBtn) { closeChatBtn.addEventListener('click', (e) => { e.preventDefault(); this.toggleChat(); }); } } setupModalControls() { // Share modal const shareBtn = document.getElementById('shareBtn'); if (shareBtn) { shareBtn.addEventListener('click', (e) => { e.preventDefault(); this.showShareModal(); }); } const closeShareBtn = document.getElementById('closeShareBtn'); if (closeShareBtn) { closeShareBtn.addEventListener('click', (e) => { e.preventDefault(); this.closeShareModal(); }); } // Signaling modal const signalingButtons = [ { id: 'closeSignalingBtn', action: () => this.closeSignaling() }, { id: 'copyOfferBtn', action: () => this.copyOffer() }, { id: 'processAnswerBtn', action: () => this.processAnswer() }, { id: 'processOfferBtn', action: () => this.processOffer() }, { id: 'copyAnswerBtn', action: () => this.copyAnswer() } ]; signalingButtons.forEach(({ id, action }) => { const element = document.getElementById(id); if (element) { element.addEventListener('click', (e) => { e.preventDefault(); action(); }); } }); } setupSharingControls() { // Social sharing buttons document.addEventListener('click', (e) => { if (e.target.closest('.social-btn')) { e.preventDefault(); const btn = e.target.closest('.social-btn'); const platform = btn.getAttribute('data-platform'); if (platform) { this.shareOnSocial(platform); } } }); } setupUtilityEvents() { // Ripple effects document.addEventListener('click', (e) => { if (e.target.closest('.btn--animated')) { const btn = e.target.closest('.btn--animated'); this.createRipple(e, btn); } }); // Modal close on outside click document.addEventListener('click', (e) => { if (e.target.classList.contains('modal')) { e.target.classList.add('hidden'); } }); // Window resize window.addEventListener('resize', () => { this.initParticles(); }); } navigateToPage(pageId) { if (!pageId) return; console.log(`📄 Navigating to: ${pageId}`); // Hide all pages const allPages = document.querySelectorAll('.page'); allPages.forEach(page => { page.classList.remove('active'); }); // Show target page const targetPage = document.getElementById(pageId); if (targetPage) { targetPage.classList.add('active'); console.log(`✅ Showing page: ${pageId}`); } else { console.error(`❌ Page not found: ${pageId}`); return; } // Update navigation state document.querySelectorAll('.nav-link').forEach(link => { link.classList.remove('active'); if (link.getAttribute('data-page') === pageId) { link.classList.add('active'); } }); // Close mobile nav const navList = document.getElementById('navList'); if (navList) { navList.classList.remove('active'); } this.currentPage = pageId; // Page-specific setup if (pageId === 'create' && !this.roomId) { this.generateRoomId(); } // Update title this.updatePageTitle(pageId); // Show success message this.showToast(`Navigated to ${pageId} page`, 'info'); } updatePageTitle(pageId) { const titles = { home: 'FreeCall - Beautiful Video Calling Without Limits', create: 'Create Room - FreeCall', join: 'Join Meeting - FreeCall', call: `Video Call - Room ${this.roomId} - FreeCall` }; document.title = titles[pageId] || titles.home; } toggleTheme() { this.isDarkTheme = !this.isDarkTheme; document.body.classList.toggle('dark-theme', this.isDarkTheme); const themeIcon = document.querySelector('#themeToggle i'); if (themeIcon) { themeIcon.className = this.isDarkTheme ? 'fas fa-sun' : 'fas fa-moon'; } localStorage.setItem('freecall-theme', this.isDarkTheme ? 'dark' : 'light'); this.updateParticles(); this.showToast(`Switched to ${this.isDarkTheme ? 'dark' : 'light'} theme`, 'success'); } initTheme() { const savedTheme = localStorage.getItem('freecall-theme'); if (savedTheme === 'dark' || (!savedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches)) { this.isDarkTheme = true; document.body.classList.add('dark-theme'); const themeIcon = document.querySelector('#themeToggle i'); if (themeIcon) { themeIcon.className = 'fas fa-sun'; } } } toggleMobileNav() { const navList = document.getElementById('navList'); if (navList) { navList.classList.toggle('active'); } } generateRoomId() { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let result = ''; for (let i = 0; i < 8; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } this.roomId = result; const roomIdInput = document.getElementById('roomId'); if (roomIdInput) { roomIdInput.value = result; } console.log('🆔 Generated room ID:', result); return result; } setupPreviewControls() { const previewControls = [ { id: 'togglePreviewCamera', type: 'video' }, { id: 'togglePreviewMic', type: 'audio' }, { id: 'toggleJoinPreviewCamera', type: 'video' }, { id: 'toggleJoinPreviewMic', type: 'audio' } ]; previewControls.forEach(control => { const element = document.getElementById(control.id); if (element) { element.addEventListener('click', (e) => { e.preventDefault(); this.togglePreviewDevice(control.type, control.id); }); } }); } async togglePreviewDevice(deviceType, buttonId) { const button = document.getElementById(buttonId); if (!button) return; if (deviceType === 'video') { this.isVideoEnabled = !this.isVideoEnabled; } else { this.isAudioEnabled = !this.isAudioEnabled; } this.updatePreviewButton(button, deviceType === 'video' ? this.isVideoEnabled : this.isAudioEnabled, deviceType); this.showToast(`${deviceType === 'video' ? 'Camera' : 'Microphone'} ${deviceType === 'video' ? this.isVideoEnabled : this.isAudioEnabled ? 'on' : 'off'}`, 'info'); } updatePreviewButton(button, isEnabled, type) { const icons = { video: { on: 'fas fa-video', off: 'fas fa-video-slash' }, audio: { on: 'fas fa-microphone', off: 'fas fa-microphone-slash' } }; const icon = isEnabled ? icons[type].on : icons[type].off; const text = type === 'video' ? 'Camera' : 'Microphone'; button.innerHTML = `${text}`; button.classList.toggle('muted', !isEnabled); } async createRoom() { console.log('🚀 Creating room...'); this.showLoading(true, 'Creating your beautiful video room...'); const roomNameInput = document.getElementById('roomName'); const roomIdInput = document.getElementById('roomId'); const roomName = roomNameInput ? roomNameInput.value.trim() : ''; const roomId = roomIdInput ? roomIdInput.value.trim() : this.roomId; if (!roomId) { this.showToast('Please generate a room ID', 'error'); this.showLoading(false); return; } this.roomId = roomId; // Simulate room creation await new Promise(resolve => setTimeout(resolve, 1500)); this.setupCallInterface(roomName, roomId); this.showLoading(false); this.navigateToPage('call'); this.unlockAchievement('first_call', 'First Call', 'Made your first video call!'); this.showToast('Room created successfully!', 'success'); } async joinRoom() { console.log('🚪 Joining room...'); this.showLoading(true, 'Joining the video call...'); const joinRoomIdInput = document.getElementById('joinRoomId'); const participantNameInput = document.getElementById('participantName'); const roomId = joinRoomIdInput ? joinRoomIdInput.value.trim() : ''; const participantName = participantNameInput ? participantNameInput.value.trim() : ''; if (!roomId) { this.showToast('Please enter a room ID', 'error'); this.showLoading(false); return; } this.roomId = roomId; this.participantName = participantName || 'Guest'; // Simulate joining await new Promise(resolve => setTimeout(resolve, 2000)); this.setupCallInterface('', roomId); this.showLoading(false); this.navigateToPage('call'); this.showToast(`Joined room ${roomId}!`, 'success'); } setupCallInterface(roomName, roomId) { const callRoomId = document.getElementById('callRoomId'); const callRoomName = document.getElementById('callRoomName'); if (callRoomId) callRoomId.textContent = roomId; if (callRoomName) { callRoomName.innerHTML = roomName ? `${roomName} (${roomId})` : `Room: ${roomId}`; } this.startCallTimer(); this.updateParticipantCount(); } toggleMute() { this.isAudioEnabled = !this.isAudioEnabled; this.updateControlButton('muteBtn', this.isAudioEnabled, 'microphone'); this.showToast(this.isAudioEnabled ? 'Microphone on' : 'Microphone off', 'info'); } toggleCamera() { this.isVideoEnabled = !this.isVideoEnabled; this.updateControlButton('cameraBtn', this.isVideoEnabled, 'video'); this.showToast(this.isVideoEnabled ? 'Camera on' : 'Camera off', 'info'); } updateControlButton(buttonId, isEnabled, type) { const button = document.getElementById(buttonId); if (!button) return; const icons = { microphone: { on: 'fas fa-microphone', off: 'fas fa-microphone-slash' }, video: { on: 'fas fa-video', off: 'fas fa-video-slash' } }; const icon = isEnabled ? icons[type].on : icons[type].off; button.innerHTML = ``; button.classList.toggle('muted', !isEnabled); } toggleScreenShare() { this.isScreenSharing = !this.isScreenSharing; const shareBtn = document.getElementById('screenShareBtn'); if (shareBtn) { shareBtn.classList.toggle('active', this.isScreenSharing); } this.showToast(this.isScreenSharing ? 'Screen sharing started' : 'Screen sharing stopped', 'info'); } toggleChat() { const chatPanel = document.getElementById('chatPanel'); const chatBtn = document.getElementById('chatBtn'); if (!chatPanel || !chatBtn) return; this.isChatOpen = !this.isChatOpen; chatPanel.classList.toggle('active', this.isChatOpen); chatBtn.classList.toggle('active', this.isChatOpen); this.showToast(this.isChatOpen ? 'Chat opened' : 'Chat closed', 'info'); } sendMessage() { const input = document.getElementById('chatInput'); if (!input) return; const message = input.value.trim(); if (!message) return; const messageData = { sender: 'You', content: message, timestamp: new Date().toLocaleTimeString() }; this.displayChatMessage(messageData); input.value = ''; this.showToast('Message sent', 'success'); } displayChatMessage(messageData) { const messagesContainer = document.getElementById('chatMessages'); if (!messagesContainer) return; const messageElement = document.createElement('div'); messageElement.className = 'chat-message'; messageElement.innerHTML = `
${messageData.sender}

${this.escapeHtml(messageData.content)}

${messageData.timestamp}
`; messagesContainer.appendChild(messageElement); messagesContainer.scrollTop = messagesContainer.scrollHeight; } escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } showReactions() { const container = document.getElementById('reactionsContainer'); if (!container) return; const emoji = this.reactions[Math.floor(Math.random() * this.reactions.length)]; const reactionElement = document.createElement('div'); reactionElement.className = 'reaction-emoji'; reactionElement.textContent = emoji; const x = Math.random() * 160 - 80; const y = Math.random() * 160 - 80; reactionElement.style.left = `${100 + x}px`; reactionElement.style.top = `${100 + y}px`; container.appendChild(reactionElement); setTimeout(() => { if (reactionElement.parentNode) { reactionElement.remove(); } }, 3000); this.showToast(`Sent ${emoji} reaction`, 'success'); } showShareModal() { const modal = document.getElementById('shareModal'); if (!modal) return; const roomLink = `${window.location.origin}${window.location.pathname}?room=${this.roomId}`; const shareLink = document.getElementById('shareLink'); if (shareLink) { shareLink.value = roomLink; } modal.classList.remove('hidden'); this.showToast('Share modal opened', 'info'); } closeShareModal() { const modal = document.getElementById('shareModal'); if (modal) { modal.classList.add('hidden'); } } async copyRoomLink() { const roomLink = `${window.location.origin}${window.location.pathname}?room=${this.roomId}`; try { await navigator.clipboard.writeText(roomLink); this.showToast('Room link copied to clipboard!', 'success'); } catch (error) { this.showToast(`Room ID: ${this.roomId}`, 'info'); } } shareOnSocial(platform) { const roomLink = `${window.location.origin}${window.location.pathname}?room=${this.roomId}`; const text = `Join my video call on FreeCall! Room: ${this.roomId}`; const platformData = this.socialPlatforms[platform]; if (!platformData) return; let shareUrl = ''; switch (platform) { case 'whatsapp': shareUrl = `${platformData.url}${encodeURIComponent(text + ' ' + roomLink)}`; break; case 'telegram': shareUrl = `${platformData.url}${encodeURIComponent(roomLink)}&text=${encodeURIComponent(text)}`; break; case 'twitter': shareUrl = `${platformData.url}${encodeURIComponent(text + ' ' + roomLink)}`; break; case 'facebook': shareUrl = `${platformData.url}${encodeURIComponent(roomLink)}`; break; case 'linkedin': shareUrl = `${platformData.url}${encodeURIComponent(roomLink)}`; break; } if (shareUrl) { window.open(shareUrl, '_blank', 'width=600,height=400'); this.unlockAchievement('social_sharer', 'Social Butterfly', 'Shared FreeCall with friends!'); this.showToast(`Sharing on ${platform}`, 'success'); } } showSignaling() { const modal = document.getElementById('signalingModal'); if (modal) { modal.classList.remove('hidden'); } const localOfferTextarea = document.getElementById('localOffer'); if (localOfferTextarea) { localOfferTextarea.value = JSON.stringify({ type: 'offer', sdp: 'Sample SDP offer for WebRTC connection...' }); } this.showToast('Connection offer generated', 'success'); } closeSignaling() { const modal = document.getElementById('signalingModal'); if (modal) { modal.classList.add('hidden'); } } async copyOffer() { const textarea = document.getElementById('localOffer'); if (!textarea) return; try { await navigator.clipboard.writeText(textarea.value); this.showToast('Offer copied to clipboard', 'success'); } catch (error) { textarea.select(); document.execCommand('copy'); this.showToast('Offer copied to clipboard', 'success'); } } processAnswer() { this.showToast('Connection established!', 'success'); this.closeSignaling(); } processOffer() { const answerStep = document.getElementById('answerStep'); if (answerStep) { answerStep.style.display = 'block'; } this.showToast('Answer generated successfully', 'success'); } async copyAnswer() { const textarea = document.getElementById('generatedAnswer'); if (!textarea) return; try { await navigator.clipboard.writeText(textarea.value); this.showToast('Answer copied to clipboard', 'success'); } catch (error) { this.showToast('Answer copied', 'success'); } } startCallTimer() { this.callStartTime = Date.now(); this.callTimer = setInterval(() => { const elapsed = Date.now() - this.callStartTime; const hours = Math.floor(elapsed / 3600000); const minutes = Math.floor((elapsed % 3600000) / 60000); const seconds = Math.floor((elapsed % 60000) / 1000); const timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; const timerElement = document.getElementById('callTimer'); if (timerElement) { timerElement.textContent = timeString; } }, 1000); } stopCallTimer() { if (this.callTimer) { clearInterval(this.callTimer); this.callTimer = null; } } updateParticipantCount() { const count = this.participants.size; const text = count === 1 ? '1 participant' : `${count} participants`; const countElement = document.getElementById('participantCount'); if (countElement) { countElement.textContent = text; } } endCall() { if (confirm('Are you sure you want to end the call?')) { this.stopCallTimer(); this.navigateToPage('home'); this.showToast('Call ended', 'info'); } } unlockAchievement(id, title, description) { if (this.achievements.has(id)) return; this.achievements.add(id); const modal = document.getElementById('achievementModal'); const descriptionElement = document.getElementById('achievementDescription'); if (modal && descriptionElement) { descriptionElement.textContent = description; modal.classList.remove('hidden'); } } initParticles() { const container = document.getElementById('particlesContainer'); if (!container) return; container.innerHTML = ''; const colors = ['#00D4FF', '#4ECDC4', '#FF6B6B', '#FFD93D', '#A8E6CF']; const particleCount = window.innerWidth < 768 ? 20 : 50; for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.className = 'particle'; const size = Math.random() * 4 + 2; const color = colors[Math.floor(Math.random() * colors.length)]; const left = Math.random() * 100; const animationDuration = Math.random() * 10 + 10; const delay = Math.random() * 5; particle.style.cssText = ` width: ${size}px; height: ${size}px; background: ${color}; left: ${left}%; top: ${Math.random() * 100}%; animation-duration: ${animationDuration}s; animation-delay: ${delay}s; opacity: ${this.isDarkTheme ? 0.8 : 0.4}; `; container.appendChild(particle); } } updateParticles() { const particles = document.querySelectorAll('.particle'); particles.forEach(particle => { const currentOpacity = parseFloat(particle.style.opacity); particle.style.opacity = this.isDarkTheme ? Math.min(currentOpacity * 2, 0.8) : Math.max(currentOpacity / 2, 0.4); }); } initScrollAnimations() { const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; } }); }, observerOptions); document.querySelectorAll('.feature-card, .testimonial-card').forEach(card => { card.style.opacity = '0'; card.style.transform = 'translateY(30px)'; card.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; observer.observe(card); }); } handleURLParams() { const urlParams = new URLSearchParams(window.location.search); const roomParam = urlParams.get('room'); if (roomParam) { const joinRoomIdInput = document.getElementById('joinRoomId'); if (joinRoomIdInput) { joinRoomIdInput.value = roomParam; } setTimeout(() => this.navigateToPage('join'), 500); } } createRipple(event, button) { if (!button) return; const existingRipple = button.querySelector('.btn-ripple'); if (existingRipple) { existingRipple.remove(); } const ripple = document.createElement('span'); ripple.className = 'btn-ripple'; const rect = button.getBoundingClientRect(); const size = Math.max(rect.width, rect.height); const x = event.clientX - rect.left - size / 2; const y = event.clientY - rect.top - size / 2; ripple.style.cssText = ` width: ${size}px; height: ${size}px; left: ${x}px; top: ${y}px; `; button.appendChild(ripple); setTimeout(() => { if (ripple.parentNode) { ripple.remove(); } }, 600); } showLoading(show, message = 'Setting up your beautiful video call...') { const overlay = document.getElementById('loadingOverlay'); const textElement = overlay?.querySelector('.loading-text'); if (overlay) { if (show) { if (textElement) textElement.textContent = message; overlay.classList.remove('hidden'); } else { overlay.classList.add('hidden'); } } } showToast(message, type = 'info') { console.log(`🔔 Toast (${type}): ${message}`); const container = document.getElementById('toastContainer'); if (!container) return; const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.textContent = message; container.appendChild(toast); setTimeout(() => { if (toast.parentNode) { toast.style.transform = 'translateX(100%)'; setTimeout(() => { if (toast.parentNode) { toast.remove(); } }, 300); } }, 3000); } } // Initialize app console.log('🎬 FreeCall - Beautiful Video Calling App Loading...'); // Ensure proper initialization if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { console.log('📱 DOM ready, initializing FreeCall...'); window.freeCallApp = new FreeCallApp(); }); } else { console.log('📱 DOM already ready, initializing FreeCall...'); window.freeCallApp = new FreeCallApp(); } // Console styling setTimeout(() => { console.log('%c🚀 Welcome to FreeCall! 🚀', 'color: #00D4FF; font-size: 20px; font-weight: bold;'); console.log('%cBuilt with ❤️ for beautiful video calling', 'color: #4ECDC4; font-size: 14px;'); }, 500);

Post a Comment

0 Comments