agenticworkflowsspace commited on
Commit
cab72b0
·
verified ·
1 Parent(s): b4e93cd

Upload dashboard.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. dashboard.html +560 -0
dashboard.html ADDED
@@ -0,0 +1,560 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html class="light" lang="en">
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
6
+ <title>Trend Hunter AI | Multi-Platform Intelligence</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;600;700&family=Fira+Sans:wght@400;500;600&display=swap" rel="stylesheet"/>
8
+ <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
9
+ <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
10
+ <script>
11
+ tailwind.config = {
12
+ darkMode:"class",
13
+ theme:{extend:{
14
+ colors:{"on-tertiary-container":"#006127","secondary-dim":"#0046bb","outline-variant":"#a5adc6","on-background":"#272e42","surface-tint":"#b90035","on-secondary":"#f1f2ff","background":"#f6f6ff","tertiary-container":"#82ff99","surface-container-highest":"#d1dcff","on-primary-fixed":"#000000","secondary-container":"#c4d0ff","on-secondary-container":"#003ea9","on-secondary-fixed-variant":"#0047bd","surface-dim":"#c7d4fa","outline":"#6f768e","on-error":"#ffefec","on-primary-container":"#4e0011","on-tertiary-fixed-variant":"#006c2d","primary-dim":"#a2002d","inverse-surface":"#060e20","error":"#b02500","on-secondary-fixed":"#002d80","inverse-primary":"#ff5168","tertiary":"#006a2c","surface-variant":"#d1dcff","on-primary":"#ffefef","on-surface-variant":"#535b71","surface-bright":"#f6f6ff","on-tertiary":"#cfffcf","secondary-fixed":"#c4d0ff","on-surface":"#272e42","tertiary-dim":"#005d25","error-container":"#f95630","primary":"#b90035","surface-container":"#e2e7ff","surface-container-lowest":"#ffffff","inverse-on-surface":"#959cb5","on-primary-fixed-variant":"#5f0017","on-error-container":"#520c00","tertiary-fixed":"#82ff99","on-tertiary-fixed":"#004c1d","surface-container-low":"#eef0ff","primary-container":"#ff7481","secondary":"#0050d4","surface":"#f6f6ff","surface-container-high":"#d9e2ff"},
15
+ fontFamily:{"mono":["Fira Code","monospace"],"sans":["Fira Sans","sans-serif"],"headline":["Fira Code","monospace"],"body":["Fira Sans","sans-serif"]},
16
+ borderRadius:{"DEFAULT":"0.125rem","lg":"0.25rem","xl":"0.5rem","2xl":"1rem","full":"9999px"},
17
+ },},
18
+ }
19
+ </script>
20
+ <style>
21
+ .material-symbols-outlined{font-variation-settings:'FILL' 0,'wght' 400,'GRAD' 0,'opsz' 24;vertical-align:middle;}
22
+ body{font-family:'Fira Sans',sans-serif;background-color:#f6f6ff;color:#272e42;}
23
+ .fira-code{font-family:'Fira Code',monospace;}
24
+ .platform-btn-active{background-color:#0050d4!important;color:white!important;box-shadow:0 10px 15px -3px rgba(0,80,212,0.2);}
25
+ .platform-btn-inactive{background-color:#d9e2ff;color:#535b71;}
26
+ .hidden-section{display:none;}
27
+ .video-card{display:block;text-decoration:none;color:inherit;background:white;border-radius:1rem;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,0.08);transition:all 200ms ease;border:1px solid #eef0ff;}
28
+ .video-card:hover{transform:translateY(-3px);box-shadow:0 10px 20px rgba(0,0,0,0.1);}
29
+ .thumb-overlay{position:absolute;inset:0;background:rgba(0,0,0,0.35);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity 200ms;}
30
+ .video-card:hover .thumb-overlay{opacity:1;}
31
+ .platform-tab{cursor:pointer;padding:10px 18px;border-radius:10px;font-weight:600;font-size:0.85rem;transition:all 200ms;color:#535b71;}
32
+ .platform-tab.active{background:#0050d4;color:white;box-shadow:0 4px 12px rgba(0,80,212,0.25);}
33
+ .platform-pane{display:none;}
34
+ .platform-pane.active{display:block;}
35
+ .score-bar-fill{height:100%;border-radius:9999px;background:linear-gradient(90deg,#b90035,#ff7481);transition:width 1s ease;}
36
+ .idea-card{background:white;border:1px solid #eef0ff;border-left:4px solid #0050d4;border-radius:0.75rem;padding:14px 18px;font-size:0.9rem;cursor:pointer;transition:all 200ms;}
37
+ .idea-card:hover{background:#eef0ff;transform:translateX(4px);}
38
+ .history-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-radius:8px;cursor:pointer;transition:background 150ms;font-size:0.85rem;}
39
+ .history-item:hover{background:#eef0ff;}
40
+ .toast{position:fixed;bottom:24px;right:24px;background:#272e42;color:white;padding:12px 20px;border-radius:10px;font-size:0.85rem;font-family:'Fira Code',monospace;z-index:1000;opacity:0;transform:translateY(10px);transition:all 300ms;}
41
+ .toast.show{opacity:1;transform:translateY(0);}
42
+ @keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
43
+ .skeleton{background:linear-gradient(90deg,#e2e7ff 25%,#d9e2ff 50%,#e2e7ff 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;}
44
+ </style>
45
+ </head>
46
+ <body class="bg-background selection:bg-primary-container selection:text-on-primary-container">
47
+
48
+ <!-- Toast -->
49
+ <div id="toast" class="toast"></div>
50
+
51
+ <!-- Nav -->
52
+ <nav class="fixed top-4 left-4 right-4 z-50 flex justify-between items-center px-6 py-3 max-w-7xl mx-auto bg-white/90 backdrop-blur-xl rounded-2xl shadow-lg shadow-rose-500/5 border border-slate-200/50">
53
+ <div class="flex items-center gap-2 text-xl font-bold fira-code text-rose-600">
54
+ <span class="material-symbols-outlined" style="font-variation-settings:'FILL' 1;">insights</span>Trend Hunter
55
+ </div>
56
+ <div class="flex items-center gap-3">
57
+ <div id="engine-badge" class="hidden md:flex items-center gap-2 px-3 py-1 bg-tertiary-container/30 text-on-tertiary-container rounded-full text-xs font-mono font-bold border border-tertiary/20">
58
+ <span class="w-2 h-2 rounded-full bg-green-500 inline-block"></span> Engine Online
59
+ </div>
60
+ <button onclick="toggleHistory()" class="material-symbols-outlined text-slate-600 hover:bg-rose-50 p-2 rounded-xl transition-all duration-200 cursor-pointer" title="Search History">history</button>
61
+ </div>
62
+ </nav>
63
+
64
+ <!-- History Drawer -->
65
+ <div id="history-drawer" class="hidden fixed top-20 right-4 z-40 w-80 bg-white rounded-2xl shadow-2xl border border-slate-200 p-4 max-h-96 overflow-y-auto">
66
+ <div class="flex justify-between items-center mb-3">
67
+ <span class="fira-code font-bold text-sm text-on-background">Search History</span>
68
+ <button onclick="clearHistory()" class="text-xs text-primary hover:underline cursor-pointer">Clear All</button>
69
+ </div>
70
+ <div id="history-list"><p class="text-xs text-outline text-center py-4">No searches yet.</p></div>
71
+ </div>
72
+
73
+ <main class="pt-32 pb-20 px-4 max-w-7xl mx-auto space-y-16">
74
+
75
+ <!-- Hero -->
76
+ <section class="text-center space-y-8">
77
+ <div class="space-y-4">
78
+ <h1 class="fira-code text-4xl md:text-6xl font-bold tracking-tight text-on-background">
79
+ What's <span class="text-primary italic">Trending</span> Right Now?
80
+ </h1>
81
+ <p class="max-w-2xl mx-auto text-on-surface-variant text-lg md:text-xl font-medium">
82
+ Autonomous AI research across 4 major social networks to find your next viral niche in seconds.
83
+ </p>
84
+ </div>
85
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-4 max-w-4xl mx-auto">
86
+ <div class="bg-surface-container-lowest p-6 rounded-2xl border-b-4 border-primary/20 shadow-sm flex flex-col items-center justify-center space-y-1">
87
+ <span class="fira-code text-3xl font-bold text-primary">2.4M+</span>
88
+ <span class="font-mono text-[10px] uppercase tracking-widest text-outline">Data Points</span>
89
+ </div>
90
+ <div class="bg-surface-container-lowest p-6 rounded-2xl border-b-4 border-secondary/20 shadow-sm flex flex-col items-center justify-center space-y-1">
91
+ <span class="fira-code text-3xl font-bold text-secondary">842</span>
92
+ <span class="font-mono text-[10px] uppercase tracking-widest text-outline">Niches Found</span>
93
+ </div>
94
+ <div class="bg-surface-container-lowest p-6 rounded-2xl border-b-4 border-tertiary/20 shadow-sm flex flex-col items-center justify-center space-y-1">
95
+ <span class="fira-code text-3xl font-bold text-tertiary">4</span>
96
+ <span class="font-mono text-[10px] uppercase tracking-widest text-outline">Platforms</span>
97
+ </div>
98
+ <div class="bg-surface-container-lowest p-6 rounded-2xl border-b-4 border-outline/20 shadow-sm flex flex-col items-center justify-center space-y-1">
99
+ <span class="fira-code text-3xl font-bold text-on-background">v2.0</span>
100
+ <span class="font-mono text-[10px] uppercase tracking-widest text-outline">Engine</span>
101
+ </div>
102
+ </div>
103
+ </section>
104
+
105
+ <!-- Research Control Panel -->
106
+ <section class="max-w-[860px] mx-auto">
107
+ <div class="bg-surface-container-lowest rounded-2xl shadow-xl border-t-[4px] border-primary p-8 md:p-10 space-y-8">
108
+
109
+ <!-- Mode Toggle -->
110
+ <div class="flex gap-3 p-1 bg-surface-container-high rounded-xl">
111
+ <button id="mode-niche" onclick="setMode('niche')" class="flex-1 py-2 px-4 fira-code text-sm font-bold rounded-lg bg-white shadow-sm text-on-background transition-all cursor-pointer">
112
+ <span class="material-symbols-outlined text-sm">search</span> Research a Niche
113
+ </button>
114
+ <button id="mode-discover" onclick="setMode('discover')" class="flex-1 py-2 px-4 fira-code text-sm font-bold rounded-lg text-on-surface-variant transition-all cursor-pointer">
115
+ <span class="material-symbols-outlined text-sm">local_fire_department</span> Discover Trends Now
116
+ </button>
117
+ </div>
118
+
119
+ <!-- Niche Input -->
120
+ <div id="niche-panel">
121
+ <label class="block">
122
+ <span class="fira-code text-sm font-bold text-on-surface-variant mb-2 block uppercase tracking-wider">Target Niche or Keyword</span>
123
+ <div class="relative group">
124
+ <span class="absolute left-4 top-1/2 -translate-y-1/2 material-symbols-outlined text-outline group-focus-within:text-secondary transition-colors">search</span>
125
+ <input id="niche-input" class="w-full bg-surface-container-high border-none rounded-xl py-4 pl-12 pr-4 fira-code text-on-surface focus:ring-2 focus:ring-secondary transition-all outline-none" placeholder="e.g. Agentic AI, Sustainable Fashion, Web3..." type="text"/>
126
+ </div>
127
+ </label>
128
+ </div>
129
+
130
+ <!-- Discovery Mode Message -->
131
+ <div id="discover-panel" class="hidden-section">
132
+ <div class="bg-tertiary-container/20 border border-tertiary/20 rounded-xl p-5 text-center space-y-2">
133
+ <span class="material-symbols-outlined text-3xl text-tertiary" style="font-variation-settings:'FILL' 1;">local_fire_department</span>
134
+ <p class="fira-code font-bold text-on-background">Discover Mode Active</p>
135
+ <p class="text-sm text-on-surface-variant">We'll scan YouTube's global trending chart and identify hot niches for you — no keyword needed.</p>
136
+ </div>
137
+ </div>
138
+
139
+ <!-- Platform Chips -->
140
+ <div id="platform-section">
141
+ <div class="flex items-center justify-between mb-3">
142
+ <span class="fira-code text-sm font-bold text-on-surface-variant uppercase tracking-wider">Platform Synthesis Focus</span>
143
+ <div class="flex gap-3">
144
+ <button onclick="selectAll()" class="text-secondary text-xs font-mono font-bold hover:underline cursor-pointer">Select All</button>
145
+ <button onclick="clearAll()" class="text-outline text-xs font-mono font-bold hover:underline cursor-pointer">Clear</button>
146
+ </div>
147
+ </div>
148
+ <div class="flex flex-wrap gap-3">
149
+ <button onclick="togglePlatform('youtube',this)" class="platform-btn platform-btn-active flex items-center gap-2 px-4 py-2 rounded-xl font-medium transition-all hover:translate-y-[-2px] active:scale-95 cursor-pointer">
150
+ <span class="material-symbols-outlined text-sm">smart_display</span> YouTube
151
+ </button>
152
+ <button onclick="togglePlatform('tiktok',this)" class="platform-btn platform-btn-active flex items-center gap-2 px-4 py-2 rounded-xl font-medium transition-all hover:translate-y-[-2px] active:scale-95 cursor-pointer">
153
+ <span class="material-symbols-outlined text-sm">bolt</span> TikTok
154
+ </button>
155
+ <button onclick="togglePlatform('instagram',this)" class="platform-btn platform-btn-active flex items-center gap-2 px-4 py-2 rounded-xl font-medium transition-all hover:translate-y-[-2px] active:scale-95 cursor-pointer">
156
+ <span class="material-symbols-outlined text-sm">photo_camera</span> Instagram
157
+ </button>
158
+ <button onclick="togglePlatform('twitter',this)" class="platform-btn platform-btn-active flex items-center gap-2 px-4 py-2 rounded-xl font-medium transition-all hover:translate-y-[-2px] active:scale-95 cursor-pointer">
159
+ <span class="material-symbols-outlined text-sm">close</span> X /Twitter
160
+ </button>
161
+ </div>
162
+ <div class="flex justify-between items-center text-[11px] font-mono text-outline uppercase tracking-tight px-1 mt-2">
163
+ <span>* High-intensity scanning enabled</span>
164
+ <span id="platform-count" class="text-secondary font-bold">4 platforms selected</span>
165
+ </div>
166
+ </div>
167
+
168
+ <button id="run-btn" onclick="startResearch()" class="w-full py-5 bg-gradient-to-br from-primary to-primary-container text-white fira-code font-bold text-lg rounded-xl shadow-xl shadow-primary/20 hover:shadow-2xl hover:translate-y-[-2px] active:translate-y-[1px] transition-all flex items-center justify-center gap-3 cursor-pointer">
169
+ RUN RESEARCH <span class="material-symbols-outlined">arrow_forward</span>
170
+ </button>
171
+ </div>
172
+ </section>
173
+
174
+ <!-- Loading State -->
175
+ <section id="loading-state" class="hidden-section max-w-[860px] mx-auto space-y-6">
176
+ <div class="relative w-full h-2 bg-surface-container rounded-full overflow-hidden">
177
+ <div id="progress-bar" class="absolute top-0 left-0 h-full bg-primary rounded-full transition-all duration-700" style="width:0%"></div>
178
+ </div>
179
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
180
+ <div id="step-1" class="bg-surface-container-low p-5 rounded-2xl flex items-center gap-4 border border-outline-variant/10 opacity-40 transition-all">
181
+ <div class="w-10 h-10 rounded-full bg-white flex items-center justify-center text-primary shadow-sm flex-shrink-0"><span class="material-symbols-outlined">cloud_download</span></div>
182
+ <div><div class="text-[10px] font-mono uppercase tracking-widest text-outline">Step 01</div><div class="text-sm font-bold flex items-center gap-2">Fetching<span class="step-dots hidden flex gap-1 ml-1"><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce"></span><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style="animation-delay:.2s"></span><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style="animation-delay:.4s"></span></span></div></div>
183
+ </div>
184
+ <div id="step-2" class="bg-surface-container-low p-5 rounded-2xl flex items-center gap-4 border border-outline-variant/10 opacity-40 transition-all">
185
+ <div class="w-10 h-10 rounded-full bg-white flex items-center justify-center text-primary shadow-sm flex-shrink-0"><span class="material-symbols-outlined">troubleshoot</span></div>
186
+ <div><div class="text-[10px] font-mono uppercase tracking-widest text-outline">Step 02</div><div class="text-sm font-bold flex items-center gap-2">Scanning<span class="step-dots hidden flex gap-1 ml-1"><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce"></span><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style="animation-delay:.2s"></span><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style="animation-delay:.4s"></span></span></div></div>
187
+ </div>
188
+ <div id="step-3" class="bg-surface-container-low p-5 rounded-2xl flex items-center gap-4 border border-outline-variant/10 opacity-40 transition-all">
189
+ <div class="w-10 h-10 rounded-full bg-white flex items-center justify-center text-primary shadow-sm flex-shrink-0"><span class="material-symbols-outlined">psychology</span></div>
190
+ <div><div class="text-[10px] font-mono uppercase tracking-widest text-outline">Step 03</div><div class="text-sm font-bold flex items-center gap-2">Synthesizing<span class="step-dots hidden flex gap-1 ml-1"><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce"></span><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style="animation-delay:.2s"></span><span class="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style="animation-delay:.4s"></span></span></div></div>
191
+ </div>
192
+ </div>
193
+ </section>
194
+
195
+ <!-- Results Board -->
196
+ <section id="results-board" class="hidden-section max-w-5xl mx-auto space-y-12">
197
+
198
+ <!-- Header + Export -->
199
+ <div class="flex flex-col md:flex-row md:items-end justify-between gap-4 px-2">
200
+ <div>
201
+ <h2 class="fira-code text-2xl font-bold text-on-background">Research Findings</h2>
202
+ <p id="session-line" class="text-on-surface-variant font-medium text-sm">Session ID: #TH-0000-X0</p>
203
+ </div>
204
+ <div class="flex gap-3 flex-wrap">
205
+ <button onclick="copyReport()" class="bg-surface-container-high hover:bg-outline-variant text-on-surface px-4 py-2.5 rounded-xl fira-code text-sm font-bold flex items-center gap-2 transition-all cursor-pointer">
206
+ <span class="material-symbols-outlined text-sm">content_copy</span> COPY
207
+ </button>
208
+ <button onclick="downloadReport()" class="bg-secondary hover:bg-secondary-dim text-white px-5 py-2.5 rounded-xl fira-code text-sm font-bold flex items-center gap-2 transition-all shadow-lg shadow-secondary/20 cursor-pointer">
209
+ <span class="material-symbols-outlined text-sm">download</span> EXPORT .TXT
210
+ </button>
211
+ </div>
212
+ </div>
213
+
214
+ <!-- Trend Score -->
215
+ <div class="bg-surface-container-lowest rounded-2xl p-6 shadow-sm border border-outline-variant/20">
216
+ <div class="flex items-center justify-between mb-3">
217
+ <span class="fira-code text-sm font-bold text-on-surface-variant uppercase tracking-wider">Trend Opportunity Score</span>
218
+ <span id="score-label" class="fira-code text-2xl font-bold text-primary">--/100</span>
219
+ </div>
220
+ <div class="h-3 bg-surface-container rounded-full overflow-hidden">
221
+ <div id="score-bar" class="score-bar-fill" style="width:0%"></div>
222
+ </div>
223
+ <p id="score-tag" class="text-xs font-mono text-outline mt-2 uppercase tracking-widest"></p>
224
+ </div>
225
+
226
+ <!-- Platform-wise Results Tabs -->
227
+ <div id="platform-results-section">
228
+ <div class="flex gap-2 flex-wrap mb-4" id="platform-tabs"></div>
229
+ <div id="platform-panes"></div>
230
+ </div>
231
+
232
+ <!-- Content Ideas -->
233
+ <div>
234
+ <h3 class="fira-code text-xl font-bold text-on-background mb-4 flex items-center gap-2">
235
+ <span class="material-symbols-outlined text-secondary" style="font-variation-settings:'FILL' 1;">lightbulb</span> Content Angle Ideas
236
+ </h3>
237
+ <div id="ideas-list" class="space-y-3"></div>
238
+ </div>
239
+
240
+ <!-- Full Report Raw -->
241
+ <div>
242
+ <div class="flex items-center justify-between mb-4">
243
+ <h3 class="fira-code text-xl font-bold text-on-background">Full Raw Report</h3>
244
+ <button onclick="downloadReport()" class="text-secondary font-mono text-sm font-bold hover:text-primary transition-colors flex items-center gap-2 cursor-pointer">
245
+ <span class="material-symbols-outlined text-sm">download</span> DOWNLOAD .TXT
246
+ </button>
247
+ </div>
248
+ <div class="bg-surface-container-low rounded-2xl overflow-hidden shadow-inner p-1">
249
+ <div class="bg-white rounded-xl p-8 border-l-[4px] border-secondary min-h-[200px]">
250
+ <pre id="report-text" class="fira-code text-sm leading-relaxed text-on-background whitespace-pre-wrap"></pre>
251
+ </div>
252
+ </div>
253
+ </div>
254
+ </section>
255
+
256
+ <!-- Bento Section -->
257
+ <section class="grid grid-cols-1 md:grid-cols-4 gap-4 h-auto md:h-[400px]">
258
+ <div class="md:col-span-2 md:row-span-2 bg-surface-container-high rounded-2xl overflow-hidden relative group h-56 md:h-full">
259
+ <img alt="abstract data visualization" class="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110" src="https://lh3.googleusercontent.com/aida-public/AB6AXuA-P6AjSTVsp9U0Xmp6_06bJnvOdAoA9WDx6w_3QPFLzcFJdRZT6_7xZ5loufV4SBcmMLyKsZnCuNlK3CYeIWr7sI3kIqYaBBKlIsiUoU_JThVnf_Py3C7GZ5mIRTO2oPvbw1flk3yD3faP5BCK35hyl76bChKCxg5I7uXft4Gq5q61Qe3nLxsNsK_fenbAqUNuXXP9TvVUJ1XH4VUsE8OaslUwj0wegPfA1X7ip2xCsK-2U72gb-K3F6KimQ1IqTKklYK176G-PbY"/>
260
+ <div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent flex items-end p-8">
261
+ <div class="text-white space-y-2"><div class="fira-code text-xl font-bold">Global Intelligence</div><p class="text-sm text-slate-200">Processing live streams from 14 server clusters.</p></div>
262
+ </div>
263
+ </div>
264
+ <div class="md:col-span-2 bg-surface-container-high rounded-2xl overflow-hidden relative group h-48 md:h-full">
265
+ <img alt="server room" class="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAv1cWhR26VWtenYrNz4-kfANaOttePUDnHyjp-5xJAn_6yo7MCk6ALvpJ4k-CKfRjyiNkuuvfc43bz19k7vC1y-_fNxGe20CcSRk5_lpOz8DBXSubRCRgg9fPcTH7l3t0WaX46DHdyPU-sBVw-TZbu7fV7wUymhs4y7EUoWTRHa9fnre9i54_hEjh2D6v2dOA6Zg6Da9LvvGXCP_jEySQHdyJjqbYIj8f10-JWjv-7Gkkrn8b6F_5YSirAldetjhfaAxxcstxEYAY"/>
266
+ </div>
267
+ <div class="md:col-span-2 bg-primary rounded-2xl flex flex-col items-center justify-center text-white p-6 text-center space-y-3 h-48 md:h-full">
268
+ <span class="material-symbols-outlined text-4xl" style="font-variation-settings:'FILL' 1;">rocket_launch</span>
269
+ <div class="fira-code font-bold text-sm">Scale Your Insights</div>
270
+ <p class="text-xs text-white/70">Start researching trends in any niche above.</p>
271
+ </div>
272
+ </section>
273
+ </main>
274
+
275
+ <footer class="w-full flex justify-center items-center py-10">
276
+ <div class="text-center space-y-2">
277
+ <div class="text-slate-500 font-mono text-[10px] uppercase tracking-widest">Trend Hunter AI • Multi-Platform Intelligence v2.0</div>
278
+ <div class="flex justify-center gap-6">
279
+ <span onclick="shareReport()" class="text-slate-400 hover:text-rose-400 transition-colors material-symbols-outlined cursor-pointer">share</span>
280
+ <span class="text-slate-400 hover:text-rose-400 transition-colors material-symbols-outlined cursor-pointer">help</span>
281
+ <span class="text-slate-400 hover:text-rose-400 transition-colors material-symbols-outlined cursor-pointer">settings</span>
282
+ </div>
283
+ </div>
284
+ </footer>
285
+
286
+ <script>
287
+ const BACKEND = 'http://localhost:8000';
288
+ let selectedPlatforms = new Set(['youtube','tiktok','instagram','twitter']);
289
+ let currentMode = 'niche';
290
+ let lastReport = '';
291
+ let lastNiche = '';
292
+ let searchHistory = JSON.parse(localStorage.getItem('th_history') || '[]');
293
+
294
+ // Boot
295
+ window.addEventListener('load', async () => {
296
+ renderHistory();
297
+ try { await fetch(`${BACKEND}/docs`); document.getElementById('engine-badge').style.display = 'flex'; } catch {}
298
+ });
299
+
300
+ // Mode toggle
301
+ function setMode(mode) {
302
+ currentMode = mode;
303
+ document.getElementById('niche-panel').className = mode === 'niche' ? '' : 'hidden-section';
304
+ document.getElementById('discover-panel').className = mode === 'discover' ? '' : 'hidden-section';
305
+ document.getElementById('platform-section').className = mode === 'niche' ? '' : 'hidden-section';
306
+ const btnNiche = document.getElementById('mode-niche');
307
+ const btnDiscover = document.getElementById('mode-discover');
308
+ if (mode === 'niche') {
309
+ btnNiche.className = 'flex-1 py-2 px-4 fira-code text-sm font-bold rounded-lg bg-white shadow-sm text-on-background transition-all cursor-pointer';
310
+ btnDiscover.className = 'flex-1 py-2 px-4 fira-code text-sm font-bold rounded-lg text-on-surface-variant transition-all cursor-pointer';
311
+ } else {
312
+ btnDiscover.className = 'flex-1 py-2 px-4 fira-code text-sm font-bold rounded-lg bg-white shadow-sm text-on-background transition-all cursor-pointer';
313
+ btnNiche.className = 'flex-1 py-2 px-4 fira-code text-sm font-bold rounded-lg text-on-surface-variant transition-all cursor-pointer';
314
+ }
315
+ }
316
+
317
+ // Platform toggles
318
+ function togglePlatform(id, btn) {
319
+ if (selectedPlatforms.has(id)) { selectedPlatforms.delete(id); btn.classList.remove('platform-btn-active'); btn.classList.add('platform-btn-inactive'); }
320
+ else { selectedPlatforms.add(id); btn.classList.remove('platform-btn-inactive'); btn.classList.add('platform-btn-active'); }
321
+ updateCount();
322
+ }
323
+ function selectAll() { document.querySelectorAll('.platform-btn').forEach(b => { b.classList.add('platform-btn-active'); b.classList.remove('platform-btn-inactive'); }); selectedPlatforms = new Set(['youtube','tiktok','instagram','twitter']); updateCount(); }
324
+ function clearAll() { document.querySelectorAll('.platform-btn').forEach(b => { b.classList.remove('platform-btn-active'); b.classList.add('platform-btn-inactive'); }); selectedPlatforms.clear(); updateCount(); }
325
+ function updateCount() { const n = selectedPlatforms.size; document.getElementById('platform-count').textContent = `${n} platform${n!==1?'s':''} selected`; }
326
+
327
+ // Step animation
328
+ function activateStep(id, pct) { const el = document.getElementById(id); el.classList.remove('opacity-40'); el.querySelector('.step-dots').classList.remove('hidden'); document.getElementById('progress-bar').style.width = pct+'%'; }
329
+ function doneStep(id) { document.getElementById(id).querySelector('.step-dots').classList.add('hidden'); }
330
+
331
+ // Main research
332
+ async function startResearch() {
333
+ if (currentMode === 'niche') {
334
+ const niche = document.getElementById('niche-input').value.trim();
335
+ if (!niche) { showToast('Please enter a niche keyword.'); return; }
336
+ if (selectedPlatforms.size === 0) { showToast('Select at least one platform.'); return; }
337
+ }
338
+
339
+ show('loading-state'); hide('results-board');
340
+ ['step-1','step-2','step-3'].forEach(id => { document.getElementById(id).classList.add('opacity-40'); document.getElementById(id).querySelector('.step-dots').classList.add('hidden'); });
341
+ document.getElementById('progress-bar').style.width = '0%';
342
+
343
+ const runBtn = document.getElementById('run-btn');
344
+ runBtn.disabled = true;
345
+ runBtn.innerHTML = '<span class="material-symbols-outlined animate-spin">sync</span> ANALYZING...';
346
+
347
+ setTimeout(() => activateStep('step-1', 30), 400);
348
+ setTimeout(() => { doneStep('step-1'); activateStep('step-2', 60); }, 4000);
349
+ setTimeout(() => { doneStep('step-2'); activateStep('step-3', 85); }, 8000);
350
+
351
+ try {
352
+ let data;
353
+ if (currentMode === 'discover') {
354
+ const res = await fetch(`${BACKEND}/api/trending`);
355
+ if (!res.ok) throw new Error(`Server error: ${res.status}`);
356
+ data = await res.json();
357
+ lastNiche = 'Trending Discovery';
358
+ } else {
359
+ const niche = document.getElementById('niche-input').value.trim();
360
+ lastNiche = niche;
361
+ const res = await fetch(`${BACKEND}/api/research`, {
362
+ method:'POST', headers:{'Content-Type':'application/json'},
363
+ body: JSON.stringify({ niche, platforms: [...selectedPlatforms] })
364
+ });
365
+ if (!res.ok) throw new Error(`Server error: ${res.status}`);
366
+ data = await res.json();
367
+ addHistory(niche);
368
+ }
369
+
370
+ doneStep('step-3');
371
+ document.getElementById('progress-bar').style.width = '100%';
372
+ await sleep(600);
373
+ hide('loading-state');
374
+ renderResults(data);
375
+ show('results-board');
376
+ document.getElementById('results-board').scrollIntoView({ behavior:'smooth', block:'start' });
377
+
378
+ } catch (err) {
379
+ hide('loading-state');
380
+ document.getElementById('report-text').textContent = `Error: ${err.message}\n\nMake sure backend is running:\n python -m uvicorn backend.main:app --host 0.0.0.0 --port 8000`;
381
+ show('results-board');
382
+ showToast(`Error: ${err.message}`);
383
+ } finally {
384
+ runBtn.disabled = false;
385
+ runBtn.innerHTML = 'RUN RESEARCH <span class="material-symbols-outlined">arrow_forward</span>';
386
+ }
387
+ }
388
+
389
+ function renderResults(data) {
390
+ // Session ID
391
+ const sid = `TH-${Math.floor(1000+Math.random()*9000)}-X${Math.floor(Math.random()*10)}`;
392
+ document.getElementById('session-line').textContent = `Session: #${sid} • Niche: ${lastNiche}`;
393
+
394
+ // Trend Score
395
+ const score = data.trend_score || 0;
396
+ document.getElementById('score-label').textContent = `${score}/100`;
397
+ setTimeout(() => { document.getElementById('score-bar').style.width = score + '%'; }, 300);
398
+ const tag = score >= 75 ? 'HIGH OPPORTUNITY — Act now, volume is rising fast' : score >= 50 ? 'MEDIUM OPPORTUNITY — Growing niche, worth exploring' : 'EMERGING — Early stage, low competition';
399
+ document.getElementById('score-tag').textContent = tag;
400
+
401
+ // Platform-wise tabs + panes
402
+ renderPlatformResults(data.platform_results || []);
403
+
404
+ // Videos
405
+ if (data.videos && data.videos.length > 0) {
406
+ // Injected into YouTube platform pane
407
+ }
408
+
409
+ // Content Ideas
410
+ const ideasEl = document.getElementById('ideas-list');
411
+ const ideas = data.content_ideas || [];
412
+ ideasEl.innerHTML = ideas.map(idea => `
413
+ <div class="idea-card" onclick="copyText('${escAttr(idea)}')" title="Click to copy">
414
+ <div class="flex items-start justify-between gap-2">
415
+ <span>${escHtml(idea)}</span>
416
+ <span class="material-symbols-outlined text-sm text-outline flex-shrink-0">content_copy</span>
417
+ </div>
418
+ </div>`).join('');
419
+
420
+ // Raw report
421
+ lastReport = data.report || '';
422
+ document.getElementById('report-text').textContent = lastReport;
423
+ }
424
+
425
+ function renderPlatformResults(platformResults) {
426
+ const tabsEl = document.getElementById('platform-tabs');
427
+ const panesEl = document.getElementById('platform-panes');
428
+ tabsEl.innerHTML = '';
429
+ panesEl.innerHTML = '';
430
+ if (!platformResults || platformResults.length === 0) return;
431
+
432
+ platformResults.forEach((pr, idx) => {
433
+ // Tab
434
+ const tab = document.createElement('button');
435
+ tab.className = `platform-tab ${idx === 0 ? 'active' : ''}`;
436
+ tab.innerHTML = `<span class="material-symbols-outlined text-sm mr-1">${pr.icon||'circle'}</span>${pr.platform}`;
437
+ tab.onclick = () => switchTab(idx, platformResults.length);
438
+ tabsEl.appendChild(tab);
439
+
440
+ // Pane
441
+ const pane = document.createElement('div');
442
+ pane.className = `platform-pane ${idx === 0 ? 'active' : ''} bg-surface-container-lowest rounded-2xl p-6 shadow-sm border border-outline-variant/20 space-y-6`;
443
+ pane.id = `pane-${idx}`;
444
+
445
+ let inner = `
446
+ <div class="flex items-center justify-between">
447
+ <h4 class="fira-code font-bold text-lg text-on-background flex items-center gap-2">
448
+ <span class="material-symbols-outlined" style="color:${pr.color||'#888'}">${pr.icon||'circle'}</span>${pr.platform}
449
+ </h4>
450
+ <span class="text-xs font-mono font-bold px-3 py-1 rounded-full ${pr.opportunity==='HIGH'?'bg-tertiary-container text-on-tertiary-container':pr.opportunity==='MEDIUM'?'bg-secondary-container text-on-secondary-container':'bg-surface-container text-outline'}">${pr.opportunity||'--'} OPPORTUNITY</span>
451
+ </div>
452
+ <div class="space-y-2">
453
+ ${(pr.insights||[]).filter(Boolean).map(i=>`<div class="flex items-start gap-2 text-sm"><span class="material-symbols-outlined text-secondary text-sm flex-shrink-0">check_circle</span><span>${escHtml(i)}</span></div>`).join('')}
454
+ </div>`;
455
+
456
+ // YouTube: videos grid
457
+ if (pr.platform === 'YouTube' && pr.videos && pr.videos.length > 0) {
458
+ inner += `<div><p class="fira-code text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-3">Trending Videos</p>
459
+ <div class="grid grid-cols-2 md:grid-cols-3 gap-3">${pr.videos.slice(0,6).map(v => videoCardHtml(v)).join('')}</div></div>`;
460
+ }
461
+
462
+ // Social: topic rows
463
+ if (pr.trends && pr.trends.length > 0) {
464
+ inner += `<div><p class="fira-code text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-3">Trending Topics</p>
465
+ <div class="space-y-3">${pr.trends.map(t => trendRowHtml(t, pr.platform)).join('')}</div></div>`;
466
+ }
467
+
468
+ // Raw data
469
+ if (pr.raw_data && pr.raw_data.length > 0) {
470
+ inner += `<details class="text-xs"><summary class="cursor-pointer text-outline font-mono uppercase tracking-widest hover:text-secondary">Show Raw Data</summary>
471
+ <pre class="mt-2 bg-surface-container p-3 rounded-xl fira-code text-[11px] leading-relaxed whitespace-pre-wrap text-on-surface-variant">${escHtml(pr.raw_data.join('\n'))}</pre></details>`;
472
+ }
473
+
474
+ pane.innerHTML = inner;
475
+ panesEl.appendChild(pane);
476
+ });
477
+ }
478
+
479
+ function switchTab(idx, total) {
480
+ document.querySelectorAll('.platform-tab').forEach((t,i) => t.classList.toggle('active', i===idx));
481
+ document.querySelectorAll('.platform-pane').forEach((p,i) => p.classList.toggle('active', i===idx));
482
+ }
483
+
484
+ function videoCardHtml(v) {
485
+ const date = v.published_at ? new Date(v.published_at).toLocaleDateString('en-US',{month:'short',day:'numeric'}) : '';
486
+ return `<a href="${escAttr(v.url)}" target="_blank" rel="noopener noreferrer" class="video-card">
487
+ <div style="position:relative;aspect-ratio:16/9;overflow:hidden;background:#eef0ff;">
488
+ ${v.thumbnail?`<img src="${escAttr(v.thumbnail)}" alt="" style="width:100%;height:100%;object-fit:cover;" loading="lazy"/>`:
489
+ `<div style="display:flex;align-items:center;justify-content:center;height:100%;"><span class="material-symbols-outlined" style="font-size:2rem;color:#b90035;">smart_display</span></div>`}
490
+ <div class="thumb-overlay"><span class="material-symbols-outlined" style="font-size:2.5rem;color:white;">play_circle</span></div>
491
+ </div>
492
+ <div style="padding:10px 12px;">
493
+ <p style="font-size:0.78rem;font-weight:600;line-height:1.4;margin:0 0 4px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;">${escHtml(v.title||'')}</p>
494
+ <p style="font-size:0.72rem;color:#b90035;font-weight:600;margin:0 0 2px;">${escHtml(v.channel||'')}</p>
495
+ ${date?`<p style="font-size:0.68rem;color:#6f768e;margin:0;">${date}</p>`:''}
496
+ </div>
497
+ </a>`;
498
+ }
499
+
500
+ function trendRowHtml(t, platform) {
501
+ const metric = t.views || t.engagement || t.tweets || '';
502
+ return `<div class="flex items-center justify-between bg-surface-container-low p-3 rounded-xl">
503
+ <div>
504
+ <p class="font-semibold text-sm text-on-background">${escHtml(t.topic||'')}</p>
505
+ <p class="text-xs text-secondary font-mono mt-0.5">${escHtml(t.hashtag||'')} ${metric?`· ${metric}`:''}</p>
506
+ </div>
507
+ <span class="text-xs font-bold text-tertiary bg-tertiary-container/30 px-2 py-1 rounded-full">${escHtml(t.growth||'')}</span>
508
+ </div>`;
509
+ }
510
+
511
+ // History
512
+ function addHistory(niche) {
513
+ searchHistory = [{ niche, time: new Date().toLocaleTimeString(), date: new Date().toLocaleDateString() }, ...searchHistory.filter(h=>h.niche!==niche)].slice(0,10);
514
+ localStorage.setItem('th_history', JSON.stringify(searchHistory));
515
+ renderHistory();
516
+ }
517
+ function clearHistory() { searchHistory = []; localStorage.removeItem('th_history'); renderHistory(); }
518
+ function renderHistory() {
519
+ const el = document.getElementById('history-list');
520
+ el.innerHTML = searchHistory.length === 0 ? '<p class="text-xs text-outline text-center py-4">No searches yet.</p>' :
521
+ searchHistory.map(h => `<div class="history-item" onclick="loadFromHistory('${escAttr(h.niche)}')">
522
+ <span class="text-on-background font-medium truncate">${escHtml(h.niche)}</span>
523
+ <span class="text-outline text-xs flex-shrink-0">${h.time}</span>
524
+ </div>`).join('');
525
+ }
526
+ function loadFromHistory(niche) {
527
+ setMode('niche');
528
+ document.getElementById('niche-input').value = niche;
529
+ toggleHistory();
530
+ startResearch();
531
+ }
532
+ function toggleHistory() { const d = document.getElementById('history-drawer'); d.classList.toggle('hidden'); }
533
+
534
+ // Utilities
535
+ function downloadReport() {
536
+ if (!lastReport) { showToast('Run research first.'); return; }
537
+ const blob = new Blob([lastReport], {type:'text/plain'});
538
+ const url = URL.createObjectURL(blob);
539
+ const a = document.createElement('a'); a.href=url; a.download=`${lastNiche.replace(/\s+/g,'_')}_Trend_Report.txt`;
540
+ document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
541
+ showToast('Report downloaded!');
542
+ }
543
+ function copyReport() { navigator.clipboard.writeText(lastReport).then(() => showToast('Report copied to clipboard!')); }
544
+ function copyText(text) { navigator.clipboard.writeText(text).then(() => showToast('Copied!')); }
545
+ function shareReport() { if (navigator.share) navigator.share({title:`Trend Report: ${lastNiche}`, text: lastReport.slice(0,500)+'...' }); else showToast('Share not supported in this browser.'); }
546
+ function showToast(msg) { const t = document.getElementById('toast'); t.textContent=msg; t.classList.add('show'); setTimeout(()=>t.classList.remove('show'),2800); }
547
+ function show(id) { document.getElementById(id).classList.remove('hidden-section'); }
548
+ function hide(id) { document.getElementById(id).classList.add('hidden-section'); }
549
+ function sleep(ms) { return new Promise(r=>setTimeout(r,ms)); }
550
+ function escHtml(s) { return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
551
+ function escAttr(s) { return String(s).replace(/"/g,'&quot;').replace(/'/g,'&#39;'); }
552
+
553
+ // Enter key
554
+ document.addEventListener('DOMContentLoaded', () => {
555
+ document.getElementById('niche-input').addEventListener('keydown', e => { if(e.key==='Enter') startResearch(); });
556
+ document.addEventListener('click', e => { const d = document.getElementById('history-drawer'); if(!d.classList.contains('hidden') && !d.contains(e.target) && !e.target.closest('[onclick="toggleHistory()"]')) d.classList.add('hidden'); });
557
+ });
558
+ </script>
559
+ </body>
560
+ </html>