// ═══════════════════════════════════════════════════════════ // SOURCES // ═══════════════════════════════════════════════════════════ const SOURCES = { dictionary: { bang: "!d", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://api.dictionaryapi.dev/api/v2/entries/en/${encodeURIComponent(q)}`, ); if (!r.ok) return []; const d = await r.json(); return d.slice(0, 3).flatMap((e) => e.meanings.slice(0, 2).map((m) => ({ meta: { phonetic: e.phonetic }, snippet: m.definitions[0]?.definition || "", source: "dictionary", title: `${e.word} [${m.partOfSpeech}]`, url: e.sourceUrls?.[0] || "#", })), ); }, name: "DICTIONARY", }, github: { bang: "!g", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://api.github.com/search/repositories?q=${encodeURIComponent(q)}&per_page=8&sort=stars`, ); const d = await r.json(); return (d.items || []).map((i) => ({ meta: { forks: i.forks_count, lang: i.language, stars: i.stargazers_count }, snippet: i.description || "NO DESCRIPTION", source: "github", title: i.full_name, url: i.html_url, })); }, name: "GITHUB", }, hackernews: { bang: "!hn", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(q)}&hitsPerPage=8`, ); const d = await r.json(); return (d.hits || []) .filter((h) => h.title) .map((h) => ({ meta: { comments: h.num_comments, points: h.points }, snippet: `${h.points || 0} POINTS // ${h.author}`, source: "hackernews", title: h.title, url: h.url || `https://news.ycombinator.com/item?id=${h.objectID}`, })); }, name: "HACKERNEWS", }, news: { bang: "!n", count: 0, enabled: true, fetch: async (q) => { // Combine HN, Reddit News, and Wiki Current Events logic const p1 = fetch( `https://hn.algolia.com/api/v1/search_by_date?query=${encodeURIComponent(q)}&tags=story&hitsPerPage=6`, ) .then((r) => r.json()) .catch(() => ({ hits: [] })); const p2 = fetch( `https://www.reddit.com/r/worldnews+news+technology/search.json?q=${encodeURIComponent(q)}&restrict_sr=1&sort=new&limit=6`, ) .then((r) => r.json()) .catch(() => ({ data: { children: [] } })); const [hn, rd] = await Promise.all([p1, p2]); const hnRes = (hn.hits || []).map((h) => ({ meta: { date: h.created_at_i, lang: "HN" }, snippet: `HACKERNEWS // ${h.points || 0} PTS // ${timeAgo(h.created_at_i * 1000)}`, source: "news", title: h.title, url: h.url || `https://news.ycombinator.com/item?id=${h.objectID}`, })); const rdRes = (rd.data?.children || []).map((c) => ({ meta: { date: c.data.created_utc, lang: "RD" }, snippet: `REDDIT r/${c.data.subreddit.toUpperCase()} // ${c.data.score} UPVOTES`, source: "news", title: c.data.title, url: `https://reddit.com${c.data.permalink}`, })); // Interleave/Sort by recency return [...hnRes, ...rdRes].sort((a, b) => b.meta.date - a.meta.date); }, name: "AGGREGATE NEWS", }, npm: { bang: "!npm", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://registry.npmjs.org/-/v1/search?text=${encodeURIComponent(q)}&size=8`, ); const d = await r.json(); return (d.objects || []).map((o) => ({ meta: { version: o.package.version }, snippet: o.package.description || "NO DESCRIPTION", source: "npm", title: o.package.name, url: `https://npmjs.com/package/${o.package.name}`, })); }, name: "NPM", }, openlibrary: { bang: "!b", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://openlibrary.org/search.json?q=${encodeURIComponent(q)}&limit=6`, ); const d = await r.json(); return (d.docs || []).map((b) => ({ meta: { year: b.first_publish_year }, snippet: `BY ${(b.author_name || ["UNKNOWN"]).join(", ").toUpperCase()}`, source: "openlibrary", title: b.title, url: `https://openlibrary.org${b.key}`, })); }, name: "OPENLIBRARY", }, reddit: { bang: "!r", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://www.reddit.com/search.json?q=${encodeURIComponent(q)}&limit=8`, ); const d = await r.json(); return (d.data?.children || []).map((c) => ({ meta: { comments: c.data.num_comments, score: c.data.score }, snippet: c.data.selftext?.substring(0, 200) || `r/${c.data.subreddit}`, source: "reddit", title: c.data.title, url: `https://reddit.com${c.data.permalink}`, })); }, name: "REDDIT", }, stackoverflow: { bang: "!so", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://api.stackexchange.com/2.3/search?order=desc&sort=relevance&intitle=${encodeURIComponent(q)}&site=stackoverflow&pagesize=8`, ); const d = await r.json(); return (d.items || []).map((i) => ({ meta: { answers: i.answer_count, score: i.score }, snippet: `${i.answer_count} ANSWERS // ${i.view_count} VIEWS`, source: "stackoverflow", title: decodeHTML(i.title), url: i.link, })); }, name: "STACKOVERFLOW", }, wikipedia: { bang: "!w", count: 0, enabled: true, fetch: async (q) => { const r = await fetch( `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(q)}&format=json&origin=*&srlimit=8`, ); const d = await r.json(); return (d.query?.search || []).map((i) => ({ meta: { words: i.wordcount }, snippet: i.snippet.replace(/<[^>]*>/g, ""), source: "wikipedia", title: i.title, url: `https://en.wikipedia.org/wiki/${encodeURIComponent(i.title)}`, })); }, instant: async (q) => { const s = await fetch( `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(q)}&format=json&origin=*&srlimit=1`, ); const sd = await s.json(); if (!sd.query?.search?.length) return null; const title = sd.query.search[0].title; const r = await fetch( `https://en.wikipedia.org/w/api.php?action=query&prop=extracts&exintro&explaintext&titles=${encodeURIComponent(title)}&format=json&origin=*`, ); const d = await r.json(); const page = Object.values(d.query.pages)[0]; return { content: page.extract, source: "WIKIPEDIA", title: page.title, url: `https://en.wikipedia.org/wiki/${encodeURIComponent(title)}`, }; }, name: "WIKIPEDIA", }, }; const STOCK_EXCHANGES = { AAPL: "NASDAQ", ADA: "CRYPTO", AMD: "NASDAQ", AMZN: "NASDAQ", BAC: "NYSE", BTC: "CRYPTO", DIS: "NYSE", DOGE: "CRYPTO", ETH: "CRYPTO", EURUSD: "FX", GBPUSD: "FX", GOOG: "NASDAQ", GOOGL: "NASDAQ", INTC: "NASDAQ", JNJ: "NYSE", JPM: "NYSE", KO: "NYSE", META: "NASDAQ", MSFT: "NASDAQ", NFLX: "NASDAQ", NVDA: "NASDAQ", PYPL: "NASDAQ", QQQ: "NASDAQ", SOL: "CRYPTO", SPY: "AMEX", TSLA: "NASDAQ", USDJPY: "FX", V: "NYSE", WMT: "NYSE", XOM: "NYSE", XRP: "CRYPTO", }; function getSymbol(ticker) { const t = ticker.toUpperCase(); const ex = STOCK_EXCHANGES[t]; if (ex === "CRYPTO") return `BINANCE:${t}USDT`; if (ex === "FX") return `FX:${t}`; if (ex) return `${ex}:${t}`; return `NASDAQ:${t}`; } // ═══════════════════════════════════════════════════════════ // STATE // ═══════════════════════════════════════════════════════════ const state = { calcExpr: "", calcResult: "0", hasSearched: false, history: JSON.parse(localStorage.getItem("sh") || "[]"), query: "", results: [], watchlist: JSON.parse(localStorage.getItem("sw") || '["TSLA", "AAPL", "BTC", "ETH"]'), }; const $ = (id) => document.getElementById(id); const searchInput = $("search-input"); const resultsEl = $("results"); const heroEl = $("hero"); const mainEl = $("main-content"); const statsBar = $("stats-bar"); // ═══════════════════════════════════════════════════════════ // INIT // ═══════════════════════════════════════════════════════════ function init() { renderSources(); renderHistory(); renderWatchlist(); initTheme(); updateClocks(); setInterval(updateClocks, 1000); setupCalc(); setupListeners(); setupWatchlistListeners(); } function renderSources() { $("sources-list").innerHTML = Object.entries(SOURCES) .map( ([k, s]) => `
${s.name} ${s.count}
`, ) .join(""); } function toggleSource(k) { SOURCES[k].enabled = !SOURCES[k].enabled; renderSources(); if (state.query) search(state.query); } function toggleWidget(id) { $(id).classList.toggle("open"); } // ═══════════════════════════════════════════════════════════ // THEME // ═══════════════════════════════════════════════════════════ function initTheme() { const t = localStorage.getItem("theme"); if (t === "light") document.body.classList.add("light-mode"); } function toggleTheme() { document.body.classList.toggle("light-mode"); const isLight = document.body.classList.contains("light-mode"); localStorage.setItem("theme", isLight ? "light" : "dark"); } // ═══════════════════════════════════════════════════════════ // WATCHLIST // ═══════════════════════════════════════════════════════════ function renderWatchlist() { const c = $("watchlist-container"); if (!state.watchlist.length) { c.innerHTML = '
EMPTY
'; return; } c.innerHTML = state.watchlist .map((t) => { const ex = STOCK_EXCHANGES[t] || "STOCK"; return `
${t} ${ex} ×
`; }) .join(""); } function addTicker() { const val = $("watchlist-input").value.toUpperCase().trim(); if (val && !state.watchlist.includes(val)) { state.watchlist.push(val); localStorage.setItem("sw", JSON.stringify(state.watchlist)); renderWatchlist(); $("watchlist-input").value = ""; } } window.removeTicker = (e, t) => { e.stopPropagation(); // Prevent search trigger state.watchlist = state.watchlist.filter((i) => i !== t); localStorage.setItem("sw", JSON.stringify(state.watchlist)); renderWatchlist(); }; function setupWatchlistListeners() { $("watchlist-add-btn").onclick = addTicker; $("watchlist-input").addEventListener("keydown", (e) => { if (e.key === "Enter") addTicker(); }); } // ═══════════════════════════════════════════════════════════ // SEARCH // ═══════════════════════════════════════════════════════════ async function search(query) { if (!query.trim()) return goHome(); // Show results view if (!state.hasSearched) { state.hasSearched = true; heroEl.classList.add("compact"); mainEl.style.display = "grid"; statsBar.classList.add("visible"); } // Stock ticker const stockMatch = query.match(/^\$([A-Za-z]{1,5})$/); if (stockMatch) { showStockWidget(stockMatch[1].toUpperCase()); addHistory(query); return; } // Bangs const bangMatch = query.match(/^!(\w+)\s*(.*)/); if (bangMatch) { const bang = `!${bangMatch[1]}`; const q = bangMatch[2]; const src = Object.entries(SOURCES).find(([_, s]) => s.bang === bang); if (src && q) { Object.keys(SOURCES).forEach((k) => (SOURCES[k].enabled = k === src[0])); renderSources(); query = q; } } // Calc if (query.startsWith("=")) { showCalcResult(query.slice(1)); return; } state.query = query; showLoading(); addHistory(query); const start = performance.now(); const enabled = Object.entries(SOURCES).filter(([_, s]) => s.enabled); fetchInstant(query); const promises = enabled.map(async ([k, s]) => { try { const r = await s.fetch(query); SOURCES[k].count = r.length; $(`c-${k}`).textContent = r.length; return r; } catch (e) { return []; } }); const all = await Promise.all(promises); state.results = all.flat(); const elapsed = Math.round(performance.now() - start); $("stat-results").textContent = state.results.length; $("stat-sources").textContent = enabled.length; $("stat-time").textContent = `${elapsed}MS`; $("results-label").textContent = `${state.results.length} RESULTS`; $("results-info").textContent = `${elapsed}MS // ${enabled.length} SOURCES`; renderResults(); } function goHome() { state.hasSearched = false; heroEl.classList.remove("compact"); mainEl.style.display = "none"; statsBar.classList.remove("visible"); searchInput.value = ""; } // ═══════════════════════════════════════════════════════════ // STOCK WIDGET // ═══════════════════════════════════════════════════════════ function showStockWidget(ticker) { const symbol = getSymbol(ticker); const widgetId = `tv_${Math.random().toString(36).substr(2, 9)}`; const isLight = document.body.classList.contains("light-mode"); resultsEl.innerHTML = `

${ticker}

${symbol}
`; $("results-label").textContent = `STOCK: ${ticker}`; $("results-info").textContent = symbol; loadTradingView(widgetId, symbol, isLight); } function loadTradingView(containerId, symbol, isLight) { if (!window.TradingView) { const s = document.createElement("script"); s.src = "https://s3.tradingview.com/tv.js"; s.onload = () => createChart(containerId, symbol, isLight); document.head.appendChild(s); } else { createChart(containerId, symbol, isLight); } } function createChart(containerId, symbol, isLight) { new TradingView.widget({ allow_symbol_change: true, backgroundColor: isLight ? "rgba(244, 244, 245, 1)" : "rgba(0,0,0,1)", container_id: containerId, enable_publishing: false, gridColor: isLight ? "rgba(220, 220, 220, 1)" : "rgba(30,30,30,1)", height: 500, interval: "D", locale: "en", studies: ["Volume@tv-basicstudies"], style: "1", symbol: symbol, theme: isLight ? "light" : "dark", timezone: "Etc/UTC", toolbar_bg: isLight ? "#f4f4f5" : "#000", width: "100%", }); } async function fetchInstant(query) { if (/^[a-zA-Z]+$/.test(query) && SOURCES.dictionary.enabled) { try { const r = await fetch( `https://api.dictionaryapi.dev/api/v2/entries/en/${encodeURIComponent(query)}`, ); if (r.ok) { const d = await r.json(); if (d[0]) { const meanings = d[0].meanings .slice(0, 3) .map((m) => `[${m.partOfSpeech.toUpperCase()}] ${m.definitions[0]?.definition}`) .join("\n\n"); showInstant({ content: meanings, source: "DICTIONARY", title: d[0].word.toUpperCase() + (d[0].phonetic ? ` ${d[0].phonetic}` : ""), }); return; } } } catch {} } if (SOURCES.wikipedia.enabled) { const w = await SOURCES.wikipedia.instant?.(query); if (w) showInstant(w); } } function showInstant(data) { const el = document.createElement("div"); el.className = "instant-box"; el.innerHTML = `
INSTANT ANSWER
${esc(data.title)}
${esc(data.content) .split("\n") .map((p) => `

${p}

`) .join("")}
SOURCE: ${esc(data.source)} ${data.url ? `VIEW FULL →` : ""}
`; resultsEl.innerHTML = ""; resultsEl.appendChild(el); } function renderResults() { if (state.results.length === 0) { resultsEl.innerHTML = `
NO RESULTS
TRY DIFFERENT KEYWORDS OR ENABLE MORE SOURCES
`; return; } const instant = resultsEl.querySelector(".instant-box"); resultsEl.innerHTML = ""; if (instant) resultsEl.appendChild(instant); state.results.forEach((r, i) => { const el = document.createElement("div"); el.className = "result"; el.innerHTML = `
${String(i + 1).padStart(2, "0")}
${r.source.toUpperCase()}
${esc(r.title)}
${esc(r.url)}
${highlight(esc(r.snippet), state.query)}
${ r.meta ? `
${r.meta.stars !== undefined ? `★ ${fmt(r.meta.stars)}` : ""} ${r.meta.forks !== undefined ? `⑂ ${fmt(r.meta.forks)}` : ""} ${r.meta.score !== undefined ? `↑ ${fmt(r.meta.score)}` : ""} ${r.meta.comments !== undefined ? `◨ ${fmt(r.meta.comments)}` : ""} ${r.meta.words !== undefined ? `◎ ${fmt(r.meta.words)}W` : ""} ${r.meta.lang ? `${r.meta.lang.toUpperCase()}` : ""} ${r.meta.version ? `V${r.meta.version}` : ""}
` : "" }
`; resultsEl.appendChild(el); }); } function showLoading() { resultsEl.innerHTML = Array(4) .fill( `
FETCHING
`, ) .join(""); } function showCalcResult(expr) { try { const result = Function(`"use strict";return (${expr.replace(/\^/g, "**")})`)(); resultsEl.innerHTML = `
CALCULATOR
${esc(expr)} = ${result}
`; } catch { toast("INVALID EXPRESSION"); } } // ═══════════════════════════════════════════════════════════ // CALCULATOR // ═══════════════════════════════════════════════════════════ function setupCalc() { document.querySelectorAll(".calc-btn").forEach((btn) => { btn.onclick = () => { const v = btn.dataset.v; if (v === "C") { state.calcExpr = ""; state.calcResult = "0"; } else if (v === "=") { try { state.calcResult = Function( `"use strict";return (${state.calcExpr.replace(/\^/g, "**")})`, )(); } catch { state.calcResult = "ERR"; } } else { state.calcExpr += v; } $("calc-expr").textContent = state.calcExpr; $("calc-result").textContent = state.calcResult; }; }); } // ═══════════════════════════════════════════════════════════ // TOOLS // ═══════════════════════════════════════════════════════════ function toolUUID() { const uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; return (c === "x" ? r : (r & 0x3) | 0x8).toString(16); }); copy(uuid); toast(`UUID: ${uuid.substring(0, 13)}...`); } let timerInterval, timerSec = 0; function toolTimer() { if (!state.hasSearched) { state.hasSearched = true; heroEl.classList.add("compact"); mainEl.style.display = "grid"; statsBar.classList.add("visible"); } resultsEl.innerHTML = `
TIMER
00:00:00
`; $("results-label").textContent = "TIMER"; } window.startTimer = () => { if (timerInterval) return; timerInterval = setInterval(() => { timerSec++; const h = String(Math.floor(timerSec / 3600)).padStart(2, "0"); const m = String(Math.floor((timerSec % 3600) / 60)).padStart(2, "0"); const s = String(timerSec % 60).padStart(2, "0"); $("timer-display").textContent = `${h}:${m}:${s}`; }, 1000); }; window.stopTimer = () => { clearInterval(timerInterval); timerInterval = null; }; window.resetTimer = () => { stopTimer(); timerSec = 0; $("timer-display").textContent = "00:00:00"; }; function toolBase64() { if (!state.hasSearched) { state.hasSearched = true; heroEl.classList.add("compact"); mainEl.style.display = "grid"; statsBar.classList.add("visible"); } resultsEl.innerHTML = `
BASE64
OUTPUT
`; $("results-label").textContent = "BASE64"; } function toolJSON() { if (!state.hasSearched) { state.hasSearched = true; heroEl.classList.add("compact"); mainEl.style.display = "grid"; statsBar.classList.add("visible"); } resultsEl.innerHTML = `
JSON
OUTPUT
`; $("results-label").textContent = "JSON"; } window.formatJSON = () => { try { $("json-output").textContent = JSON.stringify(JSON.parse($("json-input").value), null, 2); } catch (e) { $("json-output").textContent = `INVALID: ${e.message}`; } }; window.minifyJSON = () => { try { $("json-output").textContent = JSON.stringify(JSON.parse($("json-input").value)); } catch (e) { $("json-output").textContent = `INVALID: ${e.message}`; } }; function toolHash() { if (!state.hasSearched) { state.hasSearched = true; heroEl.classList.add("compact"); mainEl.style.display = "grid"; statsBar.classList.add("visible"); } resultsEl.innerHTML = `
SHA-256 HASH
OUTPUT
`; $("results-label").textContent = "HASH"; } window.genHash = async () => { const data = new TextEncoder().encode($("hash-input").value); const hash = await crypto.subtle.digest("SHA-256", data); $("hash-output").textContent = Array.from(new Uint8Array(hash)) .map((b) => b.toString(16).padStart(2, "0")) .join(""); }; function toolColor() { if (!state.hasSearched) { state.hasSearched = true; heroEl.classList.add("compact"); mainEl.style.display = "grid"; statsBar.classList.add("visible"); } resultsEl.innerHTML = `
COLOR
`; const updateColor = () => { const hex = $("color-input").value; const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); $("color-output").innerHTML = `HEX: ${hex}
RGB: ${r}, ${g}, ${b}
HSL: ${rgbToHsl(r, g, b)}`; }; $("color-input").oninput = updateColor; updateColor(); $("results-label").textContent = "COLOR"; } function rgbToHsl(r, g, b) { r /= 255; g /= 255; b /= 255; const max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if (max === min) { h = s = 0; } else { const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break; case g: h = ((b - r) / d + 2) / 6; break; case b: h = ((r - g) / d + 4) / 6; break; } } return `${Math.round(h * 360)}°, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%`; } function toolPassword() { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*"; let pass = ""; for (let i = 0; i < 20; i++) pass += chars[Math.floor(Math.random() * chars.length)]; copy(pass); toast(`PASSWORD: ${pass.substring(0, 10)}...`); } function toolLoremIpsum() { const lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris."; copy(lorem); toast("LOREM IPSUM COPIED"); } // ═══════════════════════════════════════════════════════════ // HISTORY // ═══════════════════════════════════════════════════════════ function addHistory(q) { state.history = state.history.filter((h) => h.q !== q); state.history.unshift({ q, t: Date.now() }); state.history = state.history.slice(0, 20); localStorage.setItem("sh", JSON.stringify(state.history)); renderHistory(); } function renderHistory() { const list = $("history-list"); if (!state.history.length) { list.innerHTML = '
NO HISTORY
'; return; } list.innerHTML = state.history .slice(0, 6) .map( (h) => `
${esc(h.q)}${timeAgo(h.t)}
`, ) .join(""); } // ═══════════════════════════════════════════════════════════ // CLOCKS // ═══════════════════════════════════════════════════════════ function updateClocks() { const now = new Date(); $("clock").textContent = now.toLocaleTimeString("en-GB"); const zones = [ { label: "LOCAL", tz: Intl.DateTimeFormat().resolvedOptions().timeZone }, { label: "UTC", tz: "UTC" }, { label: "NYC", tz: "America/New_York" }, { label: "TOKYO", tz: "Asia/Tokyo" }, ]; $("world-clocks").innerHTML = zones .map( (z) => `
${new Date().toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit", timeZone: z.tz })}
${z.label}
`, ) .join(""); } // ═══════════════════════════════════════════════════════════ // LISTENERS // ═══════════════════════════════════════════════════════════ function setupListeners() { let debounce; searchInput.addEventListener("input", (e) => { clearTimeout(debounce); debounce = setTimeout(() => search(e.target.value), 300); }); searchInput.addEventListener("keydown", (e) => { if (e.key === "Enter") { clearTimeout(debounce); search(searchInput.value); } if (e.key === "Escape") goHome(); }); document.addEventListener("keydown", (e) => { if ( e.key === "/" && document.activeElement !== searchInput && document.activeElement !== $("watchlist-input") ) { e.preventDefault(); searchInput.focus(); } if (e.key === "Escape") goHome(); }); $("clear-btn").onclick = goHome; $("voice-btn").onclick = voiceSearch; } function voiceSearch() { if (!("webkitSpeechRecognition" in window || "SpeechRecognition" in window)) { toast("VOICE NOT SUPPORTED"); return; } const Sr = window.SpeechRecognition || window.webkitSpeechRecognition; const r = new Sr(); r.lang = "en-US"; $("voice-btn").style.background = "#fff"; $("voice-btn").style.color = "#000"; r.onresult = (e) => { searchInput.value = e.results[0][0].transcript; search(searchInput.value); }; r.onend = () => { $("voice-btn").style.background = ""; $("voice-btn").style.color = ""; }; r.start(); } // ═══════════════════════════════════════════════════════════ // UTILITIES // ═══════════════════════════════════════════════════════════ function esc(s) { if (!s) return ""; return s.replace( /[&<>"']/g, (m) => ({ "'": "'", '"': """, "&": "&", "<": "<", ">": ">" })[m], ); } function decodeHTML(s) { const t = document.createElement("textarea"); t.innerHTML = s; return t.value; } function highlight(text, query) { if (!query) return text; const words = query.split(/\s+/).filter((w) => w.length > 2); let result = text; words.forEach((w) => { result = result.replace(new RegExp(`(${w})`, "gi"), "$1"); }); return result; } function fmt(n) { if (n >= 1000000) return `${(n / 1000000).toFixed(1)}M`; if (n >= 1000) return `${(n / 1000).toFixed(1)}K`; return n?.toString() || "0"; } function timeAgo(ts) { const s = Math.floor((Date.now() - ts) / 1000); if (s < 60) return "NOW"; if (s < 3600) return `${Math.floor(s / 60)}M`; if (s < 86400) return `${Math.floor(s / 3600)}H`; return `${Math.floor(s / 86400)}D`; } function copy(text) { navigator.clipboard.writeText(text); toast("COPIED"); } function toast(msg) { const t = document.createElement("div"); t.className = "toast"; t.textContent = msg; $("toast-container").appendChild(t); setTimeout(() => t.remove(), 3000); } function searchFor(q) { searchInput.value = q; search(q); } function insertBang(bang) { searchInput.value = `${bang} `; searchInput.focus(); } init();