Skip to content

Commit 7fc9bc3

Browse files
authored
Merge pull request #47 from jayantkageriofficial/staging
Landing Page Content Update
1 parent b205f6f commit 7fc9bc3

7 files changed

Lines changed: 296 additions & 201 deletions

File tree

components/landing/FAQ/FAQ.jsx

Lines changed: 75 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,58 @@
1-
import { useState, useRef } from 'react';
2-
import { motion, AnimatePresence } from 'framer-motion';
3-
import { gsap } from 'gsap';
4-
import { ScrollTrigger } from 'gsap/ScrollTrigger';
5-
import { useGSAP } from '@gsap/react';
6-
import { useRetroSound } from '../hooks/useRetroSound';
7-
import './FAQ.css';
1+
import { useState, useRef } from "react";
2+
import { motion, AnimatePresence } from "framer-motion";
3+
import { gsap } from "gsap";
4+
import { ScrollTrigger } from "gsap/ScrollTrigger";
5+
import { useGSAP } from "@gsap/react";
6+
import { useRetroSound } from "../hooks/useRetroSound";
7+
import "./FAQ.css";
88

99
gsap.registerPlugin(ScrollTrigger);
1010

1111
const faqsByCategory = {
1212
General: [
1313
{
14-
q: 'Who can participate?',
15-
a: 'PBCTF is open to students, professionals, and cybersecurity enthusiasts of all skill levels. Participants must be at least 18 years old or accompanied by a guardian.',
14+
q: "Who can participate?",
15+
a: "PBCTF is open to students, professionals, and cybersecurity enthusiasts of all skill levels.",
1616
},
1717
{
18-
q: 'Do I need prior CTF experience?',
19-
a: 'While prior experience is helpful, it is not mandatory. We offer challenges across multiple difficulty levels, making the competition accessible to beginners while still challenging for veterans.',
18+
q: "Do I need prior CTF experience?",
19+
a: "While prior experience is helpful, it is not mandatory. We offer challenges across multiple difficulty levels, making the competition accessible to beginners while still challenging for veterans.",
2020
},
2121
{
22-
q: 'Will certificates be issued?',
23-
a: 'Yes. All participants receive a certificate of participation. Winners receive special achievement certificates and trophies.',
22+
q: "Will certificates be issued?",
23+
a: "Yes. All participants receive a certificate of participation. Winners receive special achievement certificates and prizes.",
2424
},
2525
],
2626
Teams: [
2727
{
28-
q: 'Can I participate individually?',
29-
a: 'Teams of 2-4 members are required. If you do not have a team, join our Discord community to find teammates before registration closes.',
28+
q: "Can I participate individually?",
29+
a: "Yes, individual participation is allowed. You need to create a solo team in the dashboard",
30+
},
31+
{
32+
q: "What is the maximum team size?",
33+
a: "A team can consist of a maximum of Two members.",
3034
},
3135
],
3236
Logistics: [
3337
{
34-
q: 'What should I bring?',
35-
a: 'Bring your laptop, charger, any preferred peripherals, and a valid government-issued ID. All other equipment and resources will be provided at the venue.',
38+
q: "What should I bring?",
39+
a: "Bring your laptop, charger, any preferred peripherals, and a valid government-issued ID. All other equipment and resources will be provided at the venue.",
3640
},
3741
{
38-
q: 'Is accommodation provided?',
39-
a: 'Accommodation is not provided directly, but we have partnered with nearby hotels offering discounted rates for participants. Details will be shared after registration.',
42+
q: "Is accommodation provided?",
43+
a: "No accommodation is provided. Participants are responsible for their own lodging arrangements.",
4044
},
4145
],
4246
Rules: [
4347
{
44-
q: 'How are winners selected?',
45-
a: 'Teams are ranked based on total points earned by solving challenges. In case of a tie, the team that submitted solutions earliest wins.',
48+
q: "How are winners selected?",
49+
a: "Teams are ranked based on total points earned by solving challenges. In case of a tie, the team that submitted solutions earliest wins.",
4650
},
4751
{
48-
q: 'What is the competition format?',
49-
a: 'PBCTF is a jeopardy-style CTF with challenges across 8 categories. The competition runs for 24 continuous hours. Teams work together to solve as many challenges as possible.',
52+
q: "What is the competition format?",
53+
a: "PBCTF is a jeopardy-style CTF with challenges across 8 categories. The competition runs for 8 continuous hours. Teams work together to solve as many challenges as possible.",
5054
},
51-
]
55+
],
5256
};
5357

5458
const categories = Object.keys(faqsByCategory);
@@ -57,21 +61,25 @@ export default function FAQ() {
5761
const [activeCategory, setActiveCategory] = useState(categories[0]);
5862
const [openIndex, setOpenIndex] = useState(null);
5963
const sectionRef = useRef(null);
60-
const { playHover, playSelect, playWindowOpen, playWindowClose } = useRetroSound();
64+
const { playHover, playSelect, playWindowOpen, playWindowClose } =
65+
useRetroSound();
6166

62-
useGSAP(() => {
63-
gsap.from('.faq__gameboy', {
64-
opacity: 0,
65-
y: 50,
66-
duration: 0.8,
67-
ease: 'power3.out',
68-
scrollTrigger: {
69-
trigger: sectionRef.current,
70-
start: 'top 75%',
71-
once: true,
72-
},
73-
});
74-
}, { scope: sectionRef });
67+
useGSAP(
68+
() => {
69+
gsap.from(".faq__gameboy", {
70+
opacity: 0,
71+
y: 50,
72+
duration: 0.8,
73+
ease: "power3.out",
74+
scrollTrigger: {
75+
trigger: sectionRef.current,
76+
start: "top 75%",
77+
once: true,
78+
},
79+
});
80+
},
81+
{ scope: sectionRef },
82+
);
7583

7684
const toggle = (index) => {
7785
setOpenIndex((prev) => {
@@ -97,11 +105,9 @@ export default function FAQ() {
97105

98106
<div className="faq__gameboy-wrapper">
99107
<div className="faq__gameboy">
100-
101108
{/* Top Section: Screen */}
102109
<div className="gameboy__top">
103110
<div className="gameboy__screen-bezel">
104-
105111
<div className="gameboy__screen-header">
106112
<div className="gameboy__power-light active"></div>
107113
<span className="gameboy__brand">pbctf 5.0</span>
@@ -112,20 +118,24 @@ export default function FAQ() {
112118
<div className="screen__category-title">
113119
&gt; DIR: /{activeCategory.toUpperCase()}
114120
</div>
115-
121+
116122
<div className="faq__list">
117123
{faqsByCategory[activeCategory].map((item, i) => {
118124
const isOpen = openIndex === i;
119125
return (
120-
<div key={i} className={`faq__item ${isOpen ? 'is-open' : ''}`}>
126+
<div
127+
key={i}
128+
className={`faq__item ${isOpen ? "is-open" : ""}`}
129+
>
121130
<button
122131
className="faq__question"
123132
onClick={() => toggle(i)}
124133
onMouseEnter={playHover}
125134
aria-expanded={isOpen}
126135
>
127136
<span className="faq__prompt">
128-
<span className="faq__prompt-symbol">&gt;</span> {item.q}
137+
<span className="faq__prompt-symbol">&gt;</span>{" "}
138+
{item.q}
129139
</span>
130140
<motion.span
131141
className="faq__chevron"
@@ -140,7 +150,7 @@ export default function FAQ() {
140150
<motion.div
141151
className="faq__answer-wrapper"
142152
initial={{ height: 0, opacity: 0 }}
143-
animate={{ height: 'auto', opacity: 1 }}
153+
animate={{ height: "auto", opacity: 1 }}
144154
exit={{ height: 0, opacity: 0 }}
145155
transition={{ duration: 0.2 }}
146156
>
@@ -156,7 +166,7 @@ export default function FAQ() {
156166
</div>
157167
</div>
158168
</div>
159-
169+
160170
{/* Middle Section: Logo */}
161171
<div className="gameboy__middle">
162172
<span className="gameboy__logo">POINT BLANK</span>
@@ -175,37 +185,45 @@ export default function FAQ() {
175185
<div className="gameboy__action-buttons">
176186
<div className="gameboy__button-row">
177187
<div className="action-btn-wrapper">
178-
<button
179-
className={`gameboy__btn ${activeCategory === categories[0] ? 'active' : ''}`}
188+
<button
189+
className={`gameboy__btn ${activeCategory === categories[0] ? "active" : ""}`}
180190
onMouseEnter={playHover}
181191
onClick={() => handleCategoryChange(categories[0])}
182-
>A</button>
192+
>
193+
A
194+
</button>
183195
<span className="gameboy__btn-label">{categories[0]}</span>
184196
</div>
185197
<div className="action-btn-wrapper btn-raised">
186-
<button
187-
className={`gameboy__btn ${activeCategory === categories[1] ? 'active' : ''}`}
198+
<button
199+
className={`gameboy__btn ${activeCategory === categories[1] ? "active" : ""}`}
188200
onMouseEnter={playHover}
189201
onClick={() => handleCategoryChange(categories[1])}
190-
>B</button>
202+
>
203+
B
204+
</button>
191205
<span className="gameboy__btn-label">{categories[1]}</span>
192206
</div>
193207
</div>
194208
<div className="gameboy__button-row">
195209
<div className="action-btn-wrapper">
196-
<button
197-
className={`gameboy__btn ${activeCategory === categories[2] ? 'active' : ''}`}
210+
<button
211+
className={`gameboy__btn ${activeCategory === categories[2] ? "active" : ""}`}
198212
onMouseEnter={playHover}
199213
onClick={() => handleCategoryChange(categories[2])}
200-
>X</button>
214+
>
215+
X
216+
</button>
201217
<span className="gameboy__btn-label">{categories[2]}</span>
202218
</div>
203219
<div className="action-btn-wrapper btn-raised">
204-
<button
205-
className={`gameboy__btn ${activeCategory === categories[3] ? 'active' : ''}`}
220+
<button
221+
className={`gameboy__btn ${activeCategory === categories[3] ? "active" : ""}`}
206222
onMouseEnter={playHover}
207223
onClick={() => handleCategoryChange(categories[3])}
208-
>Y</button>
224+
>
225+
Y
226+
</button>
209227
<span className="gameboy__btn-label">{categories[3]}</span>
210228
</div>
211229
</div>
@@ -218,7 +236,6 @@ export default function FAQ() {
218236
<div key={i} className="speaker-slit"></div>
219237
))}
220238
</div>
221-
222239
</div>
223240
</div>
224241
</div>

components/landing/Sponsors/Sponsors.css

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@
126126
}
127127

128128
.pbctf-landing .sponsors__logo--paytm {
129-
width: 80px;
129+
width: 105px;
130130
height: auto;
131131
}
132132

@@ -156,7 +156,7 @@
156156
overflow: hidden;
157157
-webkit-mask-image: linear-gradient(90deg, transparent 0%, black 10%, black 90%, transparent 100%);
158158
mask-image: linear-gradient(90deg, transparent 0%, black 10%, black 90%, transparent 100%);
159-
padding: 12px 0;
159+
padding: 20px 0;
160160
border-top: 1px solid rgba(0, 255, 136, 0.08);
161161
border-bottom: 1px solid rgba(0, 255, 136, 0.08);
162162
}
@@ -165,7 +165,7 @@
165165
display: flex;
166166
gap: var(--space-8);
167167
width: max-content;
168-
animation: ticker-scroll 28s linear infinite;
168+
animation: ticker-scroll 38s linear infinite;
169169
}
170170

171171
.pbctf-landing .sponsors__ticker-track:hover .sponsors__ticker-inner {
@@ -180,27 +180,27 @@
180180
.pbctf-landing .sponsors__ticker-item {
181181
display: flex;
182182
align-items: center;
183-
gap: 10px;
184-
white-space: nowrap;
185-
font-family: var(--font-mono);
186-
font-size: 12px;
187-
letter-spacing: 0.08em;
188-
color: rgba(255, 255, 255, 0.35);
189-
transition: color 0.3s ease;
183+
flex-shrink: 0;
190184
}
191185

192-
.pbctf-landing .sponsors__ticker-item:hover {
193-
color: rgba(255, 255, 255, 0.7);
186+
.pbctf-landing .sponsors__ticker-logo {
187+
display: block;
188+
height: 56px;
189+
width: auto;
190+
max-width: 220px;
191+
object-fit: contain;
192+
opacity: 1;
193+
transition: opacity 0.3s ease, transform 0.3s ease;
194194
}
195195

196-
.pbctf-landing .sponsors__ticker-dot {
197-
display: inline-block;
198-
width: 4px;
199-
height: 4px;
200-
border-radius: 50%;
201-
background: #ffffff;
202-
opacity: 0.5;
203-
flex-shrink: 0;
196+
.pbctf-landing .sponsors__ticker-item:hover .sponsors__ticker-logo {
197+
opacity: 1;
198+
transform: scale(1.08);
199+
}
200+
201+
/* K7's brand colours clash with the dark theme — render it as a clean white (b&w) mark */
202+
.pbctf-landing .sponsors__ticker-logo--k7 {
203+
filter: brightness(0) invert(1);
204204
}
205205

206206
/* CTA block */

0 commit comments

Comments
 (0)