Tul xxx Tul
User / IP
:
216.73.216.227
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
Viewing: index.php
<?php require_once __DIR__ . '/config/config.php'; require_once __DIR__ . '/app/core/Database.php'; require_once __DIR__ . '/app/core/Model.php'; require_once __DIR__ . '/app/models/Ajuste.php'; require_once __DIR__ . '/app/models/Empleado.php'; require_once __DIR__ . '/app/models/MetodoPago.php'; function getFaviconMimeType(string $faviconUrl): string { $path = parse_url($faviconUrl, PHP_URL_PATH) ?? $faviconUrl; $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); return match ($ext) { 'png' => 'image/png', 'svg' => 'image/svg+xml', 'jpg', 'jpeg' => 'image/jpeg', 'gif' => 'image/gif', 'webp' => 'image/webp', default => 'image/x-icon', }; } function normalizeAssetUrl(string $path, string $fallback = ''): string { $path = trim($path); if ($path === '') { return $fallback; } if (preg_match('/^(https?:)?\/\//i', $path) || str_starts_with($path, 'data:')) { return $path; } return rtrim(BASE_URL, '/') . '/' . ltrim($path, '/'); } function resolveEmpleadoPhoto(?string $photo): string { $photo = trim((string)$photo); if ($photo === '') { return 'images/default-team.png'; } if (preg_match('/^(https?:)?\/\//i', $photo) || str_starts_with($photo, 'data:')) { return $photo; } if (str_contains($photo, '/')) { return normalizeAssetUrl($photo, 'images/default-team.png'); } return rtrim(BASE_URL, '/') . '/public/assets/uploads/empleados/' . rawurlencode($photo); } function normalizeSocialUrl(string $field, ?string $value): string { $value = trim((string)$value); if ($value === '') { return ''; } if ($field === 'whatsapp') { if (str_starts_with($value, 'http://') || str_starts_with($value, 'https://')) { return $value; } return 'https://wa.me/' . preg_replace('/[^0-9]/', '', $value); } if (in_array($field, ['facebook', 'instagram', 'linkedin', 'youtube', 'pagina_web', 'tiktok'], true)) { if (preg_match('/^(https?:)?\/\//i', $value)) { return $value; } return 'https://' . ltrim($value, '/'); } if ($field === 'twitter') { if (preg_match('/^(https?:)?\/\//i', $value)) { return $value; } return 'https://x.com/' . ltrim($value, '@/'); } if ($field === 'github') { if (preg_match('/^(https?:)?\/\//i', $value)) { return $value; } return 'https://github.com/' . ltrim($value, '@/'); } return $value; } function buildAbsoluteBaseUrl(): string { $siteUrl = defined('SITE_URL') ? trim((string) SITE_URL) : ''; $currentHost = $_SERVER['HTTP_HOST'] ?? ''; $siteHost = $siteUrl !== '' ? (parse_url($siteUrl, PHP_URL_HOST) ?? '') : ''; if ($siteUrl !== '' && $siteHost !== '' && $currentHost !== '' && strcasecmp($currentHost, $siteHost) === 0) { return rtrim($siteUrl, '/'); } $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (($_SERVER['SERVER_PORT'] ?? null) == 443); $scheme = $https ? 'https' : 'http'; $host = $_SERVER['HTTP_HOST'] ?? 'localhost'; return $scheme . '://' . $host . rtrim(BASE_URL, '/'); } function makeAbsoluteUrl(string $url, string $fallbackBase): string { $url = trim($url); if ($url === '') { return $fallbackBase; } if (preg_match('/^(https?:)?\/\//i', $url) || str_starts_with($url, 'data:')) { if (str_starts_with($url, '//')) { $scheme = parse_url($fallbackBase, PHP_URL_SCHEME) ?: 'https'; return $scheme . ':' . $url; } return $url; } return rtrim($fallbackBase, '/') . '/' . ltrim($url, '/'); } try { $db = Database::getConnection(); // Consultar Ajustes $ajustesMap = Ajuste::getMap(); // Cargar empleados del equipo desde la BD ordenados $stmtEquipo = $db->query("SELECT * FROM empleados ORDER BY orden ASC, id DESC"); $equipoCompleto = $stmtEquipo->fetchAll(); $logo = normalizeAssetUrl($ajustesMap['logo'] ?? 'images/aircan6.png', 'images/aircan6.png'); $favicon = normalizeAssetUrl($ajustesMap['favicon'] ?? 'images/ico.ico', 'images/ico.ico'); $pwaIcon = normalizeAssetUrl($ajustesMap['favicon'] ?? $ajustesMap['logo'] ?? 'public/assets/img/PNG.png', 'public/assets/img/PNG.png'); $heroImage = normalizeAssetUrl($ajustesMap['hero_image'] ?? '', ''); $heroVideo = normalizeAssetUrl($ajustesMap['hero_video'] ?? '', ''); // Forzamos solo uno: si hay imagen hero, ignoramos el video hero (evita ambos a la vez) if (!empty($heroImage)) { $heroVideo = ''; } // Fallback por defecto si no existe hero if (empty($heroImage) && empty($heroVideo)) { $heroImage = 'images/aircan_hero.jpg'; } $heroMockupVideo = normalizeAssetUrl($ajustesMap['hero_mockup_video'] ?? 'images/Mockup.mp4', 'images/Mockup.mp4'); $heroBgVideoDesktop = normalizeAssetUrl($ajustesMap['hero_bg_video_desktop'] ?? 'images/aircan.png', 'images/aircan.png'); $heroBgVideoMobile = normalizeAssetUrl($ajustesMap['hero_bg_video_mobile'] ?? 'images/portada.mp4', 'images/portada.mp4'); $siteTitle = $ajustesMap['site_title'] ?? 'Aircan'; // Consultar Servicios $stmtServicios = $db->query("SELECT id, nombre, descripcion, precio, imagen FROM servicios ORDER BY id DESC"); $servicios = $stmtServicios->fetchAll(); // Consultar Sistemas (Proyectos) $stmtSistemas = $db->query("SELECT id, nombre, descripcion, precio, imagen, link FROM sistemas ORDER BY id DESC"); $sistemas = $stmtSistemas->fetchAll(); // Consultar Logos de Clientes Satisfechos $stmtLogos = $db->query("SELECT nombre, logo FROM clientes_logos ORDER BY id DESC"); $clientesLogos = $stmtLogos->fetchAll(); // Consultar Métodos de Pago $metodoPagoModel = new MetodoPago(); $metodosPago = $metodoPagoModel->getAllActive(); } catch (Throwable $e) { $servicios = []; $sistemas = []; $clientesLogos = []; $logo = 'images/aircan6.png'; $favicon = 'images/ico.ico'; $pwaIcon = 'public/assets/img/PNG.png'; $heroVideo = 'images/aircan_video.mp4'; $heroImage = 'images/aircan_hero.jpg'; $heroMockupVideo = 'images/Mockup.mp4'; $heroBgVideoDesktop = 'images/aircan.png'; $heroBgVideoMobile = 'images/portada.mp4'; $siteTitle = 'Aircan'; $error = $e->getMessage(); } $absoluteBaseUrl = buildAbsoluteBaseUrl(); $homeUrl = rtrim($absoluteBaseUrl, '/') . '/'; $seoImage = makeAbsoluteUrl(!empty($heroImage) ? $heroImage : $logo, $absoluteBaseUrl); $seoTitle = $siteTitle . ' | Desarrollo de software, automatización y sistemas web'; $seoDescription = 'Aircan desarrolla software a medida, sistemas web, automatización de procesos, experiencias UI/UX y soluciones digitales escalables para empresas que quieren crecer con tecnología.'; $seoKeywords = 'Aircan, desarrollo de software, software a medida, sistemas web, aplicaciones web, automatización de procesos, diseño UI UX, transformación digital, desarrollo tecnológico, soluciones empresariales, páginas web, ecommerce, CRM, ERP'; $seoHeadline = 'Desarrollo de software, automatización y sistemas web para empresas que quieren crecer'; $socialProfiles = []; $socialFields = ['facebook_link', 'instagram_link', 'twitter_link', 'tiktok_link', 'youtube_link', 'linkedin_link', 'github_link', 'web_link']; foreach ($socialFields as $socialField) { $socialValue = trim((string)($ajustesMap[$socialField] ?? '')); if ($socialValue !== '') { $socialProfiles[] = makeAbsoluteUrl($socialValue, $absoluteBaseUrl); } } $socialProfiles = array_values(array_unique(array_filter($socialProfiles))); $whatsAppNumber = preg_replace('/[^0-9+]/', '', (string)($ajustesMap['whatsapp_number'] ?? '')); $schemaGraph = [ [ '@type' => 'Organization', '@id' => $homeUrl . '#organization', 'name' => $siteTitle, 'url' => $homeUrl, 'logo' => makeAbsoluteUrl($logo, $absoluteBaseUrl), 'image' => $seoImage, 'description' => $seoDescription, ], [ '@type' => 'WebSite', '@id' => $homeUrl . '#website', 'url' => $homeUrl, 'name' => $siteTitle, 'description' => $seoDescription, 'inLanguage' => 'es', 'publisher' => ['@id' => $homeUrl . '#organization'], ], [ '@type' => 'ProfessionalService', '@id' => $homeUrl . '#service', 'name' => $siteTitle, 'url' => $homeUrl, 'image' => $seoImage, 'description' => $seoDescription, 'areaServed' => 'Latinoamérica', 'serviceType' => ['Desarrollo de software', 'Automatización de procesos', 'Diseño UI/UX', 'Sistemas web empresariales'], 'brand' => ['@id' => $homeUrl . '#organization'], ], ]; if (!empty($socialProfiles)) { $schemaGraph[0]['sameAs'] = $socialProfiles; $schemaGraph[2]['sameAs'] = $socialProfiles; } if ($whatsAppNumber !== '') { $schemaGraph[0]['contactPoint'] = [[ '@type' => 'ContactPoint', 'telephone' => $whatsAppNumber, 'contactType' => 'sales', 'areaServed' => 'Latinoamérica', 'availableLanguage' => ['es'], ]]; } ?> <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="google" content="notranslate"> <meta http-equiv="content-language" content="es"> <meta name="language" content="Spanish"> <meta name="geo.region" content="MX"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?= htmlspecialchars($seoTitle) ?></title> <!-- ==================== AIRCAN SEO OPTIMIZATION ==================== --> <meta name="description" content="<?= htmlspecialchars($seoDescription) ?>"> <meta name="keywords" content="<?= htmlspecialchars($seoKeywords) ?>"> <meta name="author" content="Aircan"> <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"> <meta name="googlebot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"> <meta name="bingbot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"> <link rel="canonical" href="<?= htmlspecialchars($homeUrl) ?>"> <link rel="sitemap" type="application/xml" title="Sitemap" href="<?= htmlspecialchars($homeUrl . 'sitemap.php') ?>"> <!-- Open Graph (Facebook, LinkedIn, WhatsApp) --> <meta property="og:type" content="website"> <meta property="og:locale" content="es_MX"> <meta property="og:url" content="<?= htmlspecialchars($homeUrl) ?>"> <meta property="og:title" content="<?= htmlspecialchars($seoTitle) ?>"> <meta property="og:description" content="<?= htmlspecialchars($seoDescription) ?>"> <meta property="og:image" content="<?= htmlspecialchars($seoImage) ?>"> <meta property="og:image:secure_url" content="<?= htmlspecialchars($seoImage) ?>"> <meta property="og:image:alt" content="<?= htmlspecialchars($seoHeadline) ?>"> <meta property="og:site_name" content="<?= htmlspecialchars($siteTitle) ?>"> <!-- Twitter Cards --> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:url" content="<?= htmlspecialchars($homeUrl) ?>"> <meta name="twitter:title" content="<?= htmlspecialchars($seoTitle) ?>"> <meta name="twitter:description" content="<?= htmlspecialchars($seoDescription) ?>"> <meta name="twitter:image" content="<?= htmlspecialchars($seoImage) ?>"> <meta name="twitter:image:alt" content="<?= htmlspecialchars($seoHeadline) ?>"> <!-- Schema.org (JSON-LD) para Rich Snippets en Google --> <script type="application/ld+json"> <?= json_encode(['@context' => 'https://schema.org', '@graph' => $schemaGraph], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) ?> </script> <!-- Preconexiones (Mejora de rendimiento para Core Web Vitals) --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="dns-prefetch" href="//cdnjs.cloudflare.com"> <link rel="dns-prefetch" href="//cdn.jsdelivr.net"> <link rel="dns-prefetch" href="//unpkg.com"> <link rel="preload" as="image" href="<?= htmlspecialchars(makeAbsoluteUrl('public/assets/img/PNG.png', $absoluteBaseUrl)) ?>" fetchpriority="high"> <!-- ================================================================= --> <?php $faviconType = getFaviconMimeType($favicon); ?> <link rel="icon" type="<?= $faviconType ?>" href="<?= htmlspecialchars($favicon) ?>?v=<?= time() ?>"> <link rel="shortcut icon" type="<?= $faviconType ?>" href="<?= htmlspecialchars($favicon) ?>?v=<?= time() ?>"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"> <link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@500;600;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://unpkg.com/aos@2.3.1/dist/aos.css"> <!-- Aircan AI Chat --> <link rel="stylesheet" href="public/assets/css/aircan-chat.css"> <!-- PWA --> <link rel="manifest" href="manifest.php?v=<?= time() ?>"> <meta name="application-name" content="<?= htmlspecialchars($siteTitle) ?>"> <meta name="theme-color" content="#00e5ff"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-title" content="<?= htmlspecialchars($siteTitle) ?>"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="msapplication-TileColor" content="#00e5ff"> <meta name="msapplication-TileImage" content="pwa-icon.php?size=192&v=<?= time() ?>"> <link rel="apple-touch-icon" sizes="180x180" href="pwa-icon.php?size=180&v=<?= time() ?>"> <style> :root { /* AIRCAN Brand Colors - Based on Logo */ --primary: #1a2332; /* Deep dark blue from logo */ --secondary: #00e5ff; /* Electric blue highlights */ --accent: #ff6b35; /* Warm orange/amber glow */ --neon-green: #7dff5a; /* Vibrant green highlight */ --metallic: #c0c5ce; /* Brushed silver/grey metallic */ --metallic-dark: #8b95a1; /* Darker metallic for contrast */ --light: #f8f9fa; /* Light background */ --dark: #0a0e1a; /* Deep black background */ --text: #2c3e50; /* Dark text */ --white: #ffffff; /* Pure white */ --gradient-primary: linear-gradient(135deg, #1a2332 0%, #2c3e50 100%); --gradient-secondary: linear-gradient(135deg, #00e5ff 0%, #3498db 100%); --gradient-accent: linear-gradient(135deg, #ff6b35 0%, #ff8c42 100%); --gradient-metallic: linear-gradient(135deg, #c0c5ce 0%, #e8eaed 100%); --success: #27ae60; /* Brand green for pricing */ --success-soft: #eafbe7; /* Soft background for price badges */ /* Nav sizing */ --menu-font-size: 1rem; /* desktop base size for nav */ } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { color: var(--text); line-height: 1.6; background-color: #000000; overflow-x: hidden; } html { overflow-x: hidden; width: 100%; background-color: #000000; } .container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 20px; } /* Header */ header { background: rgba(0, 0, 0, 0.92) !important; box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45) !important; position: fixed; width: 100%; top: 0; z-index: 1000; border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important; backdrop-filter: blur(14px) !important; } .header-container { display: flex; justify-content: space-between; align-items: center; padding: 22px 0; gap: 28px; } /* Desktop refinements */ @media (min-width: 993px) { .header-container { padding: 14px 0; } .logo img { height: 56px; } header nav { margin-left: auto; } nav ul { gap: 10px; padding: 8px 10px; border-radius: 999px; background: linear-gradient(135deg, rgba(255,255,255,0.05), rgba(255,255,255,0.02)); border: 1px solid rgba(192, 197, 206, 0.14); box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 20px 35px rgba(0,0,0,0.18); backdrop-filter: blur(10px); } nav ul li a { font-size: 0.88rem; padding: 12px 16px; border-radius: 999px; } } .logo { display: flex; align-items: center; gap: 0; min-width: 0; } .logo-mark { position: relative; display: inline-flex; align-items: center; justify-content: center; overflow: hidden; border-radius: 14px; isolation: isolate; } .logo-mark::before { content: ''; position: absolute; inset: -18% -30%; background: linear-gradient(110deg, rgba(255,255,255,0) 25%, rgba(255,255,255,0.18) 45%, rgba(255,255,255,0.42) 50%, rgba(255,255,255,0.16) 55%, rgba(255,255,255,0) 72%); transform: translateX(-165%) skewX(-18deg); opacity: 0; pointer-events: none; } .logo-mark::after { content: ''; position: absolute; inset: 10% 8%; border-radius: 12px; background: radial-gradient(circle at 22% 50%, rgba(0,229,255,0.16), transparent 45%); opacity: 0.45; pointer-events: none; z-index: 0; } .logo img { height: 52px; margin: 0; width: auto; object-fit: contain; position: relative; z-index: 1; filter: drop-shadow(0 4px 12px rgba(0, 229, 255, 0.08)); transition: filter 0.3s ease, transform 0.3s ease; } @media (prefers-reduced-motion: no-preference) { .logo-mark::before { animation: logoSheen 6.5s cubic-bezier(0.4, 0, 0.2, 1) infinite; } } .logo:hover .logo-mark::before { animation-duration: 2.8s; } .logo:hover img { filter: drop-shadow(0 6px 18px rgba(0, 229, 255, 0.14)); } @keyframes logoSheen { 0%, 58% { transform: translateX(-165%) skewX(-18deg); opacity: 0; } 62% { opacity: 0.3; } 70% { transform: translateX(165%) skewX(-18deg); opacity: 0.78; } 78%, 100% { transform: translateX(165%) skewX(-18deg); opacity: 0; } } nav ul { display: flex; list-style: none; gap: 12px; align-items: center; } nav ul li { margin: 0; } nav ul li a { text-decoration: none; color: rgba(236, 240, 245, 0.94) !important; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px; font-size: 0.95rem; transition: color 0.25s ease, transform 0.2s ease, background 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease; border: 1px solid transparent; } /* Ocultar iconos en escritorio */ @media (min-width: 993px) { } nav ul li a::after { content: ''; position: absolute; inset: auto 12px 6px; height: 3px; border-radius: 999px; background: linear-gradient(90deg, transparent, #0084ff, transparent); box-shadow: 0 0 12px rgba(0, 132, 255, 0.85); transform: scaleX(0.1); opacity: 0; transition: transform 0.32s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.28s ease; } nav ul li a:hover::after, nav ul li a:focus-visible::after, nav ul li a.nav-cta::after { transform: scaleX(1); opacity: 1; } nav ul li a:hover, nav ul li a:focus-visible { transform: translateY(-2.5px); color: #ffffff !important; background: linear-gradient(135deg, rgba(0, 132, 255, 0.18), rgba(0, 102, 255, 0.12)); border-color: rgba(0, 132, 255, 0.38); box-shadow: 0 0 25px rgba(0, 132, 255, 0.4), 0 10px 28px rgba(0, 0, 0, 0.28); } .nav-cta { background: linear-gradient(135deg, rgba(0,132,255,0.2), rgba(52,152,219,0.14)); border-color: rgba(0, 132, 255, 0.28) !important; color: #ffffff !important; box-shadow: 0 14px 28px rgba(0, 0, 0, 0.2); } .nav-cta i { color: #0084ff; font-size: 0.92rem; } .nav-cta:hover, .nav-cta:focus-visible { background: linear-gradient(135deg, rgba(0,132,255,0.26), rgba(52,152,219,0.18)); } .nav-link-label { position: relative; z-index: 1; } /* Install buttons */ .install-btn { display: inline-flex; align-items: center; justify-content: center; gap: 12px; padding: 10px 16px; border-radius: 999px; border: 1px solid rgba(0, 229, 255, 0.22); background: linear-gradient(135deg, rgba(0, 229, 255, 0.16), rgba(52, 152, 219, 0.12)); box-shadow: 0 16px 38px rgba(0, 0, 0, 0.24), inset 0 1px 0 rgba(255, 255, 255, 0.08); backdrop-filter: blur(16px); color: #ffffff; font-weight: 800; letter-spacing: 0.03em; cursor: pointer; transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease, background 0.25s ease, opacity 0.25s ease; } .install-btn:hover, .install-btn:focus-visible { background: linear-gradient(135deg, rgba(0, 229, 255, 0.24), rgba(52, 152, 219, 0.18)); border-color: rgba(0, 229, 255, 0.45); box-shadow: 0 22px 46px rgba(0, 0, 0, 0.3), 0 0 30px rgba(0, 229, 255, 0.14); transform: translateY(-2px); outline: none; } .install-btn[hidden] { display: none !important; } .install-btn__icon { width: 42px; height: 42px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #00e5ff 0%, #3498db 100%); color: #08111d; box-shadow: 0 10px 24px rgba(0, 229, 255, 0.25); flex-shrink: 0; } .install-btn__icon i { font-size: 1rem; } .install-btn__content { display: flex; flex-direction: column; align-items: flex-start; text-align: left; line-height: 1.05; } .install-btn__label { font-size: 0.95rem; font-weight: 800; color: #ffffff; } .install-btn__eyebrow { font-size: 0.7rem; font-weight: 600; opacity: 0.72; margin-top: 4px; letter-spacing: 0.04em; text-transform: uppercase; color: #d8faff; } #install-nav-item .install-btn { width: 100%; padding: 10px 12px; } #install-nav-item .install-btn .install-btn__icon { width: 34px; height: 34px; } #install-nav-item .install-btn .install-btn__label { font-size: 0.86rem; } #install-nav-item .install-btn .install-btn__eyebrow { font-size: 0.62rem; margin-top: 3px; } /* Hidden by default; JS decide dónde mostrar */ #install-nav-item { display: none; } #install-btn-desktop { display: none; } .install-btn--small { padding: 8px 14px; } .install-btn--footer { min-width: min(100%, 320px); } .install-btn--ios .install-btn__icon { background: linear-gradient(135deg, #f8fafc 0%, #cbd5e1 100%); color: #0a0e1a; } .ios-install-modal { position: fixed; inset: 0; background: rgba(3, 8, 20, 0.74); backdrop-filter: blur(18px); display: flex; align-items: center; justify-content: center; padding: 24px; z-index: 1000000; opacity: 0; pointer-events: none; transition: opacity 0.25s ease; } .ios-install-modal.is-visible { opacity: 1; pointer-events: auto; } .ios-install-sheet { width: min(100%, 480px); border-radius: 28px; padding: 28px; background: linear-gradient(180deg, rgba(10, 14, 26, 0.98), rgba(17, 24, 39, 0.96)); border: 1px solid rgba(0, 229, 255, 0.18); box-shadow: 0 30px 80px rgba(0, 0, 0, 0.45), 0 0 40px rgba(0, 229, 255, 0.08); color: #ffffff; } .ios-install-badge { display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; padding: 8px 12px; background: rgba(0, 229, 255, 0.12); border: 1px solid rgba(0, 229, 255, 0.18); color: #bff8ff; font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; } .ios-install-sheet h3 { margin: 18px 0 10px 0; font-size: 1.55rem; line-height: 1.15; } .ios-install-sheet p { margin: 0; color: rgba(226, 232, 240, 0.88); line-height: 1.65; } .ios-install-steps { list-style: none; margin: 22px 0 0 0; padding: 0; display: grid; gap: 12px; } .ios-install-steps li { display: grid; grid-template-columns: 40px 1fr; gap: 14px; align-items: start; padding: 14px 16px; border-radius: 18px; background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.06); } .ios-install-step-num { width: 40px; height: 40px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 800; color: #08111d; background: linear-gradient(135deg, #00e5ff 0%, #7dd3fc 100%); } .ios-install-step-copy strong { display: block; margin-bottom: 3px; color: #ffffff; } .ios-install-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 22px; flex-wrap: wrap; } .ios-install-action { border: none; border-radius: 999px; padding: 12px 18px; font-weight: 700; cursor: pointer; transition: transform 0.2s ease, opacity 0.2s ease, box-shadow 0.2s ease; } .ios-install-action:hover, .ios-install-action:focus-visible { transform: translateY(-1px); outline: none; } .ios-install-action--secondary { background: rgba(255, 255, 255, 0.08); color: #f8fafc; } .ios-install-action--primary { background: linear-gradient(135deg, #00e5ff 0%, #3498db 100%); color: #08111d; box-shadow: 0 14px 28px rgba(0, 229, 255, 0.22); } @media (max-width: 992px) { #install-nav-item { margin-top: 8px; } } @media (max-width: 640px) { .install-btn--footer { width: 100%; min-width: 0; } .ios-install-sheet { padding: 22px 18px; border-radius: 24px; } .ios-install-actions { flex-direction: column-reverse; } .ios-install-action { width: 100%; } } .mobile-menu { display: none; align-items: center; justify-content: center; width: 46px; height: 46px; padding: 0; border-radius: 14px; border: 1px solid rgba(0, 132, 255, 0.35); background: rgba(0, 132, 255, 0.08); color: #ffffff; font-size: 1.4rem; cursor: pointer; transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease; } .mobile-menu:hover { background: rgba(0, 132, 255, 0.18); border-color: rgba(0, 132, 255, 0.55); transform: translateY(-1px); } .mobile-menu:focus-visible { outline: 2px solid rgba(0, 132, 255, 0.65); outline-offset: 4px; } .mobile-menu i { pointer-events: none; } nav .mobile-profile { display: none; } .mobile-nav-overlay { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.65); z-index: 998; opacity: 0; transition: opacity 0.3s ease; } .mobile-nav-overlay.active { display: block; opacity: 1; } body.nav-open { overflow: hidden; } @media (max-width: 992px) { .mobile-menu { display: inline-flex; } } @media (min-width: 993px) { .mobile-menu { display: none; } } /* Hero Section - AIRCAN Branded with DARKEST BLACK */ .hero { --pointer-x: 50%; --pointer-y: 50%; --trail-x: 50%; --trail-y: 50%; background: #04050a !important; color: var(--white); min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center; text-align: center; position: relative; padding: 0; overflow: hidden; isolation: isolate; } .hero::before { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 22% 28%, rgba(30, 68, 214, 0.12) 0%, transparent 34%), radial-gradient(circle at 74% 20%, rgba(88, 62, 196, 0.12) 0%, transparent 32%), radial-gradient(circle at 50% 72%, rgba(74, 92, 180, 0.06) 0%, transparent 38%), linear-gradient(180deg, rgba(2, 3, 8, 0.12) 0%, rgba(2, 3, 8, 0.72) 100%); z-index: 0; pointer-events: none; } .hero::after { content: ''; position: absolute; inset: -12%; background: radial-gradient(circle at var(--pointer-x) var(--pointer-y), rgba(122, 164, 255, 0.12) 0%, rgba(82, 120, 255, 0.08) 9%, rgba(56, 82, 205, 0.04) 18%, transparent 30%); filter: blur(34px); opacity: var(--pointer-opacity, 0.58); z-index: 1; pointer-events: none; transform: scale(var(--pointer-pulse, 1)); transition: opacity 0.3s ease, transform 0.42s ease; } .hero .container { position: relative; z-index: 3; width: 100%; max-width: none; min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: clamp(110px, 10vw, 132px) 24px 40px; } .hero-stage { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; min-height: calc(100vh - clamp(150px, 12vw, 180px)); min-height: calc(100dvh - clamp(150px, 12vw, 180px)); } .hero-glow-scene { position: absolute; inset: 0; z-index: 0; overflow: hidden; } .hero-glow-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: 0.8; } .hero-glow-scene::before { content: ''; position: absolute; inset: -18%; background: radial-gradient(circle at var(--trail-x) var(--trail-y), rgba(168, 206, 255, 0.2) 0%, rgba(102, 134, 255, 0.12) 10%, rgba(68, 86, 196, 0.07) 18%, rgba(42, 52, 122, 0.03) 28%, transparent 42%); filter: blur(52px); opacity: var(--trail-opacity, 0); transform: scale(var(--trail-scale, 0.72)); transition: opacity 0.7s ease-out, transform 0.9s cubic-bezier(0.22, 1, 0.36, 1); pointer-events: none; z-index: 1; } .hero-glow-scene::after { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 50% 48%, transparent 0%, rgba(3, 4, 10, 0.12) 42%, rgba(3, 4, 10, 0.4) 72%, rgba(0, 0, 0, 0.76) 100%), linear-gradient(180deg, rgba(0, 0, 0, 0.14) 0%, rgba(0, 0, 0, 0.28) 100%); pointer-events: none; } .hero-ambient-orb { position: absolute; border-radius: 999px; filter: blur(90px); pointer-events: none; opacity: 0.24; mix-blend-mode: screen; } .hero-ambient-orb-left { width: min(34vw, 380px); height: min(34vw, 380px); left: -8%; top: 16%; background: radial-gradient(circle, rgba(36, 96, 255, 0.2) 0%, rgba(36, 96, 255, 0.04) 58%, transparent 76%); animation: hero-orb-float-left 18s ease-in-out infinite; } .hero-ambient-orb-right { width: min(40vw, 460px); height: min(40vw, 460px); right: -10%; top: 10%; background: radial-gradient(circle, rgba(122, 126, 255, 0.18) 0%, rgba(122, 126, 255, 0.04) 44%, transparent 76%); opacity: 0.28; animation: hero-orb-float-right 22s ease-in-out infinite; } .hero-logo-lockup { position: relative; display: inline-flex; align-items: center; justify-content: center; padding: clamp(20px, 2.5vw, 30px); } .hero-logo-lockup::before, .hero-logo-lockup::after { content: ''; position: absolute; inset: 10% 14%; border-radius: 50%; pointer-events: none; } .hero-logo-lockup::before { background: radial-gradient(circle, rgba(86, 146, 255, 0.2) 0%, rgba(76, 98, 232, 0.12) 30%, rgba(76, 56, 186, 0.08) 54%, transparent 72%); filter: blur(30px); transform: scale(1.08); } .hero-logo-lockup::after { inset: 18% 22%; background: radial-gradient(circle, rgba(178, 212, 255, 0.34) 0%, rgba(122, 160, 255, 0.14) 24%, transparent 58%); filter: blur(38px); opacity: 0.3; } .hero-center-logo { position: relative; z-index: 2; width: min(76vw, 920px); height: auto; display: block; filter: drop-shadow(0 0 24px rgba(77, 119, 255, 0.2)) drop-shadow(0 14px 28px rgba(0, 0, 0, 0.4)); animation: hero-logo-float 14s ease-in-out infinite; user-select: none; -webkit-user-drag: none; will-change: transform, filter; } @keyframes hero-logo-float { 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(0, -10px, 0) scale(1.012); } } @keyframes hero-orb-float-left { 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(24px, -18px, 0) scale(1.06); } } @keyframes hero-orb-float-right { 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(-32px, 22px, 0) scale(1.08); } } @media (max-width: 992px) { .hero .container { padding: 110px 18px 34px; } .hero-stage { min-height: calc(100vh - 150px); min-height: calc(100dvh - 150px); } .hero-center-logo { width: min(88vw, 720px); } .hero-ambient-orb-left { width: 58vw; height: 58vw; left: -18%; top: 26%; } .hero-ambient-orb-right { width: 72vw; height: 72vw; right: -28%; top: 12%; } } @media (max-width: 576px) { .hero .container { padding: 104px 16px 28px; } .hero-stage { min-height: calc(100vh - 138px); min-height: calc(100dvh - 138px); } .hero-logo-lockup { padding: 16px; } .hero-center-logo { width: min(92vw, 520px); filter: drop-shadow(0 0 16px rgba(77, 119, 255, 0.2)) drop-shadow(0 12px 24px rgba(0, 0, 0, 0.4)); } } .hero h1 { font-size: 4.2rem; margin-bottom: 24px; font-weight: 900; letter-spacing: -1px; background: var(--gradient-secondary); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; color: transparent; text-shadow: 0 0 30px rgba(0, 229, 255, 0.4); line-height: 1.1; } .hero .subtitle { font-size: 1.8rem; margin-bottom: 32px; color: var(--metallic); font-weight: 600; text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); line-height: 1.4; } .hero .description { font-size: 1.2rem; margin-bottom: 40px; color: var(--metallic-dark); line-height: 1.6; max-width: 500px; } .hero .btn { display: inline-flex; align-items: center; gap: 12px; font-size: 1.3rem; padding: 20px 50px; border-radius: 50px; font-weight: 700; background: var(--gradient-secondary); color: var(--dark); box-shadow: 0 8px 25px rgba(0, 229, 255, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.2); border: none; cursor: pointer; transition: all 0.3s ease; text-decoration: none; position: relative; overflow: hidden; } .hero .btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); transition: left 0.5s; } .hero .btn:hover::before { left: 100%; } .hero .btn i { font-size: 1.4em; animation: pulse-glow 2s infinite; } .hero .btn:hover { transform: translateY(-3px) scale(1.05); background: var(--gradient-accent); box-shadow: 0 12px 35px rgba(255, 107, 53, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.3); } @keyframes pulse-glow { 0%, 100% { text-shadow: 0 0 5px rgba(0, 229, 255, 0.5); transform: scale(1); } 50% { text-shadow: 0 0 20px rgba(0, 229, 255, 0.8); transform: 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); } } /* Additional Mobile Responsive Design */ @media (max-width: 768px) { .hero .container { padding: 20px 15px; gap: 30px; } .hero h1 { font-size: 2.8rem; } .hero .subtitle { font-size: 1.3rem; } .hero .description { font-size: 1rem; } .hero .btn { font-size: 1.1rem; padding: 16px 40px; } } @media (max-width: 576px) { .hero .container { padding: 15px 10px; gap: 25px; } .hero h1 { font-size: 2.2rem; } .hero .subtitle { font-size: 1.1rem; } .hero .description { font-size: 0.95rem; } .hero .btn { font-size: 1rem; padding: 14px 35px; } .hero-image img, .hero-image video { border-radius: 15px; } } /* Sections */ section { padding: 30px 0; background: #000000; } .section-title { text-align: center; margin-bottom: 50px; } .section-title h2 { font-family: 'Playfair Display', 'Georgia', 'Times New Roman', serif; font-size: 3.4rem; letter-spacing: 0.02em; font-weight: 600; color: var(--metallic); position: relative; display: inline-block; padding-bottom: 18px; text-shadow: none; } .section-title h2::after { content: ''; position: absolute; width: 50px; height: 3px; background: var(--gradient-secondary); bottom: 0; left: 50%; transform: translateX(-50%); } /* Clientes Satisfechos - Carousel Ribbon */ #clientes-satisfechos .clientes-ribbon { background: var(--white); background-color: #fff !important; padding: 44px 0; position: relative; overflow: hidden; box-shadow: 0 12px 36px rgba(0,0,0,0.06); border-top: none; border-bottom: none; z-index: 2; } #clientes-satisfechos .clientes-ribbon::before, #clientes-satisfechos .clientes-ribbon::after { content: none !important; display: none !important; } /* CTA Trial Section */ .cta-trial-section { background: #000000; color: #ffffff; padding: 110px 0 110px 0; position: relative; overflow: hidden; } .cta-trial-section .container { display: flex; flex-direction: column; align-items: flex-start; max-width: 1080px; margin-left: 0; padding-left: 20px; } .cta-trial-heading { font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-weight: 500; font-size: clamp(3rem, 7vw, 5.6rem); line-height: 1.05; margin-bottom: 42px; letter-spacing: -0.01em; } .cta-trial-actions { display: flex; align-items: center; justify-content: center; gap: 20px; flex-wrap: wrap; text-align: center; } .cta-trial-button { background: #ffffff; color: #000000; border: none; font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-weight: 600; font-size: 1.2rem; padding: 18px 48px; border-radius: 999px; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 14px 36px rgba(255,255,255,0.16); transition: transform 0.2s ease, box-shadow 0.2s ease; } .cta-trial-button:hover { transform: translateY(-4px); box-shadow: 0 20px 42px rgba(255,255,255,0.22); } .cta-trial-note { font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-size: 0.9rem; color: rgba(255,255,255,0.7); max-width: 360px; margin: 0; } @media (max-width: 768px) { .cta-trial-section { padding: 70px 0 60px 0; } .cta-trial-section .container { align-items: center; padding-left: 0; } .cta-trial-actions { flex-direction: column; gap: 14px; } .cta-trial-note { font-size: 0.85rem; max-width: 100%; } } @media (max-width: 576px) { #services { padding: 50px 0 30px 0; } .cta-trial-section { padding: 60px 0 50px 0; } .cta-trial-heading { font-size: clamp(2.6rem, 9vw, 4.4rem); margin-bottom: 30px; } .cta-trial-button { width: 100%; justify-content: center; } .cta-trial-actions { gap: 12px; align-items: center; } .cta-trial-note { font-size: 0.8rem; max-width: none; line-height: 1.4; } } /* CTA Mockup Showcase */ .cta-mockup-section { background: #000000 !important; padding: 60px 0 100px 0; position: relative; } .cta-mockup-section::before { content: none !important; background: none !important; } .cta-mockup-section .container { position: relative; display: grid; grid-template-columns: minmax(420px, 1.2fr) minmax(320px, 1fr); gap: 64px; align-items: center; } .mockup-visuals { display:flex; align-items:center; justify-content:flex-start; width: 100%; margin-left: 0; } .visuals-stage { display:flex; align-items:flex-end; gap: 32px; margin-left: clamp(-220px, -12vw, -110px); } .laptop-img { width: min(620px, 70vw); height: auto; border-radius: 0; border: none; box-shadow: 0 22px 50px rgba(0,0,0,0.45); } .phone-img { position: static; width: min(180px, 24vw); height: auto; transform: none; border-radius: 0; border: none; box-shadow: 0 16px 40px rgba(0,0,0,0.5); margin-bottom: 38px; margin-left: -10px; } .cta-mockup-copy { color: #f6f8fb; display: flex; flex-direction: column; gap: 26px; } .cta-mockup-title { font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-size: clamp(2.6rem, 5vw, 3.6rem); font-weight: 700; line-height: 1.15; letter-spacing: -0.01em; } .cta-mockup-text { font-size: 1.18rem; color: rgba(228, 234, 241, 0.88); line-height: 1.75; max-width: 520px; } .cta-mockup-bullets { display: grid; gap: 16px; font-size: 1.05rem; color: rgba(212, 219, 228, 0.82); } .cta-mockup-bullets span { display: inline-flex; align-items: center; gap: 10px; } .cta-mockup-bullets span::before { content: ''; width: 10px; height: 10px; border-radius: 50%; background: var(--secondary); box-shadow: 0 0 12px rgba(0, 229, 255, 0.45); } .phone-mockup { position: relative; width: min(420px, 100%); margin: 0 auto; filter: drop-shadow(0 34px 58px rgba(0,0,0,0.55)); } .phone-frame { width: 100%; display: block; } .phone-screen { position: absolute; top: 10.5%; left: 13%; width: 74%; height: 78%; object-fit: cover; border-radius: 18px; box-shadow: inset 0 0 18px rgba(0,0,0,0.35); } .phone-badge { position: absolute; bottom: -22px; right: 18px; background: rgba(0, 229, 255, 0.16); color: var(--secondary); font-size: 0.85rem; letter-spacing: 0.1em; text-transform: uppercase; padding: 6px 16px; border-radius: 999px; font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; } @media (max-width: 992px) { .cta-mockup-section { padding: 50px 0 80px 0; } .cta-mockup-section .container { grid-template-columns: 1fr; gap: 48px; text-align: center; } .cta-mockup-copy { align-items: center; } .cta-mockup-bullets { justify-items: center; } .mockup-visuals { width: 100%; justify-content: center; } .visuals-stage { flex-direction: column; align-items: center; gap: 20px; margin-left: 0; } .laptop-img { width: 100%; max-width: 420px; } .phone-img { width: 52%; max-width: 200px; margin-bottom: 0; } .phone-badge { bottom: -18px; } } @media (max-width: 576px) { .cta-mockup-title { font-size: clamp(1.9rem, 7vw, 2.6rem); } .phone-screen { top: 11%; left: 12.8%; width: 74.4%; height: 77.4%; } } /* PC Image Showcase Section */ .pc-showcase-section { background: #000000 !important; padding: 80px 0 100px 0; position: relative; } .pc-showcase-section .container { display: flex; justify-content: center; align-items: center; min-height: 75vh; width: 100%; max-width: none; padding: 0; } .pc-showcase-image { display: flex; justify-content: center; align-items: center; width: 100%; position: relative; } .pc-showcase-image img { width: min(1900px, 98vw); height: auto; max-height: 95vh; margin: 0 auto; object-fit: contain; transition: all 0.3s ease; } @media (max-width: 992px) { .pc-showcase-section { padding: 60px 0 80px 0; } .pc-showcase-section .container { min-height: 65vh; padding: 0 12px; } .pc-showcase-image img { width: min(1300px, 95vw); max-height: 88vh; } } @media (max-width: 768px) { .pc-showcase-section { padding: 40px 0 60px 0; } .pc-showcase-section .container { min-height: 55vh; padding: 0 10px; } .pc-showcase-image img { width: min(1000px, 96vw); max-height: 80vh; } } /* Full-bleed trick so the ribbon spans full viewport width even inside a container */ #clientes-satisfechos .clientes-ribbon.full-bleed { width: 100vw; width: 100dvw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); margin-left: calc(50% - 50dvw); margin-right: calc(50% - 50dvw); border-left: none; border-right: none; } #clientes-satisfechos .clientes-marquee { position: relative; overflow: hidden; background: #fff; padding: 10px 0; --marquee-duration: 44s; } #clientes-satisfechos .clientes-marquee::before, #clientes-satisfechos .clientes-marquee::after { content: ''; position: absolute; top: 0; bottom: 0; width: 80px; pointer-events: none; z-index: 3; } #clientes-satisfechos .clientes-marquee::before { left: 0; background: linear-gradient(to right, #fff 0%, rgba(255,255,255,0) 100%); } #clientes-satisfechos .clientes-marquee::after { right: 0; background: linear-gradient(to left, #fff 0%, rgba(255,255,255,0) 100%); } #clientes-satisfechos .marquee-track { display: flex; align-items: center; gap: 96px; width: max-content; will-change: transform; } #clientes-satisfechos .marquee-track.marquee-animate { animation: clientes-marquee var(--marquee-duration, 28s) linear infinite; } #clientes-satisfechos .marquee-track:hover { animation-play-state: paused; } #clientes-satisfechos .logo-item { flex: 0 0 auto; } #clientes-satisfechos .logo-item a { cursor: pointer; display: inline-block; line-height: 0; border-radius: 14px; } #clientes-satisfechos .logo-link { display:inline-block; line-height:0; border-radius:14px; transition: transform .3s ease, box-shadow .3s ease; position: relative; } #clientes-satisfechos .logo-link:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0,0,0,0.08); } #clientes-satisfechos .logo-link .play-badge { position:absolute; right:8px; bottom:8px; width:36px; height:36px; border-radius:999px; background:linear-gradient(135deg,#ff6b35,#ff8c42); color:#fff; display:flex; align-items:center; justify-content:center; box-shadow:0 8px 18px rgba(255,107,53,0.35); font-size:.9rem; border:2px solid #fff; transition: transform .25s ease, box-shadow .25s ease; } #clientes-satisfechos .logo-link:hover .play-badge { transform: scale(1.08); box-shadow:0 10px 22px rgba(255,107,53,0.4); } #clientes-satisfechos .logo-item img { display: block; height: 128px; width: 200px; object-fit: contain; filter: none; transition: transform .4s cubic-bezier(.2,.8,.2,1), filter .35s ease; } #clientes-satisfechos .logo-item:hover img { transform: translateY(-2px) scale(1.14); filter: drop-shadow(0 16px 28px rgba(0,0,0,0.12)); } #clientes-satisfechos .marquee-empty { text-align: center; color: #aaa; font-size: 1.05rem; padding: 24px 0; } @keyframes clientes-marquee { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } } @media (max-width: 992px) { #clientes-satisfechos .marquee-track { gap: 72px; } #clientes-satisfechos .logo-item img { height: 100px; width: 160px; } } @media (max-width: 576px) { #clientes-satisfechos .marquee-track { gap: 52px; } #clientes-satisfechos .logo-item img { height: 110px; width: 172px; } } @media (min-width: 1400px) { #clientes-satisfechos .logo-item img { height: 148px; width: 240px; } #clientes-satisfechos .marquee-track { gap: 120px; } } @media (prefers-reduced-motion: reduce) { #clientes-satisfechos .marquee-track { animation: none !important; } } /* About Us Cinematic */ .about-section { background: linear-gradient(135deg, #050608 0%, #0a1018 55%, #050608 100%); padding: 50px 0 40px 0; margin-bottom: 0; } .about-content { display: grid; grid-template-columns: minmax(340px, 1fr) minmax(460px, 1.1fr); gap: 80px; align-items: center; } .about-text { display: flex; flex-direction: column; gap: 26px; } .about-headline { font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-size: clamp(3rem, 5.5vw, 5rem); font-weight: 600; line-height: 1.08; color: #f5f6f7; max-width: 540px; text-transform: uppercase; } .section-title h1, .section-title h2, .section-title h3 { font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif !important; font-size: clamp(3rem, 5.5vw, 5rem) !important; font-weight: 600 !important; line-height: 1.08 !important; text-transform: uppercase !important; margin-bottom: 24px; } .about-intro { font-size: 1.15rem; color: rgba(235, 239, 244, 0.86); line-height: 1.7; max-width: 560px; } .about-features { display: grid; gap: 24px; } .about-feature h3 { font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-size: 1.2rem; color: #fdfdfd; margin-bottom: 10px; font-weight: 600; } .about-feature p { font-size: 1rem; color: rgba(225, 231, 236, 0.8); line-height: 1.65; max-width: 520px; } .about-image { position: relative; display: flex; justify-content: flex-end; align-items: center; } .about-image img { display: block; width: min(640px, 100%); border-radius: 26px; object-fit: cover; filter: none; box-shadow: 0 28px 64px rgba(0, 0, 0, 0.55); } @media (max-width: 992px) { .about-section { padding: 80px 0 40px 0; margin-bottom: 0; } .about-content { grid-template-columns: 1fr; gap: 56px; } .about-image { justify-content: center; } } @media (max-width: 576px) { .about-section { padding: 58px 0 30px 0; } .about-headline, .section-title h1, .section-title h2, .section-title h3 { font-size: clamp(2.6rem, 7.8vw, 3.4rem) !important; } } /* Team Section - Redesigned */ .team-grid-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 25px; padding: 20px 0; } .team-card { background: rgba(255, 255, 255, 0.85); border: 1px solid rgba(255, 255, 255, 0.4); border-radius: 24px; overflow: hidden; transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1); position: relative; backdrop-filter: blur(15px); height: 100%; display: flex; flex-direction: column; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); } .team-card:hover { transform: translateY(-8px); background: rgba(255, 255, 255, 0.95); border-color: rgba(0, 229, 255, 0.5); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); } .team-card-inner { height: 100%; } .team-card-front { padding: 30px 20px 25px 20px; text-align: center; display: flex; flex-direction: column; align-items: center; height: 100%; position: relative; } .team-img { width: 130px; height: 130px; border-radius: 50%; margin: 0 auto 15px; transition: all 0.4s ease; position: relative; background: linear-gradient(135deg, #00e5ff, #0050a0); padding: 4px; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1); } .team-card:hover .team-img { transform: scale(1.05); box-shadow: 0 0 20px rgba(0, 229, 255, 0.3); } .team-img img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; border: 3px solid #ffffff; } .team-card h3 { margin: 10px 0 5px; font-size: 1.25rem; color: #1a2332; font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; } .team-card .position { font-size: 0.68rem; margin-bottom: 18px; font-weight: 700; padding: 5px 18px; border-radius: 50px; display: inline-block; text-transform: uppercase; letter-spacing: 1.5px; position: relative; transition: all 0.3s ease; border: 1px solid transparent; } /* Niveles profesionales - Refined Look */ .team-card .position.vip { background: linear-gradient(135deg, #bf953f 0%, #fcf6ba 45%, #b38728 100%); color: #4a370b; border: 1px solid rgba(184, 134, 11, 0.4); box-shadow: 0 4px 15px rgba(184, 134, 11, 0.15); } .team-card .position.platinum { background: linear-gradient(135deg, #e5e9ef 0%, #ffffff 50%, #ccd6df 100%); color: #1f2a36; border: 1px solid rgba(160, 174, 192, 0.3); box-shadow: 0 4px 15px rgba(160, 174, 192, 0.1); } .team-card .position.bronze { background: linear-gradient(135deg, #d39d76 0%, #f7e1d1 50%, #b87333 100%); color: #3e2716; border: 1px solid rgba(184, 115, 51, 0.3); box-shadow: 0 4px 15px rgba(184, 115, 51, 0.1); } .social-hover { margin-top: auto; width: 100%; padding-top: 15px; border-top: 1px solid rgba(0, 0, 0, 0.05); } .social-hover > span { display: block; color: #718096; font-size: 0.7rem; margin-bottom: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; } .team-card .emp-social-row { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; } .emp-social-icon-img { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 8px; background: #ffffff; border: 1px solid rgba(0, 0, 0, 0.08); transition: all 0.3s ease; padding: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); } .emp-social-icon-img:hover { transform: translateY(-3px); background: #f7fafc; border-color: rgba(0, 229, 255, 0.4); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .emp-social-icon-img img { width: 100%; height: 100%; object-fit: contain; } @media (max-width: 991px) { .team-grid-container { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; } .team-img { width: 120px; height: 120px; } } @media (max-width: 576px) { .team-grid-container { grid-template-columns: 1fr; max-width: 320px; margin: 0 auto; } } /* Servicios - Carrusel Cinemático */ #services { background: #000; padding: 70px 0 60px 0; position: relative; overflow: hidden; } #services .container { position: relative; max-width: 1200px; margin: 0 auto; padding: 0 24px; width: 100%; } .services-heading { display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap; margin-bottom: 28px; width: 100%; } .services-heading h2 { font-family: 'Playfair Display', 'Georgia', serif; font-size: clamp(2.6rem, 5vw, 4rem); font-weight: 600; color: #f1f5fb; letter-spacing: -0.01em; } .services-nav { display: inline-flex; gap: 14px; align-items: center; } .services-nav button { width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06); color: #f6f8fc; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: transform 0.2s ease, background 0.2s ease, border 0.2s ease; } .services-nav button:hover { background: rgba(255,255,255,0.14); transform: translateY(-2px); border-color: rgba(255,255,255,0.32); } .services-nav button:disabled { opacity: 0.35; cursor: default; transform: none; } .services-carousel { position: relative; } .services-track-wrapper { overflow: hidden; border-radius: 0; margin: 0 calc(-1 * 5vw); padding: 0 5vw; width: calc(100% + 10vw); } .services-track { display: flex; gap: 16px; scroll-behavior: smooth; padding-bottom: 6px; width: 100%; overflow-x: auto; scrollbar-width: none; } .services-track::-webkit-scrollbar { display: none; } .service-card { flex: 0 0 clamp(210px, 16vw, 260px); min-width: clamp(210px, 16vw, 260px); border-radius: 20px; background: linear-gradient(145deg, #0f1219, #080a0f); border: 1px solid rgba(255, 255, 255, 0.05); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); overflow: hidden; color: #eef2f7; display: flex; flex-direction: column; transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1); position: relative; } .service-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; border-radius: 20px; padding: 1px; background: linear-gradient(135deg, rgba(0, 229, 255, 0.2), transparent, rgba(0, 229, 255, 0.1)); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; opacity: 0.4; transition: opacity 0.4s ease; } .service-card:hover { transform: translateY(-6px); border-color: rgba(0, 229, 255, 0.2); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4), 0 0 20px rgba(0, 229, 255, 0.1); } .service-card:hover::before { opacity: 0.8; } .service-media { position: relative; height: 140px; overflow: hidden; } .service-media::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 40%; background: linear-gradient(to top, #0f1219, transparent); z-index: 1; } .service-media img { width: 100%; height: 100%; object-fit: cover; filter: saturate(1.1) contrast(1.1); transition: transform 0.8s cubic-bezier(0.165, 0.84, 0.44, 1); } .service-card:hover .service-media img { transform: scale(1.1); } .service-content { padding: 16px 18px 20px 18px; display: flex; flex-direction: column; gap: 12px; flex-grow: 1; z-index: 2; } .service-title { font-size: 1.15rem; font-weight: 700; color: #ffffff; letter-spacing: -0.01em; line-height: 1.25; margin-bottom: 2px; } .service-description { color: rgba(215,225,235,0.8); line-height: 1.55; font-size: 0.88rem; margin-bottom: 10px; /* Se elimina el line-clamp para mostrar todo el contenido */ display: block; overflow: visible; } .service-footer { margin-top: auto; display: flex; justify-content: flex-end; align-items: center; gap: 12px; padding-top: 12px; border-top: 1px solid rgba(255, 255, 255, 0.05); } .btn-comprar-servicio { text-decoration: none; display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border: none; border-radius: 12px; background: #ffffff; color: #1a2332; font-weight: 700; font-size: 0.82rem; cursor: pointer; box-shadow: 0 6px 16px rgba(255,255,255,0.08); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .btn-comprar-servicio i { font-size: 0.95rem; } .btn-comprar-servicio:hover { transform: translateY(-3px) scale(1.02); background: #00e5ff; color: #ffffff; box-shadow: 0 12px 28px rgba(0, 229, 255, 0.3); } @media (max-width: 992px) { .services-heading { flex-direction: column; align-items: flex-start; } #services { padding: 60px 0 40px 0; } .services-track-wrapper { margin: 0 calc(-1 * 4vw); padding: 0 4vw; width: calc(100% + 8vw); } .service-card { flex: 0 0 clamp(220px, 60vw, 280px); min-width: clamp(220px, 60vw, 280px); border-radius: 20px; } .service-media { height: 150px; } .service-content { padding: 16px 18px 18px 18px; gap: 12px; } .service-title { font-size: 1.2rem; } .service-description { font-size: 0.92rem; line-height: 1.55; } .btn-comprar-servicio { padding: 8px 18px; font-size: 0.85rem; } } @media (max-width: 576px) { #services .container { padding: 0 16px; } .services-track-wrapper { margin: 0 calc(-1 * 16px); padding: 0 16px; width: calc(100% + 32px); } .services-track { gap: 14px; } .service-card { flex: 0 0 min(220px, 82vw); min-width: min(220px, 82vw); border-radius: 18px; } .service-media { height: 140px; } .service-content { padding: 14px 16px 16px 16px; gap: 10px; } .service-title { font-size: 1.15rem; } .service-description { font-size: 0.88rem; } .btn-comprar-servicio { padding: 7px 16px; font-size: 0.8rem; } } /* Clients */ .clients-slider { display: flex; flex-wrap: wrap; justify-content: center; gap: 40px; align-items: center; } .client-logo { max-width: 150px; filter: grayscale(100%); opacity: 0.7; transition: all 0.3s; } .client-logo:hover { filter: grayscale(0%); opacity: 1; } /* Contact */ .contact-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 42px; } .contact-info { display: flex; flex-direction: column; gap: 22px; } /* Card de contacto elegante */ .contact-item { display: flex; align-items: center; gap: 16px; padding: 22px; border-radius: 20px; background: linear-gradient(180deg, rgba(11,15,20,.76) 0%, rgba(12,18,26,.86) 100%), radial-gradient(800px 200px at -10% -20%, rgba(0,229,255,.08), transparent 60%); border: 1px solid rgba(255,255,255,0.06); box-shadow: 0 14px 34px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.04); position: relative; overflow: hidden; transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease, background .25s ease; backdrop-filter: blur(8px) saturate(120%); --card-accent-start: #00e5ff; /* default accent */ --card-accent-end: #3498db; font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; } /* Animated gradient border using mask for glass effect */ .contact-item::before { content: ''; position: absolute; inset: -1px; padding: 1.2px; border-radius: inherit; background: linear-gradient(135deg, var(--card-accent-start), var(--card-accent-end)); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; opacity: .65; pointer-events: none; transition: opacity .25s ease; } /* Sheen sweep removed */ .contact-item::after { content: none; } .contact-item:hover { transform: translateY(-6px); box-shadow: 0 22px 50px rgba(0,0,0,0.5), inset 0 10px 22px rgba(255,255,255,0.02); } /* Per-card accents */ .contact-item.phone-card { overflow: visible; z-index: 40; } .contact-info .contact-item:nth-child(1) { --card-accent-start: #1f2937; --card-accent-end: #0f172a; } .contact-info .contact-item:nth-child(2) { --card-accent-start: #334155; --card-accent-end: #1f2937; } .contact-info .contact-item:nth-child(3) { --card-accent-start: #475569; --card-accent-end: #27313f; } .contact-info .contact-item:nth-child(4) { --card-accent-start: #28344a; --card-accent-end: #151c29; } .contact-icon { width: 58px; height: 58px; min-width: 58px; display: inline-flex; align-items: center; justify-content: center; border-radius: 16px; background: linear-gradient(135deg, var(--card-accent-start), var(--card-accent-end)); color: #0a0e1a; font-size: 1.6rem; box-shadow: 0 12px 28px rgba(0,0,0,0.35), 0 10px 24px color-mix(in oklab, var(--card-accent-start) 30%, #000 70%); position: relative; transition: transform .25s ease, box-shadow .25s ease; } .contact-item:hover .contact-icon { transform: translateY(-1px) scale(1.05); } .contact-icon::after { content: ''; position: absolute; inset: -6px; border-radius: inherit; background: linear-gradient(135deg, var(--card-accent-start), var(--card-accent-end)); filter: blur(14px); opacity: .45; z-index: -1; pointer-events: none; } .contact-text h3 { margin-bottom: 6px; color: #ecf3ff; letter-spacing: .3px; font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-weight: 700; } .contact-text p, .contact-text .contact-value { color: #ccd6e5; font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-weight: 500; letter-spacing: 0.2px; } .phone-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; } .phone-item { display: flex; align-items: center; gap: 12px; } .phone-label { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; padding: 4px 11px; border-radius: 999px; background: linear-gradient(135deg, rgba(0,229,255,0.85) 0%, rgba(0,153,255,0.85) 100%); color: #021017; box-shadow: 0 4px 14px rgba(0,229,255,0.22); } .contact-number { font-size: 1.05rem; font-weight: 600; color: #f0f7ff; letter-spacing: 0.3px; } #telefono-principal, #telefono-secundario, #correo-principal { color: #f0f7ff; font-weight: 600; letter-spacing: 0.3px; } .contact-actions { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 10px; } .contact-action { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: 999px; font-weight: 700; font-size: .95rem; color: #0a0e1a; text-decoration: none; border: none; cursor: pointer; transition: transform .2s ease, box-shadow .2s ease, filter .2s ease; box-shadow: 0 6px 18px rgba(0,0,0,0.18); font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; } .contact-action:hover { transform: translateY(-2px); filter: brightness(1.05); } .contact-action:active { transform: translateY(0); } .contact-action.call { background: var(--gradient-secondary); } .contact-action.whatsapp { background: linear-gradient(135deg, #25d366 0%, #128c7e 100%); color: #fff; } .contact-action.whatsapp.split { padding-right: 44px; position: relative; } .contact-action.whatsapp.split::after { content: "\f0dd"; font-family: 'Font Awesome 5 Free'; font-weight: 900; position: absolute; right: 18px; font-size: 0.78rem; opacity: 0.8; transition: transform 0.2s ease; } .contact-action.whatsapp.split[aria-expanded="true"]::after { transform: rotate(180deg); } .contact-action.copy { background: var(--gradient-metallic); } .contact-action.email { background: var(--gradient-accent); color: #fff; } .contact-action.location { background: linear-gradient(135deg, #7dff5a 0%, #00ffd0 100%); color: #021017; } .contact-action.call-ve { background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%); color: #1a2332; } .contact-action i { font-size: 1rem; } .whatsapp-split { position: relative; display: inline-flex; } .whatsapp-picker { position: absolute; top: calc(100% + 10px); left: 0; display: flex; flex-direction: column; gap: 8px; padding: 18px 20px; background: linear-gradient(135deg, rgba(15,20,30,0.98) 0%, rgba(8,12,20,0.98) 100%); border-radius: 16px; border: 1px solid rgba(60,78,102,0.6); box-shadow: 0 18px 42px rgba(0,0,0,0.5); min-width: 230px; opacity: 0; pointer-events: none; transform: translateY(-6px) scale(0.96); transition: opacity 0.22s ease, transform 0.22s ease; z-index: 45; } .whatsapp-picker.visible { opacity: 1; pointer-events: auto; transform: translateY(0) scale(1); } .whatsapp-option { display: flex; align-items: flex-start; gap: 12px; padding: 11px 12px; border-radius: 14px; background: linear-gradient(135deg, rgba(30,39,54,0.85) 0%, rgba(19,26,38,0.85) 100%); border: 1px solid rgba(75,98,132,0.5); color: #f0f5ff; font-weight: 600; font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; cursor: pointer; transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; text-align: left; } .whatsapp-option:hover { background: linear-gradient(135deg, rgba(39,53,74,0.9) 0%, rgba(23,31,44,0.92) 100%); border-color: rgba(122,155,204,0.55); transform: translateY(-2px); box-shadow: 0 12px 26px rgba(0,0,0,0.35); } .whatsapp-option i { font-size: 1.1rem; color: #9fc7ff; } .whatsapp-option span { display: flex; flex-direction: column; gap: 2px; } .whatsapp-option strong { font-size: 0.95rem; letter-spacing: 0.03em; } .whatsapp-option small { font-size: 0.78rem; opacity: 0.75; letter-spacing: 0.04em; } .footer-social-premium { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; } .social-item-premium { width: auto; height: auto; display: inline-flex; align-items: center; justify-content: center; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); padding: 5px; } .social-item-premium:hover { transform: translateY(-5px) scale(1.2); filter: drop-shadow(0 0 10px rgba(67, 97, 238, 0.5)); } .social-item-premium img { width: 38px; height: 38px; object-fit: contain; filter: drop-shadow(0 4px 6px rgba(0,0,0,0.3)); transition: all 0.3s ease; } .social-item-premium:hover img { filter: drop-shadow(0 6px 12px rgba(0,0,0,0.4)); } /* Rediseño Global Contacto */ .contact-global-container { max-width: 1000px; margin: 40px auto 0; display: flex; flex-direction: column; gap: 40px; } .contact-presence-banner { background: rgba(255, 255, 255, 0.03); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 30px; padding: 40px; text-align: center; position: relative; overflow: hidden; } .contact-presence-banner h3 { font-size: 1.2rem; color: #4361ee; text-transform: uppercase; letter-spacing: 3px; font-weight: 800; margin-bottom: 25px; } .countries-row { display: flex; justify-content: center; flex-wrap: wrap; gap: 30px; z-index: 1; position: relative; } .country-item { display: flex; align-items: center; gap: 12px; background: rgba(255, 255, 255, 0.05); padding: 12px 24px; border-radius: 100px; border: 1px solid rgba(255, 255, 255, 0.1); transition: all 0.3s; } .country-item:hover { background: rgba(67, 97, 238, 0.1); border-color: rgba(67, 97, 238, 0.3); transform: translateY(-5px); } .country-item span:first-child { font-size: 1.4rem; } .country-item span:last-child { color: #fff; font-weight: 600; font-size: 1rem; } .contact-channels-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; } .channel-card { background: linear-gradient(145deg, rgba(26, 32, 44, 0.8) 0%, rgba(10, 14, 20, 0.95) 100%); border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 24px; padding: 30px; display: flex; align-items: center; gap: 20px; transition: all 0.4s; text-decoration: none !important; } .channel-card:hover { border-color: rgba(67, 97, 238, 0.4); background: linear-gradient(145deg, rgba(30, 38, 54, 0.9) 0%, rgba(15, 20, 28, 0.98) 100%); transform: scale(1.02); box-shadow: 0 20px 40px rgba(0,0,0,0.3); } .channel-icon { width: 60px; height: 60px; background: rgba(67, 97, 238, 0.1); border-radius: 18px; display: flex; align-items: center; justify-content: center; color: #4361ee; font-size: 1.5rem; transition: all 0.3s; } .channel-card:hover .channel-icon { background: #4361ee; color: #fff; transform: rotate(-10deg); } .channel-info h4 { color: rgba(255, 255, 255, 0.6); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 1.5px; margin-bottom: 4px; } .channel-info p { color: #fff; font-size: 1.15rem; font-weight: 700; margin: 0; letter-spacing: -0.2px; } .contact-footer-email { text-align: center; padding: 30px; background: linear-gradient(90deg, rgba(67, 97, 238, 0.05) 0%, rgba(58, 12, 163, 0.05) 100%); border-radius: 24px; border: 1px dashed rgba(67, 97, 238, 0.3); } .contact-footer-email a { color: #fff; font-size: 1.5rem; font-weight: 800; text-decoration: none; transition: color 0.3s; display: flex; align-items: center; justify-content: center; gap: 15px; } .contact-footer-email a:hover { color: #4361ee; } @media (max-width: 768px) { .contact-presence-banner { padding: 30px 20px; } .country-item { padding: 10px 18px; } .contact-footer-email a { font-size: 1.2rem; } } /* Aparición suave de cards de contacto */ .contact-info .contact-item { animation: fadeInUp 0.7s both; } .contact-info .contact-item:nth-child(1) { animation-delay: 0.05s; } .contact-info .contact-item:nth-child(2) { animation-delay: 0.15s; } .contact-info .contact-item:nth-child(3) { animation-delay: 0.25s; } .contact-info .contact-item:nth-child(4) { animation-delay: 0.35s; } /* Formulario elegante en tema oscuro */ .contact-form { background: linear-gradient(135deg, rgba(12,18,28,0.96) 0%, rgba(8,12,20,0.98) 100%); padding: 38px 28px 32px 28px; border-radius: 18px; box-shadow: 0 12px 32px rgba(0,0,0,0.48), inset 0 1px 0 rgba(255,255,255,0.04); border: 1.5px solid rgba(82,103,132,0.35); max-width: 480px; margin: 0 auto; position: relative; } .contact-form:before { content: ''; position: absolute; top: -18px; left: -18px; right: -18px; bottom: -18px; border-radius: 24px; background: linear-gradient(120deg, rgba(31,43,63,0.55) 0%, rgba(18,26,38,0.35) 100%); z-index: 0; } .contact-form form { position: relative; z-index: 1; } .form-group { margin-bottom: 22px; position: relative; } .form-group label { display: block; margin-bottom: 7px; font-weight: 700; color: #e6f1ff; letter-spacing: 0.2px; } .form-group input, .form-group textarea, .form-group select { width: 100%; padding: 13px 16px 13px 44px; border: 1.5px solid #3a4a5c; border-radius: 8px; font-size: 1.05rem; transition: border-color 0.3s, box-shadow 0.3s; background: #0f141c; color: #cfe3ff; box-shadow: 0 2px 8px rgba(0,0,0,0.25); } .form-group input:focus, .form-group textarea:focus, .form-group select:focus { border-color: var(--secondary); outline: none; box-shadow: 0 0 0 2px #3498db33; } .form-group textarea { min-height: 110px; resize: vertical; } .form-group .input-icon { position: absolute; left: 12px; top: 38px; font-size: 1.18rem; color: var(--secondary); opacity: 0.9; pointer-events: none; } .form-group select { appearance: none; -webkit-appearance: none; -moz-appearance: none; background-image: url('data:image/svg+xml;utf8,<svg fill="%233498db" height="18" viewBox="0 0 24 24" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"/></svg>'); background-repeat: no-repeat; background-position: right 12px center; background-size: 22px 22px; cursor: pointer; } .form-group select option { padding: 8px 12px; font-size: 1rem; background: #0f141c; color: #cfe3ff; } .form-group select option:hover { background-color: var(--secondary); color: white; } .form-group select option:checked { background-color: var(--secondary); color: white; } .contact-form .btn-whatsapp { display: flex; align-items: center; justify-content: center; gap: 12px; font-size: 1.18rem; padding: 16px 0; width: 100%; border-radius: 32px; font-weight: 800; background: linear-gradient(135deg, #1f2937 0%, #101726 100%); color: #e8eff9; box-shadow: 0 12px 28px rgba(0,0,0,0.38); border: 1px solid rgba(78,102,138,0.55); cursor: pointer; transition: all 0.3s; margin-top: 10px; letter-spacing: 0.5px; position: relative; overflow: hidden; } .contact-form .btn-whatsapp i { font-size: 1.7em; animation: whatsapp-bounce 1.2s infinite alternate; color: #9fc7ff; } .contact-form .btn-whatsapp:hover { transform: translateY(-2px) scale(1.01); box-shadow: 0 16px 30px rgba(0,0,0,0.45); } @media (max-width: 576px) { .contact-form { padding: 18px 4vw 18px 4vw; max-width: 99vw; } .form-group label { font-size: 0.98rem; } .contact-form .btn-whatsapp { font-size: 1.05rem; padding: 13px 0; } } /* Footer - DARKEST BLACK EDITION */ footer { background: #000000 !important; color: var(--white); padding: 0; position: relative; overflow: hidden; } .footer-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 40px; margin-bottom: 40px; padding: 70px 0 0 0; position: relative; z-index: 3; } .footer-col h3 { font-size: 1.3rem; margin-bottom: 20px; position: relative; padding-bottom: 10px; color: #f7fafc; letter-spacing: 1px; } .footer-col h3::after { content: ''; position: absolute; width: 40px; height: 2.5px; background: var(--gradient-secondary); bottom: 0; left: 0; border-radius: 2px; } .footer-col p { margin-bottom: 15px; opacity: 0.85; color: #eaf6fb; } .footer-col p.footer-highlight { font-family: 'Playfair Display', serif; font-weight: 600; font-size: 1.1rem; letter-spacing: 0.6px; color: #ffffff; } .footer-links { list-style: none; } .footer-links li { margin-bottom: 10px; } .footer-links a { color: #eaf6fb; text-decoration: none; opacity: 0.85; transition: opacity 0.3s, color 0.3s; font-weight: 500; } .footer-links a:hover { opacity: 1; color: var(--secondary); text-decoration: underline; } .footer-social { display: flex; gap: 15px; margin-top: 20px; } .footer-social a { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 50%; background: rgba(255, 255, 255, 0.13); color: var(--white); transition: all 0.3s, box-shadow 0.3s; text-decoration: none; font-size: 1.25rem; box-shadow: 0 2px 8px rgba(44,62,80,0.10); } .footer-social a:hover { background: var(--secondary); color: #fff; transform: scale(1.13) rotate(-8deg); box-shadow: 0 4px 16px rgba(52,152,219,0.18); } .footer-col .footer-social a { margin-bottom: 0; } .footer-col:last-child p { font-size: 1.01rem; } .footer-bottom { background: #000000 !important; padding: 22px 0 12px 0; border-top: 1.5px solid rgba(255,255,255,0.08); position: relative; z-index: 3; display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 16px; } .footer-bottom p { color: #eaf6fb; opacity: 0.85; font-size: 1.01rem; margin: 0; } .footer-bottom .footer-creator { color: #fff; font-weight: 700; letter-spacing: 0.5px; font-size: 1.08rem; } .footer-bottom .footer-creator a { color: #00ffd0; background: linear-gradient(90deg, #00ffd0 0%, #3498db 100%); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; color: transparent; text-decoration: none; font-weight: 900; transition: color 0.3s, text-shadow 0.3s; text-shadow: 0 2px 12px #00ffd055; position: relative; } .footer-bottom .footer-creator a:hover { color: #fff; background: linear-gradient(90deg, #3498db 0%, #00ffd0 100%); -webkit-background-clip: text; background-clip: text; text-shadow: 0 4px 18px #3498db88; filter: brightness(1.2) drop-shadow(0 0 6px #00ffd0); letter-spacing: 1.5px; } @media (max-width: 768px) { .footer-container { grid-template-columns: 1fr; gap: 18px; padding: 38px 0 0 0; } .footer-col h3 { font-size: 1.08rem; } .footer-bottom p, .footer-bottom .footer-creator { font-size: 0.98rem; } .footer-bottom { padding: 18px 14px 16px 14px; } } /* Responsive */ @media (max-width: 992px) { .header-container { padding: 14px 16px; gap: 16px; position: relative; } .logo { margin-right: 0; } .logo img { height: 64px; } header nav { position: absolute; top: calc(100% + 10px); right: 6px; width: min(220px, 75vw); margin-left: 0; padding: 8px; background: #000000; border: 1px solid #ffffff; border-radius: 14px; box-shadow: 0 14px 32px rgba(0, 0, 0, 0.45); transition: opacity 0.25s ease, transform 0.25s ease; display: flex; flex-direction: column; align-items: stretch; opacity: 0; transform: translateY(-8px) scale(0.98); pointer-events: none; z-index: 1001; } header nav.active { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; } .mobile-menu { margin-left: auto; } .mobile-nav-overlay { background: transparent; } .mobile-nav-overlay.active { display: block; } .hero { background: #000000 !important; } .hero::before { background: none !important; } nav .mobile-profile { display: none; } nav ul { display: flex; flex-direction: column; gap: 2px; padding: 2px; margin: 0; overflow: visible; max-height: none; } nav ul li { margin: 0; width: 100%; } nav ul li a { justify-content: flex-start; align-items: center; gap: 0; font-size: 0.9rem; padding: 6px 10px; border-radius: 8px; color: #eaf6fb !important; background: rgba(255, 255, 255, 0.02); border: 1px solid transparent; box-shadow: none; transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease; } nav ul li a::after { display: none; } nav ul li a:hover, nav ul li a:focus-visible { background: rgba(0, 229, 255, 0.18); border-color: rgba(0, 229, 255, 0.24); color: #ffffff !important; } nav ul li a:active { background: rgba(0, 229, 255, 0.28); } .about-content { flex-direction: column; } .about-text, .about-image { flex: none; width: 100%; } .about-image { margin-top: 30px; } } @media (max-width: 768px) { .header-container { padding: 8px 12px; } .logo { margin-right: auto; } .logo img { height: 48px; } .mobile-menu { order: 2; margin-left: 0; margin-right: 0; } header nav { top: calc(100% + 8px); right: 4px; width: min(200px, 82vw); padding: 8px; background: #000000; border: 1px solid #ffffff; } nav ul { gap: 1px; } nav ul li a { font-size: 0.85rem; padding: 5px 8px; gap: 0; } } @media (max-width: 576px) { .hero h1 { font-size: 2rem; } .hero p { font-size: 1rem; } .section-title h2 { font-size: 2rem; } } .typewriter { display: inline-block; color: var(--primary); font-weight: 700; position: relative; } .typewriter-text { border-right: 2.5px solid var(--secondary); padding-right: 4px; white-space: nowrap; overflow: hidden; animation: blink-cursor 0.7s steps(1) infinite; } @keyframes blink-cursor { 0%, 100% { border-color: var(--secondary); } 50% { border-color: transparent; } } .whatsapp-link { background: linear-gradient(135deg, #25d366 60%, #128c7e 100%) !important; color: #fff !important; box-shadow: 0 2px 12px rgba(37,211,102,0.18); border: 2px solid #25d366; animation: whatsapp-bounce 1.2s infinite alternate; } .whatsapp-link:hover { background: linear-gradient(135deg, #128c7e 60%, #25d366 100%) !important; color: #fff !important; border: 2px solid #128c7e; transform: scale(1.18) rotate(-8deg); box-shadow: 0 4px 18px rgba(37,211,102,0.25); } @keyframes whatsapp-bounce { 0% { transform: translateY(0); } 100% { transform: translateY(-4px) scale(1.10); } } .facebook-link { background: linear-gradient(135deg, #1877f2 60%, #4267b2 100%) !important; color: #fff !important; border: 2px solid #1877f2; box-shadow: 0 2px 12px rgba(24,119,242,0.13); transition: all 0.3s, box-shadow 0.3s; } .facebook-link:hover { background: linear-gradient(135deg, #4267b2 60%, #1877f2 100%) !important; color: #fff !important; border: 2px solid #4267b2; transform: scale(1.18) rotate(-8deg); box-shadow: 0 4px 18px rgba(24,119,242,0.22); } .instagram-link { background: radial-gradient(circle at 30% 110%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285AEB 90%) !important; color: #fff !important; border: 2px solid #d6249f; box-shadow: 0 2px 12px rgba(214,36,159,0.13); transition: all 0.3s, box-shadow 0.3s; } .instagram-link:hover { background: radial-gradient(circle at 30% 110%, #fd5949 0%, #d6249f 45%, #285AEB 90%) !important; color: #fff !important; border: 2px solid #fd5949; transform: scale(1.18) rotate(-8deg); box-shadow: 0 4px 18px rgba(214,36,159,0.22); } .tiktok-link { background: linear-gradient(135deg, #010101 60%, #69C9D0 100%) !important; color: #fff !important; border: 2px solid #010101; box-shadow: 0 2px 12px rgba(105,201,208,0.13); transition: all 0.3s, box-shadow 0.3s; } .tiktok-link:hover { background: linear-gradient(135deg, #69C9D0 60%, #010101 100%) !important; color: #fff !important; border: 2px solid #69C9D0; transform: scale(1.18) rotate(-8deg); box-shadow: 0 4px 18px rgba(105,201,208,0.22); } .telegram-link { background: linear-gradient(135deg, #2aabee 60%, #1f8ecf 100%) !important; color: #fff !important; border: 2px solid #2aabee; box-shadow: 0 2px 12px rgba(42,171,238,0.16); transition: all 0.3s, box-shadow 0.3s; } .telegram-link:hover { background: linear-gradient(135deg, #1f8ecf 60%, #2aabee 100%) !important; color: #fff !important; border: 2px solid #1f8ecf; transform: scale(1.18) rotate(-8deg); box-shadow: 0 4px 18px rgba(42,171,238,0.25); } .youtube-link { background: linear-gradient(135deg, #ff0000 60%, #c4302b 100%) !important; color: #fff !important; border: 2px solid #ff0000; box-shadow: 0 2px 12px rgba(255,0,0,0.13); transition: all 0.3s, box-shadow 0.3s; } .youtube-link:hover { background: linear-gradient(135deg, #c4302b 60%, #ff0000 100%) !important; color: #fff !important; border: 2px solid #c4302b; transform: scale(1.18) rotate(-8deg); box-shadow: 0 4px 18px rgba(255,0,0,0.22); } /* Partners Cards */ .partners-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px; justify-content: center; align-items: stretch; margin-top: 18px; } .partner-card { background: linear-gradient(135deg, #f7fafc 70%, #eaf6fb 100%); border-radius: 22px; box-shadow: 0 6px 32px rgba(44,62,80,0.10), 0 1.5px 8px rgba(39,174,96,0.10); overflow: hidden; display: flex; flex-direction: column; align-items: center; transition: transform 0.35s cubic-bezier(.4,2,.3,1), box-shadow 0.35s; border: 2.5px solid #eaf6fb; position: relative; } .partner-card:hover { transform: translateY(-10px) scale(1.03); box-shadow: 0 16px 40px rgba(44,62,80,0.18), 0 2px 12px rgba(39,174,96,0.13); border: 2.5px solid #27ae60; } .partner-image { width: 100%; background: #fff; display: flex; align-items: center; justify-content: center; padding: 32px 0 18px 0; min-height: 180px; } .partner-image img { max-width: 220px; width: 100%; height: auto; object-fit: contain; border-radius: 16px; box-shadow: 0 2px 12px rgba(44,62,80,0.08); transition: transform 0.4s cubic-bezier(.4,2,.3,1); } .partner-card:hover .partner-image img { transform: scale(1.07) rotate(-2deg); } .partner-info { padding: 18px 24px 28px 24px; width: 100%; display: flex; flex-direction: column; align-items: center; } .partner-title { font-size: 1.18rem; font-weight: 800; color: var(--primary); margin-bottom: 12px; text-align: center; } .partner-features { list-style: none; padding: 0; margin: 0 0 18px 0; color: #2c3e50; font-size: 1.05rem; text-align: left; } .partner-features li { margin-bottom: 6px; display: flex; align-items: center; gap: 7px; } .partner-price { font-size: 2rem; color: #27ae60; font-weight: 900; letter-spacing: 1px; display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 8px; background: #eafbe7; border-radius: 16px; padding: 8px 24px; box-shadow: 0 2px 8px rgba(39,174,96,0.10); } .partner-price i { font-size: 1.5em; color: #27ae60; animation: money-bounce 1.2s infinite alternate; } @media (max-width: 768px) { .partners-grid { grid-template-columns: 1fr; gap: 22px; } .partner-card { max-width: 98vw; margin: 0 auto; } .partner-image { padding: 18px 0 10px 0; min-height: 120px; } .partner-info { padding: 12px 8px 18px 8px; } .partner-title { font-size: 1.05rem; } .partner-price { font-size: 1.3rem; padding: 7px 12px; } } /* Lightbox Socios */ .partner-lightbox { display: none; position: fixed; z-index: 9999; top: 0; left: 0; width: 100vw; height: 100vh; align-items: center; justify-content: center; } body.lightbox-open { overflow: hidden; } .partner-lightbox.active { display: flex; animation: lightbox-fadein 0.3s; } .lightbox-backdrop { position: absolute; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.92); z-index: 1; animation: lightbox-backdrop-fade 0.3s; } .lightbox-content { position: relative; z-index: 2; background: #fff; border-radius: 18px; box-shadow: 0 8px 40px rgba(44,62,80,0.25); padding: 18px 18px 8px 18px; display: flex; flex-direction: column; align-items: center; animation: lightbox-zoom 0.35s cubic-bezier(.4,2,.3,1); max-width: 96vw; max-height: 90vh; } .lightbox-content img { max-width: 92vw; max-height: 82vh; border-radius: 12px; box-shadow: 0 2px 18px rgba(44,62,80,0.18); object-fit: contain; background: #f7fafc; transition: box-shadow 0.3s; } .lightbox-close { position: absolute; top: 8px; right: 18px; font-size: 2.2rem; color: #e74c3c; cursor: pointer; font-weight: 900; z-index: 3; transition: color 0.2s, transform 0.2s; } .lightbox-close:hover { color: #c0392b; transform: scale(1.18) rotate(8deg); } @keyframes lightbox-fadein { from { opacity: 0; } to { opacity: 1; } } @keyframes lightbox-backdrop-fade { from { opacity: 0; } to { opacity: 1; } } @keyframes lightbox-zoom { 0% { transform: scale(0.92) translateY(40px); opacity: 0; } 100% { transform: scale(1) translateY(0); opacity: 1; } } @media (max-width: 768px) { .lightbox-content img { max-width: 96vw; max-height: 75vh; } .lightbox-content { padding: 8px 2vw 4px 2vw; } } /* Project Cards — Espectaculares */ .project-card { position: relative; background: linear-gradient(160deg, rgba(15,20,35,0.98) 0%, rgba(8,12,22,0.95) 100%); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(192,197,206,0.12); border-radius: 20px; overflow: hidden; box-shadow: 0 8px 24px rgba(0,0,0,0.44), 0 2px 6px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.08), inset 0 -1px 0 rgba(0,0,0,0.5); transform-style: preserve-3d; transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); } .project-card:hover { border-color: rgba(0,229,255,0.18); transform: translateY(-4px); box-shadow: 0 16px 36px rgba(0,0,0,0.5), 0 4px 12px rgba(0,0,0,0.24), inset 0 1px 0 rgba(255,255,255,0.08), inset 0 -1px 0 rgba(0,0,0,0.5); } .project-card::before { content: ''; position: absolute; inset: 0; border-radius: 20px; padding: 1px; background: linear-gradient(135deg, rgba(192,197,206,0.4), rgba(192,197,206,0.1), rgba(0,229,255,0.3)); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; z-index: 0; opacity: 0; transition: opacity 0.5s ease; } .project-card:hover::before { opacity: 1; } .project-media { position: relative; z-index: 1; overflow: hidden; display: flex; align-items: stretch; justify-content: center; height: 172px; background: radial-gradient(circle at 30% 20%, rgba(192,197,206,0.06) 0%, transparent 50%), radial-gradient(circle at 70% 80%, rgba(0,229,255,0.04) 0%, transparent 50%), linear-gradient(180deg, rgba(25,30,45,0.5) 0%, rgba(10,14,26,0.8) 100%); border-bottom: 1px solid rgba(255,255,255,0.03); } .project-media .lightbox-trigger { cursor: zoom-in; width: 100%; height: 100%; display:flex; align-items:center; justify-content:center; padding: 0; } .project-img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; box-shadow: none; transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); filter: brightness(0.97) contrast(1.04); } .project-card:hover .project-img { /* Mantener solo el cambio de color */ filter: brightness(1.04) contrast(1.07) saturate(1.08); } .project-badge { position: absolute; top: 12px; left: 12px; z-index: 2; padding: 8px 12px; border-radius: 16px; font-weight: 900; font-size: .78rem; letter-spacing: .4px; background: linear-gradient(135deg, #27ae60, #00e5ff); color: #0a0e1a; border: 1px solid rgba(255,255,255,0.5); box-shadow: 0 6px 16px rgba(0,0,0,0.25); } .project-fav { position: absolute; top: 12px; right: 12px; z-index: 2; width: 38px; height: 38px; border-radius: 50%; display:flex; align-items:center; justify-content:center; color:#ff6b35; background: rgba(255,255,255,0.85); border: 1px solid rgba(0,0,0,0.06); box-shadow: 0 6px 16px rgba(0,0,0,0.25); transition: transform .2s; cursor: pointer; } .project-fav:hover { transform: scale(1.12); } .project-content { position: relative; z-index: 2; padding: 16px 18px 18px 18px; background: linear-gradient(180deg, rgba(15,20,35,0.8) 0%, rgba(8,12,22,0.9) 100%); } .project-title { font-size: 1.08rem; font-weight: 800; color: #ffffff; letter-spacing: 0.2px; text-shadow: 0 2px 8px rgba(0,0,0,0.6), 0 0 20px rgba(192,197,206,0.1); line-height: 1.35; margin-bottom: 0; } .project-desc { margin-top: 10px; color: rgba(192,197,206,0.85); font-size: 0.88rem; line-height: 1.55; display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; white-space: normal; text-shadow: 0 1px 2px rgba(0,0,0,0.3); } .project-card.project-card-expanded .project-desc { -webkit-line-clamp: unset; overflow: visible; } .project-desc-more { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; padding: 0; border: none; background: transparent; color: #8fdcff; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer; transition: color 0.25s ease, transform 0.25s ease; } .project-desc-more:hover, .project-desc-more:focus-visible { color: #d9f7ff; transform: translateX(2px); outline: none; } .project-desc-more i { font-size: 0.72rem; transition: transform 0.25s ease; } .project-card.project-card-expanded .project-desc-more i { transform: rotate(180deg); } .project-desc-more[hidden] { display: none !important; } .project-tags { display:flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; } .project-tag { padding: 6px 10px; border-radius: 999px; font-size: .78rem; font-weight: 800; letter-spacing: .3px; color:#0a0e1a; background: linear-gradient(120deg,#eaf6fb,#cdeffd); border:1px solid rgba(0,229,255,.25); box-shadow: 0 2px 8px rgba(0,0,0,.12); } .project-footer { display:flex; align-items:center; justify-content:flex-start; gap: 10px; margin-top: 16px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,0.05); } .project-actions { display:flex; gap:8px; flex-wrap: wrap; } .project-btn { display:inline-flex; align-items:center; gap:6px; padding: 9px 13px; border-radius: 10px; font-weight: 800; font-size: 0.8rem; letter-spacing: 0.3px; text-decoration:none; transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1); position: relative; overflow: hidden; } .project-btn::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; border-radius: 50%; background: rgba(255,255,255,0.2); transform: translate(-50%, -50%); transition: width 0.4s, height 0.4s; } .project-btn:hover::before { width: 300px; height: 300px; } .project-btn.view { background: linear-gradient(135deg, #00e5ff 0%, #0099ff 100%); color: #000; border: 1px solid rgba(0,229,255,0.3); box-shadow: 0 4px 16px rgba(0,229,255,0.3), inset 0 1px 0 rgba(255,255,255,0.4); } .project-btn.buy { background: linear-gradient(135deg, #c0c5ce 0%, #e8eaed 100%); color: #000; border: 1px solid rgba(192,197,206,0.4); box-shadow: 0 6px 20px rgba(192,197,206,0.25), inset 0 1px 0 rgba(255,255,255,0.6); font-weight: 900; } .project-btn:hover { transform: translateY(-2px); } .project-btn.view:hover { box-shadow: 0 8px 28px rgba(0,229,255,0.45), inset 0 1px 0 rgba(255,255,255,0.6); } .project-btn.buy:hover { box-shadow: 0 10px 32px rgba(192,197,206,0.4), inset 0 1px 0 rgba(255,255,255,0.8); } @media (max-width: 768px){ .project-media{ min-height: 160px; } .project-title{ font-size: 1.06rem; } .project-btn{ padding: 10px 12px; font-size: .95rem; } } @media (max-width: 576px){ #projects-dynamic.partners-grid { gap: 16px; } #projects-dynamic .project-card { border-radius: 18px; } #projects-dynamic .project-media { height: 130px; min-height: 130px; } #projects-dynamic .project-content { padding: 14px 16px 16px 16px; } #projects-dynamic .project-title { font-size: 1rem; } #projects-dynamic .project-desc { font-size: 0.88rem; } #projects-dynamic .project-tag { font-size: .72rem; padding: 5px 8px; } #projects-dynamic .project-badge { font-size: .72rem; padding: 6px 10px; } #projects-dynamic .project-fav { width: 32px; height: 32px; } #projects-dynamic .project-footer { margin-top: 12px; padding-top: 12px; gap: 10px; } #projects-dynamic .project-actions { gap: 8px; } #projects-dynamic .project-btn { padding: 8px 10px; font-size: 0.88rem; } } .payment-methods-flex { display: flex; flex-wrap: wrap; align-items: stretch; justify-content: center; gap: 32px; padding: 20px 0; } .payment-card { background: #ffffff; border-radius: 32px; padding: 40px 30px; width: clamp(300px, 30vw, 360px); display: flex; flex-direction: column; align-items: center; position: relative; overflow: hidden; border: 1px solid rgba(0, 0, 0, 0.05); box-shadow: 0 15px 45px rgba(0, 0, 0, 0.08); transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .payment-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 6px; background: var(--card-color, #4361ee); } .payment-card:hover { transform: translateY(-12px); border-color: var(--card-color, #4361ee); box-shadow: 0 25px 60px rgba(0, 0, 0, 0.12); } .paypal-img-glow { position: relative; display: flex; align-items: center; justify-content: center; margin-bottom: 25px; width: 100%; height: 90px; z-index: 2; } .paypal-img { height: 100%; max-width: 100%; object-fit: contain; z-index: 2; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.05)); transition: transform 0.5s ease; } .payment-card:hover .paypal-img { transform: scale(1.05); } .paypal-img-glow .glow { position: absolute; width: 140px; height: 140px; background: radial-gradient(circle, var(--glow-color, #4361ee) 0%, transparent 75%); filter: blur(25px); opacity: 0.12; z-index: 1; transition: opacity 0.4s ease, transform 0.4s ease; } .payment-card:hover .glow { opacity: 0.2; transform: scale(1.2); } .payment-label { font-size: 1.3rem; font-weight: 800; color: #1a202c; margin-bottom: 25px; letter-spacing: -0.5px; text-align: center; } .payment-details-container { width: 100%; display: flex; flex-direction: column; gap: 12px; } .payment-row { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 16px; padding: 12px 16px; display: flex; align-items: center; gap: 12px; transition: all 0.3s ease; position: relative; } .payment-row:hover { background: #ffffff; border-color: var(--card-color, #4361ee); transform: translateX(5px); box-shadow: 0 4px 12px rgba(0,0,0,0.05); } .payment-row i { font-size: 1.1rem; color: var(--card-color, #4361ee); width: 24px; text-align: center; } .payment-row-content { flex-grow: 1; display: flex; flex-direction: column; } .payment-row-label { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.8px; color: #718096; font-weight: 700; margin-bottom: 1px; } .payment-row-value { font-size: 0.92rem; color: #2d3748; font-weight: 700; word-break: break-all; } .payment-row .copy-btn { background: #edf2f7; border: none; color: #4a5568; width: 32px; height: 32px; border-radius: 10px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; opacity: 0; transform: translateX(10px); } .payment-row:hover .copy-btn { opacity: 1; transform: translateX(0); } .payment-row .copy-btn:hover { background: var(--card-color, #4361ee); color: #ffffff; transform: scale(1.1); } @media (max-width: 768px) { .payment-card { width: 100%; padding: 35px 25px; } .payment-row .copy-btn { opacity: 1; transform: translateX(0); } } @media (max-width: 768px) { .payment-account { font-size: 0.98rem; padding: 10px 8px; } .copy-btn { font-size: 1em; padding: 5px 8px; } } .payment-note { margin-top: 12px; color: #27ae60; font-size: 1.13rem; font-weight: 700; display: flex; align-items: center; gap: 10px; letter-spacing: 0.2px; } .payment-note i { font-size: 1.7em; color: #1877f2; animation: money-bounce 1.2s infinite alternate; } @media (max-width: 768px) { .payment-card { padding: 28px 8vw 22px 8vw; max-width: 99vw; } .paypal-img-glow { width: 98vw; max-width: 320px; height: 90px; } .paypal-img { width: auto; max-width: 100%; height: 100%; object-fit: contain; } .paypal-img-glow .glow { width: 110vw; max-width: 340px; height: 100px; } .payment-label { font-size: 1.08rem; } .payment-account { font-size: 0.98rem; padding: 10px 8px; word-break: break-all; overflow-wrap: anywhere; max-width: 100%; } .payment-note { font-size: 1.01rem; } } .toast-copiado { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(0.9); background: rgba(15, 20, 35, 0.9); backdrop-filter: blur(15px); color: #fff; padding: 16px 32px; border-radius: 20px; border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 20px 40px rgba(0,0,0,0.5); font-size: 1rem; font-weight: 700; display: flex; align-items: center; justify-content: center; gap: 12px; z-index: 999999; opacity: 0; pointer-events: none; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); text-transform: uppercase; letter-spacing: 1px; } .toast-copiado.show { opacity: 1; transform: translate(-50%, -50%) scale(1); pointer-events: auto; } .toast-icon { font-size: 1.4rem; color: #2ecc71; } .btn-ver-proyecto { display: inline-flex; align-items: center; gap: 8px; margin-top: 14px; padding: 12px 28px; background: linear-gradient(90deg, #27ae60 0%, #3498db 100%); color: #fff; font-weight: 800; border-radius: 24px; text-decoration: none; box-shadow: 0 4px 18px #27ae6033; transition: background 0.2s, transform 0.2s; font-size: 1.08rem; letter-spacing: 0.5px; } .btn-ver-proyecto:hover { background: linear-gradient(90deg, #3498db 0%, #27ae60 100%) !important; transform: scale(1.08) rotate(-2deg); box-shadow: 0 8px 24px #27ae6033; } </style> <style id="silicon-ballic-dark"> :root { /* AIRCAN Dark Theme - Enhanced with Logo Colors */ --primary: #1a2332; --secondary: #00e5ff; --accent: #ff6b35; --metallic: #c0c5ce; --metallic-dark: #8b95a1; --light: #0f1622; --dark: #0a0e1a; --text: #cbd5e1; --white: #0f1622; --gradient-primary: linear-gradient(135deg, #1a2332 0%, #2c3e50 100%); --gradient-secondary: linear-gradient(135deg, #00e5ff 0%, #3498db 100%); --gradient-accent: linear-gradient(135deg, #ff6b35 0%, #ff8c42 100%); --gradient-metallic: linear-gradient(135deg, #c0c5ce 0%, #e8eaed 100%); --success: #27ae60; /* Brand green for pricing */ --success-soft: #14321f; /* Soft green-tinted bg for dark theme */ } html, body { background: #000000; color: var(--text); } body { background-color: #000000; } header { background: rgba(26,35,50,0.85); border-bottom: 1px solid rgba(0,229,255,0.15); backdrop-filter: blur(6px); } /* Dark theme: Thinner header */ @media (min-width: 993px) { .header-container { padding: 16px 0 !important; gap: 28px !important; } .logo { gap: 0 !important; } .logo img { height: 56px !important; } header nav { margin-left: auto !important; position: static !important; width: auto !important; padding: 0 !important; background: transparent !important; border: 0 !important; box-shadow: none !important; opacity: 1 !important; transform: none !important; pointer-events: auto !important; } nav ul { gap: 10px !important; padding: 9px 10px !important; border-radius: 999px !important; background: linear-gradient(135deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02)) !important; border: 1px solid rgba(192,197,206,0.16) !important; box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 18px 34px rgba(0,0,0,0.18) !important; backdrop-filter: blur(12px) !important; } nav ul li a { font-size: 0.88rem !important; padding: 12px 16px !important; border-radius: 999px !important; letter-spacing: .14em !important; color: rgba(236,240,245,0.94) !important; } } nav ul li a { color: var(--metallic); } nav ul li a i { color: var(--secondary); } nav ul li a:hover { color: #ffffff; } /* Nav refined: fixed position on hover and premium typography */ nav ul { gap: 36px; } nav ul li a { font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; line-height: 1.2; transition: color .25s ease, background-color .25s ease, box-shadow .25s ease !important; } nav ul li a:hover { transform: translateY(-2.5px) !important; background: rgba(0, 132, 255, 0.2) !important; color: #ffffff !important; box-shadow: 0 0 28px rgba(0, 132, 255, 0.48) !important; border-color: rgba(0, 132, 255, 0.48) !important; } /* Subrayado estable, sin desplazar layout */ nav ul li a::after { bottom: -8px; height: 2px; } /* Fix: keep menu fixed on the right and avoid shifts from typewriter */ @media (min-width: 993px) { .header-container { justify-content: flex-start; } header nav { margin-left: auto; } header nav ul { justify-content: flex-end; } /* reserve width for changing words */ .logo .typewriter { display: none; } } @media (max-width: 992px) { .logo .typewriter { display: none; } /* keep it slightly above menu scale on mobile too */ .logo .typewriter-text { font-size: 1.7rem; border-right-width: 2.5px; } } .hero { background: #04050a; } .hero .container { background: transparent; border: none; box-shadow: none; } .hero h1, .section-title h2 { color: var(--metallic); text-shadow: none; } .hero .subtitle { color: var(--metallic); } .hero .description { color: var(--metallic-dark); } .hero-center-logo { will-change: transform, filter; } /* Dark theme desktop fullscreen */ @media (min-width: 993px) { .hero-center-logo { width: min(70vw, 940px); } } .glitch-title { position: relative; } .glitch-title::before, .glitch-title::after { content: attr(data-text); position: absolute; left: 0; top: 0; color: var(--accent); opacity: 0.12; filter: blur(0.5px); } .glitch-title::after { color: var(--secondary); transform: translate(2px, 2px); opacity: 0.2; } .btn, .btn-ver-proyecto { background: var(--gradient-secondary) !important; color: var(--dark) !important; border: 1px solid rgba(0,229,255,0.3) !important; box-shadow: 0 4px 18px rgba(0,229,255,0.25) !important; } .btn:hover, .btn-ver-proyecto:hover { background: var(--gradient-accent) !important; transform: translateY(-3px) scale(1.04); box-shadow: 0 6px 25px rgba(255,107,53,0.3) !important; } section { background: transparent; } #team, #payment-methods, #contact { background: transparent !important; } /* Mantener colores ORIGINALES de las cards (equipo, servicios, proyectos, pagos, contacto) */ /* Se eliminan overrides oscuros para que prevalezca el estilo original definido anteriormente */ /* Contacto: títulos (Dirección, Teléfono, Correo, Horario) en blanco */ #contact .contact-item h3 { color: #ffffff !important; } footer { background: #000000 !important; } /* Components dark overrides: mantener About oscuro si gustó; quitar overrides que alteraban cards */ .about-section { background: radial-gradient(circle at 8% 12%, rgba(125, 255, 90, 0.16) 0%, rgba(0, 0, 0, 0) 52%), linear-gradient(145deg, #020304 0%, #04070b 48%, #080c12 100%) !important; border: 1px solid rgba(125,255,90,0.22) !important; box-shadow: 0 32px 70px rgba(0,0,0,0.6) !important; } .about-headline { color: #f5f7fa !important; } .about-headline .about-headline-highlight { color: var(--neon-green) !important; } .about-intro { color: rgba(235,239,244,0.86) !important; } .about-feature h3 { color: #ffffff !important; } .about-feature p { color: rgba(225,231,236,0.8) !important; } .visually-hidden-seo { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } /* Matrix canvas */ #matrix-canvas { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: -1; pointer-events: none; opacity: 0.22; } </style> <style id="section-themes"> /* Section theme utilities for alternating light/dark bands - DARKEST BLACK EDITION */ .theme-dark { background: #000000 !important; background: linear-gradient(120deg, #000000 0%, #000000 100%) !important; background-color: #000000 !important; /* Purest black possible */ } .theme-dark .section-title h2 { color: var(--metallic); } .theme-dark .section-title p { color: var(--metallic-dark); } .theme-light { background: #000000 !important; background: linear-gradient(120deg, #000000 0%, #000000 100%) !important; background-color: #000000 !important; /* Purest black possible */ } .theme-light .section-title h2 { color: var(--metallic); } .theme-light .section-title p { color: #666; } /* Make About section switchable to light when its parent is theme-light - DARKEST BLACK OVERRIDE */ .theme-light .about-section { background: inherit !important; border: inherit !important; box-shadow: inherit !important; } .theme-light .about-section .about-headline, .theme-light .about-section .about-intro, .theme-light .about-section .about-feature h3, .theme-light .about-section .about-feature p { color: inherit !important; } /* Ensure themed sections override previous transparent backgrounds with DARKEST BLACK */ #team.theme-light { background: linear-gradient(120deg, #000000 0%, #000000 100%) !important; } #payment-methods.theme-light { background: linear-gradient(120deg, #000000 0%, #000000 100%) !important; } #contact.theme-dark { background: linear-gradient(120deg, #000000 0%, #000000 100%) !important; } /* Keep desktop hero using its fullscreen image (no background) */ @media (min-width: 993px) { .hero.theme-dark { background: none !important; } } </style> <!-- AIRCAN 2026 Login Modal Styles --> <style> .ac-modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.4); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); z-index: 9999; display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); } .ac-modal-overlay.active { opacity: 1; pointer-events: auto; } .ac-modal { background: rgba(13, 17, 23, 0.85); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 32px; padding: 45px 40px; width: 100%; max-width: 440px; box-shadow: 0 40px 80px -20px rgba(0, 0, 0, 0.8), inset 0 0 0 1px rgba(255, 255, 255, 0.05); transform: translateY(40px) scale(0.95); transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); position: relative; overflow: hidden; text-align: center; } .ac-modal-overlay.active .ac-modal { transform: translateY(0) scale(1); } .ac-modal::after { content: ''; position: absolute; top: -100px; right: -100px; width: 250px; height: 250px; background: radial-gradient(circle, rgba(0, 229, 255, 0.08) 0%, transparent 70%); z-index: 0; pointer-events: none; } .ac-modal-close { position: absolute; top: 25px; right: 25px; width: 36px; height: 36px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: #a0aec0; cursor: pointer; transition: all 0.3s; z-index: 10; } .ac-modal-close:hover { background: rgba(255, 59, 48, 0.1); color: #ff3b30; border-color: rgba(255, 59, 48, 0.2); transform: rotate(90deg); } .ac-modal-header { margin-bottom: 30px; position: relative; z-index: 1; } .ac-modal-header .logo-only { width: 100px; height: auto; margin: 0 auto; display: block; } .ac-modal-header .logo-only img { width: 100%; height: auto; object-fit: contain; filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3)); } .ac-input-group { margin-bottom: 24px; position: relative; z-index: 1; text-align: left; } .ac-input-group label { display: block; color: rgba(255,255,255,0.6); font-size: 0.72rem; font-weight: 700; margin-bottom: 10px; letter-spacing: 1px; text-transform: uppercase; } .ac-input-wrapper { position: relative; } .ac-input-wrapper i.input-icon { position: absolute; left: 18px; top: 50%; transform: translateY(-50%); color: #4a5568; font-size: 1.1rem; transition: all 0.3s; } .ac-password-toggle { position: absolute; right: 18px; top: 50%; transform: translateY(-50%); color: #fff; cursor: pointer; font-size: 1rem; transition: all 0.3s; opacity: 0.7; } .ac-password-toggle:hover { opacity: 1; transform: translateY(-50%) scale(1.1); } .ac-input { width: 100%; background: rgba(255, 255, 255, 0.03); border: 1.5px solid rgba(255, 255, 255, 0.05); border-radius: 16px; padding: 16px 50px 16px 52px; color: #fff; font-size: 1rem; transition: all 0.3s; outline: none; box-sizing: border-box; font-family: inherit; } .ac-input:focus { border-color: rgba(255,255,255,0.2); background: rgba(255, 255, 255, 0.06); box-shadow: 0 0 20px rgba(255, 255, 255, 0.05); } .ac-input:focus + i.input-icon { color: #fff; } .ac-btn { width: 100%; padding: 18px; border-radius: 16px; border: none; background: #ffffff; color: #0d1117; font-weight: 800; font-size: 1rem; letter-spacing: 0.5px; cursor: pointer; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); position: relative; overflow: hidden; z-index: 1; display: flex; justify-content: center; align-items: center; gap: 12px; margin-top: 15px; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); } .ac-btn:hover { transform: translateY(-3px); box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3); background: #f8f9fa; } .ac-btn:active { transform: translateY(0); } .ac-error { background: rgba(255, 59, 48, 0.1); border: 1px solid rgba(255, 59, 48, 0.2); color: #ff3b30; padding: 14px 18px; border-radius: 12px; font-size: 0.85rem; margin-bottom: 25px; display: none; animation: ac-shake 0.5s cubic-bezier(.36,.07,.19,.97) both; text-align: center; position: relative; z-index: 1; font-weight: 500; } @keyframes ac-shake { 10%, 90% { transform: translate3d(-1px, 0, 0); } 20%, 80% { transform: translate3d(2px, 0, 0); } 30%, 50%, 70% { transform: translate3d(-4px, 0, 0); } 40%, 60% { transform: translate3d(4px, 0, 0); } } .ac-loader { display: none; width: 20px; height: 20px; border: 3px solid rgba(13, 17, 23, 0.1); border-top-color: #0d1117; border-radius: 50%; animation: ac-spin 0.8s linear infinite; } @keyframes ac-spin { to { transform: rotate(360deg); } } /* Logo Transition Animation */ #nav-logo-anim { opacity: 0; transform: translateY(-20px) scale(0.9) translateZ(0); transition: opacity 0.6s cubic-bezier(0.87, 0, 0.13, 1), transform 0.6s cubic-bezier(0.87, 0, 0.13, 1); pointer-events: none; will-change: transform, opacity; } #nav-logo-anim.show-nav-logo { opacity: 1; transform: translateY(0) scale(1) translateZ(0); pointer-events: auto; } #hero-logo-anim { transition: opacity 0.5s cubic-bezier(0.87, 0, 0.13, 1), transform 0.7s cubic-bezier(0.87, 0, 0.13, 1), filter 0.6s ease; will-change: transform, opacity, filter; transform: translateZ(0); } #hero-logo-anim.hide-hero-logo { opacity: 0; transform: translateY(-120px) scale(0.4) translateZ(0); filter: blur(8px); pointer-events: none; } </style> </head> <body> <canvas id="matrix-canvas"></canvas> <!-- Header --> <header> <div class="container header-container"> <div class="logo" id="nav-logo-anim"> <span class="logo-mark"> <img src="<?= htmlspecialchars($logo) ?>" alt="<?= htmlspecialchars($siteTitle) ?>"> </span> </div> <div class="mobile-menu"> <i class="fas fa-bars"></i> </div> <nav id="main-nav"> <ul> <li><a href="#home"><span class="nav-link-label">Inicio</span></a></li> <li><a href="#services"><span class="nav-link-label">Servicios</span></a></li> <li><a href="#clients"><span class="nav-link-label">Sistemas</span></a></li> <li><a href="#clientes-satisfechos"><span class="nav-link-label">Clientes</span></a></li> <li><a href="#team"><span class="nav-link-label">Equipo</span></a></li> <li><a href="#contact"><span class="nav-link-label">Contacto</span></a></li> <li><a href="#" class="nav-cta" onclick="openAircanLogin(event)"><i class="bi bi-shield-lock"></i><span class="nav-link-label">Acceder</span></a></li> <!-- Botón instalar (solo visible en móvil cuando hay prompt disponible) --> <li id="install-nav-item"><button id="install-btn-mobile" class="install-btn install-btn--nav" hidden><span class="install-btn__icon"><i class="fas fa-download"></i></span><span class="install-btn__content"><span class="install-btn__label">Instalar app</span><span class="install-btn__eyebrow">Acceso móvil instantáneo</span></span></button></li> </ul> </nav> </div> </header> <div class="mobile-nav-overlay"></div> <!-- Hero Section --> <section class="hero theme-dark" id="home"> <div class="hero-glow-scene" aria-hidden="true"> <canvas class="hero-glow-canvas"></canvas> <div class="hero-ambient-orb hero-ambient-orb-left"></div> <div class="hero-ambient-orb hero-ambient-orb-right"></div> </div> <div class="container"> <div class="hero-stage" data-aos="zoom-in" data-aos-duration="1200"> <h1 class="visually-hidden-seo"><?= htmlspecialchars($seoHeadline) ?></h1> <div class="hero-logo-lockup" id="hero-logo-anim"> <img class="hero-center-logo" src="<?= htmlspecialchars(makeAbsoluteUrl('public/assets/img/PNG.png', $absoluteBaseUrl)) ?>" alt="<?= htmlspecialchars($seoHeadline) ?>" fetchpriority="high" /> </div> </div> </div> </section> <!-- About Us --> <section id="about" class="theme-light"> <div class="container about-section"> <div class="about-content"> <div class="about-text" data-aos="fade-right"> <h2 class="about-headline">Potencia . Automatiza . Lidera .</h2> <p class="about-intro">En Aircan somos el socio que transforma ideas de negocio en plataformas digitales dominantes. Desde diagnóstico estratégico hasta despliegue y soporte, convertimos cada proceso en una experiencia fluida y medible.</p> <div class="about-features"> <div class="about-feature"> <h3>Arquitectura end-to-end</h3> <p>Conectamos sistemas heredados, APIs modernas y canales de venta en un ecosistema unificado. Cada módulo se integra con tus flujos actuales y escala contigo sin interrupciones.</p> </div> <div class="about-feature"> <h3>Experiencias que inspiran acción</h3> <p>Creamos interfaces elegantes y responsivas que eliminan fricciones. Equipos de ventas, operaciones y dirección colaboran sobre el mismo tablero, con datos confiables y en tiempo real.</p> </div> <!-- <div class="about-feature"> <h3>Resultados sostenidos</h3> <p>Automatizamos tareas críticas, liberamos talento y activamos analítica predictiva para impulsar decisiones. Tu empresa gobierna cada etapa del ciclo digital con precisión y velocidad.</p> </div> --> </div> </div> <div class="about-image" data-aos="fade-left" data-aos-delay="200"> <?php $aboutMedia = trim($ajustesMap['about_media'] ?? ''); if (empty($aboutMedia)) { $aboutMedia = 'images/fondo.png'; } $aboutExt = strtolower(pathinfo(parse_url($aboutMedia, PHP_URL_PATH), PATHINFO_EXTENSION)); $aboutIsVideo = in_array($aboutExt, ['mp4', 'webm']); $aboutSrc = (strpos($aboutMedia, 'http') === 0) ? $aboutMedia : rtrim(BASE_URL, '/') . '/' . ltrim($aboutMedia, '/'); ?> <?php if ($aboutIsVideo): ?> <video src="<?= htmlspecialchars($aboutSrc) ?>" muted loop autoplay playsinline preload="none" class="img-fluid" style="width:100%;height:auto;" poster="<?= htmlspecialchars(rtrim(BASE_URL, '/') . '/' . ltrim($heroBgVideoDesktop, '/')) ?>"></video> <?php else: ?> <img src="<?= htmlspecialchars($aboutSrc) ?>" alt="Panorama tecnológico Aircan" loading="lazy" class="img-fluid" style="width:100%;height:auto;"> <?php endif; ?> </div> </div> </div> </section> <!-- Services --> <section id="services" class="theme-dark"> <div class="container"> <div class="services-heading"> <div class="section-title" data-aos="fade-down"> <h2>Qué te ofrecemos</h2> </div> <div class="services-nav" aria-label="Controles del carrusel de servicios"> <button type="button" id="services-prev" aria-label="Ver servicios anteriores"><i class="fas fa-chevron-left"></i></button> <button type="button" id="services-next" aria-label="Ver servicios siguientes"><i class="fas fa-chevron-right"></i></button> </div> </div> <div class="services-carousel" aria-live="polite"> <div id="services-track-wrapper" class="services-track-wrapper" data-aos="zoom-in"> <div id="services-track" class="services-track"> <?php if (empty($servicios)): ?> <div style="text-align:center;color:#aab4c3;font-size:1.15rem;padding:52px 0;min-width:100%;animation:fadeIn 0.6s;">😮 Próximamente espectacular selección de servicios.</div> <?php else: ?> <?php foreach ($servicios as $idx => $s): ?> <?php $imagenValida = !empty($s['imagen']) && trim($s['imagen']) != ''; $imgSrc = $imagenValida ? 'public/assets/uploads/servicios/' . htmlspecialchars($s['imagen']) : 'images/aircan6.png'; ?> <article class="service-card" data-aos="fade-up" data-aos-delay="<?= $idx * 150 ?>"> <div class="service-media"> <img loading="lazy" src="<?= $imgSrc ?>" alt="<?= htmlspecialchars($s['nombre']) ?>"> </div> <div class="service-content"> <h3 class="service-title"><?= htmlspecialchars($s['nombre']) ?></h3> <p class="service-description"><?= htmlspecialchars($s['descripcion'] ?: 'Diseñamos experiencias digitales enfocadas en resultados medibles y escalables.') ?></p> <div class="service-footer"> <?php $waNumber = $ajustesMap['whatsapp_number'] ?? ''; $waUrl = !empty($waNumber) ? normalizeSocialUrl('whatsapp', $waNumber) : '#'; $srvName = $s['nombre']; $waText = urlencode("Hola equipo de *Aircan* 👋\n\nEstoy interesado en adquirir el servicio:\n✨ *{$srvName}*\n\nMe gustaría recibir más información al respecto. ¡Gracias!"); $href = $waUrl !== '#' ? $waUrl . '?text=' . $waText : '#'; ?> <a href="<?= htmlspecialchars($href) ?>" target="<?= $waUrl !== '#' ? '_blank' : '_self' ?>" class="btn-comprar-servicio"> <i class="fas fa-shopping-cart"></i> Comprar </a> </div> </div> </article> <?php endforeach; ?> <?php endif; ?> </div> </div> </div> </div> </section> <!-- CTA Trial Section --> <section class="cta-trial-section"> <div class="container"> <h2 class="cta-trial-heading" data-aos="fade-down" data-aos-duration="1000">Comience hoy mismo su sistema y sitio web con solo el 50%</h2> <div class="cta-trial-actions"> <?php $waNumber = $ajustesMap['whatsapp_number'] ?? ''; $waUrl = !empty($waNumber) ? normalizeSocialUrl('whatsapp', $waNumber) : '#'; $waTextCta = urlencode("Hola equipo de *Aircan* 👋\n\nQuiero empezar hoy mismo mi proyecto aprovechando la promoción del *50%*. ¡Me gustaría recibir más información para comenzar!"); $hrefCta = $waUrl !== '#' ? $waUrl . '?text=' . $waTextCta : '#'; ?> <a href="<?= htmlspecialchars($hrefCta) ?>" target="<?= $waUrl !== '#' ? '_blank' : '_self' ?>" class="cta-trial-button" data-aos="zoom-in" data-aos-delay="200">Empezar</a> <p class="cta-trial-note" data-aos="fade-up" data-aos-delay="400">Termina de cancelar cuando tengas el sistema.</p> </div> </div> </section> <!-- CTA Mockup Section --> <section class="cta-mockup-section"> <div class="container"> <div class="mockup-visuals" data-aos="fade-right"> <div class="visuals-stage"> <?php $showcaseLaptop = $ajustesMap['showcase_laptop'] ?? 'images/mockups/pc.png'; $showcasePhone = $ajustesMap['showcase_phone'] ?? 'images/mockups/Mockup_telefono.png'; $laptopSrc = (strpos($showcaseLaptop, 'http') === 0) ? $showcaseLaptop : BASE_URL . '/' . $showcaseLaptop; $phoneSrc = (strpos($showcasePhone, 'http') === 0) ? $showcasePhone : BASE_URL . '/' . $showcasePhone; ?> <img src="<?= htmlspecialchars($laptopSrc) ?>" alt="Vista en laptop del sistema Aircan" class="laptop-img" data-aos="fade-right" data-aos-delay="100"> <img src="<?= htmlspecialchars($phoneSrc) ?>" alt="Vista móvil del sistema Aircan" class="phone-img" data-aos="fade-right" data-aos-delay="300"> </div> </div> <div class="cta-mockup-copy" data-aos="fade-left" data-aos-delay="200"> <h3 class="cta-mockup-title" data-aos="fade-left" data-aos-delay="100">Experiencia premium en cada pantalla</h3> <p class="cta-mockup-text" data-aos="fade-left" data-aos-delay="200">Tus clientes ven tu solución tal como la entregamos: dashboards fluidos en laptop, acciones intuitivas en móvil y una identidad digital consistente en todos los puntos de contacto.</p> <div class="cta-mockup-bullets"> <span data-aos="fade-left" data-aos-delay="300">UX optimizada para equipos de ventas, gerencia y clientes finales.</span> <span data-aos="fade-left" data-aos-delay="400">Componentes modulares con microinteracciones y tiempos de carga ultrarrápidos.</span> <span data-aos="fade-left" data-aos-delay="500">Integraciones listas para CRM, pasarelas de pago y analítica avanzada.</span> <span data-aos="fade-left" data-aos-delay="600">Implementación acompañada por soporte estratégico 24/7.</span> </div> </div> </div> </section> <!-- PC Showcase Section --> <section class="pc-showcase-section"> <div class="container"> <div class="pc-showcase-image" data-aos="zoom-in" data-aos-delay="200"> <?php $showcasePcFull = $ajustesMap['showcase_pc_full'] ?? 'images/PC.png'; $pcSrc = (strpos($showcasePcFull, 'http') === 0) ? $showcasePcFull : BASE_URL . '/' . $showcasePcFull; ?> <img src="<?= htmlspecialchars($pcSrc) ?>" alt="PC Showcase - Aircan Technology" loading="lazy"> </div> </div> </section> <!-- Clients (Sistemas) --> <section id="clients" class="theme-dark" data-aos="fade-up"> <div class="container"> <div class="section-title" data-aos="fade-down"> <h2>Sistemas AirCan</h2> </div> <div id="projects-dynamic" class="partners-grid"> <?php if (empty($sistemas)): ?> <div style="text-align:center;color:#aaa;font-size:1.2rem;padding:32px 0;animation:fadeIn 1s;">🚀 ¡Pronto verás nuestros sistemas más destacados aquí!</div> <?php else: ?> <?php foreach ($sistemas as $idx => $p): ?> <?php $imgSrcProject = !empty($p['imagen']) ? 'public/assets/uploads/sistemas/' . htmlspecialchars($p['imagen']) : 'images/empresa1.png'; ?> <div class="project-card" data-aos="flip-up" data-aos-delay="<?= $idx * 50 ?>" data-aos-duration="450" data-aos-offset="60" data-aos-easing="ease-out"> <div class="project-media"> <div class="lightbox-trigger" data-img="<?= $imgSrcProject ?>"> <img class="project-img" src="<?= $imgSrcProject ?>" alt="<?= htmlspecialchars($p['nombre']) ?>"> </div> </div> <div class="project-content"> <h3 class="project-title"><?= htmlspecialchars($p['nombre']) ?></h3> <p class="project-desc"><?= htmlspecialchars($p['descripcion'] ?: '') ?></p> <button type="button" class="project-desc-more" hidden aria-expanded="false"> <span>Leer más</span> <i class="fas fa-chevron-down"></i> </button> <div class="project-footer"> <div class="project-actions"> <?php if (!empty($p['link'])): ?> <a href="<?= htmlspecialchars($p['link']) ?>" target="_blank" class="project-btn view"><i class='fas fa-rocket'></i> Ver</a> <?php endif; ?> <?php $waNumber = $ajustesMap['whatsapp_number'] ?? ''; $waUrl = !empty($waNumber) ? normalizeSocialUrl('whatsapp', $waNumber) : '#'; $sysName = $p['nombre']; $waTextSys = urlencode("Hola equipo de *Aircan* 👋\n\nEstoy interesado en adquirir el sistema:\n🚀 *{$sysName}*\n\nMe gustaría conocer más detalles sobre la implementación y funciones. ¡Gracias!"); $hrefSys = $waUrl !== '#' ? $waUrl . '?text=' . $waTextSys : '#'; ?> <a href="<?= htmlspecialchars($hrefSys) ?>" target="<?= $waUrl !== '#' ? '_blank' : '_self' ?>" class="project-btn buy"><i class="fas fa-shopping-cart"></i> Comprar</a> </div> </div> </div> </div> <?php endforeach; ?> <?php endif; ?> </div> </div> <!-- Lightbox para imágenes de socios --> <div id="partner-lightbox" class="partner-lightbox"> <div class="lightbox-backdrop"></div> <div class="lightbox-content"> <span class="lightbox-close" title="Cerrar">×</span> <img src="" alt="Socio" id="lightbox-img"> </div> </div> </section> <!-- Clientes Satisfechos --> <section id="clientes-satisfechos" class="theme-light" style="padding:70px 0;" data-aos="fade-up"> <div class="container"> <div class="section-title" data-aos="fade-down"> <h2>Clientes</h2> </div> <div class="clientes-ribbon full-bleed"> <div class="clientes-marquee" id="clientes-marquee" aria-label="Carrusel de clientes" role="region"> <div class="marquee-track" id="clientes-marquee-track" aria-label="Logotipos de clientes"></div> </div> </div> </div> </section> <!-- Team --> <section id="team" class="theme-light" data-aos="fade-up"> <div class="container"> <div class="section-title" style="margin-bottom: 50px; text-align: center;" data-aos="fade-down"> <h2>Nuestro Equipo</h2> <p style="color: #666; margin-top: 15px; font-size: 1.1rem;">Conoce al talentoso equipo detrás de Aircan</p> </div> <div class="team-grid-container"> <?php if (!empty($equipoCompleto)): foreach ($equipoCompleto as $idx => $empleado): $fotoUrl = resolveEmpleadoPhoto($empleado['foto'] ?? ''); $nombre = htmlspecialchars($empleado['nombre']); $cargo = htmlspecialchars($empleado['cargo'] ?: 'Miembro del equipo'); $emailEquipo = trim((string)($empleado['email'] ?? '')); if ($emailEquipo === '') { $emailEquipo = trim((string)($empleado['usuario_email'] ?? '')); } $delay = ($idx * 100) + 100; $socialIcons = [ 'email' => ['icon' => 'bi-envelope-fill', 'color' => '#EA4335'], 'facebook' => ['icon' => 'bi-facebook', 'color' => '#1877F2'], 'instagram' => ['icon' => 'bi-instagram', 'color' => '#E4405F'], 'twitter' => ['icon' => 'bi-twitter-x', 'color' => '#000000'], 'linkedin' => ['icon' => 'bi-linkedin', 'color' => '#0A66C2'], 'tiktok' => ['icon' => 'bi-tiktok', 'color' => '#000000'], 'youtube' => ['icon' => 'bi-youtube', 'color' => '#FF0000'], 'whatsapp' => ['icon' => 'bi-whatsapp', 'color' => '#25D366'], 'github' => ['icon' => 'bi-github', 'color' => '#333333'], 'pagina_web' => ['icon' => 'bi-globe2', 'color' => '#4361ee'] ]; $socialTitles = [ 'email' => 'Gmail', 'whatsapp' => 'WhatsApp', 'facebook' => 'Facebook', 'instagram' => 'Instagram', 'twitter' => 'X', 'linkedin' => 'LinkedIn', 'github' => 'GitHub', 'youtube' => 'YouTube', 'tiktok' => 'TikTok', 'pagina_web' => 'Sitio web' ]; $socialLinks = []; $iconPathBase = 'public/assets/img/redes/'; foreach ($socialIcons as $field => $iconClass) { $rawValue = trim((string)($empleado[$field] ?? '')); if ($rawValue === '') { continue; } $iconFile = ''; switch($field) { case 'email': $iconFile = 'gmail.png'; break; case 'facebook': $iconFile = 'facebook.png'; break; case 'instagram': $iconFile = 'instagram.png'; break; case 'twitter': $iconFile = 'twitterx.png'; break; case 'linkedin': $iconFile = 'linkedin.webp'; break; case 'tiktok': $iconFile = 'tiktok.png'; break; case 'youtube': $iconFile = 'youtube.webp'; break; case 'whatsapp': $iconFile = 'whatsapp.png'; break; case 'github': $iconFile = 'guthub.png'; break; case 'pagina_web': $iconFile = 'www.png'; break; } $socialLinks[] = [ 'url' => $field === 'email' ? 'mailto:' . $rawValue : normalizeSocialUrl($field, $rawValue), 'icon_url' => $iconPathBase . $iconFile, 'title' => $socialTitles[$field] ]; } ?> <div class="team-card" data-aos="flip-left" data-aos-delay="<?= $delay ?>"> <div class="team-card-inner"> <div class="team-card-front"> <div class="team-img"> <img src="<?= htmlspecialchars($fotoUrl) ?>" alt="<?= $nombre; ?>" loading="lazy" onerror="this.src='images/default-team.png'"> </div> <h3><?= $nombre ?></h3> <?php $nivelClase = htmlspecialchars($empleado['nivel'] ?? 'bronze'); $nivelLabel = ucfirst($nivelClase); ?> <p class="position <?= $nivelClase ?>" title="Miembro <?= $nivelLabel ?>"><?= $cargo ?></p> <div class="social-hover"> <span>Conectar</span> <div class="emp-social-row"> <?php foreach ($socialLinks as $social): ?> <a href="<?= htmlspecialchars($social['url']) ?>" target="_blank" rel="noopener" class="emp-social-icon-img" title="<?= htmlspecialchars($social['title']) ?>"> <img src="<?= htmlspecialchars($social['icon_url']) ?>" alt="<?= htmlspecialchars($social['title']) ?>" style="width: 24px; height: 24px; object-fit: contain;"> </a> <?php endforeach; ?> </div> </div> </div> </div> </div> <?php endforeach; else: ?> <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: #999;"> <p>No hay miembros del equipo configurados aún.</p> </div> <?php endif; ?> </div> </div> </section> <!-- Métodos de Pago --> <section id="payment-methods" class="theme-light" style="padding: 70px 0 60px 0;" data-aos="fade-up"> <div class="container"> <div class="section-title" data-aos="fade-down"> <h2>Métodos de Pago</h2> </div> <div class="payment-methods-flex"> <?php if (empty($metodosPago)): ?> <div style="text-align:center;color:#aaa;font-size:1.1rem;padding:20px 0;width:100%;">🚀 ¡Pronto verás nuestros métodos de pago aquí!</div> <?php else: ?> <?php foreach ($metodosPago as $idx => $m): $delay = ($idx * 150) + 100; $color = !empty($m['color_hex']) ? $m['color_hex'] : '#4361ee'; $logoPath = !empty($m['logo']) ? BASE_URL . '/public/assets/uploads/metodos_pago/' . $m['logo'] : 'images/paypal2.png'; ?> <div class="payment-card" style="--card-color: <?= $color ?>;" data-aos="zoom-in-up" data-aos-delay="<?= $delay ?>"> <div class="paypal-img-glow" style="--glow-color: <?= $color ?>;"> <img src="<?= $logoPath ?>" alt="<?= htmlspecialchars($m['nombre']) ?>" class="paypal-img"> <div class="glow"></div> </div> <div class="payment-details-container"> <?php if (!empty($m['identificacion'])): ?> <div class="payment-row"> <i class="fas fa-id-card"></i> <div class="payment-row-content"> <span class="payment-row-label">Identificación</span> <span class="payment-row-value"><?= htmlspecialchars($m['identificacion']) ?></span> </div> </div> <?php endif; ?> <?php if (!empty($m['n_cuenta'])): ?> <div class="payment-row"> <i class="fas fa-hashtag"></i> <div class="payment-row-content"> <span class="payment-row-label">Número de Cuenta</span> <span class="payment-row-value" id="pago-cuenta-<?= $m['id'] ?>"><?= htmlspecialchars($m['n_cuenta']) ?></span> </div> <button class="copy-btn generic-copy" data-target="pago-cuenta-<?= $m['id'] ?>" title="Copiar"><i class="fas fa-copy"></i></button> </div> <?php endif; ?> <?php if (!empty($m['email'])): ?> <div class="payment-row"> <i class="fas fa-envelope"></i> <div class="payment-row-content"> <span class="payment-row-label">Correo Electrónico</span> <span class="payment-row-value" id="pago-email-<?= $m['id'] ?>"><?= htmlspecialchars($m['email']) ?></span> </div> <button class="copy-btn generic-copy" data-target="pago-email-<?= $m['id'] ?>" title="Copiar"><i class="fas fa-copy"></i></button> </div> <?php endif; ?> <?php if (!empty($m['telefono'])): ?> <div class="payment-row"> <i class="fas fa-phone-alt"></i> <div class="payment-row-content"> <span class="payment-row-label">Teléfono</span> <span class="payment-row-value" id="pago-tel-<?= $m['id'] ?>"><?= htmlspecialchars($m['telefono']) ?></span> </div> <button class="copy-btn generic-copy" data-target="pago-tel-<?= $m['id'] ?>" title="Copiar"><i class="fas fa-copy"></i></button> </div> <?php endif; ?> </div> </div> <?php endforeach; ?> <?php endif; ?> </div> <div style="display:flex;justify-content:center;margin-top:40px;" data-aos="fade-up" data-aos-delay="600"> <button id="btn-comprobante" class="btn-premium-report"> <div class="btn-premium-content"> <div class="icon-box"> <i class="fas fa-receipt"></i> </div> <div class="text-box"> <span class="main-text">Reportar Comprobante</span> <span class="sub-text">Validación prioritaria en minutos</span> </div> <div class="arrow-box"> <i class="fas fa-chevron-right"></i> </div> </div> <div class="btn-premium-bg"></div> </button> </div> </div> <!-- Estilos Premium --> <style> .btn-premium-report { position: relative; background: #ffffff; color: #1a202c; border: none; padding: 2px; /* Espacio para el borde gradiente */ border-radius: 24px; cursor: pointer; transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); box-shadow: 0 15px 35px rgba(0,0,0,0.06), 0 5px 15px rgba(0,0,0,0.04); overflow: hidden; display: flex; align-items: center; text-decoration: none; min-width: 320px; } .btn-premium-report::before { content: ''; position: absolute; inset: 0; background: linear-gradient(90deg, #4361ee, #4cc9f0, #4361ee); background-size: 200% 100%; animation: gradient-flow 3s linear infinite; border-radius: 24px; opacity: 0.3; transition: opacity 0.5s ease; } .btn-premium-report:hover::before { opacity: 1; } @keyframes gradient-flow { 0% { background-position: 0% 50%; } 100% { background-position: 200% 50%; } } .btn-premium-content { position: relative; z-index: 2; background: #ffffff; border-radius: 22px; padding: 16px 28px; display: flex; align-items: center; gap: 20px; width: 100%; transition: background 0.5s ease; } .btn-premium-report:hover .btn-premium-content { background: rgba(255, 255, 255, 0.95); } .btn-premium-report .icon-box { width: 54px; height: 54px; background: rgba(67, 97, 238, 0.08); border-radius: 16px; display: flex; align-items: center; justify-content: center; transition: all 0.5s ease; } .btn-premium-report:hover .icon-box { background: #4361ee; transform: scale(1.1) rotate(-5deg); } .btn-premium-report .icon-box i { font-size: 1.6rem; color: #4361ee; transition: color 0.5s ease; } .btn-premium-report:hover .icon-box i { color: #ffffff; } .btn-premium-report .text-box { display: flex; flex-direction: column; flex-grow: 1; } .btn-premium-report .main-text { font-size: 1.2rem; font-weight: 800; color: #1a202c; letter-spacing: -0.3px; line-height: 1.2; } .btn-premium-report .sub-text { font-size: 0.85rem; color: #718096; font-weight: 600; margin-top: 2px; } .btn-premium-report .arrow-box { opacity: 0.3; transform: translateX(-10px); transition: all 0.5s ease; } .btn-premium-report:hover .arrow-box { opacity: 1; transform: translateX(0); color: #4361ee; } /* Modal Premium Redesign */ .modal-premium-overlay { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(10, 14, 26, 0.85); backdrop-filter: blur(16px); z-index: 99999; display: none; align-items: center; justify-content: center; padding: 20px; transition: all 0.4s ease; } .modal-premium-card { background: #ffffff; border-radius: 24px; width: 100%; max-width: 380px; position: relative; box-shadow: 0 40px 100px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.1); overflow: hidden; animation: premium-slide-up 0.5s cubic-bezier(0.19, 1, 0.22, 1); } @keyframes premium-slide-up { from { transform: translateY(40px) scale(0.96); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } } .modal-premium-header { padding: 30px 25px 10px; text-align: center; background: linear-gradient(to bottom, #fcfdfe, #ffffff); } .modal-premium-header h3 { font-size: 1.4rem; font-weight: 800; color: #1a202c; margin: 0; letter-spacing: -0.8px; } .modal-premium-header p { color: #718096; margin-top: 6px; font-weight: 500; font-size: 0.85rem; } .modal-premium-body { padding: 0 25px 25px; } .form-premium-group { margin-bottom: 15px; } .form-premium-label { display: block; font-size: 0.72rem; font-weight: 700; color: #a0aec0; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 1.2px; } .input-wrapper { position: relative; display: flex; align-items: center; } .input-wrapper i { position: absolute; left: 15px; color: #cbd5e0; font-size: 0.9rem; transition: color 0.3s ease; } .input-premium { width: 100%; background: #f8fafc; border: 1.5px solid #edf2f7; border-radius: 12px; padding: 12px 15px 12px 42px; font-size: 0.9rem; color: #2d3748; font-family: inherit; transition: all 0.3s ease; } .input-premium:focus { background: #ffffff; border-color: #4361ee; box-shadow: 0 0 0 4px rgba(67, 97, 238, 0.08); outline: none; } .input-premium:focus + i { color: #4361ee; } .upload-premium-zone { position: relative; border: 1.5px dashed #cbd5e0; border-radius: 16px; padding: 22px 15px; text-align: center; background: #fbfcfe; cursor: pointer; transition: all 0.3s ease; } .upload-premium-zone:hover { border-color: #4361ee; background: rgba(67, 97, 238, 0.01); } .upload-premium-zone i { font-size: 2rem; color: #a0aec0; margin-bottom: 8px; transition: all 0.3s ease; } .upload-premium-zone:hover i { color: #4361ee; transform: translateY(-3px); } .upload-premium-zone.uploaded { border-color: #48bb78; background: rgba(72, 187, 120, 0.05); border-style: solid; box-shadow: 0 0 15px rgba(72, 187, 120, 0.1); } .upload-premium-zone.uploaded i { color: #48bb78; transform: scale(1.1); } .upload-premium-zone.uploaded p { color: #2f855a !important; } .btn-premium-submit { width: 100%; background: #4361ee; color: #ffffff; font-weight: 700; font-size: 0.95rem; padding: 14px; border: none; border-radius: 12px; cursor: pointer; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); box-shadow: 0 10px 25px rgba(67, 97, 238, 0.2); display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 10px; } .btn-premium-submit:hover { transform: translateY(-3px); box-shadow: 0 15px 35px rgba(67, 97, 238, 0.3); background: #3751d4; } .btn-premium-close { position: absolute; top: 15px; right: 15px; width: 32px; height: 32px; border-radius: 50%; border: none; background: rgba(247, 250, 252, 0.8); color: #718096; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 1rem; transition: all 0.3s ease; z-index: 10; } .btn-premium-close:hover { background: #edf2f7; color: #1a202c; transform: rotate(90deg); } .status-success-premium { animation: premium-pop 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } @keyframes premium-pop { 0% { transform: scale(0.9); opacity: 0; } 100% { transform: scale(1); opacity: 1; } } /* Smoke Click Effect Premium - Refined V2 */ .smoke-particle { position: fixed; pointer-events: none; border-radius: 50%; background: radial-gradient(circle, rgba(67, 97, 238, 0.15) 0%, transparent 75%); filter: blur(20px); z-index: 99999; animation: smoke-float 2.5s cubic-bezier(0.2, 0, 0.3, 1) forwards; } @keyframes smoke-float { 0% { transform: translate(-50%, -50%) scale(0.2); opacity: 0; } 20% { opacity: 0.3; } 100% { transform: translate(-50%, -120%) scale(3.5); opacity: 0; } } /* Code Guardian Overlay */ .ac-guardian-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at center, #0d1117 0%, #000 100%); z-index: 100000; display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: all 0.6s cubic-bezier(0.19, 1, 0.22, 1); text-align: center; color: #fff; padding: 40px; } .ac-guardian-overlay.active { opacity: 1; pointer-events: auto; } .ac-guardian-content { max-width: 800px; transform: scale(0.9); transition: all 0.8s cubic-bezier(0.19, 1, 0.22, 1); } .ac-guardian-overlay.active .ac-guardian-content { transform: scale(1); } .ac-guardian-icon { font-size: 4rem; color: #4361ee; margin-bottom: 30px; filter: drop-shadow(0 0 20px rgba(67, 97, 238, 0.4)); } .ac-guardian-title { font-size: 3.5rem; font-weight: 900; letter-spacing: -2px; margin-bottom: 20px; text-transform: uppercase; line-height: 1; } .ac-guardian-quote { font-size: 1.4rem; color: #a0aec0; font-weight: 500; margin-bottom: 40px; line-height: 1.6; } .ac-guardian-btn { background: #fff; color: #000; padding: 18px 40px; border-radius: 100px; font-weight: 800; font-size: 1.1rem; text-decoration: none !important; transition: all 0.3s; display: inline-flex; align-items: center; gap: 12px; box-shadow: 0 20px 40px rgba(0,0,0,0.4); border: none; cursor: pointer; } .ac-guardian-btn:hover { transform: translateY(-5px); box-shadow: 0 30px 60px rgba(0,0,0,0.6); background: #f0f0f0; } @media (max-width: 768px) { .ac-guardian-title { font-size: 2.2rem; } .ac-guardian-quote { font-size: 1.1rem; } } </style> <!-- Modal Premium --> <div id="modal-comprobante" class="modal-premium-overlay"> <div class="modal-premium-card"> <button id="cerrar-modal-comprobante" class="btn-premium-close"> <i class="fas fa-times"></i> </button> <div class="modal-premium-header"> <h3>Reportar Pago</h3> <p>Sube tu comprobante para validación</p> </div> <div class="modal-premium-body"> <form id="form-comprobante-v2" enctype="multipart/form-data"> <div class="form-premium-group"> <label class="form-premium-label">Nombre Completo</label> <div class="input-wrapper"> <input type="text" name="nombre" class="input-premium" placeholder="Ej: Juan Pérez" required> <i class="fas fa-user"></i> </div> </div> <div class="form-premium-group"> <label class="form-premium-label">Descripción</label> <div class="input-wrapper"> <textarea name="descripcion" class="input-premium" placeholder="Motivo del pago (Opcional)" style="min-height: 85px; resize: none; padding-left: 42px; padding-top: 12px;"></textarea> <i class="fas fa-comment-alt" style="top: 15px;"></i> </div> </div> <div class="form-premium-group"> <label class="form-premium-label">Comprobante</label> <div class="upload-premium-zone" id="drop-zone"> <input type="file" name="comprobante" id="file-input" required accept="image/*" style="position:absolute; inset:0; opacity:0; cursor:pointer; z-index:2;"> <i class="fas fa-cloud-upload-alt"></i> <p id="file-name" style="margin:0; font-weight:600; color:#4a5568; font-size: 0.9rem;">Seleccionar archivo</p> <span style="font-size:0.7rem; color:#a0aec0; margin-top:4px; display:block;">JPG, PNG, WEBP (Máx. 10MB)</span> </div> </div> <button type="submit" class="btn-premium-submit"> <span>Enviar Reporte</span> <i class="fas fa-arrow-right"></i> </button> </form> <div id="status-message" style="display:none; margin-top:15px; padding:12px; border-radius:12px; text-align:center; font-weight:700; font-size: 0.85rem;"></div> </div> </div> </div> </section> <!-- Toast Copiado --> <div id="toast-copiado" class="toast-copiado" style="display:none;"> <span class="toast-icon">✅</span> <span class="toast-text">¡copiado al portapapeles!</span> </div> <!-- Contact --> <section id="contact" class="theme-dark" style="padding: 100px 0;"> <div class="container"> <div class="section-title" data-aos="fade-down"> <h2 style="font-size: 2.5rem; font-weight: 800; letter-spacing: -1px;">Contacto Global</h2> <p style="color: #a0aec0; max-width: 600px; margin: 15px auto;">Soluciones tecnológicas sin fronteras. Estamos listos para llevar tu visión al siguiente nivel.</p> </div> <div class="contact-global-container"> <!-- Banner de Presencia --> <div class="contact-presence-banner" data-aos="fade-up"> <h3>Presencia Operativa</h3> <div class="countries-row"> <div class="country-item"> <span>🇻🇪</span> <span>Venezuela</span> </div> <div class="country-item"> <span>🇨🇴</span> <span>Colombia</span> </div> <div class="country-item"> <span>🇳🇮</span> <span>Nicaragua</span> </div> <div class="country-item"> <span>🇭🇳</span> <span>Honduras</span> </div> </div> </div> <!-- Canales de Atención --> <div class="contact-channels-grid"> <a href="https://wa.me/573505849143?text=Hola%20Aircan" target="_blank" class="channel-card" data-aos="fade-right" data-aos-delay="100"> <div class="channel-icon"> <i class="fab fa-whatsapp"></i> </div> <div class="channel-info"> <h4>Línea Directa 01</h4> <p>+57 350 5849143</p> </div> </a> <a href="https://wa.me/584147340563?text=Hola%20Aircan" target="_blank" class="channel-card" data-aos="fade-left" data-aos-delay="200"> <div class="channel-icon"> <i class="fab fa-whatsapp"></i> </div> <div class="channel-info"> <h4>Línea Directa 02</h4> <p>+58 414 7340563</p> </div> </a> </div> <!-- Email Final --> <div class="contact-footer-email" data-aos="zoom-in" data-aos-delay="300"> <a href="mailto:inf@aircan.me"> <i class="fas fa-envelope-open-text"></i> inf@aircan.me </a> </div> </div> </div> </section> <!-- Footer --> <footer> <div class="container"> <div class="footer-container"> <div class="footer-col"> <h3>Aircan</h3> <p class="footer-highlight">Un sitio web convierte tu visión en realidad</p> <div class="footer-social-premium"> <?php $redesConfig = [ 'whatsapp_link' => ['icon' => 'whatsapp.png', 'title' => 'WhatsApp'], 'facebook_link' => ['icon' => 'facebook.png', 'title' => 'Facebook'], 'instagram_link' => ['icon' => 'instagram.png', 'title' => 'Instagram'], 'twitter_link' => ['icon' => 'twitterx.png', 'title' => 'Twitter/X'], 'tiktok_link' => ['icon' => 'tiktok.png', 'title' => 'TikTok'], 'youtube_link' => ['icon' => 'youtube.webp', 'title' => 'YouTube'], 'linkedin_link' => ['icon' => 'linkedin.webp', 'title' => 'LinkedIn'], 'github_link' => ['icon' => 'guthub.png', 'title' => 'GitHub'], 'web_link' => ['icon' => 'www.png', 'title' => 'Sitio Web'], 'gmail_link' => ['icon' => 'gmail.png', 'title' => 'Gmail'], ]; foreach ($redesConfig as $clave => $info): $link = $ajustesMap[$clave] ?? ''; if (!empty($link)): ?> <a href="<?= htmlspecialchars($link) ?>" target="_blank" title="<?= $info['title'] ?>" class="social-item-premium"> <img src="<?= BASE_URL ?>/public/assets/img/redes/<?= $info['icon'] ?>" alt="<?= $info['title'] ?>"> </a> <?php endif; endforeach; ?> </div> </div> <div class="footer-col"> <h3>Sistemas</h3> <ul class="footer-links"> <li><a href="#services">Punto de Venta (POS)</a></li> <li><a href="#services">Inventarios y Facturación</a></li> <li><a href="#services">ERP para Pymes</a></li> <li><a href="#services">CRM de Ventas</a></li> <li><a href="#services">Ecommerce</a></li> <li><a href="#services">Integraciones API</a></li> <li><a href="#services">Desarrollo a Medida</a></li> <li><a href="#services">Soporte y Mantenimiento</a></li> <li><a href="#services">Sitios web</a></li> <li><a href="#services">Dominios</a></li> <li><a href="#services">Tiendas en línea</a></li> <li><a href="#services">Programación</a></li> </ul> </div> <div class="footer-col"> <h3>Recursos</h3> <ul class="footer-links"> <li><a href="#services">Creador de sitios web con frameworks</a></li> <li><a href="#services">Inteligencia de diseño</a></li> <li><a href="#services">Servicios</a></li> <li><a href="#services">Facturación</a></li> <li><a href="#services">Contenido y membresías</a></li> <li><a href="#services">Pagos</a></li> <li><a href="#services">Herramientas de marketing</a></li> <li><a href="#services">Sitios biográficos</a></li> <li><a href="#services">Generador de nombres comerciales</a></li> <li><a href="#services">Creador de logotipos</a></li> </ul> </div> </div> </div> <div class="footer-bottom"> <p>© 2022 Aircan. Todos los derechos reservados.</p> <!-- <span class="footer-creator">Creado por: <a href="https://aircan.me" target="_blank">Aircan</a></span> --> <button id="install-btn-desktop" class="install-btn install-btn--small install-btn--footer" title="Instalar app" hidden> <span class="install-btn__icon"><i id="install-btn-desktop-icon" class="fas fa-download"></i></span> <span class="install-btn__content"> <span id="install-btn-desktop-label" class="install-btn__label">Instalar app</span> <span id="install-btn-desktop-eyebrow" class="install-btn__eyebrow">Llévala a tu pantalla de inicio</span> </span> </button> </div> </footer> <div id="ios-install-modal" class="ios-install-modal" hidden> <div class="ios-install-sheet" role="dialog" aria-modal="true" aria-labelledby="ios-install-title"> <div class="ios-install-badge"><i class="fab fa-apple"></i><span id="ios-install-badge-text">Instalación en iPhone y iPad</span></div> <h3 id="ios-install-title">Agrega Aircan a tu pantalla de inicio</h3> <p id="ios-install-copy">Instálala en segundos para abrirla como una app, con acceso rápido y experiencia de pantalla completa.</p> <ol class="ios-install-steps"> <li> <span class="ios-install-step-num">1</span> <span class="ios-install-step-copy"><strong>Abre el menú Compartir</strong><span id="ios-install-step-share">Toca el icono de compartir de Safari en la parte inferior o superior del navegador.</span></span> </li> <li> <span class="ios-install-step-num">2</span> <span class="ios-install-step-copy"><strong>Selecciona Agregar a pantalla de inicio</strong><span>Confirma el nombre de la app y continúa.</span></span> </li> <li> <span class="ios-install-step-num">3</span> <span class="ios-install-step-copy"><strong>Presiona Agregar</strong><span>Cuando la abras desde tu inicio, el botón desaparecerá automáticamente.</span></span> </li> </ol> <div class="ios-install-actions"> <button type="button" id="ios-install-close" class="ios-install-action ios-install-action--secondary">Ahora no</button> <button type="button" id="ios-install-done" class="ios-install-action ios-install-action--primary">Ya la instalé</button> </div> </div> </div> <script> const fetchWithTimeout = (url, options = {}, timeout = 8000) => { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeout); return fetch(url, { ...options, signal: controller.signal, headers: { 'Accept': 'application/json', ...(options.headers || {}) } }).finally(() => clearTimeout(timer)); }; // Mobile Menu Toggle const mobileMenuBtn = document.querySelector('.mobile-menu'); const nav = document.querySelector('nav'); const mobileOverlay = document.querySelector('.mobile-nav-overlay'); const body = document.body; const toggleMobileNav = (forceState) => { if (!nav || !mobileOverlay || !mobileMenuBtn) return; const shouldOpen = typeof forceState === 'boolean' ? forceState : !nav.classList.contains('active'); if (shouldOpen) { nav.classList.add('active'); mobileOverlay.classList.add('active'); body.classList.add('nav-open'); mobileMenuBtn.setAttribute('aria-expanded', 'true'); mobileMenuBtn.setAttribute('aria-label', 'Cerrar menú de navegación'); } else { nav.classList.remove('active'); mobileOverlay.classList.remove('active'); body.classList.remove('nav-open'); mobileMenuBtn.setAttribute('aria-expanded', 'false'); mobileMenuBtn.setAttribute('aria-label', 'Abrir menú de navegación'); } }; if (mobileMenuBtn) { mobileMenuBtn.setAttribute('aria-controls', 'main-nav'); mobileMenuBtn.setAttribute('aria-expanded', 'false'); mobileMenuBtn.addEventListener('click', () => toggleMobileNav()); } if (mobileOverlay) { mobileOverlay.addEventListener('click', () => toggleMobileNav(false)); } // Close menu when clicking on a link const navLinks = document.querySelectorAll('nav ul li a'); navLinks.forEach(link => { link.addEventListener('click', () => { toggleMobileNav(false); }); }); // Close on escape key document.addEventListener('keydown', (event) => { if (event.key === 'Escape' && nav && nav.classList.contains('active')) { toggleMobileNav(false); } }); // Smooth scrolling for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { const target = document.querySelector(this.getAttribute('href')); if (!target) return; e.preventDefault(); target.scrollIntoView({ behavior: 'smooth' }); }); }); // Ensure mobile hero video remains playing const mobileHeroVideo = document.querySelector('.hero-video-mobile'); if (mobileHeroVideo) { const ensureMobileVideoPlaying = () => { if (mobileHeroVideo.paused || mobileHeroVideo.readyState < 3) { mobileHeroVideo.play().catch(() => {}); } }; ['pause', 'stalled', 'waiting', 'ended'].forEach(eventName => { mobileHeroVideo.addEventListener(eventName, ensureMobileVideoPlaying); }); document.addEventListener('visibilitychange', () => { if (!document.hidden) { setTimeout(ensureMobileVideoPlaying, 120); } }); window.addEventListener('focus', () => setTimeout(ensureMobileVideoPlaying, 120)); window.addEventListener('touchstart', ensureMobileVideoPlaying, { passive: true }); ensureMobileVideoPlaying(); } // Utilidad: igualar alturas de tarjetas para que no haya scroll interno function equalizeFlipCards() { const cards = document.querySelectorAll('.flip-card'); cards.forEach(card => { const inner = card.querySelector('.flip-card-inner'); const front = card.querySelector('.flip-card-front'); const back = card.querySelector('.flip-card-back'); if (!inner || !front || !back) return; // reset front.style.height = 'auto'; back.style.height = 'auto'; inner.style.height = 'auto'; card.style.height = 'auto'; // compute const maxH = Math.max(front.scrollHeight, back.scrollHeight); front.style.height = maxH + 'px'; back.style.height = maxH + 'px'; inner.style.height = maxH + 'px'; card.style.height = maxH + 'px'; }); } // Flip Card Servicios Mejorado (listeners básicos) document.querySelectorAll('.services-grid .flip-card').forEach(card => { const btns = card.querySelectorAll('.flip-btn'); if (btns[0]) btns[0].addEventListener('click', () => { card.classList.add('flipped'); equalizeFlipCards(); }); if (btns[1]) btns[1].addEventListener('click', () => { card.classList.remove('flipped'); equalizeFlipCards(); }); }); window.addEventListener('resize', () => { equalizeFlipCards(); // Re-inicializar carrusel en cambios de ancho clearTimeout(window.__servicesCarouselResizeTO); window.__servicesCarouselResizeTO = setTimeout(() => { if (typeof initServiciosCarousel === 'function') initServiciosCarousel(); }, 200); }); // Lightbox para imágenes de socios const lightbox = document.getElementById('partner-lightbox'); const lightboxImg = document.getElementById('lightbox-img'); if (lightbox && lightbox.parentElement !== document.body) { document.body.appendChild(lightbox); } const openLightbox = (imgSrc) => { if (!lightbox || !lightboxImg) return; lightboxImg.src = imgSrc; lightbox.classList.add('active'); lightbox.dataset.scrollY = String(window.scrollY || document.documentElement.scrollTop || 0); document.body.classList.add('lightbox-open'); }; const closeLightbox = () => { if (!lightbox || !lightboxImg) return; lightbox.classList.remove('active'); lightboxImg.src = ''; document.body.classList.remove('lightbox-open'); const storedScroll = parseInt(lightbox.dataset.scrollY || '0', 10) || 0; delete lightbox.dataset.scrollY; window.scrollTo({ top: storedScroll, behavior: 'instant' in window ? 'instant' : 'auto' }); }; const lightboxClose = document.querySelector('.lightbox-close'); const lightboxBackdrop = document.querySelector('.lightbox-backdrop'); if (lightbox && lightboxImg && lightboxClose && lightboxBackdrop) { document.querySelectorAll('.lightbox-trigger').forEach(el => { el.addEventListener('click', function() { const imgSrc = this.getAttribute('data-img'); openLightbox(imgSrc); }); }); lightboxClose.addEventListener('click', closeLightbox); lightboxBackdrop.addEventListener('click', closeLightbox); } document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && lightbox && lightbox.classList.contains('active')) { closeLightbox(); } }); // Utilidad: Carrusel móvil auto-deslizante para servicios function initServiciosCarousel() { const grid = document.getElementById('services-dynamic'); if (!grid) return; // Limpieza previa si existe if (grid._carouselCleanup) { grid._carouselCleanup(); grid._carouselCleanup = null; } // Carrusel deshabilitado por preferencia: mostrar cards completas con espacio. // Si en el futuro quieres reactivarlo, descomenta la implementación previa. grid._carouselCleanup = () => {}; return; } // Las funciones renderServiciosHome y renderProyectosHome han sido reemplazadas por renderizado directo en PHP para mejor SEO y velocidad. // --- CLIENTES SATISFECHOS DINÁMICOS EN HOME --- function renderClientesSatisfechos() { const marquee = document.getElementById('clientes-marquee'); const track = document.getElementById('clientes-marquee-track'); if (!marquee || !track) return; // Usamos la nueva ruta del controlador para obtener los logos fetchWithTimeout('<?= BASE_URL ?>/clientesLogos/list') .then(res => res.ok ? res.json() : Promise.reject(new Error('No se pudieron cargar los clientes'))) .then(clientes => { // Limpiar track.classList.remove('marquee-animate'); track.style.removeProperty('--marquee-duration'); track.innerHTML = ''; if (!Array.isArray(clientes) || !clientes.length) { marquee.innerHTML = '<div class="marquee-empty">Aún no hay clientes publicados.</div>'; return; } // Preparar fuentes de logos (con fallback seguro) e incluir video si existe const sources = clientes.map(c => ({ src: (c.logo && String(c.logo).trim()) ? c.logo : 'images/aircan.png', name: c.nombre || 'Cliente', video: (c.video_url && String(c.video_url).trim()) ? String(c.video_url).trim() : '' })); // Calculamos cuántas veces repetir los logos para que el carrusel sea fluido // Incluso con pocos logos (como 2), los repetiremos para llenar la pantalla y que el loop sea infinito let repeatSet = 1; if (sources.length > 0 && sources.length < 10) { repeatSet = Math.ceil(10 / sources.length); // Aseguramos al menos 10 elementos por set } // Duplicamos el set completo (x2) para el efecto de loop infinito con translateX(-50%) for (let k = 0; k < 2; k++) { for (let r = 0; r < repeatSet; r++) { sources.forEach(item => { const el = document.createElement('div'); el.className = 'logo-item'; const imgHtml = `<img loading="lazy" src="${item.src}" alt="${item.name}">`; if (item.video) { const href = `video.html?vid=${encodeURIComponent(item.video)}&t=${encodeURIComponent(item.name)}`; el.innerHTML = `<a class=\"logo-link\" data-video=\"1\" href=\"${href}\" target=\"_blank\" rel=\"noopener\" title=\"Ver video de ${item.name}\" aria-label=\"Ver video de ${item.name}\">${imgHtml}<span class=\"play-badge\"><i class=\"fa-solid fa-play\"></i></span></a>`; } else { el.innerHTML = imgHtml; } track.appendChild(el); }); } } // Esperar a que el DOM pinte para medir ancho y calcular duración requestAnimationFrame(() => { const total = track.scrollWidth; const half = total / 2; // El loop es siempre a la mitad gracias al doble set const speedPxPerSec = 70; // Velocidad suave y profesional const duration = Math.max(half / speedPxPerSec, 20); track.style.setProperty('--marquee-duration', `${duration}s`); // Forzar reflow void track.offsetWidth; track.classList.add('marquee-animate'); }); }) .catch(() => { marquee.innerHTML = '<div class="marquee-empty">No se pudieron cargar los clientes.</div>'; }); } // Animaciones de aparición const styleFade = document.createElement('style'); styleFade.innerHTML = ` @keyframes fadeInUp { 0% { opacity: 0; transform: translateY(40px); } 100% { opacity: 1; transform: translateY(0); } } `; document.head.appendChild(styleFade); // Llamar al cargar la página // Inicializar componentes renderizados por PHP function initPHPRendered() { // Servicios const track = document.getElementById('services-track'); if (track) { const toggleServicesNav = (disabled) => { const prev = document.getElementById('services-prev'); const next = document.getElementById('services-next'); [prev, next].forEach(btn => { if (btn) btn.disabled = !!disabled; }); }; const syncServicesNav = () => { const prev = document.getElementById('services-prev'); const next = document.getElementById('services-next'); if (!track || !prev || !next) return; const maxScroll = track.scrollWidth - track.clientWidth - 4; const tolerance = 6; prev.disabled = track.scrollLeft <= tolerance; next.disabled = track.scrollLeft >= maxScroll - tolerance; }; const centerServicesScroll = (targetIndex) => { const cards = Array.from(track.querySelectorAll('.service-card')); if (!cards.length) return; const safeIndex = Math.max(0, Math.min(targetIndex, cards.length - 1)); const card = cards[safeIndex]; const trackRect = track.getBoundingClientRect(); const cardRect = card.getBoundingClientRect(); const offset = (cardRect.left + cardRect.right) / 2 - (trackRect.left + trackRect.right) / 2; track.scrollBy({ left: offset, behavior: 'smooth' }); setTimeout(syncServicesNav, 400); }; const attachServiciosCompra = () => { // Los botones de servicios ahora envían directamente a WhatsApp }; // Navegación const prev = document.getElementById('services-prev'); const next = document.getElementById('services-next'); if (prev && next) { const getCenteredIndex = () => { const cards = Array.from(track.querySelectorAll('.service-card')); if (!cards.length) return 0; const trackRect = track.getBoundingClientRect(); const centerX = (trackRect.left + trackRect.right) / 2; let closest = 0, bestDist = Infinity; cards.forEach((card, idx) => { const rect = card.getBoundingClientRect(); const cardCenter = (rect.left + rect.right) / 2; const dist = Math.abs(cardCenter - centerX); if (dist < bestDist) { bestDist = dist; closest = idx; } }); return closest; }; prev.addEventListener('click', () => centerServicesScroll(Math.max(0, getCenteredIndex() - 1))); next.addEventListener('click', () => centerServicesScroll(Math.min(track.querySelectorAll('.service-card').length - 1, getCenteredIndex() + 1))); } track.addEventListener('scroll', syncServicesNav); new ResizeObserver(() => { toggleServicesNav(track.scrollWidth <= track.clientWidth + 4); syncServicesNav(); }).observe(track); attachServiciosCompra(); syncServicesNav(); } // Proyectos const projectGrid = document.getElementById('projects-dynamic'); if (projectGrid) { projectGrid.querySelectorAll('.lightbox-trigger').forEach(el => { el.addEventListener('click', function() { openLightbox(this.getAttribute('data-img')); }); }); projectGrid.querySelectorAll('.btn-carrito').forEach(btn => { btn.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); mostrarModalCompra(this.getAttribute('data-id'), this.getAttribute('data-nombre')); }); }); projectGrid.querySelectorAll('.project-card').forEach(card => { const desc = card.querySelector('.project-desc'); const toggle = card.querySelector('.project-desc-more'); if (!desc || !toggle) return; const updateToggleVisibility = () => { const isOverflowing = desc.scrollHeight > desc.clientHeight + 6; toggle.hidden = !isOverflowing && !card.classList.contains('project-card-expanded'); }; requestAnimationFrame(updateToggleVisibility); window.addEventListener('resize', updateToggleVisibility); toggle.addEventListener('click', () => { const expanded = card.classList.toggle('project-card-expanded'); toggle.setAttribute('aria-expanded', expanded ? 'true' : 'false'); const label = toggle.querySelector('span'); if (label) { label.textContent = expanded ? 'Leer menos' : 'Leer más'; } requestAnimationFrame(updateToggleVisibility); if (typeof AOS !== 'undefined') { AOS.refreshHard(); } }); }); } if (typeof AOS !== 'undefined') AOS.refresh(); } initPHPRendered(); renderClientesSatisfechos(); // Copiar correo Paypal con toast flotante const copyPaypalBtn = document.getElementById('copy-paypal'); if (copyPaypalBtn) { copyPaypalBtn.addEventListener('click', function(e) { e.preventDefault(); const correoEl = document.getElementById('correo-paypal'); const toast = document.getElementById('toast-copiado'); const correo = correoEl ? correoEl.innerText : ''; if (!correo || !toast) return; navigator.clipboard.writeText(correo).then(() => { toast.classList.add('show'); toast.style.display = 'flex'; setTimeout(() => { toast.classList.remove('show'); toast.style.display = 'none'; }, 1500); }); }); } // Copiar cuentas Banpro con toast flotante (si existen) (function(){ const btnUsd = document.getElementById('copy-banpro-usd'); if (btnUsd) { btnUsd.addEventListener('click', function(e) { e.preventDefault(); const cuenta = document.getElementById('banpro-usd').innerText; navigator.clipboard.writeText(cuenta).then(() => { const toast = document.getElementById('toast-copiado'); toast.classList.add('show'); toast.querySelector('.toast-text').textContent = '¡Cuenta USD copiada!'; toast.style.display = 'flex'; setTimeout(() => { toast.classList.remove('show'); toast.style.display = 'none'; toast.querySelector('.toast-text').textContent = '¡copiado al portapapeles!'; }, 1500); }); }); } const btnNio = document.getElementById('copy-banpro-nio'); if (btnNio) { btnNio.addEventListener('click', function(e) { e.preventDefault(); const cuenta = document.getElementById('banpro-nio').innerText; navigator.clipboard.writeText(cuenta).then(() => { const toast = document.getElementById('toast-copiado'); toast.classList.add('show'); toast.querySelector('.toast-text').textContent = '¡Cuenta NIO copiada!'; toast.style.display = 'flex'; setTimeout(() => { toast.classList.remove('show'); toast.style.display = 'none'; toast.querySelector('.toast-text').textContent = '¡copiado al portapapeles!'; }, 1500); }); }); } })(); (function(){ const copyUalaBtn = document.getElementById('copy-uala'); if (copyUalaBtn) { copyUalaBtn.addEventListener('click', function(e) { e.preventDefault(); const cuenta = document.getElementById('uala-cuenta').innerText; navigator.clipboard.writeText(cuenta).then(() => { const toast = document.getElementById('toast-copiado'); toast.classList.add('show'); toast.querySelector('.toast-text').textContent = '¡Cuenta Ualá copiada!'; toast.style.display = 'flex'; setTimeout(() => { toast.classList.remove('show'); toast.style.display = 'none'; toast.querySelector('.toast-text').textContent = '¡copiado al portapapeles!'; }, 1500); }); }); } })(); // Copiar teléfono y correo en sección Contacto reutilizando el toast (function(){ const toast = document.getElementById('toast-copiado'); function showToast(msg){ if (!toast) return; const textEl = toast.querySelector('.toast-text'); const prev = textEl ? textEl.textContent : ''; if (textEl) textEl.textContent = msg || '¡copiado al portapapeles!'; toast.classList.add('show'); toast.style.display = 'flex'; setTimeout(() => { toast.classList.remove('show'); toast.style.display = 'none'; if (textEl) textEl.textContent = prev || '¡copiado al portapapeles!'; }, 1500); } const btnPhone = document.getElementById('copy-phone-main'); if (btnPhone) { btnPhone.addEventListener('click', function(){ const telEl = document.getElementById('telefono-principal'); const tel = telEl ? (telEl.innerText || telEl.textContent).trim() : ''; if (!tel) return; navigator.clipboard.writeText(tel).then(() => showToast('¡Teléfono copiado!')); }); } const btnWhatsappSplit = document.getElementById('btn-whatsapp-split'); const whatsappPicker = document.getElementById('whatsapp-picker'); if (btnWhatsappSplit && whatsappPicker) { const whatsappOptions = whatsappPicker.querySelectorAll('.whatsapp-option'); const messages = { 'CO': 'Hola Aircan, quiero asesoría desde Colombia 🇨🇴', 'VE': 'Hola Aircan, quiero asesoría desde Venezuela 🇻🇪' }; function closePicker(){ btnWhatsappSplit.setAttribute('aria-expanded', 'false'); whatsappPicker.classList.remove('visible'); } function openPicker(){ btnWhatsappSplit.setAttribute('aria-expanded', 'true'); whatsappPicker.classList.add('visible'); } btnWhatsappSplit.addEventListener('click', function(e){ e.stopPropagation(); const expanded = this.getAttribute('aria-expanded') === 'true'; if (expanded) { closePicker(); } else { openPicker(); } }); whatsappOptions.forEach(option => { option.addEventListener('click', function(){ const country = this.dataset.country; const number = this.dataset.number; if (!number) return; const message = messages[country] || 'Hola Aircan, me gustaría más información ✨'; const extraLine = '¿Podemos hablar ahora mismo?'; const url = `https://wa.me/${number}?text=${encodeURIComponent(`${message}\n\n${extraLine}`)}`; window.open(url, '_blank'); closePicker(); }); }); document.addEventListener('click', function(e){ if (!whatsappPicker.contains(e.target) && !btnWhatsappSplit.contains(e.target)) { closePicker(); } }); document.addEventListener('keydown', function(e){ if (e.key === 'Escape') { closePicker(); } }); } const btnEmail = document.getElementById('copy-email-main'); if (btnEmail) { btnEmail.addEventListener('click', function(){ const mailEl = document.getElementById('correo-principal'); const mail = mailEl ? (mailEl.innerText || mailEl.textContent).trim() : ''; if (!mail) return; navigator.clipboard.writeText(mail).then(() => showToast('¡Correo copiado!')); }); } const btnAddress = document.getElementById('copy-address-main'); if (btnAddress) { btnAddress.addEventListener('click', function(){ const dirEl = document.getElementById('direccion-principal'); const dir = dirEl ? (dirEl.innerText || dirEl.textContent).trim() : ''; if (!dir) return; navigator.clipboard.writeText(dir).then(() => showToast('¡Dirección copiada!')); }); } })(); // Modal comprobante de pago (con validaciones) const btnComprobante = document.getElementById('btn-comprobante'); const modalComprobante = document.getElementById('modal-comprobante'); const cerrarModalComprobante = document.getElementById('cerrar-modal-comprobante'); // Asegurar que el modal esté directamente bajo <body> para que position:fixed // no se vea afectado por transformaciones (p.ej. AOS) en ancestros if (modalComprobante && modalComprobante.parentElement !== document.body) { document.body.appendChild(modalComprobante); } if (btnComprobante && modalComprobante) { btnComprobante.addEventListener('click',()=>{ modalComprobante.style.display='flex'; // Bloquear scroll de fondo mientras el modal está abierto document.body.style.overflow = 'hidden'; }); } if (modalComprobante && cerrarModalComprobante) { cerrarModalComprobante.addEventListener('click',()=>{ modalComprobante.style.display='none'; document.body.style.overflow = ''; }); const overlay = modalComprobante.querySelector('div'); if (overlay) { overlay.addEventListener('click',function(e){ if(e.target===this){ modalComprobante.style.display='none'; document.body.style.overflow = ''; } }); } document.addEventListener('keydown',function(e){ if(e.key==='Escape'){ modalComprobante.style.display='none'; document.body.style.overflow = ''; } }); } // Botones de copiado genéricos // Removido para usar el listener dinámico arriba // MODAL DE COMPRA function mostrarModalCompra(proyectoId, proyectoNombre) { let modal = document.getElementById('modal-compra-proyecto'); if (!modal) { modal = document.createElement('div'); modal.id = 'modal-compra-proyecto'; modal.style.position = 'fixed'; modal.style.top = '0'; modal.style.left = '0'; modal.style.width = '100vw'; modal.style.height = '100vh'; modal.style.background = 'rgba(0,0,0,0.92)'; modal.style.zIndex = '99999'; modal.style.display = 'flex'; modal.style.alignItems = 'center'; modal.style.justifyContent = 'center'; modal.innerHTML = ` <div style="background:linear-gradient(160deg, rgba(15,20,35,0.98) 0%, rgba(8,12,22,0.95) 100%);border-radius:18px;box-shadow:0 18px 60px rgba(0,0,0,0.75), 0 0 0 1px rgba(192,197,206,0.18), inset 0 1px 0 rgba(255,255,255,0.08);padding:32px 26px 26px 26px;width:100%;max-width:360px;display:flex;flex-direction:column;align-items:center;animation:modal-zoom 0.35s cubic-bezier(0.23, 1, 0.32, 1);border:1px solid rgba(192,197,206,0.22);backdrop-filter:blur(18px);position:relative;"> <button id="cerrar-modal-compra-proyecto" style="position:absolute;top:12px;right:12px;width:32px;height:32px;border-radius:50%;font-size:1.2rem;color:rgba(255,255,255,0.6);background:rgba(255,255,255,0.05);border:1px solid rgba(255,255,255,0.1);cursor:pointer;font-weight:400;transition:all 0.3s;z-index:3;display:flex;align-items:center;justify-content:center;" onmouseover="this.style.background='rgba(255,255,255,0.1)';this.style.color='rgba(255,255,255,0.9)';this.style.transform='rotate(90deg)'" onmouseout="this.style.background='rgba(255,255,255,0.05)';this.style.color='rgba(255,255,255,0.6)';this.style.transform='rotate(0deg)'">×</button> <div style="width:54px;height:54px;border-radius:50%;background:linear-gradient(135deg, rgba(192,197,206,0.2), rgba(192,197,206,0.1));display:flex;align-items:center;justify-content:center;margin-bottom:16px;box-shadow:0 6px 18px rgba(192,197,206,0.14), inset 0 1px 0 rgba(255,255,255,0.1);border:1px solid rgba(192,197,206,0.28);"> <i class="fas fa-shopping-cart" style="font-size:1.6rem;color:#c0c5ce;"></i> </div> <div style="font-weight:900;font-size:1.3rem;margin-bottom:4px;color:#ffffff;text-align:center;letter-spacing:0.4px;">Comprar Proyecto</div> <div style="font-size:1rem;margin-bottom:6px;color:#c0c5ce;text-align:center;font-weight:700;" id="modal-proyecto-nombre">${proyectoNombre}</div> <div style="font-size:0.85rem;margin-bottom:20px;color:rgba(192,197,206,0.6);text-align:center;max-width:92%;">Completa tus datos para finalizar la compra</div> <form id="form-compra-proyecto" style="width:100%;display:flex;flex-direction:column;gap:16px;"> <div style="display:flex;flex-direction:column;align-items:flex-start;width:100%;"> <label for="nombre-compra-proyecto" style="font-weight:700;font-size:0.9rem;color:rgba(192,197,206,0.9);margin-bottom:8px;letter-spacing:0.3px;">NOMBRE COMPLETO</label> <input type="text" id="nombre-compra-proyecto" name="nombre" required style="width:100%;padding:12px 14px;border-radius:10px;border:1px solid rgba(192,197,206,0.18);background:rgba(255,255,255,0.03);font-size:0.95rem;color:#ffffff;transition:all 0.3s;box-shadow:inset 0 2px 4px rgba(0,0,0,0.18);" onfocus="this.style.borderColor='rgba(192,197,206,0.48)';this.style.boxShadow='0 0 0 2px rgba(192,197,206,0.1), inset 0 2px 4px rgba(0,0,0,0.2)'" onblur="this.style.borderColor='rgba(192,197,206,0.18)';this.style.boxShadow='inset 0 2px 4px rgba(0,0,0,0.18)'"> </div> <div style="display:flex;flex-direction:column;align-items:flex-start;width:100%;"> <label for="telefono-compra-proyecto" style="font-weight:700;font-size:0.9rem;color:rgba(192,197,206,0.9);margin-bottom:8px;letter-spacing:0.3px;">TELÉFONO</label> <input type="tel" id="telefono-compra-proyecto" name="telefono" required style="width:100%;padding:12px 14px;border-radius:10px;border:1px solid rgba(192,197,206,0.18);background:rgba(255,255,255,0.03);font-size:0.95rem;color:#ffffff;transition:all 0.3s;box-shadow:inset 0 2px 4px rgba(0,0,0,0.18);" onfocus="this.style.borderColor='rgba(192,197,206,0.48)';this.style.boxShadow='0 0 0 2px rgba(192,197,206,0.1), inset 0 2px 4px rgba(0,0,0,0.2)'" onblur="this.style.borderColor='rgba(192,197,206,0.18)';this.style.boxShadow='inset 0 2px 4px rgba(0,0,0,0.18)'"> </div> <div style="display:flex;flex-direction:column;align-items:flex-start;width:100%;"> <label for="direccion-compra-proyecto" style="font-weight:700;font-size:0.9rem;color:rgba(192,197,206,0.9);margin-bottom:8px;letter-spacing:0.3px;">DIRECCIÓN</label> <input type="text" id="direccion-compra-proyecto" name="direccion" required style="width:100%;padding:12px 14px;border-radius:10px;border:1px solid rgba(192,197,206,0.18);background:rgba(255,255,255,0.03);font-size:0.95rem;color:#ffffff;transition:all 0.3s;box-shadow:inset 0 2px 4px rgba(0,0,0,0.18);" onfocus="this.style.borderColor='rgba(192,197,206,0.48)';this.style.boxShadow='0 0 0 2px rgba(192,197,206,0.1), inset 0 2px 4px rgba(0,0,0,0.2)'" onblur="this.style.borderColor='rgba(192,197,206,0.18)';this.style.boxShadow='inset 0 2px 4px rgba(0,0,0,0.18)'"> </div> <div style="display:flex;flex-direction:column;align-items:flex-start;width:100%;"> <label for="descripcion-compra-proyecto" style="font-weight:700;font-size:0.9rem;color:rgba(192,197,206,0.9);margin-bottom:8px;letter-spacing:0.3px;">DESCRIPCIÓN</label> <textarea id="descripcion-compra-proyecto" name="descripcion" required style="width:100%;padding:12px 14px;border-radius:10px;border:1px solid rgba(192,197,206,0.18);background:rgba(255,255,255,0.03);font-size:0.95rem;color:#ffffff;transition:all 0.3s;box-shadow:inset 0 2px 4px rgba(0,0,0,0.18);min-height:88px;resize:vertical;font-family:inherit;" onfocus="this.style.borderColor='rgba(192,197,206,0.48)';this.style.boxShadow='0 0 0 2px rgba(192,197,206,0.1), inset 0 2px 4px rgba(0,0,0,0.2)'" onblur="this.style.borderColor='rgba(192,197,206,0.18)';this.style.boxShadow='inset 0 2px 4px rgba(0,0,0,0.18)'"></textarea> </div> <button type="submit" style="background:linear-gradient(135deg, #c0c5ce 0%, #e8eaed 100%);color:#000000;font-weight:800;font-size:1rem;padding:13px 0;border:none;border-radius:10px;box-shadow:0 6px 20px rgba(192,197,206,0.22), inset 0 1px 0 rgba(255,255,255,0.55);cursor:pointer;transition:all 0.3s;letter-spacing:0.6px;margin-top:4px;display:flex;align-items:center;justify-content:center;gap:10px;border:1px solid rgba(192,197,206,0.35);position:relative;overflow:hidden;" onmouseover="this.style.transform='translateY(-2px)';this.style.boxShadow='0 10px 26px rgba(192,197,206,0.32), inset 0 1px 0 rgba(255,255,255,0.8)'" onmouseout="this.style.transform='translateY(0)';this.style.boxShadow='0 6px 20px rgba(192,197,206,0.22), inset 0 1px 0 rgba(255,255,255,0.55)'"> <i class="fas fa-shopping-cart" style="font-size:1.2rem;"></i> CONFIRMAR COMPRA </button> </form> <div id="mensaje-exito-compra-proyecto" style="display:none;margin-top:24px;padding:16px 24px;background:rgba(192,197,206,0.1);border:1px solid rgba(192,197,206,0.3);border-radius:12px;color:#c0c5ce;font-weight:700;font-size:1rem;text-align:center;box-shadow:0 4px 12px rgba(192,197,206,0.15);"><i class="fas fa-check-circle" style="font-size:1.3rem;margin-right:8px;"></i>¡Compra registrada!</div> </div> `; document.body.appendChild(modal); } else { const nameEl = modal.querySelector('#modal-proyecto-nombre'); if (nameEl) nameEl.textContent = proyectoNombre; const formReset = modal.querySelector('#form-compra-proyecto'); if (formReset) formReset.reset(); } modal.style.display = 'flex'; document.body.style.overflow = 'hidden'; // Cerrar modal modal.querySelector('#cerrar-modal-compra-proyecto').onclick = function() { modal.style.display = 'none'; document.body.style.overflow = ''; }; modal.addEventListener('click', function(e){ if(e.target===modal){ modal.style.display='none'; document.body.style.overflow = ''; } }); document.addEventListener('keydown', function handler(e){ if(e.key==='Escape'){ modal.style.display='none'; document.body.style.overflow = ''; document.removeEventListener('keydown', handler); } }); // Enviar compra const form = modal.querySelector('#form-compra-proyecto'); form.onsubmit = function(e){ e.preventDefault(); const nombre = document.getElementById('nombre-compra-proyecto').value.trim(); const telefono = document.getElementById('telefono-compra-proyecto').value.trim(); const direccion = document.getElementById('direccion-compra-proyecto').value.trim(); const descripcion = document.getElementById('descripcion-compra-proyecto').value.trim(); if(!nombre||!telefono||!direccion||!descripcion)return; const fd = new FormData(); fd.append('nombre', nombre); fd.append('telefono', telefono); fd.append('direccion', direccion); fd.append('mensaje', `Interés en Proyecto: ${proyectoNombre}. Descripción: ${descripcion}`); fd.append('servicio_interes', 'Sistemas/Proyectos'); // Funcionalidad de leads deshabilitada form.style.display = 'none'; modal.querySelector('#mensaje-exito-compra-proyecto').style.display = 'block'; setTimeout(() => { modal.style.display = 'none'; document.body.style.overflow = ''; form.style.display = 'flex'; modal.querySelector('#mensaje-exito-compra-proyecto').style.display = 'none'; form.reset(); }, 1800); }; } // MODAL DE COMPRA DE SERVICIOS function mostrarModalCompraServicio(servicioId, servicioNombre, servicioPrecio) { let modal = document.getElementById('modal-compra-servicio'); if (!modal) { modal = document.createElement('div'); modal.id = 'modal-compra-servicio'; modal.style.position = 'fixed'; modal.style.top = '0'; modal.style.left = '0'; modal.style.width = '100vw'; modal.style.height = '100vh'; modal.style.background = 'rgba(0,0,0,0.92)'; modal.style.zIndex = '99999'; modal.style.display = 'flex'; modal.style.alignItems = 'center'; modal.style.justifyContent = 'center'; modal.innerHTML = ` <div style="background:linear-gradient(160deg, rgba(15,20,35,0.98) 0%, rgba(8,12,22,0.95) 100%);border-radius:24px;box-shadow:0 24px 80px rgba(0,0,0,0.8), 0 0 0 1px rgba(0,229,255,0.25), inset 0 1px 0 rgba(255,255,255,0.1);padding:48px 36px 36px 36px;max-width:96vw;width:100%;max-width:480px;display:flex;flex-direction:column;align-items:center;animation:modal-zoom 0.4s cubic-bezier(0.23, 1, 0.32, 1);border:1px solid rgba(0,229,255,0.3);backdrop-filter:blur(20px);position:relative;"> <button id="cerrar-modal-compra-servicio" style="position:absolute;top:16px;right:16px;width:36px;height:36px;border-radius:50%;font-size:1.4rem;color:rgba(255,255,255,0.6);background:rgba(255,255,255,0.05);border:1px solid rgba(255,255,255,0.1);cursor:pointer;font-weight:400;transition:all 0.3s;z-index:3;display:flex;align-items:center;justify-content:center;" onmouseover="this.style.background='rgba(255,255,255,0.1)';this.style.color='rgba(255,255,255,0.9)';this.style.transform='rotate(90deg)'" onmouseout="this.style.background='rgba(255,255,255,0.05)';this.style.color='rgba(255,255,255,0.6)';this.style.transform='rotate(0deg)'">×</button> <div style="width:64px;height:64px;border-radius:50%;background:linear-gradient(135deg, rgba(0,229,255,0.2), rgba(52,152,219,0.15));display:flex;align-items:center;justify-content:center;margin-bottom:20px;box-shadow:0 8px 24px rgba(0,229,255,0.2), inset 0 1px 0 rgba(255,255,255,0.1);border:1px solid rgba(0,229,255,0.35);"> <i class="fas fa-briefcase" style="font-size:2rem;color:#00e5ff;"></i> </div> <div style="font-weight:900;font-size:1.5rem;margin-bottom:4px;color:#ffffff;text-align:center;letter-spacing:0.5px;">Comprar Servicio</div> <div style="font-size:1.1rem;margin-bottom:6px;color:#00e5ff;text-align:center;font-weight:700;" id="modal-servicio-nombre">${servicioNombre}</div> <!-- <div style="font-size:1.15rem;font-weight:900;margin-bottom:24px;color:#7dffb3;text-align:center;padding:8px 20px;background:rgba(125,255,179,0.1);border-radius:12px;border:1px solid rgba(125,255,179,0.2);">$<span id="modal-servicio-precio">${parseFloat(servicioPrecio).toLocaleString('es-ES')}</span></div> --> <form id="form-compra-servicio" style="width:100%;display:flex;flex-direction:column;gap:20px;"> <div style="display:flex;flex-direction:column;align-items:flex-start;width:100%;"> <label for="nombre-compra-servicio" style="font-weight:700;font-size:0.9rem;color:rgba(192,197,206,0.9);margin-bottom:8px;letter-spacing:0.3px;">NOMBRE COMPLETO</label> <input type="text" id="nombre-compra-servicio" name="nombre" required style="width:100%;padding:14px 16px;border-radius:12px;border:1px solid rgba(192,197,206,0.2);background:rgba(255,255,255,0.03);font-size:1rem;color:#ffffff;transition:all 0.3s;box-shadow:inset 0 2px 4px rgba(0,0,0,0.2);" onfocus="this.style.borderColor='rgba(0,229,255,0.5)';this.style.boxShadow='0 0 0 3px rgba(0,229,255,0.1), inset 0 2px 4px rgba(0,0,0,0.2)'" onblur="this.style.borderColor='rgba(192,197,206,0.2)';this.style.boxShadow='inset 0 2px 4px rgba(0,0,0,0.2)'"> </div> <div style="display:flex;flex-direction:column;align-items:flex-start;width:100%;"> <label for="telefono-compra-servicio" style="font-weight:700;font-size:0.9rem;color:rgba(192,197,206,0.9);margin-bottom:8px;letter-spacing:0.3px;">TELÉFONO</label> <input type="tel" id="telefono-compra-servicio" name="telefono" required style="width:100%;padding:14px 16px;border-radius:12px;border:1px solid rgba(192,197,206,0.2);background:rgba(255,255,255,0.03);font-size:1rem;color:#ffffff;transition:all 0.3s;box-shadow:inset 0 2px 4px rgba(0,0,0,0.2);" onfocus="this.style.borderColor='rgba(0,229,255,0.5)';this.style.boxShadow='0 0 0 3px rgba(0,229,255,0.1), inset 0 2px 4px rgba(0,0,0,0.2)'" onblur="this.style.borderColor='rgba(192,197,206,0.2)';this.style.boxShadow='inset 0 2px 4px rgba(0,0,0,0.2)'"> </div> <div style="display:flex;flex-direction:column;align-items:flex-start;width:100%;"> <label for="descripcion-compra-servicio" style="font-weight:700;font-size:0.9rem;color:rgba(192,197,206,0.9);margin-bottom:8px;letter-spacing:0.3px;">DESCRIPCIÓN</label> <textarea id="descripcion-compra-servicio" name="descripcion" required style="width:100%;padding:14px 16px;border-radius:12px;border:1px solid rgba(192,197,206,0.2);background:rgba(255,255,255,0.03);font-size:1rem;color:#ffffff;transition:all 0.3s;box-shadow:inset 0 2px 4px rgba(0,0,0,0.2);min-height:100px;resize:vertical;font-family:inherit;" onfocus="this.style.borderColor='rgba(0,229,255,0.5)';this.style.boxShadow='0 0 0 3px rgba(0,229,255,0.1), inset 0 2px 4px rgba(0,0,0,0.2)'" onblur="this.style.borderColor='rgba(192,197,206,0.2)';this.style.boxShadow='inset 0 2px 4px rgba(0,0,0,0.2)'"></textarea> </div> <button type="submit" style="background:linear-gradient(135deg, #00e5ff 0%, #0099ff 100%);color:#000000;font-weight:900;font-size:1.1rem;padding:16px 0;border:none;border-radius:12px;box-shadow:0 8px 24px rgba(0,229,255,0.35), inset 0 1px 0 rgba(255,255,255,0.5);cursor:pointer;transition:all 0.3s;letter-spacing:0.8px;margin-top:8px;display:flex;align-items:center;justify-content:center;gap:12px;border:1px solid rgba(0,229,255,0.4);position:relative;overflow:hidden;" onmouseover="this.style.transform='translateY(-2px)';this.style.boxShadow='0 12px 32px rgba(0,229,255,0.5), inset 0 1px 0 rgba(255,255,255,0.7)'" onmouseout="this.style.transform='translateY(0)';this.style.boxShadow='0 8px 24px rgba(0,229,255,0.35), inset 0 1px 0 rgba(255,255,255,0.5)'"> <i class="fas fa-briefcase" style="font-size:1.2rem;"></i> CONFIRMAR COMPRA </button> </form> <div id="mensaje-exito-compra-servicio" style="display:none;margin-top:24px;padding:16px 24px;background:rgba(0,229,255,0.1);border:1px solid rgba(0,229,255,0.3);border-radius:12px;color:#00e5ff;font-weight:700;font-size:1rem;text-align:center;box-shadow:0 4px 12px rgba(0,229,255,0.15);"><i class="fas fa-check-circle" style="font-size:1.3rem;margin-right:8px;"></i>¡Compra registrada!</div> </div> `; document.body.appendChild(modal); } else { const nameEl = modal.querySelector('#modal-servicio-nombre'); if (nameEl) nameEl.textContent = servicioNombre; // const priceEl = modal.querySelector('#modal-servicio-precio'); // if (priceEl) priceEl.textContent = parseFloat(servicioPrecio).toLocaleString('es-ES'); const formReset = modal.querySelector('#form-compra-servicio'); if (formReset) formReset.reset(); } modal.style.display = 'flex'; document.body.style.overflow = 'hidden'; // Cerrar modal modal.querySelector('#cerrar-modal-compra-servicio').onclick = function() { modal.style.display = 'none'; document.body.style.overflow = ''; }; modal.addEventListener('click', function(e){ if(e.target===modal){ modal.style.display='none'; document.body.style.overflow = ''; } }); document.addEventListener('keydown', function handler(e){ if(e.key==='Escape'){ modal.style.display='none'; document.body.style.overflow = ''; document.removeEventListener('keydown', handler); } }); // Enviar compra const form = modal.querySelector('#form-compra-servicio'); form.onsubmit = function(e){ e.preventDefault(); const nombre = document.getElementById('nombre-compra-servicio').value.trim(); const telefono = document.getElementById('telefono-compra-servicio').value.trim(); const descripcion = document.getElementById('descripcion-compra-servicio').value.trim(); if(!nombre||!telefono||!descripcion)return; const fd = new FormData(); fd.append('nombre', nombre); fd.append('telefono', telefono); fd.append('mensaje', `Interés en Servicio: ${servicioNombre}. Descripción: ${descripcion}`); fd.append('servicio_interes', servicioNombre); // Funcionalidad de leads deshabilitada form.style.display = 'none'; modal.querySelector('#mensaje-exito-compra-servicio').style.display = 'block'; setTimeout(() => { modal.style.display = 'none'; document.body.style.overflow = ''; form.style.display = 'flex'; modal.querySelector('#mensaje-exito-compra-servicio').style.display = 'none'; form.reset(); }, 1800); }; } // Script para botones de copiado dinámicos document.addEventListener('click', function(e) { const btn = e.target.closest('.generic-copy'); if (btn) { const targetId = btn.getAttribute('data-target'); const target = targetId ? document.getElementById(targetId) : null; const toast = document.getElementById('toast-copiado'); const text = target ? target.innerText : ''; if (!text) return; navigator.clipboard.writeText(text).then(() => { if (!toast) return; toast.style.display = 'flex'; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); setTimeout(() => { toast.style.display = 'none'; }, 400); }, 2000); }); } }); // Enviar Comprobante AJAX Profesional const formComprobanteV2 = document.getElementById('form-comprobante-v2'); const statusMsgV2 = document.getElementById('status-message'); const fileInputV2 = document.getElementById('file-input'); const fileNameDisplayV2 = document.getElementById('file-name'); const modalComprobanteV2 = document.getElementById('modal-comprobante'); const btnComprobanteV2 = document.getElementById('btn-comprobante'); const cerrarModalComprobanteV2 = document.getElementById('cerrar-modal-comprobante'); if (btnComprobanteV2 && modalComprobanteV2) { btnComprobanteV2.addEventListener('click', () => { modalComprobanteV2.style.display = 'flex'; document.body.style.overflow = 'hidden'; }); } if (modalComprobanteV2 && cerrarModalComprobanteV2) { cerrarModalComprobanteV2.addEventListener('click', () => { modalComprobanteV2.style.display = 'none'; document.body.style.overflow = ''; }); modalComprobanteV2.addEventListener('click', (e) => { if (e.target === modalComprobanteV2) { modalComprobanteV2.style.display = 'none'; document.body.style.overflow = ''; } }); } if (fileInputV2 && fileNameDisplayV2) { fileInputV2.addEventListener('change', function() { const dropZone = document.getElementById('drop-zone'); if (this.files && this.files[0]) { const file = this.files[0]; fileNameDisplayV2.innerText = '✅ ' + file.name; fileNameDisplayV2.style.color = '#48bb78'; if (dropZone) dropZone.classList.add('uploaded'); // Cambiar icono const icon = document.querySelector('.upload-premium-zone i'); if (icon) { icon.className = 'fas fa-check-circle'; icon.style.color = '#48bb78'; } } else { if (dropZone) dropZone.classList.remove('uploaded'); fileNameDisplayV2.innerText = 'Seleccionar archivo'; const icon = document.querySelector('.upload-premium-zone i'); if (icon) { icon.className = 'fas fa-cloud-upload-alt'; icon.style.color = ''; } } }); } if (formComprobanteV2 && statusMsgV2) { formComprobanteV2.addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); const btn = this.querySelector('button[type="submit"]'); const btnSpan = btn.querySelector('span'); const originalText = btnSpan.innerText; const fileSelected = fileInputV2 && fileInputV2.files && fileInputV2.files[0] ? fileInputV2.files[0] : null; if (!fileSelected) { statusMsgV2.style.display = 'block'; statusMsgV2.style.background = '#fff5f5'; statusMsgV2.style.color = '#c53030'; statusMsgV2.style.border = '1px solid #fed7d7'; statusMsgV2.innerHTML = '<i class="fas fa-exclamation-circle"></i> Debes seleccionar una imagen del comprobante.'; return; } btn.disabled = true; btnSpan.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Enviando...'; // Usamos la URL absoluta construida correctamente const fetchUrl = '<?= rtrim(BASE_URL, "/") ?>/metodospago/enviarComprobante'; fetch(fetchUrl, { method: 'POST', credentials: 'same-origin', body: formData }) .then(async res => { const contentType = res.headers.get('content-type') || ''; if (!contentType.includes('application/json')) { const rawText = await res.text(); throw new Error(rawText ? rawText.slice(0, 200) : 'La respuesta del servidor no es JSON válido'); } const data = await res.json(); if (!res.ok) throw new Error(data.error || 'Error en el servidor'); return data; }) .then(data => { if (data.success) { statusMsgV2.style.display = 'block'; statusMsgV2.className = 'status-success-premium'; // Clase para estilo elegante statusMsgV2.style.background = '#f0fff4'; statusMsgV2.style.color = '#2f855a'; statusMsgV2.style.border = '1px solid #c6f6d5'; statusMsgV2.innerHTML = `<div style="padding:10px;"> <i class="fas fa-check-circle" style="font-size:1.5rem; display:block; margin-bottom:5px;"></i> <strong>${data.message}</strong> </div>`; formComprobanteV2.reset(); const dropZone = document.getElementById('drop-zone'); if (dropZone) dropZone.classList.remove('uploaded'); if (fileNameDisplayV2) { fileNameDisplayV2.innerText = 'Seleccionar archivo'; fileNameDisplayV2.style.color = '#718096'; } const icon = document.querySelector('.upload-premium-zone i'); if (icon) { icon.className = 'fas fa-cloud-upload-alt'; icon.style.color = ''; } setTimeout(() => { statusMsgV2.style.display = 'none'; if (modalComprobanteV2) { modalComprobanteV2.style.display = 'none'; } document.body.style.overflow = ''; }, 4000); } }) .catch(err => { statusMsgV2.style.display = 'block'; statusMsgV2.style.background = '#fff5f5'; statusMsgV2.style.color = '#c53030'; statusMsgV2.style.border = '1px solid #fed7d7'; statusMsgV2.innerHTML = `<i class="fas fa-exclamation-circle"></i> ${err.message}`; }) .finally(() => { btn.disabled = false; btnSpan.innerText = originalText; }); }); } </script> <script src="https://unpkg.com/three@0.160.0/build/three.min.js"></script> <script> (function(){ const hero = document.querySelector('.hero'); const canvas = document.querySelector('.hero-glow-canvas'); if (!hero || !canvas || typeof THREE === 'undefined') return; const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true, powerPreference: 'high-performance' }); renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 1.25)); const scene = new THREE.Scene(); const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); const uniforms = { u_time: { value: 0 }, u_resolution: { value: new THREE.Vector2(1, 1) }, u_mouse: { value: new THREE.Vector2(0.72, 0.42) } }; const material = new THREE.ShaderMaterial({ uniforms, vertexShader: ` varying vec2 vUv; void main() { vUv = uv; gl_Position = vec4(position, 1.0); } `, fragmentShader: ` precision highp float; uniform float u_time; uniform vec2 u_resolution; uniform vec2 u_mouse; varying vec2 vUv; float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123); } float noise(vec2 p) { vec2 i = floor(p); vec2 f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f); return mix( mix(hash(i + vec2(0.0, 0.0)), hash(i + vec2(1.0, 0.0)), u.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x), u.y ); } float fbm(vec2 p) { float value = 0.0; float amplitude = 0.5; mat2 rot = mat2(1.6, 1.2, -1.2, 1.6); for (int i = 0; i < 3; i++) { value += amplitude * noise(p); p = rot * p + vec2(0.17); amplitude *= 0.5; } return value; } void main() { vec2 uv = vUv; vec2 p = (uv - 0.5) * vec2(u_resolution.x / u_resolution.y, 1.0) * 1.38; vec2 mouse = (u_mouse - 0.5) * vec2(u_resolution.x / u_resolution.y, 1.0) * 1.38; float t = u_time * 0.045; float base = fbm(p * 1.8 + vec2(t * 0.9, -t * 0.35)); float drift = fbm((p + base * 0.45) * 2.6 + vec2(-t * 0.55, t * 0.28)); float wisps = fbm((p - drift * 0.22) * 4.1 + vec2(t * 0.18, t * 0.4)); float softNoise = fbm(p * 6.4 - drift * 0.3 + vec2(-t * 0.22, t * 0.16)); float smokeField = smoothstep(0.22, 0.88, mix(base, drift, 0.58)); float wispField = smoothstep(0.42, 0.96, wisps); float haze = smoothstep(0.18, 0.92, softNoise) * 0.36; vec3 col = vec3(0.002, 0.004, 0.012); vec3 blue = vec3(0.08, 0.18, 0.48); vec3 violet = vec3(0.18, 0.10, 0.42); vec3 mist = vec3(0.36, 0.44, 0.78); col += blue * smokeField * 0.34; col += violet * smokeField * 0.28; col += mist * wispField * 0.16; col += vec3(0.05, 0.07, 0.14) * haze; float coreGlow = exp(-3.6 * length(p - vec2(0.12, -0.02))) * 0.18; float sideGlow = exp(-4.4 * length(p - vec2(-0.52, 0.16))) * 0.1; float mouseBloom = exp(-11.0 * length(p - mouse)) * 0.18; col += vec3(0.16, 0.24, 0.62) * coreGlow; col += vec3(0.22, 0.14, 0.46) * sideGlow; col += vec3(0.34, 0.46, 0.9) * mouseBloom; float vignette = smoothstep(1.45, 0.28, length(p)); col *= vignette; col = pow(col, vec3(1.08)); gl_FragColor = vec4(col, 1.0); } ` }); const mesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), material); scene.add(mesh); const pointer = { current: new THREE.Vector2(0.72, 0.42), target: new THREE.Vector2(0.72, 0.42) }; let pulseTimeout = null; let trailTimeout = null; const updatePointerVars = (x, y) => { hero.style.setProperty('--pointer-x', `${(x * 100).toFixed(2)}%`); hero.style.setProperty('--pointer-y', `${(y * 100).toFixed(2)}%`); }; const updateTrailVars = (x, y) => { hero.style.setProperty('--trail-x', `${(x * 100).toFixed(2)}%`); hero.style.setProperty('--trail-y', `${(y * 100).toFixed(2)}%`); }; const triggerPointerPulse = () => { hero.style.setProperty('--pointer-pulse', '1.12'); hero.style.setProperty('--pointer-opacity', '0.82'); if (pulseTimeout) { window.clearTimeout(pulseTimeout); } pulseTimeout = window.setTimeout(() => { hero.style.setProperty('--pointer-pulse', '1'); hero.style.setProperty('--pointer-opacity', '0.58'); }, 320); }; const triggerTrailPulse = (x, y) => { updateTrailVars(x, y); hero.style.setProperty('--trail-opacity', '0.7'); hero.style.setProperty('--trail-scale', '1'); if (trailTimeout) { window.clearTimeout(trailTimeout); } trailTimeout = window.setTimeout(() => { hero.style.setProperty('--trail-opacity', '0'); hero.style.setProperty('--trail-scale', '1.34'); }, 30); }; const handlePointerMove = (event) => { const rect = hero.getBoundingClientRect(); const x = (event.clientX - rect.left) / rect.width; const y = (event.clientY - rect.top) / rect.height; pointer.target.set(Math.min(Math.max(x, 0.0), 1.0), Math.min(Math.max(y, 0.0), 1.0)); updatePointerVars(pointer.target.x, pointer.target.y); }; const handlePointerDown = (event) => { const rect = hero.getBoundingClientRect(); const point = event.touches && event.touches[0] ? event.touches[0] : event; const x = (point.clientX - rect.left) / rect.width; const y = (point.clientY - rect.top) / rect.height; pointer.target.set(Math.min(Math.max(x, 0.0), 1.0), Math.min(Math.max(y, 0.0), 1.0)); updatePointerVars(pointer.target.x, pointer.target.y); triggerPointerPulse(); triggerTrailPulse(pointer.target.x, pointer.target.y); }; const handlePointerLeave = () => { pointer.target.set(0.72, 0.42); updatePointerVars(pointer.target.x, pointer.target.y); hero.style.setProperty('--pointer-pulse', '1'); hero.style.setProperty('--pointer-opacity', '0.58'); }; const resize = () => { const bounds = hero.getBoundingClientRect(); const width = Math.max(1, Math.floor(bounds.width)); const height = Math.max(1, Math.floor(bounds.height)); renderer.setSize(width, height, false); uniforms.u_resolution.value.set(width, height); }; let visible = true; const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { visible = entry.isIntersecting; }); }, { threshold: 0.08 }); observer.observe(hero); hero.addEventListener('pointermove', handlePointerMove); if (window.PointerEvent) { hero.addEventListener('pointerdown', handlePointerDown); } else { hero.addEventListener('touchstart', handlePointerDown, { passive: true }); hero.addEventListener('mousedown', handlePointerDown); } hero.addEventListener('pointerleave', handlePointerLeave); window.addEventListener('resize', resize); if (typeof prefersReducedMotion.addEventListener === 'function') { prefersReducedMotion.addEventListener('change', resize); } else if (typeof prefersReducedMotion.addListener === 'function') { prefersReducedMotion.addListener(resize); } resize(); updatePointerVars(pointer.current.x, pointer.current.y); updateTrailVars(pointer.current.x, pointer.current.y); hero.style.setProperty('--pointer-pulse', '1'); hero.style.setProperty('--pointer-opacity', '0.58'); hero.style.setProperty('--trail-opacity', '0'); hero.style.setProperty('--trail-scale', '0.72'); const clock = new THREE.Clock(); const render = () => { requestAnimationFrame(render); if (!visible) return; const delta = clock.getDelta(); if (!prefersReducedMotion.matches) { uniforms.u_time.value += delta; } pointer.current.lerp(pointer.target, prefersReducedMotion.matches ? 0.1 : 0.045); uniforms.u_mouse.value.copy(pointer.current); renderer.render(scene, camera); }; render(); })(); </script> <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script> <script> AOS.init({ duration: 900, // Duración de la animación once: true, // Animar solo una vez easing: 'ease-in-out', // Curva de aceleración offset: 100, // Desfase para disparar la animación }); </script> <!-- PWA: Service Worker + Install Prompt handling --> <script> (function(){ const baseUrl = <?= json_encode(rtrim(BASE_URL, '/')) ?>; const navItem = document.getElementById('install-nav-item'); const mobileBtn = document.getElementById('install-btn-mobile'); const desktopBtn = document.getElementById('install-btn-desktop'); const desktopIcon = document.getElementById('install-btn-desktop-icon'); const desktopLabel = document.getElementById('install-btn-desktop-label'); const desktopEyebrow = document.getElementById('install-btn-desktop-eyebrow'); const iosModal = document.getElementById('ios-install-modal'); const iosInstallClose = document.getElementById('ios-install-close'); const iosInstallDone = document.getElementById('ios-install-done'); const iosInstallBadgeText = document.getElementById('ios-install-badge-text'); const iosInstallCopy = document.getElementById('ios-install-copy'); const iosInstallStepShare = document.getElementById('ios-install-step-share'); const installStorageKey = 'aircan_pwa_installed'; const installHintDismissedKey = 'aircan_pwa_ios_hint_seen'; const ua = window.navigator.userAgent || ''; const isIos = /iphone|ipad|ipod/i.test(ua); const isSafariOnIos = isIos && /safari/i.test(ua) && !/crios|fxios|edgios|opios/i.test(ua); let deferredPrompt = null; function isStandalone(){ return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; } function isMarkedInstalled(){ return window.localStorage.getItem(installStorageKey) === '1'; } function markInstalled(){ window.localStorage.setItem(installStorageKey, '1'); } function clearInstalledMark(){ if (!isStandalone()) { window.localStorage.removeItem(installStorageKey); } } function shouldOfferIosGuide(){ return isIos && !isStandalone(); } function canInstall(){ if (isStandalone() || isMarkedInstalled()) { return false; } if (shouldOfferIosGuide()) { return true; } return !!deferredPrompt; } function updateInstallButtonCopy(){ if (!desktopBtn || !desktopLabel || !desktopEyebrow || !desktopIcon) { return; } if (shouldOfferIosGuide()) { desktopBtn.classList.add('install-btn--ios'); desktopLabel.textContent = isSafariOnIos ? 'Agregar al inicio' : 'Instalar en iPhone'; desktopEyebrow.textContent = isSafariOnIos ? 'Funciona como app en tu iPhone o iPad' : 'Abre esta pagina en Safari para instalarla'; desktopIcon.className = isSafariOnIos ? 'fas fa-share-square' : 'fab fa-apple'; } else { desktopBtn.classList.remove('install-btn--ios'); desktopLabel.textContent = 'Instalar app'; desktopEyebrow.textContent = 'Llevala a tu pantalla de inicio'; desktopIcon.className = 'fas fa-download'; } } function syncButtonsVisibility(){ const available = canInstall(); const showMobile = available && window.innerWidth <= 992; if (navItem) { navItem.style.display = showMobile ? 'block' : 'none'; } if (mobileBtn) { mobileBtn.hidden = !showMobile; } if (desktopBtn) { desktopBtn.hidden = !available; desktopBtn.style.display = available ? 'inline-flex' : 'none'; } } function openIosModal(){ if (!iosModal) { return; } if (iosInstallBadgeText) { iosInstallBadgeText.textContent = isSafariOnIos ? 'Instalacion en iPhone y iPad' : 'Abrir en Safari para instalar'; } if (iosInstallCopy) { iosInstallCopy.textContent = isSafariOnIos ? 'Instalala en segundos para abrirla como una app, con acceso rapido y experiencia de pantalla completa.' : 'Para instalarla en iPhone o iPad, abre esta misma pagina en Safari y sigue los pasos de instalacion.'; } if (iosInstallStepShare) { iosInstallStepShare.textContent = isSafariOnIos ? 'Toca el icono de compartir de Safari en la parte inferior o superior del navegador.' : 'Usa el boton compartir de Safari despues de abrir esta pagina desde ese navegador.'; } iosModal.hidden = false; requestAnimationFrame(() => iosModal.classList.add('is-visible')); window.localStorage.setItem(installHintDismissedKey, '1'); } function closeIosModal(){ if (!iosModal) { return; } iosModal.classList.remove('is-visible'); window.setTimeout(() => { iosModal.hidden = true; }, 250); } async function triggerInstall(){ if (shouldOfferIosGuide()) { openIosModal(); return; } if (!deferredPrompt) { syncButtonsVisibility(); return; } deferredPrompt.prompt(); try { const choice = await deferredPrompt.userChoice; if (choice && choice.outcome === 'accepted') { markInstalled(); } } catch (_) { } deferredPrompt = null; syncButtonsVisibility(); } window.addEventListener('beforeinstallprompt', (event) => { event.preventDefault(); deferredPrompt = event; updateInstallButtonCopy(); syncButtonsVisibility(); }); window.addEventListener('appinstalled', () => { deferredPrompt = null; markInstalled(); closeIosModal(); syncButtonsVisibility(); }); if (mobileBtn) { mobileBtn.addEventListener('click', triggerInstall); } if (desktopBtn) { desktopBtn.addEventListener('click', triggerInstall); } if (iosInstallClose) { iosInstallClose.addEventListener('click', closeIosModal); } if (iosInstallDone) { iosInstallDone.addEventListener('click', function(){ markInstalled(); closeIosModal(); syncButtonsVisibility(); }); } if (iosModal) { iosModal.addEventListener('click', function(event){ if (event.target === iosModal) { closeIosModal(); } }); } window.addEventListener('resize', syncButtonsVisibility); if ('serviceWorker' in navigator) { window.addEventListener('load', function(){ const swPath = (baseUrl ? baseUrl : '') + '/service-worker.js'; const swScope = (baseUrl ? baseUrl : '') + '/'; navigator.serviceWorker.register(swPath, { scope: swScope }).catch(function(){}); }); } document.addEventListener('DOMContentLoaded', function(){ clearInstalledMark(); updateInstallButtonCopy(); syncButtonsVisibility(); if (shouldOfferIosGuide() && !window.localStorage.getItem(installHintDismissedKey)) { window.setTimeout(function(){ if (!isStandalone() && !isMarkedInstalled()) { openIosModal(); } }, 1800); } }); })(); </script> <!-- AIRCAN 2026 Login Modal --> <div class="ac-modal-overlay" id="aircanLoginOverlay"> <div class="ac-modal"> <button class="ac-modal-close" onclick="closeAircanLogin()" aria-label="Cerrar modal"><i class="fas fa-times"></i></button> <div class="ac-modal-header"> <div class="logo-only"> <img src="<?= htmlspecialchars($logo) ?>" alt="Logo Aircan"> </div> </div> <div class="ac-error" id="aircanLoginError"></div> <form id="aircanLoginForm" onsubmit="submitAircanLogin(event)" autocomplete="on"> <div class="ac-input-group"> <label for="aircanEmail">Correo Electrónico</label> <div class="ac-input-wrapper"> <i class="fas fa-envelope input-icon"></i> <input type="email" id="aircanEmail" class="ac-input" placeholder="ejemplo@aircan.me" required autocomplete="email"> </div> </div> <div class="ac-input-group"> <label for="aircanPassword">Contraseña</label> <div class="ac-input-wrapper"> <i class="fas fa-lock input-icon"></i> <input type="password" id="aircanPassword" class="ac-input" placeholder="••••••••" required autocomplete="current-password"> <i class="fas fa-eye ac-password-toggle" id="togglePassword" onclick="togglePasswordVisibility()"></i> </div> </div> <button type="submit" class="ac-btn" id="aircanSubmitBtn"> <span id="aircanBtnText">Acceder al Sistema</span> <div class="ac-loader" id="aircanBtnLoader"></div> </button> </form> </div> </div> <script> function openAircanLogin(e) { e.preventDefault(); document.getElementById('aircanLoginOverlay').classList.add('active'); setTimeout(() => document.getElementById('aircanEmail').focus(), 100); } function closeAircanLogin() { document.getElementById('aircanLoginOverlay').classList.remove('active'); document.getElementById('aircanLoginForm').reset(); document.getElementById('aircanLoginError').style.display = 'none'; // Reset password field to password type if it was visible const passwordInput = document.getElementById('aircanPassword'); const toggleIcon = document.getElementById('togglePassword'); if (passwordInput) passwordInput.type = 'password'; if (toggleIcon) { toggleIcon.classList.remove('fa-eye-slash'); toggleIcon.classList.add('fa-eye'); } } function togglePasswordVisibility() { const passwordInput = document.getElementById('aircanPassword'); const toggleIcon = document.getElementById('togglePassword'); if (passwordInput.type === 'password') { passwordInput.type = 'text'; toggleIcon.classList.remove('fa-eye'); toggleIcon.classList.add('fa-eye-slash'); } else { passwordInput.type = 'password'; toggleIcon.classList.remove('fa-eye-slash'); toggleIcon.classList.add('fa-eye'); } } // Close on esc or outside click document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeAircanLogin(); }); const aircanLoginOverlay = document.getElementById('aircanLoginOverlay'); if (aircanLoginOverlay) { aircanLoginOverlay.addEventListener('mousedown', (e) => { if (e.target === aircanLoginOverlay) closeAircanLogin(); }); } async function submitAircanLogin(e) { e.preventDefault(); const btnText = document.getElementById('aircanBtnText'); const btnLoader = document.getElementById('aircanBtnLoader'); const errorDiv = document.getElementById('aircanLoginError'); errorDiv.style.display = 'none'; btnText.style.display = 'none'; btnLoader.style.display = 'block'; const formData = new URLSearchParams(); formData.append('email', document.getElementById('aircanEmail').value); formData.append('password', document.getElementById('aircanPassword').value); try { // Ensure the path is correct dynamically based on location const loginPath = '<?= BASE_URL ?>/auth/authenticate'; const response = await fetch(loginPath, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' }, body: formData }); const data = await response.json(); if (data.success) { btnText.style.display = 'block'; btnLoader.style.display = 'none'; btnText.innerText = '¡BIENVENIDO!'; setTimeout(() => window.location.href = data.redirect, 500); } else { // Vibración profesional (Haptic Feedback) if ("vibrate" in navigator) { // Patrón de error: corto, pausa, corto (100ms vibración, 50ms pausa, 100ms vibración) navigator.vibrate([100, 50, 100]); } errorDiv.innerText = data.message; errorDiv.style.display = 'block'; btnText.style.display = 'block'; btnLoader.style.display = 'none'; // Reiniciar animación para que el usuario note el error cada vez errorDiv.style.animation = 'none'; errorDiv.offsetHeight; // trigger reflow errorDiv.style.animation = null; } } catch (err) { errorDiv.innerText = 'Error de conexión. Intente nuevamente.'; errorDiv.style.display = 'block'; btnText.style.display = 'block'; btnLoader.style.display = 'none'; } } </script> <script> // Brutal Logo Animation on Scroll document.addEventListener('DOMContentLoaded', () => { const heroSection = document.getElementById('home'); // Smoke Click Effect Logic - Refined V2 if (heroSection) { const createSmoke = (x, y) => { for (let i = 0; i < 3; i++) { const particle = document.createElement('div'); particle.className = 'smoke-particle'; const size = Math.random() * 100 + 100; const offsetX = (Math.random() - 0.5) * 60; const offsetY = (Math.random() - 0.5) * 60; particle.style.width = `${size}px`; particle.style.height = `${size}px`; particle.style.left = `${x + offsetX}px`; particle.style.top = `${y + offsetY}px`; particle.style.animationDelay = `${Math.random() * 0.5}s`; document.body.appendChild(particle); setTimeout(() => { particle.remove(); }, 3000); } }; heroSection.addEventListener('click', (e) => { createSmoke(e.clientX, e.clientY); }); heroSection.addEventListener('touchstart', (e) => { const touch = e.touches[0]; createSmoke(touch.clientX, touch.clientY); }, { passive: true }); } const navLogo = document.getElementById('nav-logo-anim'); const heroLogo = document.getElementById('hero-logo-anim'); if (heroSection && navLogo && heroLogo) { let triggerHeight = heroSection.offsetHeight * 0.3; let ticking = false; window.addEventListener('resize', () => { triggerHeight = heroSection.offsetHeight * 0.3; }, { passive: true }); const updateLogos = () => { if (window.scrollY > triggerHeight) { navLogo.classList.add('show-nav-logo'); heroLogo.classList.add('hide-hero-logo'); } else { navLogo.classList.remove('show-nav-logo'); heroLogo.classList.remove('hide-hero-logo'); } ticking = false; }; const handleScroll = () => { if (!ticking) { window.requestAnimationFrame(updateLogos); ticking = true; } }; window.addEventListener('scroll', handleScroll, { passive: true }); updateLogos(); // Initial check } }); </script> <!-- Code Guardian Overlay --> <div class="ac-guardian-overlay" id="codeGuardian"> <div class="ac-guardian-content"> <div class="ac-guardian-icon"> <i class="fas fa-bolt"></i> </div> <h2 class="ac-guardian-title"><?= htmlspecialchars($ajustesMap['guardian_title'] ?? 'Tu visión es el motor') ?></h2> <p class="ac-guardian-quote"> <?= htmlspecialchars($ajustesMap['guardian_quote'] ?? '"No busques cómo está construido el éxito ajeno, construye los cimientos del tuyo. El código es solo el lenguaje, tu determinación es el mensaje."') ?> </p> <button class="ac-guardian-btn" onclick="closeGuardian()"> Continuar Creando <i class="fas fa-arrow-right"></i> </button> </div> </div> <script> // Code Guardian Logic const guardianEnabled = "<?= $ajustesMap['guardian_enabled'] ?? '1' ?>" === "1"; const guardian = document.getElementById('codeGuardian'); function openGuardian() { if (guardianEnabled && guardian) guardian.classList.add('active'); } function closeGuardian() { if (guardian) guardian.classList.remove('active'); } if (guardianEnabled) { // Bloqueo de atajos de teclado document.addEventListener('keydown', function(e) { // Ctrl+U (Ver código fuente) if ((e.ctrlKey || e.metaKey) && e.keyCode === 85) { e.preventDefault(); openGuardian(); return false; } // F12 (DevTools) if (e.keyCode === 123) { e.preventDefault(); openGuardian(); return false; } // Ctrl+Shift+I (Inspect) if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === 73) { e.preventDefault(); openGuardian(); return false; } // Ctrl+Shift+J (Console) if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === 74) { e.preventDefault(); openGuardian(); return false; } }); // Bloqueo de Clic Derecho document.addEventListener('contextmenu', function(e) { e.preventDefault(); openGuardian(); }); } </script> <!-- ═══════════════ AIRCAN AI CHAT WIDGET ═══════════════ --> <!-- Chat Trigger Button --> <button class="ac-chat-trigger" id="ac-chat-trigger" aria-label="Abrir chat de IA"> <span class="ac-chat-icon"><i class="fas fa-comments"></i></span> <span class="ac-chat-close-icon"><i class="fas fa-xmark"></i></span> <span class="ac-chat-badge" id="ac-chat-badge">1</span> </button> <!-- Chat Window --> <div class="ac-chat-window" id="ac-chat-window" role="dialog" aria-label="Chat con Aircan IA"> <!-- Header --> <div class="ac-chat-header"> <div class="ac-chat-header-avatar"> <img src="public/assets/img/ia.png" alt="Aircan IA"> </div> <div class="ac-chat-header-info"> <div class="ac-chat-header-title">Aircan IA</div> <div class="ac-chat-header-status">En línea</div> </div> <div class="ac-chat-header-actions"> <button class="ac-chat-header-btn ac-chat-btn-restart" id="ac-chat-restart" title="Reiniciar conversación"> <i class="fas fa-arrow-rotate-left"></i> </button> <button class="ac-chat-header-btn" id="ac-chat-minimize" title="Minimizar"> <i class="fas fa-minus"></i> </button> </div> </div> <!-- Messages --> <div class="ac-chat-messages" id="ac-chat-messages"> <!-- Welcome (rendered by JS) --> </div> <!-- Typing Indicator --> <div class="ac-chat-typing" id="ac-chat-typing"> <div class="ac-chat-typing-avatar"> <img src="public/assets/img/ia.png" alt="Aircan IA"> </div> <div class="ac-chat-typing-dots"> <span></span><span></span><span></span> </div> </div> <!-- Input Area --> <div class="ac-chat-input-area"> <div class="ac-chat-input-wrapper"> <textarea class="ac-chat-input" id="ac-chat-input" placeholder="Escribe tu mensaje..." rows="1" aria-label="Escribe tu mensaje" ></textarea> <button class="ac-chat-send-btn" id="ac-chat-send" aria-label="Enviar mensaje"> <i class="fas fa-paper-plane"></i> </button> </div> </div> <!-- Powered By --> <div class="ac-chat-powered"> Potenciado por <span>Aircan IA</span> </div> <!-- Confirm Restart Dialog --> <div class="ac-chat-confirm-overlay" id="ac-chat-confirm"> <div class="ac-chat-confirm-box"> <i class="fas fa-triangle-exclamation"></i> <h4>¿Reiniciar conversación?</h4> <p>Se eliminará todo el historial de este chat. Esta acción no se puede deshacer.</p> <div class="ac-chat-confirm-btns"> <button class="ac-chat-confirm-cancel" id="ac-chat-confirm-cancel">Cancelar</button> <button class="ac-chat-confirm-yes" id="ac-chat-confirm-yes">Sí, reiniciar</button> </div> </div> </div> </div> <!-- Chat JS --> <script src="public/assets/js/aircan-chat.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { AircanChat.init('<?= htmlspecialchars($ajustesMap['whatsapp_number'] ?? '') ?>'); }); </script> <!-- ═══════════════ END AIRCAN AI CHAT ═══════════════ --> </body> </html>
Coded With 💗 by
0x6ick