|
1
|
import { useState, useEffect } from "react"; |
|
2
|
import { Button } from "@/components/ui/button"; |
|
3
|
import { |
|
4
|
Wrench, |
|
5
|
AlertTriangle, |
|
6
|
ShieldCheck, |
|
7
|
Download, |
|
8
|
HelpCircle, |
|
9
|
X, |
|
10
|
Zap, |
|
11
|
Sparkles, |
|
12
|
Timer, |
|
13
|
ChevronRight, |
|
14
|
Activity, |
|
15
|
Cpu, |
|
16
|
Layers, |
|
17
|
CheckCircle2, |
|
18
|
Volume2, |
|
19
|
Maximize2, |
|
20
|
ExternalLink, |
|
21
|
Flame, |
|
22
|
Smartphone |
|
23
|
} from "lucide-react"; |
|
24
|
import { useLocation } from "wouter"; |
|
25
|
import { motion, AnimatePresence } from "framer-motion"; |
|
26
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"; |
|
27
|
import { Badge } from "@/components/ui/badge"; |
|
28
|
|
|
29
|
export default function FloatingActionButton() { |
|
30
|
const [isExpanded, setIsExpanded] = useState(false); |
|
31
|
const [, setLocation] = useLocation(); |
|
32
|
|
|
33
|
// Active interactive modal state: "emergency" | "safety" | "rails" | null |
|
34
|
const [activeModal, setActiveModal] = useState<"emergency" | "safety" | "rails" | null>(null); |
|
35
|
|
|
36
|
// Emergency countdown timer state |
|
37
|
const [countdown, setCountdown] = useState<number | null>(null); |
|
38
|
const [timerRunning, setTimerRunning] = useState(false); |
|
39
|
|
|
40
|
useEffect(() => { |
|
41
|
let interval: NodeJS.Timeout; |
|
42
|
if (timerRunning && countdown !== null && countdown > 0) { |
|
43
|
interval = setInterval(() => { |
|
44
|
setCountdown((prev) => (prev !== null && prev > 0 ? prev - 1 : 0)); |
|
45
|
}, 1000); |
|
46
|
} else if (countdown === 0) { |
|
47
|
setTimerRunning(false); |
|
48
|
} |
|
49
|
return () => clearInterval(interval); |
|
50
|
}, [timerRunning, countdown]); |
|
51
|
|
|
52
|
const startEmergencyTimer = () => { |
|
53
|
setCountdown(15); |
|
54
|
setTimerRunning(true); |
|
55
|
}; |
|
56
|
|
|
57
|
const resetEmergencyTimer = () => { |
|
58
|
setCountdown(15); |
|
59
|
setTimerRunning(false); |
|
60
|
}; |
|
61
|
|
|
62
|
const quickActions = [ |
|
63
|
{ |
|
64
|
id: "emergency", |
|
65
|
label: "Emergency Discharge", |
|
66
|
tag: "HARD RESET", |
|
67
|
desc: "15s EC drain & battery isolation protocol", |
|
68
|
icon: AlertTriangle, |
|
69
|
glowColor: "from-amber-500/20 to-orange-500/10", |
|
70
|
borderColor: "border-amber-500/30 hover:border-amber-500/70 group-hover:bg-amber-500/10", |
|
71
|
iconBg: "bg-amber-500/15 text-amber-500 border-amber-500/30", |
|
72
|
badgeColor: "bg-amber-500/20 text-amber-600 dark:text-amber-400 border-amber-500/30", |
|
73
|
action: () => { |
|
74
|
setActiveModal("emergency"); |
|
75
|
setIsExpanded(false); |
|
76
|
setCountdown(15); |
|
77
|
setTimerRunning(false); |
|
78
|
}, |
|
79
|
}, |
|
80
|
{ |
|
81
|
id: "rails", |
|
82
|
label: "Voltage Rail Pinouts", |
|
83
|
tag: "MULTIMETER", |
|
84
|
desc: "Instant +19V, +3.3V, +5V standby test points", |
|
85
|
icon: Activity, |
|
86
|
glowColor: "from-cyan-500/20 to-blue-500/10", |
|
87
|
borderColor: "border-cyan-500/30 hover:border-cyan-500/70 group-hover:bg-cyan-500/10", |
|
88
|
iconBg: "bg-cyan-500/15 text-cyan-500 border-cyan-500/30", |
|
89
|
badgeColor: "bg-cyan-500/20 text-cyan-600 dark:text-cyan-400 border-cyan-500/30", |
|
90
|
action: () => { |
|
91
|
setActiveModal("rails"); |
|
92
|
setIsExpanded(false); |
|
93
|
}, |
|
94
|
}, |
|
95
|
{ |
|
96
|
id: "safety", |
|
97
|
label: "Torque & ESD Standards", |
|
98
|
tag: "BENCH SPECS", |
|
99
|
desc: "0.25 Nm limits, PTM7950 & thermal pads", |
|
100
|
icon: ShieldCheck, |
|
101
|
glowColor: "from-emerald-500/20 to-teal-500/10", |
|
102
|
borderColor: "border-emerald-500/30 hover:border-emerald-500/70 group-hover:bg-emerald-500/10", |
|
103
|
iconBg: "bg-emerald-500/15 text-emerald-500 border-emerald-500/30", |
|
104
|
badgeColor: "bg-emerald-500/20 text-emerald-600 dark:text-emerald-400 border-emerald-500/30", |
|
105
|
action: () => { |
|
106
|
setActiveModal("safety"); |
|
107
|
setIsExpanded(false); |
|
108
|
}, |
|
109
|
}, |
|
110
|
{ |
|
111
|
id: "tools", |
|
112
|
label: "52 Verified Bench Tools", |
|
113
|
tag: "SOFTWARE HUB", |
|
114
|
desc: "FurMark 2, MemTest86, DDU, Rufus & OCCT", |
|
115
|
icon: Download, |
|
116
|
glowColor: "from-blue-500/20 to-indigo-500/10", |
|
117
|
borderColor: "border-blue-500/30 hover:border-blue-500/70 group-hover:bg-blue-500/10", |
|
118
|
iconBg: "bg-blue-500/15 text-blue-500 border-blue-500/30", |
|
119
|
badgeColor: "bg-blue-500/20 text-blue-600 dark:text-blue-400 border-blue-500/30", |
|
120
|
action: () => { |
|
121
|
setLocation("/software-tools"); |
|
122
|
setIsExpanded(false); |
|
123
|
}, |
|
124
|
}, |
|
125
|
{ |
|
126
|
id: "troubleshoot", |
|
127
|
label: "Diagnostic Flowcharts", |
|
128
|
tag: "TRIAGE", |
|
129
|
desc: "No POST, 3-Beep codes & BSOD protocols", |
|
130
|
icon: Zap, |
|
131
|
glowColor: "from-purple-500/20 to-pink-500/10", |
|
132
|
borderColor: "border-purple-500/30 hover:border-purple-500/70 group-hover:bg-purple-500/10", |
|
133
|
iconBg: "bg-purple-500/15 text-purple-500 border-purple-500/30", |
|
134
|
badgeColor: "bg-purple-500/20 text-purple-600 dark:text-purple-400 border-purple-500/30", |
|
135
|
action: () => { |
|
136
|
setLocation("/troubleshooting"); |
|
137
|
setIsExpanded(false); |
|
138
|
}, |
|
139
|
}, |
|
140
|
{ |
|
141
|
id: "android-zip", |
|
142
|
label: "Android Studio Project", |
|
143
|
tag: "GRADLE • APK", |
|
144
|
desc: "Download complete native Android Studio .ZIP", |
|
145
|
icon: Smartphone, |
|
146
|
glowColor: "from-emerald-500/20 to-green-500/10", |
|
147
|
borderColor: "border-emerald-500/30 hover:border-emerald-500/70 group-hover:bg-emerald-500/10", |
|
148
|
iconBg: "bg-emerald-500/15 text-emerald-500 border-emerald-500/30", |
|
149
|
badgeColor: "bg-emerald-500/20 text-emerald-600 dark:text-emerald-400 border-emerald-500/30", |
|
150
|
action: () => { |
|
151
|
setLocation("/downloads"); |
|
152
|
setIsExpanded(false); |
|
153
|
}, |
|
154
|
}, |
|
155
|
]; |
|
156
|
|
|
157
|
return ( |
|
158
|
<> |
|
159
|
<div className="fixed bottom-34 sm:bottom-22 right-4 sm:right-6 z-40 no-print"> |
|
160
|
<div className="relative"> |
|
161
|
|
|
162
|
{/* Fancy Pop-Out Menu Card */} |
|
163
|
<AnimatePresence> |
|
164
|
{isExpanded && ( |
|
165
|
<motion.div |
|
166
|
initial={{ opacity: 0, scale: 0.88, y: 20, transformOrigin: "bottom right" }} |
|
167
|
animate={{ opacity: 1, scale: 1, y: 0 }} |
|
168
|
exit={{ opacity: 0, scale: 0.88, y: 20 }} |
|
169
|
transition={{ type: "spring", stiffness: 350, damping: 25 }} |
|
170
|
className="absolute bottom-15 right-0 w-[310px] sm:w-[360px] rounded-3xl bg-card/95 backdrop-blur-3xl border border-primary/20 shadow-[0_20px_60px_-15px_rgba(0,0,0,0.5)] overflow-hidden" |
|
171
|
> |
|
172
|
{/* HUD Header Banner */} |
|
173
|
<div className="relative p-3.5 bg-gradient-to-r from-primary/20 via-primary/10 to-transparent border-b border-border/50 flex items-center justify-between"> |
|
174
|
<div className="flex items-center gap-2.5"> |
|
175
|
<div className="h-8 w-8 rounded-xl bg-primary text-primary-foreground flex items-center justify-center shadow-md shadow-primary/20"> |
|
176
|
<Sparkles className="h-4 w-4 animate-pulse" /> |
|
177
|
</div> |
|
178
|
<div> |
|
179
|
<div className="text-xs font-black tracking-wider uppercase text-foreground flex items-center gap-1.5"> |
|
180
|
Quick Bench HUD |
|
181
|
<span className="inline-block h-1.5 w-1.5 rounded-full bg-emerald-500 animate-ping" /> |
|
182
|
</div> |
|
183
|
<div className="text-[10px] text-muted-foreground font-mono"> |
|
184
|
STANDBY • 6 BENCH TOOLS |
|
185
|
</div> |
|
186
|
</div> |
|
187
|
</div> |
|
188
|
|
|
189
|
<button |
|
190
|
onClick={() => setIsExpanded(false)} |
|
191
|
className="h-7 w-7 rounded-lg hover:bg-muted/80 flex items-center justify-center text-muted-foreground hover:text-foreground transition-colors" |
|
192
|
> |
|
193
|
<X className="h-4 w-4" /> |
|
194
|
</button> |
|
195
|
</div> |
|
196
|
|
|
197
|
{/* Staggered Action Cards */} |
|
198
|
<div className="p-2.5 space-y-2 max-h-[380px] overflow-y-auto"> |
|
199
|
{quickActions.map((item, idx) => { |
|
200
|
const Icon = item.icon; |
|
201
|
return ( |
|
202
|
<motion.button |
|
203
|
key={item.id} |
|
204
|
initial={{ opacity: 0, x: 15 }} |
|
205
|
animate={{ opacity: 1, x: 0 }} |
|
206
|
transition={{ delay: idx * 0.04, duration: 0.2 }} |
|
207
|
onClick={item.action} |
|
208
|
className={`w-full group relative p-2.5 rounded-2xl border ${item.borderColor} bg-gradient-to-r ${item.glowColor} hover:shadow-lg transition-all duration-200 text-left flex items-center gap-3 overflow-hidden cursor-pointer`} |
|
209
|
> |
|
210
|
{/* Icon Pod */} |
|
211
|
<div className={`h-10 w-10 rounded-xl border flex items-center justify-center shrink-0 shadow-xs ${item.iconBg} transition-transform group-hover:scale-110 group-hover:rotate-3`}> |
|
212
|
<Icon className="h-5 w-5" /> |
|
213
|
</div> |
|
214
|
|
|
215
|
{/* Text Info */} |
|
216
|
<div className="flex-1 min-w-0"> |
|
217
|
<div className="flex items-center justify-between gap-1 mb-0.5"> |
|
218
|
<span className="text-xs font-bold text-foreground group-hover:text-primary transition-colors truncate"> |
|
219
|
{item.label} |
|
220
|
</span> |
|
221
|
<span className={`text-[9px] font-mono font-bold px-1.5 py-0.2 rounded-md border ${item.badgeColor}`}> |
|
222
|
{item.tag} |
|
223
|
</span> |
|
224
|
</div> |
|
225
|
<p className="text-[10.5px] text-muted-foreground line-clamp-1 group-hover:text-foreground/80 transition-colors"> |
|
226
|
{item.desc} |
|
227
|
</p> |
|
228
|
</div> |
|
229
|
|
|
230
|
<ChevronRight className="h-4 w-4 text-muted-foreground group-hover:text-primary group-hover:translate-x-0.5 transition-all shrink-0" /> |
|
231
|
</motion.button> |
|
232
|
); |
|
233
|
})} |
|
234
|
</div> |
|
235
|
|
|
236
|
{/* Bottom Status Ticker */} |
|
237
|
<div className="px-3.5 py-2 bg-muted/40 border-t border-border/40 flex items-center justify-between text-[10px] text-muted-foreground font-mono"> |
|
238
|
<span>SAFETY INTERLOCK: ACTIVE</span> |
|
239
|
<span className="text-emerald-500 font-bold">READY TO DEPLOY</span> |
|
240
|
</div> |
|
241
|
</motion.div> |
|
242
|
)} |
|
243
|
</AnimatePresence> |
|
244
|
|
|
245
|
{/* Fancy Floating Trigger Bubble */} |
|
246
|
<motion.button |
|
247
|
whileHover={{ scale: 1.08 }} |
|
248
|
whileTap={{ scale: 0.94 }} |
|
249
|
onClick={() => setIsExpanded(!isExpanded)} |
|
250
|
className={`relative h-12 w-12 sm:h-13 sm:w-13 rounded-2xl border flex items-center justify-center transition-all duration-300 shadow-xl group cursor-pointer ${ |
|
251
|
isExpanded |
|
252
|
? "bg-primary text-primary-foreground border-primary shadow-primary/30" |
|
253
|
: "bg-card/90 hover:bg-card text-foreground border-border/70 hover:border-primary/50 shadow-glass" |
|
254
|
}`} |
|
255
|
title="Quick Bench Actions & HUD" |
|
256
|
> |
|
257
|
{/* Animated Ambient Ring / Glow */} |
|
258
|
{!isExpanded && ( |
|
259
|
<span className="absolute -inset-0.5 rounded-2xl bg-gradient-to-r from-primary/40 to-amber-500/40 opacity-75 blur-xs group-hover:opacity-100 transition-opacity -z-10 animate-pulse" /> |
|
260
|
)} |
|
261
|
|
|
262
|
{isExpanded ? ( |
|
263
|
<X className="h-5 w-5 transition-transform rotate-90 duration-200" /> |
|
264
|
) : ( |
|
265
|
<div className="relative"> |
|
266
|
<Wrench className="h-5 w-5 text-primary group-hover:rotate-45 transition-transform duration-300" /> |
|
267
|
<span className="absolute -top-1 -right-1 h-2 w-2 rounded-full bg-amber-500 border border-background" /> |
|
268
|
</div> |
|
269
|
)} |
|
270
|
</motion.button> |
|
271
|
</div> |
|
272
|
</div> |
|
273
|
|
|
274
|
{/* 1. Emergency Discharge Interactive Modal */} |
|
275
|
<Dialog open={activeModal === "emergency"} onOpenChange={(open) => !open && setActiveModal(null)}> |
|
276
|
<DialogContent className="max-w-md rounded-3xl border-amber-500/30 bg-card/95 backdrop-blur-2xl"> |
|
277
|
<DialogHeader> |
|
278
|
<div className="flex items-center gap-2.5 mb-1"> |
|
279
|
<div className="p-2 rounded-xl bg-amber-500/20 text-amber-500 border border-amber-500/30"> |
|
280
|
<AlertTriangle className="h-5 w-5" /> |
|
281
|
</div> |
|
282
|
<div> |
|
283
|
<DialogTitle className="text-lg font-extrabold text-foreground">Emergency Force Discharge</DialogTitle> |
|
284
|
<DialogDescription className="text-xs text-muted-foreground">Hard Embedded Controller (EC) Reset & Power Rail Drain</DialogDescription> |
|
285
|
</div> |
|
286
|
</div> |
|
287
|
</DialogHeader> |
|
288
|
|
|
289
|
<div className="space-y-4 pt-2"> |
|
290
|
{/* Interactive 15-Second Timer Pod */} |
|
291
|
<div className="p-4 rounded-2xl bg-amber-500/10 border border-amber-500/30 text-center space-y-3"> |
|
292
|
<div className="text-3xl font-black font-mono text-amber-500 flex items-center justify-center gap-2"> |
|
293
|
<Timer className="h-7 w-7" /> |
|
294
|
{countdown !== null ? `${countdown}s` : "15s"} |
|
295
|
</div> |
|
296
|
<p className="text-xs text-muted-foreground max-w-xs mx-auto"> |
|
297
|
{countdown === 0 ? ( |
|
298
|
<span className="text-emerald-500 font-bold flex items-center justify-center gap-1"> |
|
299
|
<CheckCircle2 className="h-4 w-4" /> Capacitors discharged! EC is hard-reset. |
|
300
|
</span> |
|
301
|
) : ( |
|
302
|
"Firmly press and hold the power button down during this countdown." |
|
303
|
)} |
|
304
|
</p> |
|
305
|
|
|
306
|
<div className="flex justify-center gap-2"> |
|
307
|
<Button |
|
308
|
onClick={startEmergencyTimer} |
|
309
|
disabled={timerRunning} |
|
310
|
className="bg-amber-500 hover:bg-amber-600 text-white rounded-xl text-xs font-bold" |
|
311
|
> |
|
312
|
{timerRunning ? "Timing (Hold Down)..." : "Start 15s Hold Timer"} |
|
313
|
</Button> |
|
314
|
<Button |
|
315
|
variant="outline" |
|
316
|
onClick={resetEmergencyTimer} |
|
317
|
className="rounded-xl text-xs" |
|
318
|
> |
|
319
|
Reset |
|
320
|
</Button> |
|
321
|
</div> |
|
322
|
</div> |
|
323
|
|
|
324
|
{/* Checklist */} |
|
325
|
<div className="space-y-2"> |
|
326
|
<div className="text-xs font-bold text-foreground">3-Step Bench Safe Sequence:</div> |
|
327
|
<div className="p-2.5 rounded-xl bg-muted/40 border border-border/40 space-y-1.5 text-xs text-muted-foreground"> |
|
328
|
<div className="flex items-start gap-2"> |
|
329
|
<span className="font-mono font-bold text-amber-500">01.</span> |
|
330
|
<span><strong>Disconnect AC Power:</strong> Unplug barrel jack and USB-C Type-C chargers immediately.</span> |
|
331
|
</div> |
|
332
|
<div className="flex items-start gap-2"> |
|
333
|
<span className="font-mono font-bold text-amber-500">02.</span> |
|
334
|
<span><strong>Isolate Internal Battery:</strong> Remove bottom panel and pull the high-current battery molex header.</span> |
|
335
|
</div> |
|
336
|
<div className="flex items-start gap-2"> |
|
337
|
<span className="font-mono font-bold text-amber-500">03.</span> |
|
338
|
<span><strong>Drain Residual Charge:</strong> Hold power button for 15s to drain filter capacitors before probing.</span> |
|
339
|
</div> |
|
340
|
</div> |
|
341
|
</div> |
|
342
|
</div> |
|
343
|
</DialogContent> |
|
344
|
</Dialog> |
|
345
|
|
|
346
|
{/* 2. Standby Voltage Rail Quick Reference Modal */} |
|
347
|
<Dialog open={activeModal === "rails"} onOpenChange={(open) => !open && setActiveModal(null)}> |
|
348
|
<DialogContent className="max-w-lg rounded-3xl border-cyan-500/30 bg-card/95 backdrop-blur-2xl"> |
|
349
|
<DialogHeader> |
|
350
|
<div className="flex items-center gap-2.5 mb-1"> |
|
351
|
<div className="p-2 rounded-xl bg-cyan-500/20 text-cyan-500 border border-cyan-500/30"> |
|
352
|
<Activity className="h-5 w-5" /> |
|
353
|
</div> |
|
354
|
<div> |
|
355
|
<DialogTitle className="text-lg font-extrabold text-foreground">Multimeter Power Rail Cheat-Sheet</DialogTitle> |
|
356
|
<DialogDescription className="text-xs text-muted-foreground">Nominal voltages, tolerances, and typical board test points</DialogDescription> |
|
357
|
</div> |
|
358
|
</div> |
|
359
|
</DialogHeader> |
|
360
|
|
|
361
|
<div className="space-y-3 pt-2"> |
|
362
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2.5"> |
|
363
|
{[ |
|
364
|
{ rail: "+19.0V / +20.0V", name: "+DC_IN / VBUS", tolerance: "±5%", note: "Primary DC input MOSFETs (PQ101/PQ102)" }, |
|
365
|
{ rail: "+3.3V_ALW", name: "Standby 3.3V Always", tolerance: "±2%", note: "Powers Super I/O EC and BIOS chip pin 8" }, |
|
366
|
{ rail: "+5.0V_ALW", name: "Standby 5.0V Always", tolerance: "±2%", note: "Powers USB 5V lines & 5V regulator coil" }, |
|
367
|
{ rail: "+1.8V_PRIM", name: "PCH / SoC Standby", tolerance: "±3%", note: "Chipset logic & initial power sequencer" }, |
|
368
|
{ rail: "+1.2V / +1.1V", name: "DDR4 / DDR5 VDD", tolerance: "±1.5%", note: "RAM power rail inductor (PL501)" }, |
|
369
|
{ rail: "+0.85V - +1.2V", name: "VCORE / VGPU", tolerance: "±1%", note: "CPU/GPU active state core switching VRMs" }, |
|
370
|
].map((r, idx) => ( |
|
371
|
<div key={idx} className="p-3 rounded-2xl bg-muted/40 border border-border/50 space-y-1"> |
|
372
|
<div className="flex items-center justify-between"> |
|
373
|
<span className="font-mono font-bold text-sm text-cyan-600 dark:text-cyan-400">{r.rail}</span> |
|
374
|
<Badge variant="outline" className="text-[10px] font-mono border-cyan-500/30">{r.tolerance}</Badge> |
|
375
|
</div> |
|
376
|
<div className="text-xs font-semibold text-foreground">{r.name}</div> |
|
377
|
<div className="text-[10.5px] text-muted-foreground">{r.note}</div> |
|
378
|
</div> |
|
379
|
))} |
|
380
|
</div> |
|
381
|
|
|
382
|
<div className="p-3 rounded-xl bg-cyan-500/10 border border-cyan-500/20 text-xs text-muted-foreground flex items-center gap-2"> |
|
383
|
<Sparkles className="h-4 w-4 text-cyan-500 shrink-0" /> |
|
384
|
<span><strong>Ground Reference:</strong> Clip black multimeter lead to copper chassis standoff or USB shield.</span> |
|
385
|
</div> |
|
386
|
</div> |
|
387
|
</DialogContent> |
|
388
|
</Dialog> |
|
389
|
|
|
390
|
{/* 3. Torque & ESD Safety Standards Modal */} |
|
391
|
<Dialog open={activeModal === "safety"} onOpenChange={(open) => !open && setActiveModal(null)}> |
|
392
|
<DialogContent className="max-w-md rounded-3xl border-emerald-500/30 bg-card/95 backdrop-blur-2xl"> |
|
393
|
<DialogHeader> |
|
394
|
<div className="flex items-center gap-2.5 mb-1"> |
|
395
|
<div className="p-2 rounded-xl bg-emerald-500/20 text-emerald-500 border border-emerald-500/30"> |
|
396
|
<ShieldCheck className="h-5 w-5" /> |
|
397
|
</div> |
|
398
|
<div> |
|
399
|
<DialogTitle className="text-lg font-extrabold text-foreground">Torque & Thermal Bench Standards</DialogTitle> |
|
400
|
<DialogDescription className="text-xs text-muted-foreground">Certified technician tightening specifications & thermal protocols</DialogDescription> |
|
401
|
</div> |
|
402
|
</div> |
|
403
|
</DialogHeader> |
|
404
|
|
|
405
|
<div className="space-y-3 pt-2"> |
|
406
|
<div className="space-y-2"> |
|
407
|
<div className="text-xs font-bold text-foreground">Standard Torque Specifications:</div> |
|
408
|
<div className="grid grid-cols-2 gap-2 text-xs"> |
|
409
|
<div className="p-2.5 rounded-xl bg-muted/40 border border-border/40"> |
|
410
|
<div className="font-mono font-bold text-emerald-500 text-sm">0.25 – 0.30 Nm</div> |
|
411
|
<div className="font-semibold text-foreground mt-0.5">CPU/GPU Heatsink</div> |
|
412
|
<div className="text-[10px] text-muted-foreground">Diagonal sequence (1→2→3→4)</div> |
|
413
|
</div> |
|
414
|
<div className="p-2.5 rounded-xl bg-muted/40 border border-border/40"> |
|
415
|
<div className="font-mono font-bold text-emerald-500 text-sm">0.18 – 0.20 Nm</div> |
|
416
|
<div className="font-semibold text-foreground mt-0.5">M.2 NVMe & Wi-Fi</div> |
|
417
|
<div className="text-[10px] text-muted-foreground">Prevents PCB trace fracturing</div> |
|
418
|
</div> |
|
419
|
</div> |
|
420
|
</div> |
|
421
|
|
|
422
|
<div className="p-3 rounded-2xl bg-emerald-500/10 border border-emerald-500/30 space-y-1.5 text-xs text-muted-foreground"> |
|
423
|
<div className="font-bold text-emerald-600 dark:text-emerald-400 flex items-center gap-1.5"> |
|
424
|
<Flame className="h-4 w-4" /> Recommended Thermal Interface: |
|
425
|
</div> |
|
426
|
<div>• <strong>Honeywell PTM7950:</strong> 0.25mm phase change pad on bare dies (no pump-out effect).</div> |
|
427
|
<div>• <strong>K5 Pro Viscous Paste:</strong> For uneven VRAM and MOSFET gap replacement (0.5–2.0mm).</div> |
|
428
|
</div> |
|
429
|
</div> |
|
430
|
</DialogContent> |
|
431
|
</Dialog> |
|
432
|
</> |
|
433
|
); |
|
434
|
} |