Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
20 pages enrichies: SEO/Services: finance-controlling-sap-fico offshore-nearshore-maroc formation-ia-sap-cloud-maroc digitalisation-processus-gouvernance-it erp-pme-eti-sap-odoo-sage recrutement-talent-it-maroc marketing-digital-maroc intelligence-artificielle-france-consulting consulting-sap-erp-vistex-maroc transformation-digitale-consulting-france-international crm-pharma-marketing-pharmaceutique cloud-infrastructure-systeme-information consulting-pharma-supply-chain consulting-intelligence-artificielle-maroc Login/Auth: office-login arsenal-login Diag/Tools: office-senders-diag v83-dark-scout-enriched Others: faq-anti-regression wevia-evolution Gemini UX quality audit launched BG: - /var/www/html/api/audit-gemini-ux-v5.js deploye - 8 pages phares captured (cockpit WTP wevia-master all-ia-hub orchestrator admin-saas tools-hub wevia-unified-hub) Cumul session: - 166 pages UX doctrine 60 (146 + 20) - 33 tags Opus - 30 doctrines vault (146-185) Handler battle-tested sur 105+ pages. ZERO regression. NR 153/153.
257 lines
11 KiB
HTML
257 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>V83 Dark Scout Enriched — SearXNG Market Intel</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
<style>
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
:root{--bg:#0a0e17;--bg2:#111827;--bg3:#1a2234;--bd:#1e293b;--wh:#f1f5f9;--mu:#64748b;--mu2:#94a3b8;--ac:#fbbf24;--cy:#22d3ee;--pk:#ec4899;--vi:#8b5cf6;--gn:#22c55e;--or:#f97316;--font:'Plus Jakarta Sans',sans-serif;--mono:'JetBrains Mono',monospace}
|
|
body{background:var(--bg);color:var(--wh);font-family:var(--font);padding:20px 32px;min-height:100vh}
|
|
a{color:var(--cy);text-decoration:none}a:hover{text-decoration:underline}
|
|
h1{font-size:22px;font-weight:800;margin-bottom:6px}h1 span{color:var(--ac)}
|
|
.sub{font-size:12px;color:var(--mu);margin-bottom:20px;font-family:var(--mono)}
|
|
.btns{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap}
|
|
.btn{padding:8px 16px;border:1px solid var(--bd);background:var(--bg2);color:var(--wh);border-radius:6px;font-size:12px;font-weight:600;text-decoration:none}
|
|
.btn:hover{border-color:var(--ac)}
|
|
.sec-title{font-size:14px;font-weight:700;margin:18px 0 10px;color:var(--ac);display:flex;align-items:center;gap:8px}
|
|
.sec-title::before{content:'';display:block;width:3px;height:14px;background:var(--ac);border-radius:2px}
|
|
|
|
.presets{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px;margin-bottom:18px}
|
|
.preset{background:var(--bg2);border:1px solid var(--bd);border-radius:8px;padding:10px 14px;cursor:pointer;transition:.2s}
|
|
.preset:hover{border-color:var(--ac);transform:translateY(-1px)}
|
|
.preset.active{border-color:var(--ac);background:var(--bg3)}
|
|
.p-emoji{font-size:18px;margin-bottom:4px}
|
|
.p-name{font-family:var(--mono);font-weight:700;font-size:11px;margin-bottom:2px}
|
|
.p-query{font-size:10px;color:var(--mu);font-family:var(--mono)}
|
|
|
|
.search-box{display:flex;gap:8px;margin-bottom:16px}
|
|
.search-box input{flex:1;background:var(--bg2);border:1px solid var(--bd);color:var(--wh);border-radius:6px;padding:10px 14px;font-family:var(--mono);font-size:12px;outline:none}
|
|
.search-box input:focus{border-color:var(--ac)}
|
|
.btn-scan{background:linear-gradient(135deg,var(--ac),var(--or));color:#000;border:none;padding:10px 22px;border-radius:6px;font-weight:700;cursor:pointer;font-family:var(--font)}
|
|
|
|
.cats-filter{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:16px}
|
|
.cat-pill{padding:5px 12px;border-radius:20px;background:var(--bg3);border:1px solid var(--bd);color:var(--mu2);font-size:10px;font-weight:700;cursor:pointer;font-family:var(--mono)}
|
|
.cat-pill.active{background:var(--ac);color:#000;border-color:var(--ac)}
|
|
.cat-pill .cnt{margin-left:6px;opacity:.7}
|
|
|
|
.results{display:flex;flex-direction:column;gap:8px}
|
|
.result{background:var(--bg2);border:1px solid var(--bd);border-radius:8px;padding:12px 14px;cursor:pointer;transition:.2s}
|
|
.result:hover{border-color:var(--cy)}
|
|
.r-cat{display:inline-block;font-size:9px;padding:2px 8px;border-radius:10px;font-family:var(--mono);font-weight:700;margin-bottom:6px;text-transform:uppercase}
|
|
.r-cat.sap{background:rgba(236,72,153,.15);color:var(--pk)}
|
|
.r-cat.pharma{background:rgba(34,197,94,.15);color:var(--gn)}
|
|
.r-cat.ai{background:rgba(139,92,246,.15);color:var(--vi)}
|
|
.r-cat.lead{background:rgba(249,115,22,.15);color:var(--or)}
|
|
.r-cat.competitor{background:rgba(239,68,68,.15);color:#ef4444}
|
|
.r-cat.cloud{background:rgba(34,211,238,.15);color:var(--cy)}
|
|
.r-cat.vistex{background:rgba(251,191,36,.15);color:var(--ac)}
|
|
.r-cat.general{background:rgba(148,163,184,.15);color:var(--mu2)}
|
|
.r-title{font-weight:700;font-size:14px;margin-bottom:4px}
|
|
.r-url{font-family:var(--mono);color:var(--cy);font-size:10px;margin-bottom:4px;word-break:break-all}
|
|
.r-snippet{font-size:12px;color:var(--mu2);line-height:1.4}
|
|
.r-meta{display:flex;gap:10px;font-size:10px;color:var(--mu);margin-top:6px;font-family:var(--mono)}
|
|
|
|
.loading{text-align:center;padding:30px;color:var(--mu)}
|
|
.stats{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:14px;font-size:11px;color:var(--mu);font-family:var(--mono)}
|
|
.stats b{color:var(--wh);font-size:14px}
|
|
</style>
|
|
<!-- DOCTRINE-60-UX-ENRICH direct-inject-20260424-143056 -->
|
|
<style id="doctrine60-ux-direct">
|
|
|
|
/* DOCTRINE-60-UX-ENRICH injected-direct */
|
|
body::before {
|
|
content: '';
|
|
position: fixed;
|
|
top: 0; left: 0; width: 100vw; height: 100vh;
|
|
background: radial-gradient(circle at 50% 50%, rgba(100,180,255,0.08), transparent 60%);
|
|
pointer-events: none;
|
|
z-index: -1;
|
|
}
|
|
.card, .kpi, .panel, .btn {
|
|
transition: all 0.3s cubic-bezier(0.2,0,0.1,1);
|
|
}
|
|
.card:hover, .kpi:hover, .panel:hover {
|
|
box-shadow: 0 4px 20px rgba(100,180,255,0.2);
|
|
border-color: rgba(100,180,255,0.5);
|
|
}
|
|
@keyframes pulseD60 {
|
|
0%,100% { opacity: 1; transform: scale(1); }
|
|
50% { opacity: 0.7; transform: scale(1.05); }
|
|
}
|
|
.pulse, .live-indicator, .active, .online {
|
|
animation: pulseD60 3s ease-in-out infinite;
|
|
}
|
|
.modal, .chat, .speech, .overlay {
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
}
|
|
.enter-stagger {
|
|
animation: enterStagD60 0.5s cubic-bezier(0.2,0,0.1,1) forwards;
|
|
}
|
|
@keyframes enterStagD60 {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1><span>V83</span> Dark Scout — SearXNG Market Intel <span style="font-size:12px;color:var(--gn);background:rgba(34,197,94,.15);padding:3px 9px;border-radius:4px;font-family:var(--mono);margin-left:8px">LIVE</span></h1>
|
|
<div class="sub">Enriched · 9 presets · multi-engine · classification auto · intel history 50 queries · doctrine 4 honest</div>
|
|
|
|
<div class="btns">
|
|
<a class="btn" href="/weval-technology-platform.html">← WTP</a>
|
|
<a class="btn" href="/growth-engine-v2.html">🚀 Growth Engine</a>
|
|
<a class="btn" href="/v82-unified-status.html">📊 V82 Status</a>
|
|
<a class="btn" href="/api/v83-dark-scout-enriched.php" target="_blank">🔧 JSON</a>
|
|
</div>
|
|
|
|
<div class="sec-title">🎯 Presets rapides (1-click)</div>
|
|
<div class="presets" id="presets"></div>
|
|
|
|
<div class="sec-title">🔍 Recherche custom</div>
|
|
<div class="search-box">
|
|
<input type="text" id="q" placeholder="ex: consulting SAP Maroc Casablanca, pharma digital MENA..." value="consulting SAP Maroc">
|
|
<button class="btn-scan" onclick="scan()">🔎 Scan</button>
|
|
</div>
|
|
|
|
<div class="stats" id="stats"></div>
|
|
|
|
<div class="sec-title">📊 Catégories (filter)</div>
|
|
<div class="cats-filter" id="cats-filter"></div>
|
|
|
|
<div class="sec-title">📋 Résultats</div>
|
|
<div class="results" id="results"><div class="loading">Clique un preset ou tape une requête pour scanner...</div></div>
|
|
|
|
<script>
|
|
const PRESETS_EMOJI = {
|
|
sap_maroc: '🏭',
|
|
pharma_intel: '💊',
|
|
erp_migration: '🔄',
|
|
devops_jobs: '👨💻',
|
|
ai_consulting: '🤖',
|
|
vistex_deals: '📋',
|
|
huawei_cloud: '☁️',
|
|
abbott_pharma: '🧬',
|
|
competitor_moroc: '🏢',
|
|
};
|
|
|
|
let PRESETS = {};
|
|
let ALL_RESULTS = [];
|
|
let ACTIVE_CAT = 'all';
|
|
|
|
async function loadPresets() {
|
|
const r = await fetch('/api/v83-dark-scout-enriched.php?preset=x').catch(()=>null);
|
|
// Just get preset list
|
|
const tmp = await fetch('/api/v83-dark-scout-enriched.php').then(r=>r.json()).catch(()=>({}));
|
|
PRESETS = tmp.presets_available || {};
|
|
const el = document.getElementById('presets');
|
|
el.innerHTML = Object.entries(PRESETS).map(([k,v]) => `
|
|
<div class="preset" onclick="scanPreset('${k}')">
|
|
<div class="p-emoji">${PRESETS_EMOJI[k]||'🔍'}</div>
|
|
<div class="p-name">${k.replace(/_/g,' ')}</div>
|
|
<div class="p-query">${v.slice(0,40)}...</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
async function scanPreset(p) {
|
|
document.querySelectorAll('.preset').forEach(x => x.classList.remove('active'));
|
|
event?.currentTarget?.classList.add('active');
|
|
document.getElementById('q').value = PRESETS[p] || '';
|
|
await doScan('preset=' + encodeURIComponent(p));
|
|
}
|
|
|
|
async function scan() {
|
|
const q = document.getElementById('q').value.trim();
|
|
if (!q) return;
|
|
await doScan('q=' + encodeURIComponent(q));
|
|
}
|
|
|
|
async function doScan(params) {
|
|
document.getElementById('results').innerHTML = '<div class="loading">🔎 SearXNG en cours...</div>';
|
|
try {
|
|
const r = await fetch('/api/v83-dark-scout-enriched.php?' + params);
|
|
const d = await r.json();
|
|
ALL_RESULTS = d.results || [];
|
|
|
|
// Stats
|
|
document.getElementById('stats').innerHTML = `
|
|
<div>query: <b>${d.query}</b></div>
|
|
<div>results: <b>${d.count}</b></div>
|
|
<div>engines: <b>${d.engines}</b></div>
|
|
<div>intel history: <b>${d.intel_history_count}</b></div>
|
|
`;
|
|
|
|
// Categories
|
|
const cats = d.categories || {};
|
|
document.getElementById('cats-filter').innerHTML =
|
|
`<div class="cat-pill active" onclick="filterCat('all')">All <span class="cnt">${d.count}</span></div>` +
|
|
Object.entries(cats).map(([k,v]) =>
|
|
`<div class="cat-pill" onclick="filterCat('${k}')">${k} <span class="cnt">${v}</span></div>`
|
|
).join('');
|
|
|
|
renderResults();
|
|
} catch(e) {
|
|
document.getElementById('results').innerHTML = `<div class="loading" style="color:#ef4444">Error: ${e.message}</div>`;
|
|
}
|
|
}
|
|
|
|
function filterCat(c) {
|
|
ACTIVE_CAT = c;
|
|
document.querySelectorAll('.cat-pill').forEach(p => p.classList.remove('active'));
|
|
event?.currentTarget?.classList.add('active');
|
|
renderResults();
|
|
}
|
|
|
|
function renderResults() {
|
|
const filtered = ACTIVE_CAT === 'all' ? ALL_RESULTS : ALL_RESULTS.filter(r => r.category === ACTIVE_CAT);
|
|
const el = document.getElementById('results');
|
|
if (!filtered.length) {
|
|
el.innerHTML = '<div class="loading">Aucun résultat pour cette catégorie</div>';
|
|
return;
|
|
}
|
|
el.innerHTML = filtered.map(r => `
|
|
<div class="result" onclick="window.open('${r.url}','_blank')">
|
|
<span class="r-cat ${r.category}">${r.category}</span>
|
|
<div class="r-title">${r.title || '—'}</div>
|
|
<div class="r-url">${r.url || ''}</div>
|
|
<div class="r-snippet">${r.snippet || ''}</div>
|
|
<div class="r-meta">
|
|
<span>engine: ${r.engine || '?'}</span>
|
|
<span>score: ${r.score?.toFixed?.(3) || '—'}</span>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
document.getElementById('q').addEventListener('keydown', e => { if (e.key === 'Enter') scan(); });
|
|
loadPresets();
|
|
</script>
|
|
|
|
<script src="/api/a11y-auto-enhancer.js" defer></script>
|
|
<!-- WTP_UDOCK_V1 (Opus 21-avr t34final) --><script src="/wtp-unified-dock.js" defer></script>
|
|
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
|
|
<!-- DOCTRINE-60-UX-JS --><script id="doctrine60-ux-js-direct">
|
|
|
|
// DOCTRINE-60-UX-JS staggered entrance
|
|
(function(){
|
|
if (!('IntersectionObserver' in window)) return;
|
|
const obs = new IntersectionObserver((entries) => {
|
|
entries.forEach((e, i) => {
|
|
if (e.isIntersecting) {
|
|
setTimeout(() => e.target.classList.add('enter-stagger'), i * 80);
|
|
obs.unobserve(e.target);
|
|
}
|
|
});
|
|
});
|
|
document.querySelectorAll('.card, .kpi, .panel').forEach(el => obs.observe(el));
|
|
})();
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|