diff --git a/README.md b/README.md index c66865f..1cba748 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,12 @@ [![Contributors](https://img.shields.io/github/contributors/mrinalray/Cybershield_URL?style=for-the-badge&color=8b5cf6&label=Contributors)](https://github.com/mrinalray/Cybershield_URL/graphs/contributors) [![Stars](https://img.shields.io/github/stars/mrinalray/Cybershield_URL?style=for-the-badge&color=f59e0b)](https://github.com/mrinalray/Cybershield_URL/stargazers) - +* πŸ” **Real-time URL scanning** +* πŸ›‘οΈ **Detects phishing, malware, and social engineering threats** +* ⚑ **Fast and responsive UI** +* 🌐 **Uses Google Safe Browsing API** +* βœ… **Simple and user-friendly interface** +* πŸ“Έ **Screenshot URL Scanner** --- diff --git a/index.html b/index.html index 7033a3a..0a95769 100644 --- a/index.html +++ b/index.html @@ -1,174 +1,182 @@ - - - - - - CyberShield β€” URL Security Scanner - - - - - - -
-
-
-
- - - -
-
-
CyberShield
-
Your Security, In Your Hands
-
-
-
- - - - - - - - - - + + + + + + CyberShield β€” URL Security Scanner + + + + + +
+
+
+ +
CyberShield
+
Your Security, In Your Hands.
+
+
+
+ + + + + + + diff --git a/script.js b/script.js index 2c902f0..80588c1 100644 --- a/script.js +++ b/script.js @@ -1,215 +1,338 @@ -// ═══════════════════════════════════ -// THEME β€” init immediately to prevent flash -// ═══════════════════════════════════ -(function initTheme() { - const saved = localStorage.getItem('theme') || 'dark'; - if (saved === 'light') { - document.documentElement.classList.add('light-mode'); - } -})(); - -// ═══════════════════════════════════ -// LOADER β€” skip on back-navigation -// ═══════════════════════════════════ -window.addEventListener('load', () => { - const loader = document.getElementById('loader'); - const main = document.getElementById('mainPage'); - if (!loader || !main) return; - - if (sessionStorage.getItem('introShown')) { - loader.style.display = 'none'; - main.classList.remove('hidden'); - } else { - setTimeout(() => { - loader.classList.add('fade-out'); - setTimeout(() => { - loader.style.display = 'none'; - main.classList.remove('hidden'); - sessionStorage.setItem('introShown', 'true'); - }, 500); - }, 3200); - } -}); - -// Handle bfcache (back/forward navigation) -window.addEventListener('pageshow', (e) => { - if (e.persisted) { - const loader = document.getElementById('loader'); - const main = document.getElementById('mainPage'); - if (loader) loader.style.display = 'none'; - if (main) { main.classList.remove('hidden'); main.style.opacity = '1'; } - } -}); - -// ═══════════════════════════════════ -// THEME TOGGLE -// ═══════════════════════════════════ -document.addEventListener('DOMContentLoaded', () => { - const btn = document.getElementById('themeToggle'); - if (btn) { - btn.addEventListener('click', () => { - const isLight = document.documentElement.classList.toggle('light-mode'); - localStorage.setItem('theme', isLight ? 'light' : 'dark'); - }); - } - - // Build team grid - buildTeam(); - - // Load persisted session stats - loadStats(); -}); - -// ═══════════════════════════════════ -// TEAM -// ═══════════════════════════════════ -const team = [ - { name: "Mrinal Roy", img: "Mrinal.jpg" }, - { name: "Rahul Sah", img: "Rahul.jpg" }, - { name: "Swastika Shaw", img: "Swastika.jpg" }, - { name: "Arpita Roy", img: "Arpita.jpg" }, - { name: "Disha Samanta", img: "Disha.jpg" }, -]; - -function buildTeam() { - const grid = document.getElementById('teamGrid'); - if (!grid) return; - grid.innerHTML = team.map(m => { - const initials = m.name.split(' ').map(w => w[0]).join(''); - return ` -
-
- ${m.name} -
-
${m.name}
-
`; - }).join(''); -} - -let teamOpen = false; - -function toggleTeam() { - teamOpen = !teamOpen; - const wrap = document.getElementById('teamGridWrap'); - const toggle = document.getElementById('teamToggle'); - if (!wrap || !toggle) return; - wrap.classList.toggle('open', teamOpen); - toggle.classList.toggle('open', teamOpen); - toggle.setAttribute('aria-label', teamOpen ? 'Hide team' : 'Show team'); -} - -// ═══════════════════════════════════ -// SCANNER -// ═══════════════════════════════════ -let totalScans = 0, safeCount = 0, dangerCount = 0; - -function loadStats() { - const history = JSON.parse(localStorage.getItem('cybershield_history') || '[]'); - totalScans = history.length; - safeCount = history.filter(r => r.status === 'safe').length; - dangerCount = history.filter(r => r.status === 'danger').length; - renderStats(); -} - -function renderStats() { - const t = document.getElementById('totalScans'); - const s = document.getElementById('safeCount'); - const d = document.getElementById('dangerCount'); - if (t) t.textContent = totalScans; - if (s) s.textContent = safeCount; - if (d) d.textContent = dangerCount; -} - -function fillExample(url) { - const input = document.getElementById('urlInput'); - if (input) { input.value = url; input.focus(); } -} - -function saveToHistory(url, status, threats) { - const history = JSON.parse(localStorage.getItem('cybershield_history') || '[]'); - history.push({ url, status, threats, timestamp: new Date().toISOString() }); - localStorage.setItem('cybershield_history', JSON.stringify(history)); -} - -function showResult(type, title, desc, url, threats) { - const el = document.getElementById('result'); - if (!el) return; - el.innerHTML = ` -
-
- ${type === 'loading' - ? '
' - : `${type === 'safe' ? 'βœ“' : type === 'danger' ? 'βœ•' : '!'}`} -
-
-
${title}
-
${desc}
- ${url ? `
${url}
` : ''} - ${threats && threats.length - ? `
${threats.map(t => `${t}`).join('')}
` - : ''} -
-
`; -} - -async function checkSecurity() { - const input = document.getElementById('urlInput'); - const btn = document.getElementById('scanBtn'); - const text = input ? input.value.trim() : ''; - - if (!text) { - showResult('error', 'Enter a URL', 'Paste the URL you want to check above.', '', []); - return; - } - - let url = text; - if (!url.startsWith('http://') && !url.startsWith('https://')) { - url = 'https://' + url; - } - - if (btn) btn.disabled = true; - showResult('loading', 'Scanning...', 'Checking against threat databases…', url, []); - - try { - const apiHost = 'https://cybershield-30a3.onrender.com'; - - const response = await fetch(`${apiHost}/check`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url }) - }); - - if (!response.ok) throw new Error(`Server error ${response.status}`); - const data = await response.json(); - console.log("API Response:", data); - if (data.error) throw new Error(data.error); - - if (data.matches && data.matches.length > 0) { - const threats = [...new Set(data.matches.map(m => m.threatType.replace(/_/g, ' ')))]; - totalScans++; dangerCount++; - renderStats(); - saveToHistory(url, 'danger', data.matches.map(m => m.threatType)); - showResult('danger', '⚠ Threat Detected', 'This URL is flagged as dangerous. Do not visit it.', url, threats); - } else { - totalScans++; safeCount++; - renderStats(); - saveToHistory(url, 'safe', []); - showResult('safe', 'βœ“ URL is Safe', 'No known threats detected via Google Safe Browsing.', url, []); - } - - } catch (err) { - showResult('error', 'Backend Not Connected', - `Ensure your backend server is running.
Error: ${err.message}`, '', []); - } finally { - if (btn) btn.disabled = false; - } -} - -document.addEventListener('DOMContentLoaded', () => { - const input = document.getElementById('urlInput'); - if (input) { - input.addEventListener('keydown', e => { - if (e.key === 'Enter') checkSecurity(); - }); - } -}); +// LOADER + +window.addEventListener('load', () => { + setTimeout(() => { + const loader = document.getElementById('loader'); + const main = document.getElementById('mainPage'); + loader.classList.add('fade-out'); + setTimeout(() => { + loader.style.display = 'none'; + main.classList.remove('hidden'); + }, 500); + }, 3200); +}); + + +// TEAM β€” collapsible + +const team = [ + { name: "Mrinal Roy", img: "Mrinal.jpg" }, + { name: "Rahul Sah", img: "Rahul.jpg" }, + { name: "Swastika Shaw", img: "Swastika.jpg" }, + { name: "Arpita Roy", img: "Arpita.jpg" }, + {name: "Disha Samanta", img: "Disha.jpg" }, +]; + +(function buildTeam() { + const grid = document.getElementById('teamGrid'); + grid.innerHTML = team.map(m => { + const initials = m.name.split(' ').map(w => w[0]).join(''); + return ` +
+
+ ${m.name} +
+
${m.name}
+
`; + }).join(''); +})(); + + +let teamOpen = false; + +function toggleTeam() { + teamOpen = !teamOpen; + const wrap = document.getElementById('teamGridWrap'); + const toggle = document.getElementById('teamToggle'); + if (teamOpen) { + wrap.classList.add('open'); + toggle.classList.add('open'); + toggle.setAttribute('aria-label', 'Hide team members'); + toggle.setAttribute('aria-expanded', 'true'); + } else { + wrap.classList.remove('open'); + toggle.classList.remove('open'); + toggle.setAttribute('aria-label', 'Show team members'); + toggle.setAttribute('aria-expanded', 'false'); + } +} + + + +// SCANNER + +let totalScans = 0, safeCount = 0, dangerCount = 0; + +function isValidUrl(urlString) { + try { + new URL(urlString); + return true; + } catch (e) { + return false; + } +} + +function formatAndValidateUrl(input) { + if (!input || input.trim() === '') { + return { valid: false, error: 'Enter a URL', url: null }; + } + + let url = input.trim(); + + if (!url.startsWith('http://') && !url.startsWith('https://')) { + url = 'https://' + url; + } + + if (!isValidUrl(url)) { + return { valid: false, error: 'Invalid URL format. Please enter a valid website URL.', url: null }; + } + + try { + const urlObj = new URL(url); + if (!urlObj.hostname) { + return { valid: false, error: 'URL must include a domain name.', url: null }; + } + return { valid: true, error: null, url: url }; + } catch (e) { + return { valid: false, error: 'Invalid URL. Please check and try again.', url: null }; + } +} + +function fillExample(url) { + document.getElementById('urlInput').value = url; + document.getElementById('urlInput').focus(); +} + +function updateStats(type) { + totalScans++; + if (type === 'safe') safeCount++; + if (type === 'danger') dangerCount++; + document.getElementById('totalScans').textContent = totalScans; + document.getElementById('safeCount').textContent = safeCount; + document.getElementById('dangerCount').textContent = dangerCount; +} + +function showResult(type, title, desc, url, threats) { + const icons = { safe: 'βœ“', danger: 'βœ•', loading: '', error: '!' }; + document.getElementById('result').innerHTML = ` +
+
+ ${type === 'loading' + ? '
' + : `${icons[type]}`} +
+
+
${title}
+
${desc}
+ ${url ? `
${url}
` : ''} + ${threats && threats.length + ? `
${threats.map(t => + `${t}`).join('')}
` + : ''} +
+
`; +} + +async function checkSecurity() { + const input = document.getElementById('urlInput').value; + const validation = formatAndValidateUrl(input); + + if (!validation.valid) { + showResult('error', 'Invalid Input', validation.error, '', []); + return; + } + + const url = validation.url; + const btn = document.getElementById('scanBtn'); + btn.disabled = true; + showResult('loading', 'Scanning...', 'Checking against threat databases. Please wait.', url, []); + + try { + const response = await fetch('https://cybershield-sxz0.onrender.com/check', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ url }) + }); + + if (!response.ok) throw new Error('Server error ' + response.status); + const data = await response.json(); + if (data.error) throw new Error(data.error); + + if (data.matches && data.matches.length > 0) { + const allThreats = data.matches.map(m => m.threatType); + const urlObj = new URL(url); + const isHttps = urlObj.protocol === 'https:'; + const hasPhishing = allThreats.includes('SOCIAL_ENGINEERING'); + const hasMalware = allThreats.includes('MALWARE'); + const hasUnwanted = allThreats.includes('UNWANTED_SOFTWARE'); + const hasHarmful = allThreats.includes('POTENTIALLY_HARMFUL_APPLICATION'); + const threats = [...new Set(allThreats.map(t => t.replace(/_/g, ' ')))]; + updateStats('danger'); + showResult('danger', 'Threat Detected!', + `This URL is flagged as dangerous. Do not visit it.

+
+
+ ${isHttps ? 'βœ…' : '⚠️'} HTTPS: ${isHttps ? 'Secure connection' : 'Not secure'} +
+
+ ${hasMalware ? 'πŸ”΄' : 'βœ…'} Malware: ${hasMalware ? 'Detected!' : 'No malware detected'} +
+
+ ${hasPhishing ? 'πŸ”΄' : 'βœ…'} Phishing: ${hasPhishing ? 'Phishing detected!' : 'No phishing detected'} +
+
+ ${hasUnwanted ? 'πŸ”΄' : 'βœ…'} Unwanted Software: ${hasUnwanted ? 'Detected!' : 'None detected'} +
+
+ ${hasHarmful ? 'πŸ”΄' : 'βœ…'} Harmful App: ${hasHarmful ? 'Detected!' : 'None detected'} +
+
`, url, threats); + } else { + updateStats('safe'); + const urlObj = new URL(url); + const isHttps = urlObj.protocol === 'https:'; + const allThreats = data.matches ? data.matches.map(m => m.threatType) : []; + const hasPhishing = allThreats.includes('SOCIAL_ENGINEERING'); + const hasMalware = allThreats.includes('MALWARE'); + const hasUnwanted = allThreats.includes('UNWANTED_SOFTWARE'); + const hasHarmful = allThreats.includes('POTENTIALLY_HARMFUL_APPLICATION'); + + showResult('safe', 'URL is Safe', + `No threats detected. Google Safe Browsing found no issues.

+
+
+ ${isHttps ? 'βœ…' : '⚠️'} HTTPS: ${isHttps ? 'Secure connection' : 'Not secure β€” use with caution'} +
+
+ ${hasMalware ? 'πŸ”΄' : 'βœ…'} Malware: ${hasMalware ? 'Detected!' : 'No malware detected'} +
+
+ ${hasPhishing ? 'πŸ”΄' : 'βœ…'} Phishing: ${hasPhishing ? 'Phishing detected!' : 'No phishing detected'} +
+
+ ${hasUnwanted ? 'πŸ”΄' : 'βœ…'} Unwanted Software: ${hasUnwanted ? 'Detected!' : 'None detected'} +
+
+ ${hasHarmful ? 'πŸ”΄' : 'βœ…'} Harmful App: ${hasHarmful ? 'Detected!' : 'None detected'} +
+
`, url, []); + } + + } catch (err) { + showResult('error', 'Backend Not Connected', + `Make sure your backend server is running.
+ Error: ${err.message}`, + '', []); + } finally { + btn.disabled = false; + } +} + +document.getElementById('urlInput').addEventListener('keydown', e => { + if (e.key === 'Enter') checkSecurity(); +}); +// SCREENSHOT UPLOAD β€” OCR URL EXTRACTION + +const dropZone = document.getElementById('dropZone'); +const fileInput = document.getElementById('fileInput'); +const previewImg = document.getElementById('previewImg'); +const ocrStatus = document.getElementById('ocrStatus'); + +const URL_REGEX = /\b((?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+(?:\/[^\s"'<>]*)?)\b/gi; + +function extractUrlsFromText(text) { + const matches = text.match(URL_REGEX) || []; + return [...new Set(matches.map(m => m.trim()))]; +} + +function setOcrStatus(msg, isError = false) { + ocrStatus.textContent = msg; + ocrStatus.style.color = isError ? '#ff5c7a' : '#94a3b8'; +} + +dropZone.addEventListener('click', () => fileInput.click()); + +dropZone.addEventListener('keydown', e => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + fileInput.click(); + } +}); + +['dragenter', 'dragover'].forEach(evt => + dropZone.addEventListener(evt, e => { + e.preventDefault(); + dropZone.classList.add('dragover'); + }) +); + +['dragleave', 'drop'].forEach(evt => + dropZone.addEventListener(evt, e => { + e.preventDefault(); + dropZone.classList.remove('dragover'); + }) +); + +dropZone.addEventListener('drop', e => { + const file = e.dataTransfer.files[0]; + if (file) handleImageFile(file); +}); + +fileInput.addEventListener('change', e => { + const file = e.target.files[0]; + if (file) handleImageFile(file); +}); + +function handleImageFile(file) { + if (!file.type.startsWith('image/')) { + setOcrStatus('Please upload an image file (PNG, JPG, etc.)', true); + return; + } + + const reader = new FileReader(); + reader.onload = e => { + previewImg.src = e.target.result; + previewImg.classList.remove('hidden'); + runOcr(file); + }; + reader.readAsDataURL(file); +} + +async function runOcr(file) { + if (typeof Tesseract === 'undefined') { + setOcrStatus('OCR engine failed to load. Check your connection.', true); + return; + } + + setOcrStatus('Reading text from screenshot…'); + + try { + const { data: { text } } = await Tesseract.recognize(file, 'eng', { + logger: m => { + if (m.status === 'recognizing text') { + setOcrStatus(`Reading screenshot… ${Math.round(m.progress * 100)}%`); + } + } + }); + + const urls = extractUrlsFromText(text); + + if (urls.length === 0) { + setOcrStatus('No URL found in that image. Try a clearer screenshot.', true); + return; + } + + const chosenUrl = urls[0]; + document.getElementById('urlInput').value = chosenUrl; + setOcrStatus( + urls.length > 1 + ? `Found ${urls.length} URLs β€” scanning the first: ${chosenUrl}` + : `Found URL: ${chosenUrl} β€” scanning…` + ); + + checkSecurity(); + } catch (err) { + setOcrStatus('Could not read text from that image. Try a clearer screenshot.', true); + } +} diff --git a/style.css b/style.css index 49e1885..6000eec 100644 --- a/style.css +++ b/style.css @@ -1,1297 +1,1095 @@ -/* ════════════════════════════════════════ - CYBERSHIELD β€” DESIGN SYSTEM - Signature: Sonar-pulse scanner hero rings -════════════════════════════════════════ */ - -/* ── Reset ── */ -*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } - -/* ── CSS Variables β€” Dark (default) ── */ -:root { - --bg: #020818; - --bg-2: #060f2a; - --bg-3: #0a1638; - --card-bg: rgba(10, 22, 56, 0.7); - --card-border: rgba(0, 245, 255, 0.12); - --card-hover: rgba(0, 245, 255, 0.06); - --text: #e8f4ff; - --text-muted: #4a6580; - --text-sub: #8aa4c0; - --accent-cyan: #00f5ff; - --accent-green: #00ff88; - --accent-red: #ff3366; - --accent-yellow: #ffcc00; - --gradient-main: linear-gradient(135deg, #00f5ff 0%, #00ff88 100%); - --gradient-danger:linear-gradient(135deg, #ff3366 0%, #ff8c42 100%); - --input-bg: rgba(6, 15, 42, 0.9); - --input-border: rgba(0, 245, 255, 0.2); - --input-focus: rgba(0, 245, 255, 0.4); - --safe-bg: rgba(0, 255, 136, 0.08); - --safe-border: rgba(0, 255, 136, 0.3); - --safe-color: #00ff88; - --danger-bg: rgba(255, 51, 102, 0.08); - --danger-border: rgba(255, 51, 102, 0.3); - --danger-color: #ff3366; - --warn-bg: rgba(255, 204, 0, 0.08); - --warn-border: rgba(255, 204, 0, 0.3); - --warn-color: #ffcc00; - --shadow-glow: 0 0 40px rgba(0, 245, 255, 0.08); - --shadow-card: 0 4px 32px rgba(0, 0, 0, 0.5); - --radius-card: 20px; - --radius-sm: 12px; - --radius-pill: 100px; -} - -/* ── Light Mode ── */ -html.light-mode { - --bg: #f0f4ff; - --bg-2: #e4ecff; - --bg-3: #d8e5ff; - --card-bg: rgba(255, 255, 255, 0.85); - --card-border: rgba(0, 120, 200, 0.15); - --card-hover: rgba(0, 120, 200, 0.05); - --text: #0a1638; - --text-muted: #8099b8; - --text-sub: #3a5580; - --accent-cyan: #0070cc; - --accent-green: #008844; - --accent-red: #cc2244; - --accent-yellow: #bb8800; - --gradient-main: linear-gradient(135deg, #0070cc 0%, #008844 100%); - --gradient-danger:linear-gradient(135deg, #cc2244 0%, #cc5500 100%); - --input-bg: rgba(255, 255, 255, 0.9); - --input-border: rgba(0, 112, 204, 0.25); - --input-focus: rgba(0, 112, 204, 0.4); - --safe-bg: rgba(0, 136, 68, 0.08); - --safe-border: rgba(0, 136, 68, 0.25); - --safe-color: #008844; - --danger-bg: rgba(204, 34, 68, 0.08); - --danger-border: rgba(204, 34, 68, 0.25); - --danger-color: #cc2244; - --warn-bg: rgba(187, 136, 0, 0.08); - --warn-border: rgba(187, 136, 0, 0.25); - --warn-color: #bb8800; - --shadow-glow: 0 0 40px rgba(0, 112, 204, 0.08); - --shadow-card: 0 4px 24px rgba(0, 0, 0, 0.1); -} - -/* ── Base ── */ -html { scroll-behavior: smooth; } - -body { - background: var(--bg); - color: var(--text); - font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; - min-height: 100vh; - overflow-x: hidden; - transition: background 0.3s, color 0.3s; -} - -/* Grid texture */ -body::before { - content: ''; - position: fixed; - inset: 0; - background-image: - linear-gradient(rgba(0,245,255,0.025) 1px, transparent 1px), - linear-gradient(90deg, rgba(0,245,255,0.025) 1px, transparent 1px); - background-size: 48px 48px; - pointer-events: none; - z-index: 0; - transition: opacity 0.3s; -} - -html.light-mode body::before { - background-image: - linear-gradient(rgba(0,112,204,0.04) 1px, transparent 1px), - linear-gradient(90deg, rgba(0,112,204,0.04) 1px, transparent 1px); -} - -.hidden { display: none !important; } - -/* ════════════════════════════════════════ - LOADER -════════════════════════════════════════ */ -#loader { - position: fixed; - inset: 0; - background: var(--bg); - display: flex; - align-items: center; - justify-content: center; - z-index: 9999; -} - -.loader-inner { - display: flex; - flex-direction: column; - align-items: center; - gap: 18px; - animation: fadeInUp 0.5s ease; -} - -.loader-sonar { - position: relative; - width: 100px; - height: 100px; - display: flex; - align-items: center; - justify-content: center; -} - -.loader-sonar::before, -.loader-sonar::after { - content: ''; - position: absolute; - border-radius: 50%; - border: 1px solid var(--accent-cyan); - animation: sonarPing 2s ease-out infinite; -} - -.loader-sonar::before { width: 100%; height: 100%; animation-delay: 0s; } -.loader-sonar::after { width: 70%; height: 70%; animation-delay: 0.5s; } - -@keyframes sonarPing { - 0% { transform: scale(0.8); opacity: 0.8; } - 100% { transform: scale(1.4); opacity: 0; } -} - -.loader-core { - width: 52px; - height: 52px; - border-radius: 50%; - background: rgba(0, 245, 255, 0.08); - border: 2px solid var(--accent-cyan); - display: flex; - align-items: center; - justify-content: center; - position: relative; - z-index: 1; - box-shadow: 0 0 20px rgba(0,245,255,0.3); - animation: corePulse 2s ease-in-out infinite; -} - -@keyframes corePulse { - 0%, 100% { box-shadow: 0 0 20px rgba(0,245,255,0.3); } - 50% { box-shadow: 0 0 40px rgba(0,245,255,0.6); } -} - -.loader-brand { - font-size: 20px; - font-weight: 800; - letter-spacing: 0.15em; - text-transform: uppercase; - background: var(--gradient-main); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.loader-tagline { - font-size: 12px; - color: var(--text-muted); - letter-spacing: 0.1em; - text-transform: uppercase; -} - -.loader-bar-wrap { - width: 200px; - height: 2px; - background: rgba(0, 245, 255, 0.1); - border-radius: 100px; - overflow: hidden; -} - -.loader-bar { - height: 100%; - background: var(--gradient-main); - border-radius: 100px; - animation: loadBar 3s cubic-bezier(0.4, 0, 0.2, 1) forwards; -} - -@keyframes loadBar { - 0% { width: 0%; } - 30% { width: 45%; } - 70% { width: 80%; } - 100% { width: 100%; } -} - -#loader.fade-out { - animation: loaderFade 0.5s ease forwards; -} - -@keyframes loaderFade { to { opacity: 0; pointer-events: none; } } - -/* ════════════════════════════════════════ - LAYOUT -════════════════════════════════════════ */ -#mainPage { - animation: pageIn 0.6s ease; - position: relative; - z-index: 1; -} - -@keyframes pageIn { - from { opacity: 0; transform: translateY(16px); } - to { opacity: 1; transform: translateY(0); } -} - -@keyframes fadeInUp { - from { opacity: 0; transform: translateY(20px); } - to { opacity: 1; transform: translateY(0); } -} - -.wrapper { - position: relative; - z-index: 1; - max-width: 820px; - margin: 0 auto; - padding: 60px 24px 80px; -} - -/* ════════════════════════════════════════ - THEME TOGGLE -════════════════════════════════════════ */ -.theme-toggle-btn { - position: fixed; - top: 20px; - right: 20px; - z-index: 1000; - width: 44px; - height: 44px; - border-radius: 50%; - background: var(--card-bg); - border: 1px solid var(--card-border); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - backdrop-filter: blur(12px); - transition: all 0.2s; - color: var(--text); -} - -.theme-toggle-btn:hover { - border-color: var(--accent-cyan); - box-shadow: 0 0 16px rgba(0,245,255,0.2); -} - -.toggle-icon-wrap { - position: relative; - width: 20px; - height: 20px; -} - -.sun-icon, .moon-icon { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - transition: opacity 0.3s, transform 0.3s; -} - -html:not(.light-mode) .sun-icon { opacity: 0; transform: rotate(90deg) scale(0.5); } -html:not(.light-mode) .moon-icon { opacity: 1; transform: rotate(0deg) scale(1); } -html.light-mode .sun-icon { opacity: 1; transform: rotate(0deg) scale(1); } -html.light-mode .moon-icon { opacity: 0; transform: rotate(-90deg) scale(0.5); } - -/* ════════════════════════════════════════ - HEADER -════════════════════════════════════════ */ -.header { - text-align: center; - margin-bottom: 56px; -} - -.logo-badge { - display: inline-flex; - align-items: center; - gap: 8px; - background: rgba(0, 245, 255, 0.06); - border: 1px solid rgba(0, 245, 255, 0.2); - border-radius: var(--radius-pill); - padding: 6px 18px; - font-size: 11px; - font-weight: 700; - letter-spacing: 0.14em; - text-transform: uppercase; - color: var(--accent-cyan); - margin-bottom: 28px; -} - -html.light-mode .logo-badge { - background: rgba(0, 112, 204, 0.06); - border-color: rgba(0, 112, 204, 0.2); -} - -.logo-badge .dot { - width: 6px; - height: 6px; - border-radius: 50%; - background: var(--accent-cyan); - animation: statusPulse 2s infinite; -} - -@keyframes statusPulse { - 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(0,245,255,0.4); } - 50% { opacity: 0.6; box-shadow: 0 0 0 4px rgba(0,245,255,0); } -} - -h1 { - font-size: clamp(32px, 5vw, 54px); - font-weight: 800; - letter-spacing: -0.04em; - line-height: 1.05; - margin-bottom: 16px; - color: var(--text); -} - -h1 span { - background: var(--gradient-main); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.subtitle { - font-size: 15px; - color: var(--text-sub); - max-width: 460px; - margin: 0 auto; - line-height: 1.7; -} - -/* ════════════════════════════════════════ - SCANNER CARD β€” SONAR HERO -════════════════════════════════════════ */ -.scanner-card { - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: var(--radius-card); - padding: 36px; - margin-bottom: 20px; - backdrop-filter: blur(20px); - box-shadow: var(--shadow-card), var(--shadow-glow); - position: relative; - overflow: hidden; -} - -.scanner-card::before { - content: ''; - position: absolute; - top: -60px; - right: -60px; - width: 200px; - height: 200px; - border-radius: 50%; - border: 1px solid var(--accent-cyan); - opacity: 0.06; - pointer-events: none; -} - -.scanner-card::after { - content: ''; - position: absolute; - top: -30px; - right: -30px; - width: 120px; - height: 120px; - border-radius: 50%; - border: 1px solid var(--accent-cyan); - opacity: 0.1; - pointer-events: none; -} - -.input-row { - display: flex; - gap: 12px; - align-items: stretch; -} - -.input-wrap { - flex: 1; - position: relative; -} - -.input-icon { - position: absolute; - left: 16px; - top: 50%; - transform: translateY(-50%); - width: 18px; - height: 18px; - color: var(--text-muted); - pointer-events: none; -} - -input[type="text"] { - width: 100%; - background: var(--input-bg); - border: 1px solid var(--input-border); - border-radius: var(--radius-sm); - padding: 16px 16px 16px 48px; - font-size: 14px; - color: var(--text); - outline: none; - transition: border-color 0.2s, background 0.2s, box-shadow 0.2s; - font-family: 'Courier New', monospace; -} - -input[type="text"]::placeholder { color: var(--text-muted); } - -input[type="text"]:focus { - border-color: var(--input-focus); - box-shadow: 0 0 0 3px rgba(0,245,255,0.08); -} - -html.light-mode input[type="text"]:focus { - box-shadow: 0 0 0 3px rgba(0,112,204,0.1); -} - -/* ── Scan Button ── */ -.scan-btn { - background: var(--gradient-main); - border: none; - border-radius: var(--radius-sm); - padding: 16px 28px; - font-size: 14px; - font-weight: 700; - color: #020818; - cursor: pointer; - white-space: nowrap; - display: inline-flex; - align-items: center; - gap: 8px; - transition: transform 0.15s, opacity 0.15s, box-shadow 0.2s; - text-decoration: none; - letter-spacing: 0.02em; -} - -.scan-btn:hover { - transform: translateY(-2px); - box-shadow: 0 8px 24px rgba(0,245,255,0.25); -} - -.scan-btn:active { transform: translateY(0); } -.scan-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; } - -/* ── Example chips ── */ -.examples { - margin-top: 18px; - display: flex; - gap: 8px; - flex-wrap: wrap; - align-items: center; -} - -.examples-label { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.1em; } - -.example-chip { - background: transparent; - border: 1px solid var(--card-border); - border-radius: 8px; - padding: 5px 12px; - font-size: 12px; - color: var(--text-sub); - cursor: pointer; - transition: all 0.15s; - font-family: 'Courier New', monospace; -} - -.example-chip:hover { - background: rgba(0,245,255,0.06); - color: var(--accent-cyan); - border-color: rgba(0,245,255,0.3); -} - -/* ════════════════════════════════════════ - RESULT CARD -════════════════════════════════════════ */ -#result { margin-top: 24px; } - -.result-card { - border-radius: 16px; - padding: 24px; - display: flex; - align-items: flex-start; - gap: 16px; - animation: slideUp 0.3s ease; -} - -@keyframes slideUp { - from { opacity: 0; transform: translateY(10px); } - to { opacity: 1; transform: translateY(0); } -} - -.result-card.safe { background: var(--safe-bg); border: 1px solid var(--safe-border); } -.result-card.danger { background: var(--danger-bg); border: 1px solid var(--danger-border); } -.result-card.loading { background: rgba(0,245,255,0.04); border: 1px solid rgba(0,245,255,0.15); } -.result-card.error { background: var(--warn-bg); border: 1px solid var(--warn-border); } - -.result-icon { - width: 48px; - height: 48px; - border-radius: 12px; - display: flex; - align-items: center; - justify-content: center; - font-size: 22px; - flex-shrink: 0; -} - -.result-card.safe .result-icon { background: rgba(0,255,136,0.12); } -.result-card.danger .result-icon { background: rgba(255,51,102,0.12); } -.result-card.loading .result-icon { background: rgba(0,245,255,0.12); } -.result-card.error .result-icon { background: rgba(255,204,0,0.12); } - -.result-title { - font-size: 17px; - font-weight: 700; - margin-bottom: 4px; -} - -.result-card.safe .result-title { color: var(--safe-color); } -.result-card.danger .result-title { color: var(--danger-color); } -.result-card.loading .result-title { color: var(--accent-cyan); } -.result-card.error .result-title { color: var(--warn-color); } - -.result-desc { - font-size: 13px; - color: var(--text-sub); - line-height: 1.6; -} - -.result-url { - margin-top: 10px; - font-family: 'Courier New', monospace; - font-size: 11px; - color: var(--text-muted); - background: rgba(0,0,0,0.2); - border-radius: 8px; - padding: 8px 12px; - word-break: break-all; -} - -html.light-mode .result-url { background: rgba(0,0,0,0.06); } - -.threat-tags { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-top: 12px; -} - -.threat-tag { - background: rgba(255,51,102,0.1); - border: 1px solid rgba(255,51,102,0.25); - border-radius: 6px; - padding: 3px 10px; - font-size: 11px; - font-weight: 600; - color: var(--danger-color); - text-transform: uppercase; - letter-spacing: 0.06em; -} - -/* ── Spinner ── */ -.spinner { - width: 22px; - height: 22px; - border: 2px solid rgba(0,245,255,0.2); - border-top-color: var(--accent-cyan); - border-radius: 50%; - animation: spin 0.8s linear infinite; -} - -@keyframes spin { to { transform: rotate(360deg); } } - -/* ════════════════════════════════════════ - STATS ROW -════════════════════════════════════════ */ -.stats-row { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 12px; - margin-top: 20px; -} - -.stat-card { - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: 14px; - padding: 22px 16px; - text-align: center; - backdrop-filter: blur(12px); - transition: border-color 0.2s, transform 0.2s; -} - -.stat-card:hover { - border-color: rgba(0,245,255,0.3); - transform: translateY(-2px); -} - -.stat-num { - font-size: 30px; - font-weight: 800; - background: var(--gradient-main); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - letter-spacing: -0.02em; -} - -.stat-label { - font-size: 11px; - color: var(--text-muted); - margin-top: 4px; - text-transform: uppercase; - letter-spacing: 0.1em; -} - -/* ════════════════════════════════════════ - FEATURES -════════════════════════════════════════ */ -.features { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 16px; - margin-top: 20px; -} - -.feature-item { - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: 14px; - padding: 22px; - backdrop-filter: blur(12px); - transition: border-color 0.2s, transform 0.2s; -} - -.feature-item:hover { - border-color: rgba(0,245,255,0.25); - transform: translateY(-2px); -} - -.feature-icon { font-size: 22px; margin-bottom: 12px; } - -.feature-title { - font-size: 13px; - font-weight: 700; - color: var(--text); - margin-bottom: 6px; - letter-spacing: 0.01em; -} - -.feature-desc { font-size: 12px; color: var(--text-muted); line-height: 1.6; } - -/* ════════════════════════════════════════ - TEAM SECTION -════════════════════════════════════════ */ -.team-section { - margin-top: 72px; - padding-top: 48px; - border-top: 1px solid var(--card-border); -} - -.team-header { text-align: center; margin-bottom: 28px; } - -.section-tag { - display: inline-block; - background: rgba(0,245,255,0.06); - border: 1px solid rgba(0,245,255,0.2); - border-radius: var(--radius-pill); - padding: 5px 18px; - font-size: 11px; - font-weight: 700; - letter-spacing: 0.14em; - text-transform: uppercase; - color: var(--accent-cyan); - margin-bottom: 14px; -} - -.team-title { - font-size: 28px; - font-weight: 800; - color: var(--text); - margin-bottom: 8px; - letter-spacing: -0.02em; -} - -.team-sub { - font-size: 14px; - color: var(--text-muted); -} - -.team-toggle { - display: flex; - align-items: center; - justify-content: center; - width: 44px; - height: 44px; - border-radius: 50%; - background: rgba(0,245,255,0.06); - border: 1px solid rgba(0,245,255,0.2); - color: var(--accent-cyan); - cursor: pointer; - margin: 0 auto 24px; - transition: background 0.2s, transform 0.35s cubic-bezier(0.4,0,0.2,1); -} - -.team-toggle:hover { background: rgba(0,245,255,0.12); } -.team-toggle.open { transform: rotate(180deg); } - -.team-grid-wrap { - overflow: hidden; - max-height: 0; - opacity: 0; - transition: max-height 0.45s cubic-bezier(0.4,0,0.2,1), opacity 0.35s ease; -} - -.team-grid-wrap.open { max-height: 400px; opacity: 1; } - -.team-grid { - display: grid; - grid-template-columns: repeat(5, 1fr); - gap: 16px; - padding-bottom: 8px; -} - -.member-card { - display: flex; - flex-direction: column; - align-items: center; - gap: 12px; - padding: 22px 12px; - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: 18px; - transition: border-color 0.2s, background 0.2s, transform 0.2s; - backdrop-filter: blur(12px); -} - -.member-card:hover { - border-color: rgba(0,245,255,0.3); - background: var(--card-hover); - transform: translateY(-4px); -} - -.member-avatar { - width: 80px; - height: 80px; - border-radius: 50%; - border: 2px solid var(--card-border); - overflow: hidden; - background: var(--bg-3); - display: flex; - align-items: center; - justify-content: center; - font-weight: 700; - font-size: 20px; - color: var(--accent-cyan); - transition: border-color 0.2s; -} - -.member-card:hover .member-avatar { border-color: var(--accent-cyan); } - -.member-avatar img { width: 100%; height: 100%; object-fit: cover; } - -.member-name { - font-size: 12px; - font-weight: 600; - color: var(--text-sub); - text-align: center; - line-height: 1.4; -} - -/* ════════════════════════════════════════ - FOOTER -════════════════════════════════════════ */ -.footer { - text-align: center; - margin-top: 64px; - font-size: 12px; - color: var(--text-muted); - letter-spacing: 0.05em; -} - -.main-footer { - background: var(--bg-2); - border-top: 1px solid var(--card-border); - padding: 48px 24px 24px; - margin-top: 80px; -} - -.footer-content { - max-width: 820px; - margin: 0 auto; - display: flex; - justify-content: space-between; - gap: 40px; - flex-wrap: wrap; - margin-bottom: 32px; -} - -.footer-brand p { - font-size: 13px; - color: var(--text-muted); - margin-top: 10px; - max-width: 240px; - line-height: 1.6; -} - -.footer-links { - display: flex; - gap: 48px; - flex-wrap: wrap; -} - -.footer-col { display: flex; flex-direction: column; gap: 8px; } - -.footer-col h4 { - font-size: 11px; - font-weight: 700; - letter-spacing: 0.14em; - text-transform: uppercase; - color: var(--text-muted); - margin-bottom: 4px; -} - -.footer-col a { - font-size: 13px; - color: var(--text-sub); - text-decoration: none; - transition: color 0.15s; -} - -.footer-col a:hover { color: var(--accent-cyan); } - -.footer-bottom { - max-width: 820px; - margin: 0 auto; - padding-top: 20px; - border-top: 1px solid var(--card-border); - font-size: 12px; - color: var(--text-muted); - text-align: center; -} - -/* ════════════════════════════════════════ - DASHBOARD -════════════════════════════════════════ */ -.dashboard-cta { - display: flex; - gap: 12px; - flex-wrap: wrap; - margin-bottom: 28px; -} - -.dashboard-grid { - display: grid; - grid-template-columns: 2fr 1fr; - gap: 16px; - margin-top: 20px; -} - -.dashboard-card { - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: var(--radius-card); - padding: 28px; - backdrop-filter: blur(12px); -} - -.dashboard-card h2 { - font-size: 16px; - font-weight: 700; - color: var(--text); - margin-bottom: 20px; - letter-spacing: 0.01em; -} - -.dashboard-note p { - font-size: 13px; - color: var(--text-muted); - line-height: 1.7; -} - -/* ════════════════════════════════════════ - CHAT PAGE -════════════════════════════════════════ */ -.chat-card { - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: var(--radius-card); - overflow: hidden; - backdrop-filter: blur(20px); - box-shadow: var(--shadow-card); -} - -.chat-container-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 24px; - border-bottom: 1px solid var(--card-border); - background: rgba(0,0,0,0.1); -} - -.chat-status { - display: flex; - align-items: center; - gap: 8px; - font-size: 12px; - font-weight: 600; - color: var(--accent-green); - letter-spacing: 0.05em; -} - -.chat-status-dot { - width: 8px; - height: 8px; - border-radius: 50%; - background: var(--accent-green); - animation: statusPulse 2s infinite; - box-shadow: 0 0 6px var(--accent-green); -} - -.chat-clear-btn { - padding: 6px 14px; - font-size: 11px; -} - -.chat-history { - height: 460px; - overflow-y: auto; - padding: 24px; - display: flex; - flex-direction: column; - gap: 16px; - scroll-behavior: smooth; -} - -.chat-history::-webkit-scrollbar { width: 4px; } -.chat-history::-webkit-scrollbar-track { background: transparent; } -.chat-history::-webkit-scrollbar-thumb { background: var(--card-border); border-radius: 4px; } - -.chat-msg { - display: flex; - gap: 12px; - align-items: flex-start; - animation: slideUp 0.3s ease; -} - -.chat-msg.user { - flex-direction: row-reverse; -} - -.chat-avatar { - width: 36px; - height: 36px; - border-radius: 50%; - background: rgba(0,245,255,0.08); - border: 1px solid var(--card-border); - display: flex; - align-items: center; - justify-content: center; - font-size: 16px; - flex-shrink: 0; -} - -.chat-bubble { - background: var(--bg-3); - border: 1px solid var(--card-border); - border-radius: 16px; - border-top-left-radius: 4px; - padding: 14px 18px; - font-size: 13px; - color: var(--text); - line-height: 1.6; - max-width: 78%; -} - -.chat-msg.user .chat-bubble { - background: rgba(0,245,255,0.08); - border-color: rgba(0,245,255,0.2); - border-radius: 16px; - border-top-right-radius: 4px; - color: var(--text); -} - -.user-bubble { - background: rgba(0,245,255,0.06) !important; - border-color: rgba(0,245,255,0.2) !important; -} - -.chat-bubble strong { color: var(--accent-cyan); } -.chat-welcome-text { margin-top: 6px; color: var(--text-sub); font-size: 13px; } - -/* Typing indicator */ -.typing-msg { padding: 0 24px; } - -.typing-indicator { - display: flex; - align-items: center; - gap: 5px; - padding: 14px 18px; - background: var(--bg-3); - border: 1px solid var(--card-border); - border-radius: 16px; - border-top-left-radius: 4px; - width: fit-content; -} - -.dot-bounce { - width: 7px; - height: 7px; - border-radius: 50%; - background: var(--accent-cyan); - opacity: 0.5; - animation: dotBounce 1.2s ease-in-out infinite; -} - -.dot-bounce:nth-child(1) { animation-delay: 0s; } -.dot-bounce:nth-child(2) { animation-delay: 0.2s; } -.dot-bounce:nth-child(3) { animation-delay: 0.4s; } - -@keyframes dotBounce { - 0%, 60%, 100% { transform: translateY(0); opacity: 0.5; } - 30% { transform: translateY(-8px); opacity: 1; } -} - -/* Chat input */ -.chat-input-wrap { - padding: 16px 24px; - border-top: 1px solid var(--card-border); - background: rgba(0,0,0,0.1); -} - -.chat-input-row { - display: flex; - gap: 10px; - align-items: flex-end; -} - -.chat-input-textarea { - flex: 1; - background: var(--input-bg); - border: 1px solid var(--input-border); - border-radius: var(--radius-sm); - padding: 12px 16px; - font-size: 13px; - color: var(--text); - outline: none; - resize: none; - font-family: inherit; - transition: border-color 0.2s, box-shadow 0.2s; - min-height: 44px; - max-height: 140px; - overflow-y: auto; - line-height: 1.5; -} - -.chat-input-textarea::placeholder { color: var(--text-muted); } - -.chat-input-textarea:focus { - border-color: var(--input-focus); - box-shadow: 0 0 0 3px rgba(0,245,255,0.06); -} - -.chat-send-btn { - padding: 12px 20px; - font-size: 13px; - flex-shrink: 0; -} - -/* Chat examples & features */ -.chat-examples-container { - margin-top: 16px; -} - -.chat-features-container { - margin-top: 16px; -} - -/* ── Report Bubble ── */ -.report-bubble { - max-width: 85% !important; - padding: 18px 20px !important; -} - -.classification-border-safe { border-color: var(--safe-border) !important; } -.classification-border-danger { border-color: var(--danger-border) !important; } -.classification-border-warn { border-color: var(--warn-border) !important; } -.classification-border-suspicious { border-color: var(--warn-border) !important; } - -.report-header-row { - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 12px; - flex-wrap: wrap; -} - -.report-badge { - display: inline-block; - padding: 3px 10px; - border-radius: 6px; - font-size: 11px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.08em; -} - -.classification-safe { background: var(--safe-bg); color: var(--safe-color); border: 1px solid var(--safe-border); } -.classification-danger { background: var(--danger-bg); color: var(--danger-color); border: 1px solid var(--danger-border); } -.classification-suspicious { background: var(--warn-bg); color: var(--warn-color); border: 1px solid var(--warn-border); } -.classification-warn { background: var(--warn-bg); color: var(--warn-color); border: 1px solid var(--warn-border); } - -.report-scam-type { - font-size: 12px; - color: var(--text-sub); - font-weight: 600; -} - -.report-explanation { - font-size: 13px; - color: var(--text-sub); - line-height: 1.65; - margin-bottom: 14px; -} - -.report-score-section { margin-bottom: 14px; } - -.report-score-labels { - display: flex; - justify-content: space-between; - font-size: 11px; - color: var(--text-muted); - margin-bottom: 6px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.08em; -} - -.report-progress-track { - height: 6px; - background: rgba(255,255,255,0.06); - border-radius: 100px; - overflow: hidden; -} - -.report-progress-bar { - height: 100%; - border-radius: 100px; - transition: width 1s cubic-bezier(0.4,0,0.2,1); -} - -.report-progress-bar.classification-safe { background: var(--safe-color); } -.report-progress-bar.classification-danger { background: var(--gradient-danger); } -.report-progress-bar.classification-suspicious { background: var(--accent-yellow); } - -.report-advice-box { - border-radius: 10px; - padding: 12px 14px; - font-size: 12px; - line-height: 1.6; -} - -.report-advice-box.classification-safe { background: var(--safe-bg); border: 1px solid var(--safe-border); color: var(--safe-color); } -.report-advice-box.classification-danger { background: var(--danger-bg); border: 1px solid var(--danger-border); color: var(--danger-color); } -.report-advice-box.classification-suspicious { background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn-color); } - -.report-advice-title { text-transform: uppercase; letter-spacing: 0.06em; font-size: 11px; } - -/* ════════════════════════════════════════ - DOCS / LEGAL PAGES -════════════════════════════════════════ */ -.docs-container, .legal-container { - max-width: 820px; - margin: 80px auto; - padding: 40px; - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: 24px; - backdrop-filter: blur(20px); -} - -.docs-container h1, .legal-container h1 { color: var(--accent-cyan); margin-bottom: 28px; font-size: 32px; } -.docs-container h2, .legal-container h2 { color: var(--text); margin-top: 36px; margin-bottom: 16px; border-bottom: 1px solid var(--card-border); padding-bottom: 10px; } -.docs-container h3 { color: var(--accent-cyan); margin-top: 24px; margin-bottom: 12px; font-size: 16px; } -.docs-container p, .docs-container li, .legal-container p, .legal-container li { color: var(--text-sub); line-height: 1.8; margin-bottom: 14px; font-size: 14px; } -.docs-container ul, .legal-container ul { padding-left: 20px; } - -.back-link { - display: inline-flex; - align-items: center; - gap: 6px; - margin-bottom: 28px; - color: var(--accent-cyan); - text-decoration: none; - font-weight: 600; - font-size: 13px; - transition: transform 0.2s; -} - -.back-link:hover { transform: translateX(-4px); } - -.code-block { - background: var(--input-bg); - padding: 18px; - border-radius: var(--radius-sm); - font-family: 'Courier New', monospace; - font-size: 13px; - color: var(--accent-green); - border: 1px solid var(--input-border); - margin: 20px 0; - overflow-x: auto; -} - -.status-badge { - display: inline-block; - padding: 4px 12px; - border-radius: 6px; - font-weight: 700; - font-size: 11px; - margin-right: 8px; - letter-spacing: 0.06em; -} - -.safe-badge { background: var(--safe-bg); color: var(--safe-color); border: 1px solid var(--safe-border); } -.danger-badge { background: var(--danger-bg); color: var(--danger-color); border: 1px solid var(--danger-border); } - -/* ════════════════════════════════════════ - SHARE PAGE -════════════════════════════════════════ */ -.share-card { - width: 100%; - max-width: 700px; - background: var(--card-bg); - border: 1px solid var(--card-border); - border-radius: 20px; - padding: 36px; - box-shadow: var(--shadow-card), var(--shadow-glow); - backdrop-filter: blur(20px); -} - -/* ════════════════════════════════════════ - RESPONSIVE -════════════════════════════════════════ */ -@media (max-width: 680px) { - .wrapper { padding: 40px 16px 60px; } - .input-row { flex-direction: column; } - .stats-row { grid-template-columns: 1fr 1fr; } - .team-grid { grid-template-columns: repeat(3, 1fr); } - .dashboard-grid { grid-template-columns: 1fr; } - .report-bubble { max-width: 96% !important; } - .docs-container, .legal-container { margin: 40px 16px; padding: 24px; } - .footer-content { flex-direction: column; gap: 24px; } -} - -@media (max-width: 400px) { - .team-grid { grid-template-columns: repeat(2, 1fr); } - .stats-row { grid-template-columns: 1fr; } -} - -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } -} +:root { + --bg-color: #050b18; + --text-color: #e2e8f0; + --accent-1: #00ffb4; + --accent-1-rgb: 0, 255, 180; + --accent-2: #00bfff; + --card-bg: rgba(255, 255, 255, 0.03); + --card-border: rgba(255, 255, 255, 0.08); + --subtitle-color: #64748b; + --label-color: #475569; + --input-bg: rgba(255, 255, 255, 0.05); + --input-border: rgba(255, 255, 255, 0.1); + --header-badge-bg: rgba(0, 255, 180, 0.08); + --header-badge-border: rgba(0, 255, 180, 0.2); + --safe-color: #00ffb4; + --safe-bg: rgba(0, 255, 180, 0.06); + --safe-border: rgba(0, 255, 180, 0.2); + --footer-bg: rgba(255, 255, 255, 0.02); +} + +.light-mode { + --bg-color: #f8fafc; + --text-color: #000000; + --accent-1: #f97316; + --accent-1-rgb: 249, 115, 22; + --accent-2: #ef4444; + --card-bg: #ffffff; + --card-border: rgba(249, 115, 22, 0.15); + --subtitle-color: #000000; + --label-color: #111111; + --input-bg: #ffffff; + --input-border: rgba(249, 115, 22, 0.25); + --header-badge-bg: rgba(249, 115, 22, 0.08); + --header-badge-border: rgba(249, 115, 22, 0.25); + --safe-color: #f97316; + --safe-bg: rgba(249, 115, 22, 0.06); + --safe-border: rgba(249, 115, 22, 0.2); + --footer-bg: #f1f5f9; +} + +* { margin: 0; padding: 0; box-sizing: border-box; } + +/* Screen reader only content */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +body { + background: var(--bg-color); + color: var(--text-color); + font-family: 'Segoe UI', system-ui, sans-serif; + min-height: 100vh; + overflow-x: hidden; + transition: background 0.3s, color 0.3s; +} + +body::before { + content: ''; + position: fixed; + inset: 0; + background-image: + linear-gradient(rgba(0,255,180,0.03) 1px, transparent 1px), + linear-gradient(90deg, rgba(0,255,180,0.03) 1px, transparent 1px); + background-size: 40px 40px; + pointer-events: none; + z-index: 0; + opacity: 1; +} + +.light-mode body::before { + background-image: + linear-gradient(rgba(249, 115, 22, 0.05) 1px, transparent 1px), + linear-gradient(90deg, rgba(249, 115, 22, 0.05) 1px, transparent 1px); +} + +.hidden { display: none !important; } + +/* ════════════════════════════ + LOADER +════════════════════════════ */ +#loader { + position: fixed; + inset: 0; + background: var(--bg-color); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + flex-direction: column; +} + +.loader-inner { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + animation: fadeInUp 0.5s ease; +} + +@keyframes fadeInUp { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +.loader-ring { + position: absolute; + width: 90px; + height: 90px; + border-radius: 50%; + border: 2px solid transparent; + border-top-color: var(--accent-1); + border-right-color: rgba(var(--accent-1-rgb, 0, 255, 180), 0.3); + animation: spin 1s linear infinite; +} + +.loader-logo { + width: 90px; + height: 90px; + border-radius: 50%; + background: var(--header-badge-bg); + border: 1px solid var(--header-badge-border); + display: flex; + align-items: center; + justify-content: center; + animation: logoPulse 2s ease-in-out infinite; +} + +@keyframes logoPulse { + 0%, 100% { box-shadow: 0 0 0 0 rgba(0,255,180,0.15); } + 50% { box-shadow: 0 0 0 12px rgba(0,255,180,0); } +} + +.loader-brand { + font-size: 22px; + font-weight: 700; + letter-spacing: 0.1em; + background: linear-gradient(135deg, var(--accent-1), var(--accent-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-top: 8px; +} + +.loader-tagline { + font-size: 13px; + color: #475569; + letter-spacing: 0.06em; +} + +.loader-bar-wrap { + width: 180px; + height: 3px; + background: rgba(255,255,255,0.06); + border-radius: 100px; + overflow: hidden; + margin-top: 8px; +} + +.loader-bar { + height: 100%; + width: 0%; + background: linear-gradient(90deg, var(--accent-1), var(--accent-2)); + border-radius: 100px; + animation: loadBar 3s ease forwards; +} + +@keyframes loadBar { + 0% { width: 0%; } + 40% { width: 60%; } + 80% { width: 85%; } + 100% { width: 100%; } +} + +#loader.fade-out { + animation: loaderFade 0.5s ease forwards; + pointer-events: none; +} + +@keyframes loaderFade { + to { opacity: 0; pointer-events: none; } +} + +/* ════════════════════════════ + MAIN PAGE +════════════════════════════ */ +#mainPage { + animation: pageIn 0.6s ease; +} + +@keyframes pageIn { + from { opacity: 0; transform: translateY(16px); } + to { opacity: 1; transform: translateY(0); } +} + +.wrapper { + position: relative; + z-index: 1; + max-width: 1200px; + margin: 0 auto; + padding: 60px 40px 80px; +} + +/* ── Theme Toggle ── */ +.theme-toggle-btn { + position: absolute; + top: 32px; + right: 24px; + width: 48px; + height: 48px; + border-radius: 12px; + background: var(--card-bg); + border: 1px solid var(--card-border); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + overflow: hidden; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.theme-toggle-btn:hover { + transform: scale(1.05); + border-color: var(--accent-1); + box-shadow: 0 0 15px rgba(0, 255, 180, 0.2); +} + +.toggle-icon-wrap { + position: relative; + width: 20px; + height: 20px; +} + +.sun-icon, .moon-icon { + position: absolute; + inset: 0; + transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); + color: var(--accent-1); +} + +.light-mode .sun-icon { + transform: translateY(30px) rotate(45deg); + opacity: 0; +} + +.light-mode .moon-icon { + transform: translateY(0) rotate(0); + opacity: 1; +} + +.sun-icon { + transform: translateY(0) rotate(0); + opacity: 1; +} + +.moon-icon { + transform: translateY(-30px) rotate(-45deg); + opacity: 0; +} + +/* ── Theme Toggle ── */ +.theme-toggle-btn { + position: absolute; + top: 32px; + right: 24px; + width: 48px; + height: 48px; + border-radius: 12px; + background: var(--card-bg); + border: 1px solid var(--card-border); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + overflow: hidden; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.theme-toggle-btn:hover { + transform: scale(1.05); + border-color: var(--accent-1); + box-shadow: 0 0 15px rgba(0, 255, 180, 0.2); +} + +.toggle-icon-wrap { + position: relative; + width: 20px; + height: 20px; +} + +.sun-icon, .moon-icon { + position: absolute; + inset: 0; + transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); + color: var(--accent-1); +} + +.light-mode .sun-icon { + transform: translateY(30px) rotate(45deg); + opacity: 0; +} + +.light-mode .moon-icon { + transform: translateY(0) rotate(0); + opacity: 1; +} + +.sun-icon { + transform: translateY(0) rotate(0); + opacity: 1; +} + +.moon-icon { + transform: translateY(-30px) rotate(-45deg); + opacity: 0; +} + +/* ── Header ── */ +.header { + text-align: center; + margin-bottom: 52px; +} + +.logo-badge { + display: inline-flex; + align-items: center; + gap: 8px; + background: var(--header-badge-bg); + border: 1px solid var(--header-badge-border); + border-radius: 100px; + padding: 6px 16px; + font-size: 12px; + font-weight: 600; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--accent-1); + margin-bottom: 24px; +} + +.logo-badge .dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--accent-1); + box-shadow: 0 0 10px var(--accent-1); +} + +@keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.4; transform: scale(0.8); } +} + +h1 { + font-size: clamp(32px, 5vw, 52px); + font-weight: 700; + letter-spacing: -0.03em; + line-height: 1.1; + margin-bottom: 16px; +} + +h1 span { + background: linear-gradient(135deg, var(--accent-1) 0%, var(--accent-2) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.subtitle { + font-size: 16px; + color: var(--subtitle-color); + max-width: 600px; + margin: 0 auto; + line-height: 1.6; +} + +/* ── Scanner Card ── */ +.scanner-card { + background: var(--card-bg); + border: 1px solid var(--card-border); + border-radius: 24px; + padding: 48px; + margin-bottom: 32px; + box-shadow: 0 4px 32px rgba(0, 0, 0, 0.1); + max-width: 900px; + margin-left: auto; + margin-right: auto; +} + +.input-row { + display: flex; + gap: 12px; + align-items: stretch; +} + +.input-wrap { + flex: 1; + position: relative; +} + +.input-icon { + position: absolute; + left: 16px; + top: 50%; + transform: translateY(-50%); + width: 18px; + height: 18px; + opacity: 0.4; + color: var(--text-color); +} + +input[type="text"] { + width: 100%; + background: var(--input-bg); + border: 1px solid var(--input-border); + border-radius: 12px; + padding: 16px 48px 16px 46px; + font-size: 15px; + color: var(--text-color); + outline: none; + transition: all 0.2s; + font-family: 'Courier New', monospace; +} + +input[type="text"]::placeholder { color: #475569; } + +input[type="text"]:focus { + border-color: var(--accent-1); + background: var(--input-bg); + box-shadow: 0 0 15px rgba(var(--accent-1-rgb), 0.1); +} + +.clear-btn { + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 6px; + width: 28px; + height: 28px; + display: none; + align-items: center; + justify-content: center; + color: #64748b; + cursor: pointer; + transition: all 0.2s; + z-index: 2; +} + +.clear-btn:hover { + background: rgba(255, 50, 50, 0.1); + color: #f87171; + border-color: rgba(255, 50, 50, 0.2); +} + +.scan-btn { + background: linear-gradient(135deg, var(--accent-1), var(--accent-2)); + border: none; + border-radius: 12px; + padding: 16px 28px; + font-size: 15px; + font-weight: 600; + color: white; + cursor: pointer; + white-space: nowrap; + display: flex; + align-items: center; + gap: 8px; + transition: transform 0.15s, opacity 0.15s; +} + +.scan-btn:hover { transform: translateY(-1px); opacity: 0.92; } +.scan-btn:active { transform: translateY(0); } +.scan-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; } + +.dashboard-cta { + display: flex; + justify-content: center; + margin-bottom: 32px; +} + +.dashboard-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 24px; + margin-bottom: 32px; +} + +.dashboard-card { + background: var(--card-bg); + border: 1px solid var(--card-border); + border-radius: 24px; + padding: 32px; + box-shadow: 0 18px 40px rgba(0, 0, 0, 0.08); +} + +.dashboard-card h2 { + margin-bottom: 16px; +} + +.dashboard-card ul { + padding-left: 20px; + color: var(--subtitle-color); + line-height: 1.8; +} + +.chart-card { + background: var(--input-bg); + border: 1px solid var(--input-border); + border-radius: 24px; + padding: 28px; + min-height: 220px; + display: flex; + flex-direction: column; + justify-content: center; + gap: 18px; +} + +.chart-placeholder { + width: 100%; + min-height: 140px; + border: 1px dashed var(--accent-1); + border-radius: 20px; + display: flex; + align-items: center; + justify-content: center; + color: var(--subtitle-color); + font-size: 14px; +} + +.dashboard-note { + grid-column: span 2; +} + +/* ── Example chips ── */ +.examples { + margin-top: 16px; + display: flex; + gap: 8px; + flex-wrap: wrap; + align-items: center; +} + +.examples-label { font-size: 12px; color: #475569; } + +.example-chip { + background: var(--input-bg); + border: 1px solid var(--input-border); + border-radius: 8px; + padding: 4px 12px; + font-size: 12px; + color: var(--subtitle-color); + cursor: pointer; + transition: all 0.15s; + font-family: 'Courier New', monospace; + background: none; + font-weight: inherit; +} + +.example-chip:hover { + background: var(--header-badge-bg); + border-color: var(--accent-1); + color: var(--accent-1); + transform: translateY(-1px); +} + +.example-chip:focus { + outline: 2px solid rgba(0,255,180,0.6); + outline-offset: 2px; + background: rgba(0,255,180,0.08); + color: #00ffb4; +} + +/* ── Result ── */ +#result { margin-top: 24px; } + +.result-card { + border-radius: 16px; + padding: 24px; + display: flex; + align-items: flex-start; + gap: 16px; + animation: slideUp 0.3s ease; +} + +@keyframes slideUp { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: translateY(0); } +} + +.result-card.safe { background: var(--safe-bg); border: 1px solid var(--safe-border); } +.result-card.danger { background: rgba(255,50,50,0.06); border: 1px solid rgba(255,50,50,0.25); } +.result-card.loading { background: rgba(0,191,255,0.05); border: 1px solid rgba(0,191,255,0.15); } +.result-card.error { background: rgba(255,170,0,0.05); border: 1px solid rgba(255,170,0,0.2); } + +.result-icon { + width: 48px; + height: 48px; + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + font-size: 22px; + flex-shrink: 0; +} + +.result-card.safe .result-icon { background: var(--safe-border); opacity: 0.8; } +.result-card.danger .result-icon { background: rgba(255,50,50,0.12); } +.result-card.loading .result-icon { background: rgba(0,191,255,0.12); } +.result-card.error .result-icon { background: rgba(255,170,0,0.12); } + +.result-body { flex: 1; } + +.result-title { + font-size: 18px; + font-weight: 600; + margin-bottom: 4px; +} + +.result-card.safe .result-title { color: var(--safe-color); } +.result-card.danger .result-title { color: #f87171; } +.result-card.loading .result-title { color: #60bfff; } +.result-card.error .result-title { color: #fbbf24; } + +.result-desc { + font-size: 14px; + color: #64748b; + line-height: 1.5; +} + +.result-url { + margin-top: 10px; + font-family: 'Courier New', monospace; + font-size: 12px; + color: #475569; + background: rgba(255,255,255,0.04); + border-radius: 8px; + padding: 8px 12px; + word-break: break-all; +} + +.threat-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 12px; +} + +.threat-tag { + background: rgba(255,50,50,0.12); + border: 1px solid rgba(255,50,50,0.2); + border-radius: 6px; + padding: 3px 10px; + font-size: 12px; + font-weight: 500; + color: #f87171; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +/* ── Spinner ── */ +.spinner { + width: 22px; + height: 22px; + border: 2px solid rgba(0,191,255,0.2); + border-top-color: #00bfff; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { to { transform: rotate(360deg); } } + +/* ── Stats ── */ +.stats-row { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 12px; + margin-top: 24px; +} + +.stat-card { + background: var(--card-bg); + border: 1px solid var(--card-border); + border-radius: 14px; + padding: 20px 16px; + text-align: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); +} + +.stat-num { + font-size: 28px; + font-weight: 700; + background: linear-gradient(135deg, var(--accent-1), var(--accent-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.stat-label { + font-size: 11px; + color: #475569; + margin-top: 4px; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +/* ── Features ── */ +.features { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 16px; + margin-top: 24px; +} + +.feature-item { + background: var(--card-bg); + border: 1px solid var(--card-border); + border-radius: 14px; + padding: 20px; + transition: transform 0.2s; +} + +.feature-item:hover { + transform: translateY(-5px); + border-color: var(--accent-1); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); +} + +.feature-icon { font-size: 20px; margin-bottom: 10px; } + +.feature-title { + font-size: 14px; + font-weight: 600; + color: var(--text-color); + margin-bottom: 4px; +} + +.feature-desc { font-size: 12px; color: var(--subtitle-color); line-height: 1.5; } + +/* ════════════════════════════ + TEAM SECTION +════════════════════════════ */ +.team-section { + margin-top: 72px; + padding-top: 48px; + border-top: 1px solid var(--card-border); +} + +.team-header { + text-align: center; + margin-bottom: 28px; +} + +.section-tag { + display: inline-block; + background: var(--header-badge-bg); + border: 1px solid var(--header-badge-border); + border-radius: 100px; + padding: 5px 16px; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--accent-1); + margin-bottom: 14px; +} + +.team-title { + font-size: 28px; + font-weight: 700; + color: var(--text-color); + margin-bottom: 8px; + letter-spacing: -0.02em; +} + +.team-sub { + font-size: 14px; + color: var(--subtitle-color); +} + +/* Toggle button */ +.team-toggle { + display: flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border-radius: 50%; + background: var(--header-badge-bg); + border: 1px solid var(--header-badge-border); + color: var(--accent-1); + cursor: pointer; + margin: 0 auto 24px; + transition: background 0.2s, transform 0.3s; +} + +.team-toggle:hover { + background: var(--header-badge-border); +} + +.team-toggle.open { + transform: rotate(180deg); +} + +/* Collapsible wrapper */ +.team-grid-wrap { + overflow: hidden; + max-height: 0; + transition: max-height 0.45s cubic-bezier(0.4, 0, 0.2, 1), + opacity 0.35s ease; + opacity: 0; +} + +.team-grid-wrap.open { + max-height: 400px; + opacity: 1; +} + +/* Grid */ +.team-grid { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 20px; + padding-bottom: 8px; +} + +.member-card { + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + padding: 24px 12px; + background: var(--card-bg); + border: 1px solid var(--card-border); + border-radius: 18px; + transition: all 0.2s; + width: 100%; +} + +.member-card:hover { + background: var(--header-badge-bg); + border-color: var(--accent-1); + transform: translateY(-4px); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08); +} + +.member-avatar { + width: 88px; + height: 88px; + border-radius: 50%; + border: 2px solid var(--header-badge-border); + overflow: hidden; + background: var(--input-bg); + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 22px; + color: var(--accent-1); + transition: border-color 0.2s; +} + +.member-card:hover .member-avatar { + border-color: var(--accent-1); +} + +.member-avatar img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.member-name { + font-size: 13px; + font-weight: 600; + color: var(--text-color); + text-align: center; + line-height: 1.4; +} + +/* ── Main Footer ── */ +.main-footer { + margin-top: 100px; + padding: 64px 0 32px; + border-top: 1px solid var(--card-border); + background: var(--footer-bg); + border-radius: 40px 40px 0 0; + position: relative; + z-index: 10; +} + +.footer-content { + display: grid; + grid-template-columns: 1.5fr 1fr 1fr; + gap: 80px; + margin-bottom: 60px; + max-width: 1000px; + margin-left: auto; + margin-right: auto; +} + +.footer-brand .logo-badge { + font-size: 14px; + padding: 8px 20px; +} + +.footer-brand p { + margin-top: 16px; + font-size: 14px; + color: var(--subtitle-color); + max-width: 280px; + line-height: 1.6; +} + +.footer-links { + display: flex; + gap: 60px; +} + +.footer-col h4 { + font-size: 13px; + font-weight: 700; + color: var(--accent-1); + text-transform: uppercase; + letter-spacing: 0.15em; + margin-bottom: 24px; +} + +.footer-col a { + display: block; + font-size: 14px; + color: var(--text-color); + opacity: 0.7; + text-decoration: none; + margin-bottom: 12px; + transition: all 0.2s; +} + +.footer-col a:hover { + color: var(--accent-1); + opacity: 1; + transform: translateX(4px); +} + +.footer-actions { + display: flex; + justify-content: flex-end; + align-items: flex-start; +} + +.theme-toggle-btn.secondary { display: none; } + +.footer-bottom { + text-align: center; + padding-top: 32px; + border-top: 1px solid var(--card-border); + font-size: 13px; + color: var(--label-color); + letter-spacing: 0.02em; +} + +/* ── Responsive ── */ +@media (max-width: 1024px) { + .wrapper { padding: 40px 24px; } + .footer-content { gap: 40px; } +} + +@media (max-width: 768px) { + .footer-content { + grid-template-columns: 1fr; + gap: 40px; + text-align: center; + } + + .footer-brand p { + max-width: 100%; + margin-left: auto; + margin-right: auto; + } + + .footer-links { + flex-direction: column; + gap: 32px; + align-items: center; + } + + .footer-col h4 { + margin-bottom: 16px; + } + + .footer-actions { + justify-content: center; + } + + .stats-row { + grid-template-columns: 1fr; + gap: 16px; + } + + .team-grid { + grid-template-columns: repeat(2, 1fr); + } + + .features { + grid-template-columns: 1fr; + } +} +.breakdown { + margin-top: 10px; + display: flex; + flex-direction: column; + gap: 6px; +} + +.breakdown-item { + font-size: 0.9rem; + color: #a0aec0; +} +@media (max-width: 600px) { + .header h1 { font-size: 32px; } + .scanner-card { padding: 24px; } + .input-row { + flex-direction: column; + gap: 16px; + } + .scan-btn { + width: 100%; + justify-content: center; + padding: 16px; + font-size: 16px; + } + .examples { + justify-content: center; + margin-top: 20px; + } + .examples-label { + width: 100%; + text-align: center; + margin-bottom: 8px; + } + .example-chip { + padding: 6px 14px; + font-size: 13px; + } + .team-grid { + grid-template-columns: 1fr; + } + .member-avatar { + width: 72px; + height: 72px; + } + .theme-toggle-btn { + top: 16px; + right: 16px; + width: 40px; + height: 40px; + } + .team-grid-wrap.open { + max-height: 2000px; + } +} + +@media (max-width: 380px) { + .team-grid { grid-template-columns: repeat(2, 1fr); } +} +.upload-row { margin-top: 16px; } +.drop-zone { + border: 2px dashed rgba(0,255,180,0.35); + border-radius: 14px; + padding: 28px 20px; + text-align: center; + cursor: pointer; + transition: border-color .2s, background .2s; +} +.drop-zone:hover, +.drop-zone.dragover { + border-color: #00ffb4; + background: rgba(0,255,180,0.06); +} +.drop-zone .upload-icon { width: 28px; height: 28px; color: #00ffb4; margin-bottom: 8px; } +.drop-zone-text { color: #cbd5e1; font-size: 14px; } +.drop-zone-sub { display: block; font-size: 12px; color: #64748b; margin-top: 4px; } +.preview-img { max-width: 100%; max-height: 160px; border-radius: 10px; margin-top: 12px; display: block; } +.hidden { display: none; } +.ocr-status { text-align: center; font-size: 13px; color: #94a3b8; margin-top: 8px; min-height: 18px; }