Skip to content

Commit 58ff484

Browse files
committed
freebuff web: improve styles
1 parent cbbfe73 commit 58ff484

File tree

8 files changed

+117
-99
lines changed

8 files changed

+117
-99
lines changed

freebuff/web/src/app/home-client.tsx

Lines changed: 89 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ function SetupGuide() {
6868
<button
6969
onClick={() => setIsOpen(!isOpen)}
7070
aria-expanded={isOpen}
71-
className="flex items-center gap-2 mx-auto text-sm text-zinc-400 hover:text-acid-green transition-colors duration-200 cursor-pointer group"
71+
className="flex items-center gap-2 mx-auto text-sm text-zinc-400 hover:text-acid-matrix transition-colors duration-200 cursor-pointer group"
7272
>
7373
<span>Install guide</span>
7474
<motion.span
@@ -92,7 +92,7 @@ function SetupGuide() {
9292
<ol className="space-y-4">
9393
{setupSteps.map((step, i) => (
9494
<li key={i} className="flex gap-3">
95-
<span className="flex-shrink-0 w-6 h-6 rounded-full bg-acid-green/10 border border-acid-green/30 flex items-center justify-center text-xs font-mono text-acid-green">
95+
<span className="flex-shrink-0 w-6 h-6 rounded-full bg-acid-matrix/10 border border-acid-matrix/30 flex items-center justify-center text-xs font-mono text-acid-matrix">
9696
{i + 1}
9797
</span>
9898
<div className="flex-1 min-w-0">
@@ -101,7 +101,7 @@ function SetupGuide() {
101101
<p className="text-xs text-zinc-500 mt-0.5">{step.description}</p>
102102
)}
103103
{'command' in step && step.command && (
104-
<div className="mt-1.5 flex items-center gap-2 bg-zinc-800/60 border border-zinc-700/40 rounded-md px-3 py-1.5 hover:border-acid-green/30 transition-colors duration-200">
104+
<div className="mt-1.5 flex items-center gap-2 bg-zinc-800/60 border border-zinc-700/40 rounded-md px-3 py-1.5 hover:border-acid-matrix/30 transition-colors duration-200">
105105
<code className="font-mono text-xs text-white/80 flex-1 select-all">
106106
{step.command}
107107
</code>
@@ -125,12 +125,12 @@ function InstallCommand({ className }: { className?: string }) {
125125
<div
126126
className={cn(
127127
'flex items-center gap-2 bg-zinc-900/80 border border-zinc-700/50 rounded-lg px-4 py-3 font-mono text-sm',
128-
'hover:border-acid-green/50 hover:shadow-[0_0_20px_rgba(0,255,149,0.12)] transition-all duration-300',
128+
'hover:border-acid-matrix/50 hover:shadow-[0_0_20px_rgba(124,255,63,0.12)] transition-all duration-300',
129129
'gradient-border-shine',
130130
className,
131131
)}
132132
>
133-
<span className="text-acid-green select-none">$</span>
133+
<span className="text-acid-matrix select-none">$</span>
134134
<code className="text-white/90 select-all flex-1">
135135
{INSTALL_COMMAND}
136136
</code>
@@ -156,7 +156,7 @@ function FAQList() {
156156
>
157157
<button
158158
onClick={() => setOpenIndex(isOpen ? null : i)}
159-
className="w-full flex items-center justify-between gap-4 bg-zinc-900/50 border border-zinc-800 rounded-xl px-6 py-4 text-left hover:border-acid-green/30 hover:bg-zinc-900/80 transition-all duration-300 cursor-pointer"
159+
className="w-full flex items-center justify-between gap-4 bg-zinc-900/50 border border-zinc-800 rounded-xl px-6 py-4 text-left hover:border-acid-matrix/30 hover:bg-zinc-900/80 transition-all duration-300 cursor-pointer"
160160
>
161161
<span className="font-semibold text-white">{faq.question}</span>
162162
<motion.span
@@ -192,9 +192,61 @@ function FAQList() {
192192
const PHILOSOPHY_WORDS = [
193193
{ word: 'SIMPLE', description: 'No modes. No config. Just code.' },
194194
{ word: 'FAST', description: 'Up to 3× the speed of Claude Code' },
195-
{ word: 'LOADED', description: 'Web research, browser use, and more — built in' },
195+
{ word: 'LOADED', description: 'Built in web research, browser use, and more' },
196196
]
197197

198+
function PhilosophySection() {
199+
const [litWords, setLitWords] = useState<Set<number>>(new Set())
200+
201+
const lightUp = (i: number) => {
202+
setLitWords(prev => {
203+
const next = new Set(prev)
204+
next.add(i)
205+
return next
206+
})
207+
}
208+
209+
const dimDown = (i: number) => {
210+
setLitWords(prev => {
211+
const next = new Set(prev)
212+
next.delete(i)
213+
return next
214+
})
215+
}
216+
217+
return (
218+
<div className="relative z-10 container mx-auto max-w-5xl px-4 pt-16 md:pt-24 pb-24 md:pb-32">
219+
<div className="flex flex-col gap-12 md:gap-16">
220+
{PHILOSOPHY_WORDS.map((item, i) => (
221+
<motion.div
222+
key={item.word}
223+
initial={{ opacity: 0, filter: 'blur(12px)' }}
224+
whileInView={{ opacity: 1, filter: 'blur(0px)' }}
225+
viewport={{ once: true, amount: 0.5 }}
226+
transition={{ duration: 0.7, delay: i * 0.1 }}
227+
className="group"
228+
>
229+
<motion.div
230+
onViewportEnter={() => lightUp(i)}
231+
onViewportLeave={() => dimDown(i)}
232+
viewport={{ margin: '0px 0px -55% 0px' }}
233+
className={cn(
234+
'font-dm-mono text-7xl md:text-[8rem] lg:text-[10rem] font-medium leading-[0.85] tracking-tighter select-none transition-all duration-500',
235+
litWords.has(i) ? 'keyword-filled' : 'keyword-hollow',
236+
)}
237+
>
238+
{item.word}
239+
</motion.div>
240+
<p className="mt-3 md:mt-4 text-zinc-500 text-sm md:text-base font-mono tracking-wide">
241+
{item.description}
242+
</p>
243+
</motion.div>
244+
))}
245+
</div>
246+
</div>
247+
)
248+
}
249+
198250
const wordVariant = {
199251
initial: { opacity: 0, y: 30, filter: 'blur(8px)' },
200252
animate: {
@@ -211,12 +263,12 @@ const wordVariant = {
211263
export default function HomeClient() {
212264
return (
213265
<div className="relative">
214-
{/* ─── Hero Section ─── */}
215-
<section className="relative min-h-[90vh] flex flex-col items-center justify-center overflow-hidden">
216-
{/* Layered backgrounds */}
217-
<div className="absolute inset-0 bg-gradient-to-b from-dark-forest-green via-black to-black" />
218-
<div className="absolute inset-0 bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(0,255,149,0.12),transparent_60%)]" />
219-
<div className="absolute inset-0 bg-[radial-gradient(ellipse_50%_80%_at_50%_100%,rgba(0,255,149,0.04),transparent_60%)]" />
266+
{/* ─── Hero + Philosophy: unified section ─── */}
267+
<div className="relative overflow-hidden">
268+
{/* Shared layered backgrounds */}
269+
<div className="absolute inset-0 bg-gradient-to-b from-dark-forest-green via-black/95 to-black" />
270+
<div className="absolute inset-0 bg-[radial-gradient(ellipse_80%_50%_at_50%_-10%,rgba(124,255,63,0.12),transparent_50%)]" />
271+
<div className="absolute inset-0 bg-[radial-gradient(ellipse_60%_40%_at_50%_65%,rgba(124,255,63,0.06),transparent_50%)]" />
220272

221273
<HeroGrid />
222274
<BackgroundBeams />
@@ -237,9 +289,9 @@ export default function HomeClient() {
237289
alt="Freebuff"
238290
width={28}
239291
height={28}
240-
className="rounded-sm transition-all duration-300 group-hover:brightness-110"
292+
className="rounded-sm opacity-60 group-hover:opacity-100 transition-all duration-300 group-hover:brightness-110"
241293
/>
242-
<span className="text-xl tracking-widest font-serif text-white">
294+
<span className="text-xl tracking-widest font-serif text-zinc-400 group-hover:text-white transition-colors duration-200">
243295
freebuff
244296
</span>
245297
</Link>
@@ -258,7 +310,7 @@ export default function HomeClient() {
258310
</motion.div>
259311

260312
{/* Hero content */}
261-
<div className="relative z-10 container mx-auto px-4 pt-20 pb-12 text-center">
313+
<div className="relative z-10 container mx-auto px-4 pt-32 pb-16 md:pt-40 md:pb-20 text-center min-h-screen flex flex-col items-center justify-center">
262314
{/* Headline with staggered word animation */}
263315
<motion.h1
264316
className="hero-heading mb-8"
@@ -275,7 +327,7 @@ export default function HomeClient() {
275327
<motion.span
276328
key={i}
277329
variants={wordVariant}
278-
className={word === 'free' ? 'inline-block mr-[0.3em] text-acid-green neon-text animate-glow-pulse' : 'inline-block mr-[0.3em] text-white'}
330+
className={word === 'free' ? 'inline-block mr-[0.3em] text-acid-matrix neon-text animate-glow-pulse' : 'inline-block mr-[0.3em] text-white'}
279331
>
280332
{word}
281333
</motion.span>
@@ -298,7 +350,7 @@ export default function HomeClient() {
298350
initial={{ opacity: 0, y: 20 }}
299351
animate={{ opacity: 1, y: 0 }}
300352
transition={{ duration: 0.5, delay: 1.0 }}
301-
className="max-w-md mx-auto mb-4"
353+
className="max-w-lg w-full mx-auto mb-4"
302354
>
303355
<InstallCommand />
304356
</motion.div>
@@ -313,56 +365,28 @@ export default function HomeClient() {
313365
</motion.div>
314366
</div>
315367

316-
{/* Bottom fade */}
317-
<div className="absolute bottom-0 left-0 right-0 h-32 bg-gradient-to-t from-black to-transparent" />
318-
</section>
368+
{/* Philosophy content — same background, continuous flow */}
369+
<PhilosophySection />
319370

320-
{/* ─── Philosophy Section ─── */}
321-
<section className="relative py-24 md:py-32 px-4 overflow-hidden">
322-
<div className="relative z-10 container mx-auto max-w-5xl">
323-
<div className="flex flex-col gap-12 md:gap-16">
324-
{PHILOSOPHY_WORDS.map((item, i) => (
325-
<motion.div
326-
key={item.word}
327-
initial={{ opacity: 0, filter: 'blur(12px)' }}
328-
whileInView={{ opacity: 1, filter: 'blur(0px)' }}
329-
viewport={{ once: true, amount: 0.5 }}
330-
transition={{ duration: 0.7, delay: i * 0.1 }}
331-
className="group"
332-
>
333-
<div className="keyword-hollow font-dm-mono text-7xl md:text-[8rem] lg:text-[10rem] font-medium leading-[0.85] tracking-tighter select-none">
334-
{item.word}
335-
</div>
336-
<p className="mt-3 md:mt-4 text-zinc-500 text-sm md:text-base font-mono tracking-wide">
337-
{item.description}
338-
</p>
339-
</motion.div>
340-
))}
341-
</div>
342-
</div>
343-
</section>
344-
345-
{/* Divider */}
346-
<div className="h-px bg-gradient-to-r from-transparent via-acid-green/30 to-transparent" />
347-
348-
{/* ─── FAQ Section ─── */}
349-
<section className="py-24 px-4">
350-
<div className="container mx-auto max-w-2xl">
351-
<motion.div
352-
initial={{ opacity: 0, y: 20 }}
353-
whileInView={{ opacity: 1, y: 0 }}
354-
viewport={{ once: true, amount: 0.3 }}
355-
transition={{ duration: 0.6 }}
356-
className="text-center mb-12"
357-
>
358-
<h2 className="text-3xl md:text-4xl font-bold mb-4">
359-
Frequently asked questions
360-
</h2>
361-
</motion.div>
371+
{/* ─── FAQ Section ─── */}
372+
<div className="relative z-10 py-24 px-4">
373+
<div className="container mx-auto max-w-2xl">
374+
<motion.div
375+
initial={{ opacity: 0, y: 20 }}
376+
whileInView={{ opacity: 1, y: 0 }}
377+
viewport={{ once: true, amount: 0.3 }}
378+
transition={{ duration: 0.6 }}
379+
className="text-center mb-12"
380+
>
381+
<h2 className="text-3xl md:text-4xl font-bold mb-4">
382+
Frequently asked questions
383+
</h2>
384+
</motion.div>
362385

363-
<FAQList />
386+
<FAQList />
387+
</div>
364388
</div>
365-
</section>
389+
</div>
366390
</div>
367391
)
368392
}

freebuff/web/src/components/background-beams.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function BackgroundBeams({ className }: { className?: string }) {
3737
className="absolute left-[--beam-x] top-[--beam-y] h-px w-px"
3838
style={{
3939
boxShadow:
40-
'0 0 150px 80px rgba(0, 255, 149, 0.08), 0 0 300px 150px rgba(0, 255, 149, 0.04)',
40+
'0 0 150px 80px rgba(124, 255, 63, 0.08), 0 0 300px 150px rgba(124, 255, 63, 0.04)',
4141
transform: 'translate(-50%, -50%)',
4242
}}
4343
/>

freebuff/web/src/components/copy-button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function CopyButton({
3030
aria-label={`Copy: ${value}`}
3131
>
3232
{copied ? (
33-
<Check className="h-4 w-4 text-acid-green" />
33+
<Check className="h-4 w-4 text-acid-matrix" />
3434
) : (
3535
<Copy className="h-4 w-4 text-white/60" />
3636
)}

freebuff/web/src/components/footer.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Link from 'next/link'
33

44
export function Footer() {
55
return (
6-
<footer className="w-full border-t">
6+
<footer className="w-full">
77
<div className="container mx-auto flex flex-col gap-4 py-8 px-4">
88
<div className="grid grid-cols-1 sm:grid-cols-3 gap-8">
99
<div>
@@ -66,20 +66,12 @@ export function Footer() {
6666
>
6767
Terms of Service
6868
</Link>
69+
<span className="text-xs text-muted-foreground mt-1">
70+
© {new Date().getFullYear()} Freebuff
71+
</span>
6972
</nav>
7073
</div>
7174
</div>
72-
73-
<div className="border-t pt-4 text-center text-xs text-muted-foreground">
74-
© {new Date().getFullYear()} Freebuff. Built on the{' '}
75-
<Link
76-
href="https://codebuff.com"
77-
className="hover:text-primary underline underline-offset-4"
78-
>
79-
Codebuff
80-
</Link>{' '}
81-
platform.
82-
</div>
8375
</div>
8476
</footer>
8577
)

freebuff/web/src/components/hero-grid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function HeroGrid({ className }: { className?: string }) {
1010
className="absolute inset-0 opacity-[0.03]"
1111
style={{
1212
backgroundImage:
13-
'radial-gradient(circle, #00FF95 1px, transparent 1px)',
13+
'radial-gradient(circle, #7CFF3F 1px, transparent 1px)',
1414
backgroundSize: '32px 32px',
1515
}}
1616
/>
@@ -20,7 +20,7 @@ export function HeroGrid({ className }: { className?: string }) {
2020
className="h-px w-full"
2121
style={{
2222
background:
23-
'linear-gradient(90deg, transparent, rgba(0,255,149,0.15) 20%, rgba(0,255,149,0.3) 50%, rgba(0,255,149,0.15) 80%, transparent)',
23+
'linear-gradient(90deg, transparent, rgba(124,255,63,0.15) 20%, rgba(124,255,63,0.3) 50%, rgba(124,255,63,0.15) 80%, transparent)',
2424
}}
2525
/>
2626
</div>
@@ -29,7 +29,7 @@ export function HeroGrid({ className }: { className?: string }) {
2929
className="absolute inset-0 opacity-[0.025]"
3030
style={{
3131
backgroundImage:
32-
'linear-gradient(90deg, #00FF95 1px, transparent 1px)',
32+
'linear-gradient(90deg, #7CFF3F 1px, transparent 1px)',
3333
backgroundSize: '120px 120px',
3434
}}
3535
/>

freebuff/web/src/components/terminal-demo.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ export function TerminalDemo() {
4242
const getLineColor = (type: string) => {
4343
switch (type) {
4444
case 'prompt':
45-
return 'text-acid-green'
45+
return 'text-acid-matrix'
4646
case 'user':
4747
return 'text-white font-medium'
4848
case 'agent':
4949
return 'text-zinc-300'
5050
case 'success':
51-
return 'text-acid-green font-medium'
51+
return 'text-acid-matrix font-medium'
5252
default:
5353
return 'text-zinc-500'
5454
}
@@ -62,7 +62,7 @@ export function TerminalDemo() {
6262
className="relative mx-auto max-w-2xl"
6363
>
6464
{/* Glow behind terminal */}
65-
<div className="absolute -inset-4 bg-acid-green/[0.03] blur-2xl rounded-3xl" />
65+
<div className="absolute -inset-4 bg-acid-matrix/[0.03] blur-2xl rounded-3xl" />
6666

6767
<div className="relative rounded-xl border border-zinc-800/80 bg-zinc-950/90 backdrop-blur-sm overflow-hidden shadow-2xl shadow-black/50">
6868
{/* Title bar */}
@@ -93,7 +93,7 @@ export function TerminalDemo() {
9393
))}
9494
</AnimatePresence>
9595
{visibleLines < DEMO_LINES.length && (
96-
<span className="inline-block w-2 h-4 bg-acid-green/70 animate-terminal-cursor" />
96+
<span className="inline-block w-2 h-4 bg-acid-matrix/70 animate-terminal-cursor" />
9797
)}
9898
</div>
9999
</div>

0 commit comments

Comments
 (0)